diff options
Diffstat (limited to 'private/ole2ui32')
60 files changed, 20340 insertions, 0 deletions
diff --git a/private/ole2ui32/busy.cpp b/private/ole2ui32/busy.cpp new file mode 100644 index 000000000..eb18144f0 --- /dev/null +++ b/private/ole2ui32/busy.cpp @@ -0,0 +1,421 @@ +/* + * BUSY.CPP + * + * Implements the OleUIBusy function which invokes the "Server Busy" + * dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "common.h" +#include "utility.h" + +OLEDBGDATA + +// Internally used structure +typedef struct tagBUSY +{ + // Keep these items first as the Standard* functions depend on it here. + LPOLEUIBUSY lpOBZ; // Original structure passed. + UINT nIDD; // IDD of dialog (used for help info) + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog or that we don't want to change in the original structure + * until the user presses OK. + */ + DWORD dwFlags; // Flags passed in + HWND hWndBlocked; // HWND of app which is blocking + +} BUSY, *PBUSY, FAR *LPBUSY; + +// Internal function prototypes +// BUSY.CPP + +BOOL CALLBACK BusyDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam); +BOOL GetTaskInfo(HWND hWnd, HTASK htask, LPTSTR* lplpszWindowName, HWND* lphWnd); +void BuildBusyDialogString(HWND, DWORD, int, LPTSTR); +BOOL FBusyInit(HWND hDlg, WPARAM wParam, LPARAM lParam); +void MakeWindowActive(HWND hWndSwitchTo); + +/* + * OleUIBusy + * + * Purpose: + * Invokes the standard OLE "Server Busy" dialog box which + * notifies the user that the server application is not receiving + * messages. The dialog then asks the user to either cancel + * the operation, switch to the task which is blocked, or continue + * waiting. + * + * Parameters: + * lpBZ LPOLEUIBUSY pointing to the in-out structure + * for this dialog. + * + * Return Value: + * OLEUI_BZERR_HTASKINVALID : Error + * OLEUI_BZ_SWITCHTOSELECTED : Success, user selected "switch to" + * OLEUI_BZ_RETRYSELECTED : Success, user selected "retry" + * OLEUI_CANCEL : Success, user selected "cancel" + */ +STDAPI_(UINT) OleUIBusy(LPOLEUIBUSY lpOBZ) +{ + HGLOBAL hMemDlg = NULL; + UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpOBZ, sizeof(OLEUIBUSY), + &hMemDlg); + + // Error out if the standard validation failed + if (OLEUI_SUCCESS != uRet) + return uRet; + + // Error out if our secondary validation failed + if (OLEUI_ERR_STANDARDMIN <= uRet) + { + return uRet; + } + + // Invoke the dialog. + uRet = UStandardInvocation(BusyDialogProc, (LPOLEUISTANDARD)lpOBZ, + hMemDlg, MAKEINTRESOURCE(IDD_BUSY)); + return uRet; +} + +/* + * BusyDialogProc + * + * Purpose: + * Implements the OLE Busy dialog as invoked through the OleUIBusy function. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + * + */ +BOOL CALLBACK BusyDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + // Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + // This will fail under WM_INITDIALOG, where we allocate it. + UINT uRet = 0; + LPBUSY lpBZ = (LPBUSY)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet); + + // If the hook processed the message, we're done. + if (0 != uRet) + return (BOOL)uRet; + + // Process the temination message + if (iMsg == uMsgEndDialog) + { + EndDialog(hDlg, wParam); + return TRUE; + } + + // Process our special "close" message. If we get this message, + // this means that the call got unblocked, so we need to + // return OLEUI_BZ_CALLUNBLOCKED to our calling app. + if (iMsg == uMsgCloseBusyDlg) + { + SendMessage(hDlg, uMsgEndDialog, OLEUI_BZ_CALLUNBLOCKED, 0L); + return TRUE; + } + + switch (iMsg) + { + case WM_DESTROY: + if (lpBZ) + { + StandardCleanup(lpBZ, hDlg); + } + break; + case WM_INITDIALOG: + FBusyInit(hDlg, wParam, lParam); + return TRUE; + + case WM_ACTIVATEAPP: + { + /* try to bring down our Busy/NotResponding dialog as if + ** the user entered RETRY. + */ + BOOL fActive = (BOOL)wParam; + if (fActive) + { + // If this is the app BUSY case, then bring down our + // dialog when switching BACK to our app + if (lpBZ && !(lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG)) + SendMessage(hDlg,uMsgEndDialog,OLEUI_BZ_RETRYSELECTED,0L); + } + else + { + // If this is the app NOT RESPONDING case, then bring down + // our dialog when switching AWAY to another app + if (lpBZ && (lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG)) + SendMessage(hDlg,uMsgEndDialog,OLEUI_BZ_RETRYSELECTED,0L); + } + } + return TRUE; + + case WM_COMMAND: + switch (wID) + { + case IDC_BZ_SWITCHTO: + { + BOOL fNotRespondingDlg = + (BOOL)(lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG); + HWND hwndTaskList = hDlg; + + // If this is the app not responding case, then we want + // to bring down the dialog when "SwitchTo" is selected. + // If the app is busy (RetryRejectedCall situation) then + // we do NOT want to bring down the dialog. this is + // the OLE2.0 user model design. + if (fNotRespondingDlg) + { + hwndTaskList = GetParent(hDlg); + if (hwndTaskList == NULL) + hwndTaskList = GetDesktopWindow(); + PostMessage(hDlg, uMsgEndDialog, + OLEUI_BZ_SWITCHTOSELECTED, 0L); + } + + // If user selects "Switch To...", switch activation + // directly to the window which is causing the problem. + if (IsWindow(lpBZ->hWndBlocked)) + MakeWindowActive(lpBZ->hWndBlocked); + else + PostMessage(hwndTaskList, WM_SYSCOMMAND, SC_TASKLIST, 0); + } + break; + + case IDC_BZ_RETRY: + SendMessage(hDlg, uMsgEndDialog, OLEUI_BZ_RETRYSELECTED, 0L); + break; + + case IDCANCEL: + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + } + break; + } + + return FALSE; +} + +/* + * FBusyInit + * + * Purpose: + * WM_INITIDIALOG handler for the Busy dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ +BOOL FBusyInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + HFONT hFont; + LPBUSY lpBZ = (LPBUSY)LpvStandardInit(hDlg, sizeof(BUSY), &hFont); + + // PvStandardInit sent a termination to us already. + if (NULL == lpBZ) + return FALSE; + + // Our original structure is in lParam + LPOLEUIBUSY lpOBZ = (LPOLEUIBUSY)lParam; + + // Copy it to our instance of the structure (in lpBZ) + lpBZ->lpOBZ = lpOBZ; + lpBZ->nIDD = IDD_BUSY; + + //Copy other information from lpOBZ that we might modify. + lpBZ->dwFlags = lpOBZ->dwFlags; + + // Set default information + lpBZ->hWndBlocked = NULL; + + // Insert HWND of our dialog into the address pointed to by + // lphWndDialog. This can be used by the app who called + // OleUIBusy to bring down the dialog with uMsgCloseBusyDialog + if (lpOBZ->lphWndDialog && + !IsBadWritePtr(lpOBZ->lphWndDialog, sizeof(HWND))) + { + *lpOBZ->lphWndDialog = hDlg; + } + + // Update text in text box -- + // GetTaskInfo will return two pointers, one to the task name + // (file name) and one to the window name. We need to call + // OleStdFree on these when we're done with them. We also + // get the HWND which is blocked in this call + // + // In the case where this call fails, a default message should already + // be present in the dialog template, so no action is needed + + LPTSTR lpWindowName; + if (GetTaskInfo(hDlg, lpOBZ->hTask, &lpWindowName, &lpBZ->hWndBlocked)) + { + // Build string to present to user, place in IDC_BZ_MESSAGE1 control + BuildBusyDialogString(hDlg, lpBZ->dwFlags, IDC_BZ_MESSAGE1, lpWindowName); + OleStdFree(lpWindowName); + } + + // Update icon with the system "exclamation" icon + HICON hIcon = LoadIcon(NULL, IDI_EXCLAMATION); + SendDlgItemMessage(hDlg, IDC_BZ_ICON, STM_SETICON, (WPARAM)hIcon, 0L); + + // Disable/Enable controls + if ((lpBZ->dwFlags & BZ_DISABLECANCELBUTTON) || + (lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG)) + { + // Disable cancel for "not responding" dialog + StandardEnableDlgItem(hDlg, IDCANCEL, FALSE); + } + + if (lpBZ->dwFlags & BZ_DISABLESWITCHTOBUTTON) + StandardEnableDlgItem(hDlg, IDC_BZ_SWITCHTO, FALSE); + + if (lpBZ->dwFlags & BZ_DISABLERETRYBUTTON) + StandardEnableDlgItem(hDlg, IDC_BZ_RETRY, FALSE); + + // Call the hook with lCustData in lParam + UStandardHook((LPVOID)lpBZ, hDlg, WM_INITDIALOG, wParam, lpOBZ->lCustData); + + // Update caption if lpszCaption was specified + if (lpBZ->lpOBZ->lpszCaption && !IsBadReadPtr(lpBZ->lpOBZ->lpszCaption, 1)) + { + SetWindowText(hDlg, lpBZ->lpOBZ->lpszCaption); + } + return TRUE; +} + +/* + * BuildBusyDialogString + * + * Purpose: + * Builds the string that will be displayed in the dialog from the + * task name and window name parameters. + * + * Parameters: + * hDlg HWND of the dialog + * dwFlags DWORD containing flags passed into dialog + * iControl Control ID to place the text string + * lpTaskName LPSTR pointing to name of task (e.g. C:\TEST\TEST.EXE) + * lpWindowName LPSTR for name of window + * + * Caveats: + * The caller of this function MUST de-allocate the lpTaskName and + * lpWindowName pointers itself with OleStdFree + * + * Return Value: + * void + */ +void BuildBusyDialogString( + HWND hDlg, DWORD dwFlags, int iControl, LPTSTR lpWindowName) +{ + // Load the format string out of stringtable, choose a different + // string depending on what flags are passed in to the dialog + UINT uiStringNum; + if (dwFlags & BZ_NOTRESPONDINGDIALOG) + uiStringNum = IDS_BZRESULTTEXTNOTRESPONDING; + else + uiStringNum = IDS_BZRESULTTEXTBUSY; + + TCHAR szFormat[256]; + if (LoadString(_g_hOleStdResInst, uiStringNum, szFormat, 256) == 0) + return; + + // Build the string. The format string looks like this: + // "This action cannot be completed because the "%1" application + // is [busy | not responding]. Choose \"Switch To\" to correct the + // problem." + + TCHAR szMessage[512]; + FormatString1(szMessage, szFormat, lpWindowName); + SetDlgItemText(hDlg, iControl, szMessage); +} + +/* + * GetTaskInfo() + * + * Purpose: Gets information about the specified task and places the + * module name, window name and top-level HWND for the task in the specified + * pointers + * + * NOTE: The two string pointers allocated in this routine are + * the responsibility of the CALLER to de-allocate. + * + * Parameters: + * hWnd HWND who called this function + * htask HTASK which we want to find out more info about + * lplpszTaskName Location that the module name is returned + * lplpszWindowName Location where the window name is returned + * + */ +BOOL GetTaskInfo( + HWND hWnd, HTASK htask, LPTSTR* lplpszWindowName, HWND* lphWnd) +{ + if (htask == NULL) + return FALSE; + + // initialize 'out' parameters + *lplpszWindowName = NULL; + + // Now, enumerate top-level windows in system + HWND hwndNext = GetWindow(hWnd, GW_HWNDFIRST); + while (hwndNext) + { + // See if we can find a non-owned top level window whose + // hInstance matches the one we just got passed. If we find one, + // we can be fairly certain that this is the top-level window for + // the task which is blocked. + DWORD dwProcessID; + DWORD dwThreadID = GetWindowThreadProcessId(hwndNext, &dwProcessID); + if ((hwndNext != hWnd) && + (dwThreadID == (DWORD)htask) && + (IsWindowVisible(hwndNext)) && !GetWindow(hwndNext, GW_OWNER)) + { + // We found our window! Alloc space for new strings + LPTSTR lpszWN; + if ((lpszWN = (LPTSTR)OleStdMalloc(MAX_PATH_SIZE)) == NULL) + break; + + // We found the window we were looking for, copy info to + // local vars + GetWindowText(hwndNext, lpszWN, MAX_PATH); + + // Note: the task name cannot be retrieved with the Win32 API. + + // everything was successful. Set string pointers to point to our data. + *lplpszWindowName = lpszWN; + *lphWnd = hwndNext; + return TRUE; + } + hwndNext = GetWindow(hwndNext, GW_HWNDNEXT); + } + + return FALSE; +} + +/* + * MakeWindowActive() + * + * Purpose: Makes specified window the active window. + * + */ +void MakeWindowActive(HWND hWndSwitchTo) +{ + // If it's iconic, we need to restore it. + if (IsIconic(hWndSwitchTo)) + ShowWindow(hWndSwitchTo, SW_RESTORE); + + // Move the new window to the top of the Z-order + SetForegroundWindow(GetLastActivePopup(hWndSwitchTo)); +} diff --git a/private/ole2ui32/chngsrc.cpp b/private/ole2ui32/chngsrc.cpp new file mode 100644 index 000000000..bca1c115b --- /dev/null +++ b/private/ole2ui32/chngsrc.cpp @@ -0,0 +1,432 @@ +/* + * CHNGSRC.CPP + * + * Implements the OleUIChangeSource function which invokes the complete + * Change Source dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "common.h" +#include "utility.h" + +OLEDBGDATA + +// Internally used structure +typedef struct tagCHANGESOURCE +{ + // Keep this item first as the Standard* functions depend on it here. + LPOLEUICHANGESOURCE lpOCS; //Original structure passed. + UINT nIDD; // IDD of dialog (used for help info) + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + +} CHANGESOURCE, *PCHANGESOURCE, FAR* LPCHANGESOURCE; + +// Internal function prototypes +// CHNGSRC.CPP + +UINT CALLBACK ChangeSourceHookProc(HWND, UINT, WPARAM, LPARAM); +BOOL FChangeSourceInit(HWND hDlg, WPARAM, LPARAM); +STDAPI_(BOOL) IsValidInterface(void FAR* ppv); + +/* + * OleUIChangeSource + * + * Purpose: + * Invokes the standard OLE Change Source dialog box allowing the user + * to change the source of a link. The link source is not actually + * changed by this dialog. It is up to the caller to actually change + * the link source itself. + * + * Parameters: + * lpCS LPOLEUIChangeSource pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT One of the following codes, indicating success or error: + * OLEUI_SUCCESS Success + * OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong + */ +STDAPI_(UINT) OleUIChangeSource(LPOLEUICHANGESOURCE lpCS) +{ + HGLOBAL hMemDlg = NULL; + UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpCS, + sizeof(OLEUICHANGESOURCE), &hMemDlg); + + if (OLEUI_SUCCESS != uRet) + return uRet; + + + HCURSOR hCurSave = NULL; + + // validate contents of lpCS + if (lpCS->lpOleUILinkContainer == NULL) + { + uRet = OLEUI_CSERR_LINKCNTRNULL; + goto Error; + } + if (!IsValidInterface(lpCS->lpOleUILinkContainer)) + { + uRet = OLEUI_CSERR_LINKCNTRINVALID; + goto Error; + } + + // lpszFrom and lpszTo must be NULL (they are out only) + if (lpCS->lpszFrom != NULL) + { + uRet = OLEUI_CSERR_FROMNOTNULL; + goto Error; + } + if (lpCS->lpszTo != NULL) + { + uRet = OLEUI_CSERR_TONOTNULL; + goto Error; + } + + // lpszDisplayName must be valid or NULL + if (lpCS->lpszDisplayName != NULL && + IsBadStringPtr(lpCS->lpszDisplayName, (UINT)-1)) + { + uRet = OLEUI_CSERR_SOURCEINVALID; + goto Error; + } + + hCurSave = HourGlassOn(); + + // attempt to retrieve link source if not provided + if (lpCS->lpszDisplayName == NULL) + { + if (NOERROR != lpCS->lpOleUILinkContainer->GetLinkSource( + lpCS->dwLink, &lpCS->lpszDisplayName, &lpCS->nFileLength, + NULL, NULL, NULL, NULL)) + { + uRet = OLEUI_CSERR_SOURCEINVALID; + goto Error; + } + } + + // verify that nFileLength is valid + if ((UINT)lstrlen(lpCS->lpszDisplayName) < lpCS->nFileLength) + { + uRet = OLEUI_CSERR_SOURCEINVALID; + goto Error; + } + + // allocate file buffer and split directory and file name + UINT nFileLength; nFileLength = lpCS->nFileLength; + UINT nFileBuf; nFileBuf = max(nFileLength+1, MAX_PATH); + LPTSTR lpszFileBuf; + LPTSTR lpszDirBuf; lpszDirBuf = (LPTSTR)OleStdMalloc(nFileBuf * sizeof(TCHAR)); + if (lpszDirBuf == NULL) + { + uRet = OLEUI_ERR_OLEMEMALLOC; + goto Error; + } + lstrcpyn(lpszDirBuf, lpCS->lpszDisplayName, nFileLength+1); + + UINT nFileLen; nFileLen = GetFileName(lpszDirBuf, NULL, 0); + + lpszFileBuf = (LPTSTR)OleStdMalloc(nFileBuf * sizeof(TCHAR)); + if (lpszFileBuf == NULL) + { + uRet = OLEUI_ERR_OLEMEMALLOC; + goto ErrorFreeDirBuf; + } + memmove(lpszFileBuf, lpszDirBuf+nFileLength-nFileLen+1, + (nFileLen+1)*sizeof(TCHAR)); + lpszDirBuf[nFileLength-(nFileLen - 1)] = 0; + + // start filling the OPENFILENAME struct + OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); + ofn.lpstrFile = lpszFileBuf; + ofn.nMaxFile = nFileBuf; + ofn.lpstrInitialDir = lpszDirBuf; + + // load filter strings + TCHAR szFilters[MAX_PATH]; + if (!LoadString(_g_hOleStdResInst, IDS_FILTERS, szFilters, MAX_PATH)) + szFilters[0] = 0; + else + ReplaceCharWithNull(szFilters, szFilters[lstrlen(szFilters)-1]); + ofn.lpstrFilter = szFilters; + ofn.nFilterIndex = 1; + + TCHAR szTitle[MAX_PATH]; + + // set the caption + if (NULL!=lpCS->lpszCaption) + ofn.lpstrTitle = lpCS->lpszCaption; + else + { + LoadString(_g_hOleStdResInst, IDS_CHANGESOURCE, szTitle, MAX_PATH); + ofn.lpstrTitle = szTitle; + } + + // fill in rest of OPENFILENAME struct + ofn.hwndOwner = lpCS->hWndOwner; + ofn.lStructSize = sizeof(ofn); + ofn.Flags = OFN_HIDEREADONLY | OFN_ENABLEHOOK; + if (bWin4 && ((NULL == lpCS->hInstance && NULL == lpCS->hResource) + || 0 != (lpCS->dwFlags & CSF_EXPLORER))) + ofn.Flags |= OFN_EXPLORER; + if (lpCS->dwFlags & CSF_SHOWHELP) + ofn.Flags |= OFN_SHOWHELP; + ofn.lCustData = (LPARAM)lpCS; + ofn.lpfnHook = ChangeSourceHookProc; + ofn.lCustData = (LPARAM)lpCS; + lpCS->lpOFN = &ofn; // needed sometimes in hook proc + + // allow hooking of the dialog resource + if (lpCS->hResource != NULL) + { + ofn.hInstance = (HINSTANCE)lpCS->hResource; + ofn.lpTemplateName = (LPCTSTR)lpCS->hResource; + ofn.Flags |= OFN_ENABLETEMPLATEHANDLE; + } + else + { + if (lpCS->hInstance == NULL) + { + ofn.hInstance = _g_hOleStdResInst; + ofn.lpTemplateName = bWin4 ? + MAKEINTRESOURCE(IDD_CHANGESOURCE4) : MAKEINTRESOURCE(IDD_CHANGESOURCE); + ofn.Flags |= OFN_ENABLETEMPLATE; + } + else + { + ofn.hInstance = lpCS->hInstance; + ofn.lpTemplateName = lpCS->lpszTemplate; + ofn.Flags |= OFN_ENABLETEMPLATE; + } + } + + if (lpCS->hWndOwner != NULL) + { + // allow hooking of the OFN struct + SendMessage(lpCS->hWndOwner, uMsgBrowseOFN, ID_BROWSE_CHANGESOURCE, (LPARAM)&ofn); + } + + // call up the dialog + BOOL bResult; + + bResult = StandardGetOpenFileName(&ofn); + + // cleanup + OleStdFree(lpszDirBuf); + OleStdFree(lpszFileBuf); + + HourGlassOff(hCurSave); + + // map return value to OLEUI_ standard returns + return bResult ? OLEUI_OK : OLEUI_CANCEL; + +// handle most error returns here +ErrorFreeDirBuf: + OleStdFree(lpszDirBuf); + +Error: + if (hCurSave != NULL) + HourGlassOff(hCurSave); + return uRet; +} + +/* + * ChangeSourceHookProc + * + * Purpose: + * Implements the OLE Change Source dialog as invoked through the + * OleUIChangeSource function. This is a standard COMMDLG hook function + * as opposed to a dialog proc. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ +UINT CALLBACK ChangeSourceHookProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + // Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + // This will fail under WM_INITDIALOG, where we allocate it. + UINT uHook = 0; + LPCHANGESOURCE lpCS = (LPCHANGESOURCE)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook); + + LPOLEUICHANGESOURCE lpOCS = NULL; + if (lpCS != NULL) + lpOCS = lpCS->lpOCS; + + // If the hook processed the message, we're done. + if (0 != uHook) + return uHook; + + // Process help message + if ((iMsg == uMsgHelp) && NULL != lpOCS) + { + PostMessage(lpOCS->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_CHANGESOURCE, 0)); + } + + // Process the temination message + if (iMsg == uMsgEndDialog) + { + // Free any specific allocations before calling StandardCleanup + StandardCleanup((PVOID)lpCS, hDlg); + EndDialog(hDlg, wParam); + return TRUE; + } + + // handle validation of the file name (when user hits OK) + if (iMsg == uMsgFileOKString) + { + // always use fully qualified name + LPOPENFILENAME lpOFN = lpOCS->lpOFN; + LPCTSTR lpsz = lpOFN->lpstrFile; + LPTSTR lpszFile; + TCHAR szPath[MAX_PATH]; + if (!GetFullPathName(lpsz, MAX_PATH, szPath, &lpszFile)) + lstrcpyn(szPath, lpsz, MAX_PATH); + UINT nLenFile = lstrlen(szPath); + TCHAR szItemName[MAX_PATH]; + GetDlgItemText(hDlg, edt2, szItemName, MAX_PATH); + + // combine them into szDisplayName (which is now large enough) + TCHAR szDisplayName[MAX_PATH+MAX_PATH]; + lstrcpy(szDisplayName, szPath); + if (szItemName[0] != '\0') + { + lstrcat(szDisplayName, TEXT("\\")); + lstrcat(szDisplayName, szItemName); + } + + if (!(lpOCS->dwFlags & CSF_ONLYGETSOURCE)) + { + // verify the source by calling into the link container + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpOCS->lpOleUILinkContainer; + ULONG chEaten; + if (lpOleUILinkCntr->SetLinkSource(lpOCS->dwLink, szDisplayName, nLenFile, + &chEaten, TRUE) != NOERROR) + { + // link not verified ok + lpOCS->dwFlags &= ~CSF_VALIDSOURCE; + UINT uRet = PopupMessage(hDlg, IDS_CHANGESOURCE, IDS_INVALIDSOURCE, + MB_ICONQUESTION | MB_YESNO); + if (uRet == IDYES) + { + SetWindowLong(hDlg, DWL_MSGRESULT, 1); + return 1; // do not close dialog + } + + // user doesn't care if the link is valid or not + lpOleUILinkCntr->SetLinkSource(lpOCS->dwLink, szDisplayName, nLenFile, + &chEaten, FALSE); + } + else + { + // link was verified ok + lpOCS->dwFlags |= CSF_VALIDSOURCE; + } + } + + // calculate lpszFrom and lpszTo for batch changes to links + DiffPrefix(lpOCS->lpszDisplayName, szDisplayName, &lpOCS->lpszFrom, &lpOCS->lpszTo); + + // only keep them if the file name portion is the only part that changed + if (lstrcmpi(lpOCS->lpszTo, lpOCS->lpszFrom) == 0 || + (UINT)lstrlen(lpOCS->lpszFrom) > lpOCS->nFileLength) + { + OleStdFree(lpOCS->lpszFrom); + lpOCS->lpszFrom = NULL; + + OleStdFree(lpOCS->lpszTo); + lpOCS->lpszTo = NULL; + } + + // store new source in lpOCS->lpszDisplayName + OleStdFree(lpOCS->lpszDisplayName); + lpOCS->lpszDisplayName = OleStdCopyString(szDisplayName); + lpOCS->nFileLength = nLenFile; + + return 0; + } + + switch (iMsg) + { + case WM_NOTIFY: + if (((NMHDR*)lParam)->code == CDN_HELP) + { + goto POSTHELP; + } + break; + case WM_COMMAND: + if (wID == pshHelp) + { +POSTHELP: + PostMessage(lpCS->lpOCS->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_CHANGESOURCE, 0)); + } + break; + case WM_INITDIALOG: + return FChangeSourceInit(hDlg, wParam, lParam); + } + + return 0; +} + +/* + * FChangeSourceInit + * + * Purpose: + * WM_INITIDIALOG handler for the Change Source dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ +BOOL FChangeSourceInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + // Copy the structure at lParam into our instance memory. + LPCHANGESOURCE lpCS = (LPCHANGESOURCE)LpvStandardInit(hDlg, sizeof(CHANGESOURCE), NULL); + + // PvStandardInit send a termination to us already. + if (NULL == lpCS) + return FALSE; + + LPOLEUICHANGESOURCE lpOCS= + (LPOLEUICHANGESOURCE)((LPOPENFILENAME)lParam)->lCustData; + lpCS->lpOCS = lpOCS; + lpCS->nIDD = IDD_CHANGESOURCE; + + // Setup Item text box with item part of lpszDisplayName + LPTSTR lpszItemName = lpOCS->lpszDisplayName + lpOCS->nFileLength; + if (*lpszItemName != '\0') + SetDlgItemText(hDlg, edt2, lpszItemName+1); + SendDlgItemMessage(hDlg, edt2, EM_LIMITTEXT, MAX_PATH, 0L); + + // Change the caption + if (NULL!=lpOCS->lpszCaption) + SetWindowText(hDlg, lpOCS->lpszCaption); + + // Call the hook with lCustData in lParam + UStandardHook((PVOID)lpCS, hDlg, WM_INITDIALOG, wParam, lpOCS->lCustData); +#ifdef CHICO + TCHAR szTemp[MAX_PATH]; + LoadString(_g_hOleStdResInst, IDS_CHNGSRCOKBUTTON , szTemp, MAX_PATH); + CommDlg_OpenSave_SetControlText(GetParent(hDlg), IDOK, szTemp); +#endif + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/private/ole2ui32/common.cpp b/private/ole2ui32/common.cpp new file mode 100644 index 000000000..fb31a80e2 --- /dev/null +++ b/private/ole2ui32/common.cpp @@ -0,0 +1,685 @@ +/* + * COMMON.CPP + * + * Standardized (and centralized) pieces of each OLEDLG dialog function: + * + * UStandardValidation Validates standard fields in each dialog structure + * UStandardInvocation Invokes a dialog through DialogBoxIndirectParam + * LpvStandardInit Common WM_INITDIALOG processing + * LpvStandardEntry Common code to execute on dialog proc entry. + * UStandardHook Centralized hook calling function. + * StandardCleanup Common exit/cleanup code. + * StandardShowDlgItem Show-Enable/Hide-Disable dialog item + * StandardEnableDlgItem Enable/Disable dialog item + * StandardResizeDlgY Resize dialog to fit controls + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "common.h" +#include "utility.h" + +OLEDBGDATA + +/* + * UStandardValidation + * + * Purpose: + * Performs validation on the standard pieces of any dialog structure, + * that is, the fields defined in the OLEUISTANDARD structure. + * + * Parameters: + * lpUI const LPOLEUISTANDARD pointing to the shared data of + * all structs. + * cbExpect const UINT structure size desired by the caller. + * phDlgMem const HGLOBAL FAR * in which to store a loaded customized + * template, if one exists. + * (This may be NULL in which case the template pointer isn't + * needed by the calling function and should be released.) + * + * Return Value: + * UINT OLEUI_SUCCESS if all validation succeeded. Otherwise + * it will be one of the standard error codes. + */ +UINT WINAPI UStandardValidation(LPOLEUISTANDARD lpUI, const UINT cbExpect, + HGLOBAL* phMemDlg) +{ + /* + * 1. Validate non-NULL pointer parameter. Note: We don't validate + * phDlg since it's not passed from an external source. + */ + if (NULL == lpUI) + return OLEUI_ERR_STRUCTURENULL; + + // 2. Validate that the structure is readable and writable. + if (IsBadWritePtr(lpUI, cbExpect)) + return OLEUI_ERR_STRUCTUREINVALID; + + // 3. Validate the structure size + if (cbExpect != lpUI->cbStruct) + return OLEUI_ERR_CBSTRUCTINCORRECT; + + // 4. Validate owner-window handle. NULL is considered valid. + if (NULL != lpUI->hWndOwner && !IsWindow(lpUI->hWndOwner)) + return OLEUI_ERR_HWNDOWNERINVALID; + + // 5. Validate the dialog caption. NULL is considered valid. + if (NULL != lpUI->lpszCaption && IsBadReadPtr(lpUI->lpszCaption, 1)) + return OLEUI_ERR_LPSZCAPTIONINVALID; + + // 6. Validate the hook pointer. NULL is considered valid. + if (NULL != lpUI->lpfnHook && IsBadCodePtr((FARPROC)lpUI->lpfnHook)) + return OLEUI_ERR_LPFNHOOKINVALID; + + /* + * 7. If hInstance is non-NULL, we have to also check lpszTemplate. + * Otherwise, lpszTemplate is not used and requires no validation. + * lpszTemplate cannot be NULL if used. + */ + HGLOBAL hMem = NULL; + if (NULL != lpUI->hInstance) + { + //Best we can try is one character + if (NULL == lpUI->lpszTemplate || (HIWORD(lpUI->lpszTemplate) != 0 && + IsBadReadPtr(lpUI->lpszTemplate, 1))) + return OLEUI_ERR_LPSZTEMPLATEINVALID; + HRSRC hRes = FindResource(lpUI->hInstance, lpUI->lpszTemplate, RT_DIALOG); + if (NULL == hRes) + return OLEUI_ERR_FINDTEMPLATEFAILURE; + + hMem = LoadResource(lpUI->hInstance, hRes); + if (NULL == hMem) + return OLEUI_ERR_LOADTEMPLATEFAILURE; + } + + // 8. If hResource is non-NULL, be sure we can lock it. + if (NULL != lpUI->hResource) + { + if ((LPSTR)NULL == LockResource(lpUI->hResource)) + return OLEUI_ERR_HRESOURCEINVALID; + } + + /* + * Here we have hMem==NULL if we should use the standard template + * or the one in lpUI->hResource. If hMem is non-NULL, then we + * loaded one from the calling application's resources which the + * caller of this function has to free if it sees any other error. + */ + if (NULL != phMemDlg) + { + *phMemDlg = hMem; + } + return OLEUI_SUCCESS; +} + +/* + * UStandardInvocation + * + * Purpose: + * Provides standard template loading and calling on DialogBoxIndirectParam + * for all the OLE UI dialogs. + * + * Parameters: + * lpDlgProc DLGPROC of the dialog function. + * lpUI LPOLEUISTANDARD containing the dialog structure. + * hMemDlg HGLOBAL containing the dialog template. If this + * is NULL and lpUI->hResource is NULL, then we load + * the standard template given the name in lpszStdTemplate + * lpszStdTemplate LPCSTR standard template to load if hMemDlg is NULL + * and lpUI->hResource is NULL. + * + * Return Value: + * UINT OLEUI_SUCCESS if all is well, otherwise and error + * code. + */ +UINT WINAPI UStandardInvocation( + DLGPROC lpDlgProc, LPOLEUISTANDARD lpUI, HGLOBAL hMemDlg, LPTSTR lpszStdTemplate) +{ + // Make sure we have a template, then lock it down + HGLOBAL hTemplate = hMemDlg; + if (NULL == hTemplate) + hTemplate = lpUI->hResource; + + if (NULL == hTemplate) + { + HRSRC hRes = FindResource(_g_hOleStdResInst, (LPCTSTR) lpszStdTemplate, RT_DIALOG); + if (NULL == hRes) + return OLEUI_ERR_FINDTEMPLATEFAILURE; + + hTemplate = LoadResource(_g_hOleStdResInst, hRes); + if (NULL == hTemplate) + return OLEUI_ERR_LOADTEMPLATEFAILURE; + } + + /* + * hTemplate has the template to use, so now we can invoke the dialog. + * Since we have exported all of our dialog procedures using the + * _keyword, we do not need to call MakeProcInstance, + * we can ue the dialog procedure address directly. + */ + + int iRet = DialogBoxIndirectParam(_g_hOleStdResInst, (LPCDLGTEMPLATE)hTemplate, + lpUI->hWndOwner, lpDlgProc, (LPARAM)lpUI); + + if (-1 == iRet) + return OLEUI_ERR_DIALOGFAILURE; + + // Return the code from EndDialog, generally OLEUI_OK or OLEUI_CANCEL + return (UINT)iRet; +} + +/* + * LpvStandardInit + * + * Purpose: + * Default actions for WM_INITDIALOG handling in the dialog, allocating + * a dialog-specific structure, setting that memory as a dialog property, + * and creating a small font if necessary setting that font as a property. + * + * Parameters: + * hDlg HWND of the dialog + * cbStruct UINT size of dialog-specific structure to allocate. + * fCreateFont BOOL indicating if we need to create a small Helv + * font for this dialog. + * phFont HFONT FAR * in which to place a created font. Can be + * NULL if fCreateFont is FALSE. + * + * Return Value: + * LPVOID Pointer to global memory allocated for the dialog. + * The memory will have been set as a dialog property + * using the STRUCTUREPROP label. + */ +LPVOID WINAPI LpvStandardInit(HWND hDlg, UINT cbStruct, HFONT* phFont) +{ + // Must have at least sizeof(void*) bytes in cbStruct + if (sizeof(void*) > cbStruct) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L); + return NULL; + } + + HGLOBAL gh = GlobalAlloc(GHND, cbStruct); + if (NULL == gh) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L); + return NULL; + } + LPVOID lpv = GlobalLock(gh); + SetProp(hDlg, STRUCTUREPROP, gh); + + if (phFont != NULL) + *phFont = NULL; + if (!bWin4 && phFont != NULL) + { + // Create the non-bold font for result and file texts. We call + HFONT hFont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0L); + LOGFONT lf; + GetObject(hFont, sizeof(LOGFONT), &lf); + lf.lfWeight = FW_NORMAL; + + // Attempt to create the font. If this fails, then we return no font. + *phFont = CreateFontIndirect(&lf); + + // If we couldn't create the font, we'll do with the default. + if (NULL != *phFont) + SetProp(hDlg, FONTPROP, (HANDLE)*phFont); + } + + // Setup the context help mode (WS_EX_CONTEXTHELP) + if (bWin4) + { + DWORD dwExStyle = GetWindowLong(hDlg, GWL_EXSTYLE); + dwExStyle |= WS_EX_CONTEXTHELP; + SetWindowLong(hDlg, GWL_EXSTYLE, dwExStyle); + } + + return lpv; +} + +typedef struct COMMON +{ + OLEUISTANDARD* pStandard; + UINT nIDD; + +} COMMON, *PCOMMON, FAR* LPCOMMON; + +/* + * LpvStandardEntry + * + * Purpose: + * Retrieves the dialog's structure property and calls the hook + * as necessary. This should be called on entry into all dialog + * procedures. + * + * Parameters: + * hDlg HWND of the dialog + * iMsg UINT message to the dialog + * wParam, lParam WPARAM, LPARAM message parameters + * puHookResult UINT FAR * in which this function stores the return value + * from the hook if it is called. If no hook is available, + * this will be FALSE. + * + * Return Value: + * LPVOID Pointer to the dialog's extra structure held in the + * STRUCTUREPROP property. + */ +LPVOID WINAPI LpvStandardEntry(HWND hDlg, UINT iMsg, + WPARAM wParam, LPARAM lParam, UINT FAR * puHookResult) +{ + // This will fail under WM_INITDIALOG, where we allocate using StandardInit + LPVOID lpv = NULL; + HGLOBAL gh = GetProp(hDlg, STRUCTUREPROP); + + if (NULL != puHookResult && NULL != gh) + { + *puHookResult = 0; + + // gh was locked previously, lock and unlock to get lpv + lpv = GlobalLock(gh); + GlobalUnlock(gh); + + // Call the hook for all messages except WM_INITDIALOG + if (NULL != lpv && WM_INITDIALOG != iMsg) + *puHookResult = UStandardHook(lpv, hDlg, iMsg, wParam, lParam); + + // Default processing for various messages + LPCOMMON lpCommon = (LPCOMMON)lpv; + if (*puHookResult == 0 && NULL != lpv) + { + switch (iMsg) + { + // handle standard Win4 help messages + case WM_HELP: + { + HWND hWnd = (HWND)((LPHELPINFO)lParam)->hItemHandle; + StandardHelp(hWnd, lpCommon->nIDD); + break; + } + case WM_CONTEXTMENU: + StandardContextMenu(wParam, lParam, lpCommon->nIDD); + break; + + // make readonly edits have gray background + case WM_CTLCOLOREDIT: + if (bWin4 && (GetWindowLong((HWND)lParam, GWL_STYLE) + & ES_READONLY)) + { + *puHookResult = SendMessage(hDlg, WM_CTLCOLORSTATIC, + wParam, lParam); + } + break; + } + } + } + return lpv; +} + +/* + * UStandardHook + * + * Purpose: + * Provides a generic hook calling function assuming that all private + * dialog structures have a far pointer to their assocated public + * structure as the first field, and that the first part of the public + * structure matches an OLEUISTANDARD. + * + * Parameters: + * pv PVOID to the dialog structure. + * hDlg HWND to send with the call to the hook. + * iMsg UINT message to send to the hook. + * wParam, lParam WPARAM, LPARAM message parameters + * + * Return Value: + * UINT Return value from the hook, zero to indicate that + * default action should occur, nonzero to specify + * that the hook did process the message. In some + * circumstances it will be important for the hook to + * return a non-trivial non-zero value here, such as + * a brush from WM_CTLCOLOR, in which case the caller + * should return that value from the dialog procedure. + */ +UINT WINAPI UStandardHook(LPVOID lpv, HWND hDlg, UINT iMsg, + WPARAM wParam, LPARAM lParam) +{ + UINT uRet = 0; + LPOLEUISTANDARD lpUI = *((LPOLEUISTANDARD FAR *)lpv); + if (NULL != lpUI && NULL != lpUI->lpfnHook) + { + /* + * In order for the hook to have the proper DS, they should be + * compiling with -GA -GEs so and usin __to get everything + * set up properly. + */ + uRet = (*lpUI->lpfnHook)(hDlg, iMsg, wParam, lParam); + } + return uRet; +} + +/* + * StandardCleanup + * + * Purpose: + * Removes properties and reverses any other standard initiazation + * done through StandardSetup. + * + * Parameters: + * lpv LPVOID containing the private dialog structure. + * hDlg HWND of the dialog closing. + * + * Return Value: + * None + */ +void WINAPI StandardCleanup(LPVOID lpv, HWND hDlg) +{ + HFONT hFont=(HFONT)GetProp(hDlg, FONTPROP); + if (NULL != hFont) + { + DeleteObject(hFont); + RemoveProp(hDlg, FONTPROP); + } + + HGLOBAL gh = RemoveProp(hDlg, STRUCTUREPROP); + if (gh != NULL) + { + GlobalUnlock(gh); + GlobalFree(gh); + } +} + +/* StandardShowDlgItem + * ------------------- + * Show & Enable or Hide & Disable a dialog item as appropriate. + * it is NOT sufficient to simply hide the item; it must be disabled + * too or the keyboard accelerator still functions. + */ +void WINAPI StandardShowDlgItem(HWND hDlg, int idControl, int nCmdShow) +{ + HWND hItem = GetDlgItem(hDlg, idControl); + if (hItem != NULL) + { + ShowWindow(hItem, nCmdShow); + EnableWindow(hItem, nCmdShow != SW_HIDE); + } +} + +/* StandardEnableDlgItem + * ------------------- + * Enable/Disable a dialog item. If the item does not exist + * this call is a noop. + */ +void WINAPI StandardEnableDlgItem(HWND hDlg, int idControl, BOOL bEnable) +{ + HWND hItem = GetDlgItem(hDlg, idControl); + if (hItem != NULL) + EnableWindow(hItem, bEnable); +} + +/* StandardResizeDlgY + * ------------------ + * Resize a dialog to fit around the visible controls. This is used + * for dialogs which remove controls from the bottom of the dialogs. + * A good example of this is the convert dialog, which when CF_HIDERESULTS + * is selected, removes the "results box" at the bottom of the dialog. + * This implementation currently + */ +BOOL WINAPI StandardResizeDlgY(HWND hDlg) +{ + RECT rect; + + // determine maxY by looking at all child windows on the dialog + int maxY = 0; + HWND hChild = GetWindow(hDlg, GW_CHILD); + while (hChild != NULL) + { + if (GetWindowLong(hChild, GWL_STYLE) & WS_VISIBLE) + { + GetWindowRect(hChild, &rect); + if (rect.bottom > maxY) + maxY = rect.bottom; + } + hChild = GetWindow(hChild, GW_HWNDNEXT); + } + + if (maxY > 0) + { + // get current font that the dialog is using + HFONT hFont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0); + if (hFont == NULL) + hFont = (HFONT)GetStockObject(SYSTEM_FONT); + OleDbgAssert(hFont != NULL); + + // calculate height of the font in pixels + HDC hDC = GetDC(NULL); + hFont = (HFONT)SelectObject(hDC, hFont); + TEXTMETRIC tm; + GetTextMetrics(hDC, &tm); + SelectObject(hDC, hFont); + ReleaseDC(NULL, hDC); + + // determine if window is too large and resize if necessary + GetWindowRect(hDlg, &rect); + if (rect.bottom > maxY + tm.tmHeight) + { + // window is too large -- resize it + rect.bottom = maxY + tm.tmHeight; + SetWindowPos(hDlg, NULL, + 0, 0, rect.right-rect.left, rect.bottom-rect.top, + SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); + return TRUE; + } + } + + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// Support for Windows 95 help +// BUGBUG - probably need to rename +#define HELPFILE TEXT("mfcuix.hlp") + +LPDWORD LoadHelpInfo(UINT nIDD) +{ + HRSRC hrsrc = FindResource(_g_hOleStdResInst, MAKEINTRESOURCE(nIDD), + MAKEINTRESOURCE(RT_HELPINFO)); + if (hrsrc == NULL) + return NULL; + + HGLOBAL hHelpInfo = LoadResource(_g_hOleStdResInst, hrsrc); + if (hHelpInfo == NULL) + return NULL; + + LPDWORD lpdwHelpInfo = (LPDWORD)LockResource(hHelpInfo); + return lpdwHelpInfo; +} + +void WINAPI StandardHelp(HWND hWnd, UINT nIDD) +{ + LPDWORD lpdwHelpInfo = LoadHelpInfo(nIDD); + if (lpdwHelpInfo == NULL) + { + OleDbgOut1(TEXT("Warning: unable to load help information (RT_HELPINFO)\n")); + return; + } + WinHelp(hWnd, HELPFILE, HELP_WM_HELP, (DWORD)lpdwHelpInfo); +} + +void WINAPI StandardContextMenu(WPARAM wParam, LPARAM, UINT nIDD) +{ + LPDWORD lpdwHelpInfo = LoadHelpInfo(nIDD); + if (lpdwHelpInfo == NULL) + { + OleDbgOut1(TEXT("Warning: unable to load help information (RT_HELPINFO)\n")); + return; + } + WinHelp((HWND)wParam, HELPFILE, HELP_CONTEXTMENU, (DWORD)lpdwHelpInfo); +} + +///////////////////////////////////////////////////////////////////////////// +// StandardPropertySheet (stub for Windows 95 API PropertySheet) + +typedef void (WINAPI* LPFNINITCOMMONCONTROLS)(VOID); + +int WINAPI StandardInitCommonControls() +{ + TASKDATA* pTaskData = GetTaskData(); + OleDbgAssert(pTaskData != NULL); + + if (pTaskData->hInstCommCtrl == NULL) + { + pTaskData->hInstCommCtrl = LoadLibrary(TEXT("comctl32.dll")); + if (pTaskData->hInstCommCtrl == NULL) + goto Error; + + LPFNINITCOMMONCONTROLS lpfnInitCommonControls = (LPFNINITCOMMONCONTROLS) + GetProcAddress(pTaskData->hInstCommCtrl, "InitCommonControls"); + if (lpfnInitCommonControls == NULL) + goto ErrorFreeLibrary; + (*lpfnInitCommonControls)(); + } + return 0; + +ErrorFreeLibrary: + if (pTaskData->hInstCommCtrl != NULL) + { + FreeLibrary(pTaskData->hInstCommCtrl); + pTaskData->hInstCommCtrl = NULL; + } + +Error: + return -1; +} + +typedef int (WINAPI* LPFNPROPERTYSHEET)(LPCPROPSHEETHEADER); + +int WINAPI StandardPropertySheet(LPPROPSHEETHEADER lpPS, BOOL fWide) +{ + int nResult = StandardInitCommonControls(); + if (nResult < 0) + return nResult; + + TASKDATA* pTaskData = GetTaskData(); + OleDbgAssert(pTaskData != NULL); + + LPFNPROPERTYSHEET lpfnPropertySheet; + if (fWide) + { + lpfnPropertySheet = (LPFNPROPERTYSHEET)GetProcAddress(pTaskData->hInstCommCtrl, "PropertySheetW"); + } + else + { + lpfnPropertySheet = (LPFNPROPERTYSHEET)GetProcAddress(pTaskData->hInstCommCtrl, "PropertySheetA"); + } + if (lpfnPropertySheet == NULL) + return -1; + + nResult = (*lpfnPropertySheet)(lpPS); + return nResult; +} + +typedef HICON (WINAPI* LPFNEXTRACTICON)(HINSTANCE, LPCTSTR, UINT); + +HICON StandardExtractIcon(HINSTANCE hInst, LPCTSTR lpszExeFileName, UINT nIconIndex) +{ + TASKDATA* pTaskData = GetTaskData(); + OleDbgAssert(pTaskData != NULL); + LPFNEXTRACTICON lpfnExtractIcon; + + if (pTaskData->hInstShell == NULL) + { + pTaskData->hInstShell = LoadLibrary(TEXT("shell32.dll")); + if (pTaskData->hInstShell == NULL) + goto Error; + } + lpfnExtractIcon = (LPFNEXTRACTICON) +#ifdef UNICODE + GetProcAddress(pTaskData->hInstShell, "ExtractIconW"); +#else + GetProcAddress(pTaskData->hInstShell, "ExtractIconA"); +#endif + if (lpfnExtractIcon == NULL) + goto ErrorFreeLibrary; + return (*lpfnExtractIcon)(hInst, lpszExeFileName, nIconIndex); + +ErrorFreeLibrary: + if (pTaskData->hInstShell != NULL) + { + FreeLibrary(pTaskData->hInstShell); + pTaskData->hInstShell = NULL; + } + +Error: + return NULL; +} + + +typedef BOOL (WINAPI* LPFNGETOPENFILENAME)(LPOPENFILENAME); + +BOOL StandardGetOpenFileName(LPOPENFILENAME lpofn) +{ + TASKDATA* pTaskData = GetTaskData(); + OleDbgAssert(pTaskData != NULL); + LPFNGETOPENFILENAME lpfnGetOpenFileName; + + if (pTaskData->hInstComDlg == NULL) + { + pTaskData->hInstComDlg = LoadLibrary(TEXT("comdlg32.dll")); + if (pTaskData->hInstComDlg == NULL) + goto Error; + } + lpfnGetOpenFileName = (LPFNGETOPENFILENAME) +#ifdef UNICODE + GetProcAddress(pTaskData->hInstComDlg, "GetOpenFileNameW"); +#else + GetProcAddress(pTaskData->hInstComDlg, "GetOpenFileNameA"); +#endif + if (lpfnGetOpenFileName == NULL) + goto ErrorFreeLibrary; + return (*lpfnGetOpenFileName)(lpofn); + +ErrorFreeLibrary: + if (pTaskData->hInstComDlg != NULL) + { + FreeLibrary(pTaskData->hInstComDlg); + pTaskData->hInstComDlg = NULL; + } + +Error: + return FALSE; +} + +typedef short (WINAPI* LPFNGETFILETITLE)(LPCTSTR, LPTSTR, WORD); + +short StandardGetFileTitle(LPCTSTR lpszFile, LPTSTR lpszTitle, WORD cbBuf) +{ + TASKDATA* pTaskData = GetTaskData(); + OleDbgAssert(pTaskData != NULL); + LPFNGETFILETITLE lpfnGetFileTitle; + + if (pTaskData->hInstComDlg == NULL) + { + pTaskData->hInstComDlg = LoadLibrary(TEXT("comdlg32.dll")); + if (pTaskData->hInstComDlg == NULL) + goto Error; + } + lpfnGetFileTitle = (LPFNGETFILETITLE) +#ifdef UNICODE + GetProcAddress(pTaskData->hInstComDlg, "GetFileTitleW"); +#else + GetProcAddress(pTaskData->hInstComDlg, "GetFileTitleA"); +#endif + if (lpfnGetFileTitle == NULL) + goto ErrorFreeLibrary; + return (*lpfnGetFileTitle)(lpszFile, lpszTitle, cbBuf); + +ErrorFreeLibrary: + if (pTaskData->hInstComDlg != NULL) + { + FreeLibrary(pTaskData->hInstComDlg); + pTaskData->hInstComDlg = NULL; + } + +Error: + return -1; +} + diff --git a/private/ole2ui32/common.h b/private/ole2ui32/common.h new file mode 100644 index 000000000..fbbd585bf --- /dev/null +++ b/private/ole2ui32/common.h @@ -0,0 +1,154 @@ +/* + * COMMON.H + * + * Structures and definitions applicable to all OLE 2.0 UI dialogs. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +// Macros to handle control message packing between Win16 and Win32 +#ifndef COMMANDPARAMS +#define COMMANDPARAMS(wID, wCode, hWndMsg) \ + WORD wID = LOWORD(wParam); \ + WORD wCode = HIWORD(wParam); \ + HWND hWndMsg = (HWND)(UINT)lParam; +#endif + +#ifndef SendCommand +#define SendCommand(hWnd, wID, wCode, hControl) \ + SendMessage(hWnd, WM_COMMAND, MAKELONG(wID, wCode) \ + , (LPARAM)hControl) +#endif + +// Property labels used to store dialog structures and fonts +#define STRUCTUREPROP TEXT("Structure") +#define FONTPROP TEXT("Font") + +#ifndef WM_HELP + +// WM_HELP is new Windows 95 help message +#define WM_HELP 0x0053 +// WM_CONTEXTMENU is new Windows 95 right button menus +#define WM_CONTEXTMENU 0x007B + +typedef struct tagHELPINFO /* Structure pointed to by lParam of WM_HELP */ +{ + UINT cbSize; /* Size in bytes of this struct */ + int iContextType; /* Either HELPINFO_WINDOW or HELPINFO_MENUITEM */ + int iCtrlId; /* Control Id or a Menu item Id. */ + HANDLE hItemHandle; /* hWnd of control or hMenu. */ + DWORD dwContextId; /* Context Id associated with this item */ + POINT MousePos; /* Mouse Position in screen co-ordinates */ +} HELPINFO, FAR *LPHELPINFO; + +#define HELP_CONTEXTMENU 0x000a +#define HELP_WM_HELP 0x000c + +#endif //!WM_HELP + + +#ifndef WS_EX_CONTEXTHELP +#define WS_EX_CONTEXTHELP 0x0400L +#endif + +#ifndef OFN_EXPLORER +#define OFN_EXPLORER 0x00080000 +#endif + +#ifndef WS_EX_CLIENTEDGE +#define WS_EX_CLIENTEDGE 0x200 +#endif + + +/* + * Standard structure for all dialogs. This commonality lets us make + * a single piece of code that will validate this entire structure and + * perform any necessary initialization. + */ + +typedef struct tagOLEUISTANDARD +{ + // These IN fields are standard across all OLEUI dialog functions. + DWORD cbStruct; // Structure Size + DWORD dwFlags; // IN-OUT: Flags + HWND hWndOwner; // Owning window + LPCTSTR lpszCaption; // Dialog caption bar contents + LPFNOLEUIHOOK lpfnHook; // Hook callback + LPARAM lCustData; // Custom data to pass to hook + HINSTANCE hInstance; // Instance for customized template name + LPCTSTR lpszTemplate; // Customized template name + HRSRC hResource; // Customized template handle + +} OLEUISTANDARD, *POLEUISTANDARD, FAR *LPOLEUISTANDARD; + +// Function prototypes +// COMMON.CPP + +UINT WINAPI UStandardValidation(LPOLEUISTANDARD, const UINT, HGLOBAL*); +UINT WINAPI UStandardInvocation(DLGPROC, LPOLEUISTANDARD, HGLOBAL, LPTSTR); +LPVOID WINAPI LpvStandardInit(HWND, UINT, HFONT* = NULL); +LPVOID WINAPI LpvStandardEntry(HWND, UINT, WPARAM, LPARAM, UINT FAR *); +UINT WINAPI UStandardHook(LPVOID, HWND, UINT, WPARAM, LPARAM); +void WINAPI StandardCleanup(LPVOID, HWND); +void WINAPI StandardShowDlgItem(HWND hDlg, int idControl, int nCmdShow); +void WINAPI StandardEnableDlgItem(HWND hDlg, int idControl, BOOL bEnable); +BOOL WINAPI StandardResizeDlgY(HWND hDlg); +void WINAPI StandardHelp(HWND, UINT); +void WINAPI StandardContextMenu(WPARAM, LPARAM, UINT nIDD); +UINT InternalObjectProperties(LPOLEUIOBJECTPROPS lpOP, BOOL fWide); +int WINAPI StandardPropertySheet(LPPROPSHEETHEADER lpPS, BOOL fWide); +int WINAPI StandardInitCommonControls(); +HICON StandardExtractIcon(HINSTANCE hInst, LPCTSTR lpszExeFileName, UINT nIconIndex); +BOOL StandardGetOpenFileName(LPOPENFILENAME lpofn); +short StandardGetFileTitle(LPCTSTR lpszFile, LPTSTR lpszTitle, WORD cbBuf); + +// shared globals: registered messages +extern UINT uMsgHelp; +extern UINT uMsgEndDialog; +extern UINT uMsgBrowse; +extern UINT uMsgChangeIcon; +extern UINT uMsgFileOKString; +extern UINT uMsgCloseBusyDlg; +extern UINT uMsgConvert; +extern UINT uMsgChangeSource; +extern UINT uMsgAddControl; +extern UINT uMsgBrowseOFN; + +typedef struct tagTASKDATA +{ + HINSTANCE hInstCommCtrl; + HINSTANCE hInstShell; + HINSTANCE hInstComDlg; +} TASKDATA; + +STDAPI_(TASKDATA*) GetTaskData(); // returns TASKDATA for current process + +extern BOOL bWin4; // TRUE if running Win4 or greater +extern BOOL bSharedData; // TRUE if runing Win32s + +///////////////////////////////////////////////////////////////////////////// +// Maximum buffer sizes + +// Maximum key size we read from the RegDB. +#define OLEUI_CCHKEYMAX 256 // same in geticon.c too +#define OLEUI_CCHKEYMAX_SIZE OLEUI_CCHKEYMAX*sizeof(TCHAR) + +// Maximum length of Object menu +#define OLEUI_OBJECTMENUMAX 256 + +// Maximim length of a path in BYTEs +#define MAX_PATH_SIZE (MAX_PATH*sizeof(TCHAR)) + +// Icon label length +#define OLEUI_CCHLABELMAX 40 // same in geticon.c too +#define OLEUI_CCHLABELMAX_SIZE OLEUI_CCHLABELMAX*sizeof(TCHAR) + +// Length of the CLSID string +#define OLEUI_CCHCLSIDSTRING 39 +#define OLEUI_CCHCLSIDSTRING_SIZE OLEUI_CCHCLSIDSTRING*sizeof(TCHAR) + +#endif //_COMMON_H_ diff --git a/private/ole2ui32/convert.cpp b/private/ole2ui32/convert.cpp new file mode 100644 index 000000000..928ef4438 --- /dev/null +++ b/private/ole2ui32/convert.cpp @@ -0,0 +1,1424 @@ +/* + * CONVERT.CPP + * + * Implements the OleUIConvert function which invokes the complete + * Convert dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "common.h" +#include <stdlib.h> +#include "utility.h" +#include "iconbox.h" + +OLEDBGDATA + +// Internally used structure +typedef struct tagCONVERT +{ + // Keep this item first as the Standard* functions depend on it here. + LPOLEUICONVERT lpOCV; // Original structure passed. + UINT nIDD; // IDD of dialog (used for help info) + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + + DWORD dwFlags; // Flags passed in + HWND hListVisible; // listbox that is currently visible + HWND hListInvisible; // listbox that is currently hidden + CLSID clsid; // Class ID sent in to dialog: IN only + DWORD dvAspect; + BOOL fCustomIcon; + UINT IconIndex; // index (in exe) of current icon + LPTSTR lpszIconSource; // path to current icon source + LPTSTR lpszCurrentObject; + LPTSTR lpszConvertDefault; + LPTSTR lpszActivateDefault; + +} CONVERT, *PCONVERT, FAR *LPCONVERT; + +// Internal function prototypes +// CONVERT.CPP + +BOOL CALLBACK ConvertDialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL FConvertInit(HWND hDlg, WPARAM, LPARAM); +void SetConvertResults(HWND, LPCONVERT); +UINT FillClassList(CLSID clsid, HWND hList, HWND hListInvisible, + LPTSTR FAR *lplpszCurrentClass, BOOL fIsLinkedObject, WORD wFormat, + UINT cClsidExclude, LPCLSID lpClsidExclude, BOOL bAddSameClass); +BOOL FormatIncluded(LPTSTR szStringToSearch, WORD wFormat); +void SwapWindows(HWND, HWND, HWND); +void ConvertCleanup(HWND hDlg, LPCONVERT lpCV); +static void UpdateClassIcon(HWND hDlg, LPCONVERT lpCV, HWND hList); + +/* + * OleUIConvert + * + * Purpose: + * Invokes the standard OLE Change Type dialog box allowing the user + * to change the type of the single specified object, or change the + * type of all OLE objects of a specified type. + * + * Parameters: + * lpCV LPOLEUICONVERT pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT One of the following codes, indicating success or error: + * OLEUI_SUCCESS Success + * OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong + */ +STDAPI_(UINT) OleUIConvert(LPOLEUICONVERT lpCV) +{ + HGLOBAL hMemDlg = NULL; + UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpCV, sizeof(OLEUICONVERT), + &hMemDlg); + + if (OLEUI_SUCCESS != uRet) + return uRet; + + if (lpCV->hMetaPict != NULL && !IsValidMetaPict(lpCV->hMetaPict)) + { + return(OLEUI_CTERR_HMETAPICTINVALID); + } + + if ((lpCV->dwFlags & CF_SETCONVERTDEFAULT) + && (!IsValidClassID(lpCV->clsidConvertDefault))) + uRet = OLEUI_CTERR_CLASSIDINVALID; + + if ((lpCV->dwFlags & CF_SETACTIVATEDEFAULT) + && (!IsValidClassID(lpCV->clsidActivateDefault))) + uRet = OLEUI_CTERR_CLASSIDINVALID; + + if ((lpCV->dvAspect != DVASPECT_ICON) && (lpCV->dvAspect != DVASPECT_CONTENT)) + uRet = OLEUI_CTERR_DVASPECTINVALID; + + if ((lpCV->wFormat >= CF_CLIPBOARDMIN) && (lpCV->wFormat <= CF_CLIPBOARDMAX)) + { + TCHAR szTemp[8]; + if (0 == GetClipboardFormatName(lpCV->wFormat, szTemp, 8)) + uRet = OLEUI_CTERR_CBFORMATINVALID; + } + + if ((NULL != lpCV->lpszUserType) + && (IsBadReadPtr(lpCV->lpszUserType, 1))) + uRet = OLEUI_CTERR_STRINGINVALID; + + if ( (NULL != lpCV->lpszDefLabel) + && (IsBadReadPtr(lpCV->lpszDefLabel, 1)) ) + uRet = OLEUI_CTERR_STRINGINVALID; + + if (0 != lpCV->cClsidExclude && + IsBadReadPtr(lpCV->lpClsidExclude, lpCV->cClsidExclude * sizeof(CLSID))) + { + uRet = OLEUI_IOERR_LPCLSIDEXCLUDEINVALID; + } + + if (OLEUI_ERR_STANDARDMIN <= uRet) + { + return uRet; + } + + UINT nIDD; + if (!bWin4) + nIDD = lpCV->dwFlags & CF_CONVERTONLY ? IDD_CONVERTONLY : IDD_CONVERT; + else + nIDD = lpCV->dwFlags & CF_CONVERTONLY ? IDD_CONVERTONLY4 : IDD_CONVERT4; + + // Now that we've validated everything, we can invoke the dialog. + uRet = UStandardInvocation(ConvertDialogProc, (LPOLEUISTANDARD)lpCV, + hMemDlg, MAKEINTRESOURCE(nIDD)); + return uRet; +} + +/* + * ConvertDialogProc + * + * Purpose: + * Implements the OLE Convert dialog as invoked through the + * OleUIConvert function. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + * + */ +BOOL CALLBACK ConvertDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + // Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + // This will fail under WM_INITDIALOG, where we allocate it. + UINT uRet = 0; + LPCONVERT lpCV = (LPCONVERT)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet); + + //If the hook processed the message, we're done. + if (0 != uRet) + return (BOOL)uRet; + + //Process the temination message + if (iMsg == uMsgEndDialog) + { + EndDialog(hDlg, wParam); + return TRUE; + } + + // Process help message from Change Icon + if (iMsg == uMsgHelp) + { + PostMessage(lpCV->lpOCV->hWndOwner, uMsgHelp, wParam, lParam); + return FALSE; + } + + switch (iMsg) + { + case WM_DESTROY: + if (lpCV) + { + ConvertCleanup(hDlg, lpCV); + StandardCleanup(lpCV, hDlg); + } + break; + case WM_INITDIALOG: + FConvertInit(hDlg, wParam, lParam); + return TRUE; + + case WM_COMMAND: + switch (wID) + { + case IDC_CV_ACTIVATELIST: + case IDC_CV_CONVERTLIST: + switch (wCode) + { + case LBN_SELCHANGE: + // Change "Results" window to reflect current selection + SetConvertResults(hDlg, lpCV); + + // Update the icon we display, if in display as icon mode + if ((lpCV->dwFlags & CF_SELECTCONVERTTO) && + lpCV->dvAspect == DVASPECT_ICON && !lpCV->fCustomIcon) + { + UpdateClassIcon(hDlg, lpCV, hWndMsg); + } + break; + + case LBN_DBLCLK: + SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg); + break; + } + break; + + case IDC_CV_CONVERTTO: + case IDC_CV_ACTIVATEAS: + { + HWND hList = lpCV->hListVisible; + HWND hListInvisible = lpCV->hListInvisible; + + if (IDC_CV_CONVERTTO == wParam) + { + // User just click on the button again - it was + // already selected. + if (lpCV->dwFlags & CF_SELECTCONVERTTO) + break; + + // If we're working with a linked object, don't + // add the activate list - just the object's + // class should appear in the listbox. + SwapWindows(hDlg, hList, hListInvisible); + + lpCV->hListVisible = hListInvisible; + lpCV->hListInvisible = hList; + + EnableWindow(lpCV->hListInvisible, FALSE); + EnableWindow(lpCV->hListVisible, TRUE); + + // Update our flags. + lpCV->dwFlags &= ~CF_SELECTACTIVATEAS; + lpCV->dwFlags |= CF_SELECTCONVERTTO; + } + else + { + if (lpCV->dwFlags & CF_SELECTACTIVATEAS) + break; + + SwapWindows(hDlg, hList, hListInvisible); + + lpCV->hListVisible = hListInvisible; + lpCV->hListInvisible = hList; + + EnableWindow(lpCV->hListInvisible, FALSE); + EnableWindow(lpCV->hListVisible, TRUE); + + // Update our flags. + lpCV->dwFlags |= CF_SELECTACTIVATEAS; + lpCV->dwFlags &= ~CF_SELECTCONVERTTO; + } + + LRESULT lRetVal; + if (lpCV->dwFlags & CF_SELECTCONVERTTO) + lRetVal = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszConvertDefault); + else + lRetVal = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszActivateDefault); + + if (LB_ERR == lRetVal) + { + TCHAR szCurrentObject[40]; + GetDlgItemText(hDlg, IDC_CV_OBJECTTYPE, szCurrentObject, 40); + SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)szCurrentObject); + } + + // Turn updates back on. + SendMessage(hDlg, WM_SETREDRAW, TRUE, 0L); + + InvalidateRect(lpCV->hListVisible, NULL, TRUE); + UpdateWindow(lpCV->hListVisible); + + if ((lpCV->dvAspect & DVASPECT_ICON) && (lpCV->dwFlags & CF_SELECTCONVERTTO)) + UpdateClassIcon(hDlg, lpCV, lpCV->hListVisible); + + // Hide the icon stuff when Activate is selected...show + // it again when Convert is selected. + BOOL fState = ((lpCV->dwFlags & CF_SELECTACTIVATEAS) || + (lpCV->dwFlags & CF_DISABLEDISPLAYASICON)) ? + SW_HIDE : SW_SHOW; + + StandardShowDlgItem(hDlg, IDC_CV_DISPLAYASICON, fState); + + // Only display the icon if convert is selected AND + // display as icon is checked. + if ((SW_SHOW==fState) && (DVASPECT_ICON!=lpCV->dvAspect)) + fState = SW_HIDE; + + StandardShowDlgItem(hDlg, IDC_CV_CHANGEICON, fState); + StandardShowDlgItem(hDlg, IDC_CV_ICONDISPLAY, fState); + + SetConvertResults(hDlg, lpCV); + } + break; + + case IDOK: + { + // Set output flags to current ones + lpCV->lpOCV->dwFlags = lpCV->dwFlags; + + // Update the dvAspect and fObjectsIconChanged members + // as appropriate. + if (lpCV->dwFlags & CF_SELECTACTIVATEAS) + { + // DON'T update aspect if activate as was selected. + lpCV->lpOCV->fObjectsIconChanged = FALSE; + } + else + lpCV->lpOCV->dvAspect = lpCV->dvAspect; + + // Get the new clsid + TCHAR szBuffer[256]; + LRESULT iCurSel = SendMessage(lpCV->hListVisible, LB_GETCURSEL, 0, 0); + SendMessage(lpCV->hListVisible, LB_GETTEXT, iCurSel, (LPARAM)szBuffer); + + LPTSTR lpszCLSID = PointerToNthField(szBuffer, 2, '\t'); +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszCLSID[OLEUI_CCHKEYMAX]; + ATOW(wszCLSID, lpszCLSID, OLEUI_CCHKEYMAX); + CLSIDFromString(wszCLSID, (&(lpCV->lpOCV->clsidNew))); +#else + CLSIDFromString(lpszCLSID, (&(lpCV->lpOCV->clsidNew))); +#endif + + // Free the hMetaPict we got in. + OleUIMetafilePictIconFree(lpCV->lpOCV->hMetaPict); + + // Get the hMetaPict (if display as icon is checked) + if (DVASPECT_ICON == lpCV->dvAspect) + lpCV->lpOCV->hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, + IDC_CV_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); + else + lpCV->lpOCV->hMetaPict = (HGLOBAL)NULL; + + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + } + break; + + case IDCANCEL: + { + HGLOBAL hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, + IDC_CV_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); + OleUIMetafilePictIconFree(hMetaPict); + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + } + break; + + case IDC_OLEUIHELP: + PostMessage(lpCV->lpOCV->hWndOwner, + uMsgHelp, (WPARAM)hDlg, MAKELPARAM(IDD_CONVERT, 0)); + break; + + case IDC_CV_DISPLAYASICON: + { + BOOL fCheck = IsDlgButtonChecked(hDlg, wID); + if (fCheck) + lpCV->dvAspect = DVASPECT_ICON; + else + lpCV->dvAspect = DVASPECT_CONTENT; + + if (fCheck && !lpCV->fCustomIcon) + UpdateClassIcon(hDlg, lpCV, lpCV->hListVisible); + + // Show or hide the icon depending on the check state. + int i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE; + StandardShowDlgItem(hDlg, IDC_CV_CHANGEICON, i); + StandardShowDlgItem(hDlg, IDC_CV_ICONDISPLAY, i); + SetConvertResults(hDlg, lpCV); + } + break; + + case IDC_CV_CHANGEICON: + { + // Initialize the structure for the hook. + OLEUICHANGEICON ci; memset(&ci, 0, sizeof(ci)); + + ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, + IDC_CV_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); + ci.cbStruct = sizeof(ci); + ci.hWndOwner= hDlg; + ci.dwFlags = CIF_SELECTCURRENT; + + // Only show help if we're showing it for this dialog. + if (lpCV->dwFlags & CF_SHOWHELPBUTTON) + ci.dwFlags |= CIF_SHOWHELP; + + int iSel = (INT)SendMessage(lpCV->hListVisible, LB_GETCURSEL, 0, 0); + + // Get whole string + LPTSTR pszString = (LPTSTR)OleStdMalloc( + OLEUI_CCHLABELMAX_SIZE + OLEUI_CCHCLSIDSTRING_SIZE); + + SendMessage(lpCV->hListVisible, LB_GETTEXT, iSel, (LPARAM)pszString); + + // Set pointer to CLSID (string) + LPTSTR pszCLSID = PointerToNthField(pszString, 2, '\t'); + + // Get the clsid to pass to change icon. +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszCLSID[OLEUI_CCHKEYMAX]; + ATOW(wszCLSID, pszCLSID, OLEUI_CCHKEYMAX); + CLSIDFromString(wszCLSID, &(ci.clsid)); +#else + CLSIDFromString(pszCLSID, &(ci.clsid)); +#endif + OleStdFree(pszString); + + // Let the hook in to customize Change Icon if desired. + uRet = UStandardHook(lpCV, hDlg, uMsgChangeIcon, 0, (LPARAM)&ci); + + if (0 == uRet) + uRet= (OLEUI_OK == OleUIChangeIcon(&ci)); + + // Update the display if necessary. + if (0 != uRet) + { + SendDlgItemMessage(hDlg, IDC_CV_ICONDISPLAY, IBXM_IMAGESET, 0, + (LPARAM)ci.hMetaPict); + + // Update our custom/default flag + if (ci.dwFlags & CIF_SELECTDEFAULT) + lpCV->fCustomIcon = FALSE; // we're in default mode (icon changes on each LB selchange) + else if (ci.dwFlags & CIF_SELECTFROMFILE) + lpCV->fCustomIcon = TRUE; // we're in custom mode (icon doesn't change) + + // no change in fCustomIcon if user selected current + lpCV->lpOCV->fObjectsIconChanged = TRUE; + } + } + break; + } + break; + } + + return FALSE; +} + +/* + * FConvertInit + * + * Purpose: + * WM_INITIDIALOG handler for the Convert dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ +BOOL FConvertInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + // Copy the structure at lParam into our instance memory. + HFONT hFont; // non-bold version of dialog's font + LPCONVERT lpCV = (LPCONVERT)LpvStandardInit(hDlg, sizeof(CONVERT), &hFont); + + // PvStandardInit send a termination to us already. + if (NULL == lpCV) + return FALSE; + + LPOLEUICONVERT lpOCV = (LPOLEUICONVERT)lParam; + lpCV->lpOCV = lpOCV; + lpCV->nIDD = IDD_CONVERT; + lpCV->fCustomIcon = FALSE; + + // Copy other information from lpOCV that we might modify. + lpCV->dwFlags = lpOCV->dwFlags; + lpCV->clsid = lpOCV->clsid; + lpCV->dvAspect = lpOCV->dvAspect; + lpCV->hListVisible = GetDlgItem(hDlg, IDC_CV_ACTIVATELIST); + lpCV->hListInvisible = GetDlgItem(hDlg, IDC_CV_CONVERTLIST); + OleDbgAssert(lpCV->hListInvisible != NULL); + lpCV->lpszCurrentObject = lpOCV->lpszUserType; + lpOCV->clsidNew = CLSID_NULL; + lpOCV->fObjectsIconChanged = FALSE; + + lpCV->lpszConvertDefault = (LPTSTR)OleStdMalloc(OLEUI_CCHLABELMAX_SIZE); + lpCV->lpszActivateDefault = (LPTSTR)OleStdMalloc(OLEUI_CCHLABELMAX_SIZE); + lpCV->lpszIconSource = (LPTSTR)OleStdMalloc(MAX_PATH_SIZE); + + // If we got a font, send it to the necessary controls. + if (NULL != hFont) + { + SendDlgItemMessage(hDlg, IDC_CV_OBJECTTYPE, WM_SETFONT, (WPARAM)hFont, 0L); + SendDlgItemMessage(hDlg, IDC_CV_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L); + } + + // Hide the help button if necessary + if (!(lpCV->dwFlags & CF_SHOWHELPBUTTON)) + StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE); + + // Show or hide the Change icon button + if (lpCV->dwFlags & CF_HIDECHANGEICON) + DestroyWindow(GetDlgItem(hDlg, IDC_CV_CHANGEICON)); + + // Fill the Object Type listbox with entries from the reg DB. + UINT nRet = FillClassList(lpOCV->clsid, lpCV->hListVisible, + lpCV->hListInvisible, &(lpCV->lpszCurrentObject), + lpOCV->fIsLinkedObject, lpOCV->wFormat, + lpOCV->cClsidExclude, lpOCV->lpClsidExclude, + !(lpCV->dwFlags & CF_CONVERTONLY)); + + if (nRet == -1) + { + // bring down dialog if error when filling list box + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L); + } + + // Set the name of the current object. + SetDlgItemText(hDlg, IDC_CV_OBJECTTYPE, lpCV->lpszCurrentObject); + + // Disable the "Activate As" button if the Activate list doesn't + // have any objects in it. + int cItemsActivate = (INT)SendMessage(lpCV->hListVisible, LB_GETCOUNT, 0, 0L); + if (1 >= cItemsActivate || (lpCV->dwFlags & CF_DISABLEACTIVATEAS)) + StandardEnableDlgItem(hDlg, IDC_CV_ACTIVATEAS, FALSE); + + // Set the tab width in the list to push all the tabs off the side. + RECT rect; + if (lpCV->hListVisible != NULL) + GetClientRect(lpCV->hListVisible, &rect); + else + GetClientRect(lpCV->hListInvisible, &rect); + DWORD dw = GetDialogBaseUnits(); + rect.right = (8*rect.right)/LOWORD(dw); //Convert pixels to 2x dlg units. + if (lpCV->hListVisible != NULL) + SendMessage(lpCV->hListVisible, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)(&rect.right)); + SendMessage(lpCV->hListInvisible, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)(&rect.right)); + + // Make sure that either "Convert To" or "Activate As" is selected + // and initialize listbox contents and selection accordingly + if (lpCV->dwFlags & CF_SELECTACTIVATEAS) + { + // Don't need to adjust listbox here because FillClassList + // initializes to the "Activate As" state. + CheckRadioButton(hDlg, IDC_CV_CONVERTTO, IDC_CV_ACTIVATEAS, IDC_CV_ACTIVATEAS); + + // Hide the icon stuff when Activate is selected...it gets shown + // again when Convert is selected. + StandardShowDlgItem(hDlg, IDC_CV_DISPLAYASICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_CV_CHANGEICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_CV_ICONDISPLAY, SW_HIDE); + } + else + { + // Default case. If user hasn't selected either flag, we will + // come here anyway. + // swap listboxes. + + HWND hWndTemp = lpCV->hListVisible; + + if (lpCV->dwFlags & CF_DISABLEDISPLAYASICON) + { + StandardShowDlgItem(hDlg, IDC_CV_DISPLAYASICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_CV_CHANGEICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_CV_ICONDISPLAY, SW_HIDE); + } + + lpCV->dwFlags |= CF_SELECTCONVERTTO; // Make sure flag is set + if (!(lpCV->dwFlags & CF_CONVERTONLY)) + CheckRadioButton(hDlg, IDC_CV_CONVERTTO, IDC_CV_ACTIVATEAS, IDC_CV_CONVERTTO); + + SwapWindows(hDlg, lpCV->hListVisible, lpCV->hListInvisible); + + lpCV->hListVisible = lpCV->hListInvisible; + lpCV->hListInvisible = hWndTemp; + + if (lpCV->hListInvisible) + EnableWindow(lpCV->hListInvisible, FALSE); + EnableWindow(lpCV->hListVisible, TRUE); + } + + // Initialize Default strings. + + // Default convert string is easy...just user the user type name from + // the clsid we got, or the current object + if ((lpCV->dwFlags & CF_SETCONVERTDEFAULT) + && (IsValidClassID(lpCV->lpOCV->clsidConvertDefault))) + { + LPOLESTR lpszTemp = NULL; + if (OleRegGetUserType(lpCV->lpOCV->clsidConvertDefault, USERCLASSTYPE_FULL, + &lpszTemp) == NOERROR) + { +#if defined(WIN32) && !defined(UNICODE) + WTOA(lpCV->lpszConvertDefault, lpszTemp, OLEUI_CCHLABELMAX); +#else + lstrcpyn(lpCV->lpszConvertDefault, lpszTemp, OLEUI_CCHLABELMAX); +#endif + OleStdFree(lpszTemp); + } + else + { + lstrcpy(lpCV->lpszConvertDefault, lpCV->lpszCurrentObject); + } + } + else + lstrcpy(lpCV->lpszConvertDefault, lpCV->lpszCurrentObject); + + + // Default activate is a bit trickier. We want to use the user type + // name if from the clsid we got (assuming we got one), or the current + // object if it fails or we didn't get a clsid. But...if there's a + // Treat As entry in the reg db, then we use that instead. So... the + // logic boils down to this: + // + // if ("Treat As" in reg db) + // use it; + // else + // if (CF_SETACTIVATEDEFAULT) + // use it; + // else + // use current object; + + HKEY hKey; + LONG lRet = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("CLSID"), &hKey); + + if (lRet != ERROR_SUCCESS) + goto CheckInputFlag; + + LPOLESTR lpszCLSID; + StringFromCLSID(lpCV->lpOCV->clsid, &lpszCLSID); + TCHAR szKey[OLEUI_CCHKEYMAX]; +#if defined(WIN32) && !defined(UNICODE) + WTOA(szKey, lpszCLSID, OLEUI_CCHKEYMAX); +#else + lstrcpy(szKey, lpszCLSID); +#endif + lstrcat(szKey, TEXT("\\TreatAs")); + OleStdFree(lpszCLSID); + + TCHAR szValue[OLEUI_CCHKEYMAX]; + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, szKey, szValue, (LONG*)&dw); + + CLSID clsid; + if (lRet != ERROR_SUCCESS) + { + RegCloseKey(hKey); + goto CheckInputFlag; + } + else + { +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszValue[OLEUI_CCHKEYMAX]; + ATOW(wszValue,szValue,OLEUI_CCHKEYMAX); + CLSIDFromString(wszValue, &clsid); +#else + CLSIDFromString(szValue, &clsid); +#endif + LPOLESTR lpszTemp = NULL; + if (OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &lpszTemp) == NOERROR) + { +#if defined(WIN32) && !defined(UNICODE) + WTOA(lpCV->lpszActivateDefault, lpszTemp, OLEUI_CCHLABELMAX); +#else + lstrcpyn(lpCV->lpszActivateDefault, lpszTemp, OLEUI_CCHLABELMAX); +#endif + OleStdFree(lpszTemp); + } + else + { + RegCloseKey(hKey); + goto CheckInputFlag; + } + } + RegCloseKey(hKey); + goto SelectStringInListbox; + +CheckInputFlag: + if ((lpCV->dwFlags & CF_SETACTIVATEDEFAULT) + && (IsValidClassID(lpCV->lpOCV->clsidActivateDefault))) + { + LPOLESTR lpszTemp = NULL; + if (OleRegGetUserType(lpCV->lpOCV->clsidActivateDefault, USERCLASSTYPE_FULL, + &lpszTemp) == NOERROR) + { +#if defined(WIN32) && !defined(UNICODE) + WTOA(lpCV->lpszActivateDefault, lpszTemp, OLEUI_CCHLABELMAX); +#else + lstrcpyn(lpCV->lpszActivateDefault, lpszTemp, OLEUI_CCHLABELMAX); +#endif + OleStdFree(lpszTemp); + } + else + { + lstrcpy(lpCV->lpszActivateDefault, lpCV->lpszCurrentObject); + } + } + else + lstrcpy((lpCV->lpszActivateDefault), lpCV->lpszCurrentObject); + + +SelectStringInListbox: + if (lpCV->dwFlags & CF_SELECTCONVERTTO) + lRet = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszConvertDefault); + else + lRet = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszActivateDefault); + + if (LB_ERR == lRet) + SendMessage(lpCV->hListVisible, LB_SETCURSEL, (WPARAM)0, 0L); + + if ((HGLOBAL)NULL != lpOCV->hMetaPict) + { + HGLOBAL hMetaPict = OleDuplicateData(lpOCV->hMetaPict, CF_METAFILEPICT, NULL); + SendDlgItemMessage(hDlg, IDC_CV_ICONDISPLAY, IBXM_IMAGESET, + 0, (LPARAM)hMetaPict); + lpCV->fCustomIcon = TRUE; + } + else + { + UpdateClassIcon(hDlg, lpCV, lpCV->hListVisible); + } + + // Initialize icon stuff + if (DVASPECT_ICON == lpCV->dvAspect ) + { + SendDlgItemMessage(hDlg, IDC_CV_DISPLAYASICON, BM_SETCHECK, TRUE, 0L); + } + else + { + // Hide & disable icon stuff + StandardShowDlgItem(hDlg, IDC_CV_CHANGEICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_CV_ICONDISPLAY, SW_HIDE); + } + + // Call the hook with lCustData in lParam + UStandardHook((LPVOID)lpCV, hDlg, WM_INITDIALOG, wParam, lpOCV->lCustData); + + // Update results window + SetConvertResults(hDlg, lpCV); + + // Update caption if lpszCaption was specified + if (lpCV->lpOCV->lpszCaption && !IsBadReadPtr(lpCV->lpOCV->lpszCaption, 1)) + { + SetWindowText(hDlg, lpCV->lpOCV->lpszCaption); + } + + return TRUE; +} + +/* + * FillClassList + * + * Purpose: + * Enumerates available OLE object classes from the registration + * database that we can convert or activate the specified clsid from. + * + * Note that this function removes any prior contents of the listbox. + * + * Parameters: + * clsid Class ID for class to find convert classes for + * hList HWND to the listbox to fill. + * hListActivate HWND to invisible listbox that stores "activate as" list. + * lpszClassName LPSTR to put the (hr) class name of the clsid; we + * do it here since we've already got the reg db open. + * fIsLinkedObject BOOL is the original object a linked object + * wFormat WORD specifying the format of the original class. + * cClsidExclude UINT number of entries in exclude list + * lpClsidExclude LPCLSID array classes to exclude for list + * + * Return Value: + * UINT Number of strings added to the listbox, -1 on failure. + */ +UINT FillClassList(CLSID clsid, HWND hListActivate, HWND hListConvert, + LPTSTR FAR *lplpszCurrentClass, BOOL fIsLinkedObject, + WORD wFormat, UINT cClsidExclude, LPCLSID lpClsidExclude, BOOL bAddSameClass) +{ + // Clean out the existing strings. + if (hListActivate) + SendMessage(hListActivate, LB_RESETCONTENT, 0, 0L); + + OleDbgAssert(hListConvert != NULL); + SendMessage(hListConvert, LB_RESETCONTENT, 0, 0L); + + // Open up the root key. + HKEY hKey; + LONG lRet = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("CLSID"), &hKey); + + if (ERROR_SUCCESS != lRet) + return (UINT)-1; + + if (NULL == *lplpszCurrentClass) + { +#if defined(WIN32) && !defined(UNICODE) + LPOLESTR wszCurrentClass; + if (OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &wszCurrentClass) != NOERROR) +#else + if (OleRegGetUserType(clsid, USERCLASSTYPE_FULL, lplpszCurrentClass) != NOERROR) +#endif + { + *lplpszCurrentClass = OleStdLoadString(_g_hOleStdResInst, IDS_PSUNKNOWNTYPE); + if (*lplpszCurrentClass == NULL) + { + RegCloseKey(hKey); + return (UINT)-1; + } + } +#if defined(WIN32) && !defined(UNICODE) + else + { + UINT uLen = WTOALEN(wszCurrentClass); + *lplpszCurrentClass = (LPTSTR)OleStdMalloc(uLen); + if (NULL == *lplpszCurrentClass) + { + RegCloseKey(hKey); + OleStdFree(wszCurrentClass); + return (UINT)-1; + } + WTOA(*lplpszCurrentClass, wszCurrentClass, uLen); + OleStdFree(wszCurrentClass); + } +#endif + } + + // Get the class name of the original class. + LPTSTR lpszCLSID; +#if defined(WIN32) && !defined(UNICODE) + // This code does not report allocation errors because neither did + // the original code before I extended it to support 32-bit ANSI builds. + // (NOTE that the result of StringFromCLSID is never checked against + // NULL after the #else case below, which contains the original code.) + // In any event, if OleStdMalloc returns NULL, then the string will + // simply be lost. Technically an error, but not a fatal one. + LPOLESTR wszCLSID; + StringFromCLSID(clsid, &wszCLSID); + lpszCLSID = NULL; + if (NULL != wszCLSID) + { + UINT uLen = WTOALEN(wszCLSID); + lpszCLSID = (LPTSTR) OleStdMalloc(uLen); + if (NULL != lpszCLSID) + { + WTOA(lpszCLSID, wszCLSID, uLen); + } + OleStdFree(wszCLSID); + } +#else + StringFromCLSID(clsid, &lpszCLSID); +#endif + // Here, we step through the entire registration db looking for + // class that can read or write the original class' format. We + // maintain two lists - an activate list and a convert list. The + // activate list is a subset of the convert list - activate == read/write + // and convert == read. We swap the listboxes as needed with + // SwapWindows, and keep track of which is which in the lpCV structure. + + // Every item has the following format: + // + // Class Name\tclsid\0 + + UINT cStrings = 0; + TCHAR szClass[OLEUI_CCHKEYMAX]; + lRet = RegEnumKey(hKey, cStrings++, szClass, OLEUI_CCHKEYMAX_SIZE); + + TCHAR szFormatKey[OLEUI_CCHKEYMAX]; + TCHAR szFormat[OLEUI_CCHKEYMAX]; + TCHAR szHRClassName[OLEUI_CCHKEYMAX]; + CLSID clsidForList; + + while (ERROR_SUCCESS == lRet) + { + UINT j; + BOOL fExclude = FALSE; + + //Check if this CLSID is in the exclusion list. +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszClass[OLEUI_CCHKEYMAX]; + ATOW(wszClass, szClass, OLEUI_CCHKEYMAX); + CLSIDFromString(wszClass, &clsidForList); +#else + CLSIDFromString(szClass, &clsidForList); +#endif + for (j = 0; j < cClsidExclude; j++) + { + if (IsEqualCLSID(clsidForList, lpClsidExclude[j])) + { + fExclude=TRUE; + break; + } + } + if (fExclude) + goto Next; // don't add this class to list + + // Check for a \Conversion\Readwritable\Main - if its + // readwriteable, then the class can be added to the ActivateAs + // list. + // NOTE: the presence of this key should NOT automatically be + // used to add the class to the CONVERT list. + + lstrcpy(szFormatKey, szClass); + lstrcat(szFormatKey, TEXT("\\Conversion\\Readwritable\\Main")); + + DWORD dw; dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, szFormatKey, szFormat, (LONG*)&dw); + + if (ERROR_SUCCESS == lRet && FormatIncluded(szFormat, wFormat)) + { + // Here, we've got a list of formats that this class can read + // and write. We need to see if the original class' format is + // in this list. We do that by looking for wFormat in + // szFormat - if it in there, then we add this class to the + // ACTIVATEAS list only. we do NOT automatically add it to the + // CONVERT list. Readable and Readwritable format lists should + // be handled separately. + + dw=OLEUI_CCHKEYMAX_SIZE; + lRet=RegQueryValue(hKey, szClass, szHRClassName, (LONG*)&dw); + + if (ERROR_SUCCESS == lRet && hListActivate != NULL) + { + // only add if not already in list + lstrcat(szHRClassName, TEXT("\t")); + if (LB_ERR == SendMessage(hListActivate, LB_FINDSTRING, 0, (LPARAM)szHRClassName)) + { + lstrcat(szHRClassName, szClass); + SendMessage(hListActivate, LB_ADDSTRING, 0, (DWORD)szHRClassName); + } + } + } + + // Here we'll check to see if the original class' format is in the + // readable list. if so, we will add the class to the CONVERTLIST + + // We've got a special case for a linked object here. + // If an object is linked, then the only class that + // should appear in the convert list is the object's + // class. So, here we check to see if the object is + // linked. If it is, then we compare the classes. If + // they aren't the same, then we just go to the next key. + + if (!fIsLinkedObject || lstrcmp(lpszCLSID, szClass) == 0) + { + //Check for a \Conversion\Readable\Main entry + lstrcpy(szFormatKey, szClass); + lstrcat(szFormatKey, TEXT("\\Conversion\\Readable\\Main")); + + // Check to see if this class can read the original class + // format. If it can, add the string to the listbox as + // CONVERT_LIST. + + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, szFormatKey, szFormat, (LONG*)&dw); + + if (ERROR_SUCCESS == lRet && FormatIncluded(szFormat, wFormat)) + { + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, szClass, szHRClassName, (LONG*)&dw); + + if (ERROR_SUCCESS == lRet) + { + // only add if not already in list + lstrcat(szHRClassName, TEXT("\t")); + if (LB_ERR == SendMessage(hListConvert, LB_FINDSTRING, 0, (LPARAM)szHRClassName)) + { + lstrcat(szHRClassName, szClass); + SendMessage(hListConvert, LB_ADDSTRING, 0, (DWORD)szHRClassName); + } + } + } + } +Next: + //Continue with the next key. + lRet = RegEnumKey(hKey, cStrings++, szClass, OLEUI_CCHKEYMAX_SIZE); + + } // end while + + // If the original class isn't already in the list, add it. + if (bAddSameClass) + { + lstrcpy(szHRClassName, *lplpszCurrentClass); + lstrcat(szHRClassName, TEXT("\t")); + lstrcat(szHRClassName, lpszCLSID); + + if (hListActivate != NULL) + { + // only add it if it's not there already. + lRet = SendMessage(hListActivate, LB_FINDSTRING, (WPARAM)-1, (LPARAM)szHRClassName); + if (LB_ERR == lRet) + SendMessage(hListActivate, LB_ADDSTRING, 0, (LPARAM)szHRClassName); + } + + // only add it if it's not there already. + lRet = SendMessage(hListConvert, LB_FINDSTRING, (WPARAM)-1, (LPARAM)szHRClassName); + if (LB_ERR == lRet) + SendMessage(hListConvert, LB_ADDSTRING, 0, (LPARAM)szHRClassName); + } + + // Free the string we got from StringFromCLSID. + OleStdFree(lpszCLSID); + RegCloseKey(hKey); + + return cStrings; // return # of strings added +} + +/* + * OleUICanConvertOrActivateAs + * + * Purpose: + * Determine if there is any OLE object class from the registration + * database that we can convert or activate the specified clsid from. + * + * Parameters: + * rClsid REFCLSID Class ID for class to find convert classes for + * fIsLinkedObject BOOL is the original object a linked object + * wFormat WORD specifying the format of the original class. + * + * Return Value: + * BOOL TRUE if Convert command should be enabled, else FALSE + */ +STDAPI_(BOOL) OleUICanConvertOrActivateAs( + REFCLSID rClsid, BOOL fIsLinkedObject, WORD wFormat) +{ + // Open up the root key. + HKEY hKey; + LONG lRet = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("CLSID"), &hKey); + + if (ERROR_SUCCESS != lRet) + return FALSE; + + // Get the class name of the original class. + LPTSTR lpszCLSID; +#if defined(WIN32) && !defined(UNICODE) + // This code does not report allocation errors because neither did + // the original code before I extended it to support 32-bit ANSI builds. + // In any event, if OleStdMalloc returns NULL, then the string will + // simply be lost. Technically an error, but not a fatal one. + // Since this routine has no way to report errors anyway (a design flaw + // IMHO) I consider this to be marginally acceptable. + LPOLESTR wszCLSID; + StringFromCLSID(rClsid, &wszCLSID); + lpszCLSID = NULL; + if (NULL != wszCLSID) + { + UINT uLen = WTOALEN(wszCLSID); + lpszCLSID = (LPTSTR) OleStdMalloc(uLen); + if (NULL != lpszCLSID) + { + WTOA(lpszCLSID, wszCLSID, uLen); + } + OleStdFree(wszCLSID); + } +#else + StringFromCLSID(rClsid, &lpszCLSID); +#endif + + // Here, we step through the entire registration db looking for + // class that can read or write the original class' format. + // This loop stops if a single class is found. + + UINT cStrings = 0; + TCHAR szClass[OLEUI_CCHKEYMAX]; + lRet = RegEnumKey(hKey, cStrings++, szClass, OLEUI_CCHKEYMAX_SIZE); + + TCHAR szFormatKey[OLEUI_CCHKEYMAX]; + TCHAR szFormat[OLEUI_CCHKEYMAX]; + TCHAR szHRClassName[OLEUI_CCHKEYMAX]; + BOOL fEnableConvert = FALSE; + + while (ERROR_SUCCESS == lRet) + { + if (lstrcmp(lpszCLSID, szClass) == 0) + goto next; // we don't want to consider the source class + + // Check for a \Conversion\ReadWriteable\Main entry first - if its + // readwriteable, then we don't need to bother checking to see if + // its readable. + + lstrcpy(szFormatKey, szClass); + lstrcat(szFormatKey, TEXT("\\Conversion\\Readwritable\\Main")); + DWORD dw; dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, szFormatKey, szFormat, (LONG*)&dw); + + if (ERROR_SUCCESS != lRet) + { + // Try \\DataFormats\DefaultFile too + lstrcpy(szFormatKey, szClass); + lstrcat(szFormatKey, TEXT("\\DataFormats\\DefaultFile")); + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, szFormatKey, szFormat, (LONG*)&dw); + } + + if (ERROR_SUCCESS == lRet && FormatIncluded(szFormat, wFormat)) + { + // Here, we've got a list of formats that this class can read + // and write. We need to see if the original class' format is + // in this list. We do that by looking for wFormat in + // szFormat - if it in there, then we add this class to the + // both lists and continue. If not, then we look at the + // class' readable formats. + + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, szClass, szHRClassName, (LONG*)&dw); + if (ERROR_SUCCESS == lRet) + { + fEnableConvert = TRUE; + break; // STOP -- found one! + } + } + + // We either didn't find the readwritable key, or the + // list of readwritable formats didn't include the + // original class format. So, here we'll check to + // see if its in the readable list. + + // We've got a special case for a linked object here. + // If an object is linked, then the only class that + // should appear in the convert list is the object's + // class. So, here we check to see if the object is + // linked. If it is, then we compare the classes. If + // they aren't the same, then we just go to the next key. + + else if (!fIsLinkedObject || lstrcmp(lpszCLSID, szClass) == 0) + { + // Check for a \Conversion\Readable\Main entry + lstrcpy(szFormatKey, szClass); + lstrcat(szFormatKey, TEXT("\\Conversion\\Readable\\Main")); + + // Check to see if this class can read the original class format. + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, szFormatKey, szFormat, (LONG*)&dw); + + if (ERROR_SUCCESS == lRet && FormatIncluded(szFormat, wFormat)) + { + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, szClass, szHRClassName, (LONG*)&dw); + if (ERROR_SUCCESS == lRet) + { + fEnableConvert = TRUE; + break; // STOP -- found one! + } + } + } +next: + // Continue with the next key. + lRet = RegEnumKey(hKey, cStrings++, szClass, OLEUI_CCHKEYMAX_SIZE); + } + + // Free the string we got from StringFromCLSID. + OleStdFree(lpszCLSID); + RegCloseKey(hKey); + + return fEnableConvert; +} + +/* + * FormatIncluded + * + * Purpose: + * Parses the string for format from the word. + * + * Parameters: + * szStringToSearch String to parse + * wFormat format to find + * + * Return Value: + * BOOL TRUE if format is found in string, + * FALSE otherwise. + */ +BOOL FormatIncluded(LPTSTR szStringToSearch, WORD wFormat) +{ + TCHAR szFormat[255]; + if (wFormat < 0xC000) + wsprintf(szFormat, TEXT("%d"), wFormat); + else + GetClipboardFormatName(wFormat, szFormat, 255); + + LPTSTR lpToken = szStringToSearch; + while (lpToken != NULL) + { + LPTSTR lpTokenNext = FindChar(lpToken, TEXT(',')); + if (lpTokenNext != NULL) + { + *lpTokenNext = 0; + ++lpTokenNext; + } + if (0 == lstrcmpi(lpToken, szFormat)) + return TRUE; + + lpToken = lpTokenNext; + } + return FALSE; +} + +/* + * UpdateClassIcon + * + * Purpose: + * Handles LBN_SELCHANGE for the Object Type listbox. On a selection + * change, we extract an icon from the server handling the currently + * selected object type using the utility function HIconFromClass. + * Note that we depend on the behavior of FillClassList to stuff the + * object class after a tab in the listbox string that we hide from + * view (see WM_INITDIALOG). + * + * Parameters + * hDlg HWND of the dialog box. + * lpCV LPCONVERT pointing to the dialog structure + * hList HWND of the Object Type listbox. + * + * Return Value: + * None + */ +static void UpdateClassIcon(HWND hDlg, LPCONVERT lpCV, HWND hList) +{ + if (GetDlgItem(hDlg, IDC_CV_ICONDISPLAY) == NULL) + return; + + // Get current selection in the list box + int iSel= (UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L); + if (LB_ERR == iSel) + return; + + // Allocate a string to hold the entire listbox string + DWORD cb = SendMessage(hList, LB_GETTEXTLEN, iSel, 0L); + LPTSTR pszName = (LPTSTR)OleStdMalloc((cb+1) * sizeof(TCHAR)); + if (pszName == NULL) + return; + + // Get whole string + SendMessage(hList, LB_GETTEXT, iSel, (LPARAM)pszName); + + // Set pointer to CLSID (string) + LPTSTR pszCLSID = PointerToNthField(pszName, 2, '\t'); + + // Create the class ID with this string. + CLSID clsid; +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszCLSID[OLEUI_CCHKEYMAX]; + ATOW(wszCLSID, pszCLSID, OLEUI_CCHKEYMAX); + CLSIDFromString(wszCLSID, &clsid); +#else + CLSIDFromString(pszCLSID, &clsid); +#endif + // Get Icon for that CLSID + HGLOBAL hMetaPict = OleGetIconOfClass(clsid, NULL, TRUE); + + // Replace current icon with the new one. + SendDlgItemMessage(hDlg, IDC_CV_ICONDISPLAY, IBXM_IMAGESET, 1, + (LPARAM)hMetaPict); + + OleStdFree(pszName); +} + +/* + * SetConvertResults + * + * Purpose: + * Centralizes setting of the Result display in the Convert + * dialog. Handles loading the appropriate string from the module's + * resources and setting the text, displaying the proper result picture, + * and showing the proper icon. + * + * Parameters: + * hDlg HWND of the dialog box so we can access controls. + * lpCV LPCONVERT in which we assume that the dwFlags is + * set to the appropriate radio button selection, and + * the list box has the appropriate class selected. + * + * Return Value: + * None + */ +void SetConvertResults(HWND hDlg, LPCONVERT lpCV) +{ + HWND hList = lpCV->hListVisible; + + /* + * We need scratch memory for loading the stringtable string, loading + * the object type from the listbox, loading the source object + * type, and constructing the final string. We therefore allocate + * four buffers as large as the maximum message length (512) plus + * the object type, guaranteeing that we have enough + * in all cases. + */ + UINT i = (UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L); + UINT cch = 512+(UINT)SendMessage(hList, LB_GETTEXTLEN, i, 0L); + HGLOBAL hMem = GlobalAlloc(GHND, (DWORD)(4*cch)*sizeof(TCHAR)); + if (NULL == hMem) + return; + + LPTSTR lpszOutput = (LPTSTR)GlobalLock(hMem); + LPTSTR lpszSelObj = lpszOutput + cch; + LPTSTR lpszDefObj = lpszSelObj + cch; + LPTSTR lpszString = lpszDefObj + cch; + + // Get selected object and null terminate human-readable name (1st field). + SendMessage(hList, LB_GETTEXT, i, (LPARAM)lpszSelObj); + + LPTSTR pszT = PointerToNthField(lpszSelObj, 2, '\t'); + pszT = CharPrev(lpszSelObj, pszT); + *pszT = '\0'; + + // Get default object + GetDlgItemText(hDlg, IDC_CV_OBJECTTYPE, lpszDefObj, 512); + + //Default is an empty string. + *lpszOutput=0; + + if (lpCV->dwFlags & CF_SELECTCONVERTTO) + { + if (lpCV->lpOCV->fIsLinkedObject) // working with linked object + LoadString(_g_hOleStdResInst, IDS_CVRESULTCONVERTLINK, lpszOutput, cch); + else + { + if (0 !=lstrcmp(lpszDefObj, lpszSelObj)) + { + // converting to a new class + if (0 != LoadString(_g_hOleStdResInst, IDS_CVRESULTCONVERTTO, lpszString, cch)) + FormatString2(lpszOutput, lpszString, lpszDefObj, lpszSelObj); + } + else + { + // converting to the same class (no conversion) + if (0 != LoadString(_g_hOleStdResInst, IDS_CVRESULTNOCHANGE, lpszString, cch)) + wsprintf(lpszOutput, lpszString, lpszDefObj); + } + } + + if (lpCV->dvAspect == DVASPECT_ICON) // Display as icon is checked + { + if (0 != LoadString(_g_hOleStdResInst, IDS_CVRESULTDISPLAYASICON, lpszString, cch)) + lstrcat(lpszOutput, lpszString); + } + } + + if (lpCV->dwFlags & CF_SELECTACTIVATEAS) + { + if (0 != LoadString(_g_hOleStdResInst, IDS_CVRESULTACTIVATEAS, lpszString, cch)) + FormatString2(lpszOutput, lpszString, lpszDefObj, lpszSelObj); + + // activating as a new class + if (0 != lstrcmp(lpszDefObj, lpszSelObj)) + { + if (0 != LoadString(_g_hOleStdResInst, IDS_CVRESULTACTIVATEDIFF, lpszString, cch)) + lstrcat(lpszOutput, lpszString); + } + else // activating as itself. + { + lstrcat(lpszOutput, TEXT(".")); + } + } + + // If LoadString failed, we simply clear out the results (*lpszOutput=0 above) + SetDlgItemText(hDlg, IDC_CV_RESULTTEXT, lpszOutput); + + GlobalUnlock(hMem); + GlobalFree(hMem); +} + +/* + * ConvertCleanup + * + * Purpose: + * Performs convert-specific cleanup before Convert termination. + * + * Parameters: + * hDlg HWND of the dialog box so we can access controls. + * + * Return Value: + * None + */ +void ConvertCleanup(HWND hDlg, LPCONVERT lpCV) +{ + // Free our strings. Zero out the user type name string + // the the calling app doesn't free to it. + + OleStdFree((LPVOID)lpCV->lpszConvertDefault); + OleStdFree((LPVOID)lpCV->lpszActivateDefault); + OleStdFree((LPVOID)lpCV->lpszIconSource); + if (lpCV->lpOCV->lpszUserType) + { + OleStdFree((LPVOID)lpCV->lpOCV->lpszUserType); + lpCV->lpOCV->lpszUserType = NULL; + } + + if (lpCV->lpOCV->lpszDefLabel) + { + OleStdFree((LPVOID)lpCV->lpOCV->lpszDefLabel); + lpCV->lpOCV->lpszDefLabel = NULL; + } +} + +/* + * SwapWindows + * + * Purpose: + * Moves hWnd1 to hWnd2's position and hWnd2 to hWnd1's position. + * Does NOT change sizes. + * + * Parameters: + * hDlg HWND of the dialog box so we can turn redraw off + * + * Return Value: + * None + */ +void SwapWindows(HWND hDlg, HWND hWnd1, HWND hWnd2) +{ + if (hWnd1 != NULL && hWnd2 != NULL) + { + RECT rect1; GetWindowRect(hWnd1, &rect1); + ScreenToClient(hDlg, (LPPOINT)&rect1.left); + ScreenToClient(hDlg, (LPPOINT)&rect1.right); + + RECT rect2; GetWindowRect(hWnd2, &rect2); + ScreenToClient(hDlg, (LPPOINT)&rect2.left); + ScreenToClient(hDlg, (LPPOINT)&rect2.right); + + SetWindowPos(hWnd1, NULL, + rect2.left, rect2.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + SetWindowPos(hWnd2, NULL, + rect1.left, rect1.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + } +} diff --git a/private/ole2ui32/daytona/makefile b/private/ole2ui32/daytona/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ole2ui32/daytona/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ole2ui32/daytona/sources b/private/ole2ui32/daytona/sources new file mode 100644 index 000000000..92fd5ccfa --- /dev/null +++ b/private/ole2ui32/daytona/sources @@ -0,0 +1,74 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + + +!ENDIF + +DLLENTRY=DllMain + +DLLDEF=obj\*\oledlg.def + +MAJORCOMP=oledlg +MINORCOMP= + +TARGETNAME=oledlg +TARGETPATHLIB=$(BASEDIR)\public\sdk\lib +TARGETPATH=obj +C_DEFINES=-DWIN32 -DWINVER=0x400 -DUNICODE +TARGETTYPE=DYNLINK + +UMTYPE=windows +INCLUDES=.. + +PRECOMPILED_INCLUDE=..\precomp.h +PRECOMPILED_PCH=precomp.pch +PRECOMPILED_OBJ=precomp.obj + +SOURCES= ..\chngsrc.cpp \ + ..\objprop.cpp \ + ..\busy.cpp \ + ..\common.cpp \ + ..\convert.cpp \ + ..\drawicon.cpp \ + ..\icon.cpp \ + ..\iconbox.cpp \ + ..\insobj.cpp \ + ..\links.cpp \ + ..\ole2ui.cpp \ + ..\olestd.cpp \ + ..\pastespl.cpp \ + ..\targtdev.cpp \ + ..\oleutl.cpp \ + ..\resimage.cpp \ + ..\utility.cpp \ + ..\dllfuncs.cpp \ + ..\geticon.cpp \ + ..\wrapstub.cpp \ + ..\ole2ui.rc + +USE_CRTDLL=1 + +TARGETLIBS= \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\user32.lib \ + $(BASEDIR)\public\sdk\lib\*\gdi32.lib \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib \ + $(BASEDIR)\public\sdk\lib\*\ole32.lib \ + $(BASEDIR)\public\sdk\lib\*\uuid.lib + diff --git a/private/ole2ui32/dbgutil.cpp b/private/ole2ui32/dbgutil.cpp new file mode 100644 index 000000000..b66c703ba --- /dev/null +++ b/private/ole2ui32/dbgutil.cpp @@ -0,0 +1,372 @@ +/************************************************************************* +** +** OLE 2.0 Common Utilities +** +** dbgutil.h +** +** This file contains file contains functions to support debug output. +** +** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved +** +*************************************************************************/ + +#include "precomp.h" + +#ifdef _DEBUG + +static int s_nDbgIndent = 0; // indent level for debug message +static int s_nDbgLevel = 0; // default dbg level printed + +STDAPI_(void) OleDbgPrint( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + int nIndent) +{ + if (nDbgLvl <= s_nDbgLevel) + OleDbgPrintAlways(lpszPrefix, lpszMsg, nIndent); +} + +STDAPI_(void) OleDbgPrintAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, int nIndent) +{ + if (nIndent < 0) + OleDbgIndent(nIndent); + + if (lpszPrefix && *lpszPrefix != '\0') + { + OutputDebugString(TEXT("| ")); + for (int i = 0; i < s_nDbgIndent; i++) + OutputDebugString(TEXT("----")); + + OutputDebugString(lpszPrefix); + OutputDebugString(TEXT(": ")); + } + + OutputDebugString(lpszMsg); + if (nIndent > 0) + OleDbgIndent(nIndent); +} + +STDAPI_(void) OleDbgSetDbgLevel(int nDbgLvl) +{ + s_nDbgLevel = nDbgLvl; +} + +STDAPI_(int) OleDbgGetDbgLevel( void ) +{ + return s_nDbgLevel; +} + +STDAPI_(void) OleDbgIndent(int n) +{ + switch (n) + { + case -1: + s_nDbgIndent--; + break; + case 1: + s_nDbgIndent++; + break; + case -2: + s_nDbgIndent = 0; + break; + } +} + + +STDAPI_(void) OleDbgPrintRefCnt( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPVOID lpObj, + ULONG refcnt) +{ + if (nDbgLvl <= s_nDbgLevel) + OleDbgPrintRefCntAlways(lpszPrefix, lpszMsg, lpObj, refcnt); +} + + +STDAPI_(void) OleDbgPrintRefCntAlways( + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPVOID lpObj, + ULONG refcnt) +{ + TCHAR szBuf[256]; + wsprintf(szBuf, TEXT("[obj=(0x%lx) cnt=%ld] %s"), lpObj, refcnt, lpszMsg); + OleDbgPrintAlways(lpszPrefix, szBuf, 0); +} + +STDAPI_(void) OleDbgPrintRect( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPRECT lpRect) +{ + if (nDbgLvl <= s_nDbgLevel) + OleDbgPrintRectAlways(lpszPrefix, lpszMsg, lpRect); +} + + +STDAPI_(void) OleDbgPrintRectAlways( + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPRECT lpRect) +{ + TCHAR szBuf[256]; + wsprintf( + szBuf, + TEXT("%s: (%d,%d)-(%d,%d) %dx%d\r\n"), + lpszMsg, + lpRect->left, + lpRect->top, + lpRect->right, + lpRect->bottom, + (lpRect->right-lpRect->left), + (lpRect->bottom-lpRect->top) + ); + OleDbgPrintAlways(lpszPrefix, szBuf, 0); +} + + +#define CASE_SCODE(sc) \ + case sc: \ + pszErrName = TEXT(#sc); \ + break; + +STDAPI_(void) OleDbgPrintScodeAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, SCODE sc) +{ + const TCHAR* pszErrName; + + switch (sc) + { + /* SCODE's defined in SCODE.H */ + + CASE_SCODE(S_OK) + CASE_SCODE(S_FALSE) + CASE_SCODE(E_UNEXPECTED) + CASE_SCODE(E_OUTOFMEMORY) + CASE_SCODE(E_INVALIDARG) + CASE_SCODE(E_NOINTERFACE) + CASE_SCODE(E_POINTER) + CASE_SCODE(E_HANDLE) + CASE_SCODE(E_ABORT) + CASE_SCODE(E_FAIL) + CASE_SCODE(E_ACCESSDENIED) + + /* SCODE's defined in OLE2.H */ + + CASE_SCODE(OLE_E_OLEVERB) + CASE_SCODE(OLE_E_ADVF) + CASE_SCODE(OLE_E_ENUM_NOMORE) + CASE_SCODE(OLE_E_ADVISENOTSUPPORTED) + CASE_SCODE(OLE_E_NOCONNECTION) + CASE_SCODE(OLE_E_NOTRUNNING) + CASE_SCODE(OLE_E_NOCACHE) + CASE_SCODE(OLE_E_BLANK) + CASE_SCODE(OLE_E_CLASSDIFF) + CASE_SCODE(OLE_E_CANT_GETMONIKER) + CASE_SCODE(OLE_E_CANT_BINDTOSOURCE) + CASE_SCODE(OLE_E_STATIC) + CASE_SCODE(OLE_E_PROMPTSAVECANCELLED) + CASE_SCODE(OLE_E_INVALIDRECT) + CASE_SCODE(OLE_E_WRONGCOMPOBJ) + CASE_SCODE(OLE_E_INVALIDHWND) + CASE_SCODE(OLE_E_NOT_INPLACEACTIVE) + CASE_SCODE(OLE_E_CANTCONVERT) + CASE_SCODE(OLE_E_NOSTORAGE) + + CASE_SCODE(DV_E_FORMATETC) + CASE_SCODE(DV_E_DVTARGETDEVICE) + CASE_SCODE(DV_E_STGMEDIUM) + CASE_SCODE(DV_E_STATDATA) + CASE_SCODE(DV_E_LINDEX) + CASE_SCODE(DV_E_TYMED) + CASE_SCODE(DV_E_CLIPFORMAT) + CASE_SCODE(DV_E_DVASPECT) + CASE_SCODE(DV_E_DVTARGETDEVICE_SIZE) + CASE_SCODE(DV_E_NOIVIEWOBJECT) + + CASE_SCODE(OLE_S_USEREG) + CASE_SCODE(OLE_S_STATIC) + CASE_SCODE(OLE_S_MAC_CLIPFORMAT) + + CASE_SCODE(CONVERT10_E_OLESTREAM_GET) + CASE_SCODE(CONVERT10_E_OLESTREAM_PUT) + CASE_SCODE(CONVERT10_E_OLESTREAM_FMT) + CASE_SCODE(CONVERT10_E_OLESTREAM_BITMAP_TO_DIB) + CASE_SCODE(CONVERT10_E_STG_FMT) + CASE_SCODE(CONVERT10_E_STG_NO_STD_STREAM) + CASE_SCODE(CONVERT10_E_STG_DIB_TO_BITMAP) + CASE_SCODE(CONVERT10_S_NO_PRESENTATION) + + CASE_SCODE(CLIPBRD_E_CANT_OPEN) + CASE_SCODE(CLIPBRD_E_CANT_EMPTY) + CASE_SCODE(CLIPBRD_E_CANT_SET) + CASE_SCODE(CLIPBRD_E_BAD_DATA) + CASE_SCODE(CLIPBRD_E_CANT_CLOSE) + + CASE_SCODE(DRAGDROP_E_NOTREGISTERED) + CASE_SCODE(DRAGDROP_E_ALREADYREGISTERED) + CASE_SCODE(DRAGDROP_E_INVALIDHWND) + CASE_SCODE(DRAGDROP_S_DROP) + CASE_SCODE(DRAGDROP_S_CANCEL) + CASE_SCODE(DRAGDROP_S_USEDEFAULTCURSORS) + + CASE_SCODE(OLEOBJ_E_NOVERBS) + CASE_SCODE(OLEOBJ_E_INVALIDVERB) + CASE_SCODE(OLEOBJ_S_INVALIDVERB) + CASE_SCODE(OLEOBJ_S_CANNOT_DOVERB_NOW) + CASE_SCODE(OLEOBJ_S_INVALIDHWND) + CASE_SCODE(INPLACE_E_NOTUNDOABLE) + CASE_SCODE(INPLACE_E_NOTOOLSPACE) + CASE_SCODE(INPLACE_S_TRUNCATED) + + /* SCODE's defined in COMPOBJ.H */ + + CASE_SCODE(CO_E_NOTINITIALIZED) + CASE_SCODE(CO_E_ALREADYINITIALIZED) + CASE_SCODE(CO_E_CANTDETERMINECLASS) + CASE_SCODE(CO_E_CLASSSTRING) + CASE_SCODE(CO_E_IIDSTRING) + CASE_SCODE(CO_E_APPNOTFOUND) + CASE_SCODE(CO_E_APPSINGLEUSE) + CASE_SCODE(CO_E_ERRORINAPP) + CASE_SCODE(CO_E_DLLNOTFOUND) + CASE_SCODE(CO_E_ERRORINDLL) + CASE_SCODE(CO_E_WRONGOSFORAPP) + CASE_SCODE(CO_E_OBJNOTREG) + CASE_SCODE(CO_E_OBJISREG) + CASE_SCODE(CO_E_OBJNOTCONNECTED) + CASE_SCODE(CO_E_APPDIDNTREG) + CASE_SCODE(CLASS_E_NOAGGREGATION) + CASE_SCODE(CLASS_E_CLASSNOTAVAILABLE) + CASE_SCODE(REGDB_E_READREGDB) + CASE_SCODE(REGDB_E_WRITEREGDB) + CASE_SCODE(REGDB_E_KEYMISSING) + CASE_SCODE(REGDB_E_INVALIDVALUE) + CASE_SCODE(REGDB_E_CLASSNOTREG) + CASE_SCODE(REGDB_E_IIDNOTREG) + CASE_SCODE(RPC_E_CALL_REJECTED) + CASE_SCODE(RPC_E_CALL_CANCELED) + CASE_SCODE(RPC_E_CANTPOST_INSENDCALL) + CASE_SCODE(RPC_E_CANTCALLOUT_INASYNCCALL) + CASE_SCODE(RPC_E_CANTCALLOUT_INEXTERNALCALL) + CASE_SCODE(RPC_E_CONNECTION_TERMINATED) + CASE_SCODE(RPC_E_SERVER_DIED) + CASE_SCODE(RPC_E_CLIENT_DIED) + CASE_SCODE(RPC_E_INVALID_DATAPACKET) + CASE_SCODE(RPC_E_CANTTRANSMIT_CALL) + CASE_SCODE(RPC_E_CLIENT_CANTMARSHAL_DATA) + CASE_SCODE(RPC_E_CLIENT_CANTUNMARSHAL_DATA) + CASE_SCODE(RPC_E_SERVER_CANTMARSHAL_DATA) + CASE_SCODE(RPC_E_SERVER_CANTUNMARSHAL_DATA) + CASE_SCODE(RPC_E_INVALID_DATA) + CASE_SCODE(RPC_E_INVALID_PARAMETER) + CASE_SCODE(RPC_E_UNEXPECTED) + + /* SCODE's defined in DVOBJ.H */ + + CASE_SCODE(DATA_S_SAMEFORMATETC) + CASE_SCODE(VIEW_E_DRAW) + CASE_SCODE(VIEW_S_ALREADY_FROZEN) + CASE_SCODE(CACHE_E_NOCACHE_UPDATED) + CASE_SCODE(CACHE_S_FORMATETC_NOTSUPPORTED) + CASE_SCODE(CACHE_S_SAMECACHE) + CASE_SCODE(CACHE_S_SOMECACHES_NOTUPDATED) + + /* SCODE's defined in STORAGE.H */ + + CASE_SCODE(STG_E_INVALIDFUNCTION) + CASE_SCODE(STG_E_FILENOTFOUND) + CASE_SCODE(STG_E_PATHNOTFOUND) + CASE_SCODE(STG_E_TOOMANYOPENFILES) + CASE_SCODE(STG_E_ACCESSDENIED) + CASE_SCODE(STG_E_INVALIDHANDLE) + CASE_SCODE(STG_E_INSUFFICIENTMEMORY) + CASE_SCODE(STG_E_INVALIDPOINTER) + CASE_SCODE(STG_E_NOMOREFILES) + CASE_SCODE(STG_E_DISKISWRITEPROTECTED) + CASE_SCODE(STG_E_SEEKERROR) + CASE_SCODE(STG_E_WRITEFAULT) + CASE_SCODE(STG_E_READFAULT) + CASE_SCODE(STG_E_SHAREVIOLATION) + CASE_SCODE(STG_E_LOCKVIOLATION) + CASE_SCODE(STG_E_FILEALREADYEXISTS) + CASE_SCODE(STG_E_INVALIDPARAMETER) + CASE_SCODE(STG_E_MEDIUMFULL) + CASE_SCODE(STG_E_ABNORMALAPIEXIT) + CASE_SCODE(STG_E_INVALIDHEADER) + CASE_SCODE(STG_E_INVALIDNAME) + CASE_SCODE(STG_E_UNKNOWN) + CASE_SCODE(STG_E_UNIMPLEMENTEDFUNCTION) + CASE_SCODE(STG_E_INVALIDFLAG) + CASE_SCODE(STG_E_INUSE) + CASE_SCODE(STG_E_NOTCURRENT) + CASE_SCODE(STG_E_REVERTED) + CASE_SCODE(STG_E_CANTSAVE) + CASE_SCODE(STG_E_OLDFORMAT) + CASE_SCODE(STG_E_OLDDLL) + CASE_SCODE(STG_E_SHAREREQUIRED) + CASE_SCODE(STG_E_NOTFILEBASEDSTORAGE) + CASE_SCODE(STG_E_EXTANTMARSHALLINGS) + CASE_SCODE(STG_S_CONVERTED) + + /* SCODE's defined in STORAGE.H */ + + CASE_SCODE(MK_E_CONNECTMANUALLY) + CASE_SCODE(MK_E_EXCEEDEDDEADLINE) + CASE_SCODE(MK_E_NEEDGENERIC) + CASE_SCODE(MK_E_UNAVAILABLE) + CASE_SCODE(MK_E_SYNTAX) + CASE_SCODE(MK_E_NOOBJECT) + CASE_SCODE(MK_E_INVALIDEXTENSION) + CASE_SCODE(MK_E_INTERMEDIATEINTERFACENOTSUPPORTED) + CASE_SCODE(MK_E_NOTBINDABLE) + CASE_SCODE(MK_E_NOTBOUND) + CASE_SCODE(MK_E_CANTOPENFILE) + CASE_SCODE(MK_E_MUSTBOTHERUSER) + CASE_SCODE(MK_E_NOINVERSE) + CASE_SCODE(MK_E_NOSTORAGE) + CASE_SCODE(MK_E_NOPREFIX) + CASE_SCODE(MK_S_REDUCED_TO_SELF) + CASE_SCODE(MK_S_ME) + CASE_SCODE(MK_S_HIM) + CASE_SCODE(MK_S_US) + CASE_SCODE(MK_S_MONIKERALREADYREGISTERED) + + default: + pszErrName = TEXT("UNKNOWN SCODE"); + break; + } + + TCHAR szBuf[256]; + wsprintf(szBuf, TEXT("%s %s (0x%lx)\n"), lpszMsg, pszErrName, sc); + OleDbgPrintAlways(lpszPrefix, szBuf, 0); +} + +STDAPI OleStdAssert(LPTSTR lpstrExpr, LPTSTR lpstrMsg, LPTSTR lpstrFileName, UINT iLine) +{ + TCHAR buf[4096]; + wsprintf(buf, _T("Expr: %s Msg: (%s)\n") + _T("File: %s, line: %ud"), lpstrExpr, lpstrMsg, lpstrFileName, iLine); + int i = MessageBox(GetActiveWindow(), buf, _T("Assertion Failed!"), + MB_TASKMODAL|MB_ABORTRETRYIGNORE); + switch (i) + { + case IDABORT: + ExitProcess((UINT)-3); + break; + + case IDRETRY: + #ifdef _X86_ + _asm int 3; + #else + DebugBreak(); + #endif + break; + } + return NOERROR; +} + +#endif //_DEBUG diff --git a/private/ole2ui32/dirs b/private/ole2ui32/dirs new file mode 100644 index 000000000..0980150c3 --- /dev/null +++ b/private/ole2ui32/dirs @@ -0,0 +1,40 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Drew Bliss (DrewB) 21-Dec-1993 + +!ENDIF + +# +# This is a list of all subdirectories that build required components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +DIRS= + +# +# This is a list of all subdirectories that build optional components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +OPTIONAL_DIRS= \ + \ + daytona \ + win32s \ + mfcui \ + test diff --git a/private/ole2ui32/dllfuncs.cpp b/private/ole2ui32/dllfuncs.cpp new file mode 100644 index 000000000..830d2079c --- /dev/null +++ b/private/ole2ui32/dllfuncs.cpp @@ -0,0 +1,65 @@ +/* + * DLLFUNCS.CPP + * + * Contains entry and exit points for the DLL implementation + * of the OLE 2.0 User Interface Support Library. + * + * This file is not needed if we are linking the static library + * version of this library. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "common.h" +#include "uiclass.h" + +OLEDBGDATA_MAIN(TEXT("OLEDLG")) + +/* + * DllMain + * + * Purpose: + * DLL-specific entry point called from LibEntry. + */ + +STDAPI_(BOOL) OleUIInitialize(HINSTANCE, HINSTANCE); +STDAPI_(BOOL) OleUIUnInitialize(); + +#pragma code_seg(".text$initseg") + +BOOL WINAPI DllMain(HINSTANCE hInst, DWORD Reason, LPVOID lpv) +{ + if (Reason == DLL_PROCESS_DETACH) + { + OleDbgOut2(TEXT("DllMain: OLEDLG.DLL unloaded\r\n")); + + OleUIUnInitialize(); + } + else if (Reason == DLL_PROCESS_ATTACH) + { + OSVERSIONINFO sVersion; + + sVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + if (GetVersionEx(&sVersion)) + { + if (VER_PLATFORM_WIN32s == sVersion.dwPlatformId) + { + if ((1 == sVersion.dwMajorVersion) && (30 > sVersion.dwMinorVersion)) + { + return(FALSE); // fail to load on older versions of Win32s + } + } + } + + OleDbgOut2(TEXT("DllMain: OLEDLG.DLL loaded\r\n")); + + DisableThreadLibraryCalls(hInst); + + OleUIInitialize(hInst, (HINSTANCE)0); + } + return TRUE; +} + +#pragma code_seg() diff --git a/private/ole2ui32/drawicon.cpp b/private/ole2ui32/drawicon.cpp new file mode 100644 index 000000000..1fd01514b --- /dev/null +++ b/private/ole2ui32/drawicon.cpp @@ -0,0 +1,674 @@ +/* + * DRAWICON.CPP + * + * Functions to handle creation of metafiles with icons and labels + * as well as functions to draw such metafiles with or without the label. + * + * The metafile is created with a comment that marks the records containing + * the label code. Drawing the metafile enumerates the records, draws + * all records up to that point, then decides to either skip the label + * or draw it. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "utility.h" +#include "malloc.h" + +// Private implementation + +//Structure for label and source extraction from a metafile +typedef struct tagLABELEXTRACT +{ + LPTSTR lpsz; + UINT Index; // index in lpsz (so we can retrieve 2+ lines) + DWORD PrevIndex; // index of last line (so we can mimic word wrap) + + union + { + UINT cch; //Length of label for label extraction + UINT iIcon; //Index of icon in source extraction. + } u; + + //For internal use in enum procs + BOOL fFoundIconOnly; + BOOL fFoundSource; + BOOL fFoundIndex; +} LABELEXTRACT, FAR * LPLABELEXTRACT; + + +//Structure for extracting icons from a metafile (CreateIcon parameters) +typedef struct tagICONEXTRACT +{ + HICON hIcon; //Icon created in the enumeration proc. + + /* + * Since we want to handle multitasking well we have the caller + * of the enumeration proc instantiate these variables instead of + * using statics in the enum proc (which would be bad). + */ + BOOL fAND; + HGLOBAL hMemAND; //Enumeration proc allocates and copies +} ICONEXTRACT, FAR * LPICONEXTRACT; + + +//Structure to use to pass info to EnumMetafileDraw +typedef struct tagDRAWINFO +{ + RECT Rect; + BOOL fIconOnly; +} DRAWINFO, FAR * LPDRAWINFO; + + +int CALLBACK EnumMetafileIconDraw(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPARAM); +int CALLBACK EnumMetafileExtractLabel(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPLABELEXTRACT); +int CALLBACK EnumMetafileExtractIcon(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPICONEXTRACT); +int CALLBACK EnumMetafileExtractIconSource(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPLABELEXTRACT); + +/* + * Strings for metafile comments. KEEP THESE IN SYNC WITH THE + * STRINGS IN GETICON.CPP + */ + +static const char szIconOnly[] = "IconOnly"; // Where to stop to exclude label. + +/* + * OleUIMetafilePictIconFree + * + * Purpose: + * Deletes the metafile contained in a METAFILEPICT structure and + * frees the memory for the structure itself. + * + * Parameters: + * hMetaPict HGLOBAL metafilepict structure created in + * OleMetafilePictFromIconAndLabel + * + * Return Value: + * None + */ + +STDAPI_(void) OleUIMetafilePictIconFree(HGLOBAL hMetaPict) +{ + if (NULL != hMetaPict) + { + STGMEDIUM stgMedium; + stgMedium.tymed = TYMED_MFPICT; + stgMedium.hMetaFilePict = hMetaPict; + stgMedium.pUnkForRelease = NULL; + ReleaseStgMedium(&stgMedium); + } +} + +/* + * OleUIMetafilePictIconDraw + * + * Purpose: + * Draws the metafile from OleMetafilePictFromIconAndLabel, either with + * the label or without. + * + * Parameters: + * hDC HDC on which to draw. + * pRect LPRECT in which to draw the metafile. + * hMetaPict HGLOBAL to the METAFILEPICT from + * OleMetafilePictFromIconAndLabel + * fIconOnly BOOL specifying to draw the label or not. + * + * Return Value: + * BOOL TRUE if the function is successful, FALSE if the + * given metafilepict is invalid. + */ + +STDAPI_(BOOL) OleUIMetafilePictIconDraw(HDC hDC, LPCRECT pRect, + HGLOBAL hMetaPict, BOOL fIconOnly) +{ + if (NULL == hMetaPict) + return FALSE; + + LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(hMetaPict); + + if (NULL == pMF) + return FALSE; + + DRAWINFO di; + di.Rect = *pRect; + di.fIconOnly = fIconOnly; + + //Transform to back to pixels + int cx = XformWidthInHimetricToPixels(hDC, pMF->xExt); + int cy = XformHeightInHimetricToPixels(hDC, pMF->yExt); + + SaveDC(hDC); + + SetMapMode(hDC, pMF->mm); + SetViewportOrgEx(hDC, (pRect->right - cx) / 2, 0, NULL); + SetViewportExtEx(hDC, min ((pRect->right - cx) / 2 + cx, cx), cy, NULL); + + if (fIconOnly) + EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileIconDraw, (LPARAM)&di); + else + PlayMetaFile(hDC, pMF->hMF); + + RestoreDC(hDC, -1); + + GlobalUnlock(hMetaPict); + return TRUE; +} + +/* + * EnumMetafileIconDraw + * + * Purpose: + * EnumMetaFile callback function that draws either the icon only or + * the icon and label depending on given flags. + * + * Parameters: + * hDC HDC into which the metafile should be played. + * phTable HANDLETABLE FAR * providing handles selected into the DC. + * pMFR METARECORD FAR * giving the enumerated record. + * lParam LPARAM flags passed in EnumMetaFile. + * + * Return Value: + * int 0 to stop enumeration, 1 to continue. + */ +int CALLBACK EnumMetafileIconDraw(HDC hDC, HANDLETABLE FAR *phTable, + METARECORD FAR *pMFR, int cObj, LPARAM lParam) +{ + LPDRAWINFO lpdi = (LPDRAWINFO)lParam; + + /* + * We play everything blindly except for DIBBITBLT (or DIBSTRETCHBLT) + * and ESCAPE with MFCOMMENT. For the BitBlts we change the x,y to + * draw at (0,0) instead of wherever it was written to draw. The + * comment tells us there to stop if we don't want to draw the label. + */ + + //If we're playing icon only, stop enumeration at the comment. + if (lpdi->fIconOnly) + { + if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0]) + { + if (0 == lstrcmpiA(szIconOnly, (LPSTR)&pMFR->rdParm[2])) + return 0; + } + + /* + * Check for the records in which we want to munge the coordinates. + * destX is offset 6 for BitBlt, offset 9 for StretchBlt, either of + * which may appear in the metafile. + */ + if (META_DIBBITBLT == pMFR->rdFunction) + pMFR->rdParm[6]=0; + + if (META_DIBSTRETCHBLT == pMFR->rdFunction) + pMFR->rdParm[9] = 0; + } + + PlayMetaFileRecord(hDC, phTable, pMFR, cObj); + return 1; +} + + +/* + * OleUIMetafilePictExtractLabel + * + * Purpose: + * Retrieves the label string from metafile representation of an icon. + * + * Parameters: + * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile. + * lpszLabel LPSTR in which to store the label. + * cchLabel UINT length of lpszLabel. + * lpWrapIndex DWORD index of first character in last line. Can be NULL + * if calling function doesn't care about word wrap. + * + * Return Value: + * UINT Number of characters copied. + */ +STDAPI_(UINT) OleUIMetafilePictExtractLabel(HGLOBAL hMetaPict, LPTSTR lpszLabel, + UINT cchLabel, LPDWORD lpWrapIndex) +{ + if (NULL == hMetaPict || NULL == lpszLabel || 0 == cchLabel) + return FALSE; + + /* + * We extract the label by getting a screen DC and walking the metafile + * records until we see the ExtTextOut record we put there. That + * record will have the string embedded in it which we then copy out. + */ + LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(hMetaPict); + + if (NULL == pMF) + return FALSE; + + LABELEXTRACT le; + le.lpsz=lpszLabel; + le.u.cch=cchLabel; + le.Index=0; + le.fFoundIconOnly=FALSE; + le.fFoundSource=FALSE; //Unused for this function. + le.fFoundIndex=FALSE; //Unused for this function. + le.PrevIndex = 0; + + //Use a screen DC so we have something valid to pass in. + HDC hDC = GetDC(NULL); + EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractLabel, (LONG)(LPLABELEXTRACT)&le); + ReleaseDC(NULL, hDC); + + GlobalUnlock(hMetaPict); + + //Tell where we wrapped (if calling function cares) + if (NULL != lpWrapIndex) + *lpWrapIndex = le.PrevIndex; + + //Return amount of text copied + return le.u.cch; +} + +/* + * EnumMetafileExtractLabel + * + * Purpose: + * EnumMetaFile callback function that walks a metafile looking for + * ExtTextOut, then concatenates the text from each one into a buffer + * in lParam. + * + * Parameters: + * hDC HDC into which the metafile should be played. + * phTable HANDLETABLE FAR * providing handles selected into the DC. + * pMFR METARECORD FAR * giving the enumerated record. + * pLE LPLABELEXTRACT providing the destination buffer and length. + * + * Return Value: + * int 0 to stop enumeration, 1 to continue. + */ + +int CALLBACK EnumMetafileExtractLabel(HDC hDC, HANDLETABLE FAR *phTable, + METARECORD FAR *pMFR, int cObj, LPLABELEXTRACT pLE) +{ + /* + * We don't allow anything to happen until we see "IconOnly" + * in an MFCOMMENT that is used to enable everything else. + */ + if (!pLE->fFoundIconOnly) + { + if (META_ESCAPE == pMFR->rdFunction && MFCOMMENT == pMFR->rdParm[0]) + { + if (0 == lstrcmpiA(szIconOnly, (LPSTR)&pMFR->rdParm[2])) + pLE->fFoundIconOnly=TRUE; + } + return 1; + } + + //Enumerate all records looking for META_EXTTEXTOUT - there can be more + //than one. + if (META_EXTTEXTOUT == pMFR->rdFunction) + { + /* + * If ExtTextOut has NULL fuOptions, then the rectangle is omitted + * from the record, and the string starts at rdParm[4]. If + * fuOptions is non-NULL, then the string starts at rdParm[8] + * (since the rectange takes up four WORDs in the array). In + * both cases, the string continues for (rdParm[2]+1) >> 1 + * words. We just cast a pointer to rdParm[8] to an LPSTR and + * lstrcpyn into the buffer we were given. + * + * Note that we use element 8 in rdParm instead of 4 because we + * passed ETO_CLIPPED in for the options on ExtTextOut--docs say + * [4] which is rect doesn't exist if we passed zero there. + * + */ + + UINT cchMax = min(pLE->u.cch - pLE->Index, (UINT)pMFR->rdParm[2]); + LPTSTR lpszTemp = pLE->lpsz + pLE->Index; +#ifdef _UNICODE + MultiByteToWideChar(CP_ACP, 0, (LPSTR)&pMFR->rdParm[8], cchMax, + lpszTemp, cchMax+1); +#else + lstrcpyn(lpszTemp, (LPSTR)&pMFR->rdParm[8], cchMax+1); +#endif + lpszTemp[cchMax+1] = 0; + + pLE->PrevIndex = pLE->Index; + pLE->Index += cchMax; + } + return 1; +} + +/* + * OleUIMetafilePictExtractIcon + * + * Purpose: + * Retrieves the icon from metafile into which DrawIcon was done before. + * + * Parameters: + * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile. + * + * Return Value: + * HICON Icon recreated from the data in the metafile. + */ +STDAPI_(HICON) OleUIMetafilePictExtractIcon(HGLOBAL hMetaPict) +{ + if (NULL == hMetaPict) + return NULL; + + /* + * We extract the label by getting a screen DC and walking the metafile + * records until we see the ExtTextOut record we put there. That + * record will have the string embedded in it which we then copy out. + */ + LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(hMetaPict); + + if (NULL == pMF) + return FALSE; + + ICONEXTRACT ie; + ie.fAND = TRUE; + + //Use a screen DC so we have something valid to pass in. + HDC hDC=GetDC(NULL); + EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIcon, (LONG)&ie); + ReleaseDC(NULL, hDC); + + GlobalUnlock(hMetaPict); + + return ie.hIcon; +} + +/* + * EnumMetafileExtractIcon + * + * Purpose: + * EnumMetaFile callback function that walks a metafile looking for + * StretchBlt (3.1) and BitBlt (3.0) records. We expect to see two + * of them, the first being the AND mask and the second being the XOR + * data. We + * ExtTextOut, then copies the text into a buffer in lParam. + * + * Parameters: + * hDC HDC into which the metafile should be played. + * phTable HANDLETABLE FAR * providing handles selected into the DC. + * pMFR METARECORD FAR * giving the enumerated record. + * pIE LPICONEXTRACT providing the destination buffer and length. + * + * Return Value: + * int 0 to stop enumeration, 1 to continue. + */ + +int CALLBACK EnumMetafileExtractIcon(HDC hDC, HANDLETABLE FAR *phTable, + METARECORD FAR *pMFR, int cObj, LPICONEXTRACT pIE) +{ + //Continue enumeration if we don't see the records we want. + if (META_DIBBITBLT != pMFR->rdFunction && META_DIBSTRETCHBLT != pMFR->rdFunction) + return 1; + + UNALIGNED BITMAPINFO* lpBI; + UINT uWidth, uHeight; + /* + * Windows 3.0 DrawIcon uses META_DIBBITBLT in whereas 3.1 uses + * META_DIBSTRETCHBLT so we have to handle each case separately. + */ + if (META_DIBBITBLT==pMFR->rdFunction) //Win3.0 + { + //Get dimensions and the BITMAPINFO struct. + uHeight = pMFR->rdParm[1]; + uWidth = pMFR->rdParm[2]; + lpBI = (LPBITMAPINFO)&(pMFR->rdParm[8]); + } + + if (META_DIBSTRETCHBLT == pMFR->rdFunction) //Win3.1 + { + //Get dimensions and the BITMAPINFO struct. + uHeight = pMFR->rdParm[2]; + uWidth = pMFR->rdParm[3]; + lpBI = (LPBITMAPINFO)&(pMFR->rdParm[10]); + } + + UNALIGNED BITMAPINFOHEADER* lpBH=(LPBITMAPINFOHEADER)&(lpBI->bmiHeader); + + //Pointer to the bits which follows the BITMAPINFO structure. + LPBYTE lpbSrc=(LPBYTE)lpBI+sizeof(BITMAPINFOHEADER); + + //Add the length of the color table (if one exists) + if (0 != lpBH->biClrUsed) + { + // If we have an explicit count of colors used, we + // can find the offset to the data directly + lpbSrc += (lpBH->biClrUsed*sizeof(RGBQUAD)); + } + else if (lpBH->biCompression == BI_BITFIELDS) + { + // 16 or 32 bpp, indicated by BI_BITFIELDS in the compression + // field, have 3 DWORD masks for adjusting subsequent + // direct-color values, and no palette + lpbSrc += 3 * sizeof(DWORD); + } + else + { + // In other cases, there is an array of RGBQUAD entries + // equal to 2^(biBitCount) where biBitCount is the number + // of bits per pixel. The exception is 24 bpp bitmaps, + // which have no color table and just use direct RGB values. + lpbSrc += (lpBH->biBitCount == 24) ? 0 : + (1 << (lpBH->biBitCount)) * sizeof(RGBQUAD); + } + + // copy into aligned stack space (since SetDIBits needs aligned data) + size_t nSize = lpbSrc - (LPBYTE)lpBI; + LPBITMAPINFO lpTemp = (LPBITMAPINFO)_alloca(nSize); + memcpy(lpTemp, lpBI, nSize); + + /* + * All the bits we have in lpbSrc are device-independent, so we + * need to change them over to be device-dependent using SetDIBits. + * Once we have a bitmap with the device-dependent bits, we can + * GetBitmapBits to have buffers with the real data. + * + * For each pass we have to allocate memory for the bits. We save + * the memory for the mask between passes. + */ + + HBITMAP hBmp; + + //Use CreateBitmap for ANY monochrome bitmaps + if (pIE->fAND || 1==lpBH->biBitCount) + hBmp=CreateBitmap((UINT)lpBH->biWidth, (UINT)lpBH->biHeight, 1, 1, NULL); + else + hBmp=CreateCompatibleBitmap(hDC, (UINT)lpBH->biWidth, (UINT)lpBH->biHeight); + + if (!hBmp || !SetDIBits(hDC, hBmp, 0, (UINT)lpBH->biHeight, (LPVOID)lpbSrc, lpTemp, DIB_RGB_COLORS)) + { + if (!pIE->fAND) + GlobalFree(pIE->hMemAND); + + DeleteObject(hBmp); + return 0; + } + + //Allocate memory and get the DDBits into it. + BITMAP bm; + GetObject(hBmp, sizeof(bm), &bm); + + DWORD cb = bm.bmHeight*bm.bmWidthBytes * bm.bmPlanes; + HGLOBAL hMem = GlobalAlloc(GHND, cb); + + if (NULL==hMem) + { + if (NULL != pIE->hMemAND) + GlobalFree(pIE->hMemAND); + + DeleteObject(hBmp); + return 0; + } + + LPBYTE lpbDst = (LPBYTE)GlobalLock(hMem); + GetBitmapBits(hBmp, cb, (LPVOID)lpbDst); + DeleteObject(hBmp); + GlobalUnlock(hMem); + + /* + * If this is the first pass (pIE->fAND==TRUE) then save the memory + * of the AND bits for the next pass. + */ + if (pIE->fAND) + { + pIE->fAND = FALSE; + pIE->hMemAND = hMem; + + //Continue enumeration looking for the next blt record. + return 1; + } + else + { + //Get the AND pointer again. + lpbSrc=(LPBYTE)GlobalLock(pIE->hMemAND); + + /* + * Create the icon now that we have all the data. lpbDst already + * points to the XOR bits. + */ + + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + + pIE->hIcon = CreateIcon(_g_hOleStdInst, uWidth, uHeight, + (BYTE)bm.bmPlanes, (BYTE)bm.bmBitsPixel, lpbSrc, lpbDst); + + GlobalUnlock(pIE->hMemAND); + GlobalFree(pIE->hMemAND); + GlobalFree(hMem); + + return 0; + } +} + + +/* + * OleUIMetafilePictExtractIconSource + * + * Purpose: + * Retrieves the filename and index of the icon source from a metafile + * created with OleMetafilePictFromIconAndLabel. + * + * Parameters: + * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile. + * lpszSource LPTSTR in which to store the source filename. This + * buffer should be MAX_PATH characters. + * piIcon UINT FAR * in which to store the icon's index + * within lpszSource + * + * Return Value: + * BOOL TRUE if the records were found, FALSE otherwise. + */ +STDAPI_(BOOL) OleUIMetafilePictExtractIconSource(HGLOBAL hMetaPict, + LPTSTR lpszSource, UINT FAR *piIcon) +{ + if (NULL == hMetaPict || NULL == lpszSource || NULL == piIcon) + return FALSE; + + /* + * We will walk the metafile looking for the two comment records + * following the IconOnly comment. The flags fFoundIconOnly and + * fFoundSource indicate if we have found IconOnly and if we have + * found the source comment already. + */ + + LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(hMetaPict); + if (NULL == pMF) + return FALSE; + + LABELEXTRACT le; + le.lpsz = lpszSource; + le.fFoundIconOnly = FALSE; + le.fFoundSource = FALSE; + le.fFoundIndex = FALSE; + + //Use a screen DC so we have something valid to pass in. + HDC hDC = GetDC(NULL); + EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIconSource, + (LONG)(LPLABELEXTRACT)&le); + ReleaseDC(NULL, hDC); + GlobalUnlock(hMetaPict); + + //Copy the icon index to the caller's variable. + *piIcon=le.u.iIcon; + + //Check that we found everything. + return (le.fFoundIconOnly && le.fFoundSource && le.fFoundIndex); +} + + +/* + * EnumMetafileExtractIconSource + * + * Purpose: + * EnumMetaFile callback function that walks a metafile skipping the first + * comment record, extracting the source filename from the second, and + * the index of the icon in the third. + * + * Parameters: + * hDC HDC into which the metafile should be played. + * phTable HANDLETABLE FAR * providing handles selected into the DC. + * pMFR METARECORD FAR * giving the enumerated record. + * pLE LPLABELEXTRACT providing the destination buffer and + * area to store the icon index. + * + * Return Value: + * int 0 to stop enumeration, 1 to continue. + */ + +int CALLBACK EnumMetafileExtractIconSource(HDC hDC, HANDLETABLE FAR *phTable, + METARECORD FAR *pMFR, int cObj, LPLABELEXTRACT pLE) +{ + /* + * We don't allow anything to happen until we see "IconOnly" + * in an MFCOMMENT that is used to enable everything else. + */ + if (!pLE->fFoundIconOnly) + { + if (META_ESCAPE == pMFR->rdFunction && MFCOMMENT == pMFR->rdParm[0]) + { + if (0 == lstrcmpiA(szIconOnly, (LPSTR)&pMFR->rdParm[2])) + pLE->fFoundIconOnly=TRUE; + } + return 1; + } + + //Now see if we find the source string. + if (!pLE->fFoundSource) + { + if (META_ESCAPE == pMFR->rdFunction && MFCOMMENT == pMFR->rdParm[0]) + { +#ifdef _UNICODE + MultiByteToWideChar(CP_ACP, 0, (LPSTR)&pMFR->rdParm[2], -1, + pLE->lpsz, MAX_PATH); +#else + lstrcpyn(pLE->lpsz, (LPSTR)&pMFR->rdParm[2], MAX_PATH); +#endif + pLE->lpsz[MAX_PATH-1] = '\0'; + pLE->fFoundSource=TRUE; + } + return 1; + } + + //Next comment will be the icon index. + if (META_ESCAPE == pMFR->rdFunction && MFCOMMENT == pMFR->rdParm[0]) + { + /* + * This string contains the icon index in string form, + * so we need to convert back to a UINT. After we see this + * we can stop the enumeration. The comment will have + * a null terminator because we made sure to save it. + */ + LPSTR psz = (LPSTR)&pMFR->rdParm[2]; + pLE->u.iIcon = 0; + + //Do Ye Olde atoi + while (*psz) + pLE->u.iIcon = (10*pLE->u.iIcon)+((*psz++)-'0'); + + pLE->fFoundIndex=TRUE; + return 0; + } + return 1; +} diff --git a/private/ole2ui32/geticon.cpp b/private/ole2ui32/geticon.cpp new file mode 100644 index 000000000..1bb6fca92 --- /dev/null +++ b/private/ole2ui32/geticon.cpp @@ -0,0 +1,166 @@ +/* + * GETICON.CPP + * + * Functions to create DVASPECT_ICON metafile from filename or classname. + * + * OleMetafilePictFromIconAndLabel + * + * (c) Copyright Microsoft Corp. 1992-1993 All Rights Reserved + */ + + +/******* + * + * ICON (DVASPECT_ICON) METAFILE FORMAT: + * + * The metafile generated with OleMetafilePictFromIconAndLabel contains + * the following records which are used by the functions in DRAWICON.CPP + * to draw the icon with and without the label and to extract the icon, + * label, and icon source/index. + * + * SetWindowOrg + * SetWindowExt + * DrawIcon: + * Inserts records of DIBBITBLT or DIBSTRETCHBLT, once for the + * AND mask, one for the image bits. + * Escape with the comment "IconOnly" + * This indicates where to stop record enumeration to draw only + * the icon. + * SetTextColor + * SetTextAlign + * SetBkColor + * CreateFont + * SelectObject on the font. + * ExtTextOut + * One or more ExtTextOuts occur if the label is wrapped. The + * text in these records is used to extract the label. + * SelectObject on the old font. + * DeleteObject on the font. + * Escape with a comment that contains the path to the icon source. + * Escape with a comment that is the ASCII of the icon index. + * + *******/ + +#include "precomp.h" +#include "common.h" +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <commdlg.h> +#include <memory.h> +#include <cderr.h> +#include "utility.h" + +OLEDBGDATA + +static const TCHAR szSeparators[] = TEXT(" \t\\/!:"); + +#define IS_SEPARATOR(c) ( (c) == ' ' || (c) == '\\' \ + || (c) == '/' || (c) == '\t' \ + || (c) == '!' || (c) == ':') +#define IS_FILENAME_DELIM(c) ( (c) == '\\' || (c) == '/' || (c) == ':' ) + +#define IS_SPACE(c) ( (c) == ' ' || (c) == '\t' || (c) == '\n' ) + +/* + * GetAssociatedExecutable + * + * Purpose: Finds the executable associated with the provided extension + * + * Parameters: + * lpszExtension LPSTR points to the extension we're trying to find + * an exe for. Does **NO** validation. + * + * lpszExecutable LPSTR points to where the exe name will be returned. + * No validation here either - pass in 128 char buffer. + * + * Return: + * BOOL TRUE if we found an exe, FALSE if we didn't. + * + */ +BOOL FAR PASCAL GetAssociatedExecutable(LPTSTR lpszExtension, LPTSTR lpszExecutable) +{ + HKEY hKey; + LRESULT lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); + if (ERROR_SUCCESS != lRet) + return FALSE; + + LONG dw = MAX_PATH_SIZE; + TCHAR szValue[OLEUI_CCHKEYMAX]; + lRet = RegQueryValue(hKey, lpszExtension, szValue, &dw); //ProgId + if (ERROR_SUCCESS != lRet) + { + RegCloseKey(hKey); + return FALSE; + } + + // szValue now has ProgID + TCHAR szKey[OLEUI_CCHKEYMAX]; + lstrcpy(szKey, szValue); + lstrcat(szKey, TEXT("\\Shell\\Open\\Command")); + + dw = MAX_PATH_SIZE; + lRet = RegQueryValue(hKey, szKey, szValue, &dw); + if (ERROR_SUCCESS != lRet) + { + RegCloseKey(hKey); + return FALSE; + } + + // szValue now has an executable name in it. Let's null-terminate + // at the first post-executable space (so we don't have cmd line + // args. + LPTSTR lpszTemp = szValue; + while ('\0' != *lpszTemp && IS_SPACE(*lpszTemp)) + lpszTemp = CharNext(lpszTemp); // Strip off leading spaces + + LPTSTR lpszExe = lpszTemp; + while ('\0' != *lpszTemp && !IS_SPACE(*lpszTemp)) + lpszTemp = CharNext(lpszTemp); // Step through exe name + *lpszTemp = '\0'; // null terminate at first space (or at end). + + lstrcpy(lpszExecutable, lpszExe); + return TRUE; +} + + +/* + * PointerToNthField + * + * Purpose: + * Returns a pointer to the beginning of the nth field. + * Assumes null-terminated string. + * + * Parameters: + * lpszString string to parse + * nField field to return starting index of. + * chDelimiter char that delimits fields + * + * Return Value: + * LPSTR pointer to beginning of nField field. + * NOTE: If the null terminator is found + * Before we find the Nth field, then + * we return a pointer to the null terminator - + * calling app should be sure to check for + * this case. + * + */ +LPTSTR FAR PASCAL PointerToNthField(LPTSTR lpszString, int nField, TCHAR chDelimiter) +{ + if (1 == nField) + return lpszString; + + int cFieldFound = 1; + LPTSTR lpField = lpszString; + while (*lpField != '\0') + { + if (*lpField++ == chDelimiter) + { + cFieldFound++; + if (nField == cFieldFound) + return lpField; + } + } + return lpField; +} + diff --git a/private/ole2ui32/icon.cpp b/private/ole2ui32/icon.cpp new file mode 100644 index 000000000..d112bdbf2 --- /dev/null +++ b/private/ole2ui32/icon.cpp @@ -0,0 +1,1316 @@ +/* + * ICON.CPP + * + * Implements the OleUIChangeIcon function which invokes the complete + * Change Icon dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "common.h" +#include "utility.h" +#include "iconbox.h" + +OLEDBGDATA + +ULONG +GetLongPathName(LPCTSTR pcsPath, + LPTSTR pcsLongPath, + ULONG cchLongPath); + +#define CXICONPAD (12) +#define CYICONPAD (4) + +// Internally used structure +typedef struct tagCHANGEICON +{ + LPOLEUICHANGEICON lpOCI; //Original structure passed. + UINT nIDD; // IDD of dialog (used for help info) + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + DWORD dwFlags; + HICON hCurIcon; + TCHAR szLabel[OLEUI_CCHLABELMAX+1]; + TCHAR szFile[MAX_PATH]; + UINT iIcon; + HICON hDefIcon; + TCHAR szDefIconFile[MAX_PATH]; + UINT iDefIcon; + UINT nBrowseHelpID; // Help ID callback for Browse dlg + +} CHANGEICON, *PCHANGEICON, FAR *LPCHANGEICON; + +// Internal function prototypes +// ICON.CPP + +BOOL CALLBACK ChangeIconDialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL FChangeIconInit(HWND, WPARAM, LPARAM); +UINT UFillIconList(HWND, UINT, LPTSTR, BOOL); +BOOL FDrawListIcon(LPDRAWITEMSTRUCT); +void UpdateResultIcon(LPCHANGEICON, HWND, UINT); + +/* + * OleUIChangeIcon + * + * Purpose: + * Invokes the standard OLE Change Icon dialog box allowing the user + * to select an icon from an icon file, executable, or DLL. + * + * Parameters: + * lpCI LPOLEUIChangeIcon pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT OLEUI_SUCCESS or OLEUI_OK if all is well, otherwise + * an error value. + */ +STDAPI_(UINT) OleUIChangeIcon(LPOLEUICHANGEICON lpCI) +{ + HGLOBAL hMemDlg = NULL; + UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpCI, sizeof(OLEUICHANGEICON), + &hMemDlg); + + if (OLEUI_SUCCESS != uRet) + return uRet; + + // Check for a valid hMetaPict. + if (NULL == lpCI->hMetaPict && NULL == lpCI->szIconExe && CLSID_NULL == lpCI->clsid) + { + return(OLEUI_CIERR_MUSTHAVECURRENTMETAFILE); + } + if (lpCI->hMetaPict != NULL && !IsValidMetaPict(lpCI->hMetaPict)) + { + return(OLEUI_CIERR_MUSTHAVECURRENTMETAFILE); + } + + // Test to be sure that the class ID matches a registered class ID + // so we can return OLEUI_CIERR_MUSTHAVECLSID if necessary. + HGLOBAL hTemp = OleGetIconOfClass(lpCI->clsid, NULL, TRUE); + if (hTemp == NULL) + { + return(OLEUI_CIERR_MUSTHAVECLSID); + } + OleUIMetafilePictIconFree(hTemp); + + if (lpCI->dwFlags & CIF_USEICONEXE && + (lpCI->cchIconExe < 1 || lpCI->cchIconExe > MAX_PATH)) + { + uRet = OLEUI_CIERR_SZICONEXEINVALID; + } + + if (OLEUI_ERR_STANDARDMIN <= uRet) + { + return uRet; + } + + // Now that we've validated everything, we can invoke the dialog. + uRet = UStandardInvocation(ChangeIconDialogProc, (LPOLEUISTANDARD)lpCI, + hMemDlg, MAKEINTRESOURCE(IDD_CHANGEICON)); + return uRet; +} + +/* + * ChangeIconDialogProc + * + * Purpose: + * Implements the OLE Change Icon dialog as invoked through the + * OleUIChangeIcon function. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ +BOOL CALLBACK ChangeIconDialogProc(HWND hDlg, UINT iMsg, + WPARAM wParam, LPARAM lParam) +{ + + // Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + UINT uRet = 0; + LPCHANGEICON lpCI = (LPCHANGEICON)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet); + + // If the hook processed the message, we're done. + if (0 != uRet) + return uRet; + + // Process the temination message + if (iMsg == uMsgEndDialog) + { + EndDialog(hDlg, wParam); + return TRUE; + } + + TCHAR szTemp[MAX_PATH]; + HICON hIcon; + HGLOBAL hMetaPict; + + switch (iMsg) + { + case WM_DESTROY: + if (lpCI) + { + SendDlgItemMessage(hDlg, IDC_CI_ICONLIST, LB_RESETCONTENT, 0, 0L); + StandardCleanup(lpCI, hDlg); + } + break; + case WM_INITDIALOG: + FChangeIconInit(hDlg, wParam, lParam); + return TRUE; + + case WM_MEASUREITEM: + { + LPMEASUREITEMSTRUCT lpMI = (LPMEASUREITEMSTRUCT)lParam; + + // All icons are system metric+padding in width and height + lpMI->itemWidth = GetSystemMetrics(SM_CXICON)+CXICONPAD; + lpMI->itemHeight= GetSystemMetrics(SM_CYICON)+CYICONPAD; + } + break; + + case WM_DRAWITEM: + return FDrawListIcon((LPDRAWITEMSTRUCT)lParam); + + case WM_DELETEITEM: + DestroyIcon((HICON)(((LPDELETEITEMSTRUCT)lParam)->itemData)); + break; + + case WM_COMMAND: + switch (wID) + { + case IDC_CI_CURRENT: + case IDC_CI_DEFAULT: + case IDC_CI_FROMFILE: + UpdateResultIcon(lpCI, hDlg, (UINT)-1); + break; + + case IDC_CI_LABELEDIT: + if (lpCI != NULL && EN_KILLFOCUS == wCode) + UpdateResultIcon(lpCI, hDlg, (UINT)-1); + break; + + case IDC_CI_FROMFILEEDIT: + GetDlgItemText(hDlg, IDC_CI_FROMFILEEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR)); + if (lpCI != NULL) + { + if (wCode == EN_KILLFOCUS) + { + if (lstrcmpi(szTemp, lpCI->szFile)) + { + lstrcpy(lpCI->szFile, szTemp); + UFillIconList(hDlg, IDC_CI_ICONLIST, lpCI->szFile, FALSE); + UpdateResultIcon(lpCI, hDlg, IDC_CI_FROMFILE); + } + } + else if (wCode == EN_SETFOCUS) + { + UpdateResultIcon(lpCI, hDlg, IDC_CI_FROMFILE); + } + } + break; + + case IDC_CI_ICONLIST: + switch (wCode) + { + case LBN_SETFOCUS: + // If we got the focus, see about updating. + GetDlgItemText(hDlg, IDC_CI_FROMFILEEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR)); + + // Check if file changed and update the list if so + if (lpCI && 0 != lstrcmpi(szTemp, lpCI->szFile)) + { + lstrcpy(lpCI->szFile, szTemp); + UFillIconList(hDlg, IDC_CI_ICONLIST, lpCI->szFile, FALSE); + } + UpdateResultIcon(lpCI, hDlg, IDC_CI_FROMFILE); + break; + + case LBN_SELCHANGE: + UpdateResultIcon(lpCI, hDlg, IDC_CI_FROMFILE); + break; + + case LBN_DBLCLK: + SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg); + break; + } + break; + + case IDC_CI_BROWSE: + { + lstrcpyn(szTemp, lpCI->szFile, sizeof(szTemp)/sizeof(TCHAR)); + uRet = UStandardHook(lpCI, hDlg, uMsgBrowse, MAX_PATH_SIZE, + (LPARAM)lpCI->szFile); + + DWORD dwOfnFlags = OFN_FILEMUSTEXIST; + if (lpCI->lpOCI->dwFlags & CIF_SHOWHELP) + dwOfnFlags |= OFN_SHOWHELP; + + if (0 == uRet) + { + uRet = (BOOL)Browse(hDlg, lpCI->szFile, NULL, MAX_PATH_SIZE, + IDS_ICONFILTERS, dwOfnFlags, ID_BROWSE_CHANGEICON, NULL); + } + + if (0 != uRet && 0 != lstrcmpi(szTemp, lpCI->szFile)) + { + SetDlgItemText(hDlg, IDC_CI_FROMFILEEDIT, lpCI->szFile); + UFillIconList(hDlg, IDC_CI_ICONLIST, lpCI->szFile, TRUE); + UpdateResultIcon(lpCI, hDlg, IDC_CI_FROMFILE); + } + } + break; + + case IDOK: + { + HWND hwndCtl = GetDlgItem(hDlg, IDOK); + if (hwndCtl == GetFocus()) + { + GetDlgItemText(hDlg, IDC_CI_FROMFILEEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR)); + + // Check if the file name is valid + // if SelectFromFile radio button selected + if (lpCI->dwFlags & CIF_SELECTFROMFILE) + { + // Check if the file changed at all. + if (0 != lstrcmpi(szTemp, lpCI->szFile)) + { + lstrcpy(lpCI->szFile, szTemp); + // file changed. May need to expand the name + // calling DoesFileExist will do the trick + DoesFileExist(lpCI->szFile, MAX_PATH); + UFillIconList(hDlg, IDC_CI_ICONLIST, lpCI->szFile, TRUE); + SetDlgItemText(hDlg, IDC_CI_FROMFILEEDIT, lpCI->szFile); + UpdateResultIcon(lpCI, hDlg, IDC_CI_FROMFILE); + return TRUE; // eat this message to prevent focus change. + } + if (!DoesFileExist(lpCI->szFile, MAX_PATH)) + { + OpenFileError(hDlg, ERROR_FILE_NOT_FOUND, lpCI->szFile); + HWND hWnd = GetDlgItem(hDlg, IDC_CI_FROMFILEEDIT); + SetFocus(hWnd); + SendMessage(hWnd, EM_SETSEL, 0, -1); + return TRUE; // eat this message + } + } + + // Get current metafile image + UpdateResultIcon(lpCI, hDlg, (UINT)-1); + hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, IDC_CI_ICONDISPLAY, + IBXM_IMAGEGET, 0, 0); + + // Clean up the current icon that we extracted. + hIcon = (HICON)SendDlgItemMessage(hDlg, IDC_CI_CURRENTICON, STM_GETICON, 0, 0L); + DestroyIcon(hIcon); + + // Clean up the default icon + DestroyIcon(lpCI->hDefIcon); + + // Remove the prop set on our parent + RemoveProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG); + + OleUIMetafilePictIconFree(lpCI->lpOCI->hMetaPict); + lpCI->lpOCI->hMetaPict = hMetaPict; + lpCI->lpOCI->dwFlags = lpCI->dwFlags; + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + } + else + { + SetFocus(hwndCtl); + SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg); + } + break; + } + + case IDCANCEL: + // Free current icon display image + SendDlgItemMessage(hDlg, IDC_CI_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0); + + // Clean up the current icon that we extracted. + hIcon = (HICON)SendDlgItemMessage(hDlg, IDC_CI_CURRENTICON, STM_GETICON, 0, 0L); + DestroyIcon(hIcon); + + // Clean up the default icon + DestroyIcon(lpCI->hDefIcon); + + // Remove the prop set on our parent + RemoveProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG); + + // We leave hMetaPict intact on Cancel; caller's responsibility + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + + case IDC_OLEUIHELP: + PostMessage(lpCI->lpOCI->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_CHANGEICON, 0)); + break; + } + break; + + default: + if (lpCI && iMsg == lpCI->nBrowseHelpID) + { + PostMessage(lpCI->lpOCI->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_CHANGEICONBROWSE, 0)); + } + if (iMsg == uMsgBrowseOFN && + lpCI && lpCI->lpOCI && lpCI->lpOCI->hWndOwner) + { + SendMessage(lpCI->lpOCI->hWndOwner, uMsgBrowseOFN, wParam, lParam); + } + break; + } + + return FALSE; +} + +/* + * FChangeIconInit + * + * Purpose: + * WM_INITIDIALOG handler for the Change Icon dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ +BOOL FChangeIconInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + // Copy the structure at lParam into our instance memory. + LPCHANGEICON lpCI = (LPCHANGEICON)LpvStandardInit(hDlg, sizeof(CHANGEICON)); + + // LpvStandardInit send a termination to us already. + if (NULL == lpCI) + return FALSE; + + // Save the original pointer and copy necessary information. + LPOLEUICHANGEICON lpOCI = (LPOLEUICHANGEICON)lParam; + lpCI->lpOCI = lpOCI; + lpCI->nIDD = IDD_CHANGEICON; + lpCI->dwFlags = lpOCI->dwFlags; + + // Go extract the icon source from the metafile. + TCHAR szTemp[MAX_PATH]; + OleUIMetafilePictExtractIconSource(lpOCI->hMetaPict, szTemp, &lpCI->iIcon); + GetLongPathName(szTemp, lpCI->szFile, MAX_PATH); + + // Go extract the icon and the label from the metafile + OleUIMetafilePictExtractLabel(lpOCI->hMetaPict, lpCI->szLabel, OLEUI_CCHLABELMAX_SIZE, NULL); + lpCI->hCurIcon = OleUIMetafilePictExtractIcon(lpOCI->hMetaPict); + + // Show or hide the help button + if (!(lpCI->dwFlags & CIF_SHOWHELP)) + StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE); + + // Set text limits and initial control contents + SendDlgItemMessage(hDlg, IDC_CI_LABELEDIT, EM_LIMITTEXT, OLEUI_CCHLABELMAX, 0L); + SendDlgItemMessage(hDlg, IDC_CI_FROMFILEEDIT, EM_LIMITTEXT, MAX_PATH, 0L); + SetDlgItemText(hDlg, IDC_CI_FROMFILEEDIT, lpCI->szFile); + + // Copy the label text into the edit and static controls. + SetDlgItemText(hDlg, IDC_CI_LABELEDIT, lpCI->szLabel); + + lpCI->hDefIcon = NULL; + if (lpCI->dwFlags & CIF_USEICONEXE) + { + lpCI->hDefIcon = StandardExtractIcon(_g_hOleStdInst, lpCI->lpOCI->szIconExe, 0); + if (NULL != lpCI->hDefIcon) + { + lstrcpy(lpCI->szDefIconFile, lpCI->lpOCI->szIconExe); + lpCI->iDefIcon = 0; + } + } + + if (NULL == lpCI->hDefIcon) + { + HGLOBAL hMetaPict; + hMetaPict = OleGetIconOfClass(lpCI->lpOCI->clsid, NULL, TRUE); + lpCI->hDefIcon = OleUIMetafilePictExtractIcon(hMetaPict); + TCHAR szTemp[MAX_PATH]; + OleUIMetafilePictExtractIconSource(hMetaPict, + szTemp, &lpCI->iDefIcon); + GetLongPathName(szTemp, lpCI->szDefIconFile, MAX_PATH); + OleUIMetafilePictIconFree(hMetaPict); + } + + // Initialize all the icon displays. + SendDlgItemMessage(hDlg, IDC_CI_CURRENTICON, STM_SETICON, + (WPARAM)lpCI->hCurIcon, 0L); + SendDlgItemMessage(hDlg, IDC_CI_DEFAULTICON, STM_SETICON, + (WPARAM)lpCI->hDefIcon, 0L); + + /* + * Since we cannot predict the size of icons on any display, + * we have to resize the icon listbox to the size of an icon + * (plus padding), a scrollbar, and two borders (top & bottom). + */ + UINT cyList = GetSystemMetrics(SM_CYICON)+GetSystemMetrics(SM_CYHSCROLL) + +GetSystemMetrics(SM_CYBORDER)*2+CYICONPAD; + HWND hList = GetDlgItem(hDlg, IDC_CI_ICONLIST); + RECT rc; + GetClientRect(hList, &rc); + SetWindowPos(hList, NULL, 0, 0, rc.right, cyList, SWP_NOMOVE | SWP_NOZORDER); + + // Set the columns in this multi-column listbox to hold one icon + SendMessage(hList, LB_SETCOLUMNWIDTH, + GetSystemMetrics(SM_CXICON)+CXICONPAD,0L); + + /* + * If the listbox expanded below the group box, then size + * the groupbox down, move the label static and exit controls + * down, and expand the entire dialog appropriately. + */ + GetWindowRect(hList, &rc); + RECT rcG; + GetWindowRect(GetDlgItem(hDlg, IDC_CI_GROUP), &rcG); + if (rc.bottom > rcG.bottom) + { + // Calculate amount to move things down. + cyList=(rcG.bottom-rcG.top)-(rc.bottom-rc.top-cyList); + + // Expand the group box. + rcG.right -=rcG.left; + rcG.bottom-=rcG.top; + SetWindowPos(GetDlgItem(hDlg, IDC_CI_GROUP), NULL, 0, 0, + rcG.right, rcG.bottom+cyList, SWP_NOMOVE | SWP_NOZORDER); + + // Expand the dialog box. + GetClientRect(hDlg, &rc); + SetWindowPos(hDlg, NULL, 0, 0, rc.right, rc.bottom+cyList, + SWP_NOMOVE | SWP_NOZORDER); + + // Move the label and edit controls down. + GetClientRect(GetDlgItem(hDlg, IDC_CI_LABEL), &rc); + SetWindowPos(GetDlgItem(hDlg, IDC_CI_LABEL), NULL, 0, cyList, + rc.right, rc.bottom, SWP_NOSIZE | SWP_NOZORDER); + + GetClientRect(GetDlgItem(hDlg, IDC_CI_LABELEDIT), &rc); + SetWindowPos(GetDlgItem(hDlg, IDC_CI_LABELEDIT), NULL, 0, cyList, + rc.right, rc.bottom, SWP_NOSIZE | SWP_NOZORDER); + } + + /* + * Select Current, Default, or From File radiobuttons appropriately. + * The CheckRadioButton call sends WM_COMMANDs which handle + * other actions. Note that if we check From File, which + * takes an icon from the list, we better fill the list. + * This will also fill the list even if default is selected. + */ + if (0 != UFillIconList(hDlg, IDC_CI_ICONLIST, lpCI->szFile, FALSE)) + { + // If szFile worked, then select the source icon in the listbox. + SendDlgItemMessage(hDlg, IDC_CI_ICONLIST, LB_SETCURSEL, lpCI->iIcon, 0L); + } + + if (lpCI->dwFlags & CIF_SELECTCURRENT) + { + CheckRadioButton(hDlg, IDC_CI_CURRENT, IDC_CI_FROMFILE, IDC_CI_CURRENT); + } + else + { + UINT uID = (lpCI->dwFlags & CIF_SELECTFROMFILE) ? IDC_CI_FROMFILE : IDC_CI_DEFAULT; + CheckRadioButton(hDlg, IDC_CI_CURRENT, IDC_CI_FROMFILE, uID); + } + UpdateResultIcon(lpCI, hDlg, (UINT)-1); + + // Change the caption + if (NULL!=lpOCI->lpszCaption) + SetWindowText(hDlg, lpOCI->lpszCaption); + + /* Give our parent window access to our hDlg (via a special SetProp). + * The PasteSpecial dialog may need to force our dialog down if the + * clipboard contents change underneath it. if so it will send + * us a IDCANCEL command. + */ + SetProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG, hDlg); + lpCI->nBrowseHelpID = RegisterWindowMessage(HELPMSGSTRING); + + // Call the hook with lCustData in lParam + UStandardHook(lpCI, hDlg, WM_INITDIALOG, wParam, lpOCI->lCustData); + return TRUE; +} + +/* + * UFillIconList + * + * Purpose: + * Given a listbox and a filename, attempts to open that file and + * read all the icons that exist therein, adding them to the listbox + * hList as owner-draw items. If the file does not exist or has no + * icons, then you get no icons and an appropriate warning message. + * + * Parameters: + * hDlg HWND of the dialog containing the listbox. + * idList UINT identifier of the listbox to fill. + * pszFile LPSTR of the file from which to extract icons. + * + * Return Value: + * UINT Number of items added to the listbox. 0 on failure. + */ +UINT UFillIconList(HWND hDlg, UINT idList, LPTSTR pszFile, BOOL bError) +{ + HWND hList = GetDlgItem(hDlg, idList); + if (NULL == hList) + return 0; + + // Clean out the listbox. + SendMessage(hList, LB_RESETCONTENT, 0, 0L); + + // If we have an empty string, just exit leaving the listbox empty as well + if (0 == lstrlen(pszFile)) + return 0; + + // Turn on the hourglass + HCURSOR hCur = HourGlassOn(); + UINT nFileError = 0; + + // Check if the file is valid. + TCHAR szPathName[MAX_PATH]; + LPTSTR lpszFilePart = NULL; + UINT cIcons = 0; + if (SearchPath(NULL, pszFile, NULL, MAX_PATH, szPathName, &lpszFilePart) != 0) + { + // This hack is still necessary in Win32 because even under + // Win32s this ExtractIcon bug appears. + #ifdef EXTRACTICONWORKS + // Get the icon count for this file. + cIcons = (UINT)StandardExtractIcon(_g_hOleStdInst, szPathName, (UINT)-1); + #else + /* + * ExtractIcon in Windows 3.1 with -1 eats a selector, leaving an + * extra global memory object around for this applciation. Since + * changing icons may happen very often with all OLE apps in + * the system, we have to work around it. So we'll say we + * have lots of icons and just call ExtractIcon until it + * fails. We check if there's any around by trying to get + * the first one. + */ + cIcons = 0xFFFF; + HICON hIcon = StandardExtractIcon(_g_hOleStdInst, szPathName, 0); + + // Fake a failure with cIcons=0, or cleanup hIcon from this test. + if (NULL == hIcon || 1 == (int)hIcon) + cIcons = 0; + else + DestroyIcon(hIcon); + #endif + + if (0 != cIcons) + { + SendMessage(hList, WM_SETREDRAW, FALSE, 0L); + for (UINT i = 0; i < cIcons; i++) + { + hIcon=StandardExtractIcon(_g_hOleStdInst, szPathName, i); + if (hIcon != NULL) + SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)hIcon); + else + break; + } + + //Force complete repaint + SendMessage(hList, WM_SETREDRAW, TRUE, 0L); + InvalidateRect(hList, NULL, TRUE); + + //Select an icon + SendMessage(hList, LB_SETCURSEL, 0, 0L); + } + else + nFileError = IDS_CINOICONSINFILE; + } + else + nFileError = ERROR_FILE_NOT_FOUND; + + // show error if necessary and possible + if (nFileError && bError) + { + ErrorWithFile(hDlg, _g_hOleStdResInst, nFileError, szPathName, + MB_OK | MB_ICONEXCLAMATION); + } + + HourGlassOff(hCur); + return cIcons; +} + +/* + * FDrawListIcon + * + * Purpose: + * Handles WM_DRAWITEM for the icon listbox. + * + * Parameters: + * lpDI LPDRAWITEMSTRUCT from WM_DRAWITEM + * + * Return Value: + * BOOL TRUE if we did anything, FALSE if there are no items + * in the list. + */ +BOOL FDrawListIcon(LPDRAWITEMSTRUCT lpDI) +{ + /* + * If there are no items in the list, then itemID is negative according + * to the Win3.1 SDK. Unfortunately DRAWITEMSTRUCT has an unsigned int + * for this field, so we need the typecast to do a signed comparison. + */ + if ((int)lpDI->itemID < 0) + return FALSE; + + /* + * For selection or draw entire case we just draw the entire item all + * over again. For focus cases, we only call DrawFocusRect. + */ + if (lpDI->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)) + { + COLORREF cr; + + // Clear background and draw the icon. + if (lpDI->itemState & ODS_SELECTED) + cr = SetBkColor(lpDI->hDC, GetSysColor(COLOR_HIGHLIGHT)); + else + cr = SetBkColor(lpDI->hDC, GetSysColor(COLOR_WINDOW)); + + // Draw a cheap rectangle. + ExtTextOut(lpDI->hDC, 0, 0, ETO_OPAQUE, &lpDI->rcItem, NULL, 0, NULL); + DrawIcon(lpDI->hDC, lpDI->rcItem.left+(CXICONPAD/2), + lpDI->rcItem.top+(CYICONPAD/2), (HICON)(lpDI->itemData)); + + // Restore original background for DrawFocusRect + SetBkColor(lpDI->hDC, cr); + } + + // Always change focus on the focus action. + if (lpDI->itemAction & ODA_FOCUS || lpDI->itemState & ODS_FOCUS) + DrawFocusRect(lpDI->hDC, &lpDI->rcItem); + + return TRUE; +} + +/* + * UpdateResultIcon + * + * Purpose: + * Updates the result icon using the current icon in the default display + * or the icon listbox depending on fFromDefault. + * + * Parameters: + * lpCI LPCHANGEICON containing dialog flags. + * hDlg HWND of the dialog + * uID UINT identifying the radiobutton selected. + * + * Return Value: + * None + */ +void UpdateResultIcon(LPCHANGEICON lpCI, HWND hDlg, UINT uID) +{ + if (uID == -1) + { + if (SendDlgItemMessage(hDlg, IDC_CI_CURRENT, BM_GETCHECK, 0, 0)) + uID = IDC_CI_CURRENT; + else if (SendDlgItemMessage(hDlg, IDC_CI_DEFAULT, BM_GETCHECK, 0, 0)) + uID = IDC_CI_DEFAULT; + else if (SendDlgItemMessage(hDlg, IDC_CI_FROMFILE, BM_GETCHECK, 0, 0)) + uID = IDC_CI_FROMFILE; + } + + lpCI->dwFlags &= ~(CIF_SELECTCURRENT | CIF_SELECTDEFAULT | CIF_SELECTFROMFILE); + LONG lTemp = -1; + + switch (uID) + { + case IDC_CI_CURRENT: + lTemp = SendDlgItemMessage(hDlg, IDC_CI_CURRENTICON, STM_GETICON, 0, 0L); + lpCI->dwFlags |= CIF_SELECTCURRENT; + break; + + case IDC_CI_DEFAULT: + lTemp = SendDlgItemMessage(hDlg, IDC_CI_DEFAULTICON, STM_GETICON, 0, 0L); + lpCI->dwFlags |= CIF_SELECTDEFAULT; + break; + + case IDC_CI_FROMFILE: + { + // Get the selected icon from the list and place it in the result + lpCI->dwFlags |= CIF_SELECTFROMFILE; + UINT iSel = (UINT)SendDlgItemMessage(hDlg, IDC_CI_ICONLIST, LB_GETCURSEL, 0, 0L); + if (LB_ERR == (int)iSel) + lTemp = SendDlgItemMessage(hDlg, IDC_CI_DEFAULTICON, STM_GETICON, 0, 0L); + else + lTemp = SendDlgItemMessage(hDlg, IDC_CI_ICONLIST, LB_GETITEMDATA, iSel, 0); + break; + } + + default: + OleDbgAssert(FALSE); + break; + } + CheckRadioButton(hDlg, IDC_CI_CURRENT, IDC_CI_FROMFILE, uID); + + // set current icon display as a result of the controls + LPTSTR lpszSourceFile = lpCI->szFile; + if (lpCI->dwFlags & CIF_SELECTDEFAULT) + { + // use defaults + lpszSourceFile = lpCI->szDefIconFile; + lpCI->iIcon = lpCI->iDefIcon; + } + else if (lpCI->dwFlags & CIF_SELECTCURRENT) + { + TCHAR szTemp[MAX_PATH]; + OleUIMetafilePictExtractIconSource(lpCI->lpOCI->hMetaPict, + szTemp, &lpCI->iIcon); + GetLongPathName(szTemp, lpszSourceFile, MAX_PATH); + } + else if (lpCI->dwFlags & CIF_SELECTFROMFILE) + { + // get from file and index + GetDlgItemText(hDlg, IDC_CI_FROMFILEEDIT, lpszSourceFile, MAX_PATH); + lpCI->iIcon = (UINT)SendDlgItemMessage(hDlg, + IDC_CI_ICONLIST, LB_GETCURSEL, 0, 0L); + } + + // Get new hMetaPict and set result text + TCHAR szTemp[MAX_PATH]; + GetDlgItemText(hDlg, IDC_CI_LABELEDIT, szTemp, MAX_PATH); + TCHAR szShortFile[MAX_PATH]; + GetShortPathName(lpszSourceFile, szShortFile, MAX_PATH); +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszTemp[MAX_PATH]; + OLECHAR wszSourceFile[MAX_PATH]; + ATOW(wszTemp, szTemp, MAX_PATH); + ATOW(wszSourceFile, szShortFile, MAX_PATH); + HGLOBAL hMetaPict = OleMetafilePictFromIconAndLabel( + (HICON)lTemp, wszTemp, wszSourceFile, lpCI->iIcon); +#else + HGLOBAL hMetaPict = OleMetafilePictFromIconAndLabel( + (HICON)lTemp, szTemp, szShortFile, lpCI->iIcon); +#endif + SendDlgItemMessage(hDlg, IDC_CI_ICONDISPLAY, IBXM_IMAGESET, 1, + (LPARAM)hMetaPict); +} + +//+--------------------------------------------------------------------------- +// +// Function: IsLongComponent, public +// +// Synopsis: Determines whether the current path component is a legal +// 8.3 name or not. If not, it is considered to be a long +// component. +// +// Arguments: [pwcsPath] - Path to check +// [ppwcsEnd] - Return for end of component pointer +// +// Returns: BOOL +// +// Modifies: [ppwcsEnd] +// +// History: 28-Aug-94 DrewB Created +// 5-04-95 stevebl Modified for use by oledlg +// +// Notes: An empty path is considered to be long +// The following characters are not valid in file name domain: +// * + , : ; < = > ? [ ] | +// +//---------------------------------------------------------------------------- + +BOOL IsLongComponent(LPCTSTR pwcsPath, + PTSTR *ppwcsEnd) +{ + LPTSTR pwcEnd, pwcDot; + BOOL fLongNameFound; + TCHAR wc; + + pwcEnd = (LPTSTR)pwcsPath; + fLongNameFound = FALSE; + pwcDot = NULL; + + while (TRUE) + { + wc = *pwcEnd; + + if (wc == '\\' || wc == 0) + { + *ppwcsEnd = pwcEnd; + + // We're at a component terminator, so make the + // determination of whether what we've seen is a long + // name or short one + + // If we've aready seen illegal characters or invalid + // structure for a short name, don't bother to check lengths + if (pwcEnd-pwcsPath > 0 && !fLongNameFound) + { + // If this component fits in 8.3 then it is a short name + if ((!pwcDot && (ULONG)(pwcEnd - pwcsPath) <= 8) || + (pwcDot && ((ULONG)(pwcEnd - pwcDot) <= 3 + 1 && + (ULONG)(pwcEnd - pwcsPath) <= 8 + 3 + 1))) + { + return FALSE; + } + } + + return TRUE; + } + + // Handle dots + if (wc == '.') + { + // If two or more '.' or the base name is longer than + // 8 characters or no base name at all, it is an illegal dos + // file name + if (pwcDot != NULL || + ((ULONG)(pwcEnd - pwcsPath)) > 8 || + (pwcEnd == pwcsPath && *(pwcEnd + 1) != '\\')) + { + fLongNameFound = TRUE; + } + + pwcDot = pwcEnd; + } + + // Check for characters which aren't valid in short names + else if (wc <= ' ' || + wc == '*' || + wc == '+' || + wc == ',' || + wc == ':' || + wc == ';' || + wc == '<' || + wc == '=' || + wc == '>' || + wc == '?' || + wc == '[' || + wc == ']' || + wc == '|') + { + fLongNameFound = TRUE; + } + + pwcEnd++; + } +} + +// +// The following code was stolen from NT's RTL in curdir.c +// + +#define IS_PATH_SEPARATOR(wch) \ + ((wch) == '\\' || (wch) == '/') + +typedef enum +{ + PATH_TYPE_UNKNOWN, + PATH_TYPE_UNC_ABSOLUTE, + PATH_TYPE_LOCAL_DEVICE, + PATH_TYPE_ROOT_LOCAL_DEVICE, + PATH_TYPE_DRIVE_ABSOLUTE, + PATH_TYPE_DRIVE_RELATIVE, + PATH_TYPE_ROOTED, + PATH_TYPE_RELATIVE +} PATH_TYPE; + +PATH_TYPE +DetermineDosPathNameType( + IN LPCTSTR DosFileName + ) + +/*++ + +Routine Description: + + This function examines the Dos format file name and determines the + type of file name (i.e. UNC, DriveAbsolute, Current Directory + rooted, or Relative. + +Arguments: + + DosFileName - Supplies the Dos format file name whose type is to be + determined. + +Return Value: + + PATH_TYPE_UNKNOWN - The path type can not be determined + + PATH_TYPE_UNC_ABSOLUTE - The path specifies a Unc absolute path + in the format \\server-name\sharename\rest-of-path + + PATH_TYPE_LOCAL_DEVICE - The path specifies a local device in the format + \\.\rest-of-path this can be used for any device where the nt and + Win32 names are the same. For example mailslots. + + PATH_TYPE_ROOT_LOCAL_DEVICE - The path specifies the root of the local + devices in the format \\. + + PATH_TYPE_DRIVE_ABSOLUTE - The path specifies a drive letter absolute + path in the form drive:\rest-of-path + + PATH_TYPE_DRIVE_RELATIVE - The path specifies a drive letter relative + path in the form drive:rest-of-path + + PATH_TYPE_ROOTED - The path is rooted relative to the current disk + designator (either Unc disk, or drive). The form is \rest-of-path. + + PATH_TYPE_RELATIVE - The path is relative (i.e. not absolute or rooted). + +--*/ + +{ + PATH_TYPE ReturnValue; + + if ( IS_PATH_SEPARATOR(*DosFileName) ) + { + if ( IS_PATH_SEPARATOR(*(DosFileName+1)) ) + { + if ( DosFileName[2] == '.' ) + { + if ( IS_PATH_SEPARATOR(*(DosFileName+3)) ) + { + ReturnValue = PATH_TYPE_LOCAL_DEVICE; + } + else if ( (*(DosFileName+3)) == 0 ) + { + ReturnValue = PATH_TYPE_ROOT_LOCAL_DEVICE; + } + else + { + ReturnValue = PATH_TYPE_UNC_ABSOLUTE; + } + } + else + { + ReturnValue = PATH_TYPE_UNC_ABSOLUTE; + } + } + else + { + ReturnValue = PATH_TYPE_ROOTED; + } + } + else if (*(DosFileName+1) == ':') + { + if (IS_PATH_SEPARATOR(*(DosFileName+2))) + { + ReturnValue = PATH_TYPE_DRIVE_ABSOLUTE; + } + else + { + ReturnValue = PATH_TYPE_DRIVE_RELATIVE; + } + } + else + { + ReturnValue = PATH_TYPE_RELATIVE; + } + + return ReturnValue; +} + +//+--------------------------------------------------------------------------- +// +// Function: GetLongPathName, public +// +// Synopsis: Expand each component of the given path into its +// long form +// +// Arguments: [pwcsPath] - Path +// [pwcsLongPath] - Long path return buffer +// [cchLongPath] - Size of return buffer in characters +// +// Returns: 0 for errors +// Number of characters needed for buffer if buffer is too small +// includes NULL terminator +// Length of long path, doesn't include NULL terminator +// +// Modifies: [pwcsLongPath] +// +// History: 28-Aug-94 DrewB Created +// 11-Nov-94 BruceMa Modifed to use for Chicago at +// FindFirstFile +// 5-04-95 stevebl Modified for use by OLEDLG +// +// Notes: The source and destination buffers can be the same memory +// Doesn't handle paths with internal . and .., although +// they are handled at the beginning +// +//---------------------------------------------------------------------------- + +ULONG +GetLongPathName(LPCTSTR pcsPath, + LPTSTR pwcsLongPath, + ULONG cchLongPath) +{ + PATH_TYPE pt; + HANDLE h; + LPTSTR pwcsLocalLongPath; + ULONG cchReturn, cb, cch, cchOutput; + LPTSTR pwcStart = NULL; + LPTSTR pwcEnd; + LPTSTR pwcLong; + TCHAR wcSave; + BOOL fLong; + WIN32_FIND_DATA wfd; + cchReturn = 0; + pwcsLocalLongPath = NULL; + + __try + { + // + // First, run down the string checking for tilde's. Any path + // that has a short name section to it will have a tilde. If + // there are no tilde's, then we already have the long path, + // so we can return the string. + // + fLong = TRUE; + for (pwcLong = (LPTSTR)pcsPath; *pwcLong != 0; pwcLong++) + { + if (*pwcLong == L'~') + { + fLong = FALSE; + } + } + // + // This derives the number of characters, including the NULL + // + cch = (pwcLong - pcsPath) + 1; + + // + // If it isn't a long path already, then we are going to have + // to parse it. + // + if (!fLong) + { + // Decide the path type, we want find out the position of + // the first character of the first name + pt = DetermineDosPathNameType(pcsPath); + switch(pt) + { + // Form: "\\server_name\share_name\rest_of_the_path" + case PATH_TYPE_UNC_ABSOLUTE: +#if defined(UNICODE) + if ((pwcStart = wcschr(pcsPath + 2, L'\\')) != NULL && + (pwcStart = wcschr(pwcStart + 1, L'\\')) != NULL) +#else + if ((pwcStart = strchr(pcsPath + 2, '\\')) != NULL && + (pwcStart = strchr(pwcStart + 1, '\\')) != NULL) +#endif + { + pwcStart++; + } + else + { + pwcStart = NULL; + } + break; + + // Form: "\\.\rest_of_the_path" + case PATH_TYPE_LOCAL_DEVICE: + pwcStart = (LPTSTR)pcsPath + 4; + break; + + // Form: "\\." + case PATH_TYPE_ROOT_LOCAL_DEVICE: + pwcStart = NULL; + break; + + // Form: "D:\rest_of_the_path" + case PATH_TYPE_DRIVE_ABSOLUTE: + pwcStart = (LPTSTR)pcsPath + 3; + break; + + // Form: "rest_of_the_path" + case PATH_TYPE_RELATIVE: + pwcStart = (LPTSTR) pcsPath; + goto EatDots; + + // Form: "D:rest_of_the_path" + case PATH_TYPE_DRIVE_RELATIVE: + pwcStart = (LPTSTR)pcsPath+2; + + EatDots: + // Handle .\ and ..\ cases + while (*pwcStart != 0 && *pwcStart == L'.') + { + if (pwcStart[1] == L'\\') + { + pwcStart += 2; + } + else if (pwcStart[1] == L'.' && pwcStart[2] == L'\\') + { + pwcStart += 3; + } + else + { + break; + } + } + break; + + // Form: "\rest_of_the_path" + case PATH_TYPE_ROOTED: + pwcStart = (LPTSTR)pcsPath + 1; + break; + + default: + pwcStart = NULL; + break; + } + } + + // In the special case where we have no work to do, exit quickly + // This saves a lot of instructions for trivial cases + // In one case the path as given requires no processing + // The middle case, we determine there were no tilde's in the path + // In the other, the path only has one component and it is already + // long + /// + if (pwcStart == NULL || + (fLong == TRUE) || + ((fLong = IsLongComponent(pwcStart, &pwcEnd)) && + *pwcEnd == 0)) + { + // Nothing to convert, copy down the source string + // to the buffer if necessary + + if (pwcStart != NULL) + { + cch = (ULONG)(pwcEnd - pcsPath + 1); + } + + if (cchLongPath >= cch) + { + memcpy(pwcsLongPath, pcsPath, cch * sizeof(TCHAR)); + + cchReturn = cch - 1; + goto gsnTryExit; + } + else + { + cchReturn = cch; + goto gsnTryExit; + } + } + + // Make a local buffer so that we won't overlap the + // source pathname in case the long name is longer than the + // source name. + if (cchLongPath > 0) + { + pwcsLocalLongPath = (PTCHAR)malloc(cchLongPath * sizeof(TCHAR)); + if (pwcsLocalLongPath == NULL) + { + goto gsnTryExit; + } + } + + // Set up pointer to copy output to + pwcLong = pwcsLocalLongPath; + cchOutput = 0; + + // Copy the portions of the path that we skipped initially + cch = pwcStart-pcsPath; + cchOutput += cch; + if (cchOutput <= cchLongPath) + { + memcpy(pwcLong, pcsPath, cch*sizeof(TCHAR)); + pwcLong += cch; + } + + for (;;) + { + // Determine whether the current component is long or short + cch = pwcEnd-pwcStart+1; + cb = cch*sizeof(TCHAR); + + if (fLong) + { + // If the component is already long, just copy it into + // the output. Copy the terminating character along with it + // so the output remains properly punctuated + + cchOutput += cch; + if (cchOutput <= cchLongPath) + { + memcpy(pwcLong, pwcStart, cb); + pwcLong += cch; + } + } + else + { + TCHAR wcsTmp[MAX_PATH]; + + // For a short component we need to determine the + // long name, if there is one. The only way to + // do this reliably is to enumerate for the child + + wcSave = *pwcEnd; + *pwcEnd = 0; + + h = FindFirstFile(pcsPath, &wfd); + *pwcEnd = wcSave; + + if (h == INVALID_HANDLE_VALUE) + { + goto gsnTryExit; + } + + FindClose(h); + + lstrcpy(wcsTmp, wfd.cFileName); + + // Copy the filename returned by the query into the output + // Copy the terminator from the original component into + // the output to maintain punctuation + cch = lstrlen(wcsTmp)+1; + cchOutput += cch; + if (cchOutput <= cchLongPath) + { + memcpy(pwcLong, wcsTmp, (cch-1)*sizeof(TCHAR)); + pwcLong += cch; + *(pwcLong-1) = *pwcEnd; + } + } + + if (*pwcEnd == 0) + { + break; + } + + // Update start pointer to next component + pwcStart = pwcEnd+1; + fLong = IsLongComponent(pwcStart, &pwcEnd); + } + + // Copy local output buffer to given output buffer if necessary + if (cchLongPath >= cchOutput) + { + memcpy(pwcsLongPath, pwcsLocalLongPath, cchOutput * sizeof(TCHAR)); + cchReturn = cchOutput-1; + } + else + { + cchReturn = cchOutput; + } + +gsnTryExit:; + } + __finally + { + if (pwcsLocalLongPath != NULL) + { + free(pwcsLocalLongPath); + pwcsLocalLongPath = NULL; + } + } + + return cchReturn; +} + diff --git a/private/ole2ui32/iconbox.cpp b/private/ole2ui32/iconbox.cpp new file mode 100644 index 000000000..d18adb8be --- /dev/null +++ b/private/ole2ui32/iconbox.cpp @@ -0,0 +1,215 @@ +/* + * ICONBOX.CPP + * + * Implemenatation of an IconBox control for OLE 2.0 UI dialogs that we'll + * use wherever a dialog needs an icon/label display. Through the control's + * interface we can change the image or control label visibility. + * + * The IconBox discusses images in CF_METAFILEPICT format. When drawing + * such a metafile, the entire aspect is centered in the IconBox, so long + * labels are chopped at either end. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "iconbox.h" +#include "utility.h" +#include "uiclass.h" + +OLEDBGDATA + +//Flag indicating if we've registered the class +static BOOL fRegistered; + + +/* + * FIconBoxInitialize + * + * Purpose: + * Registers the IconBox control class. + * + * Parameters: + * hInst HINSTANCE instance of the DLL. + * + * hPrevInst HINSTANCE of the previous instance. Used to + * determine whether to register window classes or not. + * + * Return Value: + * BOOL TRUE if all initialization succeeded, FALSE otherwise. + */ + +#pragma code_seg(".text$initseg") + +BOOL FIconBoxInitialize(HINSTANCE hInst, HINSTANCE hPrevInst) +{ + // Only register class if we're the first instance + if (hPrevInst) + fRegistered = TRUE; + else + { + // Static flag fRegistered guards against calling this function more + // than once + if (!fRegistered) + { + WNDCLASS wc; + wc.lpfnWndProc =IconBoxWndProc; + wc.cbClsExtra =0; + wc.cbWndExtra =CBICONBOXWNDEXTRA; + wc.hInstance =hInst; + wc.hIcon =NULL; + wc.hCursor =LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground =(HBRUSH)NULL; + wc.lpszMenuName =NULL; + wc.style =CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW; + + wc.lpszClassName = TEXT(SZCLASSICONBOX1); + fRegistered = RegisterClass(&wc); + + wc.lpszClassName = TEXT(SZCLASSICONBOX2); + fRegistered = RegisterClass(&wc); + + wc.lpszClassName = TEXT(SZCLASSICONBOX3); + fRegistered = RegisterClass(&wc); + } + } + return fRegistered; +} + +#pragma code_seg() + + +/* + * IconBoxUninitialize + * + * Purpose: + * Cleans up anything done in FIconBoxInitialize. Currently there is + * nothing, but we do this for symmetry. + * + * Parameters: + * None + * + * Return Value: + * None + */ + +void IconBoxUninitialize(void) +{ + return; +} + +/* + * IconBoxWndProc + * + * Purpose: + * Window Procedure for the IconBox custom control. Only handles + * WM_CREATE, WM_PAINT, and private messages to manipulate the image. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ + +LONG CALLBACK IconBoxWndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + //Handle standard Windows messages. + switch (iMsg) + { + case WM_CREATE: + SetWindowLong(hWnd, IBWW_HIMAGE, 0); + SetWindowWord(hWnd, IBWW_FLABEL, TRUE); + return 0L; + + case WM_ERASEBKGND: + { + + RECT rect; + GetClientRect(hWnd, &rect); + HBRUSH hBrush = (HBRUSH)SendMessage(GetParent(hWnd), WM_CTLCOLORDLG, + wParam, (LPARAM)GetParent(hWnd)); + + if (!hBrush) + return FALSE; + + UnrealizeObject(hBrush); + + SetBrushOrgEx((HDC)wParam, 0, 0, NULL); + FillRect((HDC)wParam, &rect, hBrush); + return TRUE; + } + + case WM_PAINT: + { + HGLOBAL hMF = (HGLOBAL)GetWindowLong(hWnd, IBWW_HIMAGE); + + //BeginPaint and EndPaint clear us even if hMF is NULL. + PAINTSTRUCT ps; + HDC hDC = BeginPaint(hWnd, &ps); + + if (NULL != hMF) + { + //Now we get to paint the metafile, centered in our rect. + RECT rc; + GetClientRect(hWnd, &rc); + + /* + * If we're doing icon only, then place the metafile + * at the center of our box minus half the icon width. + * Top is top. + */ + BOOL fLabel = GetWindowWord(hWnd, IBWW_FLABEL); + + //Go draw where we decided to place it. + OleUIMetafilePictIconDraw(hDC, &rc, hMF, !fLabel); + } + EndPaint(hWnd, &ps); + } + break; + + case IBXM_IMAGESET: + { + /* + * wParam is a flag to delete the old or not. + * lParam contains the new handle. + */ + HGLOBAL hMF = (HGLOBAL)SetWindowLong(hWnd, IBWW_HIMAGE, lParam); + InvalidateRect(hWnd, NULL, TRUE); + UpdateWindow(hWnd); + + //Delete the old handle if requested + if (0L!=wParam) + { + OleUIMetafilePictIconFree(hMF); + hMF=NULL; + } + return (LONG)(UINT)hMF; + } + + case IBXM_IMAGEGET: + { + //Return the current index. + HGLOBAL hMF=(HGLOBAL)GetWindowLong(hWnd, IBWW_HIMAGE); + return (LONG)(UINT)hMF; + } + + case IBXM_IMAGEFREE: + { + //Free up whatever we're holding. + HGLOBAL hMF=(HGLOBAL)GetWindowLong(hWnd, IBWW_HIMAGE); + OleUIMetafilePictIconFree(hMF); + SetWindowLong(hWnd, IBWW_HIMAGE, 0); + return 1L; + } + + case IBXM_LABELENABLE: + //wParam has the new flag, returns the previous flag. + return (LONG)SetWindowWord(hWnd, IBWW_FLABEL, (WORD)wParam); + + default: + return DefWindowProc(hWnd, iMsg, wParam, lParam); + } + + return 0L; +} diff --git a/private/ole2ui32/iconbox.h b/private/ole2ui32/iconbox.h new file mode 100644 index 000000000..dc6084052 --- /dev/null +++ b/private/ole2ui32/iconbox.h @@ -0,0 +1,29 @@ +/* + * ICONBOX.H + * + * Structures and definitions for the IconBox control. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef _ICONBOX_H_ +#define _ICONBOX_H_ + +// Function prototypes +BOOL FIconBoxInitialize(HINSTANCE, HINSTANCE); +void IconBoxUninitialize(void); +LONG CALLBACK IconBoxWndProc(HWND, UINT, WPARAM, LPARAM); + +// Window extra bytes contain the bitmap index we deal with currently. +#define CBICONBOXWNDEXTRA (sizeof(HGLOBAL)+sizeof(BOOL)) +#define IBWW_HIMAGE 0 +#define IBWW_FLABEL (sizeof(HGLOBAL)) + +// Control messages +#define IBXM_IMAGESET (WM_USER+0) +#define IBXM_IMAGEGET (WM_USER+1) +#define IBXM_IMAGEFREE (WM_USER+2) +#define IBXM_LABELENABLE (WM_USER+3) + +#endif //_ICONBOX_H_ diff --git a/private/ole2ui32/insobj.cpp b/private/ole2ui32/insobj.cpp new file mode 100644 index 000000000..6421bad4b --- /dev/null +++ b/private/ole2ui32/insobj.cpp @@ -0,0 +1,1850 @@ +/* + * INSOBJ.CPP + * + * Implements the OleUIInsertObject function which invokes the complete + * Insert Object dialog. Makes use of the OleChangeIcon function in + * ICON.CPP. + * + * Copyright (c)1993 Microsoft Corporation, All Rights Reserved + */ + +#include "precomp.h" +#include "common.h" +#include <commdlg.h> +#include <memory.h> +#include <dos.h> +#include <stdlib.h> +#include "utility.h" +#include "resimage.h" +#include "iconbox.h" + +OLEDBGDATA + +// Internally used structure +typedef struct tagINSERTOBJECT +{ + LPOLEUIINSERTOBJECT lpOIO; // Original structure passed. + UINT nIDD; // IDD of dialog (used for help info) + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + DWORD dwFlags; + CLSID clsid; + TCHAR szFile[MAX_PATH]; + BOOL fFileSelected; // Enables Display As Icon for links + BOOL fAsIconNew; + BOOL fAsIconFile; + BOOL fFileDirty; + BOOL fFileValid; + UINT nErrCode; + HGLOBAL hMetaPictFile; + UINT nBrowseHelpID; // Help ID callback for Browse dlg + BOOL bObjectListFilled; + BOOL bControlListFilled; + BOOL bControlListActive; + +} INSERTOBJECT, *PINSERTOBJECT, FAR *LPINSERTOBJECT; + +// Internal function prototypes +// INSOBJ.CPP + +BOOL CALLBACK InsertObjectDialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL FInsertObjectInit(HWND, WPARAM, LPARAM); +UINT UFillClassList(HWND, UINT, LPCLSID, BOOL, BOOL); +UINT URefillClassList(HWND, LPINSERTOBJECT); +BOOL FToggleObjectSource(HWND, LPINSERTOBJECT, DWORD); +void UpdateClassType(HWND, LPINSERTOBJECT, BOOL); +void SetInsertObjectResults(HWND, LPINSERTOBJECT); +BOOL FValidateInsertFile(HWND, BOOL, UINT FAR*); +void InsertObjectCleanup(HWND); +static void UpdateClassIcon(HWND hDlg, LPINSERTOBJECT lpIO, HWND hList); +BOOL CALLBACK HookDlgProc(HWND, UINT, WPARAM, LPARAM); + +#define IS_FILENAME_DELIM(c) ( (c) == '\\' || (c) == '/' || (c) == ':') + +BOOL CALLBACK HookDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ +#ifdef CHICO + switch (uMsg) + { + case WM_INITDIALOG: + TCHAR szTemp[MAX_PATH]; + LoadString(_g_hOleStdResInst, IDS_INSERT , szTemp, MAX_PATH); + CommDlg_OpenSave_SetControlText(GetParent(hDlg), IDOK, szTemp); + return(TRUE); + default: + break; + } +#endif + return(FALSE); +} + +/* + * OleUIInsertObject + * + * Purpose: + * Invokes the standard OLE Insert Object dialog box allowing the + * user to select an object source and classname as well as the option + * to display the object as itself or as an icon. + * + * Parameters: + * lpIO LPOLEUIINSERTOBJECT pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT OLEUI_SUCCESS or OLEUI_OK if all is well, otherwise + * an error value. + */ + +STDAPI_(UINT) OleUIInsertObject(LPOLEUIINSERTOBJECT lpIO) +{ + HGLOBAL hMemDlg = NULL; + UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpIO, sizeof(OLEUIINSERTOBJECT), + &hMemDlg); + + if (OLEUI_SUCCESS != uRet) + return uRet; + + //Now we can do Insert Object specific validation. + + if (NULL != lpIO->lpszFile && + (lpIO->cchFile <= 0 || lpIO->cchFile > MAX_PATH)) + { + uRet = OLEUI_IOERR_CCHFILEINVALID; + } + + // NULL is NOT valid for lpszFile + if (lpIO->lpszFile == NULL) + { + uRet = OLEUI_IOERR_LPSZFILEINVALID; + } + else + { + if (IsBadWritePtr(lpIO->lpszFile, lpIO->cchFile*sizeof(TCHAR))) + uRet = OLEUI_IOERR_LPSZFILEINVALID; + } + + if (0 != lpIO->cClsidExclude && + IsBadReadPtr(lpIO->lpClsidExclude, lpIO->cClsidExclude * sizeof(CLSID))) + { + uRet = OLEUI_IOERR_LPCLSIDEXCLUDEINVALID; + } + + //If we have flags to create any object, validate necessary data. + if (lpIO->dwFlags & (IOF_CREATENEWOBJECT | IOF_CREATEFILEOBJECT | IOF_CREATELINKOBJECT)) + { + if (NULL != lpIO->lpFormatEtc + && IsBadReadPtr(lpIO->lpFormatEtc, sizeof(FORMATETC))) + uRet = OLEUI_IOERR_LPFORMATETCINVALID; + + if (NULL != lpIO->ppvObj && IsBadWritePtr(lpIO->ppvObj, sizeof(LPVOID))) + uRet = OLEUI_IOERR_PPVOBJINVALID; + + if (NULL != lpIO->lpIOleClientSite + && IsBadReadPtr(*(VOID**)&lpIO->lpIOleClientSite, sizeof(DWORD))) + uRet = OLEUI_IOERR_LPIOLECLIENTSITEINVALID; + + if (NULL != lpIO->lpIStorage + && IsBadReadPtr(*(VOID**)&lpIO->lpIStorage, sizeof(DWORD))) + uRet = OLEUI_IOERR_LPISTORAGEINVALID; + } + + if (OLEUI_ERR_STANDARDMIN <= uRet) + { + return uRet; + } + + //Now that we've validated everything, we can invoke the dialog. + uRet = UStandardInvocation(InsertObjectDialogProc, (LPOLEUISTANDARD)lpIO, + hMemDlg, MAKEINTRESOURCE(IDD_INSERTOBJECT)); + + //Stop here if we cancelled or had an error. + if (OLEUI_SUCCESS !=uRet && OLEUI_OK!=uRet) + return uRet; + + /* + * If any of the flags specify that we're to create objects on return + * from this dialog, then do so. If we encounter an error in this + * processing, we return OLEUI_IOERR_SCODEHASERROR. Since the + * three select flags are mutually exclusive, we don't have to + * if...else here, just if each case (keeps things cleaner that way). + */ + + lpIO->sc = S_OK; + + // Check if Create New was selected and we have IOF_CREATENEWOBJECT + if ((lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL)) && + (lpIO->dwFlags & IOF_CREATENEWOBJECT)) + { + HRESULT hrErr = OleCreate(lpIO->clsid, lpIO->iid, lpIO->oleRender, + lpIO->lpFormatEtc, lpIO->lpIOleClientSite, lpIO->lpIStorage, + lpIO->ppvObj); + lpIO->sc = GetScode(hrErr); + } + + // Try Create From File + if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)) + { + if (!(lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATEFILEOBJECT)) + { +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszFile[MAX_PATH]; + ATOW(wszFile, lpIO->lpszFile, MAX_PATH); + HRESULT hrErr=OleCreateFromFile(CLSID_NULL, wszFile, lpIO->iid, + lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite, + lpIO->lpIStorage, lpIO->ppvObj); +#else + HRESULT hrErr=OleCreateFromFile(CLSID_NULL, lpIO->lpszFile, lpIO->iid, + lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite, + lpIO->lpIStorage, lpIO->ppvObj); +#endif + lpIO->sc = GetScode(hrErr); + } + + if ((lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATELINKOBJECT)) + { +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszFile[MAX_PATH]; + ATOW(wszFile, lpIO->lpszFile, MAX_PATH); + HRESULT hrErr=OleCreateLinkToFile(wszFile, lpIO->iid, + lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite, + lpIO->lpIStorage, lpIO->ppvObj); +#else + HRESULT hrErr=OleCreateLinkToFile(lpIO->lpszFile, lpIO->iid, + lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite, + lpIO->lpIStorage, lpIO->ppvObj); +#endif + lpIO->sc = GetScode(hrErr); + } + } + + //If we tried but failed a create option, then return the appropriate error + if (S_OK != lpIO->sc) + uRet = OLEUI_IOERR_SCODEHASERROR; + + return uRet; +} + +/* + * InsertObjectDialogProc + * + * Purpose: + * Implements the OLE Insert Object dialog as invoked through the + * OleUIInsertObject function. + */ + +BOOL CALLBACK InsertObjectDialogProc(HWND hDlg, UINT iMsg, + WPARAM wParam, LPARAM lParam) +{ + // Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + // This will fail under WM_INITDIALOG, where we allocate it. + UINT uRet = 0; + LPINSERTOBJECT lpIO = (LPINSERTOBJECT)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet); + + // If the hook processed the message, we're done. + if (0 != uRet) + return (BOOL)uRet; + + // Process help message from Change Icon + if (iMsg == uMsgHelp) + { + PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp, wParam, lParam); + return FALSE; + } + + // Process the temination message + if (iMsg == uMsgEndDialog) + { + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) + { + case WM_DESTROY: + if (lpIO) + { + InsertObjectCleanup(hDlg); + StandardCleanup(lpIO, hDlg); + } + break; + case WM_INITDIALOG: + return FInsertObjectInit(hDlg, wParam, lParam); + + case WM_COMMAND: + switch (wID) + { + case IDC_IO_CREATENEW: + if (1 == IsDlgButtonChecked(hDlg, IDC_IO_CREATENEW)) + { + FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATENEW); + } + break; + + case IDC_IO_CREATEFROMFILE: + if (1 == IsDlgButtonChecked(hDlg, IDC_IO_CREATEFROMFILE)) + { + FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATEFROMFILE); + } + break; + + case IDC_IO_INSERTCONTROL: + if (1 == IsDlgButtonChecked(hDlg, IDC_IO_INSERTCONTROL)) + { + FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATECONTROL); + } + break; + + case IDC_IO_LINKFILE: + { + BOOL fCheck=IsDlgButtonChecked(hDlg, wID); + if (fCheck) + lpIO->dwFlags |=IOF_CHECKLINK; + else + lpIO->dwFlags &=~IOF_CHECKLINK; + + // Results change here, so be sure to update it. + SetInsertObjectResults(hDlg, lpIO); + UpdateClassIcon(hDlg, lpIO, NULL); + } + break; + + case IDC_IO_OBJECTTYPELIST: + switch (wCode) + { + case LBN_SELCHANGE: + UpdateClassIcon(hDlg, lpIO, hWndMsg); + SetInsertObjectResults(hDlg, lpIO); + break; + + case LBN_DBLCLK: + SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg); + break; + } + break; + + case IDC_IO_FILEDISPLAY: + // If there are characters, enable OK and Display As Icon + if (EN_CHANGE == wCode) + { + lpIO->fFileDirty = TRUE; + lpIO->fFileValid = FALSE; + lpIO->fFileSelected = (0L != SendMessage(hWndMsg, EM_LINELENGTH, 0, 0L)); + StandardEnableDlgItem(hDlg, IDC_IO_LINKFILE, lpIO->fFileSelected); + StandardEnableDlgItem(hDlg, IDC_IO_DISPLAYASICON, lpIO->fFileSelected); + StandardEnableDlgItem(hDlg, IDC_IO_CHANGEICON, lpIO->fFileSelected); + StandardEnableDlgItem(hDlg, IDOK, lpIO->fFileSelected); + } + if (EN_KILLFOCUS == wCode && NULL != lpIO) + { + if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode)) + { + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = TRUE; + UpdateClassIcon(hDlg, lpIO, NULL); + UpdateClassType(hDlg, lpIO, TRUE); + } + else + { + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = FALSE; + UpdateClassType(hDlg, lpIO, FALSE); + } + } + break; + + case IDC_IO_DISPLAYASICON: + { + BOOL fCheck = IsDlgButtonChecked(hDlg, wID); + StandardEnableDlgItem(hDlg, IDC_IO_CHANGEICON, fCheck); + if (fCheck) + lpIO->dwFlags |=IOF_CHECKDISPLAYASICON; + else + lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON; + + // Update the internal flag based on this checking + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + lpIO->fAsIconNew = fCheck; + else + lpIO->fAsIconFile = fCheck; + + // Re-read the class icon on Display checked + if (fCheck) + { + if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) + { + if (FValidateInsertFile(hDlg, TRUE,&lpIO->nErrCode)) + { + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = TRUE; + UpdateClassIcon(hDlg, lpIO, + GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST)); + UpdateClassType(hDlg, lpIO, TRUE); + } + else + { + lpIO->fAsIconFile= FALSE; + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = FALSE; + SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY, + IBXM_IMAGESET, 0, 0L); + UpdateClassType(hDlg, lpIO, FALSE); + + lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, IDC_IO_DISPLAYASICON, 0); + + HWND hWndEC = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY); + SetFocus(hWndEC); + SendMessage(hWndEC, EM_SETSEL, 0, -1); + return TRUE; + } + } + else + UpdateClassIcon(hDlg, lpIO, + GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST)); + } + + // Results change here, so be sure to update it. + SetInsertObjectResults(hDlg, lpIO); + + /* + * Show or hide controls as appropriate. Do the icon + * display last because it will take some time to repaint. + * If we do it first then the dialog looks too sluggish. + */ + UINT i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE; + StandardShowDlgItem(hDlg, IDC_IO_CHANGEICON, i); + StandardShowDlgItem(hDlg, IDC_IO_ICONDISPLAY, i); + } + break; + + case IDC_IO_CHANGEICON: + { + // if we're in SELECTCREATEFROMFILE mode, then we need to Validate + // the contents of the edit control first. + + if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) + { + if (lpIO->fFileDirty && + !FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode)) + { + HWND hWndEC; + lpIO->fFileValid = FALSE; + hWndEC = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY); + SetFocus(hWndEC); + SendMessage(hWndEC, EM_SETSEL, 0, -1); + return TRUE; + } + else + { + lpIO->fFileDirty = FALSE; + } + } + + // Initialize the structure for the hook. + OLEUICHANGEICON ci; memset(&ci, 0, sizeof(ci)); + ci.cbStruct = sizeof(ci); + ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, + IDC_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); + ci.hWndOwner= hDlg; + ci.dwFlags = CIF_SELECTCURRENT; + if (lpIO->dwFlags & IOF_SHOWHELP) + ci.dwFlags |= CIF_SHOWHELP; + + HWND hList = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST); + int iCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L); + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + { + LPTSTR pszString = (LPTSTR)OleStdMalloc( + OLEUI_CCHKEYMAX_SIZE + OLEUI_CCHCLSIDSTRING_SIZE); + + SendMessage(hList, LB_GETTEXT, iCurSel, (LONG)pszString); + + LPTSTR pszCLSID = PointerToNthField(pszString, 2, '\t'); +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszCLSID[OLEUI_CCHKEYMAX]; + ATOW(wszCLSID, pszCLSID, OLEUI_CCHKEYMAX); + CLSIDFromString(wszCLSID, &ci.clsid); +#else + CLSIDFromString(pszCLSID, &ci.clsid); +#endif + OleStdFree((LPVOID)pszString); + } + else // IOF_SELECTCREATEFROMFILE + { + TCHAR szFileName[MAX_PATH]; + GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szFileName, MAX_PATH); +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszFileName[MAX_PATH]; + ATOW(wszFileName, szFileName, MAX_PATH); + if (NOERROR != GetClassFile(wszFileName, &ci.clsid)) +#else + if (NOERROR != GetClassFile(szFileName, &ci.clsid)) +#endif + { + int istrlen = lstrlen(szFileName); + LPTSTR lpszExtension = szFileName + istrlen -1; + + while (lpszExtension > szFileName && + *lpszExtension != '.') + { + lpszExtension = CharPrev(szFileName, lpszExtension); + } + + GetAssociatedExecutable(lpszExtension, ci.szIconExe); + ci.cchIconExe = lstrlen(ci.szIconExe); + ci.dwFlags |= CIF_USEICONEXE; + } + } + + // Let the hook in to customize Change Icon if desired. + uRet = UStandardHook(lpIO, hDlg, uMsgChangeIcon, 0, (LONG)&ci); + + if (0 == uRet) + uRet = (UINT)(OLEUI_OK == OleUIChangeIcon(&ci)); + + // Update the display and itemdata if necessary. + if (0 != uRet) + { + /* + * OleUIChangeIcon will have already freed our + * current hMetaPict that we passed in when OK is + * pressed in that dialog. So we use 0L as lParam + * here so the IconBox doesn't try to free the + * metafilepict again. + */ + SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY, + IBXM_IMAGESET, 0, (LPARAM)ci.hMetaPict); + + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + SendMessage(hList, LB_SETITEMDATA, iCurSel, (LPARAM)ci.hMetaPict); + } + } + break; + + case IDC_IO_FILE: + { + /* + * To allow the hook to customize the browse dialog, we + * send OLEUI_MSG_BROWSE. If the hook returns FALSE + * we use the default, otherwise we trust that it retrieved + * a filename for us. This mechanism prevents hooks from + * trapping IDC_IO_BROWSE to customize the dialog and from + * trying to figure out what we do after we have the name. + */ + TCHAR szTemp[MAX_PATH]; + int nChars = GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szTemp, MAX_PATH); + + TCHAR szInitialDir[MAX_PATH]; + BOOL fUseInitialDir = FALSE; + if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode)) + { + StandardGetFileTitle(szTemp, lpIO->szFile, MAX_PATH); + int istrlen = lstrlen(lpIO->szFile); + + lstrcpyn(szInitialDir, szTemp, nChars - istrlen); + fUseInitialDir = TRUE; + } + else // file name isn't valid...lop off end of szTemp to get a + // valid directory + { + TCHAR szBuffer[MAX_PATH]; + lstrcpyn(szBuffer, szTemp, sizeof(szBuffer)/sizeof(TCHAR)); + + if ('\\' == szBuffer[nChars-1]) + szBuffer[nChars-1] = '\0'; + + DWORD Attribs = GetFileAttributes(szBuffer); + if (Attribs != 0xffffffff && + (Attribs & FILE_ATTRIBUTE_DIRECTORY) ) + { + lstrcpy(szInitialDir, szBuffer); + fUseInitialDir = TRUE; + } + *lpIO->szFile = '\0'; + } + + uRet = UStandardHook(lpIO, hDlg, uMsgBrowse, + MAX_PATH, (LPARAM)(LPSTR)lpIO->szFile); + + if (0 == uRet) + { + DWORD dwOfnFlags = OFN_FILEMUSTEXIST | OFN_ENABLEHOOK; + if (lpIO->lpOIO->dwFlags & IOF_SHOWHELP) + dwOfnFlags |= OFN_SHOWHELP; + + uRet = (UINT)Browse(hDlg, lpIO->szFile, + fUseInitialDir ? szInitialDir : NULL, MAX_PATH, + IDS_FILTERS, dwOfnFlags, ID_BROWSE_INSERTFILE, (LPOFNHOOKPROC)HookDlgProc); + } + + // Only update if the file changed. + if (0 != uRet && 0 != lstrcmpi(szTemp, lpIO->szFile)) + { + SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, lpIO->szFile); + lpIO->fFileSelected=TRUE; + + if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode)) + { + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = TRUE; + UpdateClassIcon(hDlg, lpIO, NULL); + UpdateClassType(hDlg, lpIO, TRUE); + // auto set OK to be default button if valid file + SendMessage(hDlg, DM_SETDEFID, + (WPARAM)GetDlgItem(hDlg, IDOK), 0L); + SetFocus(GetDlgItem(hDlg, IDOK)); + } + else // filename is invalid - set focus back to ec + { + HWND hWnd; + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = FALSE; + hWnd = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY); + SetFocus(hWnd); + SendMessage(hWnd, EM_SETSEL, 0, -1); + } + + // Once we have a file, Display As Icon is always enabled + StandardEnableDlgItem(hDlg, IDC_IO_DISPLAYASICON, TRUE); + + // As well as OK + StandardEnableDlgItem(hDlg, IDOK, TRUE); + } + } + break; + + case IDC_IO_ADDCONTROL: + { + TCHAR szFileName[MAX_PATH]; + szFileName[0] = 0; + + // allow hook to customize + uRet = UStandardHook(lpIO, hDlg, uMsgAddControl, + MAX_PATH, (LPARAM)szFileName); + + if (0 == uRet) + { + DWORD dwOfnFlags = OFN_FILEMUSTEXIST | OFN_ENABLEHOOK; + if (lpIO->lpOIO->dwFlags & IOF_SHOWHELP) + dwOfnFlags |= OFN_SHOWHELP; + uRet = (UINT)Browse(hDlg, szFileName, NULL, MAX_PATH, + IDS_OCX_FILTERS, dwOfnFlags, ID_BROWSE_ADDCONTROL , (LPOFNHOOKPROC)HookDlgProc); + } + + if (0 != uRet) + { + // try to register the control DLL + HINSTANCE hInst = LoadLibrary(szFileName); + if (hInst == NULL) + { + PopupMessage(hDlg, IDS_ADDCONTROL, IDS_CANNOTLOADOCX, + MB_OK | MB_ICONEXCLAMATION); + break; + } + + HRESULT (FAR STDAPICALLTYPE* lpfn)(void); + (FARPROC&)lpfn = GetProcAddress(hInst, "DllRegisterServer"); + if (lpfn == NULL) + { + PopupMessage(hDlg, IDS_ADDCONTROL, IDS_NODLLREGISTERSERVER, + MB_OK | MB_ICONEXCLAMATION); + FreeLibrary(hInst); + break; + } + + if (FAILED((*lpfn)())) + { + PopupMessage(hDlg, IDS_ADDCONTROL, IDS_DLLREGISTERFAILED, + MB_OK | MB_ICONEXCLAMATION); + FreeLibrary(hInst); + break; + } + + // cleanup the DLL from memory + FreeLibrary(hInst); + + // registered successfully -- refill the list box + lpIO->bControlListFilled = FALSE; + lpIO->bObjectListFilled = FALSE; + URefillClassList(hDlg, lpIO); + } + } + break; + + case IDOK: + { + if ((HWND)lParam != GetFocus()) + SetFocus((HWND)lParam); + + // If the file name is clean (already validated), or + // if Create New is selected, then we can skip this part. + + if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) && + lpIO->fFileDirty) + { + if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode)) + { + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = TRUE; + UpdateClassIcon(hDlg, lpIO, NULL); + UpdateClassType(hDlg, lpIO, TRUE); + } + else // filename is invalid - set focus back to ec + { + HWND hWnd; + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = FALSE; + hWnd = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY); + SetFocus(hWnd); + SendMessage(hWnd, EM_SETSEL, 0, -1); + UpdateClassType(hDlg, lpIO, FALSE); + } + return TRUE; // eat this message + } + else if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) && + !lpIO->fFileValid) + { + // filename is invalid - set focus back to ec + HWND hWnd; + TCHAR szFile[MAX_PATH]; + + if (0 != GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, + szFile, MAX_PATH)) + { + OpenFileError(hDlg, lpIO->nErrCode, szFile); + } + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = FALSE; + hWnd = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY); + SetFocus(hWnd); + SendMessage(hWnd, EM_SETSEL, 0, -1); + UpdateClassType(hDlg, lpIO, FALSE); + return TRUE; // eat this message + } + + // Copy the necessary information back to the original struct + LPOLEUIINSERTOBJECT lpOIO = lpIO->lpOIO; + lpOIO->dwFlags = lpIO->dwFlags; + + if (lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL)) + { + HWND hListBox = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST); + UINT iCurSel = (UINT)SendMessage(hListBox, LB_GETCURSEL, 0, 0); + + if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON) + { + lpOIO->hMetaPict=(HGLOBAL)SendMessage(hListBox, + LB_GETITEMDATA, iCurSel, 0L); + + /* + * Set the item data to 0 here so that the cleanup + * code doesn't delete the metafile. + */ + SendMessage(hListBox, LB_SETITEMDATA, iCurSel, 0L); + } + else + lpOIO->hMetaPict = (HGLOBAL)NULL; + + TCHAR szBuffer[OLEUI_CCHKEYMAX+OLEUI_CCHCLSIDSTRING]; + SendMessage(hListBox, LB_GETTEXT, iCurSel, (LPARAM)szBuffer); + + LPTSTR lpszCLSID = PointerToNthField(szBuffer, 2, '\t'); +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszCLSID[OLEUI_CCHKEYMAX]; + ATOW(wszCLSID, lpszCLSID, OLEUI_CCHKEYMAX); + CLSIDFromString(wszCLSID, &lpOIO->clsid); +#else + CLSIDFromString(lpszCLSID, &lpOIO->clsid); +#endif + } + else // IOF_SELECTCREATEFROMFILE + { + if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON) + { + // get metafile here + lpOIO->hMetaPict = (HGLOBAL)SendDlgItemMessage( + hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); + } + else + lpOIO->hMetaPict = (HGLOBAL)NULL; + } + + GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, + lpIO->szFile, lpOIO->cchFile); + lstrcpyn(lpOIO->lpszFile, lpIO->szFile, lpOIO->cchFile); + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + } + break; + + case IDCANCEL: + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + + case IDC_OLEUIHELP: + PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_INSERTOBJECT, 0)); + break; + } + break; + + default: + if (lpIO && iMsg == lpIO->nBrowseHelpID) + { + PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_INSERTFILEBROWSE, 0)); + } + if (iMsg == uMsgBrowseOFN && + lpIO && lpIO->lpOIO && lpIO->lpOIO->hWndOwner) + { + SendMessage(lpIO->lpOIO->hWndOwner, uMsgBrowseOFN, wParam, lParam); + } + break; + } + + return FALSE; +} + +//+--------------------------------------------------------------------------- +// +// Function: CheckButton +// +// Synopsis: Handles checking the radio buttons +// +// Arguments: [hDlg] - dialog handle +// [iID] - ID of the button to check +// +// Returns: nothing +// +// History: 1-19-95 stevebl Created +// +// Notes: Used in place of CheckRadioButtons to avoid a GP fault under +// win32s that arises from IDC_IO_CREATENEW, IDC_IO_CREATEFROMFILE +// and IDC_IO_INSERTCONTROL not being contiguous. +// +//---------------------------------------------------------------------------- + +void CheckButton(HWND hDlg, int iID) +{ + CheckDlgButton(hDlg, IDC_IO_CREATENEW, iID == IDC_IO_CREATENEW ? 1 : 0); + CheckDlgButton(hDlg, IDC_IO_CREATEFROMFILE, iID == IDC_IO_CREATEFROMFILE ? 1 : 0); + CheckDlgButton(hDlg, IDC_IO_INSERTCONTROL, iID == IDC_IO_INSERTCONTROL ? 1 : 0); +} + + +/* + * FInsertObjectInit + * + * Purpose: + * WM_INITIDIALOG handler for the Insert Object dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ +BOOL FInsertObjectInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + // Copy the structure at lParam into our instance memory. + HFONT hFont; + LPINSERTOBJECT lpIO = (LPINSERTOBJECT)LpvStandardInit(hDlg, sizeof(INSERTOBJECT), &hFont); + + // PvStandardInit send a termination to us already. + if (NULL == lpIO) + return FALSE; + + LPOLEUIINSERTOBJECT lpOIO = (LPOLEUIINSERTOBJECT)lParam; + + // Save the original pointer and copy necessary information. + lpIO->lpOIO = lpOIO; + lpIO->nIDD = IDD_INSERTOBJECT; + lpIO->dwFlags = lpOIO->dwFlags; + lpIO->clsid = lpOIO->clsid; + + if ((lpOIO->lpszFile) && ('\0' != *lpOIO->lpszFile)) + lstrcpyn(lpIO->szFile, lpOIO->lpszFile, MAX_PATH); + else + *(lpIO->szFile) = '\0'; + + lpIO->hMetaPictFile = (HGLOBAL)NULL; + + // If we got a font, send it to the necessary controls. + if (NULL != hFont) + { + SendDlgItemMessage(hDlg, IDC_IO_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L); + SendDlgItemMessage(hDlg, IDC_IO_FILETYPE, WM_SETFONT, (WPARAM)hFont, 0L); + } + + // Initilize the file name display to cwd if we don't have any name. + if ('\0' == *(lpIO->szFile)) + { + TCHAR szCurDir[MAX_PATH]; + int nLen; + GetCurrentDirectory(MAX_PATH, szCurDir); + nLen = lstrlen(szCurDir); + if (nLen != 0 && szCurDir[nLen-1] != '\\') + lstrcat(szCurDir, _T("\\")); + SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szCurDir); + lpIO->fFileDirty = TRUE; // cwd is not a valid filename + } + else + { + SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, lpIO->szFile); + if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode)) + { + lpIO->fFileDirty = FALSE; + lpIO->fFileValid = TRUE; + } + else + { + lpIO->fFileDirty = TRUE; + lpIO->fFileValid = FALSE; + } + } + + // Initialize radio button and related controls + if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON) + { + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + lpIO->fAsIconNew = TRUE; + else + lpIO->fAsIconFile = TRUE; + } + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + CheckButton(hDlg, IDC_IO_CREATENEW); + if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) + CheckButton(hDlg, IDC_IO_CREATEFROMFILE); + if (lpIO->dwFlags & IOF_SELECTCREATECONTROL) + CheckButton(hDlg, IDC_IO_INSERTCONTROL); + CheckDlgButton(hDlg, IDC_IO_LINKFILE, (BOOL)(0L != (lpIO->dwFlags & IOF_CHECKLINK))); + + lpIO->dwFlags &= + ~(IOF_SELECTCREATENEW|IOF_SELECTCREATEFROMFILE|IOF_SELECTCREATECONTROL); + FToggleObjectSource(hDlg, lpIO, lpOIO->dwFlags & + (IOF_SELECTCREATENEW|IOF_SELECTCREATEFROMFILE|IOF_SELECTCREATECONTROL)); + + // Show or hide the help button + if (!(lpIO->dwFlags & IOF_SHOWHELP)) + StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE); + + // Show or hide the Change icon button + if (lpIO->dwFlags & IOF_HIDECHANGEICON) + DestroyWindow(GetDlgItem(hDlg, IDC_IO_CHANGEICON)); + + // Hide Insert Control button if necessary + if (!(lpIO->dwFlags & IOF_SHOWINSERTCONTROL)) + StandardShowDlgItem(hDlg, IDC_IO_INSERTCONTROL, SW_HIDE); + + // Initialize the result display + UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST)); + SetInsertObjectResults(hDlg, lpIO); + + // Change the caption + if (NULL!=lpOIO->lpszCaption) + SetWindowText(hDlg, lpOIO->lpszCaption); + + // Hide all DisplayAsIcon related controls if it should be disabled + if (lpIO->dwFlags & IOF_DISABLEDISPLAYASICON) + { + StandardShowDlgItem(hDlg, IDC_IO_DISPLAYASICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_IO_CHANGEICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_IO_ICONDISPLAY, SW_HIDE); + } + + lpIO->nBrowseHelpID = RegisterWindowMessage(HELPMSGSTRING); + + // All Done: call the hook with lCustData + UStandardHook(lpIO, hDlg, WM_INITDIALOG, wParam, lpOIO->lCustData); + + /* + * We either set focus to the listbox or the edit control. In either + * case we don't want Windows to do any SetFocus, so we return FALSE. + */ + return FALSE; +} + +/* + * URefillClassList + * + * Purpose: + * Fills the class list box with names as appropriate for the current + * flags. This function is called when the user changes the flags + * via the "exclusion" radio buttons. + * + * Note that this function removes any prior contents of the listbox. + * + * Parameters: + * hDlg HWND to the dialog box. + * lpIO pointer to LPINSERTOBJECT structure + * + * Return Value: + * UINT Number of strings added to the listbox, -1 on failure. + */ +UINT URefillClassList(HWND hDlg, LPINSERTOBJECT lpIO) +{ + OleDbgAssert(lpIO->dwFlags & (IOF_SELECTCREATECONTROL|IOF_SELECTCREATENEW)); + + // always the same dialog ID because they are swapped + HWND hList = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST); + + // determine if already filled + BOOL bFilled; + if (lpIO->dwFlags & IOF_SELECTCREATECONTROL) + bFilled = lpIO->bControlListFilled; + else + bFilled = lpIO->bObjectListFilled; + + if (!bFilled) + { + // fill the list + LPOLEUIINSERTOBJECT lpOIO = lpIO->lpOIO; + UINT uResult = UFillClassList(hList, lpOIO->cClsidExclude, lpOIO->lpClsidExclude, + (BOOL)(lpIO->dwFlags & IOF_VERIFYSERVERSEXIST), + (lpIO->dwFlags & IOF_SELECTCREATECONTROL)); + + // mark the list as filled + if (lpIO->dwFlags & IOF_SELECTCREATECONTROL) + lpIO->bControlListFilled = TRUE; + else + lpIO->bObjectListFilled = TRUE; + } + + // return number of items now in the list + return SendMessage(hList, LB_GETCOUNT, 0, 0); +} + + +/* + * UFillClassList + * + * Purpose: + * Enumerates available OLE object classes from the registration + * database and fills a listbox with those names. + * + * Note that this function removes any prior contents of the listbox. + * + * Parameters: + * hList HWND to the listbox to fill. + * cIDEx UINT number of CLSIDs to exclude in lpIDEx + * lpIDEx LPCLSID to CLSIDs to leave out of the listbox. + * fVerify BOOL indicating if we are to validate existence of + * servers before putting them in the list. + * + * Return Value: + * UINT Number of strings added to the listbox, -1 on failure. + */ + +UINT UFillClassList(HWND hList, UINT cIDEx, LPCLSID lpIDEx, BOOL fVerify, + BOOL fExcludeObjects) +{ + OleDbgAssert(hList != NULL); + + // Set the tab width in the list to push all the tabs off the side. + RECT rc; + GetClientRect(hList, &rc); + DWORD dw = GetDialogBaseUnits(); + rc.right =(8*rc.right)/LOWORD(dw); //Convert pixels to 2x dlg units. + SendMessage(hList, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&rc.right); + + LPTSTR pszExec = (LPTSTR)OleStdMalloc(OLEUI_CCHKEYMAX_SIZE*4); + if (NULL == pszExec) + return (UINT)-1; + + LPTSTR pszClass = pszExec+OLEUI_CCHKEYMAX; + LPTSTR pszKey = pszClass+OLEUI_CCHKEYMAX; + + // Open up the root key. + HKEY hKey; + LONG lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); + if ((LONG)ERROR_SUCCESS!=lRet) + { + OleStdFree((LPVOID)pszExec); + return (UINT)-1; + } + + // Clean out the existing strings. + SendMessage(hList, LB_RESETCONTENT, 0, 0L); + UINT cStrings = 0; + + while (TRUE) + { + BOOL bHaveCLSID = FALSE;// assume not yet (for handling of OLE1.0 compat case) + LPTSTR pszID = pszKey+OLEUI_CCHKEYMAX; + + lRet = RegEnumKey(hKey, cStrings++, pszClass, OLEUI_CCHKEYMAX_SIZE); + if ((LONG)ERROR_SUCCESS != lRet) + break; + + // Cheat on lstrcat by using lstrcpy after this string, saving time + UINT cch = lstrlen(pszClass); + + // Check for \NotInsertable. If this is found then this overrides + // all other keys; this class will NOT be added to the InsertObject + // list. + + lstrcpy(pszClass+cch, TEXT("\\NotInsertable")); + HKEY hKeyTemp = NULL; + lRet = RegOpenKey(hKey, pszClass, &hKeyTemp); + if (hKeyTemp != NULL) + RegCloseKey(hKeyTemp); + if ((LONG)ERROR_SUCCESS == lRet) + continue; // NotInsertable IS found--skip this class + + // Check for a \protocol\StdFileEditing\server entry. + lstrcpy(pszClass+cch, TEXT("\\protocol\\StdFileEditing\\server")); + DWORD dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, pszClass, pszKey, (LONG*)&dw); + if ((LONG)ERROR_SUCCESS == lRet) + { + // This is not a control -- skip it if excluding non-controls + if (fExcludeObjects) + continue; + + // Check if the EXE actually exists. By default we don't do this + // to bring up the dialog faster. If an application wants to be + // stringent, they can provide IOF_VERIFYSERVERSEXIST. + if (fVerify && !DoesFileExist(pszKey, OLEUI_CCHKEYMAX)) + continue; + + // get readable class name + dw = OLEUI_CCHKEYMAX_SIZE; + *(pszClass+cch) = 0; // set back to rootkey + lRet=RegQueryValue(hKey, pszClass, pszKey, (LONG*)&dw); + + // attempt to get clsid directly from registry + lstrcpy(pszClass+cch, TEXT("\\CLSID")); + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, pszClass, pszID, (LONG*)&dw); + if ((LONG)ERROR_SUCCESS == lRet) + bHaveCLSID = TRUE; + *(pszClass+cch) = 0; // set back to rootkey + } + else + { + // No \protocol\StdFileEditing\server entry. + + // Check for CLSID + lstrcpy(pszClass+cch, TEXT("\\CLSID")); + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, pszClass, pszID, (LONG*)&dw); + if ((LONG)ERROR_SUCCESS != lRet) + continue; // CLSID subkey not found + + // But it does have a CLSID entry so it's a control. + + // CLSID\ is 6, dw contains pszID length. + cch = 6 + ((UINT)dw/sizeof(TCHAR)) - 1; + lstrcpy(pszExec, TEXT("CLSID\\")); + lstrcpy(pszExec+6, pszID); + + // Check for CLISD\clsid\Control + // (needed for inclusion in the Insert Control list box) + + // fExcludeObjects is TRUE for the Insert Control box. + // It's FALSE for the Insert Object box. + + lstrcpy(pszExec+cch, TEXT("\\Control")); + hKeyTemp = NULL; + lRet = RegOpenKey(hKey, pszExec, &hKeyTemp); + if (hKeyTemp != NULL) + RegCloseKey(hKeyTemp); + if ((LONG)ERROR_SUCCESS != lRet && fExcludeObjects) + continue; + + // Check for CLSID\clsid\Insertable + // (needed for inclusion in the Insert Object list box) + + lstrcpy(pszExec+cch, TEXT("\\Insertable")); + hKeyTemp = NULL; + lRet = RegOpenKey(hKey, pszExec, &hKeyTemp); + if (hKeyTemp != NULL) + RegCloseKey(hKeyTemp); + if ((LONG)ERROR_SUCCESS != lRet && !fExcludeObjects) + continue; + + // Check \LocalServer32, LocalServer, and \InprocServer + + // Try LocalServer32 + lstrcpy(pszExec+cch, TEXT("\\LocalServer32")); + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw); + if ((LONG)ERROR_SUCCESS != lRet) + { + // Try LocalServer + lstrcpy(pszExec+cch, TEXT("\\LocalServer")); + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw); + if ((LONG)ERROR_SUCCESS != lRet) + { + // Try InprocServer32 + lstrcpy(pszExec+cch, TEXT("\\InProcServer32")); + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw); + if ((LONG)ERROR_SUCCESS != lRet) + { + // Try InprocServer + lstrcpy(pszExec+cch, TEXT("\\InProcServer")); + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw); + if ((LONG)ERROR_SUCCESS != lRet) + continue; + } + } + } + + if (fVerify && !DoesFileExist(pszKey, OLEUI_CCHKEYMAX)) + continue; + + *(pszExec+cch) = 0; //Remove \\*Server + dw = OLEUI_CCHKEYMAX_SIZE; + lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw); + if ((LONG)ERROR_SUCCESS!=lRet) + continue; + + bHaveCLSID = TRUE; + } + + // get CLSID to add to listbox. + CLSID clsid; + if (!bHaveCLSID) + { +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszClass[OLEUI_CCHKEYMAX]; + ATOW(wszClass, pszClass, OLEUI_CCHKEYMAX); + if (FAILED(CLSIDFromProgID(wszClass, &clsid))) + continue; + LPOLESTR wszID; + if (FAILED(StringFromCLSID(clsid, &wszID))) + continue; + UINT uLen = WTOALEN(wszID); + pszID = (LPTSTR) OleStdMalloc(uLen); + WTOA(pszID, wszID, uLen); +#else + if (FAILED(CLSIDFromProgID(pszClass, &clsid))) + continue; + if (FAILED(StringFromCLSID(clsid, &pszID))) + continue; +#endif + } + else + { +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszID[OLEUI_CCHKEYMAX]; + ATOW(wszID, pszID, OLEUI_CCHKEYMAX); + if (FAILED(CLSIDFromString(wszID, &clsid))) + continue; +#else + if (FAILED(CLSIDFromString(pszID, &clsid))) + continue; +#endif + } + + // Note: 'continue' after this point would leak memory so we don't use them! + + // check if this CLSID is in the exclusion list. + BOOL fExclude = FALSE; + for (UINT i=0; i < cIDEx; i++) + { + if (IsEqualCLSID(clsid, lpIDEx[i])) + { + fExclude=TRUE; + break; + } + } + + // don't add objects without names + if (lstrlen(pszKey) > 0 && !fExclude) + { + // We got through all the conditions, add the string. + if (LB_ERR == SendMessage(hList, LB_FINDSTRING, 0, (LPARAM)pszKey)) + { + pszKey[cch = lstrlen(pszKey)] = '\t'; + lstrcpy(pszKey+cch+1, pszID); + SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)pszKey); + } + } + + if (!bHaveCLSID) + OleStdFree((LPVOID)pszID); + } + + // Select the first item by default + SendMessage(hList, LB_SETCURSEL, 0, 0L); + RegCloseKey(hKey); + OleStdFree((LPVOID)pszExec); + + return cStrings; +} + +/* + * FToggleObjectSource + * + * Purpose: + * Handles enabling, disabling, showing, and flag manipulation when the + * user changes between Create New, Insert File, and Link File in the + * Insert Object dialog. + * + * Parameters: + * hDlg HWND of the dialog + * lpIO LPINSERTOBJECT pointing to the dialog structure + * dwOption DWORD flag indicating the option just selected: + * IOF_SELECTCREATENEW or IOF_SELECTCREATEFROMFILE + * + * Return Value: + * BOOL TRUE if the option was already selected, FALSE otherwise. + */ + +BOOL FToggleObjectSource(HWND hDlg, LPINSERTOBJECT lpIO, DWORD dwOption) +{ + // Skip all of this if we're already selected. + if (lpIO->dwFlags & dwOption) + return TRUE; + + // if we're switching from "from file" to "create new" and we've got + // an icon for "from file", then we need to save it so that we can + // show it if the user reselects "from file". + + if ((IOF_SELECTCREATENEW == dwOption) && + (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)) + { + lpIO->hMetaPictFile = (HGLOBAL)SendDlgItemMessage(hDlg, + IDC_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); + } + + /* + * 1. Change the Display As Icon checked state to reflect the + * selection for this option, stored in the fAsIcon* flags. + */ + BOOL fTemp; + if (IOF_SELECTCREATENEW == dwOption) + fTemp = lpIO->fAsIconNew; + else if (IOF_SELECTCREATEFROMFILE == dwOption) + fTemp = lpIO->fAsIconFile; + else + fTemp = FALSE; + + if (fTemp) + lpIO->dwFlags |= IOF_CHECKDISPLAYASICON; + else + lpIO->dwFlags &= ~IOF_CHECKDISPLAYASICON; + + CheckDlgButton(hDlg, IDC_IO_DISPLAYASICON, + (BOOL)(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON))); + + StandardEnableDlgItem(hDlg, IDC_IO_CHANGEICON, fTemp); + + /* + * Display Icon: Enabled on Create New or on Create from File if + * there is a selected file. + */ + if (IOF_SELECTCREATENEW == dwOption) + fTemp = TRUE; + else if (IOF_SELECTCREATEFROMFILE == dwOption) + fTemp = lpIO->fFileSelected; + else + fTemp = FALSE; + + if (IOF_SELECTCREATECONTROL == dwOption) + StandardShowDlgItem(hDlg, IDC_IO_DISPLAYASICON, SW_HIDE); + else if (!(lpIO->dwFlags & IOF_DISABLEDISPLAYASICON)) + StandardShowDlgItem(hDlg, IDC_IO_DISPLAYASICON, SW_SHOW); + + StandardEnableDlgItem(hDlg, IDC_IO_DISPLAYASICON, fTemp); + + // OK and Link follow the same enabling as Display As Icon. + StandardEnableDlgItem(hDlg, IDOK, + fTemp || IOF_SELECTCREATECONTROL == dwOption); + StandardEnableDlgItem(hDlg, IDC_IO_LINKFILE, fTemp); + + // Enable Browse... when Create from File is selected. + fTemp = (IOF_SELECTCREATEFROMFILE != dwOption); + StandardEnableDlgItem(hDlg, IDC_IO_FILE, !fTemp); + StandardEnableDlgItem(hDlg, IDC_IO_FILEDISPLAY, !fTemp); + + // Switch Object Type & Control Type listboxes if necessary + HWND hWnd1 = NULL, hWnd2 = NULL; + if (lpIO->bControlListActive && IOF_SELECTCREATENEW == dwOption) + { + hWnd1 = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST); + hWnd2 = GetDlgItem(hDlg, IDC_IO_CONTROLTYPELIST); + SetWindowLong(hWnd1, GWL_ID, IDC_IO_CONTROLTYPELIST); + SetWindowLong(hWnd2, GWL_ID, IDC_IO_OBJECTTYPELIST); + lpIO->bControlListActive = FALSE; + } + else if (!lpIO->bControlListActive && IOF_SELECTCREATECONTROL == dwOption) + { + hWnd1 = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST); + hWnd2 = GetDlgItem(hDlg, IDC_IO_CONTROLTYPELIST); + SetWindowLong(hWnd1, GWL_ID, IDC_IO_CONTROLTYPELIST); + SetWindowLong(hWnd2, GWL_ID, IDC_IO_OBJECTTYPELIST); + lpIO->bControlListActive = TRUE; + } + + // Clear out any existing selection flags and set the new one + DWORD dwTemp = IOF_SELECTCREATENEW | IOF_SELECTCREATEFROMFILE | + IOF_SELECTCREATECONTROL; + lpIO->dwFlags = (lpIO->dwFlags & ~dwTemp) | dwOption; + + if (dwOption & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL)) + { + // refill class list box if necessary + if ((lpIO->bControlListActive && !lpIO->bControlListFilled) || + (!lpIO->bControlListActive && !lpIO->bObjectListFilled)) + { + URefillClassList(hDlg, lpIO); + } + } + + if (hWnd1 != NULL && hWnd2 != NULL) + { + ShowWindow(hWnd1, SW_HIDE); + ShowWindow(hWnd2, SW_SHOW); + } + + /* + * Switch between Object Type listbox on Create New and + * file buttons on others. + */ + UINT uTemp = (fTemp) ? SW_SHOWNORMAL : SW_HIDE; + StandardShowDlgItem(hDlg, IDC_IO_OBJECTTYPELIST, uTemp); + StandardShowDlgItem(hDlg, IDC_IO_OBJECTTYPETEXT, uTemp); + + uTemp = (fTemp) ? SW_HIDE : SW_SHOWNORMAL; + StandardShowDlgItem(hDlg, IDC_IO_FILETEXT, uTemp); + StandardShowDlgItem(hDlg, IDC_IO_FILETYPE, uTemp); + StandardShowDlgItem(hDlg, IDC_IO_FILEDISPLAY, uTemp); + StandardShowDlgItem(hDlg, IDC_IO_FILE, uTemp); + + // Link is always hidden if IOF_DISABLELINK is set. + if (IOF_DISABLELINK & lpIO->dwFlags) + uTemp = SW_HIDE; + + StandardShowDlgItem(hDlg, IDC_IO_LINKFILE, uTemp); //last use of uTemp + + // Remove add button when not in Insert control mode + uTemp = (IOF_SELECTCREATECONTROL == dwOption) ? SW_SHOW : SW_HIDE; + StandardShowDlgItem(hDlg, IDC_IO_ADDCONTROL, uTemp); + + /* + * Show or hide controls as appropriate. Do the icon + * display last because it will take some time to repaint. + * If we do it first then the dialog looks too sluggish. + */ + + int i = (lpIO->dwFlags & IOF_CHECKDISPLAYASICON) ? SW_SHOWNORMAL : SW_HIDE; + StandardShowDlgItem(hDlg, IDC_IO_CHANGEICON, i); + StandardShowDlgItem(hDlg, IDC_IO_ICONDISPLAY, i); + + // Change result display + SetInsertObjectResults(hDlg, lpIO); + + /* + * For Create New, twiddle the listbox to think we selected it + * so it updates the icon from the object type. set the focus + * to the list box. + * + * For Insert or Link file, set the focus to the filename button + * and update the icon if necessary. + */ + if (fTemp) + { + UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST)); + SetFocus(GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST)); + } + else + { + if (lpIO->fAsIconFile && (NULL != lpIO->hMetaPictFile) ) + { + SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGESET, 0, + (LPARAM)lpIO->hMetaPictFile); + lpIO->hMetaPictFile = 0; + } + else + { + UpdateClassIcon(hDlg, lpIO, NULL); + } + SetFocus(GetDlgItem(hDlg, IDC_IO_FILE)); + } + + return FALSE; +} + + +/* + * UpdateClassType + * + * Purpose: + * Updates static text control to reflect current file type. Assumes + * a valid filename. + * + * Parameters + * hDlg HWND of the dialog box. + * lpIO LPINSERTOBJECT pointing to the dialog structure + * fSet TRUE to set the text, FALSE to explicitly clear it + * + * Return Value: + * None + */ + +void UpdateClassType(HWND hDlg, LPINSERTOBJECT lpIO, BOOL fSet) +{ + LPTSTR lpszFileType = NULL; + if (fSet) + { + TCHAR szFileName[MAX_PATH]; + GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szFileName, MAX_PATH); + + CLSID clsid; +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszFileName[MAX_PATH]; + LPOLESTR wszFileType = NULL; + ATOW(wszFileName, szFileName, MAX_PATH); + if (NOERROR == GetClassFile(wszFileName, &clsid)) + OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &wszFileType); + if (NULL != wszFileType) + { + UINT uLen = WTOALEN(wszFileType); + lpszFileType = (LPTSTR)OleStdMalloc(uLen); + if (NULL != lpszFileType) + { + WTOA(lpszFileType, wszFileType, uLen); + } + OleStdFree(wszFileType); + } +#else + if (NOERROR == GetClassFile(szFileName, &clsid)) + OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &lpszFileType); +#endif + } + SetDlgItemText(hDlg, IDC_IO_FILETYPE, lpszFileType); + OleStdFree(lpszFileType); +} + + +/* + * UpdateClassIcon + * + * Purpose: + * Handles LBN_SELCHANGE for the Object Type listbox. On a selection + * change, we extract an icon from the server handling the currently + * selected object type using the utility function HIconFromClass. + * Note that we depend on the behavior of FillClassList to stuff the + * object class after a tab in the listbox string that we hide from + * view (see WM_INITDIALOG). + * + * Parameters + * hDlg HWND of the dialog box. + * lpIO LPINSERTOBJECT pointing to the dialog structure + * hList HWND of the Object Type listbox. + * + * Return Value: + * None + */ + +static void UpdateClassIcon(HWND hDlg, LPINSERTOBJECT lpIO, HWND hList) +{ + // If Display as Icon is not selected, exit + if (!(lpIO->dwFlags & IOF_CHECKDISPLAYASICON)) + return; + + /* + * When we change object type selection, get the new icon for that + * type into our structure and update it in the display. We use the + * class in the listbox when Create New is selected or the association + * with the extension in Create From File. + */ + + DWORD cb = MAX_PATH; + UINT iSel; + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + { + iSel = (UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L); + + if (LB_ERR==(int)iSel) + return; + + // Check to see if we've already got the hMetaPict for this item + DWORD dwRet = SendMessage(hList, LB_GETITEMDATA, (WPARAM)iSel, 0L); + + HGLOBAL hMetaPict=(HGLOBAL)(UINT)dwRet; + if (hMetaPict) + { + // Yep, we've already got it, so just display it and return. + SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGESET, + 0, (LPARAM)hMetaPict); + return; + } + iSel = (UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L); + if (LB_ERR==(int)iSel) + return; + + // Allocate a string to hold the entire listbox string + cb = SendMessage(hList, LB_GETTEXTLEN, iSel, 0L); + } + + LPTSTR pszName = (LPTSTR)OleStdMalloc((cb+1)*sizeof(TCHAR)); + if (NULL == pszName) + return; + *pszName = 0; + + // Get the clsid we want. + HGLOBAL hMetaPict; + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + { + // Grab the classname string from the list + SendMessage(hList, LB_GETTEXT, iSel, (LONG)pszName); + + // Set pointer to CLSID (string) + LPTSTR pszCLSID = PointerToNthField(pszName, 2, '\t'); + + // Get CLSID from the string and then accociated icon +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszCLSID[OLEUI_CCHKEYMAX]; + ATOW(wszCLSID, pszCLSID, OLEUI_CCHKEYMAX); + CLSIDFromString(wszCLSID, &lpIO->clsid); +#else + CLSIDFromString(pszCLSID, &lpIO->clsid); +#endif + hMetaPict = OleGetIconOfClass(lpIO->clsid, NULL, TRUE); + } + + else + { + // Get the class from the filename + GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, pszName, MAX_PATH); +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszName[MAX_PATH]; + ATOW(wszName, pszName, MAX_PATH); + hMetaPict = OleGetIconOfFile(wszName, + lpIO->dwFlags & IOF_CHECKLINK ? TRUE : FALSE); +#else + hMetaPict = OleGetIconOfFile(pszName, + lpIO->dwFlags & IOF_CHECKLINK ? TRUE : FALSE); +#endif + } + + // Replace the current display with this new one. + SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGESET, + 0, (LPARAM)hMetaPict); + + // Enable or disable "Change Icon" button depending on whether + // we've got a valid filename or not. + StandardEnableDlgItem(hDlg, IDC_IO_CHANGEICON, hMetaPict ? TRUE : FALSE); + + // Save the hMetaPict so that we won't have to re-create + if (lpIO->dwFlags & IOF_SELECTCREATENEW) + SendMessage(hList, LB_SETITEMDATA, (WPARAM)iSel, (LPARAM)hMetaPict); + + OleStdFree(pszName); +} + + +/* + * SetInsertObjectResults + * + * Purpose: + * Centralizes setting of the Result and icon displays in the Insert Object + * dialog. Handles loading the appropriate string from the module's + * resources and setting the text, displaying the proper result picture, + * and showing the proper icon. + * + * Parameters: + * hDlg HWND of the dialog box so we can access controls. + * lpIO LPINSERTOBJECT in which we assume that the + * current radiobutton and Display as Icon selections + * are set. We use the state of those variables to + * determine which string we use. + * + * Return Value: + * None + */ + +void SetInsertObjectResults(HWND hDlg, LPINSERTOBJECT lpIO) +{ + /* + * We need scratch memory for loading the stringtable string, loading + * the object type from the listbox, and constructing the final string. + * We therefore allocate three buffers as large as the maximum message + * length (512) plus the object type, guaranteeing that we have enough + * in all cases. + */ + UINT i = (UINT)SendDlgItemMessage(hDlg, IDC_IO_OBJECTTYPELIST, LB_GETCURSEL, 0, 0L); + + UINT cch = 512; + + if (i != LB_ERR) + { + cch += (UINT)SendDlgItemMessage(hDlg, IDC_IO_OBJECTTYPELIST, LB_GETTEXTLEN, i, 0L); + } + + LPTSTR pszTemp= (LPTSTR)OleStdMalloc((DWORD)(4*cch)*sizeof(TCHAR)); + if (NULL == pszTemp) + return; + + LPTSTR psz1 = pszTemp; + LPTSTR psz2 = psz1+cch; + LPTSTR psz3 = psz2+cch; + LPTSTR psz4 = psz3+cch; + + BOOL fAsIcon = (0L != (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)); + UINT iImage, iString1, iString2; + + if (lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL)) + { + iString1 = fAsIcon ? IDS_IORESULTNEWICON : IDS_IORESULTNEW; + iString2 = 0; + iImage = fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED; + } + + if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) + { + // Pay attention to Link checkbox + if (lpIO->dwFlags & IOF_CHECKLINK) + { + iString1 = fAsIcon ? IDS_IORESULTLINKFILEICON1 : IDS_IORESULTLINKFILE1; + iString2 = fAsIcon ? IDS_IORESULTLINKFILEICON2 : IDS_IORESULTLINKFILE2; + iImage =fAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK; + } + else + { + iString1 = IDS_IORESULTFROMFILE1; + iString2 = fAsIcon ? IDS_IORESULTFROMFILEICON2 : IDS_IORESULTFROMFILE2; + iImage =fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED; + } + } + + // Default is an empty string. + *psz1=0; + + if (0 != LoadString(_g_hOleStdResInst, iString1, psz1, cch)) + { + // Load second string, if necessary + if (0 != iString2 && + 0 != LoadString(_g_hOleStdResInst, iString2, psz4, cch)) + { + lstrcat(psz1, psz4); // concatenate strings together. + } + + // In Create New, do the extra step of inserting the object type string + if (lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL)) + { + if (i == LB_ERR) + { + SetDlgItemText(hDlg, IDC_IO_RESULTTEXT, NULL); + + // Change the image. + SendDlgItemMessage(hDlg, IDC_IO_RESULTIMAGE, RIM_IMAGESET, RESULTIMAGE_NONE, 0L); + + OleStdFree((LPVOID)pszTemp); + return; + } + + SendDlgItemMessage(hDlg, IDC_IO_OBJECTTYPELIST, LB_GETTEXT, i, (LONG)psz2); + + // Null terminate at any tab (before the classname) + LPTSTR pszT = psz2; + while ('\t' != *pszT && 0 != *pszT) + pszT++; + *pszT=0; + + // Build the string and point psz1 to it. + wsprintf(psz3, psz1, psz2); + psz1 = psz3; + } + } + + // If LoadString failed, we simply clear out the results (*psz1=0 above) + SetDlgItemText(hDlg, IDC_IO_RESULTTEXT, psz1); + + // Go change the image and Presto! There you have it. + SendDlgItemMessage(hDlg, IDC_IO_RESULTIMAGE, RIM_IMAGESET, iImage, 0L); + + OleStdFree((LPVOID)pszTemp); +} + +/* + * FValidateInsertFile + * + * Purpose: + * Given a possibly partial pathname from the file edit control, + * attempt to locate the file and if found, store the full path + * in the edit control IDC_IO_FILEDISPLAY. + * + * Parameters: + * hDlg HWND of the dialog box. + * fTellUser BOOL TRUE if function should tell user, FALSE if + * function should validate silently. + * + * Return Value: + * BOOL TRUE if the file is acceptable, FALSE otherwise. + */ + +BOOL FValidateInsertFile(HWND hDlg, BOOL fTellUser, UINT FAR* lpnErrCode) +{ + *lpnErrCode = 0; + + /* + * To validate we attempt OpenFile on the string. If OpenFile + * fails then we display an error. If not, OpenFile will store + * the complete path to that file in the OFSTRUCT which we can + * then stuff in the edit control. + */ + TCHAR szFile[MAX_PATH]; + if (0 == GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szFile, MAX_PATH)) + return FALSE; // #4569 : return FALSE when there is no text in ctl + + // if file is currently open (ie. sharing violation) OleCreateFromFile + // and OleCreateLinkToFile can still succeed; do not consider it an + // error. + if (!DoesFileExist(szFile, MAX_PATH)) + { + *lpnErrCode = ERROR_FILE_NOT_FOUND; + if (fTellUser) + OpenFileError(hDlg, ERROR_FILE_NOT_FOUND, szFile); + return FALSE; + } + + // get full pathname, since the file exists + TCHAR szPath[MAX_PATH]; + LPTSTR lpszDummy; + GetFullPathName(szFile, sizeof(szPath)/sizeof(TCHAR), szPath, &lpszDummy); + SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szPath); + + return TRUE; +} + + +/* + * InsertObjectCleanup + * + * Purpose: + * Clears cached icon metafiles from those stored in the listbox. + * + * Parameters: + * hDlg HWND of the dialog. + * + * Return Value: + * None + */ + +void InsertObjectCleanup(HWND hDlg) +{ + HWND hList = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST); + UINT iItems= (UINT)SendMessage(hList, LB_GETCOUNT, 0, 0L); + for (UINT i = 0; i < iItems; i++) + { + LRESULT dwRet = SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L); + HGLOBAL hMetaPict=(HGLOBAL)(UINT)dwRet; + if (hMetaPict) + OleUIMetafilePictIconFree(hMetaPict); + } +} diff --git a/private/ole2ui32/links.cpp b/private/ole2ui32/links.cpp new file mode 100644 index 000000000..68b160020 --- /dev/null +++ b/private/ole2ui32/links.cpp @@ -0,0 +1,1537 @@ +/* + * links.c + * + * Implements the OleUIEditLinks function which invokes the complete + * Edit Links dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "common.h" +#include "utility.h" +#include <commdlg.h> +#include <dlgs.h> +#include <stdlib.h> + +OLEDBGDATA + +// INTERNAL INFORMATION STARTS HERE +#define OLEUI_SZMAX 255 +#define LINKTYPELEN 30 // was 9, now I've more than tripled it +#define szNULL TEXT("\0") + +typedef UINT (CALLBACK* COMMDLGHOOKPROC)(HWND, UINT, WPARAM, LPARAM); + +// Internally used structure + +typedef struct tagLINKINFO +{ + DWORD dwLink; // app specific identifier of a link + LPTSTR lpszDisplayName; // file based part of name + LPTSTR lpszItemName; // object part of name + LPTSTR lpszShortFileName; // filename without path + LPTSTR lpszShortLinkType; // Short link type - progID + LPTSTR lpszFullLinkType; // Full link type - user friendly name + LPTSTR lpszAMX; // Is the link auto (A) man (M) or dead (X) + ULONG clenFileName; // count of file part of mon. + BOOL fSourceAvailable; // bound or not - on boot assume yes?? + BOOL fIsAuto; // 1 =automatic, 0=manual update + BOOL fIsMarked; // 1 = marked, 0 = not + BOOL fDontFree; // Don't free this data since it's being reused + BOOL fIsSelected; // item selected or to be selected +} LINKINFO, FAR* LPLINKINFO; + +typedef struct tagEDITLINKS +{ + // Keep this item first as the Standard* functions depend on it here. + LPOLEUIEDITLINKS lpOEL; // Original structure passed. + UINT nIDD; // IDD of dialog (used for help info) + + BOOL fClose; // Does the button read cancel (0) or + // close (1)? + BOOL fItemsExist; // TRUE, items in lbox, FALSE, none + UINT nChgSrcHelpID; // ID for Help callback from ChangeSrc dlg + TCHAR szClose[50]; // Text for Close button + // (when Cancel button gets renamed) + int nColPos[3]; // tab positions for list box + int nHeightLine; // height of each line in owner draw listbox + int nMaxCharWidth; // maximim width of text in owner draw listbox + +} EDITLINKS, *PEDITLINKS, FAR *LPEDITLINKS; + +// Internal function prototypes +// LINKS.CPP + +BOOL CALLBACK EditLinksDialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL FEditLinksInit(HWND, WPARAM, LPARAM); +BOOL Container_ChangeSource(HWND, LPEDITLINKS); +HRESULT Container_AutomaticManual(HWND, BOOL, LPEDITLINKS); +HRESULT CancelLink(HWND, LPEDITLINKS); +HRESULT Container_UpdateNow(HWND, LPEDITLINKS); +HRESULT Container_OpenSource(HWND, LPEDITLINKS); +int AddLinkLBItem(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPLINKINFO lpLI, + BOOL fGetSelected); +VOID BreakString(LPLINKINFO); +int GetSelectedItems(HWND, int FAR* FAR*); +VOID InitControls(HWND hDlg, LPEDITLINKS lpEL); +VOID UpdateLinkLBItem(HWND hListBox, int nIndex, LPEDITLINKS lpEL, BOOL bSelect); +VOID ChangeAllLinks(HWND hLIstBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPTSTR lpszFrom, LPTSTR lpszTo); +int LoadLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr); +VOID RefreshLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr); + + +/* +* OleUIEditLinks +* +* Purpose: +* Invokes the standard OLE Edit Links dialog box allowing the user +* to manipulate ole links (delete, update, change source, etc). +* +* Parameters: +* lpEL LPOLEUIEditLinks pointing to the in-out structure +* for this dialog. +* +* Return Value: +* UINT One of the following codes, indicating success or error: +* OLEUI_SUCCESS Success +* OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong +*/ +STDAPI_(UINT) OleUIEditLinks(LPOLEUIEDITLINKS lpEL) +{ + HGLOBAL hMemDlg = NULL; + UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpEL, sizeof(OLEUIEDITLINKS), + &hMemDlg); + + if (OLEUI_SUCCESS != uRet) + return uRet; + + // Validate interface. + if (NULL == lpEL->lpOleUILinkContainer) + { + uRet = OLEUI_ELERR_LINKCNTRNULL; + } + else if(IsBadReadPtr(lpEL->lpOleUILinkContainer, sizeof(IOleUILinkContainer))) + { + uRet = OLEUI_ELERR_LINKCNTRINVALID; + } + + if (OLEUI_SUCCESS != uRet) + { + return(uRet); + } + + UINT nIDD = bWin4 ? IDD_EDITLINKS4 : IDD_EDITLINKS; + + // Now that we've validated everything, we can invoke the dialog. + uRet = UStandardInvocation(EditLinksDialogProc, (LPOLEUISTANDARD)lpEL, + hMemDlg, MAKEINTRESOURCE(nIDD)); + return uRet; +} + +/* +* EditLinksDialogProc +* +* Purpose: +* Implements the OLE Edit Links dialog as invoked through the +* OleUIEditLinks function. +* +* Parameters: +* Standard +* +* Return Value: +* Standard +*/ +BOOL CALLBACK EditLinksDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + // Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + // This will fail under WM_INITDIALOG, where we allocate it. + UINT uRet = 0; + LPEDITLINKS lpEL = (LPEDITLINKS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet); + + // If the hook processed the message, we're done. + if (0 != uRet) + return (BOOL)uRet; + + //Process help message from secondary dialog + if (iMsg == uMsgHelp) + { + PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp, wParam, lParam); + return FALSE; + } + + // Process the temination message + if (iMsg == uMsgEndDialog) + { + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) + { + case WM_DESTROY: + if (lpEL) + { + StandardCleanup(lpEL, hDlg); + } + break; + case WM_INITDIALOG: + return FEditLinksInit(hDlg, wParam, lParam); + + case WM_MEASUREITEM: + { + LPMEASUREITEMSTRUCT lpMIS = (LPMEASUREITEMSTRUCT)lParam; + int nHeightLine; + + if (lpEL && lpEL->nHeightLine != -1) + { + // use cached height + nHeightLine = lpEL->nHeightLine; + } + else + { + HFONT hFont; + HDC hDC; + TEXTMETRIC tm; + + hFont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0L); + + if (hFont == NULL) + hFont = (HFONT)GetStockObject(SYSTEM_FONT); + + hDC = GetDC(hDlg); + hFont = (HFONT)SelectObject(hDC, hFont); + + GetTextMetrics(hDC, &tm); + nHeightLine = tm.tmHeight; + + if (lpEL) + { + lpEL->nHeightLine = nHeightLine; + lpEL->nMaxCharWidth = tm.tmMaxCharWidth; + } + ReleaseDC(hDlg, hDC); + } + lpMIS->itemHeight = nHeightLine; + } + break; + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam; + LPLINKINFO lpLI = (LPLINKINFO)lpDIS->itemData; + + if ((int)lpDIS->itemID < 0) + break; + + if ((ODA_DRAWENTIRE | ODA_SELECT) & lpDIS->itemAction) + { + HBRUSH hbr; + COLORREF crText; + if (ODS_SELECTED & lpDIS->itemState) + { + /*Get proper txt colors */ + crText = SetTextColor(lpDIS->hDC, + GetSysColor(COLOR_HIGHLIGHTTEXT)); + hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); + lpLI->fIsSelected = TRUE; + } + else + { + hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW)); + lpLI->fIsSelected = FALSE; + } + + FillRect(lpDIS->hDC, &lpDIS->rcItem, hbr); + DeleteObject(hbr); + + int nOldBkMode = SetBkMode(lpDIS->hDC, TRANSPARENT); + + RECT rcClip; + if (lpLI->lpszDisplayName) + { + TCHAR szTemp[MAX_PATH]; + lstrcpy(szTemp, lpLI->lpszDisplayName); + LPTSTR lpsz = ChopText( + lpDIS->hwndItem, + lpEL->nColPos[1] - lpEL->nColPos[0] + - (lpEL->nMaxCharWidth > 0 ? + lpEL->nMaxCharWidth : 5), + szTemp, 0 + ); + rcClip.left = lpDIS->rcItem.left + lpEL->nColPos[0]; + rcClip.top = lpDIS->rcItem.top; + rcClip.right = lpDIS->rcItem.left + lpEL->nColPos[1] + - (lpEL->nMaxCharWidth > 0 ? + lpEL->nMaxCharWidth : 5); + rcClip.bottom = lpDIS->rcItem.bottom; + ExtTextOut( + lpDIS->hDC, + rcClip.left, + rcClip.top, + ETO_CLIPPED, + (LPRECT)&rcClip, + lpsz, + lstrlen(lpsz), + NULL + ); + } + if (lpLI->lpszShortLinkType) + { + rcClip.left = lpDIS->rcItem.left + lpEL->nColPos[1]; + rcClip.top = lpDIS->rcItem.top; + rcClip.right = lpDIS->rcItem.left + lpEL->nColPos[2] + - (lpEL->nMaxCharWidth > 0 ? + lpEL->nMaxCharWidth : 5); + rcClip.bottom = lpDIS->rcItem.bottom; + ExtTextOut( + lpDIS->hDC, + rcClip.left, + rcClip.top, + ETO_CLIPPED, + (LPRECT)&rcClip, + lpLI->lpszShortLinkType, + lstrlen(lpLI->lpszShortLinkType), + NULL + ); + } + if (lpLI->lpszAMX) + { + rcClip.left = lpDIS->rcItem.left + lpEL->nColPos[2]; + rcClip.top = lpDIS->rcItem.top; + rcClip.right = lpDIS->rcItem.right; + rcClip.bottom = lpDIS->rcItem.bottom; + ExtTextOut( + lpDIS->hDC, + rcClip.left, + rcClip.top, + ETO_CLIPPED, + (LPRECT)&rcClip, + lpLI->lpszAMX, + lstrlen(lpLI->lpszAMX), + NULL + ); + } + + SetBkMode(lpDIS->hDC, nOldBkMode); + + // restore orig colors if we changed them + if (ODS_SELECTED & lpDIS->itemState) + SetTextColor(lpDIS->hDC, crText); + + } + if (ODA_FOCUS & lpDIS->itemAction) + DrawFocusRect(lpDIS->hDC, &lpDIS->rcItem); + } + return TRUE; + + case WM_DELETEITEM: + { + LPDELETEITEMSTRUCT lpDIS = (LPDELETEITEMSTRUCT)lParam; + UINT idCtl = wParam; + LPLINKINFO lpLI = (LPLINKINFO)lpDIS->itemData; + + if (lpLI->lpszDisplayName) + OleStdFree((LPVOID)lpLI->lpszDisplayName); + if (lpLI->lpszShortLinkType) + OleStdFree((LPVOID)lpLI->lpszShortLinkType); + if (lpLI->lpszFullLinkType) + OleStdFree((LPVOID)lpLI->lpszFullLinkType); + + /* The ChangeSource processing reuses allocated space for + ** links that have been modified. + */ + // Don't free the LINKINFO for the changed links + if (lpLI->fDontFree) + lpLI->fDontFree = FALSE; + else + { + if (lpLI->lpszAMX) + OleStdFree((LPVOID)lpLI->lpszAMX); + OleStdFree((LPVOID)lpLI); + } + } + return TRUE; + + case WM_COMPAREITEM: + { + LPCOMPAREITEMSTRUCT lpCIS = (LPCOMPAREITEMSTRUCT)lParam; + LPLINKINFO lpLI1 = (LPLINKINFO)lpCIS->itemData1; + LPLINKINFO lpLI2 = (LPLINKINFO)lpCIS->itemData2; + + // Sort list entries by DisplayName + return lstrcmp(lpLI1->lpszDisplayName, lpLI2->lpszDisplayName); + } + + case WM_COMMAND: + switch (wID) + { + case IDC_EL_CHANGESOURCE: + { + BOOL fRet = Container_ChangeSource(hDlg, lpEL); + if (!fRet) + PopupMessage(hDlg, IDS_LINKS, IDS_FAILED, + MB_ICONEXCLAMATION | MB_OK); + InitControls(hDlg, lpEL); + } + break; + + case IDC_EL_AUTOMATIC: + { + CheckDlgButton(hDlg, IDC_EL_AUTOMATIC, 1); + CheckDlgButton(hDlg, IDC_EL_MANUAL, 0); + + HRESULT hErr = Container_AutomaticManual(hDlg, TRUE, lpEL); + if (hErr != NOERROR) + PopupMessage(hDlg, IDS_LINKS, IDS_FAILED, + MB_ICONEXCLAMATION | MB_OK); + + InitControls(hDlg, lpEL); + } + break; + + case IDC_EL_MANUAL: + { + CheckDlgButton(hDlg, IDC_EL_MANUAL, 1); + CheckDlgButton(hDlg, IDC_EL_AUTOMATIC, 0); + + HRESULT hErr = Container_AutomaticManual(hDlg, FALSE, lpEL); + if (hErr != NOERROR) + PopupMessage(hDlg, IDS_LINKS, IDS_FAILED, + MB_ICONEXCLAMATION | MB_OK); + + InitControls(hDlg, lpEL); + } + break; + + case IDC_EL_CANCELLINK: + CancelLink(hDlg,lpEL); + InitControls(hDlg, lpEL); + break; + + case IDC_EL_UPDATENOW: + Container_UpdateNow(hDlg, lpEL); + InitControls(hDlg, lpEL); + break; + + case IDC_EL_OPENSOURCE: + { + HRESULT hErr = Container_OpenSource(hDlg, lpEL); + if (hErr != NOERROR) + { + InitControls(hDlg, lpEL); + // Don't close dialog + break; + } + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + } // fall through + + case IDC_EL_LINKSLISTBOX: + if (wCode == LBN_SELCHANGE) + InitControls(hDlg, lpEL); + break; + + case IDCANCEL: + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + + case IDC_OLEUIHELP: + PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_EDITLINKS, 0)); + break; + } + break; + + default: + if (lpEL != NULL && iMsg == lpEL->nChgSrcHelpID) + { + PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_CHANGESOURCE, 0)); + } + if (iMsg == uMsgBrowseOFN && + lpEL != NULL && lpEL->lpOEL && lpEL->lpOEL->hWndOwner) + { + SendMessage(lpEL->lpOEL->hWndOwner, uMsgBrowseOFN, wParam, lParam); + } + break; + } + + return FALSE; +} + +/* + * FEditLinksInit + * + * Purpose: + * WM_INITIDIALOG handler for the Edit Links dialog box. + * + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ +BOOL FEditLinksInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + // Copy the structure at lParam into our instance memory. + HFONT hFont; + LPEDITLINKS lpEL = (LPEDITLINKS)LpvStandardInit(hDlg, sizeof(EDITLINKS), &hFont); + + // PvStandardInit send a termination to us already. + if (NULL == lpEL) + return FALSE; + + LPOLEUIEDITLINKS lpOEL = (LPOLEUIEDITLINKS)lParam; + lpEL->lpOEL = lpOEL; + lpEL->nIDD = IDD_EDITLINKS; + + // metrics unknown so far + lpEL->nHeightLine = -1; + lpEL->nMaxCharWidth = -1; + + /* calculate the column positions relative to the listbox */ + HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX); + RECT rc; + GetWindowRect(hListBox, (LPRECT)&rc); + int nStart = rc.left; + GetWindowRect(GetDlgItem(hDlg, IDC_EL_COL1), (LPRECT)&rc); + lpEL->nColPos[0] = rc.left - nStart; + GetWindowRect(GetDlgItem(hDlg, IDC_EL_COL2), (LPRECT)&rc); + lpEL->nColPos[1] = rc.left - nStart; + GetWindowRect(GetDlgItem(hDlg, IDC_EL_COL3), (LPRECT)&rc); + lpEL->nColPos[2] = rc.left - nStart; + + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + + ULONG cLinks = LoadLinkLB(hListBox, lpOleUILinkCntr); + if (cLinks < 0) + return FALSE; + + BOOL fDlgItem = (BOOL)cLinks; + lpEL->fItemsExist = (BOOL)cLinks; + + InitControls(hDlg, lpEL); + + // Copy other information from lpOEL that we might modify. + + // If we got a font, send it to the necessary controls. + if (NULL != hFont) + { + // Do this for as many controls as you need it for. + // SendDlgItemMessage(hDlg, ID_<UFILL>, WM_SETFONT, (WPARAM)hFont, 0L); + } + + // Show or hide the help button + if (!(lpEL->lpOEL->dwFlags & ELF_SHOWHELP)) + StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE); + + /* + * PERFORM OTHER INITIALIZATION HERE. ON ANY LoadString + * FAILURE POST OLEUI_MSG_ENDDIALOG WITH OLEUI_ERR_LOADSTRING. + */ + + // If requested disable UpdateNow button + if ((lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW)) + StandardShowDlgItem(hDlg, IDC_EL_UPDATENOW, SW_HIDE); + + // If requested disable OpenSource button + if ((lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE)) + StandardShowDlgItem(hDlg, IDC_EL_OPENSOURCE, SW_HIDE); + + // If requested disable UpdateNow button + if ((lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE)) + StandardShowDlgItem(hDlg, IDC_EL_CHANGESOURCE, SW_HIDE); + + // If requested disable CancelLink button + if ((lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK)) + StandardShowDlgItem(hDlg, IDC_EL_CANCELLINK, SW_HIDE); + + // Change the caption + if (NULL!=lpOEL->lpszCaption) + SetWindowText(hDlg, lpOEL->lpszCaption); + + // Load 'Close' string used to rename Cancel button + int n = LoadString(_g_hOleStdResInst, IDS_CLOSE, lpEL->szClose, sizeof(lpEL->szClose)/sizeof(TCHAR)); + if (!n) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L); + return FALSE; + } + + if (cLinks > 0) + SetFocus(hListBox); + else + SetFocus(GetDlgItem(hDlg, IDCANCEL)); + + lpEL->nChgSrcHelpID = RegisterWindowMessage(HELPMSGSTRING); + + // Call the hook with lCustData in lParam + UStandardHook(lpEL, hDlg, WM_INITDIALOG, wParam, lpOEL->lCustData); + + return FALSE; +} + +/* +* Container_ChangeSource +* +* Purpose: +* Tunnel to File Open type dlg and allow user to select new file +* for file based monikers, OR to change the whole moniker to what +* the user types into the editable field. +* +* Parameters: +* hDlg HWND of the dialog +* LPEDITLINKS Pointer to EditLinks structure (contains all nec. +* info) +* +* Return Value: +* BOOL for now, because we are not using any ole functions +* to return an HRESULT. +* HRESULT HRESULT value indicating success or failure of +* changing the moniker value +*/ + +BOOL Container_ChangeSource(HWND hDlg, LPEDITLINKS lpEL) +{ + HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX); + int FAR* rgIndex; + int cSelItems = GetSelectedItems(hListBox, &rgIndex); + + if (cSelItems < 0) + return FALSE; + + if (!cSelItems) + return TRUE; + + OLEUICHANGESOURCE cs; memset(&cs, 0, sizeof(cs)); + cs.cbStruct = sizeof(cs); + cs.hWndOwner = hDlg; + if (lpEL->lpOEL->dwFlags & ELF_SHOWHELP) + cs.dwFlags |= CSF_SHOWHELP; + + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + cs.lpOleUILinkContainer = lpOleUILinkCntr; + + for (int i = cSelItems-1; i >= 0; i--) + { + // allow caller to customize the change source dialog + LPLINKINFO lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0); + cs.lpszDisplayName = lpLI->lpszDisplayName; + cs.dwLink = lpLI->dwLink; + cs.nFileLength = lpLI->clenFileName; + + UINT uRet = UStandardHook(lpEL, hDlg, uMsgChangeSource, 0, (LPARAM)&cs); + if (!uRet) + uRet = (OLEUI_OK == OleUIChangeSource(&cs)); + if (!uRet) + break; // dialog canceled (cancel for all) + + if (!lpEL->fClose) + { + SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose); + lpEL->fClose = TRUE; + } + + // update the list box item for the new name + // (note: original lpszDisplayName already freed) + lpLI->fSourceAvailable = (cs.dwFlags & CSF_VALIDSOURCE); + lpLI->lpszDisplayName = cs.lpszDisplayName; + UpdateLinkLBItem(hListBox, rgIndex[i], lpEL, TRUE); + + // if differed only in file name, allow user to change all links + if (cs.lpszFrom != NULL && cs.lpszTo != NULL) + ChangeAllLinks(hListBox, lpOleUILinkCntr, cs.lpszFrom, cs.lpszTo); + + // must free and NULL out the lpszFrom and lpszTo OUT fields + OleStdFree(cs.lpszFrom); + cs.lpszFrom = NULL; + OleStdFree(cs.lpszTo); + cs.lpszTo = NULL; + } + + if (rgIndex != NULL) + OleStdFree(rgIndex); + + return TRUE; +} + +/* +* Container_AutomaticManual +* +* Purpose: +* To change the selected moniker to manual or automatic update. +* +* Parameters: +* hDlg HWND of the dialog +* FAutoMan Flag indicating AUTO (TRUE/1) or MANUAL(FALSE/0) +* LPEDITLINKS Pointer to EditLinks structure (contains all nec. +* info) +* * this may change - don't know how the linked list +* * of multi-selected items will work. +* Return Value: +* HRESULT HRESULT value indicating success or failure of +* changing the moniker value +*/ + +HRESULT Container_AutomaticManual(HWND hDlg, BOOL fAutoMan, LPEDITLINKS lpEL) +{ + HRESULT hErr = NOERROR; + int cSelItems; + int FAR* rgIndex; + int i = 0; + LPLINKINFO lpLI; + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX); + BOOL bUpdate = FALSE; + + OleDbgAssert(lpOleUILinkCntr); + + /* Change so looks at flag in structure. Only update those that + need to be updated. Make sure to change flag if status changes. + */ + + cSelItems = GetSelectedItems(hListBox, &rgIndex); + + if (cSelItems < 0) + return ResultFromScode(E_FAIL); + + if (!cSelItems) + return NOERROR; + + HCURSOR hCursorOld = HourGlassOn(); + + if (!lpEL->fClose) + { + SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose); + lpEL->fClose = TRUE; + } + + for (i = 0; i < cSelItems; i++) + { + lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0); + if (fAutoMan) + { + // If switching to AUTOMATIC + if (!lpLI->fIsAuto) // Only change MANUAL links + { + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n")); + hErr=lpOleUILinkCntr->SetLinkUpdateOptions( + lpLI->dwLink, + OLEUPDATE_ALWAYS + ); + OLEDBG_END2 + + lpLI->fIsAuto=TRUE; + lpLI->fIsMarked = TRUE; + bUpdate = TRUE; + } + } + else // If switching to MANUAL + { + if (lpLI->fIsAuto) // Only do AUTOMATIC Links + { + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n")); + hErr=lpOleUILinkCntr->SetLinkUpdateOptions( + lpLI->dwLink, + OLEUPDATE_ONCALL + ); + OLEDBG_END2 + + lpLI->fIsAuto = FALSE; + lpLI->fIsMarked = TRUE; + bUpdate = TRUE; + } + } + + if (hErr != NOERROR) + { + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::SetLinkUpdateOptions returned"),hErr); + break; + } + } + + if (bUpdate) + RefreshLinkLB(hListBox, lpOleUILinkCntr); + + if (rgIndex) + OleStdFree((LPVOID)rgIndex); + + HourGlassOff(hCursorOld); + + return hErr; +} + +HRESULT CancelLink(HWND hDlg, LPEDITLINKS lpEL) +{ + HRESULT hErr; + LPMONIKER lpmk; + int cSelItems; + int FAR* rgIndex; + int i = 0; + LPLINKINFO lpLI; + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX); + BOOL bUpdate = FALSE; + + OleDbgAssert(lpOleUILinkCntr); + + lpmk = NULL; + + cSelItems = GetSelectedItems(hListBox, &rgIndex); + + if (cSelItems < 0) + return ResultFromScode(E_FAIL); + + if (!cSelItems) + return NOERROR; + + HCURSOR hCursorOld = HourGlassOn(); + + for (i = 0; i < cSelItems; i++) + { + lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0); + + UINT uRet = PopupMessage(hDlg, IDS_LINKS, + IDS_CONFIRMBREAKLINK, MB_YESNO|MB_ICONQUESTION); + if (uRet == IDNO) + break; + + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::CancelLink called\r\n")); + hErr = lpOleUILinkCntr->CancelLink(lpLI->dwLink); + OLEDBG_END2 + + if (!lpEL->fClose) + { + SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose); + lpEL->fClose = TRUE; + } + + if (hErr != NOERROR) + { + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::CancelLink returned"),hErr); + lpLI->fIsMarked = TRUE; + bUpdate = TRUE; + } + else + { + // Delete links that we make null from listbox + SendMessage(hListBox, LB_DELETESTRING, (WPARAM) rgIndex[i], 0L); + int i2; + for (i2 = i + 1; i2 < cSelItems; i2++) + { + if (rgIndex[i2] > rgIndex[i]) + rgIndex[i2]--; + } + } + } + + if (bUpdate) + RefreshLinkLB(hListBox, lpOleUILinkCntr); + + if (rgIndex) + OleStdFree((LPVOID)rgIndex); + + HourGlassOff(hCursorOld); + + return hErr; +} + +/* + * Container_UpdateNow + * + * Purpose: + * Immediately force an update for all (manual) links + * + * Parameters: + * hDlg HWND of the dialog + * LPEDITLINKS Pointer to EditLinks structure (contains all nec. info) + * * this may change - don't know how the linked list + * * of multi-selected items will work. + * Return Value: + * HRESULT HRESULT value indicating success or failure of + * changing the moniker value + */ +HRESULT Container_UpdateNow(HWND hDlg, LPEDITLINKS lpEL) +{ + HRESULT hErr; + LPLINKINFO lpLI; + int cSelItems; + int FAR* rgIndex; + int i = 0; + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX); + BOOL bUpdate = FALSE; + + OleDbgAssert(lpOleUILinkCntr); + + cSelItems = GetSelectedItems(hListBox, &rgIndex); + + if (cSelItems < 0) + return ResultFromScode(E_FAIL); + + if (!cSelItems) + return NOERROR; + + HCURSOR hCursorOld = HourGlassOn(); + + if (!lpEL->fClose) + { + SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose); + lpEL->fClose = TRUE; + } + + for (i = 0; i < cSelItems; i++) + { + lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0); + + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::UpdateLink called\r\n")); + hErr = lpOleUILinkCntr->UpdateLink( + lpLI->dwLink, + TRUE, + FALSE + ); + OLEDBG_END2 + bUpdate = TRUE; + lpLI->fIsMarked = TRUE; + + if (hErr != NOERROR) + { + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::UpdateLink returned"),hErr); + break; + } + } + + if (bUpdate) + RefreshLinkLB(hListBox, lpOleUILinkCntr); + + if (rgIndex) + OleStdFree((LPVOID)rgIndex); + + HourGlassOff(hCursorOld); + + return hErr; + +} + +/* + * Container_OpenSource + * + * Purpose: + * Immediately force an update for all (manual) links + * + * Parameters: + * hDlg HWND of the dialog + * LPEDITLINKS Pointer to EditLinks structure (contains all nec. + * info) + * + * Return Value: + * HRESULT HRESULT value indicating success or failure of + * changing the moniker value + */ + +HRESULT Container_OpenSource(HWND hDlg, LPEDITLINKS lpEL) +{ + HRESULT hErr; + int cSelItems; + int FAR* rgIndex; + LPLINKINFO lpLI; + RECT rcPosRect; + LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX); + + OleDbgAssert(lpOleUILinkCntr); + + rcPosRect.top = 0; + rcPosRect.left = 0; + rcPosRect.right = 0; + rcPosRect.bottom = 0; + + cSelItems = GetSelectedItems(hListBox, &rgIndex); + + if (cSelItems < 0) + return ResultFromScode(E_FAIL); + + if (cSelItems != 1) // can't open source for multiple items + return NOERROR; + + HCURSOR hCursorOld = HourGlassOn(); + + if (!lpEL->fClose) + { + SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose); + lpEL->fClose = TRUE; + } + + lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[0], 0); + + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::OpenLinkSource called\r\n")); + hErr = lpOleUILinkCntr->OpenLinkSource( + lpLI->dwLink + ); + OLEDBG_END2 + + UpdateLinkLBItem(hListBox, rgIndex[0], lpEL, TRUE); + if (hErr != NOERROR) + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::OpenLinkSource returned"),hErr); + + if (rgIndex) + OleStdFree((LPVOID)rgIndex); + + HourGlassOff(hCursorOld); + + return hErr; +} + +/* AddLinkLBItem +** ------------- +** +** Add the item pointed to by lpLI to the Link ListBox and return +** the index of it in the ListBox +*/ +int AddLinkLBItem(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPLINKINFO lpLI, BOOL fGetSelected) +{ + HRESULT hErr; + DWORD dwUpdateOpt; + int nIndex; + + OleDbgAssert(lpOleUILinkCntr && hListBox && lpLI); + + lpLI->fDontFree = FALSE; + + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkSource called\r\n")); + hErr = lpOleUILinkCntr->GetLinkSource( + lpLI->dwLink, + (LPTSTR FAR*)&lpLI->lpszDisplayName, + (ULONG FAR*)&lpLI->clenFileName, + (LPTSTR FAR*)&lpLI->lpszFullLinkType, + (LPTSTR FAR*)&lpLI->lpszShortLinkType, + (BOOL FAR*)&lpLI->fSourceAvailable, + fGetSelected ? (BOOL FAR*)&lpLI->fIsSelected : NULL + ); + OLEDBG_END2 + + if (hErr != NOERROR) + { + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkSource returned"),hErr); + PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKSOURCE, + MB_ICONEXCLAMATION | MB_OK); + goto cleanup; + } + + OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkUpdateOptions called\r\n")); + hErr=lpOleUILinkCntr->GetLinkUpdateOptions( + lpLI->dwLink, + (LPDWORD)&dwUpdateOpt + ); + OLEDBG_END2 + + if (hErr != NOERROR) + { + OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkUpdateOptions returned"),hErr); + PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKUPDATEOPTIONS, + MB_ICONEXCLAMATION | MB_OK); + + goto cleanup; + } + + if (lpLI->fSourceAvailable) + { + if (dwUpdateOpt == OLEUPDATE_ALWAYS) + { + lpLI->fIsAuto = TRUE; + LoadString(_g_hOleStdResInst, IDS_LINK_AUTO, lpLI->lpszAMX, + (int)OleStdGetSize((LPVOID)lpLI->lpszAMX) / sizeof (TCHAR)); + } + else + { + lpLI->fIsAuto = FALSE; + LoadString(_g_hOleStdResInst, IDS_LINK_MANUAL, lpLI->lpszAMX, + (int)OleStdGetSize((LPVOID)lpLI->lpszAMX) / sizeof (TCHAR)); + } + } + else + LoadString(_g_hOleStdResInst, IDS_LINK_UNKNOWN, lpLI->lpszAMX, + (int)OleStdGetSize((LPVOID)lpLI->lpszAMX) / sizeof (TCHAR)); + + BreakString(lpLI); + + nIndex = (int)SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0, + (LPARAM)(DWORD)lpLI); + + if (nIndex == LB_ERR) + { + PopupMessage(hListBox, IDS_LINKS, IDS_ERR_ADDSTRING, + MB_ICONEXCLAMATION | MB_OK); + goto cleanup; + } + return nIndex; + +cleanup: + if (lpLI->lpszDisplayName) + OleStdFree((LPVOID)lpLI->lpszDisplayName); + + if (lpLI->lpszShortLinkType) + OleStdFree((LPVOID)lpLI->lpszShortLinkType); + + if (lpLI->lpszFullLinkType) + OleStdFree((LPVOID)lpLI->lpszFullLinkType); + + return -1; +} + +/* BreakString + * ----------- + * + * Purpose: + * Break the lpszDisplayName into various parts + * + * Parameters: + * lpLI pointer to LINKINFO structure + * + * Returns: + * + */ +VOID BreakString(LPLINKINFO lpLI) +{ + LPTSTR lpsz; + + if (!lpLI->clenFileName || + (lstrlen(lpLI->lpszDisplayName)==(int)lpLI->clenFileName)) + { + lpLI->lpszItemName = NULL; + } + else + { + lpLI->lpszItemName = lpLI->lpszDisplayName + lpLI->clenFileName; + } + + // search from last character of filename + lpsz = lpLI->lpszDisplayName + lstrlen(lpLI->lpszDisplayName); + while (lpsz > lpLI->lpszDisplayName) + { + lpsz = CharPrev(lpLI->lpszDisplayName, lpsz); + if ((*lpsz == '\\') || (*lpsz == '/') || (*lpsz == ':')) + break; + } + + if (lpsz == lpLI->lpszDisplayName) + lpLI->lpszShortFileName = lpsz; + else + lpLI->lpszShortFileName = CharNext(lpsz); +} + +/* GetSelectedItems + * ---------------- + * + * Purpose: + * Retrieve the indices of the selected items in the listbox + * Note that *lprgIndex needed to be free after using the function + * + * Parameters: + * hListBox window handle of listbox + * lprgIndex pointer to an integer array to receive the indices + * must be freed afterwards + * + * Returns: + * number of indices retrieved, -1 if error + */ +int GetSelectedItems(HWND hListBox, int FAR* FAR* lprgIndex) +{ + DWORD cSelItems; + DWORD cCheckItems; + + *lprgIndex = NULL; + + cSelItems = SendMessage(hListBox, LB_GETSELCOUNT, 0, 0L); + if (cSelItems < 0) // error + return (int)cSelItems; + + if (!cSelItems) + return 0; + + *lprgIndex = (int FAR*)OleStdMalloc((int)cSelItems * sizeof(int)); + + cCheckItems = SendMessage(hListBox, LB_GETSELITEMS, + (WPARAM) cSelItems, (LPARAM) (int FAR*) *lprgIndex); + + if (cCheckItems == cSelItems) + return (int)cSelItems; + else + { + if (*lprgIndex) + OleStdFree((LPVOID)*lprgIndex); + *lprgIndex = NULL; + return 0; + } +} + +/* InitControls + * ------------ + * + * Purpose: + * Initialize the state of the Auto/Manual button, Link source/type + * static field, etc in the dialogs according to the selection in the + * listbox + * + * Parameters: + * hDlg handle to the dialog window + */ +VOID InitControls(HWND hDlg, LPEDITLINKS lpEL) +{ + int cSelItems; + HWND hListBox; + int i; + int FAR* rgIndex; + LPLINKINFO lpLI; + LPTSTR lpszType = NULL; + LPTSTR lpszSource = NULL; + int cAuto = 0; + int cManual = 0; + BOOL bSameType = TRUE; + BOOL bSameSource = TRUE; + TCHAR tsz[MAX_PATH]; + LPTSTR lpsz; + + hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX); + + cSelItems = GetSelectedItems(hListBox, &rgIndex); + if (cSelItems < 0) + return; + + StandardEnableDlgItem(hDlg, IDC_EL_AUTOMATIC, (BOOL)cSelItems); + StandardEnableDlgItem(hDlg, IDC_EL_MANUAL, (BOOL)cSelItems); + if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK)) + StandardEnableDlgItem(hDlg, IDC_EL_CANCELLINK, (BOOL)cSelItems); + if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE)) + StandardEnableDlgItem(hDlg, IDC_EL_OPENSOURCE, cSelItems == 1); + if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE)) + StandardEnableDlgItem(hDlg, IDC_EL_CHANGESOURCE, cSelItems == 1); + if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW)) + StandardEnableDlgItem(hDlg, IDC_EL_UPDATENOW, (BOOL)cSelItems); + + for (i = 0; i < cSelItems; i++) + { + lpLI = (LPLINKINFO)SendDlgItemMessage(hDlg, IDC_EL_LINKSLISTBOX, + LB_GETITEMDATA, rgIndex[i], 0); + + if (lpszSource && lpLI->lpszDisplayName) + { + if (bSameSource && lstrcmp(lpszSource, lpLI->lpszDisplayName)) + bSameSource = FALSE; + } + else + lpszSource = lpLI->lpszDisplayName; + + if (lpszType && lpLI->lpszFullLinkType) + { + if (bSameType && lstrcmp(lpszType, lpLI->lpszFullLinkType)) + bSameType = FALSE; + } + else + lpszType = lpLI->lpszFullLinkType; + + if (lpLI->fIsAuto) + cAuto++; + else + cManual++; + } + + CheckDlgButton(hDlg, IDC_EL_AUTOMATIC, cAuto && !cManual); + CheckDlgButton(hDlg, IDC_EL_MANUAL, !cAuto && cManual); + + /* fill full source in static text box + ** below list + */ + if (!bSameSource || !lpszSource) + lpszSource = szNULL; + lstrcpy(tsz, lpszSource); + lpsz = ChopText(GetDlgItem(hDlg, IDC_EL_LINKSOURCE), 0, tsz, 0); + SetDlgItemText(hDlg, IDC_EL_LINKSOURCE, lpsz); + + /* fill full link type name in static + ** "type" text box + */ + if (!bSameType || !lpszType) + lpszType = szNULL; + SetDlgItemText(hDlg, IDC_EL_LINKTYPE, lpszType); + + if (rgIndex) + OleStdFree((LPVOID)rgIndex); +} + + +/* UpdateLinkLBItem + * ----------------- + * + * Purpose: + * Update the linkinfo struct in the listbox to reflect the changes + * made by the last operation. It is done simply by removing the item + * from the listbox and add it back. + * + * Parameters: + * hListBox handle of listbox + * nIndex index of listbox item + * lpEL pointer to editlinks structure + * bSelect select the item or not after update + */ +VOID UpdateLinkLBItem(HWND hListBox, int nIndex, LPEDITLINKS lpEL, BOOL bSelect) +{ + LPLINKINFO lpLI; + LPOLEUILINKCONTAINER lpOleUILinkCntr; + + if (!hListBox || (nIndex < 0) || !lpEL) + return; + + lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer; + + lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, nIndex, 0); + + if (lpLI == NULL) + return; + + /* Don't free the data associated with this listbox item + ** because we are going to reuse the allocated space for + ** the modified link. WM_DELETEITEM processing in the + ** dialog checks this flag before deleting data + ** associcated with list item. + */ + lpLI->fDontFree = TRUE; + SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L); + + nIndex = AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE); + if (bSelect) + { + SendMessage(hListBox, LB_SETSEL, TRUE, MAKELPARAM(nIndex, 0)); + SendMessage(hListBox, LB_SETCARETINDEX, nIndex, MAKELPARAM(TRUE, 0)); + } +} + + + +/* ChangeAllLinks + * -------------- + * + * Purpose: + * Enumerate all the links in the listbox and change those starting + * with lpszFrom to lpszTo. + * + * Parameters: + * hListBox window handle of + * lpOleUILinkCntr pointer to OleUI Link Container + * lpszFrom prefix for matching + * lpszTo prefix to substitution + * + * Returns: + */ +VOID ChangeAllLinks(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPTSTR lpszFrom, LPTSTR lpszTo) +{ + int cItems; + int nIndex; + int cFrom; + LPLINKINFO lpLI; + TCHAR szTmp[MAX_PATH]; + BOOL bFound; + + cFrom = lstrlen(lpszFrom); + + cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L); + OleDbgAssert(cItems >= 0); + + bFound = FALSE; + +#ifdef _DEBUG + OleDbgPrint(3, TEXT("From : "), lpszFrom, 0); + OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0); + OleDbgPrint(3, TEXT("To : "), lpszTo, 0); + OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0); +#endif + + for (nIndex = 0; nIndex < cItems; nIndex++) + { + lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, nIndex, 0); + + // unmark the item + lpLI->fIsMarked = FALSE; + + /* if the corresponding position for the end of lpszFrom in the + ** display name is not a separator. We stop comparing this + ** link. + */ + if (!*(lpLI->lpszDisplayName + cFrom) || + (*(lpLI->lpszDisplayName + cFrom) == '\\') || + (*(lpLI->lpszDisplayName + cFrom) == '!')) + { + lstrcpyn(szTmp, lpLI->lpszDisplayName, cFrom + 1); + if (!lstrcmp(szTmp, lpszFrom)) + { + HRESULT hErr; + int nFileLength; + ULONG ulDummy; + + if (!bFound) + { + TCHAR szTitle[256]; + TCHAR szMsg[256]; + TCHAR szBuf[256]; + int uRet; + + LoadString(_g_hOleStdResInst, IDS_CHANGESOURCE, szTitle, + sizeof(szTitle)/sizeof(TCHAR)); + LoadString(_g_hOleStdResInst, IDS_CHANGEADDITIONALLINKS, + szMsg, sizeof(szMsg)/sizeof(TCHAR)); + wsprintf(szBuf, szMsg, lpszFrom); + uRet = MessageBox(hListBox, szBuf, szTitle, + MB_ICONQUESTION | MB_YESNO); + if (uRet == IDYES) + bFound = TRUE; + else + return; + } + + lstrcpy(szTmp, lpszTo); + lstrcat(szTmp, lpLI->lpszDisplayName + cFrom); + nFileLength = lstrlen(szTmp) - + (lpLI->lpszItemName ? lstrlen(lpLI->lpszItemName) : 0); + + hErr = lpOleUILinkCntr->SetLinkSource( + lpLI->dwLink, + szTmp, + (ULONG)nFileLength, + (ULONG FAR*)&ulDummy, + TRUE + ); + if (hErr != NOERROR) + { + lpOleUILinkCntr->SetLinkSource( + lpLI->dwLink, + szTmp, + (ULONG)nFileLength, + (ULONG FAR*)&ulDummy, + FALSE); + } + lpLI->fIsMarked = TRUE; + } + } + } + + /* have to do the refreshing after processing all links, otherwise + ** the item positions will change during the process as the + ** listbox stores items in order + */ + if (bFound) + RefreshLinkLB(hListBox, lpOleUILinkCntr); +} + + + +/* LoadLinkLB + * ---------- + * + * Purpose: + * Enumerate all links from the Link Container and build up the Link + * ListBox + * + * Parameters: + * hListBox window handle of + * lpOleUILinkCntr pointer to OleUI Link Container + * lpszFrom prefix for matching + * lpszTo prefix to substitution + * + * Returns: + * number of link items loaded, -1 if error + */ +int LoadLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr) +{ + DWORD dwLink = 0; + LPLINKINFO lpLI; + int nIndex; + int cLinks; + + cLinks = 0; + + while ((dwLink = lpOleUILinkCntr->GetNextLink(dwLink)) != 0) + { + lpLI = (LPLINKINFO)OleStdMalloc(sizeof(LINKINFO)); + if (NULL == lpLI) + return -1; + + lpLI->fIsMarked = FALSE; + lpLI->fIsSelected = FALSE; + lpLI->fDontFree = FALSE; + + lpLI->lpszAMX = (LPTSTR)OleStdMalloc((LINKTYPELEN+1)*sizeof(TCHAR)); + + lpLI->dwLink = dwLink; + cLinks++; + if ((nIndex = AddLinkLBItem(hListBox,lpOleUILinkCntr,lpLI,TRUE)) < 0) + // can't load list box + return -1; + + if (lpLI->fIsSelected) + SendMessage(hListBox, LB_SETSEL, TRUE, MAKELPARAM(nIndex, 0)); + } + if (SendMessage(hListBox,LB_GETSELITEMS,(WPARAM)1,(LPARAM)(int FAR*)&nIndex)) + SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, MAKELPARAM(TRUE, 0)); + + return cLinks; +} + +/* RefreshLinkLB + * ------------- + * + * Purpose: + * Enumerate all items in the links listbox and update those with + * fIsMarked set. + * Note that this is a time consuming routine as it keeps iterating + * all items in the listbox until all of them are unmarked. + * + * Parameters: + * hListBox window handle of listbox + * lpOleUILinkCntr pointer to OleUI Link Container + * + * Returns: + * + */ +VOID RefreshLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr) +{ + int cItems; + int nIndex; + LPLINKINFO lpLI; + BOOL bStop; + + OleDbgAssert(hListBox); + + cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L); + OleDbgAssert(cItems >= 0); + + do + { + bStop = TRUE; + for (nIndex = 0; nIndex < cItems; nIndex++) + { + lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, nIndex, 0); + if (lpLI->fIsMarked) + { + lpLI->fIsMarked = FALSE; + lpLI->fDontFree = TRUE; + + SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L); + nIndex=AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE); + if (lpLI->fIsSelected) + { + SendMessage(hListBox, LB_SETSEL, (WPARAM)TRUE, + MAKELPARAM(nIndex, 0)); + SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, + MAKELPARAM(TRUE, 0)); + } + bStop = FALSE; + break; + } + } + } while (!bStop); +} diff --git a/private/ole2ui32/mfcui/dirs b/private/ole2ui32/mfcui/dirs new file mode 100644 index 000000000..06cd74c21 --- /dev/null +++ b/private/ole2ui32/mfcui/dirs @@ -0,0 +1,37 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Drew Bliss (DrewB) 21-Dec-1993 + +!ENDIF + +# +# This is a list of all subdirectories that build required components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +DIRS= \ + mfcuia32 \ + mfcuiw32 + +# +# This is a list of all subdirectories that build optional components. +# Each subdirectory name should appear on a line by itself. The build +# follows the order in which the subdirectories are specified. +# + +OPTIONAL_DIRS= diff --git a/private/ole2ui32/mfcui/mfcui.cpp b/private/ole2ui32/mfcui/mfcui.cpp new file mode 100644 index 000000000..c6043582d --- /dev/null +++ b/private/ole2ui32/mfcui/mfcui.cpp @@ -0,0 +1,223 @@ +// =========================================================================== +// File: M F C U I . C P P +// +// Copyright 1995 Microsoft Corporation. All Rights Reserved. +// Microsoft Confidential +// =========================================================================== +#ifndef UNICODE + +// %%Includes: --------------------------------------------------------------- +#include <windows.h> +#include <ole2.h> +#include <oledlg.h> + +// %%Prototypes: ------------------------------------------------------------- +STDAPI Ole2AnsiWFromA(REFIID riid, LPUNKNOWN punkWrappeeA, LPUNKNOWN *ppunkWrapperW); +STDAPI Ole2AnsiAFromW(REFIID riid, LPUNKNOWN punkWrappeeW, LPUNKNOWN *ppunkWrapperA); + + +// --------------------------------------------------------------------------- +// %%Function: OleUIAddVerbMenu %%Reviewed: 00/00/95 +// +// Description: +// Wraps OleUIAddVerbMenu to OLEDLG.DLL for MFC clients, which expect to be +// able to pass Ansi IOleObject's. +// --------------------------------------------------------------------------- +#undef OleUIAddVerbMenu // overrides the Ansi/Unicode macros in OLEDLG.H + STDAPI_(BOOL) +OleUIAddVerbMenu(LPOLEOBJECT lpOleObjA, LPCSTR lpszShortType, + HMENU hMenu, UINT uPos, UINT uIDVerbMin, UINT uIDVerbMax, + BOOL bAddConvert, UINT idConvert, HMENU FAR *lphMenu) +{ + LPOLEOBJECT lpOleObjW = NULL; + BOOL fResult = FALSE; + + // allow NULL IOleObject (OleUIAddVerbMenuA handles this by making an empty menu), but + // otherwise wrap the Ansi IOleObject to Unicode. + if (lpOleObjA == NULL || + SUCCEEDED(Ole2AnsiWFromA(IID_IOleObject, (LPUNKNOWN)lpOleObjA, (LPUNKNOWN *)&lpOleObjW))) + { + fResult = OleUIAddVerbMenuA(lpOleObjW, lpszShortType, hMenu, uPos, uIDVerbMin, + uIDVerbMax, bAddConvert, idConvert, lphMenu); + + // release the Unicode IOleObject if it was created + if (lpOleObjW != NULL) + lpOleObjW->Release(); + } + + return fResult; +} // OleUIAddVerbMenu + +// --------------------------------------------------------------------------- +// %%Function: OleUIInsertObject %%Reviewed: 00/00/95 +// +// Description: +// Wraps OleUIInsertObject to OLEDLG.DLL for MFC clients, which expect to be +// able to pass Ansi IOleClientSite and IStorage in and receive Ansi interfaces +// out in ppvObj. +// --------------------------------------------------------------------------- +#undef OleUIInsertObject // overrides the Ansi/Unicode macros in OLEDLG.H + STDAPI_(UINT) +OleUIInsertObject(LPOLEUIINSERTOBJECTA lpio) +{ + LPOLECLIENTSITE lpIOleClientSiteA = NULL; + LPSTORAGE lpIStorageA = NULL; + LPVOID FAR *ppvObjA; + LPUNKNOWN punkObjW = NULL; + BOOL fCreatingObject; + UINT wResult; + HRESULT hr = S_OK; + + // validate the structure superficially: let the actual function do most of the validation + if (!lpio) + return OLEUI_ERR_STRUCTURENULL; + if (IsBadReadPtr(lpio, sizeof(LPOLEUIINSERTOBJECTA)) || + IsBadWritePtr(lpio, sizeof(LPOLEUIINSERTOBJECTA))) + return OLEUI_ERR_STRUCTUREINVALID; + if (lpio->cbStruct < sizeof(LPOLEUIINSERTOBJECTA)) + return OLEUI_ERR_CBSTRUCTINCORRECT; + + if (fCreatingObject = (lpio->dwFlags & (IOF_CREATENEWOBJECT | IOF_CREATEFILEOBJECT | IOF_CREATELINKOBJECT))) + { + // verify these parameters, otherwise cleanup becomes complicated + if (IsBadWritePtr(lpio->ppvObj, sizeof(LPUNKNOWN))) + return OLEUI_IOERR_PPVOBJINVALID; + if (lpio->lpIOleClientSite != NULL && IsBadReadPtr(lpio->lpIOleClientSite, sizeof(IOleClientSite))) + return OLEUI_IOERR_LPIOLECLIENTSITEINVALID; + if (lpio->lpIStorage != NULL && IsBadReadPtr(lpio->lpIStorage, sizeof(IStorage))) + return OLEUI_IOERR_LPISTORAGEINVALID; + + // save away the Ansi IOleClientSite, stuff in our Unicode one. + // if it's NULL, OleUIInsertObjectA() will handle the error appropriately and we'll clean up correctly, below. + if (lpIOleClientSiteA = lpio->lpIOleClientSite) + { + hr = Ole2AnsiWFromA(IID_IOleClientSite, (LPUNKNOWN)lpIOleClientSiteA, (LPUNKNOWN *)&lpio->lpIOleClientSite); + if (FAILED(hr)) + { + lpio->lpIOleClientSite = lpIOleClientSiteA; + lpio->sc = hr; + return OLEUI_IOERR_SCODEHASERROR; + } + } + + // save away the Ansi IStorage, stuff in our Unicode one. + // if it's NULL, OleUIInsertObjectA() will handle the error appropriately and we'll clean up correctly, below. + if (lpIStorageA = lpio->lpIStorage) + { + hr = Ole2AnsiWFromA(IID_IStorage, (LPUNKNOWN)lpIStorageA, (LPUNKNOWN *)&lpio->lpIStorage); + if (FAILED(hr)) + { + // make sure to free the Unicode IOleClientSite which we converted above. + if (lpio->lpIOleClientSite) + { + lpio->lpIOleClientSite->Release(); + lpio->lpIOleClientSite = lpIOleClientSiteA; + } + lpio->lpIStorage = lpIStorageA; + lpio->sc = hr; + return OLEUI_IOERR_SCODEHASERROR; + } + } + + // save the current Ansi ppvObj, stuff in our Unicode one + ppvObjA = lpio->ppvObj; + lpio->ppvObj = (LPVOID FAR *)&punkObjW; + } + + wResult = OleUIInsertObjectA(lpio); + + // regardless of success or failure of the above call, we have to clean up the wrapping we did + if (fCreatingObject) + { + // return the Ansi versions of the IOleClientSite and IStorage to + // the structure, and release the Unicode ones + if (lpio->lpIOleClientSite) + { + lpio->lpIOleClientSite->Release(); + lpio->lpIOleClientSite = lpIOleClientSiteA; + } + if (lpio->lpIStorage) + { + lpio->lpIStorage->Release(); + lpio->lpIStorage = lpIStorageA; + } + + // return the Ansi object pointer to the structure + lpio->ppvObj = ppvObjA; + + // convert + if (punkObjW != NULL) + { + HRESULT hr; + // if we were creating an object and we succeeded, punkObjW must be valid and contain an interface + // of type iid. if not, there is a problem in OleUIInsertObjectA(), not in this code. we could assert + // here if this code wanted to, but wouldn't be able to properly circumvent the error anyway. + if (FAILED(hr = Ole2AnsiAFromW(lpio->iid, (LPUNKNOWN)punkObjW, (LPUNKNOWN *)ppvObjA))) + { + lpio->sc = hr; + } + punkObjW->Release(); + if (lpio->sc != S_OK) + return OLEUI_IOERR_SCODEHASERROR; + } + } + + return wResult; +} // OleUIInsertObject + +// --------------------------------------------------------------------------- +// %%Function: OleUIPasteSpecial %%Reviewed: 00/00/95 +// +// Description: +// Wraps OleUIPasteSpecial to OLEDLG.DLL for MFC clients, which expect to be +// able to pass in and get back Ansi IDataObject's. +// --------------------------------------------------------------------------- +#undef OleUIPasteSpecial // overrides the Ansi/Unicode macros in OLEDLG.H + STDAPI_(UINT) +OleUIPasteSpecial(LPOLEUIPASTESPECIALA lpps) +{ + LPDATAOBJECT lpSrcDataObjA; + UINT wResult; + + // validate the structure superficially: let the actual function do most of the validation + if (!lpps) + return OLEUI_ERR_STRUCTURENULL; + if (IsBadReadPtr(lpps, sizeof(LPOLEUIPASTESPECIALA)) || + IsBadWritePtr(lpps, sizeof(LPOLEUIPASTESPECIALA))) + return OLEUI_ERR_STRUCTUREINVALID; + if (lpps->cbStruct < sizeof(LPOLEUIPASTESPECIALA)) + return OLEUI_ERR_CBSTRUCTINCORRECT; + if (NULL != lpps->lpSrcDataObj && IsBadReadPtr(lpps->lpSrcDataObj, sizeof(IDataObject))) + return OLEUI_IOERR_SRCDATAOBJECTINVALID; + + if (!(lpSrcDataObjA = lpps->lpSrcDataObj) || + SUCCEEDED(Ole2AnsiWFromA(IID_IDataObject, (LPUNKNOWN)lpSrcDataObjA, (LPUNKNOWN *)&lpps->lpSrcDataObj))) + { + wResult = OleUIPasteSpecialA(lpps); + + // if we had an Ansi IDataObject on entry, put it back and release the Unicode wrapper. + if (lpSrcDataObjA != NULL) + { + lpps->lpSrcDataObj->Release(); + lpps->lpSrcDataObj = lpSrcDataObjA; + } + // otherwise check to see if OleUIPasteSpecialA() placed a Unicode IDataObject into our structure. + // if it did, wrap it to make sure an Ansi one gets sent back out. + else if (lpps->lpSrcDataObj != NULL) + { + if (FAILED(Ole2AnsiAFromW(IID_IDataObject, (LPUNKNOWN)lpps->lpSrcDataObj, (LPUNKNOWN *)&lpSrcDataObjA))) + { + lpps->lpSrcDataObj->Release(); + lpps->lpSrcDataObj = NULL; + return OLEUI_PSERR_GETCLIPBOARDFAILED; // well, that's pretty much what happened, after all + } + lpps->lpSrcDataObj->Release(); + lpps->lpSrcDataObj = lpSrcDataObjA; + } + } + + return wResult; +} // OleUIPasteSpecial + +#endif // !UNICODE +// EOF ======================================================================= diff --git a/private/ole2ui32/mfcui/mfcuia32/makefile b/private/ole2ui32/mfcui/mfcuia32/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ole2ui32/mfcui/mfcuia32/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ole2ui32/mfcui/mfcuia32/mfcui.rc b/private/ole2ui32/mfcui/mfcuia32/mfcui.rc new file mode 100644 index 000000000..e2f4e019c --- /dev/null +++ b/private/ole2ui32/mfcui/mfcuia32/mfcui.rc @@ -0,0 +1,80 @@ +//Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +///////////////////////////////////////////////////////////////////////////// +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +1 VERSIONINFO + FILEVERSION 3,0,0,0 + PRODUCTVERSION 2,0,1,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "Microsoft Corporation\0" + VALUE "FileDescription", "Microsoft Windows(TM) OLE 2.0 User Interface Support\0" + VALUE "FileVersion", "3.0\0" + VALUE "InternalName", "MFCUIA32\0" + VALUE "LegalCopyright", "Copyright (C) Microsoft Corp. 1995\0" + VALUE "OriginalFilename", "MFCUIA32.DLL\0" + VALUE "ProductName", "Microsoft Windows(TM) OLE 2.0 User Interface Support\0" + VALUE "ProductVersion", "2.01\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/private/ole2ui32/mfcui/mfcuia32/mfcuia32.def b/private/ole2ui32/mfcui/mfcuia32/mfcuia32.def new file mode 100644 index 000000000..e218230a1 --- /dev/null +++ b/private/ole2ui32/mfcui/mfcuia32/mfcuia32.def @@ -0,0 +1,19 @@ +; mfcuia32.def +; Copyright 1995 Microsoft Corporation. All Rights Reserved. + +DESCRIPTION 'OLE 2.0 UI Support Library.' + +EXPORTS +OleUIAddVerbMenu @1 +OleUICanConvertOrActivateAs @2 +OleUIInsertObject @3 +OleUIPasteSpecial @4 +OleUIEditLinks=OleUIEditLinksA @5 +OleUIChangeIcon=OleUIChangeIconA @6 +OleUIConvert=OleUIConvertA @7 +OleUIBusy=OleUIBusyA @8 +OleUIUpdateLinks=OleUIUpdateLinksA @9 +OleUIPromptUser=OleUIPromptUserA @10 +OleUIObjectProperties=OleUIObjectPropertiesA @11 +OleUIChangeSource=OleUIChangeSourceA @12 + diff --git a/private/ole2ui32/mfcui/mfcuia32/sources b/private/ole2ui32/mfcui/mfcuia32/sources new file mode 100644 index 000000000..f7d2102f8 --- /dev/null +++ b/private/ole2ui32/mfcui/mfcuia32/sources @@ -0,0 +1,52 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + + +!ENDIF + +DLLENTRY=DllMain + +DLLBASE=@$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,usermode + +DLLDEF=obj\*\mfcuia32.def + +MAJORCOMP=mfcuia32 +MINORCOMP= + +TARGETNAME=mfcuia32 +TARGETPATH=$(BASEDIR)\public\sdk\lib +C_DEFINES=-DWIN32 +TARGETTYPE=DYNLINK +UMTYPE=windows + +INCLUDES=.. + +386_OPTIMIZATION=/Oy- + +SOURCES= ..\mfcui.cpp \ + mfcui.rc + +USE_CRTDLL=1 + +LINKLIBS= $(BASEDIR)\public\sdk\lib\*\oledlg.lib \ + mfcans32.lib \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\uuid.lib + + diff --git a/private/ole2ui32/mfcui/mfcuiw32/makefile b/private/ole2ui32/mfcui/mfcuiw32/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ole2ui32/mfcui/mfcuiw32/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ole2ui32/mfcui/mfcuiw32/mfcui.rc b/private/ole2ui32/mfcui/mfcuiw32/mfcui.rc new file mode 100644 index 000000000..2e11ee0d7 --- /dev/null +++ b/private/ole2ui32/mfcui/mfcuiw32/mfcui.rc @@ -0,0 +1,80 @@ +//Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +///////////////////////////////////////////////////////////////////////////// +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +1 VERSIONINFO + FILEVERSION 3,0,0,0 + PRODUCTVERSION 2,0,1,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "Microsoft Corporation\0" + VALUE "FileDescription", "Microsoft Windows(TM) OLE 2.0 User Interface Support\0" + VALUE "FileVersion", "3.0\0" + VALUE "InternalName", "MFCUIW32\0" + VALUE "LegalCopyright", "Copyright \251 Microsoft Corp. 1995\0" + VALUE "OriginalFilename", "MFCUIW32.DLL\0" + VALUE "ProductName", "Microsoft Windows(TM) OLE 2.0 User Interface Support\0" + VALUE "ProductVersion", "2.01\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/private/ole2ui32/mfcui/mfcuiw32/mfcuiw32.def b/private/ole2ui32/mfcui/mfcuiw32/mfcuiw32.def new file mode 100644 index 000000000..39ee70590 --- /dev/null +++ b/private/ole2ui32/mfcui/mfcuiw32/mfcuiw32.def @@ -0,0 +1,19 @@ +; mfcuiw32.def +; Copyright 1995 Microsoft Corporation. All Rights Reserved. + +DESCRIPTION 'OLE 2.0 UI Support Library.' + + +EXPORTS +OleUIAddVerbMenu=OleUIAddVerbMenuW @1 +OleUICanConvertOrActivateAs @2 +OleUIInsertObject=OleUIInsertObjectW @3 +OleUIPasteSpecial=OleUIPasteSpecialW @4 +OleUIEditLinks=OleUIEditLinksW @5 +OleUIChangeIcon=OleUIChangeIconW @6 +OleUIConvert=OleUIConvertW @7 +OleUIBusy=OleUIBusyW @8 +OleUIUpdateLinks=OleUIUpdateLinksW @9 +OleUIPromptUser=OleUIPromptUserW @10 +OleUIObjectProperties=OleUIObjectPropertiesW @11 +OleUIChangeSource=OleUIChangeSourceW @12 diff --git a/private/ole2ui32/mfcui/mfcuiw32/sources b/private/ole2ui32/mfcui/mfcuiw32/sources new file mode 100644 index 000000000..e39252b9a --- /dev/null +++ b/private/ole2ui32/mfcui/mfcuiw32/sources @@ -0,0 +1,50 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + + +!ENDIF + + +DLLENTRY=DllMain + +DLLBASE=@$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,usermode + +DLLDEF=obj\*\mfcuiw32.def + +MAJORCOMP=mfcuiw32 +MINORCOMP= + +TARGETNAME=mfcuiw32 +TARGETPATH=$(BASEDIR)\public\sdk\lib +C_DEFINES=-DWIN32 -DUNICODE +TARGETTYPE=DYNLINK +UMTYPE=windows + +INCLUDES=.. + +386_OPTIMIZATION=/Oy- + +USE_CRTDLL=1 + +SOURCES= ..\mfcui.cpp \ + mfcui.rc + +LINKLIBS= $(BASEDIR)\public\sdk\lib\*\oledlg.lib \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib + diff --git a/private/ole2ui32/mfcui/resource.h b/private/ole2ui32/mfcui/resource.h new file mode 100644 index 000000000..a0484466f --- /dev/null +++ b/private/ole2ui32/mfcui/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by mfcui.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/private/ole2ui32/objprop.cpp b/private/ole2ui32/objprop.cpp new file mode 100644 index 000000000..20b3cabc6 --- /dev/null +++ b/private/ole2ui32/objprop.cpp @@ -0,0 +1,1335 @@ +/* + * OBJPROP.CPP + * + * Implements the OleUIObjectProperties function which invokes the complete + * Object Properties dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "common.h" +#include "utility.h" +#include "iconbox.h" +#include "resimage.h" +#include <stddef.h> + +OLEDBGDATA + +// Internally used structure +typedef struct tagGNRLPROPS +{ + // Keep this item first as the Standard* functions depend on it here. + LPOLEUIGNRLPROPS lpOGP; // Original structure passed. + UINT nIDD; // IDD of dialog (used for help info) + + CLSID clsidNew; // new class ID (if conversion done) + +} GNRLPROPS, *PGNRLPROPS, FAR* LPGNRLPROPS; + +typedef struct tagVIEWPROPS +{ + // Keep this item first as the Standard* functions depend on it here. + LPOLEUIVIEWPROPS lpOVP; // Original structure passed. + UINT nIDD; // IDD of dialog (used for help info) + + BOOL bIconChanged; + int nCurrentScale; + BOOL bRelativeToOrig; + DWORD dvAspect; + +} VIEWPROPS, *PVIEWPROPS, FAR* LPVIEWPROPS; + +typedef struct tagLINKPROPS +{ + // Keep this item first as the Standard* functions depend on it here. + LPOLEUILINKPROPS lpOLP; // Original structure passed. + UINT nIDD; // IDD of dialog (used for help info) + + DWORD dwUpdate; // original update mode + LPTSTR lpszDisplayName;// new link source + ULONG nFileLength; // file name part of source + +} LINKPROPS, *PLINKPROPS, FAR* LPLINKPROPS; + +// Internal function prototypes +// OBJPROP.CPP + +/* + * OleUIObjectProperties + * + * Purpose: + * Invokes the standard OLE Object Properties dialog box allowing the user + * to change General, View, and Link properties of an OLE object. This + * dialog uses the new Windows 95 tabbed dialogs. + * + * Parameters: + * lpOP LPOLEUIObjectProperties pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT One of the following codes, indicating success or error: + * OLEUI_SUCCESS Success + * OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong + * + */ + +static UINT WINAPI ValidateObjectProperties(LPOLEUIOBJECTPROPS); +static UINT WINAPI PrepareObjectProperties(LPOLEUIOBJECTPROPS); + +STDAPI_(UINT) OleUIObjectProperties(LPOLEUIOBJECTPROPS lpOP) +{ +#ifdef UNICODE + return (InternalObjectProperties(lpOP, TRUE)); +#else + return (InternalObjectProperties(lpOP, FALSE)); +#endif +} + +UINT InternalObjectProperties(LPOLEUIOBJECTPROPS lpOP, BOOL fWide) +{ + // Validate Parameters + UINT uRet = ValidateObjectProperties(lpOP); + if (OLEUI_SUCCESS != uRet) + return uRet; + + if (NULL == lpOP->lpObjInfo) + { + return(OLEUI_OPERR_OBJINFOINVALID); + } + + if (IsBadReadPtr(lpOP->lpObjInfo, sizeof(IOleUIObjInfo))) + { + return(OLEUI_OPERR_OBJINFOINVALID); + } + + if (lpOP->dwFlags & OPF_OBJECTISLINK) + { + if (NULL == lpOP->lpLinkInfo) + { + return(OLEUI_OPERR_LINKINFOINVALID); + } + + if (IsBadReadPtr(lpOP->lpLinkInfo, sizeof(IOleUILinkInfo))) + { + return(OLEUI_OPERR_LINKINFOINVALID); + } + } + + // Fill Missing values in lpPS + LPPROPSHEETHEADER lpPS = (LPPROPSHEETHEADER)lpOP->lpPS; + LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lpPS->ppsp; + uRet = PrepareObjectProperties(lpOP); + if (OLEUI_SUCCESS != uRet) + return uRet; + + LPTSTR lpszShortType = NULL; + lpOP->lpObjInfo->GetObjectInfo(lpOP->dwObject, NULL, NULL, + NULL, &lpszShortType, NULL); + if (lpszShortType == NULL) + return OLEUI_ERR_OLEMEMALLOC; + + TCHAR szCaption[256]; + if (lpPS->pszCaption == NULL) + { + TCHAR szTemp[256]; + LoadString(_g_hOleStdResInst, + (lpOP->dwFlags & OPF_OBJECTISLINK) ? + IDS_LINKOBJECTPROPERTIES : IDS_OBJECTPROPERTIES, + szTemp, sizeof(szTemp)); + wsprintf(szCaption, szTemp, lpszShortType); +#ifdef UNICODE + if (!fWide) + { + // We're going to actually call the ANSI version of PropertySheet, + // so we need to store the caption as an ANSI string. + lstrcpy(szTemp, szCaption); + WTOA((char *)szCaption, szTemp, 256); + } +#endif + lpPS->pszCaption = szCaption; + } + OleStdFree(lpszShortType); + // Invoke the property sheet + int nResult = StandardPropertySheet(lpOP->lpPS, fWide); + + // Cleanup any temporary memory allocated during the process + if (lpPP == NULL) + { + OleStdFree((LPVOID)lpOP->lpPS->ppsp); + lpOP->lpPS->ppsp = NULL; + } + + // map PropertPage return value to OLEUI_ return code + if (nResult < 0) + uRet = OLEUI_OPERR_PROPERTYSHEET; + else if (nResult == 0) + uRet = OLEUI_CANCEL; + else + uRet = OLEUI_OK; + + return uRet; +} + +///////////////////////////////////////////////////////////////////////////// +// Validation code + +static UINT WINAPI ValidateGnrlProps(LPOLEUIGNRLPROPS lpGP) +{ + OleDbgAssert(lpGP != NULL); + + if (lpGP->cbStruct != sizeof(OLEUIGNRLPROPS)) + return OLEUI_ERR_CBSTRUCTINCORRECT; + if (lpGP->lpfnHook && IsBadCodePtr((FARPROC)lpGP->lpfnHook)) + return OLEUI_ERR_LPFNHOOKINVALID; + + return OLEUI_SUCCESS; +} + +static UINT WINAPI ValidateViewProps(LPOLEUIVIEWPROPS lpVP) +{ + OleDbgAssert(lpVP != NULL); + + if (lpVP->cbStruct != sizeof(OLEUIVIEWPROPS)) + return OLEUI_ERR_CBSTRUCTINCORRECT; + if (lpVP->lpfnHook && IsBadCodePtr((FARPROC)lpVP->lpfnHook)) + return OLEUI_ERR_LPFNHOOKINVALID; + + return OLEUI_SUCCESS; +} + +static UINT WINAPI ValidateLinkProps(LPOLEUILINKPROPS lpLP) +{ + OleDbgAssert(lpLP != NULL); + + if (lpLP->cbStruct != sizeof(OLEUILINKPROPS)) + return OLEUI_ERR_CBSTRUCTINCORRECT; + if (lpLP->lpfnHook && IsBadCodePtr((FARPROC)lpLP->lpfnHook)) + return OLEUI_ERR_LPFNHOOKINVALID; + + return OLEUI_SUCCESS; +} + +static UINT WINAPI ValidateObjectProperties(LPOLEUIOBJECTPROPS lpOP) +{ + // Validate LPOLEUIOBJECTPROPS lpOP + if (lpOP == NULL) + return OLEUI_ERR_STRUCTURENULL; + + if (IsBadWritePtr(lpOP, sizeof(OLEUIOBJECTPROPS))) + return OLEUI_ERR_STRUCTUREINVALID; + + // Validate cbStruct field of OLEUIOBJECTPROPS + if (lpOP->cbStruct != sizeof(OLEUIOBJECTPROPS)) + return OLEUI_ERR_CBSTRUCTINCORRECT; + + // Validate "sub" property pointers + if (lpOP->lpGP == NULL || lpOP->lpVP == NULL || + ((lpOP->dwFlags & OPF_OBJECTISLINK) && lpOP->lpLP == NULL)) + return OLEUI_OPERR_SUBPROPNULL; + + if (IsBadWritePtr(lpOP->lpGP, sizeof(OLEUIGNRLPROPS)) || + IsBadWritePtr(lpOP->lpVP, sizeof(OLEUIVIEWPROPS)) || + ((lpOP->dwFlags & OPF_OBJECTISLINK) && + IsBadWritePtr(lpOP->lpLP, sizeof(OLEUILINKPROPS)))) + return OLEUI_OPERR_SUBPROPINVALID; + + // Validate property sheet data pointers + LPPROPSHEETHEADER lpPS = lpOP->lpPS; + if (lpPS == NULL) + return OLEUI_OPERR_PROPSHEETNULL; + + if (IsBadWritePtr(lpPS, sizeof(PROPSHEETHEADER))) + return OLEUI_OPERR_PROPSHEETINVALID; + + DWORD dwSize = lpPS->dwSize; + if (dwSize < sizeof(PROPSHEETHEADER)) + return OLEUI_ERR_CBSTRUCTINCORRECT; + + // If links specified, validate "sub" link property pointer + if (lpOP->dwFlags & OPF_OBJECTISLINK) + { + if (lpPS->ppsp != NULL && lpPS->nPages < 3) + return OLEUI_OPERR_PAGESINCORRECT; + } + else + { + if (lpPS->ppsp != NULL && lpPS->nPages < 2) + return OLEUI_OPERR_PAGESINCORRECT; + } + + if (lpPS->ppsp != NULL && + IsBadWritePtr((PROPSHEETPAGE*)lpPS->ppsp, + lpPS->nPages * sizeof(PROPSHEETPAGE))) + { + return OLEUI_OPERR_INVALIDPAGES; + } + + // not setting PSH_PROPSHEETPAGE is not supported + if (lpOP->dwFlags & OPF_NOFILLDEFAULT) + { + if (!(lpPS->dwFlags & PSH_PROPSHEETPAGE)) + return OLEUI_OPERR_NOTSUPPORTED; + } + else if (lpPS->dwFlags != 0) + { + return OLEUI_OPERR_NOTSUPPORTED; + } + + // Sanity check any pages provided + for (UINT nPage = 0; nPage < lpPS->nPages; nPage++) + { + LPPROPSHEETPAGE lpPP = (PROPSHEETPAGE*)&lpPS->ppsp[nPage]; + if (lpPP->dwSize != sizeof(PROPSHEETPAGE)) + return OLEUI_ERR_CBSTRUCTINCORRECT; + if (lpPP->pfnDlgProc != NULL) + return OLEUI_OPERR_DLGPROCNOTNULL; + if (lpPP->lParam != 0) + return OLEUI_OPERR_LPARAMNOTZERO; + } + + // validate individual prop page structures + UINT uRet = ValidateGnrlProps(lpOP->lpGP); + if (uRet != OLEUI_SUCCESS) + return uRet; + uRet = ValidateViewProps(lpOP->lpVP); + if (uRet != OLEUI_SUCCESS) + return uRet; + if ((lpOP->dwFlags & OPF_OBJECTISLINK) && lpOP->lpLP != NULL) + { + uRet = ValidateLinkProps(lpOP->lpLP); + if (uRet != OLEUI_SUCCESS) + return uRet; + } + + return OLEUI_SUCCESS; +} + +///////////////////////////////////////////////////////////////////////////// +// GnrlPropsDialogProc and helpers + +// takes a DWORD add commas etc to it and puts the result in the buffer +LPTSTR AddCommas(DWORD dw, LPTSTR pszResult, UINT nMax) +{ + NUMBERFMT numberFmt; + numberFmt.NumDigits = 0; + numberFmt.LeadingZero = 0; + + TCHAR szSep[5]; + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, sizeof(szSep)); + numberFmt.Grouping = Atol(szSep); + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, sizeof(szSep)); + numberFmt.lpDecimalSep = numberFmt.lpThousandSep = szSep; + numberFmt.NegativeOrder= 0; + + TCHAR szTemp[64]; + wsprintf(szTemp, TEXT("%lu"), dw); + + GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &numberFmt, pszResult, nMax); + return pszResult; +} + +const short pwOrders[] = {IDS_BYTES, IDS_ORDERKB, IDS_ORDERMB, IDS_ORDERGB, IDS_ORDERTB}; + +/* converts numbers into short formats + * 532 -> 523 bytes + * 1340 -> 1.3KB + * 23506 -> 23.5KB + * -> 2.4MB + * -> 5.2GB + */ +LPTSTR ShortSizeFormat64(__int64 dw64, LPTSTR szBuf) +{ + int i; + UINT wInt, wLen, wDec; + TCHAR szTemp[10], szOrder[20], szFormat[5]; + + if (dw64 < 1000) + { + wsprintf(szTemp, TEXT("%d"), DWORD(dw64)); + i = 0; + } + else + { + for (i = 1; i < (sizeof(pwOrders)/sizeof(pwOrders))-1 + && dw64 >= 1000L * 1024L; dw64 >>= 10, i++) + ; /* do nothing */ + + wInt = DWORD(dw64 >> 10); + AddCommas(wInt, szTemp, sizeof(szTemp)/sizeof(TCHAR)); + wLen = lstrlen(szTemp); + if (wLen < 3) + { + wDec = DWORD(dw64 - (__int64)wInt * 1024L) * 1000 / 1024; + // At this point, wDec should be between 0 and 1000 + // we want get the top one (or two) digits. + wDec /= 10; + if (wLen == 2) + wDec /= 10; + + // Note that we need to set the format before getting the + // intl char. + lstrcpy(szFormat, TEXT("%02d")); + + szFormat[2] = '0' + 3 - wLen; + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, + szTemp+wLen, sizeof(szTemp)-wLen); + wLen = lstrlen(szTemp); + wLen += wsprintf(szTemp+wLen, szFormat, wDec); + } + } + + LoadString(_g_hOleStdResInst, pwOrders[i], szOrder, sizeof(szOrder)); + wsprintf(szBuf, szOrder, (LPSTR)szTemp); + + return szBuf; +} + +LPTSTR WINAPI ShortSizeFormat(DWORD dw, LPTSTR szBuf) +{ + return ShortSizeFormat64((__int64)dw, szBuf); +} + +BOOL FGnrlPropsRefresh(HWND hDlg, LPGNRLPROPS lpGP) +{ + // get object information and fill in default fields + LPOLEUIOBJECTPROPS lpOP = lpGP->lpOGP->lpOP; + LPOLEUIOBJINFO lpObjInfo = lpOP->lpObjInfo; + + // get object's icon + HGLOBAL hMetaPict; + lpObjInfo->GetViewInfo(lpOP->dwObject, &hMetaPict, NULL, NULL); + if (hMetaPict != NULL) + { + HICON hIcon = OleUIMetafilePictExtractIcon(hMetaPict); + SendDlgItemMessage(hDlg, IDC_GP_OBJECTICON, STM_SETICON, + (WPARAM)hIcon, 0); + } + OleUIMetafilePictIconFree(hMetaPict); + + // get type, short type, location, and size of object + DWORD dwObjSize; + LPTSTR lpszLabel = NULL; + LPTSTR lpszType = NULL; + LPTSTR lpszShortType = NULL; + LPTSTR lpszLocation = NULL; + lpObjInfo->GetObjectInfo(lpOP->dwObject, &dwObjSize, &lpszLabel, + &lpszType, &lpszShortType, &lpszLocation); + + // set name, type, and size of object + SetDlgItemText(hDlg, IDC_GP_OBJECTNAME, lpszLabel); + SetDlgItemText(hDlg, IDC_GP_OBJECTTYPE, lpszType); + SetDlgItemText(hDlg, IDC_GP_OBJECTLOCATION, lpszLocation); + TCHAR szTemp[128]; + if (dwObjSize == (DWORD)-1) + { + LoadString(_g_hOleStdResInst, IDS_OLE2UIUNKNOWN, szTemp, 64); + SetDlgItemText(hDlg, IDC_GP_OBJECTSIZE, szTemp); + } + else + { + // get the master formatting string + TCHAR szFormat[64]; + LoadString(_g_hOleStdResInst, IDS_OBJECTSIZE, szFormat, 64); + + // format the size in two ways (short, and with commas) + TCHAR szNum1[20], szNum2[32]; + ShortSizeFormat(dwObjSize, szNum1); + AddCommas(dwObjSize, szNum2, 32); + FormatString2(szTemp, szFormat, szNum1, szNum2); + + // set the control's text + SetDlgItemText(hDlg, IDC_GP_OBJECTSIZE, szTemp); + } + + // enable/disable convert button as necessary + BOOL bEnable = TRUE; + if (lpOP->dwFlags & (OPF_OBJECTISLINK|OPF_DISABLECONVERT)) + bEnable = FALSE; + else + { + CLSID clsid; WORD wFormat; + lpObjInfo->GetConvertInfo(lpOP->dwObject, &clsid, &wFormat, NULL, NULL, NULL); + bEnable = OleUICanConvertOrActivateAs(clsid, FALSE, wFormat); + } + StandardEnableDlgItem(hDlg, IDC_GP_CONVERT, bEnable); + + // cleanup temporary info strings + OleStdFree(lpszLabel); + OleStdFree(lpszType); + OleStdFree(lpszShortType); + OleStdFree(lpszLocation); + + return TRUE; +} + +BOOL FGnrlPropsInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + // Copy the structure at lParam into our instance memory. + HFONT hFont; + LPGNRLPROPS lpGP = (LPGNRLPROPS)LpvStandardInit(hDlg, sizeof(GNRLPROPS), &hFont); + + // LpvStandardInit send a termination to us already. + if (NULL == lpGP) + return FALSE; + + LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lParam; + LPOLEUIGNRLPROPS lpOGP = (LPOLEUIGNRLPROPS)lpPP->lParam; + lpGP->lpOGP = lpOGP; + lpGP->nIDD = IDD_GNRLPROPS; + + // If we got a font, send it to the necessary controls. + if (NULL != hFont) + { + SendDlgItemMessage(hDlg, IDC_GP_OBJECTNAME, WM_SETFONT, (WPARAM)hFont, 0L); + SendDlgItemMessage(hDlg, IDC_GP_OBJECTTYPE, WM_SETFONT, (WPARAM)hFont, 0L); + SendDlgItemMessage(hDlg, IDC_GP_OBJECTLOCATION, WM_SETFONT, (WPARAM)hFont, 0L); + SendDlgItemMessage(hDlg, IDC_GP_OBJECTSIZE, WM_SETFONT, (WPARAM)hFont, 0L); + } + + // Initialize the controls + FGnrlPropsRefresh(hDlg, lpGP); + + // Call the hook with lCustData in lParam + UStandardHook((PVOID)lpGP, hDlg, WM_INITDIALOG, wParam, lpOGP->lCustData); + return TRUE; +} + +BOOL CALLBACK GnrlPropsDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + // Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + // This will fail under WM_INITDIALOG, where we allocate it. + UINT uHook = 0; + LPGNRLPROPS lpGP = (LPGNRLPROPS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook); + + // If the hook processed the message, we're done. + if (0 != uHook) + return (BOOL)uHook; + + // Get pointers to important info + LPOLEUIGNRLPROPS lpOGP = NULL; + LPOLEUIOBJECTPROPS lpOP = NULL; + LPOLEUIOBJINFO lpObjInfo = NULL; + if (lpGP != NULL) + { + lpOGP = lpGP->lpOGP; + if (lpOGP != NULL) + { + lpObjInfo = lpOGP->lpOP->lpObjInfo; + lpOP = lpOGP->lpOP; + } + } + + switch (iMsg) + { + case WM_INITDIALOG: + FGnrlPropsInit(hDlg, wParam, lParam); + return TRUE; + + case WM_COMMAND: + switch (wID) + { + case IDC_GP_CONVERT: + { + // Call up convert dialog to obtain new CLSID + OLEUICONVERT cv; memset(&cv, 0, sizeof(cv)); + cv.cbStruct = sizeof(cv); + cv.dwFlags |= CF_CONVERTONLY; + if (lpOP->dwFlags & OPF_SHOWHELP) + cv.dwFlags |= CF_SHOWHELPBUTTON; + cv.clsidConvertDefault = lpGP->clsidNew; + cv.dvAspect = DVASPECT_CONTENT; + lpObjInfo->GetObjectInfo(lpOP->dwObject, + NULL, NULL, &cv.lpszUserType, NULL, NULL); + lpObjInfo->GetConvertInfo(lpOP->dwObject, + &cv.clsid, &cv.wFormat, &cv.clsidConvertDefault, + &cv.lpClsidExclude, &cv.cClsidExclude); + cv.fIsLinkedObject = + (lpOGP->lpOP->dwFlags & OPF_OBJECTISLINK); + if (cv.clsidConvertDefault != CLSID_NULL) + cv.dwFlags |= CF_SETCONVERTDEFAULT; + cv.hWndOwner = GetParent(GetParent(hDlg)); + + // allow caller to hook the convert structure + uHook = UStandardHook(lpGP, hDlg, uMsgConvert, 0, (LPARAM)&cv); + if (0 == uHook) + { + uHook = (OLEUI_OK == OleUIConvert(&cv)); + SetFocus(hDlg); + } + + // check to see dialog results + if (uHook != 0 && (cv.dwFlags & CF_SELECTCONVERTTO)) + { + lpGP->clsidNew = cv.clsidNew; + SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0); + } + } + return TRUE; + } + break; + + case PSM_QUERYSIBLINGS: + SetWindowLong(hDlg, DWL_MSGRESULT, 0); + switch (wParam) + { + case OLEUI_QUERY_GETCLASSID: + *(CLSID*)lParam = lpGP->clsidNew; + SetWindowLong(hDlg, DWL_MSGRESULT, 1); + return TRUE; + + case OLEUI_QUERY_LINKBROKEN: + FGnrlPropsRefresh(hDlg, lpGP); + return TRUE; + } + break; + + case WM_NOTIFY: + switch (((NMHDR*)lParam)->code) + { + case PSN_HELP: + PostMessage(GetParent(GetParent(hDlg)), uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_GNRLPROPS, 0)); + break; + case PSN_APPLY: + // apply changes if changes made + if (lpGP->clsidNew != CLSID_NULL) + { + // convert the object -- fail the apply if convert fails + if (NOERROR != lpObjInfo->ConvertObject(lpOP->dwObject, + lpGP->clsidNew)) + { + SetWindowLong(hDlg, DWL_MSGRESULT, 1); + return TRUE; + } + lpGP->clsidNew = CLSID_NULL; + } + SetWindowLong(hDlg, DWL_MSGRESULT, 0); + PostMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0); + return TRUE; + } + break; + + case WM_DESTROY: + { + HICON hIcon = (HICON)SendDlgItemMessage(hDlg, IDC_GP_OBJECTICON, + STM_GETICON, 0, 0); + if (hIcon != NULL) + DestroyIcon(hIcon); + StandardCleanup((PVOID)lpGP, hDlg); + } + return TRUE; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// ViewPropsDialogProc and helpers + +void EnableDisableScaleControls(LPVIEWPROPS lpVP, HWND hDlg) +{ + LPOLEUIVIEWPROPS lpOVP = lpVP->lpOVP; + BOOL bEnable = !(lpOVP->dwFlags & VPF_DISABLESCALE) && + SendDlgItemMessage(hDlg, IDC_VP_ASICON, BM_GETCHECK, 0, 0) == 0; + StandardEnableDlgItem(hDlg, IDC_VP_SPIN, bEnable); + StandardEnableDlgItem(hDlg, IDC_VP_PERCENT, bEnable); + StandardEnableDlgItem(hDlg, IDC_VP_SCALETXT, bEnable); + bEnable = bEnable && !(lpOVP->dwFlags & VPF_DISABLERELATIVE); + StandardEnableDlgItem(hDlg, IDC_VP_RELATIVE, bEnable); +} + +BOOL FViewPropsInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + // Copy the structure at lParam into our instance memory. + LPVIEWPROPS lpVP = (LPVIEWPROPS)LpvStandardInit(hDlg, sizeof(VIEWPROPS)); + + // LpvStandardInit send a termination to us already. + if (NULL == lpVP) + return FALSE; + + LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lParam; + LPOLEUIVIEWPROPS lpOVP = (LPOLEUIVIEWPROPS)lpPP->lParam; + lpVP->lpOVP = lpOVP; + lpVP->nIDD = IDD_VIEWPROPS; + + // get object information and fill in default fields + LPOLEUIOBJECTPROPS lpOP = lpOVP->lpOP; + LPOLEUIOBJINFO lpObjInfo = lpOP->lpObjInfo; + + // initialize icon and scale variables + HGLOBAL hMetaPict; + DWORD dvAspect; + int nCurrentScale; + lpObjInfo->GetViewInfo(lpOP->dwObject, &hMetaPict, + &dvAspect, &nCurrentScale); + SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGESET, + 0, (LPARAM)hMetaPict); + lpVP->nCurrentScale = nCurrentScale; + lpVP->dvAspect = dvAspect; + + // Initialize the result image + SendDlgItemMessage(hDlg, IDC_VP_RESULTIMAGE, + RIM_IMAGESET, RESULTIMAGE_EDITABLE, 0L); + + // Initialize controls + CheckRadioButton(hDlg, IDC_VP_EDITABLE, IDC_VP_ASICON, + dvAspect == DVASPECT_CONTENT ? IDC_VP_EDITABLE : IDC_VP_ASICON); + SendDlgItemMessage(hDlg, IDC_VP_RELATIVE, BM_SETCHECK, + (lpOVP->dwFlags & VPF_SELECTRELATIVE) != 0, 0L); + if (!(lpOVP->dwFlags & VPF_DISABLESCALE)) + SetDlgItemInt(hDlg, IDC_VP_PERCENT, nCurrentScale, FALSE); + lpVP->bRelativeToOrig = SendDlgItemMessage(hDlg, IDC_VP_RELATIVE, + BM_GETCHECK, 0, 0) != 0; + + // Setup up-down control as buddy to IDC_VP_PERCENT + HWND hWndSpin = CreateWindowEx(0, UPDOWN_CLASS, NULL, + WS_CHILD|UDS_SETBUDDYINT|UDS_ARROWKEYS|UDS_ALIGNRIGHT, 0, 0, 0, 0, + hDlg, (HMENU)IDC_VP_SPIN, _g_hOleStdInst, NULL); + if (hWndSpin != NULL) + { + SendMessage(hWndSpin, UDM_SETRANGE, 0, + MAKELPARAM(lpOVP->nScaleMax, lpOVP->nScaleMin)); + SendMessage(hWndSpin, UDM_SETPOS, 0, nCurrentScale); + SendMessage(hWndSpin, UDM_SETBUDDY, + (WPARAM)GetDlgItem(hDlg, IDC_VP_PERCENT), 0); + ShowWindow(hWndSpin, SW_SHOW); + } + EnableDisableScaleControls(lpVP, hDlg); + + // Call the hook with lCustData in lParam + UStandardHook((PVOID)lpVP, hDlg, WM_INITDIALOG, wParam, lpOVP->lCustData); + return TRUE; +} + +BOOL CALLBACK ViewPropsDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + // Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + // This will fail under WM_INITDIALOG, where we allocate it. + UINT uHook = 0; + LPVIEWPROPS lpVP = (LPVIEWPROPS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook); + + // If the hook processed the message, we're done. + if (0 != uHook) + return (BOOL)uHook; + + // Get pointers to important info + LPOLEUIVIEWPROPS lpOVP = NULL; + LPOLEUIOBJECTPROPS lpOP = NULL; + LPOLEUIOBJINFO lpObjInfo = NULL; + if (lpVP != NULL) + { + lpOVP = lpVP->lpOVP; + if (lpOVP != NULL) + { + lpObjInfo = lpOVP->lpOP->lpObjInfo; + lpOP = lpOVP->lpOP; + } + } + + switch (iMsg) + { + case WM_INITDIALOG: + FViewPropsInit(hDlg, wParam, lParam); + return TRUE; + + case WM_COMMAND: + switch (wID) + { + case IDC_VP_ASICON: + case IDC_VP_EDITABLE: + EnableDisableScaleControls(lpVP, hDlg); + SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0); + return TRUE; + + case IDC_VP_CHANGEICON: + { + // Call up Change Icon dialog to obtain new icon + OLEUICHANGEICON ci; memset(&ci, 0, sizeof(ci)); + ci.cbStruct = sizeof(ci); + ci.dwFlags = CIF_SELECTCURRENT; + ci.hWndOwner = GetParent(GetParent(hDlg)); + ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, + IBXM_IMAGEGET, 0, 0L); + + // get classid to look for (may be new class if conversion applied) + SendMessage(GetParent(hDlg), PSM_QUERYSIBLINGS, + OLEUI_QUERY_GETCLASSID, (LPARAM)&ci.clsid); + lpObjInfo->GetConvertInfo(lpOP->dwObject, + &ci.clsid, NULL, NULL, NULL, NULL); + if (lpOP->dwFlags & OPF_SHOWHELP) + ci.dwFlags |= CIF_SHOWHELP; + + // allow the caller to hook the change icon + uHook = UStandardHook(lpVP, hDlg, uMsgChangeIcon, 0, (LPARAM)&ci); + if (0 == uHook) + { + uHook = (OLEUI_OK == OleUIChangeIcon(&ci)); + SetFocus(hDlg); + } + if (0 != uHook) + { + // apply the changes + SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGESET, 1, + (LPARAM)ci.hMetaPict); + lpVP->bIconChanged = TRUE; + SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0); + } + } + return TRUE; + + case IDC_VP_PERCENT: + case IDC_VP_RELATIVE: + SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0); + return TRUE; + } + break; + + case WM_VSCROLL: + SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0); + break; + + case PSM_QUERYSIBLINGS: + SetWindowLong(hDlg, DWL_MSGRESULT, 0); + switch (wParam) + { + case OLEUI_QUERY_LINKBROKEN: + if (!lpVP->bIconChanged) + { + // re-init icon, since user hasn't changed it + HGLOBAL hMetaPict; + lpObjInfo->GetViewInfo(lpOP->dwObject, &hMetaPict, NULL, NULL); + SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGESET, + 1, (LPARAM)hMetaPict); + } + return TRUE; + } + break; + + case WM_NOTIFY: + switch (((NMHDR*)lParam)->code) + { + case PSN_HELP: + PostMessage(GetParent(GetParent(hDlg)), uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_VIEWPROPS, 0)); + break; + case PSN_APPLY: + { + HGLOBAL hMetaPict = NULL; + int nCurrentScale = -1; + DWORD dvAspect = (DWORD)-1; + BOOL bRelativeToOrig = FALSE; + + // handle icon change + if (lpVP->bIconChanged) + { + hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, + IDC_VP_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); + lpVP->bIconChanged = FALSE; + } + + // handle scale changes + if (IsWindowEnabled(GetDlgItem(hDlg, IDC_VP_PERCENT))) + { + // parse the percentage entered + BOOL bValid; + nCurrentScale = GetDlgItemInt(hDlg, IDC_VP_PERCENT, &bValid, FALSE); + if (!bValid) + { + PopupMessage(GetParent(hDlg), IDS_VIEWPROPS, + IDS_INVALIDPERCENTAGE, MB_OK|MB_ICONEXCLAMATION); + + // cancel the call + SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE); + return TRUE; + } + // normalize range + int nScaleMin, nScaleMax; + if (lpOVP->nScaleMin > lpOVP->nScaleMax) + { + nScaleMin = lpOVP->nScaleMax; + nScaleMax = lpOVP->nScaleMin; + } + else + { + nScaleMin = lpOVP->nScaleMin; + nScaleMax = lpOVP->nScaleMax; + } + // check range for validity + if (nCurrentScale < nScaleMin || nCurrentScale > nScaleMax) + { + // format appropriate message + TCHAR szCaption[128]; + LoadString(_g_hOleStdResInst, IDS_VIEWPROPS, szCaption, 128); + TCHAR szFormat[128]; + LoadString(_g_hOleStdResInst, IDS_RANGEERROR, szFormat, 128); + TCHAR szTemp[256], szNum1[32], szNum2[32]; + wsprintf(szNum1, _T("%d"), lpOVP->nScaleMin); + wsprintf(szNum2, _T("%d"), lpOVP->nScaleMax); + FormatString2(szTemp, szFormat, szNum1, szNum2); + MessageBox(GetParent(hDlg), szTemp, szCaption, MB_OK|MB_ICONEXCLAMATION); + + // and cancel the call + SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE); + return TRUE; + } + + // otherwise scale is in correct range + bRelativeToOrig = + SendDlgItemMessage(hDlg, IDC_VP_RELATIVE, BM_GETCHECK, 0, 0) != 0; + if (nCurrentScale != lpVP->nCurrentScale || + bRelativeToOrig != lpVP->bRelativeToOrig) + { + lpVP->nCurrentScale = nCurrentScale; + lpVP->bRelativeToOrig = bRelativeToOrig; + } + } + + // handle aspect changes + if (SendDlgItemMessage(hDlg, IDC_VP_ASICON, BM_GETCHECK, 0, 0L)) + dvAspect = DVASPECT_ICON; + else + dvAspect = DVASPECT_CONTENT; + if (dvAspect == lpVP->dvAspect) + dvAspect = (DWORD)-1; + else + { + lpVP->dvAspect = dvAspect; + bRelativeToOrig = 1; + } + + lpObjInfo->SetViewInfo(lpOP->dwObject, hMetaPict, dvAspect, + nCurrentScale, bRelativeToOrig); + } + SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR); + PostMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0); + return TRUE; + } + break; + + case WM_DESTROY: + SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0); + StandardCleanup((PVOID)lpVP, hDlg); + return TRUE; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// LinkPropsDialogProc and helpers + +static BOOL IsNullTime(const FILETIME* lpFileTime) +{ + FILETIME fileTimeNull = { 0, 0 }; + return CompareFileTime(&fileTimeNull, lpFileTime) == 0; +} + +static BOOL SetDlgItemDate(HWND hDlg, int nID, const FILETIME* lpFileTime) +{ + if (IsNullTime(lpFileTime)) + return FALSE; + + // convert UTC file time to system time + FILETIME localTime; + FileTimeToLocalFileTime(lpFileTime, &localTime); + SYSTEMTIME systemTime; + FileTimeToSystemTime(&localTime, &systemTime); + + TCHAR szDate[80]; + GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemTime, + NULL, szDate, sizeof(szDate)); + + SetDlgItemText(hDlg, nID, szDate); + return TRUE; +} + +static BOOL SetDlgItemTime(HWND hDlg, int nID, const FILETIME* lpFileTime) +{ + if (IsNullTime(lpFileTime)) + return FALSE; + + // convert UTC file time to system time + FILETIME localTime; + FileTimeToLocalFileTime(lpFileTime, &localTime); + SYSTEMTIME systemTime; + FileTimeToSystemTime(&localTime, &systemTime); + + if (systemTime.wHour || systemTime.wMinute || systemTime.wSecond) + { + TCHAR szTime[80]; + GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systemTime, + NULL, szTime, sizeof(szTime)); + + SetDlgItemText(hDlg, nID, szTime); + } + return TRUE; +} + +BOOL FLinkPropsInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + // Copy the structure at lParam into our instance memory. + HFONT hFont; + LPLINKPROPS lpLP = (LPLINKPROPS)LpvStandardInit(hDlg, sizeof(LINKPROPS), &hFont); + + // LpvStandardInit send a termination to us already. + if (NULL == lpLP) + return FALSE; + + LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lParam; + LPOLEUILINKPROPS lpOLP = (LPOLEUILINKPROPS)lpPP->lParam; + lpLP->lpOLP = lpOLP; + lpLP->nIDD = IDD_LINKPROPS; + + // If we got a font, send it to the necessary controls. + if (NULL != hFont) + { + // Do this for as many controls as you need it for. + SendDlgItemMessage(hDlg, IDC_LP_LINKSOURCE, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(hDlg, IDC_LP_DATE, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(hDlg, IDC_LP_TIME, WM_SETFONT, (WPARAM)hFont, 0); + } + + // general "Unknown" string for unknown items + TCHAR szUnknown[64]; + LoadString(_g_hOleStdResInst, IDS_OLE2UIUNKNOWN, szUnknown, 64); + + // get object information and fill in default fields + LPOLEUIOBJECTPROPS lpOP = lpOLP->lpOP; + LPOLEUILINKINFO lpLinkInfo = lpOP->lpLinkInfo; + FILETIME lastUpdate; memset(&lastUpdate, 0, sizeof(lastUpdate)); + lpLinkInfo->GetLastUpdate(lpOP->dwLink, &lastUpdate); + + // initialize time and date static text + if (IsNullTime(&lastUpdate)) + { + // time and date are unknown + SetDlgItemText(hDlg, IDC_LP_DATE, szUnknown); + SetDlgItemText(hDlg, IDC_LP_TIME, szUnknown); + } + else + { + // time and date are known + SetDlgItemDate(hDlg, IDC_LP_DATE, &lastUpdate); + SetDlgItemTime(hDlg, IDC_LP_TIME, &lastUpdate); + } + + // initialize source display name + LPTSTR lpszDisplayName; + lpLinkInfo->GetLinkSource(lpOP->dwLink, &lpszDisplayName, + &lpLP->nFileLength, NULL, NULL, NULL, NULL); + SetDlgItemText(hDlg, IDC_LP_LINKSOURCE, lpszDisplayName); + OleStdFree(lpszDisplayName); + + // initialize automatic/manual update field + DWORD dwUpdate; + lpLinkInfo->GetLinkUpdateOptions(lpOP->dwLink, &dwUpdate); + CheckRadioButton(hDlg, IDC_LP_AUTOMATIC, IDC_LP_MANUAL, + dwUpdate == OLEUPDATE_ALWAYS ? IDC_LP_AUTOMATIC : IDC_LP_MANUAL); + lpLP->dwUpdate = dwUpdate; + + // Call the hook with lCustData in lParam + UStandardHook((PVOID)lpLP, hDlg, WM_INITDIALOG, wParam, lpOLP->lCustData); + return TRUE; +} + +BOOL CALLBACK LinkPropsDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + // Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + // This will fail under WM_INITDIALOG, where we allocate it. + UINT uHook = 0; + LPLINKPROPS lpLP = (LPLINKPROPS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook); + + // If the hook processed the message, we're done. + if (0 != uHook) + return (BOOL)uHook; + + // Get pointers to important info + LPOLEUILINKPROPS lpOLP = NULL; + LPOLEUIOBJECTPROPS lpOP = NULL; + LPOLEUILINKINFO lpLinkInfo; + if (lpLP != NULL) + { + lpOLP = lpLP->lpOLP; + if (lpOLP != NULL) + { + lpLinkInfo = lpOLP->lpOP->lpLinkInfo; + lpOP = lpOLP->lpOP; + } + } + + switch (iMsg) + { + case WM_INITDIALOG: + FLinkPropsInit(hDlg, wParam, lParam); + return TRUE; + + case WM_COMMAND: + switch (wID) + { + case IDC_LP_OPENSOURCE: + // force update + SendMessage(GetParent(hDlg), PSM_APPLY, 0, 0); + + // launch the object + lpLinkInfo->OpenLinkSource(lpOP->dwLink); + + // close the dialog + SendMessage(GetParent(hDlg), WM_COMMAND, IDOK, 0); + break; + + case IDC_LP_UPDATENOW: + { + // force update + SendMessage(GetParent(hDlg), PSM_APPLY, 0, 0); + + // update the link via container provided callback + if (lpLinkInfo->UpdateLink(lpOP->dwLink, TRUE, FALSE) != NOERROR) + break; + + // since link was updated, update the time/date display + SYSTEMTIME systemTime; GetSystemTime(&systemTime); + FILETIME localTime; SystemTimeToFileTime(&systemTime, &localTime); + FILETIME lastUpdate; LocalFileTimeToFileTime(&localTime, &lastUpdate); + lpLinkInfo->GetLastUpdate(lpOP->dwLink, &lastUpdate); + + SetDlgItemDate(hDlg, IDC_LP_DATE, &lastUpdate); + SetDlgItemTime(hDlg, IDC_LP_TIME, &lastUpdate); + + // modification that cannot be undone + SendMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0); + } + break; + + case IDC_LP_BREAKLINK: + { + UINT uRet = PopupMessage(GetParent(hDlg), IDS_LINKPROPS, + IDS_CONFIRMBREAKLINK, MB_YESNO|MB_ICONQUESTION); + if (uRet == IDYES) + { + // cancel the link turning it into a picture + lpLinkInfo->CancelLink(lpOP->dwLink); + + // allow other pages to refresh + lpOP->dwFlags &= ~OPF_OBJECTISLINK; + SendMessage(GetParent(hDlg), PSM_QUERYSIBLINGS, + OLEUI_QUERY_LINKBROKEN, 0); + + // remove the links page (since this is no longer a link) + SendMessage(GetParent(hDlg), PSM_REMOVEPAGE, 2, 0); + + } + } + break; + + case IDC_LP_CHANGESOURCE: + { + // get current source in OLE memory + UINT nLen = GetWindowTextLength(GetDlgItem(hDlg, IDC_LP_LINKSOURCE)); + LPTSTR lpszDisplayName = (LPTSTR)OleStdMalloc((nLen+1) * sizeof(TCHAR)); + GetDlgItemText(hDlg, IDC_LP_LINKSOURCE, lpszDisplayName, nLen+1); + if (lpszDisplayName == NULL) + break; + + // fill in the OLEUICHANGESOURCE struct + OLEUICHANGESOURCE cs; memset(&cs, 0, sizeof(cs)); + cs.cbStruct = sizeof(cs); + cs.hWndOwner = GetParent(GetParent(hDlg)); + cs.dwFlags = CSF_ONLYGETSOURCE; + if (lpOP->dwFlags & OPF_SHOWHELP) + cs.dwFlags |= CSF_SHOWHELP; + cs.lpOleUILinkContainer = lpLinkInfo; + cs.dwLink = lpOP->dwLink; + cs.lpszDisplayName = lpszDisplayName; + cs.nFileLength = lpLP->nFileLength; + + // allow the Change Souce dialog to be hooked + UINT uRet = UStandardHook(lpLP, hDlg, uMsgChangeSource, 0, + (LPARAM)&cs); + if (!uRet) + { + uRet = (OLEUI_OK == OleUIChangeSource(&cs)); + SetFocus(hDlg); + } + if (uRet) + { + OleStdFree(lpLP->lpszDisplayName); + + lpLP->lpszDisplayName = cs.lpszDisplayName; + lpLP->nFileLength = cs.nFileLength; + SetDlgItemText(hDlg, IDC_LP_LINKSOURCE, lpLP->lpszDisplayName); + + OleStdFree(cs.lpszTo); + OleStdFree(cs.lpszFrom); + + SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0); + } + } + break; + + case IDC_LP_MANUAL: + case IDC_LP_AUTOMATIC: + SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0); + break; + } + break; + + case WM_NOTIFY: + switch (((NMHDR*)lParam)->code) + { + case PSN_HELP: + PostMessage(GetParent(GetParent(hDlg)), uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_LINKPROPS, 0)); + break; + case PSN_APPLY: + { + // update link update options first + DWORD dwUpdate; + if (SendDlgItemMessage(hDlg, IDC_LP_AUTOMATIC, BM_GETCHECK, 0, 0)) + dwUpdate = OLEUPDATE_ALWAYS; + else + dwUpdate = OLEUPDATE_ONCALL; + if (dwUpdate != lpLP->dwUpdate) + lpLinkInfo->SetLinkUpdateOptions(lpOP->dwLink, dwUpdate); + + // set the link source + if (lpLP->lpszDisplayName != NULL) + { + // try setting with validation first + ULONG chEaten; + if (NOERROR != lpLinkInfo->SetLinkSource(lpOP->dwLink, + lpLP->lpszDisplayName, lpLP->nFileLength, &chEaten, + TRUE)) + { + UINT uRet = PopupMessage(GetParent(hDlg), IDS_LINKPROPS, + IDS_INVALIDSOURCE, MB_ICONQUESTION|MB_YESNO); + if (uRet == IDYES) + { + // user wants to correct the link source + SetWindowLong(hDlg, DWL_MSGRESULT, 1); + return TRUE; + } + // user doesn't care if link source is bogus + lpLinkInfo->SetLinkSource(lpOP->dwLink, + lpLP->lpszDisplayName, lpLP->nFileLength, &chEaten, + FALSE); + } + OleStdFree(lpLP->lpszDisplayName); + lpLP->lpszDisplayName = NULL; + } + } + SetWindowLong(hDlg, DWL_MSGRESULT, 0); + PostMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0); + return TRUE; + } + break; + + case WM_DESTROY: + if (lpLP != NULL) + { + OleStdFree(lpLP->lpszDisplayName); + lpLP->lpszDisplayName = NULL; + } + StandardCleanup((PVOID)lpLP, hDlg); + return TRUE; + + default: + if (lpOP != NULL && lpOP->lpPS->hwndParent && iMsg == uMsgBrowseOFN) + { + SendMessage(lpOP->lpPS->hwndParent, uMsgBrowseOFN, wParam, lParam); + } + break; + } + + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// Property Page initialization code + +struct PROPPAGEDATA +{ + UINT nTemplateID; + UINT nTemplateID4; + DLGPROC pfnDlgProc; + size_t nPtrOffset; +}; + +#define PTR_OFFSET(x) offsetof(OLEUIOBJECTPROPS, x) +static PROPPAGEDATA pageData[3] = +{ + { IDD_GNRLPROPS,IDD_GNRLPROPS4, GnrlPropsDialogProc, PTR_OFFSET(lpGP), }, + { IDD_VIEWPROPS,IDD_VIEWPROPS, ViewPropsDialogProc, PTR_OFFSET(lpVP), }, + { IDD_LINKPROPS,IDD_LINKPROPS4, LinkPropsDialogProc, PTR_OFFSET(lpLP), }, +}; +#undef PTR_OFFSET + +static UINT WINAPI PrepareObjectProperties(LPOLEUIOBJECTPROPS lpOP) +{ + // setup back pointers from page structs to sheet structs + lpOP->lpGP->lpOP = lpOP; + lpOP->lpVP->lpOP = lpOP; + if ((lpOP->dwFlags & OPF_OBJECTISLINK) && lpOP->lpLP != NULL) + lpOP->lpLP->lpOP = lpOP; + + // pre-init GNRLPROPS struct + LPOLEUIGNRLPROPS lpGP = lpOP->lpGP; + + // get ready to initialize PROPSHEET structs + LPPROPSHEETHEADER lpPS = lpOP->lpPS; + LPPROPSHEETPAGE lpPPs = (LPPROPSHEETPAGE)lpPS->ppsp; + UINT nMaxPage = (lpOP->dwFlags & OPF_OBJECTISLINK ? 3 : 2); + + // setting OPF_NOFILLDEFAULT allows you to control almost everything + if (!(lpOP->dwFlags & OPF_NOFILLDEFAULT)) + { + // get array of 3 PROPSHEETPAGE structs if not provided + if (lpPS->ppsp == NULL) + { + lpPS->nPages = nMaxPage; + lpPPs = (LPPROPSHEETPAGE) + OleStdMalloc(nMaxPage * sizeof(PROPSHEETPAGE)); + if (lpPPs == NULL) + return OLEUI_ERR_OLEMEMALLOC; + memset(lpPPs, 0, nMaxPage * sizeof(PROPSHEETPAGE)); + lpPS->ppsp = lpPPs; + } + + // fill in defaults for lpPS + lpPS->dwFlags |= PSH_PROPSHEETPAGE; + if (lpPS->hInstance == NULL) + lpPS->hInstance = _g_hOleStdResInst; + + // fill Defaults for Standard Property Pages + for (UINT nPage = 0; nPage < nMaxPage; nPage++) + { + LPPROPSHEETPAGE lpPP = &lpPPs[nPage]; + PROPPAGEDATA* pPageData = &pageData[nPage]; + if (lpPP->dwSize == 0) + lpPP->dwSize = sizeof(PROPSHEETPAGE); + if (lpPP->hInstance == NULL) + lpPP->hInstance = _g_hOleStdResInst; + UINT nIDD = bWin4 ? + pPageData->nTemplateID4 : pPageData->nTemplateID; + if (lpPP->pszTemplate == NULL) + lpPP->pszTemplate = MAKEINTRESOURCE(nIDD); + } + } + + // fill Property Page info which cannot be overridden + for (UINT nPage = 0; nPage < nMaxPage; nPage++) + { + LPPROPSHEETPAGE lpPP = &lpPPs[nPage]; + PROPPAGEDATA* pPageData = &pageData[nPage]; + lpPP->pfnDlgProc = pPageData->pfnDlgProc; + lpPP->lParam = (LONG) + *(OLEUIGNRLPROPS**)((LPBYTE)lpOP + pPageData->nPtrOffset); + } + return OLEUI_SUCCESS; +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/private/ole2ui32/ole2ui.cpp b/private/ole2ui32/ole2ui.cpp new file mode 100644 index 000000000..30828b946 --- /dev/null +++ b/private/ole2ui32/ole2ui.cpp @@ -0,0 +1,1036 @@ +/* + * OLE2UI.CPP + * + * Contains initialization routines and miscellaneous API implementations for + * the OLE 2.0 User Interface Support Library. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "common.h" +#include "utility.h" +#include "resimage.h" +#include "iconbox.h" +#include <commdlg.h> +#include <stdarg.h> + +OLEDBGDATA + +// Registered messages for use with all the dialogs, registered in LibMain +UINT uMsgHelp; +UINT uMsgEndDialog; +UINT uMsgBrowse; +UINT uMsgChangeIcon; +UINT uMsgFileOKString; +UINT uMsgCloseBusyDlg; +UINT uMsgConvert; +UINT uMsgChangeSource; +UINT uMsgAddControl; +UINT uMsgBrowseOFN; + +// local function prototypes +BOOL CALLBACK PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam); + +// local definition +#define WM_U_UPDATELINK (WM_USER+0x2000) +#define WM_U_SHOWWINDOW (WM_USER+0x2001) + +// local structure definition +typedef struct tagUPDATELINKS +{ + LPOLEUILINKCONTAINER lpOleUILinkCntr; // pointer to Link Container + UINT cLinks; // total number of links + UINT cUpdated; // number of links updated + DWORD dwLink; // pointer to link + BOOL fError; // error flag + LPTSTR lpszTitle; // caption for dialog box +} UPDATELINKS, *PUPDATELINKS, FAR *LPUPDATELINKS; + + +/* + * OleUIInitialize + * + * NOTE: This function should only be called by your application IF it is + * using the static-link version of this library. If the DLL version is + * being used, this function is automatically called from the OLEDLG DLL's + * LibMain. + * + * Purpose: + * Initializes the OLE UI Library. Registers the OLE clipboard formats + * used in the Paste Special dialog, registers private custom window + * messages, and registers window classes of the "Result Image" + * and "Icon Box" custom controls used in the UI dialogs. + * + * Parameters: + * + * hInstance HINSTANCE of the module where the UI library resources + * and Dialog Procedures are contained. If you are calling + * this function yourself, this should be the instance handle + * of your application. + * + * hPrevInst HINSTANCE of the previous application instance. + * This is the parameter passed in to your WinMain. For + * the DLL version, this should always be set to zero (for + * WIN16 DLLs). + * + * Return Value: + * BOOL TRUE if initialization was successful. + * FALSE otherwise. + */ + +#pragma code_seg(".text$initseg") + +BOOL bWin4; // TRUE if running Windows4 or greater +BOOL bSharedData; // TRUE if running Win32s (it has shared data) + +static DWORD tlsIndex= (DWORD)-1; +static TASKDATA taskData; + +STDAPI_(TASKDATA*) GetTaskData() +{ + TASKDATA* pData; + if (tlsIndex == (DWORD)-1) + pData = &taskData; + else + pData = (TASKDATA*)TlsGetValue(tlsIndex); + return pData; +} + +DWORD WINAPI _AfxTlsAlloc() +{ + DWORD dwResult = TlsAlloc(); + DWORD dwVersion = GetVersion(); + if ((dwVersion & 0x80000000) && (BYTE)dwVersion <= 3) + { + while (dwResult >= 0 && dwResult <= 2) + dwResult = TlsAlloc(); + } + return dwResult; +} + +static int nInitCount; + +STDAPI_(BOOL) OleUIUnInitialize(); + +STDAPI_(BOOL) OleUIInitialize(HINSTANCE hInstance, + HINSTANCE hPrevInst) +{ + OleDbgOut1(TEXT("OleUIInitialize called.\r\n")); + + // Cache information about the windows version we are running + DWORD dwVersion = GetVersion(); + bWin4 = LOBYTE(dwVersion) >= 4; + bSharedData = !bWin4 && (dwVersion & 0x80000000); + + if (nInitCount == 0) + { + if (bSharedData) + { + // allocate thread local storage on Win32s + tlsIndex = _AfxTlsAlloc(); + if (tlsIndex == (DWORD)-1) + return FALSE; + } + } + ++nInitCount; + + // Setup process local storage if necessary + if (tlsIndex != (DWORD)-1) + { + void* pData = LocalAlloc(LPTR, sizeof(TASKDATA)); + if (pData == NULL) + { + if (nInitCount == 0) + { + OleUIUnInitialize(); + return FALSE; + } + } + TlsSetValue(tlsIndex, pData); + } + + // Initialize OleStd functions + OleStdInitialize(hInstance, hInstance); + + // Register messages we need for the dialogs. + uMsgHelp = RegisterWindowMessage(SZOLEUI_MSG_HELP); + uMsgEndDialog = RegisterWindowMessage(SZOLEUI_MSG_ENDDIALOG); + uMsgBrowse = RegisterWindowMessage(SZOLEUI_MSG_BROWSE); + uMsgChangeIcon = RegisterWindowMessage(SZOLEUI_MSG_CHANGEICON); + uMsgFileOKString = RegisterWindowMessage(FILEOKSTRING); + uMsgCloseBusyDlg = RegisterWindowMessage(SZOLEUI_MSG_CLOSEBUSYDIALOG); + uMsgConvert = RegisterWindowMessage(SZOLEUI_MSG_CONVERT); + uMsgChangeSource = RegisterWindowMessage(SZOLEUI_MSG_CHANGESOURCE); + uMsgAddControl = RegisterWindowMessage(SZOLEUI_MSG_ADDCONTROL); + uMsgBrowseOFN = RegisterWindowMessage(SZOLEUI_MSG_BROWSE_OFN); + + if (!FResultImageInitialize(hInstance, hPrevInst)) + { + OleDbgOut1(TEXT("OleUIInitialize: FResultImageInitialize failed. Terminating.\r\n")); + return 0; + } + if (!FIconBoxInitialize(hInstance, hPrevInst)) + { + OleDbgOut1(TEXT("OleUIInitialize: FIconBoxInitialize failed. Terminating.\r\n")); + return 0; + } + return TRUE; +} + +#pragma code_seg() + + +/* + * OleUIUnInitialize + * + * NOTE: This function should only be called by your application IF it is using + * the static-link version of this library. If the DLL version is being used, + * this function is automatically called from the DLL's LibMain. + * + * Purpose: + * Uninitializes OLE UI libraries. Deletes any resources allocated by the + * library. + * + * Return Value: + * BOOL TRUE if successful, FALSE if not. Current implementation always + * returns TRUE. + */ +STDAPI_(BOOL) OleUIUnInitialize() +{ + IconBoxUninitialize(); + ResultImageUninitialize(); + + // Cleanup thread local storage + if (tlsIndex != (DWORD)-1) + { + TASKDATA* pData = (TASKDATA*)TlsGetValue(tlsIndex); + TlsSetValue(tlsIndex, NULL); + if (pData != NULL) + { + if (pData->hInstCommCtrl != NULL) + FreeLibrary(pData->hInstCommCtrl); + if (pData->hInstShell != NULL) + FreeLibrary(pData->hInstShell); + if (pData->hInstComDlg != NULL) + FreeLibrary(pData->hInstComDlg); + LocalFree(pData); + } + } + + // Last chance cleanup + if (nInitCount == 1) + { + // cleanup thread local storage + if (tlsIndex != (DWORD)-1) + { + TlsFree(tlsIndex); + tlsIndex = (DWORD)-1; + } + } + if (nInitCount != 0) + --nInitCount; + + return TRUE; +} + + +/* + * OleUIAddVerbMenu + * + * Purpose: + * Add the Verb menu for the specified object to the given menu. If the + * object has one verb, we directly add the verb to the given menu. If + * the object has multiple verbs we create a cascading sub-menu. + * + * Parameters: + * lpObj LPOLEOBJECT pointing to the selected object. If this + * is NULL, then we create a default disabled menu item. + * + * lpszShortType LPTSTR with short type name (AuxName==2) corresponding + * to the lpOleObj. if the string is NOT known, then NULL + * may be passed. if NULL is passed, then + * IOleObject::GetUserType will be called to retrieve it. + * if the caller has the string handy, then it is faster + * to pass it in. + * + * hMenu HMENU in which to make modifications. + * + * uPos Position of the menu item + * + * uIDVerbMin UINT ID value at which to start the verbs. + * verb_0 = wIDMVerbMin + verb_0 + * verb_1 = wIDMVerbMin + verb_1 + * verb_2 = wIDMVerbMin + verb_2 + * etc. + * uIDVerbMax UINT maximum ID value allowed for object verbs. + * if uIDVerbMax==0 then any ID value is allowed + * + * bAddConvert BOOL specifying whether or not to add a "Convert" item + * to the bottom of the menu (with a separator). + * + * idConvert UINT ID value to use for the Convert menu item, if + * bAddConvert is TRUE. + * + * lphMenu HMENU FAR * of the cascading verb menu if it's created. + * If there is only one verb, this will be filled with NULL. + * + * + * Return Value: + * BOOL TRUE if lpObj was valid and we added at least one verb + * to the menu. FALSE if lpObj was NULL and we created + * a disabled default menu item + */ + +STDAPI_(BOOL) OleUIAddVerbMenu(LPOLEOBJECT lpOleObj, + LPCTSTR lpszShortType, + HMENU hMenu, UINT uPos, + UINT uIDVerbMin, UINT uIDVerbMax, + BOOL bAddConvert, UINT idConvert, + HMENU FAR *lphMenu) +{ + LPPERSISTSTORAGE lpPS=NULL; + LPENUMOLEVERB lpEnumOleVerb = NULL; + OLEVERB oleverb; + LPCTSTR lpszShortTypeName = lpszShortType; + LPTSTR lpszVerbName = NULL; + HRESULT hrErr; + BOOL fStatus; + BOOL fIsLink = FALSE; + BOOL fResult = TRUE; + BOOL fAddConvertItem = FALSE; + int cVerbs = 0; + UINT uFlags = MF_BYPOSITION; + static BOOL fFirstTime = TRUE; + static TCHAR szBuffer[OLEUI_OBJECTMENUMAX]; + static TCHAR szNoObjectCmd[OLEUI_OBJECTMENUMAX]; + static TCHAR szObjectCmd1Verb[OLEUI_OBJECTMENUMAX]; + static TCHAR szLinkCmd1Verb[OLEUI_OBJECTMENUMAX]; + static TCHAR szObjectCmdNVerb[OLEUI_OBJECTMENUMAX]; + static TCHAR szLinkCmdNVerb[OLEUI_OBJECTMENUMAX]; + static TCHAR szUnknown[OLEUI_OBJECTMENUMAX]; + static TCHAR szEdit[OLEUI_OBJECTMENUMAX]; + static TCHAR szConvert[OLEUI_OBJECTMENUMAX]; + + // Set fAddConvertItem flag + if (bAddConvert & (idConvert != 0)) + fAddConvertItem = TRUE; + + // only need to load the strings the 1st time + if (fFirstTime) + { + if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITNOOBJCMD, + szNoObjectCmd, OLEUI_OBJECTMENUMAX)) + return FALSE; + if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITLINKCMD_1VERB, + szLinkCmd1Verb, OLEUI_OBJECTMENUMAX)) + return FALSE; + if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITOBJECTCMD_1VERB, + szObjectCmd1Verb, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITLINKCMD_NVERB, + szLinkCmdNVerb, OLEUI_OBJECTMENUMAX)) + return FALSE; + if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITOBJECTCMD_NVERB, + szObjectCmdNVerb, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIUNKNOWN, + szUnknown, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDIT, + szEdit, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UICONVERT, + szConvert, OLEUI_OBJECTMENUMAX) && fAddConvertItem) + return FALSE; + + fFirstTime = FALSE; + } + + // Delete whatever menu may happen to be here already. + DeleteMenu(hMenu, uPos, uFlags); + + if (lphMenu == NULL || IsBadWritePtr(lphMenu, sizeof(HMENU))) + { + goto AVMError; + } + *lphMenu=NULL; + + if ((!lpOleObj) || IsBadReadPtr(lpOleObj, sizeof (IOleObject))) + goto AVMError; + + if ((!lpszShortTypeName) || IsBadReadPtr(lpszShortTypeName, sizeof(TCHAR))) + { + // get the Short form of the user type name for the menu + OLEDBG_BEGIN2(TEXT("IOleObject::GetUserType called\r\n")) +#if defined(WIN32) && !defined(UNICODE) + LPOLESTR wszShortTypeName = NULL; + lpszShortTypeName = NULL; + hrErr = lpOleObj->GetUserType( + USERCLASSTYPE_SHORT, + &wszShortTypeName); + if (NULL != wszShortTypeName) + { + UINT uLen = WTOALEN(wszShortTypeName); + lpszShortTypeName = (LPTSTR) OleStdMalloc(uLen); + if (NULL != lpszShortTypeName) + { + WTOA((char *)lpszShortTypeName, wszShortTypeName, uLen); + } + OleStdFree(wszShortTypeName); + } +#else + hrErr = lpOleObj->GetUserType( + USERCLASSTYPE_SHORT, + (LPTSTR FAR*)&lpszShortTypeName); +#endif + OLEDBG_END2 + + if (NOERROR != hrErr) + OleDbgOutHResult(TEXT("IOleObject::GetUserType returned"), hrErr); + } + + // check if the object is a link + fIsLink = OleStdIsOleLink((LPUNKNOWN)lpOleObj); + + // Get the verb enumerator from the OLE object + OLEDBG_BEGIN2(TEXT("IOleObject::EnumVerbs called\r\n")) + hrErr = lpOleObj->EnumVerbs( + (LPENUMOLEVERB FAR*)&lpEnumOleVerb + ); + OLEDBG_END2 + + if (NOERROR != hrErr) + OleDbgOutHResult(TEXT("IOleObject::EnumVerbs returned"), hrErr); + + if (!(*lphMenu = CreatePopupMenu())) + goto AVMError; + + // loop through all verbs + while (lpEnumOleVerb != NULL) + { + hrErr = lpEnumOleVerb->Next( + 1, + (LPOLEVERB)&oleverb, + NULL + ); + if (NOERROR != hrErr) + break; // DONE! no more verbs + + /* OLE2NOTE: negative verb numbers and verbs that do not + ** indicate ONCONTAINERMENU should NOT be put on the verb menu + */ + if (oleverb.lVerb < 0 || + ! (oleverb.grfAttribs & OLEVERBATTRIB_ONCONTAINERMENU)) + { + /* OLE2NOTE: we must still free the verb name string */ + if (oleverb.lpszVerbName) + OleStdFree(oleverb.lpszVerbName); + continue; + } + + // we must free the previous verb name string + if (lpszVerbName) + OleStdFree(lpszVerbName); + +#if defined(WIN32) && !defined(UNICODE) + lpszVerbName = NULL; + if (NULL != oleverb.lpszVerbName) + { + UINT uLen = WTOALEN(oleverb.lpszVerbName); + lpszVerbName = (LPTSTR) OleStdMalloc(uLen); + if (NULL != lpszVerbName) + { + WTOA(lpszVerbName, oleverb.lpszVerbName, uLen); + } + OleStdFree(oleverb.lpszVerbName); + } +#else + lpszVerbName = oleverb.lpszVerbName; +#endif + if ( 0 == uIDVerbMax || + (uIDVerbMax >= uIDVerbMin+(UINT)oleverb.lVerb) ) + { + fStatus = InsertMenu( + *lphMenu, + (UINT)-1, + MF_BYPOSITION | (UINT)oleverb.fuFlags, + uIDVerbMin+(UINT)oleverb.lVerb, + lpszVerbName + ); + if (! fStatus) + goto AVMError; + + cVerbs++; + } + } + + // Add the separator and "Convert" menu item. + if (fAddConvertItem) + { + if (0 == cVerbs) + { + LPTSTR lpsz; + + // if object has no verbs, then use "Convert" as the obj's verb + lpsz = lpszVerbName = OleStdCopyString(szConvert); + uIDVerbMin = idConvert; + + // remove "..." from "Convert..." string; it will be added later + if (lpsz) + { + while(*lpsz && *lpsz != '.') + lpsz = CharNext(lpsz); + *lpsz = '\0'; + } + } + + if (cVerbs > 0) + { + fStatus = InsertMenu(*lphMenu, + (UINT)-1, + MF_BYPOSITION | MF_SEPARATOR, + (UINT)0, + (LPCTSTR)NULL); + if (! fStatus) + goto AVMError; + } + + /* add convert menu */ + fStatus = InsertMenu(*lphMenu, + (UINT)-1, + MF_BYPOSITION, + idConvert, + (LPCTSTR)szConvert); + if (! fStatus) + goto AVMError; + + cVerbs++; + } + + + /* + * Build the appropriate menu based on the number of verbs found + * + */ + if (cVerbs == 0) + { + // there are NO verbs (not even Convert...). set the menu to be + // "<short type> &Object/Link" and gray it out. + wsprintf( + szBuffer, + (fIsLink ? szLinkCmdNVerb : szObjectCmdNVerb), + (lpszShortTypeName ? lpszShortTypeName : TEXT("")) + ); + uFlags |= MF_GRAYED; + + fResult = FALSE; + DestroyMenu(*lphMenu); + *lphMenu = NULL; + + } + else if (cVerbs == 1) + { + //One verb without Convert, one item. + LPTSTR lpsz = (fIsLink ? szLinkCmd1Verb : szObjectCmd1Verb); + + // strip ampersands from lpszVerbName to ensure that + // the right character is used as the menu key + LPTSTR pchIn; + LPTSTR pchOut; + pchIn = pchOut = lpszVerbName; + while (*pchIn) + { + while (*pchIn && '&' == *pchIn) + { + pchIn++; + } + *pchOut = *pchIn; + pchOut++; + pchIn++; + } + *pchOut = 0; + + FormatString2(szBuffer, lpsz, lpszVerbName, lpszShortTypeName); + + // if only "verb" is "Convert..." then append the ellipses + if (fAddConvertItem) + lstrcat(szBuffer, TEXT("...")); + + DestroyMenu(*lphMenu); + *lphMenu=NULL; + } + else + { + + //Multiple verbs or one verb with Convert, add the cascading menu + wsprintf( + szBuffer, + (fIsLink ? szLinkCmdNVerb: szObjectCmdNVerb), + (lpszShortTypeName ? lpszShortTypeName : TEXT("")) + ); + uFlags |= MF_ENABLED | MF_POPUP; + uIDVerbMin=(UINT)*lphMenu; + } + + if (!InsertMenu(hMenu, uPos, uFlags, uIDVerbMin, szBuffer)) + { +AVMError: + InsertMenu(hMenu, uPos, MF_GRAYED | uFlags, + uIDVerbMin, szNoObjectCmd); + fResult = FALSE; + } + + if (lpszVerbName) + OleStdFree(lpszVerbName); + if (!lpszShortType && lpszShortTypeName) + OleStdFree((LPVOID)lpszShortTypeName); + if (lpEnumOleVerb) + lpEnumOleVerb->Release(); + return fResult; +} + +///////////////////////////////////////////////////////////////////////////// +// Support for special error prompts + +typedef struct tagPROMPTUSER +{ + va_list argptr; + UINT nIDD; // dialog/help ID + LPTSTR szTitle; +} PROMPTUSER, *PPROMPTUSER, FAR* LPPROMPTUSER; + +/* PromptUserDlgProc + * ----------------- + * + * Purpose: + * Dialog procedure used by OleUIPromptUser(). Returns when a button is + * clicked in the dialog box and the button id is return. + * + * Parameters: + * hDlg + * iMsg + * wParam + * lParam + * + * Returns: + * + */ +BOOL CALLBACK PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + switch (iMsg) + { + case WM_INITDIALOG: + { + SendDlgItemMessage(hDlg, IDC_PU_ICON, + STM_SETICON, (WPARAM)LoadIcon(NULL, IDI_EXCLAMATION), 0L); + + LPPROMPTUSER lpPU = (LPPROMPTUSER)lParam; + SetProp(hDlg, STRUCTUREPROP, lpPU); + SetWindowText(hDlg, lpPU->szTitle); + + TCHAR szFormat[256]; + GetDlgItemText(hDlg, IDC_PU_TEXT, szFormat, + sizeof(szFormat)/sizeof(TCHAR)); + TCHAR szBuf[256]; + wvsprintf(szBuf, szFormat, lpPU->argptr); + SetDlgItemText(hDlg, IDC_PU_TEXT, szBuf); + } + return TRUE; + + case WM_COMMAND: + EndDialog(hDlg, wParam); + return TRUE; + + default: + return FALSE; + } +} + +//+--------------------------------------------------------------------------- +// +// Function: OleUIPromptUserInternal +// +// Synopsis: internal entry point to start the PromptUser dialog +// Used to support both ANSI and Unicode entrypoints +// +// Arguments: [nTemplate] - dialog template ID +// [szTitle] - the title string +// [hwndParent] - the dialog's parent window +// [arglist] - variable argument list +// +// History: 12-01-94 stevebl Created +// +//---------------------------------------------------------------------------- + +int OleUIPromptUserInternal(int nTemplate, HWND hwndParent, LPTSTR szTitle, va_list arglist) +{ + PROMPTUSER pu; + pu.szTitle = szTitle; + pu.argptr = arglist; + pu.nIDD = nTemplate; + return (DialogBoxParam(_g_hOleStdResInst, MAKEINTRESOURCE(nTemplate), hwndParent, + PromptUserDlgProc, (LPARAM)&pu)); +} + +/* OleUIPromptUser + * --------------- + * + * Purpose: + * Popup a dialog box with the specified template and returned the + * response (button id) from the user. + * + * Parameters: + * nTemplate resource number of the dialog + * hwndParent parent of the dialog box + * ... title of the dialog box followed by argument list + * for the format string in the static control + * (IDC_PU_TEXT) of the dialog box. + * The caller has to make sure that the correct number + * and type of argument are passed in. + * + * Returns: + * button id selected by the user (template dependent) + * + * Comments: + * the following message dialog boxes are supported: + * + * IDD_LINKSOURCEUNAVAILABLE -- Link source is unavailable + * VARARG Parameters: + * None. + * Used for the following error codes: + * OLE_E_CANT_BINDTOSOURCE + * STG_E_PATHNOTFOUND + * (sc >= MK_E_FIRST) && (sc <= MK_E_LAST) -- any Moniker error + * any unknown error if object is a link + * + * IDD_SERVERNOTFOUND -- server registered but NOT found + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of object + * Used for the following error codes: + * CO_E_APPNOTFOUND + * CO_E_APPDIDNTREG + * any unknown error if object is an embedded object + * + * IDD_SERVERNOTREG -- server NOT registered + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of object + * Used for the following error codes: + * REGDB_E_CLASSNOTREG + * OLE_E_STATIC -- static object with no server registered + * + * IDD_LINKTYPECHANGED -- class of link source changed since last binding + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of ole link source + * Used for the following error codes: + * OLE_E_CLASSDIFF + * + * IDD_LINKTYPECHANGED -- class of link source changed since last binding + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of ole link source + * Used for the following error codes: + * OLE_E_CLASSDIFF + * + * IDD_OUTOFMEMORY -- out of memory + * VARARG Parameters: + * None. + * Used for the following error codes: + * E_OUTOFMEMORY + * + */ + +int FAR CDECL OleUIPromptUser(int nTemplate, HWND hwndParent, ...) +{ + va_list arglist; + va_start(arglist, hwndParent); + LPTSTR szTitle = va_arg(arglist, LPTSTR); + int nRet = OleUIPromptUserInternal(nTemplate, hwndParent, szTitle, arglist); + va_end(arglist); + + return nRet; +} + +/* UpdateLinksDlgProc + * ------------------ + * + * Purpose: + * Dialog procedure used by OleUIUpdateLinks(). It will enumerate all + * all links in the container and updates all automatic links. + * Returns when the Stop Button is clicked in the dialog box or when all + * links are updated + * + * Parameters: + * hDlg + * iMsg + * wParam + * lParam pointer to the UPDATELINKS structure + * + * Returns: + * + */ + +#define UPDATELINKS_STARTDELAY 2000 // delay before 1st link updates + +BOOL CALLBACK UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + LPUPDATELINKS FAR* lplpUL = NULL; + HANDLE gh; + static BOOL fAbort = FALSE; + + // Process the temination message + if (iMsg == uMsgEndDialog) + { + gh = RemoveProp(hDlg, STRUCTUREPROP); + if (NULL != gh) + { + GlobalUnlock(gh); + GlobalFree(gh); + } + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) + { + case WM_INITDIALOG: + { + gh = GlobalAlloc(GHND, sizeof(LPUPDATELINKS)); + SetProp(hDlg, STRUCTUREPROP, gh); + + if (NULL == gh) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L); + return FALSE; + } + + fAbort = FALSE; + lplpUL = (LPUPDATELINKS FAR*)GlobalLock(gh); + + if (!lplpUL) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L); + return FALSE; + } + + if (bWin4) + { + if (StandardInitCommonControls() >= 0) + { + // get rect of the existing "progress" control + RECT rect; + GetWindowRect(GetDlgItem(hDlg, IDC_UL_METER), &rect); + ScreenToClient(hDlg, ((POINT*)&rect)+0); + ScreenToClient(hDlg, ((POINT*)&rect)+1); + + // create progress control in that rect + HWND hProgress = CreateWindowEx( + 0, PROGRESS_CLASS, NULL, WS_CHILD|WS_VISIBLE, + rect.left, rect.top, + rect.right-rect.left, rect.bottom-rect.top, hDlg, + (HMENU)IDC_UL_PROGRESS, _g_hOleStdInst, NULL); + if (hProgress != NULL) + { + // initialize the progress control + SendMessage(hProgress, PBM_SETRANGE, 0, MAKELONG(0, 100)); + + // hide the other "meter" control + StandardShowDlgItem(hDlg, IDC_UL_METER, SW_HIDE); + } + } + } + + *lplpUL = (LPUPDATELINKS)lParam; + if ((*lplpUL)->lpszTitle) + { + SetWindowText(hDlg, (*lplpUL)->lpszTitle); + } + SetTimer(hDlg, 1, UPDATELINKS_STARTDELAY, NULL); + return TRUE; + } + + case WM_TIMER: + KillTimer(hDlg, 1); + gh = GetProp(hDlg, STRUCTUREPROP); + + if (NULL!=gh) + { + // gh was locked previously, lock and unlock to get lplpUL + lplpUL = (LPUPDATELINKS*)GlobalLock(gh); + GlobalUnlock(gh); + } + if (! fAbort && lplpUL) + PostMessage(hDlg, WM_U_UPDATELINK, 0, (LPARAM)(*lplpUL)); + else + PostMessage(hDlg,uMsgEndDialog,OLEUI_CANCEL,0L); + + return 0; + + case WM_COMMAND: // Stop button + fAbort = TRUE; + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + return TRUE; + + case WM_U_UPDATELINK: + { + HRESULT hErr; + int nPercent; + RECT rc; + TCHAR szPercent[5]; // 0% to 100% + HBRUSH hbr; + HDC hDC; + HWND hwndMeter; + MSG msg; + DWORD dwUpdateOpt; + LPUPDATELINKS lpUL = (LPUPDATELINKS)lParam; + + lpUL->dwLink=lpUL->lpOleUILinkCntr->GetNextLink(lpUL->dwLink); + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (! IsDialogMessage(hDlg, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + if (fAbort) + return FALSE; + + if (!lpUL->dwLink) + { + // all links processed + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + return TRUE; + } + + hErr = lpUL->lpOleUILinkCntr->GetLinkUpdateOptions( + lpUL->dwLink, (LPDWORD)&dwUpdateOpt); + + if ((hErr == NOERROR) && (dwUpdateOpt == OLEUPDATE_ALWAYS)) + { + hErr = lpUL->lpOleUILinkCntr->UpdateLink(lpUL->dwLink, FALSE, FALSE); + lpUL->fError |= (hErr != NOERROR); + lpUL->cUpdated++; + + nPercent = (lpUL->cLinks > 0) ? (lpUL->cUpdated * 100 / lpUL->cLinks) : 100; + if (nPercent <= 100) + { + // update percentage + wsprintf(szPercent, TEXT("%d%%"), nPercent); + SetDlgItemText(hDlg, IDC_UL_PERCENT, szPercent); + + HWND hProgress = GetDlgItem(hDlg, IDC_UL_PROGRESS); + if (hProgress == NULL) + { + // update indicator + hwndMeter = GetDlgItem(hDlg, IDC_UL_METER); + GetClientRect(hwndMeter, (LPRECT)&rc); + InflateRect((LPRECT)&rc, -1, -1); + rc.right = (rc.right - rc.left) * nPercent / 100 + rc.left; + hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); + if (hbr) + { + hDC = GetDC(hwndMeter); + if (hDC) + { + FillRect(hDC, (LPRECT)&rc, hbr); + ReleaseDC(hwndMeter, hDC); + } + DeleteObject(hbr); + } + } + else + { + // update the progress indicator + SendMessage(hProgress, PBM_SETPOS, nPercent, 0); + } + } + } + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (! IsDialogMessage(hDlg, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + PostMessage(hDlg, WM_U_UPDATELINK, 0, lParam); + } + return TRUE; + + case WM_U_SHOWWINDOW: + ShowWindow(hDlg, SW_SHOW); + return TRUE; + } + return FALSE; +} + + +/* OleUIUpdateLinkS + * ---------------- + * + * Purpose: + * Update all links in the Link Container and popup a dialog box which + * shows the progress of the updating. + * The process is stopped when the user press Stop button or when all + * links are processed. + * + * Parameters: + * lpOleUILinkCntr pointer to Link Container + * hwndParent parent window of the dialog + * lpszTitle title of the dialog box + * cLinks total number of links + * + * Returns: + * TRUE all links updated successfully or user aborted dialog + * FALSE oherwise + */ +STDAPI_(BOOL) OleUIUpdateLinks( + LPOLEUILINKCONTAINER lpOleUILinkCntr, HWND hwndParent, LPTSTR lpszTitle, int cLinks) +{ + LPUPDATELINKS lpUL = (LPUPDATELINKS)OleStdMalloc(sizeof(UPDATELINKS)); + BOOL fError = TRUE; + + + // Validate interface. + if (NULL == lpOleUILinkCntr || IsBadReadPtr(lpOleUILinkCntr, sizeof(IOleUILinkContainer))) + goto Error; + + + // Validate parent-window handle. NULL is considered valid. + if (NULL != hwndParent && !IsWindow(hwndParent)) + goto Error; + + // Validate the dialog title. NULL is considered valid. + if (NULL != lpszTitle && IsBadReadPtr(lpszTitle, 1)) + goto Error; + + if (cLinks < 0) + goto Error; + + OleDbgAssert(lpOleUILinkCntr && hwndParent && lpszTitle && (cLinks>0)); + OleDbgAssert(lpUL); + + lpUL->lpOleUILinkCntr = lpOleUILinkCntr; + lpUL->cLinks = cLinks; + lpUL->cUpdated = 0; + lpUL->dwLink = 0; + lpUL->fError = FALSE; + lpUL->lpszTitle = lpszTitle; + + DialogBoxParam(_g_hOleStdResInst, MAKEINTRESOURCE(IDD_UPDATELINKS), + hwndParent, UpdateLinksDlgProc, (LPARAM)lpUL); + + fError = lpUL->fError; +Error: + OleStdFree((LPVOID)lpUL); + + return !fError; +} diff --git a/private/ole2ui32/ole2ui.rc b/private/ole2ui32/ole2ui.rc new file mode 100644 index 000000000..315eccec9 --- /dev/null +++ b/private/ole2ui32/ole2ui.rc @@ -0,0 +1,254 @@ +//Microsoft Visual C++ generated resource script. +// +#include "resource.h" +#include "winuser.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "oledlg.dlg" + +IDB_RESULTSEGA BITMAP MOVEABLE PURE "res\\egares.bmp" +IDB_RESULTSVGA BITMAP MOVEABLE PURE "res\\vgares.bmp" +IDB_RESULTSHIRESVGA BITMAP MOVEABLE PURE "res\\hivgares.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef WIN32 +#include <windows.h> +#include <ntverp.h> + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Microsoft Windows(TM) OLE 2.0 User Interface Support" +#define VER_FILEVERSION_STR "1.0" +#undef VER_PRODUCTNAME_STR +#define VER_PRODUCTNAME_STR "Microsoft Windows(TM) OLE 2.0 User Interface Support" +#undef VER_PRODUCTVERSION_STR +#define VER_PRODUCTVERSION_STR "2.01" +#define VER_INTERNALNAME_STR "OLEDLG" +#define VER_ORIGINALFILENAME_STR "OLEDLG.DLL" + +#include "common.ver" + +#else + + +1 VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 2,0,1,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "Microsoft Corporation\0" + VALUE "FileDescription", "Microsoft Windows(TM) OLE 2.0 User Interface Support\0" + VALUE "FileVersion", "1.0\0" + VALUE "InternalName", "OLEDLG\0" + VALUE "LegalCopyright", "Copyright (C) Microsoft Corp. 1995\0" + VALUE "OriginalFilename", "OLEDLG.DLL\0" + VALUE "ProductName", "Microsoft Windows(TM) OLE 2.0 User Interface Support\0" + VALUE "ProductVersion", "2.01\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""winres.h""\r\n" + "#include ""dlgs.h""\r\n" + "#include ""oledlg.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""res/ole2ui.rc2""\r\n" + "\0" +END + +///////////////////////////////////////////////////////////////////////////// +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_FILTERS "All Files (*.*)|*.*|" + IDS_ICONFILTERS "Icon Files|*.exe;*.dll;*.ico|Programs (*.exe)|*.exe|Libraries (*.dll)|*.dll|Icons (*.ico)|*.ico|All Files (*.*)|*.*|" + IDS_BROWSE "Browse" + IDS_OCX_FILTERS "OLE Controls (*.ocx)|*.ocx|Libraries (*.dll)|*.dll|All Files (*.*)|*.*|" + IDS_INSERT "Insert" + IDS_CHNGSRCOKBUTTON "OK" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_IORESULTNEW "Inserts a new %s object into your document." + IDS_IORESULTNEWICON "Inserts a new %s object into your document. It will be displayed as an icon." + IDS_IORESULTFROMFILE1 "Inserts the contents of the file as an object into your document so that you may activate it using the " + IDS_IORESULTFROMFILE2 "program which created it." + IDS_IORESULTFROMFILEICON2 + "program which created it. It will be displayed as an icon." + IDS_IORESULTLINKFILE1 "Inserts a picture of the file contents into your document. The picture will be linked to " + IDS_IORESULTLINKFILE2 "the file so that changes to the file will be reflected in your document." + IDS_IORESULTLINKFILEICON1 + "Inserts a shortcut which represents the file. The shortcut will be linked to " + IDS_IORESULTLINKFILEICON2 + "the file so that changes to the file will be reflected in your document." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_CINOICONSINFILE "There are no icons in %s." + IDS_CIINVALIDFILE "File %s does not exist." + IDS_CIFILEACCESS "Unable to open file %s. Access denied." + IDS_CIFILESHARE "Unable to open file %s. Sharing violation." + IDS_CIFILEOPENFAIL "Unable to open file %s. General failure." + IDS_OLE2UIUNKNOWN "Unknown" + IDS_OLE2UILINK "Link" + IDS_OLE2UIOBJECT "Object" + IDS_OLE2UIEDIT "&Edit" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_CVRESULTCONVERTLINK "A linked object must be converted at the source." + IDS_CVRESULTCONVERTTO "Permanently changes the selected %1 object to a %2 object." + IDS_CVRESULTNOCHANGE "The selected %s object will not be converted." + IDS_CVRESULTDISPLAYASICON " It will be displayed as an icon." + IDS_CVRESULTACTIVATEAS "Every %1 object will be activated as a %2 object" + IDS_CVRESULTACTIVATEDIFF ", but it will not be converted." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_PSPASTEDATA "Inserts the contents of the clipboard into your document as %s." + IDS_PSPASTEOBJECT "Inserts the contents of the clipboard into your document so that you may activate it using %s." + IDS_PSPASTEOBJECTASICON "Inserts the contents of the clipboard into your document so that you may activate it using %s. It will be displayed as an icon." + IDS_PSPASTELINKDATA "Inserts the contents of the clipboard into your document as %s. The data is linked to the source file so that changes to the file will be reflected in your document." + IDS_PSPASTELINKOBJECT "Inserts a picture of the clipboard contents into your document. The picure is linked to the source file so that changes to the file will be reflected in your document." + IDS_PSPASTELINKOBJECTASICON + "Inserts a shortcut which points to the location of the clipboard contents. The shortcut is linked to the source file so that changes to the file will be reflected in your document." + IDS_PSNONOLE "Inserts the contents of the clipboard into your document." + IDS_PSUNKNOWNTYPE "Unknown Type" + IDS_PSUNKNOWNSRC "Unknown Source" + IDS_PSUNKNOWNAPP "the program which created it" +END + +STRINGTABLE DISCARDABLE +BEGIN +#ifdef CHICO + IDS_BZRESULTTEXTBUSY "This action cannot be completed because the ""%1"" program is busy. Click the appropriate button on the task bar to activate the program and correct the problem." + IDS_BZRESULTTEXTNOTRESPONDING + "This action cannot be completed because the ""%1"" program is not responding. Click the appropriate button on the task bar to activate the program and correct the problem." +#else + IDS_BZRESULTTEXTBUSY "This action cannot be completed because the ""%1"" program is busy. Choose ""Switch To"" and correct the problem." + IDS_BZRESULTTEXTNOTRESPONDING + "This action cannot be completed because the ""%1"" program is not responding. Choose ""Switch To"" and correct the problem." +#endif +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_OLESTDNOCREATEFILE "Could not create file!" + IDS_OLESTDNOOPENFILE "Could not open file!" + IDS_OLESTDDISKFULL "Disk full--unable to complete save operation" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_OLE2UICONVERT "&Convert..." + IDS_OLE2UIEDITLINKCMD_1VERB "%1 Linked %2 &Object" + IDS_OLE2UIEDITOBJECTCMD_1VERB "%1 %2 &Object" + IDS_OLE2UIEDITLINKCMD_NVERB "Linked %s &Object" + IDS_OLE2UIEDITOBJECTCMD_NVERB "%s &Object" + IDS_OLE2UIEDITNOOBJCMD "&Object" + IDS_DEFICONLABEL "Document" + IDS_OLE2UIPASTELINKEDTYPE "Linked %s" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LINK_AUTO "Automatic" + IDS_LINK_MANUAL "Manual" + IDS_LINK_UNKNOWN "Unavail" + IDS_LINKS "Links" + IDS_FAILED "Operation failed!" + IDS_CHANGESOURCE "Change Source" + IDS_INVALIDSOURCE "Invalid Source : Do you want to correct it?" + IDS_ERR_GETLINKSOURCE "Fail to get source of the link!" + IDS_ERR_GETLINKUPDATEOPTIONS "Fail to get update option of the link!" + IDS_ERR_ADDSTRING "Fail to add item to ListBox!" + IDS_CHANGEADDITIONALLINKS + "The selected link has been changed.\nThis document contains additional links to\n%s.\n\nChange additional links?" + IDS_CLOSE "Close" + IDS_OBJECTPROPERTIES "%s Properties" + IDS_LINKOBJECTPROPERTIES "Linked %s Properties" + IDS_LINKPROPS "Link Properties" + IDS_CONFIRMBREAKLINK "Breaking a link will disconnect it from its link source. Are you sure you want to break this link?" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_BYTES """%s bytes""" + IDS_ORDERKB "%sKB" + IDS_ORDERMB "%sMB" + IDS_ORDERGB "%sGB" + IDS_ORDERTB "%sTB" + IDS_OBJECTSIZE "%1 (%2 bytes)" + IDS_CANNOTLOADOCX "Unable to load the requested OLE control." + IDS_NODLLREGISTERSERVER "The file does not appear to be a valid OLE control module. Unable to register the OLE control." + IDS_DLLREGISTERFAILED "The OLE control module failed to register correctly." + IDS_ADDCONTROL "Add Control" + IDS_RANGEERROR "The scaling factor specified is not in the correct range. Valid scaling factors are between %1 and %2." + IDS_INVALIDPERCENTAGE "The scaling factor specified is not a valid positive integer." + IDS_VIEWPROPS "View Properties" +END + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "res/ole2ui.rc2" + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/private/ole2ui32/oledlg.def b/private/ole2ui32/oledlg.def new file mode 100644 index 000000000..dea30fe8f --- /dev/null +++ b/private/ole2ui32/oledlg.def @@ -0,0 +1,46 @@ +;/////////////////////////////////////////////////////////////////////////// +; +; ole2ui.def +; +; Definition file for oledlg.dll +; c) Copyright Microsoft Corp. 1992 - 1994 All Rights Reserved +; + +DESCRIPTION 'OLEDLG - OLE 2 Common Dialog Support Library.' +EXPORTS + +; Narrow APIs: + +; OLE Menu APIs +OleUIAddVerbMenuA @1 +OleUICanConvertOrActivateAs @2 + +; OLE Common Dialog APIs +OleUIInsertObjectA @3 +OleUIPasteSpecialA @4 +OleUIEditLinksA @5 +OleUIChangeIconA @6 +OleUIConvertA @7 +OleUIBusyA @8 +OleUIUpdateLinksA @9 +OleUIPromptUserA @10 +OleUIObjectPropertiesA @11 +OleUIChangeSourceA @12 + +; Wide APIs: + +; OLE Menu APIs +OleUIAddVerbMenuW + +; OLE Common Dialog APIs +OleUIInsertObjectW +OleUIPasteSpecialW +OleUIEditLinksW +OleUIChangeIconW +OleUIConvertW +OleUIBusyW +OleUIUpdateLinksW +OleUIPromptUserW +OleUIObjectPropertiesW +OleUIChangeSourceW + diff --git a/private/ole2ui32/oledlgs.h b/private/ole2ui32/oledlgs.h new file mode 100644 index 000000000..d93b62cb9 --- /dev/null +++ b/private/ole2ui32/oledlgs.h @@ -0,0 +1,170 @@ +/*++ BUILD Version: 0002 Increment this if a change has global effects + +Copyright (c) 1993-1995, Microsoft Corporation + +Module Name: + + oledlgs.h + +Abstract: + + Resource ID identifiers for the OLE common dialog boxes. + +--*/ + +// Help Button Identifier +#define IDC_OLEUIHELP 99 + +// Insert Object Dialog identifiers +#define IDC_IO_CREATENEW 2100 +#define IDC_IO_CREATEFROMFILE 2101 +#define IDC_IO_INSERTCONTROL 2102 +#define IDC_IO_LINKFILE 2103 +#define IDC_IO_OBJECTTYPELIST 2104 +#define IDC_IO_DISPLAYASICON 2105 +#define IDC_IO_CHANGEICON 2106 +#define IDC_IO_FILE 2107 +#define IDC_IO_FILEDISPLAY 2108 +#define IDC_IO_RESULTIMAGE 2109 +#define IDC_IO_RESULTTEXT 2110 +#define IDC_IO_ICONDISPLAY 2111 +#define IDC_IO_OBJECTTYPETEXT 2112 +#define IDC_IO_FILETEXT 2113 +#define IDC_IO_FILETYPE 2114 +#define IDC_IO_ADDCONTROL 2115 +#define IDC_IO_CONTROLTYPELIST 2116 + +// Paste Special Dialog identifiers +#define IDC_PS_PASTE 500 +#define IDC_PS_PASTELINK 501 +#define IDC_PS_SOURCETEXT 502 +#define IDC_PS_PASTELIST 503 //{{NOHELP}} +#define IDC_PS_PASTELINKLIST 504 //{{NOHELP}} +#define IDC_PS_DISPLAYLIST 505 +#define IDC_PS_DISPLAYASICON 506 +#define IDC_PS_ICONDISPLAY 507 +#define IDC_PS_CHANGEICON 508 +#define IDC_PS_RESULTIMAGE 509 +#define IDC_PS_RESULTTEXT 510 + +// Change Icon Dialog identifiers +#define IDC_CI_GROUP 120 //{{NOHELP}} +#define IDC_CI_CURRENT 121 +#define IDC_CI_CURRENTICON 122 +#define IDC_CI_DEFAULT 123 +#define IDC_CI_DEFAULTICON 124 +#define IDC_CI_FROMFILE 125 +#define IDC_CI_FROMFILEEDIT 126 +#define IDC_CI_ICONLIST 127 +#define IDC_CI_LABEL 128 //{{NOHELP} +#define IDC_CI_LABELEDIT 129 +#define IDC_CI_BROWSE 130 +#define IDC_CI_ICONDISPLAY 131 + +// Convert Dialog identifiers +#define IDC_CV_OBJECTTYPE 150 +#define IDC_CV_DISPLAYASICON 152 +#define IDC_CV_CHANGEICON 153 +#define IDC_CV_ACTIVATELIST 154 +#define IDC_CV_CONVERTTO 155 +#define IDC_CV_ACTIVATEAS 156 +#define IDC_CV_RESULTTEXT 157 +#define IDC_CV_CONVERTLIST 158 +#define IDC_CV_ICONDISPLAY 165 + +// Edit Links Dialog identifiers +#define IDC_EL_CHANGESOURCE 201 +#define IDC_EL_AUTOMATIC 202 +#define IDC_EL_CANCELLINK 209 +#define IDC_EL_UPDATENOW 210 +#define IDC_EL_OPENSOURCE 211 +#define IDC_EL_MANUAL 212 +#define IDC_EL_LINKSOURCE 216 +#define IDC_EL_LINKTYPE 217 +#define IDC_EL_LINKSLISTBOX 206 +#define IDC_EL_COL1 220 +#define IDC_EL_COL2 221 +#define IDC_EL_COL3 222 + +// Busy dialog identifiers +#define IDC_BZ_RETRY 600 +#define IDC_BZ_ICON 601 +#define IDC_BZ_MESSAGE1 602 //{{NOHELP}} +#define IDC_BZ_SWITCHTO 604 + +// Update Links dialog identifiers +#define IDC_UL_METER 1029 //{{NOHELP}} +#define IDC_UL_STOP 1030 //{{NOHELP}} +#define IDC_UL_PERCENT 1031 //{{NOHELP}} +#define IDC_UL_PROGRESS 1032 //{{NOHELP}} + +// User Prompt dialog identifiers +#define IDC_PU_LINKS 900 //{{NOHELP}} +#define IDC_PU_TEXT 901 //{{NOHELP}} +#define IDC_PU_CONVERT 902 //{{NOHELP}} +#define IDC_PU_ICON 908 //{{NOHELP}} + +// General Properties identifiers +#define IDC_GP_OBJECTNAME 1009 +#define IDC_GP_OBJECTTYPE 1010 +#define IDC_GP_OBJECTSIZE 1011 +#define IDC_GP_CONVERT 1013 +#define IDC_GP_OBJECTICON 1014 //{{NOHELP}} +#define IDC_GP_OBJECTLOCATION 1022 + +// View Properties identifiers +#define IDC_VP_PERCENT 1000 +#define IDC_VP_CHANGEICON 1001 +#define IDC_VP_EDITABLE 1002 +#define IDC_VP_ASICON 1003 +#define IDC_VP_RELATIVE 1005 +#define IDC_VP_SPIN 1006 +#define IDC_VP_SCALETXT 1034 +#define IDC_VP_ICONDISPLAY 1021 +#define IDC_VP_RESULTIMAGE 1033 + +// Link Properties identifiers +#define IDC_LP_OPENSOURCE 1006 +#define IDC_LP_UPDATENOW 1007 +#define IDC_LP_BREAKLINK 1008 +#define IDC_LP_LINKSOURCE 1012 +#define IDC_LP_CHANGESOURCE 1015 +#define IDC_LP_AUTOMATIC 1016 +#define IDC_LP_MANUAL 1017 +#define IDC_LP_DATE 1018 +#define IDC_LP_TIME 1019 + +// Dialog Identifiers as passed in Help messages to identify the source. +#define IDD_INSERTOBJECT 1000 +#define IDD_CHANGEICON 1001 +#define IDD_CONVERT 1002 +#define IDD_PASTESPECIAL 1003 +#define IDD_EDITLINKS 1004 +#define IDD_BUSY 1006 +#define IDD_UPDATELINKS 1007 +#define IDD_CHANGESOURCE 1009 +#define IDD_INSERTFILEBROWSE 1010 +#define IDD_CHANGEICONBROWSE 1011 +#define IDD_CONVERTONLY 1012 +#define IDD_CHANGESOURCE4 1013 +#define IDD_GNRLPROPS 1100 +#define IDD_VIEWPROPS 1101 +#define IDD_LINKPROPS 1102 + +// The following Dialogs are message dialogs used by OleUIPromptUser API +#define IDD_CANNOTUPDATELINK 1008 +#define IDD_LINKSOURCEUNAVAILABLE 1020 +#define IDD_SERVERNOTFOUND 1023 +#define IDD_OUTOFMEMORY 1024 +#define IDD_SERVERNOTREGW 1021 +#define IDD_LINKTYPECHANGEDW 1022 +#define IDD_SERVERNOTREGA 1025 +#define IDD_LINKTYPECHANGEDA 1026 +#ifdef UNICODE +#define IDD_SERVERNOTREG IDD_SERVERNOTREGW +#define IDD_LINKTYPECHANGED IDD_LINKTYPECHANGEDW +#else +#define IDD_SERVERNOTREG IDD_SERVERNOTREGA +#define IDD_LINKTYPECHANGED IDD_LINKTYPECHANGEDA +#endif +///////////////////////////////////////////////////////////////////////////// diff --git a/private/ole2ui32/olestd.cpp b/private/ole2ui32/olestd.cpp new file mode 100644 index 000000000..0701b6c54 --- /dev/null +++ b/private/ole2ui32/olestd.cpp @@ -0,0 +1,816 @@ +/************************************************************************* +** +** OLE 2 Standard Utilities +** +** olestd.c +** +** This file contains utilities that are useful for most standard +** OLE 2.0 compound document type applications. +** +** (c) Copyright Microsoft Corp. 1992 All Rights Reserved +** +*************************************************************************/ + +#include "precomp.h" +#include "common.h" +#include "utility.h" +#include <stdlib.h> +#include <shellapi.h> +#include <wchar.h> + +OLEDBGDATA + +#ifdef _DEBUG +static TCHAR szAssertMemAlloc[] = TEXT("CoGetMalloc failed"); +#endif + +static int IsCloseFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight); + +/* OleStdInitialize +** ---------------- +** Call to initialize this library sample code +** +*/ + +UINT _g_cfObjectDescriptor; +UINT _g_cfLinkSrcDescriptor; +UINT _g_cfEmbedSource; +UINT _g_cfEmbeddedObject; +UINT _g_cfLinkSource; +UINT _g_cfOwnerLink; +UINT _g_cfFileName; +UINT _g_cfFileNameW; + +HINSTANCE _g_hOleStdInst; +HINSTANCE _g_hOleStdResInst; + +#pragma code_seg(".text$initseg") + +STDAPI_(void) OleStdInitialize(HINSTANCE hInstance, HINSTANCE hResInstance) +{ + _g_hOleStdInst = hInstance; + _g_hOleStdResInst = hResInstance ? hResInstance : hInstance; + + _g_cfObjectDescriptor = RegisterClipboardFormat(CF_OBJECTDESCRIPTOR); + _g_cfLinkSrcDescriptor = RegisterClipboardFormat(CF_LINKSRCDESCRIPTOR); + _g_cfEmbedSource = RegisterClipboardFormat(CF_EMBEDSOURCE); + _g_cfEmbeddedObject = RegisterClipboardFormat(CF_EMBEDDEDOBJECT); + _g_cfLinkSource = RegisterClipboardFormat(CF_LINKSOURCE); + _g_cfOwnerLink = RegisterClipboardFormat(CF_OWNERLINK); + _g_cfFileName = RegisterClipboardFormat(CF_FILENAME); + _g_cfFileNameW = RegisterClipboardFormat(CF_FILENAMEW); +} + +#pragma code_seg() + +/* OleStdIsOleLink +** --------------- +** Returns TRUE if the OleObject is infact an OLE link object. this +** checks if IOleLink interface is supported. if so, the object is a +** link, otherwise not. +*/ +STDAPI_(BOOL) OleStdIsOleLink(LPUNKNOWN lpUnk) +{ + LPUNKNOWN lpOleLink; + lpOleLink = OleStdQueryInterface(lpUnk, IID_IOleLink); + if (lpOleLink) + { + OleStdRelease(lpOleLink); + return TRUE; + } + return FALSE; +} + + +/* OleStdQueryInterface +** -------------------- +** Returns the desired interface pointer if exposed by the given object. +** Returns NULL if the interface is not available. +** eg.: +** lpDataObj = OleStdQueryInterface(lpOleObj, &IID_DataObject); +*/ +STDAPI_(LPUNKNOWN) OleStdQueryInterface(LPUNKNOWN lpUnk, REFIID riid) +{ + LPUNKNOWN lpInterface; + HRESULT hrErr; + + hrErr = lpUnk->QueryInterface( + riid, + (LPVOID FAR*)&lpInterface + ); + + if (hrErr == NOERROR) + return lpInterface; + else + return NULL; +} + + +/* OleStdGetData +** ------------- +** Retrieve data from an IDataObject in a specified format on a +** global memory block. This function ALWAYS returns a private copy +** of the data to the caller. if necessary a copy is made of the +** data (ie. if lpMedium->pUnkForRelease != NULL). The caller assumes +** ownership of the data block in all cases and must free the data +** when done with it. The caller may directly free the data handle +** returned (taking care whether it is a simple HGLOBAL or a HANDLE +** to a MetafilePict) or the caller may call +** ReleaseStgMedium(lpMedium). this OLE helper function will do the +** right thing. +** +** PARAMETERS: +** LPDATAOBJECT lpDataObj -- object on which GetData should be +** called. +** CLIPFORMAT cfFormat -- desired clipboard format (eg. CF_TEXT) +** DVTARGETDEVICE FAR* lpTargetDevice -- target device for which +** the data should be composed. This may +** be NULL. NULL can be used whenever the +** data format is insensitive to target +** device or when the caller does not care +** what device is used. +** LPSTGMEDIUM lpMedium -- ptr to STGMEDIUM struct. the +** resultant medium from the +** IDataObject::GetData call is +** returned. +** +** RETURNS: +** HGLOBAL -- global memory handle of retrieved data block. +** NULL -- if error. +*/ +STDAPI_(HGLOBAL) OleStdGetData( + LPDATAOBJECT lpDataObj, + CLIPFORMAT cfFormat, + DVTARGETDEVICE FAR* lpTargetDevice, + DWORD dwDrawAspect, + LPSTGMEDIUM lpMedium) +{ + HRESULT hrErr; + FORMATETC formatetc; + HGLOBAL hGlobal = NULL; + HGLOBAL hCopy; + LPVOID lp; + + formatetc.cfFormat = cfFormat; + formatetc.ptd = lpTargetDevice; + formatetc.dwAspect = dwDrawAspect; + formatetc.lindex = -1; + + switch (cfFormat) + { + case CF_METAFILEPICT: + formatetc.tymed = TYMED_MFPICT; + break; + + case CF_BITMAP: + formatetc.tymed = TYMED_GDI; + break; + + default: + formatetc.tymed = TYMED_HGLOBAL; + break; + } + + OLEDBG_BEGIN2(TEXT("IDataObject::GetData called\r\n")) + hrErr = lpDataObj->GetData( + (LPFORMATETC)&formatetc, + lpMedium + ); + OLEDBG_END2 + + if (hrErr != NOERROR) + return NULL; + + if ((hGlobal = lpMedium->hGlobal) == NULL) + return NULL; + + // Check if hGlobal really points to valid memory + if ((lp = GlobalLock(hGlobal)) != NULL) + { + if (IsBadReadPtr(lp, 1)) + { + GlobalUnlock(hGlobal); + return NULL; // ERROR: memory is NOT valid + } + GlobalUnlock(hGlobal); + } + + if (hGlobal != NULL && lpMedium->pUnkForRelease != NULL) + { + /* OLE2NOTE: the callee wants to retain ownership of the data. + ** this is indicated by passing a non-NULL pUnkForRelease. + ** thus, we will make a copy of the data and release the + ** callee's copy. + */ + + hCopy = OleDuplicateData(hGlobal, cfFormat, GHND|GMEM_SHARE); + ReleaseStgMedium(lpMedium); // release callee's copy of data + + hGlobal = hCopy; + lpMedium->hGlobal = hCopy; + lpMedium->pUnkForRelease = NULL; + } + return hGlobal; +} + + +/* OleStdMalloc +** ------------ +** allocate memory using the currently active IMalloc* allocator +*/ +STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize) +{ + LPVOID pout; + LPMALLOC pmalloc; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) + { + OleDbgAssertSz(0, szAssertMemAlloc); + return NULL; + } + pout = (LPVOID)pmalloc->Alloc(ulSize); + pmalloc->Release(); + + return pout; +} + + +/* OleStdRealloc +** ------------- +** re-allocate memory using the currently active IMalloc* allocator +*/ +STDAPI_(LPVOID) OleStdRealloc(LPVOID pmem, ULONG ulSize) +{ + LPVOID pout; + LPMALLOC pmalloc; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) + { + OleDbgAssertSz(0, szAssertMemAlloc); + return NULL; + } + pout = (LPVOID)pmalloc->Realloc(pmem, ulSize); + pmalloc->Release(); + + return pout; +} + + +/* OleStdFree +** ---------- +** free memory using the currently active IMalloc* allocator +*/ +STDAPI_(void) OleStdFree(LPVOID pmem) +{ + LPMALLOC pmalloc; + + if (pmem == NULL) + return; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) + { + OleDbgAssertSz(0, szAssertMemAlloc); + return; + } + if (1 == pmalloc->DidAlloc(pmem)) + { + pmalloc->Free(pmem); + } + pmalloc->Release(); +} + + +/* OleStdGetSize +** ------------- +** Get the size of a memory block that was allocated using the +** currently active IMalloc* allocator. +*/ +STDAPI_(ULONG) OleStdGetSize(LPVOID pmem) +{ + ULONG ulSize; + LPMALLOC pmalloc; + + if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) + { + OleDbgAssertSz(0, szAssertMemAlloc); + return (ULONG)-1; + } + ulSize = pmalloc->GetSize(pmem); + pmalloc->Release(); + + return ulSize; +} + + +/* OleStdLoadString +** ---------------- +** Load a string from resources. The string is allocated +** with the active IMalloc allocator. +*/ +STDAPI_(LPTSTR) OleStdLoadString(HINSTANCE hInst, UINT nID) +{ + LPTSTR lpszResult = (LPTSTR)OleStdMalloc(256 * sizeof(TCHAR)); + if (lpszResult == NULL) + return NULL; + LoadString(hInst, nID, lpszResult, 256); + return lpszResult; +} + +/* OleStdCopyString +** ---------------- +** Copy a string into memory allocated with the currently active +** IMalloc* allocator. +*/ +STDAPI_(LPTSTR) OleStdCopyString(LPTSTR lpszSrc) +{ + UINT nSize = (lstrlen(lpszSrc)+1) * sizeof(TCHAR); + LPTSTR lpszResult = (LPTSTR)OleStdMalloc(nSize); + if (lpszResult == NULL) + return NULL; + memcpy(lpszResult, lpszSrc, nSize); + return lpszResult; +} + +/* + * OleStdGetObjectDescriptorData + * + * Purpose: + * Fills and returns a OBJECTDESCRIPTOR structure. + * See OBJECTDESCRIPTOR for more information. + * + * Parameters: + * clsid CLSID CLSID of object being transferred + * dwDrawAspect DWORD Display Aspect of object + * sizel SIZEL Size of object in HIMETRIC + * pointl POINTL Offset from upper-left corner of object where mouse went + * down for drag. Meaningful only when drag-drop is used. + * dwStatus DWORD OLEMISC flags + * lpszFullUserTypeName LPSTR Full User Type Name + * lpszSrcOfCopy LPSTR Source of Copy + * + * Return Value: + * HBGLOBAL Handle to OBJECTDESCRIPTOR structure. + */ +STDAPI_(HGLOBAL) OleStdGetObjectDescriptorData( + CLSID clsid, + DWORD dwDrawAspect, + SIZEL sizel, + POINTL pointl, + DWORD dwStatus, + LPTSTR lpszFullUserTypeName, + LPTSTR lpszSrcOfCopy) +{ + HGLOBAL hMem = NULL; + IBindCtx FAR *pbc = NULL; + LPOBJECTDESCRIPTOR lpOD; + DWORD dwObjectDescSize, dwFullUserTypeNameLen, dwSrcOfCopyLen; + + // Get the length of Full User Type Name; Add 1 for the null terminator +#if defined(WIN32) && !defined(UNICODE) + dwFullUserTypeNameLen = lpszFullUserTypeName ? ATOWLEN(lpszFullUserTypeName) : 0; + // Get the Source of Copy string and it's length; Add 1 for the null terminator + if (lpszSrcOfCopy) + dwSrcOfCopyLen = ATOWLEN(lpszSrcOfCopy); + else + { + // No src moniker so use user type name as source string. + lpszSrcOfCopy = lpszFullUserTypeName; + dwSrcOfCopyLen = dwFullUserTypeNameLen; + } +#else + dwFullUserTypeNameLen = lpszFullUserTypeName ? lstrlen(lpszFullUserTypeName)+1 : 0; + // Get the Source of Copy string and it's length; Add 1 for the null terminator + if (lpszSrcOfCopy) + dwSrcOfCopyLen = lstrlen(lpszSrcOfCopy)+1; + else + { + // No src moniker so use user type name as source string. + lpszSrcOfCopy = lpszFullUserTypeName; + dwSrcOfCopyLen = dwFullUserTypeNameLen; + } +#endif + // Allocate space for OBJECTDESCRIPTOR and the additional string data + dwObjectDescSize = sizeof(OBJECTDESCRIPTOR); + hMem = GlobalAlloc(GHND|GMEM_SHARE, dwObjectDescSize + + (dwFullUserTypeNameLen + dwSrcOfCopyLen) * sizeof(OLECHAR)); + if (!hMem) + return NULL; + + lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem); + + // Set the FullUserTypeName offset and copy the string + if (lpszFullUserTypeName) + { + lpOD->dwFullUserTypeName = dwObjectDescSize; +#if defined(WIN32) && !defined(UNICODE) + ATOW((LPWSTR)((LPBYTE)lpOD+lpOD->dwFullUserTypeName), lpszFullUserTypeName, dwFullUserTypeNameLen); +#else + lstrcpy((LPTSTR)((LPBYTE)lpOD+lpOD->dwFullUserTypeName), lpszFullUserTypeName); +#endif + } + else + lpOD->dwFullUserTypeName = 0; // zero offset indicates that string is not present + + // Set the SrcOfCopy offset and copy the string + if (lpszSrcOfCopy) + { + lpOD->dwSrcOfCopy = dwObjectDescSize + dwFullUserTypeNameLen * sizeof(OLECHAR); +#if defined(WIN32) && !defined(UNICODE) + ATOW((LPWSTR)((LPBYTE)lpOD+lpOD->dwSrcOfCopy), lpszSrcOfCopy, dwSrcOfCopyLen); +#else + lstrcpy((LPTSTR)((LPBYTE)lpOD+lpOD->dwSrcOfCopy), lpszSrcOfCopy); +#endif + } + else + lpOD->dwSrcOfCopy = 0; // zero offset indicates that string is not present + + // Initialize the rest of the OBJECTDESCRIPTOR + lpOD->cbSize = dwObjectDescSize + + (dwFullUserTypeNameLen + dwSrcOfCopyLen) * sizeof(OLECHAR); + lpOD->clsid = clsid; + lpOD->dwDrawAspect = dwDrawAspect; + lpOD->sizel = sizel; + lpOD->pointl = pointl; + lpOD->dwStatus = dwStatus; + + GlobalUnlock(hMem); + return hMem; +} + +/* + * OleStdFillObjectDescriptorFromData + * + * Purpose: + * Fills and returns a OBJECTDESCRIPTOR structure. The source object will + * offer CF_OBJECTDESCRIPTOR if it is an OLE2 object, CF_OWNERLINK if it + * is an OLE1 object, or CF_FILENAME if it has been copied to the clipboard + * by FileManager. + * + * Parameters: + * lpDataObject LPDATAOBJECT Source object + * lpmedium LPSTGMEDIUM Storage medium + * lpcfFmt CLIPFORMAT FAR * Format offered by lpDataObject + * (OUT parameter) + * + * Return Value: + * HBGLOBAL Handle to OBJECTDESCRIPTOR structure. + */ + +STDAPI_(HGLOBAL) OleStdFillObjectDescriptorFromData( + LPDATAOBJECT lpDataObject, + LPSTGMEDIUM lpmedium, + CLIPFORMAT FAR* lpcfFmt) +{ + CLSID clsid; + SIZEL sizelHim; + POINTL pointl; + LPTSTR lpsz, szFullUserTypeName, szSrcOfCopy, szClassName, szDocName, szItemName; + int nClassName, nDocName, nItemName, nFullUserTypeName; + LPTSTR szBuf = NULL; + HGLOBAL hMem = NULL; + HKEY hKey = NULL; + DWORD dw = OLEUI_CCHKEYMAX_SIZE; + HGLOBAL hObjDesc; + HRESULT hrErr; + + + // GetData CF_OBJECTDESCRIPTOR format from the object on the clipboard. + // Only OLE 2 objects on the clipboard will offer CF_OBJECTDESCRIPTOR + hMem = OleStdGetData( + lpDataObject, + (CLIPFORMAT) _g_cfObjectDescriptor, + NULL, + DVASPECT_CONTENT, + lpmedium); + if (hMem) + { + *lpcfFmt = (CLIPFORMAT)_g_cfObjectDescriptor; + return hMem; // Don't drop to clean up at the end of this function + } + // If CF_OBJECTDESCRIPTOR is not available, i.e. if this is not an OLE2 object, + // check if this is an OLE 1 object. OLE 1 objects will offer CF_OWNERLINK + else + { + hMem = OleStdGetData( + lpDataObject, + (CLIPFORMAT) _g_cfOwnerLink, + NULL, + DVASPECT_CONTENT, + lpmedium); + if (hMem) + { + *lpcfFmt = (CLIPFORMAT)_g_cfOwnerLink; + // CF_OWNERLINK contains null-terminated strings for class name, document name + // and item name with two null terminating characters at the end + szClassName = (LPTSTR)GlobalLock(hMem); + nClassName = lstrlen(szClassName); + szDocName = szClassName + nClassName + 1; + nDocName = lstrlen(szDocName); + szItemName = szDocName + nDocName + 1; + nItemName = lstrlen(szItemName); + + // Find FullUserTypeName from Registration database using class name + if (RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey) != ERROR_SUCCESS) + goto error; + + // Allocate space for szFullUserTypeName & szSrcOfCopy. Maximum length of FullUserTypeName + // is OLEUI_CCHKEYMAX_SIZE. SrcOfCopy is constructed by concatenating FullUserTypeName, Document + // Name and ItemName separated by spaces. + szBuf = (LPTSTR)OleStdMalloc( + (DWORD)2*OLEUI_CCHKEYMAX_SIZE+ + (nDocName+nItemName+4)*sizeof(TCHAR)); + if (NULL == szBuf) + goto error; + szFullUserTypeName = szBuf; + szSrcOfCopy = szFullUserTypeName+OLEUI_CCHKEYMAX_SIZE+1; + + // Get FullUserTypeName + if (RegQueryValue(hKey, NULL, szFullUserTypeName, (LONG*)&dw) != ERROR_SUCCESS) + goto error; + + // Build up SrcOfCopy string from FullUserTypeName, DocumentName & ItemName + lpsz = szSrcOfCopy; + lstrcpy(lpsz, szFullUserTypeName); + nFullUserTypeName = lstrlen(szFullUserTypeName); + lpsz[nFullUserTypeName]= ' '; + lpsz += nFullUserTypeName+1; + lstrcpy(lpsz, szDocName); + lpsz[nDocName] = ' '; + lpsz += nDocName+1; + lstrcpy(lpsz, szItemName); + + sizelHim.cx = sizelHim.cy = 0; + pointl.x = pointl.y = 0; + +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszClassName[OLEUI_CCHKEYMAX]; + ATOW(wszClassName, szClassName, OLEUI_CCHKEYMAX); + CLSIDFromProgID(wszClassName, &clsid); +#else + CLSIDFromProgID(szClassName, &clsid); +#endif + hObjDesc = OleStdGetObjectDescriptorData( + clsid, + DVASPECT_CONTENT, + sizelHim, + pointl, + 0, + szFullUserTypeName, + szSrcOfCopy + ); + if (!hObjDesc) + goto error; + } + else + { + BOOL fUnicode = TRUE; + + hMem = OleStdGetData( + lpDataObject, + (CLIPFORMAT) _g_cfFileNameW, + NULL, + DVASPECT_CONTENT, + lpmedium); + + if (!hMem) + { + hMem = OleStdGetData( + lpDataObject, + (CLIPFORMAT) _g_cfFileName, + NULL, + DVASPECT_CONTENT, + lpmedium); + + fUnicode = FALSE; + } + + if (hMem) + { + *lpcfFmt = fUnicode ? (CLIPFORMAT)_g_cfFileNameW : (CLIPFORMAT)_g_cfFileName; + lpsz = (LPTSTR)GlobalLock(hMem); + if (!fUnicode) + { + OLECHAR wsz[OLEUI_CCHKEYMAX]; + ATOW(wsz, (LPSTR)lpsz, OLEUI_CCHKEYMAX); + hrErr = GetClassFile(wsz, &clsid); + } + else + hrErr = GetClassFile((LPWSTR)lpsz, &clsid); + + /* OLE2NOTE: if the file does not have an OLE class + ** associated, then use the OLE 1 Packager as the class of + ** the object to be created. this is the behavior of + ** OleCreateFromData API + */ + if (hrErr != NOERROR) + CLSIDFromProgID(OLESTR("Package"), &clsid); + sizelHim.cx = sizelHim.cy = 0; + pointl.x = pointl.y = 0; + +#if defined(WIN32) && !defined(UNICODE) + LPOLESTR wszBuf = NULL; + szBuf = NULL; + if (OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &wszBuf) != NOERROR) + { + OleStdFree(wszBuf); + goto error; + } + if (NULL != wszBuf) + { + UINT uLen = WTOALEN(wszBuf) + 1; + szBuf = (LPTSTR) OleStdMalloc(uLen); + if (NULL != szBuf) + { + WTOA(szBuf, wszBuf, uLen); + } + else + { + OleStdFree(wszBuf); + goto error; + } + OleStdFree(wszBuf); + } +#else + if (OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &szBuf) != NOERROR) + goto error; +#endif + + hObjDesc = OleStdGetObjectDescriptorData( + clsid, + DVASPECT_CONTENT, + sizelHim, + pointl, + 0, + szBuf, + lpsz + ); + if (!hObjDesc) + goto error; + } + else + goto error; + } + } + // Check if object is CF_FILENAME + + // Clean up + OleStdFree(szBuf); + if (hMem) + { + GlobalUnlock(hMem); + GlobalFree(hMem); + } + if (hKey) + RegCloseKey(hKey); + return hObjDesc; + +error: + OleStdFree(szBuf); + if (hMem) + { + GlobalUnlock(hMem); + GlobalFree(hMem); + } + if (hKey) + RegCloseKey(hKey); + return NULL; +} + +/* Call Release on the object that is NOT necessarily expected to go away. +*/ +STDAPI_(ULONG) OleStdRelease(LPUNKNOWN lpUnk) +{ + ULONG cRef; + cRef = lpUnk->Release(); + +#ifdef _DEBUG + { + TCHAR szBuf[80]; + wsprintf( + szBuf, + TEXT("refcnt = %ld after object (0x%lx) release\n"), + cRef, + lpUnk + ); + OleDbgOut4(szBuf); + } +#endif + return cRef; +} + + +/* + * OleStdMarkPasteEntryList + * + * Purpose: + * Mark each entry in the PasteEntryList if its format is available from + * the source IDataObject*. the dwScratchSpace field of each PasteEntry + * is set to TRUE if available, else FALSE. + * + * Parameters: + * LPOLEUIPASTEENTRY array of PasteEntry structures + * int count of elements in PasteEntry array + * LPDATAOBJECT source IDataObject* pointer + * + * Return Value: + * none + */ +STDAPI_(void) OleStdMarkPasteEntryList( + LPDATAOBJECT lpSrcDataObj, + LPOLEUIPASTEENTRY lpPriorityList, + int cEntries) +{ + LPENUMFORMATETC lpEnumFmtEtc = NULL; + #define FORMATETC_MAX 20 + FORMATETC rgfmtetc[FORMATETC_MAX]; + int i; + HRESULT hrErr; + DWORD j, cFetched; + + // Clear all marks + for (i = 0; i < cEntries; i++) + { + lpPriorityList[i].dwScratchSpace = FALSE; + if (! lpPriorityList[i].fmtetc.cfFormat) + { + // caller wants this item always considered available + // (by specifying a NULL format) + lpPriorityList[i].dwScratchSpace = TRUE; + } + else if (lpPriorityList[i].fmtetc.cfFormat == _g_cfEmbeddedObject + || lpPriorityList[i].fmtetc.cfFormat == _g_cfEmbedSource + || lpPriorityList[i].fmtetc.cfFormat == _g_cfFileName) + { + // if there is an OLE object format, then handle it + // specially by calling OleQueryCreateFromData. the caller + // need only specify one object type format. + OLEDBG_BEGIN2(TEXT("OleQueryCreateFromData called\r\n")) + hrErr = OleQueryCreateFromData(lpSrcDataObj); + OLEDBG_END2 + if(NOERROR == hrErr) + lpPriorityList[i].dwScratchSpace = TRUE; + } + else if (lpPriorityList[i].fmtetc.cfFormat == _g_cfLinkSource) + { + // if there is OLE 2.0 LinkSource format, then handle it + // specially by calling OleQueryLinkFromData. + OLEDBG_BEGIN2(TEXT("OleQueryLinkFromData called\r\n")) + hrErr = OleQueryLinkFromData(lpSrcDataObj); + OLEDBG_END2 + if(NOERROR == hrErr) { + lpPriorityList[i].dwScratchSpace = TRUE; + } + } + } + + OLEDBG_BEGIN2(TEXT("IDataObject::EnumFormatEtc called\r\n")) + hrErr = lpSrcDataObj->EnumFormatEtc( + DATADIR_GET, + (LPENUMFORMATETC FAR*)&lpEnumFmtEtc + ); + OLEDBG_END2 + + if (hrErr != NOERROR) + return; // unable to get format enumerator + + // Enumerate the formats offered by the source + // Loop over all formats offered by the source + cFetched = 0; + memset(rgfmtetc,0,sizeof(rgfmtetc[FORMATETC_MAX]) ); + if (lpEnumFmtEtc->Next( + FORMATETC_MAX, rgfmtetc, &cFetched) == NOERROR + || (cFetched > 0 && cFetched <= FORMATETC_MAX) ) + { + for (j = 0; j < cFetched; j++) + { + for (i = 0; i < cEntries; i++) + { + if (!lpPriorityList[i].dwScratchSpace && + IsCloseFormatEtc(&lpPriorityList[i].fmtetc, &rgfmtetc[j])) + { + lpPriorityList[i].dwScratchSpace = TRUE; + } + } + } + } // endif + + OleStdRelease((LPUNKNOWN)lpEnumFmtEtc); +} + + +// returns 1 for a close match +// (all fields match exactly except the tymed which simply overlaps) +// 0 for no match + +int IsCloseFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight) +{ + if (pFetcLeft->cfFormat != pFetcRight->cfFormat) + return 0; + else if (!OleStdCompareTargetDevice (pFetcLeft->ptd, pFetcRight->ptd)) + return 0; + if (pFetcLeft->dwAspect != pFetcRight->dwAspect) + return 0; + return((pFetcLeft->tymed | pFetcRight->tymed) != 0); +} + + diff --git a/private/ole2ui32/olestd.h b/private/ole2ui32/olestd.h new file mode 100644 index 000000000..2f406bc2d --- /dev/null +++ b/private/ole2ui32/olestd.h @@ -0,0 +1,328 @@ +/************************************************************************* +** +** OLE 2.0 Utility Library +** +** olestd.h +** +** This file contains file contains data structure defintions, +** function prototypes, constants, etc. for the common OLE 2.0 +** utilities. +** These utilities include the following: +** Debuging Assert/Verify macros +** HIMETRIC conversion routines +** reference counting debug support +** OleStd API's for common compound-document app support +** +** (c) Copyright Microsoft Corp. 1990 - 1995 All Rights Reserved +** +*************************************************************************/ + +#ifndef _OLESTD_H_ +#define _OLESTD_H_ + +#include <commdlg.h> // needed for LPPRINTDLG +#include <shellapi.h> // needed for HKEY +#include <oledlg.h> // need some paste special defines + +#ifdef __cplusplus +extern "C" { +#endif + +STDAPI_(void) OleStdInitialize(HINSTANCE hInstance, HINSTANCE hResInstance); + +// Clipboard Copy/Paste & Drag/Drop support support + +// Clipboard format strings +#define CF_EMBEDSOURCE TEXT("Embed Source") +#define CF_EMBEDDEDOBJECT TEXT("Embedded Object") +#define CF_LINKSOURCE TEXT("Link Source") +#define CF_OBJECTDESCRIPTOR TEXT("Object Descriptor") +#define CF_LINKSRCDESCRIPTOR TEXT("Link Source Descriptor") +#define CF_OWNERLINK TEXT("OwnerLink") +#define CF_FILENAME TEXT("FileName") +#define CF_FILENAMEW TEXT("FileNameW") + +// Other useful defines +#define HIMETRIC_PER_INCH 2540 // number HIMETRIC units per inch +#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH) + +/****** DEBUG Support *****************************************************/ + +#ifdef _DEBUG + +#ifndef _DBGTRACE + #define _DEBUGLEVEL 2 +#else + #define _DEBUGLEVEL _DBGTRACE +#endif + +#ifdef NOASSERT + +#define OLEDBGASSERTDATA +#define OleDbgAssert(a) +#define OleDbgAssertSz(a, b) +#define OleDbgVerify(a) +#define OleDbgVerifySz(a, b) + +#else // ! NOASSERT + +STDAPI OleStdAssert(LPTSTR lpstrExpr, LPTSTR lpstrMsg, + LPTSTR lpstrFileName, UINT iLine); + +#define OLEDBGASSERTDATA \ + static TCHAR _szAssertFile[]= TEXT(__FILE__); + +#define OleDbgAssert(a) \ + (!(a) ? OleStdAssert(TEXT(#a), NULL, _szAssertFile, __LINE__) : (HRESULT)1) + +#define OleDbgAssertSz(a, b) \ + (!(a) ? OleStdAssert(TEXT(#a), b, _szAssertFile, __LINE__) : (HRESULT)1) + +#endif + +#define OleDbgVerify(a) \ + OleDbgAssert(a) + +#define OleDbgVerifySz(a, b) \ + OleDbgAssertSz(a, b) + +#define OLEDBGDATA_MAIN(szPrefix) \ + TCHAR g_szDbgPrefix[] = szPrefix; \ + OLEDBGASSERTDATA +#define OLEDBGDATA \ + extern TCHAR g_szDbgPrefix[]; \ + OLEDBGASSERTDATA + +#define OLEDBG_BEGIN(lpsz) \ + OleDbgPrintAlways(g_szDbgPrefix,lpsz,1); + +#define OLEDBG_END \ + OleDbgPrintAlways(g_szDbgPrefix,TEXT("End\r\n"),-1); + +#define OleDbgOut(lpsz) \ + OleDbgPrintAlways(g_szDbgPrefix,lpsz,0) + +#define OleDbgOutNoPrefix(lpsz) \ + OleDbgPrintAlways(TEXT(""),lpsz,0) + +#define OleDbgOutRefCnt(lpsz,lpObj,refcnt) \ + OleDbgPrintRefCntAlways(g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt) + +#define OleDbgOutRect(lpsz,lpRect) \ + OleDbgPrintRectAlways(g_szDbgPrefix,lpsz,lpRect) + +#define OleDbgOutHResult(lpsz,hr) \ + OleDbgPrintScodeAlways(g_szDbgPrefix,lpsz,GetScode(hr)) + +#define OleDbgOutScode(lpsz,sc) \ + OleDbgPrintScodeAlways(g_szDbgPrefix,lpsz,sc) + +#define OleDbgOut1(lpsz) \ + OleDbgPrint(1,g_szDbgPrefix,lpsz,0) + +#define OleDbgOutNoPrefix1(lpsz) \ + OleDbgPrint(1,TEXT(""),lpsz,0) + +#define OLEDBG_BEGIN1(lpsz) \ + OleDbgPrint(1,g_szDbgPrefix,lpsz,1); + +#define OLEDBG_END1 \ + OleDbgPrint(1,g_szDbgPrefix,TEXT("End\r\n"),-1); + +#define OleDbgOutRefCnt1(lpsz,lpObj,refcnt) \ + OleDbgPrintRefCnt(1,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt) + +#define OleDbgOutRect1(lpsz,lpRect) \ + OleDbgPrintRect(1,g_szDbgPrefix,lpsz,lpRect) + +#define OleDbgOut2(lpsz) \ + OleDbgPrint(2,g_szDbgPrefix,lpsz,0) + +#define OleDbgOutNoPrefix2(lpsz) \ + OleDbgPrint(2,TEXT(""),lpsz,0) + +#define OLEDBG_BEGIN2(lpsz) \ + OleDbgPrint(2,g_szDbgPrefix,lpsz,1); + +#define OLEDBG_END2 \ + OleDbgPrint(2,g_szDbgPrefix, TEXT("End\r\n"),-1); + +#define OleDbgOutRefCnt2(lpsz,lpObj,refcnt) \ + OleDbgPrintRefCnt(2,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt) + +#define OleDbgOutRect2(lpsz,lpRect) \ + OleDbgPrintRect(2,g_szDbgPrefix,lpsz,lpRect) + +#define OleDbgOut3(lpsz) \ + OleDbgPrint(3,g_szDbgPrefix,lpsz,0) + +#define OleDbgOutNoPrefix3(lpsz) \ + OleDbgPrint(3,TEXT(""),lpsz,0) + +#define OLEDBG_BEGIN3(lpsz) \ + OleDbgPrint(3,g_szDbgPrefix,lpsz,1); + +#define OLEDBG_END3 \ + OleDbgPrint(3,g_szDbgPrefix,TEXT("End\r\n"),-1); + +#define OleDbgOutRefCnt3(lpsz,lpObj,refcnt) \ + OleDbgPrintRefCnt(3,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt) + +#define OleDbgOutRect3(lpsz,lpRect) \ + OleDbgPrintRect(3,g_szDbgPrefix,lpsz,lpRect) + +#define OleDbgOut4(lpsz) \ + OleDbgPrint(4,g_szDbgPrefix,lpsz,0) + +#define OleDbgOutNoPrefix4(lpsz) \ + OleDbgPrint(4,TEXT(""),lpsz,0) + +#define OLEDBG_BEGIN4(lpsz) \ + OleDbgPrint(4,g_szDbgPrefix,lpsz,1); + +#define OLEDBG_END4 \ + OleDbgPrint(4,g_szDbgPrefix,TEXT("End\r\n"),-1); + +#define OleDbgOutRefCnt4(lpsz,lpObj,refcnt) \ + OleDbgPrintRefCnt(4,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt) + +#define OleDbgOutRect4(lpsz,lpRect) \ + OleDbgPrintRect(4,g_szDbgPrefix,lpsz,lpRect) + +#else // !_DEBUG + +#define OLEDBGDATA_MAIN(szPrefix) +#define OLEDBGDATA +#define OleDbgAssert(a) +#define OleDbgAssertSz(a, b) +#define OleDbgVerify(a) (a) +#define OleDbgVerifySz(a, b) (a) +#define OleDbgOutHResult(lpsz,hr) +#define OleDbgOutScode(lpsz,sc) +#define OLEDBG_BEGIN(lpsz) +#define OLEDBG_END +#define OleDbgOut(lpsz) +#define OleDbgOut1(lpsz) +#define OleDbgOut2(lpsz) +#define OleDbgOut3(lpsz) +#define OleDbgOut4(lpsz) +#define OleDbgOutNoPrefix(lpsz) +#define OleDbgOutNoPrefix1(lpsz) +#define OleDbgOutNoPrefix2(lpsz) +#define OleDbgOutNoPrefix3(lpsz) +#define OleDbgOutNoPrefix4(lpsz) +#define OLEDBG_BEGIN1(lpsz) +#define OLEDBG_BEGIN2(lpsz) +#define OLEDBG_BEGIN3(lpsz) +#define OLEDBG_BEGIN4(lpsz) +#define OLEDBG_END1 +#define OLEDBG_END2 +#define OLEDBG_END3 +#define OLEDBG_END4 +#define OleDbgOutRefCnt(lpsz,lpObj,refcnt) +#define OleDbgOutRefCnt1(lpsz,lpObj,refcnt) +#define OleDbgOutRefCnt2(lpsz,lpObj,refcnt) +#define OleDbgOutRefCnt3(lpsz,lpObj,refcnt) +#define OleDbgOutRefCnt4(lpsz,lpObj,refcnt) +#define OleDbgOutRect(lpsz,lpRect) +#define OleDbgOutRect1(lpsz,lpRect) +#define OleDbgOutRect2(lpsz,lpRect) +#define OleDbgOutRect3(lpsz,lpRect) +#define OleDbgOutRect4(lpsz,lpRect) + +#endif // _DEBUG + +/************************************************************************* +** Function prototypes +*************************************************************************/ + +// OLESTD.CPP +STDAPI_(int) XformWidthInHimetricToPixels(HDC, int); +STDAPI_(int) XformHeightInHimetricToPixels(HDC, int); + +STDAPI_(BOOL) OleStdIsOleLink(LPUNKNOWN lpUnk); +STDAPI_(LPUNKNOWN) OleStdQueryInterface(LPUNKNOWN lpUnk, REFIID riid); +STDAPI_(HGLOBAL) OleStdGetData( + LPDATAOBJECT lpDataObj, + CLIPFORMAT cfFormat, + DVTARGETDEVICE FAR* lpTargetDevice, + DWORD dwAspect, + LPSTGMEDIUM lpMedium +); +STDAPI_(void) OleStdMarkPasteEntryList( + LPDATAOBJECT lpSrcDataObj, + LPOLEUIPASTEENTRY lpPriorityList, + int cEntries +); +STDAPI_(HGLOBAL) OleStdGetObjectDescriptorData( + CLSID clsid, + DWORD dwAspect, + SIZEL sizel, + POINTL pointl, + DWORD dwStatus, + LPTSTR lpszFullUserTypeName, + LPTSTR lpszSrcOfCopy +); +STDAPI_(HGLOBAL) OleStdFillObjectDescriptorFromData( + LPDATAOBJECT lpDataObject, + LPSTGMEDIUM lpmedium, + CLIPFORMAT FAR* lpcfFmt +); + +STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize); +STDAPI_(LPVOID) OleStdRealloc(LPVOID pmem, ULONG ulSize); +STDAPI_(void) OleStdFree(LPVOID pmem); +STDAPI_(ULONG) OleStdGetSize(LPVOID pmem); +STDAPI_(LPTSTR) OleStdCopyString(LPTSTR lpszSrc); +STDAPI_(LPTSTR) OleStdLoadString(HINSTANCE hInst, UINT nID); +STDAPI_(ULONG) OleStdRelease(LPUNKNOWN lpUnk); + +STDAPI_(BOOL) OleStdCompareTargetDevice + (DVTARGETDEVICE FAR* ptdLeft, DVTARGETDEVICE FAR* ptdRight); + +STDAPI_(void) OleDbgPrint( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + int nIndent +); +STDAPI_(void) OleDbgPrintAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, int nIndent); +STDAPI_(void) OleDbgSetDbgLevel(int nDbgLvl); +STDAPI_(int) OleDbgGetDbgLevel( void ); +STDAPI_(void) OleDbgIndent(int n); +STDAPI_(void) OleDbgPrintRefCnt( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPVOID lpObj, + ULONG refcnt +); +STDAPI_(void) OleDbgPrintRefCntAlways( + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPVOID lpObj, + ULONG refcnt +); +STDAPI_(void) OleDbgPrintRect( + int nDbgLvl, + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPRECT lpRect +); +STDAPI_(void) OleDbgPrintRectAlways( + LPTSTR lpszPrefix, + LPTSTR lpszMsg, + LPRECT lpRect +); +STDAPI_(void) OleDbgPrintScodeAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, SCODE sc); + +#ifdef __cplusplus +} +#endif + +#define ATOW(wsz, sz, cch) MultiByteToWideChar(CP_ACP, 0, sz, -1, wsz, cch) +#define WTOA(sz, wsz, cch) WideCharToMultiByte(CP_ACP, 0, wsz, -1, sz, cch, NULL, NULL) +#define ATOWLEN(sz) MultiByteToWideChar(CP_ACP, 0, sz, -1, NULL, 0) +#define WTOALEN(wsz) WideCharToMultiByte(CP_ACP, 0, wsz, -1, NULL, 0, NULL, NULL) + +#endif // _OLESTD_H_ diff --git a/private/ole2ui32/oleutl.cpp b/private/ole2ui32/oleutl.cpp new file mode 100644 index 000000000..1a0b0ca6b --- /dev/null +++ b/private/ole2ui32/oleutl.cpp @@ -0,0 +1,132 @@ +/* + * OLEUTL.CPP + * + * Miscellaneous utility functions for OLE 2.0 Applications: + * + * Function Purpose + * ------------------------------------------------------------------- + * XformWidthInHimetricToPixels Converts an int width from HiMetric units + * XformHeightInHimetricToPixels Converts an int height from HiMetric units + * + * CommitStorage Commits all changes in a docfile + * CreateChildStorage Creates child storage in another storage + * OpenChildStorage Opens child storage in another storage + * + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#include "precomp.h" +#include <stdlib.h> + +//Internal function to this module. No need for UNICODE in this function +static LPSTR GetWord(LPSTR lpszSrc, LPSTR lpszDst); + +/* + * XformWidthInHimetricToPixels + * XformHeightInHimetricToPixels + * + * Functions to convert an int between a device coordinate system and + * logical HiMetric units. + * + * Parameters: + * hDC HDC providing reference to the pixel mapping. If + * NULL, a screen DC is used. + * + * Size Functions: + * lpSizeSrc LPSIZEL providing the structure to convert. + * lpSizeDst LPSIZEL providing the structure to receive converted + * units. + * + * Width Functions: + * iWidth int containing the value to convert. + * + * Return Value: + * Size Functions: None + * Width Functions: Converted value of the input parameters. + * + * NOTE: + * When displaying on the screen, Window apps display everything enlarged + * from its actual size so that it is easier to read. For example, if an + * app wants to display a 1in. horizontal line, that when printed is + * actually a 1in. line on the printed page, then it will display the line + * on the screen physically larger than 1in. This is described as a line + * that is "logically" 1in. along the display width. Windows maintains as + * part of the device-specific information about a given display device: + * LOGPIXELSX -- no. of pixels per logical in along the display width + * LOGPIXELSY -- no. of pixels per logical in along the display height + * + * The following formula converts a distance in pixels into its equivalent + * logical HIMETRIC units: + * + * DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix) + * ------------------------------- + * PIXELS_PER_LOGICAL_IN + * + */ +STDAPI_(int) XformWidthInHimetricToPixels(HDC hDC, int iWidthInHiMetric) +{ + int iXppli; //Pixels per logical inch along width + int iWidthInPix; + BOOL fSystemDC=FALSE; + + if (NULL==hDC) + { + hDC=GetDC(NULL); + fSystemDC=TRUE; + } + + iXppli = GetDeviceCaps (hDC, LOGPIXELSX); + + //We got logical HIMETRIC along the display, convert them to pixel units + iWidthInPix = MAP_LOGHIM_TO_PIX(iWidthInHiMetric, iXppli); + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return iWidthInPix; +} + + +STDAPI_(int) XformHeightInHimetricToPixels(HDC hDC, int iHeightInHiMetric) +{ + int iYppli; //Pixels per logical inch along height + int iHeightInPix; + BOOL fSystemDC=FALSE; + + if (NULL==hDC) + { + hDC=GetDC(NULL); + fSystemDC=TRUE; + } + + iYppli = GetDeviceCaps (hDC, LOGPIXELSY); + + //* We got logical HIMETRIC along the display, convert them to pixel units + iHeightInPix = MAP_LOGHIM_TO_PIX(iHeightInHiMetric, iYppli); + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return iHeightInPix; +} + +/* GetWord + * ------- + * + * LPSTR lpszSrc - Pointer to a source string + * LPSTR lpszDst - Pointer to destination buffer + * + * Will copy one space-terminated or null-terminated word from the source + * string to the destination buffer. + * returns: pointer to next character following the word. + */ +static LPSTR GetWord(LPSTR lpszSrc, LPSTR lpszDst) +{ + while (*lpszSrc && !(*lpszSrc == ' ' || *lpszSrc == '\t' || *lpszSrc == '\n')) + *lpszDst++ = *lpszSrc++; + + *lpszDst = '\0'; + return lpszSrc; +} diff --git a/private/ole2ui32/pastespl.cpp b/private/ole2ui32/pastespl.cpp new file mode 100644 index 000000000..1c55b2948 --- /dev/null +++ b/private/ole2ui32/pastespl.cpp @@ -0,0 +1,1881 @@ +/* + * PASTESPL.CPP + * + * Implements the OleUIPasteSpecial function which invokes the complete + * Paste Special dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Rights Reserved + */ + +#include "precomp.h" +#include "common.h" +#include "utility.h" +#include "resimage.h" +#include "iconbox.h" +#include <stdlib.h> + +OLEDBGDATA + +// Length of buffers to hold the strings 'Unknown Type', Unknown Source' +// and 'the application which created it' +// Extra long to allow room for localization. +#define PS_UNKNOWNSTRLEN 200 +#define PS_UNKNOWNNAMELEN 256 + +// Property label used to store clipboard viewer chain information +#define NEXTCBVIEWER TEXT("NextCBViewer") + +// Internally used structure +typedef struct tagPASTESPECIAL +{ + // Keep this item first as the Standard* functions depend on it here. + LPOLEUIPASTESPECIAL lpOPS; //Original structure passed. + UINT nIDD; // IDD of dialog (used for help info) + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + + DWORD dwFlags; // Local copy of paste special flags + + int nPasteListCurSel; // Save the selection the user made last + int nPasteLinkListCurSel; // in the paste and pastelink lists + int nSelectedIndex; // Index in arrPasteEntries[] corresponding to user selection + BOOL fLink; // Indicates if Paste or PasteLink was selected by user + + HGLOBAL hBuff; // Scratch Buffer for building up strings + TCHAR szUnknownType[PS_UNKNOWNSTRLEN]; // Buffer for 'Unknown Type' string + TCHAR szUnknownSource[PS_UNKNOWNSTRLEN]; // Buffer for 'Unknown Source' string + TCHAR szAppName[OLEUI_CCHKEYMAX]; // Application name of Source. Used in the result text + // when Paste is selected. Obtained using clsidOD. + + // Information obtained from OBJECTDESCRIPTOR. This information is accessed when the Paste + // radio button is selected. + CLSID clsidOD; // ClassID of source + SIZEL sizelOD; // sizel transfered in + // ObjectDescriptor + TCHAR szFullUserTypeNameOD[PS_UNKNOWNNAMELEN]; // Full User Type Name + TCHAR szSourceOfDataOD[PS_UNKNOWNNAMELEN]; // Source of Data + BOOL fSrcAspectIconOD; // Does Source specify DVASPECT_ICON? + BOOL fSrcOnlyIconicOD; // Does Source specify OLEMISC_ONLYICONIC? + HGLOBAL hMetaPictOD; // Metafile containing icon and icon title + HGLOBAL hObjDesc; // Handle to OBJECTDESCRIPTOR structure from which the + // above information is obtained + + // Information obtained from LINKSRCDESCRIPTOR. This infomation is accessed when the PasteLink + // radio button is selected. + CLSID clsidLSD; // ClassID of source + SIZEL sizelLSD; // sizel transfered in + // LinkSrcDescriptor + TCHAR szFullUserTypeNameLSD[PS_UNKNOWNNAMELEN];// Full User Type Name + TCHAR szSourceOfDataLSD[PS_UNKNOWNNAMELEN]; // Source of Data + BOOL fSrcAspectIconLSD; // Does Source specify DVASPECT_ICON? + BOOL fSrcOnlyIconicLSD; // Does Source specify OLEMISC_ONLYICONIC? + HGLOBAL hMetaPictLSD; // Metafile containing icon and icon title + HGLOBAL hLinkSrcDesc; // Handle to LINKSRCDESCRIPTOR structure from which the + // above information is obtained + + BOOL fClipboardChanged; // Has clipboard content changed + // if so bring down dlg after + // ChangeIcon dlg returns. +} PASTESPECIAL, *PPASTESPECIAL, FAR *LPPASTESPECIAL; + +// Data corresponding to each list item. A pointer to this structure is attached to each +// Paste\PasteLink list box item using LB_SETITEMDATA +typedef struct tagPASTELISTITEMDATA +{ + int nPasteEntriesIndex; // Index of arrPasteEntries[] corresponding to list item + BOOL fCntrEnableIcon; // Does calling application (called container here) + // specify OLEUIPASTE_ENABLEICON for this item? +} PASTELISTITEMDATA, *PPASTELISTITEMDATA, FAR *LPPASTELISTITEMDATA; + +// Internal function prototypes +// PASTESPL.CPP +BOOL CALLBACK PasteSpecialDialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL FPasteSpecialInit(HWND hDlg, WPARAM, LPARAM); +BOOL FTogglePasteType(HWND, LPPASTESPECIAL, DWORD); +void ChangeListSelection(HWND, LPPASTESPECIAL, HWND); +void EnableDisplayAsIcon(HWND, LPPASTESPECIAL); +void ToggleDisplayAsIcon(HWND, LPPASTESPECIAL); +void ChangeIcon(HWND, LPPASTESPECIAL); +void SetPasteSpecialHelpResults(HWND, LPPASTESPECIAL); +BOOL FAddPasteListItem(HWND, BOOL, int, LPPASTESPECIAL, LPTSTR, LPTSTR); +BOOL FFillPasteList(HWND, LPPASTESPECIAL); +BOOL FFillPasteLinkList(HWND, LPPASTESPECIAL); +BOOL FHasPercentS(LPCTSTR, LPPASTESPECIAL); +HGLOBAL AllocateScratchMem(LPPASTESPECIAL); +void FreeListData(HWND); +BOOL FPasteSpecialReInit(HWND hDlg, LPPASTESPECIAL lpPS); + +/* + * OleUIPasteSpecial + * + * Purpose: + * Invokes the standard OLE Paste Special dialog box which allows the user + * to select the format of the clipboard object to be pasted or paste linked. + * + * Parameters: + * lpPS LPOLEUIPasteSpecial pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT One of the following codes or one of the standard error codes (OLEUI_ERR_*) + * defined in OLEDLG.H, indicating success or error: + * OLEUI_OK User selected OK + * OLEUI_CANCEL User cancelled the dialog + * OLEUI_IOERR_SRCDATAOBJECTINVALID lpSrcDataObject field of OLEUIPASTESPECIAL invalid + * OLEUI_IOERR_ARRPASTEENTRIESINVALID arrPasteEntries field of OLEUIPASTESPECIAL invalid + * OLEUI_IOERR_ARRLINKTYPESINVALID arrLinkTypes field of OLEUIPASTESPECIAL invalid + * OLEUI_PSERR_CLIPBOARDCHANGED Clipboard contents changed while dialog was up + */ +STDAPI_(UINT) OleUIPasteSpecial(LPOLEUIPASTESPECIAL lpPS) +{ + UINT uRet; + HGLOBAL hMemDlg=NULL; + + uRet = UStandardValidation((LPOLEUISTANDARD)lpPS, sizeof(OLEUIPASTESPECIAL), + &hMemDlg); + + if (uRet != OLEUI_SUCCESS) + return uRet; + + // Validate PasteSpecial specific fields + if (NULL != lpPS->lpSrcDataObj && IsBadReadPtr(lpPS->lpSrcDataObj, sizeof(IDataObject))) + { + uRet = OLEUI_IOERR_SRCDATAOBJECTINVALID; + } + if (NULL == lpPS->arrPasteEntries || + IsBadReadPtr(lpPS->arrPasteEntries, lpPS->cPasteEntries * sizeof(OLEUIPASTEENTRY))) + { + uRet = OLEUI_IOERR_ARRPASTEENTRIESINVALID; + } + if (0 > lpPS->cLinkTypes || lpPS->cLinkTypes > PS_MAXLINKTYPES || + IsBadReadPtr(lpPS->arrLinkTypes, lpPS->cLinkTypes * sizeof(UINT))) + { + uRet = OLEUI_IOERR_ARRLINKTYPESINVALID; + } + + if (0 != lpPS->cClsidExclude && + IsBadReadPtr(lpPS->lpClsidExclude, lpPS->cClsidExclude * sizeof(CLSID))) + { + uRet = OLEUI_IOERR_LPCLSIDEXCLUDEINVALID; + } + + // If IDataObject passed is NULL, collect it from the clipboard + if (NULL == lpPS->lpSrcDataObj) + { + if (OleGetClipboard(&lpPS->lpSrcDataObj) != NOERROR) + uRet = OLEUI_PSERR_GETCLIPBOARDFAILED; + + if (NULL == lpPS->lpSrcDataObj) + uRet = OLEUI_PSERR_GETCLIPBOARDFAILED; + } + + if (uRet >= OLEUI_ERR_STANDARDMIN) + { + return uRet; + } + + UINT nIDD = bWin4 ? IDD_PASTESPECIAL4 : IDD_PASTESPECIAL; + + //Now that we've validated everything, we can invoke the dialog. + uRet = UStandardInvocation(PasteSpecialDialogProc, (LPOLEUISTANDARD)lpPS, + hMemDlg, MAKEINTRESOURCE(nIDD)); + + return uRet; +} + +/* + * PasteSpecialDialogProc + * + * Purpose: + * Implements the OLE Paste Special dialog as invoked through the + * OleUIPasteSpecial function. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ +BOOL CALLBACK PasteSpecialDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + // Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + // This will fail under WM_INITDIALOG, where we allocate it. + UINT fHook = FALSE; + LPPASTESPECIAL lpPS = (LPPASTESPECIAL)LpvStandardEntry( + hDlg, iMsg, wParam, lParam, &fHook); + LPOLEUIPASTESPECIAL lpOPS = NULL; + if (lpPS != NULL) + lpOPS = lpPS->lpOPS; + + //If the hook processed the message, we're done. + if (0!=fHook) + return fHook; + + // Process help message from Change Icon + if (iMsg == uMsgHelp) + { + PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp, wParam, lParam); + return FALSE; + } + + //Process the temination message + if (iMsg == uMsgEndDialog) + { + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) + { + case WM_DESTROY: + if (lpPS) + { + HWND hwndNextViewer; + + // Free the icon/icon-title metafile corresponding to Paste/PasteList option which is not selected + if (lpPS->fLink) + OleUIMetafilePictIconFree(lpPS->hMetaPictOD); + else + OleUIMetafilePictIconFree(lpPS->hMetaPictLSD); + + // Free data associated with each list box entry + FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELIST)); + FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELINKLIST)); + + //Free any specific allocations before calling StandardCleanup + if (lpPS->hObjDesc) GlobalFree(lpPS->hObjDesc); + if (lpPS->hLinkSrcDesc) GlobalFree(lpPS->hLinkSrcDesc); + if (lpPS->hBuff) + { + GlobalFree(lpPS->hBuff); + lpPS->hBuff = NULL; + } + + // Change the clipboard notification chain + hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER); + if (hwndNextViewer != HWND_BROADCAST) + { + SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST); + ChangeClipboardChain(hDlg, hwndNextViewer); + } + RemoveProp(hDlg, NEXTCBVIEWER); + + StandardCleanup(lpPS, hDlg); + } + break; + case WM_INITDIALOG: + FPasteSpecialInit(hDlg, wParam, lParam); + return FALSE; + + case WM_DRAWCLIPBOARD: + { + HWND hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER); + HWND hDlg_ChgIcon; + + if (hwndNextViewer == HWND_BROADCAST) + break; + + if (hwndNextViewer) + { + SendMessage(hwndNextViewer, iMsg, wParam, lParam); + // Refresh next viewer in case it got modified + // by the SendMessage() (likely if multiple + // PasteSpecial dialogs are up simultaneously) + hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER); + } + + if (!(lpPS->dwFlags & PSF_STAYONCLIPBOARDCHANGE)) + { + SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST); + ChangeClipboardChain(hDlg, hwndNextViewer); + + /* OLE2NOTE: if the ChangeIcon dialog is currently up, then + ** we need to defer bringing down PasteSpecial dialog + ** until after ChangeIcon dialog returns. if the + ** ChangeIcon dialog is NOT up, then we can bring down + ** the PasteSpecial dialog immediately. + */ + if ((hDlg_ChgIcon=(HWND)GetProp(hDlg,PROP_HWND_CHGICONDLG))!=NULL) + { + // ChangeIcon dialog is UP + lpPS->fClipboardChanged = TRUE; + } + else + { + // ChangeIcon dialog is NOT up + + // Free icon and icon title metafile + SendDlgItemMessage( + hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L); + SendMessage( + hDlg, uMsgEndDialog, OLEUI_PSERR_CLIPBOARDCHANGED,0L); + } + } + else + { + // skip refresh, ignoring clipboard change if PSF_NOREFRESHDATAOBJECT + if (lpPS->dwFlags & PSF_NOREFRESHDATAOBJECT) + break; + + // release current data object + if (lpOPS->lpSrcDataObj != NULL) + { + lpOPS->lpSrcDataObj->Release(); + lpOPS->lpSrcDataObj = NULL; + } + + // obtain new one + if (OleGetClipboard(&lpOPS->lpSrcDataObj) != NOERROR) + { + SendMessage(hDlg, uMsgEndDialog, OLEUI_PSERR_GETCLIPBOARDFAILED, 0); + break; + } + + // otherwise update the display to the new clipboard object + FPasteSpecialReInit(hDlg, lpPS); + } + } + break; + + case WM_CHANGECBCHAIN: + { + HWND hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER); + if ((HWND)wParam == hwndNextViewer) + SetProp(hDlg, NEXTCBVIEWER, (hwndNextViewer = (HWND)lParam)); + else if (hwndNextViewer && hwndNextViewer != HWND_BROADCAST) + SendMessage(hwndNextViewer, iMsg, wParam, lParam); + } + break; + + case WM_COMMAND: + switch (wID) + { + case IDC_PS_PASTE: + FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE); + break; + + case IDC_PS_PASTELINK: + FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK); + break; + + case IDC_PS_DISPLAYLIST: + switch (wCode) + { + case LBN_SELCHANGE: + ChangeListSelection(hDlg, lpPS, hWndMsg); + break; + case LBN_DBLCLK: + // Same as pressing OK + if (IsWindowEnabled(GetDlgItem(hDlg, IDOK))) + SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg); + break; + } + break; + + case IDC_PS_DISPLAYASICON: + ToggleDisplayAsIcon(hDlg, lpPS); + break; + + case IDC_PS_CHANGEICON: + ChangeIcon(hDlg, lpPS); + if (lpPS->fClipboardChanged) + { + // Free icon and icon title metafile + SendDlgItemMessage( + hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGEFREE,0,0L); + SendMessage(hDlg, uMsgEndDialog, + OLEUI_PSERR_CLIPBOARDCHANGED, 0L); + } + break; + + case IDOK: + { + BOOL fDestAspectIcon = + ((lpPS->dwFlags & PSF_CHECKDISPLAYASICON) ? + TRUE : FALSE); + // Return current flags + lpOPS->dwFlags = lpPS->dwFlags; + // Return index of arrPasteEntries[] corresponding to format selected by user + lpOPS->nSelectedIndex = lpPS->nSelectedIndex; + // Return if user selected Paste or PasteLink + lpOPS->fLink = lpPS->fLink; + + /* if user selected same ASPECT as displayed in the + ** source, then sizel passed in the + ** ObjectDescriptor/LinkSrcDescriptor is + ** applicable. otherwise, the sizel does not apply. + */ + if (lpPS->fLink) + { + if (lpPS->fSrcAspectIconLSD == fDestAspectIcon) + lpOPS->sizel = lpPS->sizelLSD; + else + lpOPS->sizel.cx = lpOPS->sizel.cy = 0; + } + else + { + if (lpPS->fSrcAspectIconOD == fDestAspectIcon) + lpOPS->sizel = lpPS->sizelOD; + else + lpOPS->sizel.cx = lpOPS->sizel.cy = 0; + } + // Return metafile with icon and icon title that the user selected + lpOPS->hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, + IDC_PS_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L); + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + } + break; + + case IDCANCEL: + // Free icon and icon title metafile + SendDlgItemMessage( + hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L); + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + + case IDC_OLEUIHELP: + PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp, + (WPARAM)hDlg, MAKELPARAM(IDD_PASTESPECIAL, 0)); + break; + } + break; + } + return FALSE; +} + +BOOL FPasteSpecialReInit(HWND hDlg, LPPASTESPECIAL lpPS) +{ + LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; + + // free the icon/icon-title metafiel + if (lpPS->fLink) + OleUIMetafilePictIconFree(lpPS->hMetaPictOD); + else + OleUIMetafilePictIconFree(lpPS->hMetaPictLSD); + + // Free data assocatiated with each list box entry + FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELIST)); + FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELINKLIST)); + SendDlgItemMessage(hDlg, IDC_PS_DISPLAYLIST, LB_RESETCONTENT, 0, 0); + + // Initialize user selections in the Paste and PasteLink listboxes + lpPS->nPasteListCurSel = 0; + lpPS->nPasteLinkListCurSel = 0; + + // Free previous object descriptor/link descriptor data + if (lpPS->hObjDesc != NULL) + { + GlobalFree(lpPS->hObjDesc); + lpPS->hObjDesc = NULL; + } + if (lpPS->hLinkSrcDesc != NULL) + { + GlobalFree(lpPS->hLinkSrcDesc); + lpPS->hLinkSrcDesc = NULL; + } + + lpPS->szAppName[0] = '\0'; + + // GetData CF_OBJECTDESCRIPTOR. If the object on the clipboard in an + // OLE1 object (offering CF_OWNERLINK) or has been copied to + // clipboard by FileMaager (offering CF_FILENAME), an + // OBJECTDESCRIPTOR will be created will be created from CF_OWNERLINK + // or CF_FILENAME. See OBJECTDESCRIPTOR for more info. + + STGMEDIUM medium; + CLIPFORMAT cfFormat; + lpPS->hObjDesc = OleStdFillObjectDescriptorFromData( + lpOPS->lpSrcDataObj, &medium, &cfFormat); + if (lpPS->hObjDesc) + { + LPOBJECTDESCRIPTOR lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(lpPS->hObjDesc); + + // Get FullUserTypeName, SourceOfCopy and CLSID + if (lpOD->dwFullUserTypeName) +#if defined(WIN32) && !defined(UNICODE) + WTOA(lpPS->szFullUserTypeNameOD, (LPWSTR)((LPBYTE)lpOD+lpOD->dwFullUserTypeName), PS_UNKNOWNNAMELEN); +#else + lstrcpyn(lpPS->szFullUserTypeNameOD, (LPTSTR)((LPBYTE)lpOD+lpOD->dwFullUserTypeName), PS_UNKNOWNNAMELEN); +#endif + else + lstrcpyn(lpPS->szFullUserTypeNameOD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN); + + if (lpOD->dwSrcOfCopy) + { +#if defined(WIN32) && !defined(UNICODE) + WTOA(lpPS->szSourceOfDataOD, (LPWSTR)((LPBYTE)lpOD+lpOD->dwSrcOfCopy), PS_UNKNOWNNAMELEN); +#else + lstrcpyn(lpPS->szSourceOfDataOD, (LPTSTR)((LPBYTE)lpOD+lpOD->dwSrcOfCopy), PS_UNKNOWNNAMELEN); +#endif + // If CF_FILENAME was offered, source of copy is a + // path name. Fit the path to the static control that will display it. + if (cfFormat == _g_cfFileName) + { + lstrcpyn(lpPS->szSourceOfDataOD, ChopText(GetDlgItem(hDlg, IDC_PS_SOURCETEXT), 0, + lpPS->szSourceOfDataOD, 0), PS_UNKNOWNNAMELEN); + } + } + else + lstrcpyn(lpPS->szSourceOfDataOD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN); + + lpPS->clsidOD = lpOD->clsid; + lpPS->sizelOD = lpOD->sizel; + + // Does source specify DVASPECT_ICON? + if (lpOD->dwDrawAspect & DVASPECT_ICON) + lpPS->fSrcAspectIconOD = TRUE; + else + lpPS->fSrcAspectIconOD = FALSE; + + // Does source specify OLEMISC_ONLYICONIC? + if (lpOD->dwStatus & OLEMISC_ONLYICONIC) + lpPS->fSrcOnlyIconicOD = TRUE; + else + lpPS->fSrcOnlyIconicOD = FALSE; + + // Get application name of source from auxusertype3 in the registration database + LPOLESTR lpszAppName = NULL; + if (OleRegGetUserType(lpPS->clsidOD, USERCLASSTYPE_APPNAME, + &lpszAppName) == NOERROR) + { +#if defined(WIN32) && !defined(UNICODE) + WTOA(lpPS->szAppName, lpszAppName, OLEUI_CCHKEYMAX); +#else + lstrcpyn(lpPS->szAppName, lpszAppName, OLEUI_CCHKEYMAX); +#endif + OleStdFree(lpszAppName); + } + else + { + if (0 == LoadString(_g_hOleStdResInst, IDS_PSUNKNOWNAPP, lpPS->szAppName, + PS_UNKNOWNSTRLEN)) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L); + return FALSE; + } + } + + // Retrieve an icon from the object + if (lpPS->fSrcAspectIconOD) + { + lpPS->hMetaPictOD = OleStdGetData( + lpOPS->lpSrcDataObj, + (CLIPFORMAT) CF_METAFILEPICT, + NULL, + DVASPECT_ICON, + &medium + ); + + } + // If object does not offer icon, obtain it from the CLSID + if (NULL == lpPS->hMetaPictOD) + lpPS->hMetaPictOD = OleGetIconOfClass(lpPS->clsidOD, NULL, TRUE); + } + + // Does object offer CF_LINKSRCDESCRIPTOR? + lpPS->hLinkSrcDesc = OleStdGetData( + lpOPS->lpSrcDataObj, + (CLIPFORMAT) _g_cfLinkSrcDescriptor, + NULL, + DVASPECT_CONTENT, + &medium); + if (lpPS->hLinkSrcDesc) + { + // Get FullUserTypeName, SourceOfCopy and CLSID + LPLINKSRCDESCRIPTOR lpLSD = (LPLINKSRCDESCRIPTOR)GlobalLock(lpPS->hLinkSrcDesc); + if (lpLSD->dwFullUserTypeName) +#if defined(WIN32) && !defined(UNICODE) + WTOA(lpPS->szFullUserTypeNameLSD, (LPWSTR)((LPBYTE)lpLSD+lpLSD->dwFullUserTypeName), PS_UNKNOWNNAMELEN); +#else + lstrcpyn(lpPS->szFullUserTypeNameLSD, (LPTSTR)((LPBYTE)lpLSD+lpLSD->dwFullUserTypeName), PS_UNKNOWNNAMELEN); +#endif + else + lstrcpyn(lpPS->szFullUserTypeNameLSD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN); + + if (lpLSD->dwSrcOfCopy) +#if defined(WIN32) && !defined(UNICODE) + WTOA(lpPS->szSourceOfDataLSD, (LPWSTR)((LPBYTE)lpLSD+lpLSD->dwSrcOfCopy), PS_UNKNOWNNAMELEN); +#else + lstrcpyn(lpPS->szSourceOfDataLSD, (LPTSTR)((LPBYTE)lpLSD+lpLSD->dwSrcOfCopy), PS_UNKNOWNNAMELEN); +#endif + else + lstrcpyn(lpPS->szSourceOfDataLSD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN); + + // if no ObjectDescriptor, then use LinkSourceDescriptor source string + if (!lpPS->hObjDesc) + lstrcpyn(lpPS->szSourceOfDataOD, lpPS->szSourceOfDataLSD, PS_UNKNOWNNAMELEN); + + lpPS->clsidLSD = lpLSD->clsid; + lpPS->sizelLSD = lpLSD->sizel; + + // Does source specify DVASPECT_ICON? + if (lpLSD->dwDrawAspect & DVASPECT_ICON) + lpPS->fSrcAspectIconLSD = TRUE; + else + lpPS->fSrcAspectIconLSD = FALSE; + + // Does source specify OLEMISC_ONLYICONIC? + if (lpLSD->dwStatus & OLEMISC_ONLYICONIC) + lpPS->fSrcOnlyIconicLSD = TRUE; + else + lpPS->fSrcOnlyIconicLSD = FALSE; + + // Retrieve an icon from the object + if (lpPS->fSrcAspectIconLSD) + { + lpPS->hMetaPictLSD = OleStdGetData( + lpOPS->lpSrcDataObj, + CF_METAFILEPICT, + NULL, + DVASPECT_ICON, + &medium + ); + } + // If object does not offer icon, obtain it from the CLSID + if (NULL == lpPS->hMetaPictLSD) + { + HWND hIconWnd = GetDlgItem(hDlg, IDC_PS_ICONDISPLAY); + RECT IconRect; GetClientRect(hIconWnd, &IconRect); + + LPTSTR lpszLabel = OleStdCopyString(lpPS->szSourceOfDataLSD); + // width is 2 times width of iconbox because it can wrap + int nWidth = (IconRect.right-IconRect.left) * 2; + // limit text to the width or max characters + LPTSTR lpszChopLabel = ChopText(hIconWnd, nWidth, lpszLabel, + lstrlen(lpszLabel)); +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszChopLabel[MAX_PATH]; + ATOW(wszChopLabel, lpszChopLabel, MAX_PATH); + lpPS->hMetaPictLSD = + OleGetIconOfClass(lpPS->clsidLSD, wszChopLabel, FALSE); +#else + lpPS->hMetaPictLSD = + OleGetIconOfClass(lpPS->clsidLSD, lpszChopLabel, FALSE); +#endif + OleStdFree(lpszLabel); + } + } + else if (lpPS->hObjDesc) // Does not offer CF_LINKSRCDESCRIPTOR but offers CF_OBJECTDESCRIPTOR + { + // Copy the values of OBJECTDESCRIPTOR + lstrcpyn(lpPS->szFullUserTypeNameLSD, lpPS->szFullUserTypeNameOD, PS_UNKNOWNNAMELEN); + lstrcpyn(lpPS->szSourceOfDataLSD, lpPS->szSourceOfDataOD, PS_UNKNOWNNAMELEN); + lpPS->clsidLSD = lpPS->clsidOD; + lpPS->sizelLSD = lpPS->sizelOD; + lpPS->fSrcAspectIconLSD = lpPS->fSrcAspectIconOD; + lpPS->fSrcOnlyIconicLSD = lpPS->fSrcOnlyIconicOD; + + // Don't copy the hMetaPict; instead get a separate copy + if (lpPS->fSrcAspectIconLSD) + { + lpPS->hMetaPictLSD = OleStdGetData( + lpOPS->lpSrcDataObj, + CF_METAFILEPICT, + NULL, + DVASPECT_ICON, + &medium + ); + } + if (NULL == lpPS->hMetaPictLSD) + { + HWND hIconWnd = GetDlgItem(hDlg, IDC_PS_ICONDISPLAY); + RECT IconRect; GetClientRect(hIconWnd, &IconRect); + + LPTSTR lpszLabel = OleStdCopyString(lpPS->szSourceOfDataLSD); + // width is 2 times width of iconbox because it can wrap + int nWidth = (IconRect.right-IconRect.left) * 2; + // limit text to the width or max characters + LPTSTR lpszChopLabel = ChopText(hIconWnd, nWidth, lpszLabel, + lstrlen(lpszLabel)); +#if defined(WIN32) && !defined(UNICODE) + OLECHAR wszChopLabel[MAX_PATH]; + ATOW(wszChopLabel, lpszChopLabel, MAX_PATH); + lpPS->hMetaPictLSD = + OleGetIconOfClass(lpPS->clsidLSD, wszChopLabel, FALSE); +#else + lpPS->hMetaPictLSD = + OleGetIconOfClass(lpPS->clsidLSD, lpszChopLabel, FALSE); +#endif + OleStdFree(lpszLabel); + } + } + + // Not an OLE object + if (lpPS->hObjDesc == NULL && lpPS->hLinkSrcDesc == NULL) + { + lstrcpyn(lpPS->szFullUserTypeNameLSD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN); + lstrcpyn(lpPS->szFullUserTypeNameOD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN); + lstrcpyn(lpPS->szSourceOfDataLSD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN); + lstrcpyn(lpPS->szSourceOfDataOD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN); + lpPS->hMetaPictLSD = lpPS->hMetaPictOD = NULL; + } + + // Allocate scratch memory to construct item names in the paste and pastelink listboxes + if (lpPS->hBuff != NULL) + { + GlobalFree(lpPS->hBuff); + lpPS->hBuff = NULL; + } + + lpPS->hBuff = AllocateScratchMem(lpPS); + if (lpPS->hBuff == NULL) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L); + return FALSE; + } + + // Select the Paste Link Button if specified. Otherwise select + // Paste Button by default + if (lpPS->dwFlags & PSF_SELECTPASTELINK) + lpPS->dwFlags = (lpPS->dwFlags & ~PSF_SELECTPASTE) | PSF_SELECTPASTELINK; + else + lpPS->dwFlags =(lpPS->dwFlags & ~PSF_SELECTPASTELINK) | PSF_SELECTPASTE; + + // Mark which PasteEntry formats are available from source data object + OleStdMarkPasteEntryList( + lpOPS->lpSrcDataObj, lpOPS->arrPasteEntries, lpOPS->cPasteEntries); + + // Check if items are available to be pasted + BOOL fPasteAvailable = FFillPasteList(hDlg, lpPS); + if (!fPasteAvailable) + lpPS->dwFlags &= ~PSF_SELECTPASTE; + StandardEnableDlgItem(hDlg, IDC_PS_PASTE, fPasteAvailable); + + // Check if items are available to be paste-linked + BOOL fPasteLinkAvailable = FFillPasteLinkList(hDlg, lpPS); + if (!fPasteLinkAvailable) + lpPS->dwFlags &= ~PSF_SELECTPASTELINK; + StandardEnableDlgItem(hDlg, IDC_PS_PASTELINK, fPasteLinkAvailable); + + // If one of Paste or PasteLink is disabled, select the other one + // regardless of what the input flags say + if (fPasteAvailable && !fPasteLinkAvailable) + lpPS->dwFlags |= PSF_SELECTPASTE; + if (fPasteLinkAvailable && !fPasteAvailable) + lpPS->dwFlags |= PSF_SELECTPASTELINK; + + BOOL bEnabled = TRUE; + if (lpPS->dwFlags & PSF_SELECTPASTE) + { + // FTogglePaste will set the PSF_SELECTPASTE flag, so clear it. + lpPS->dwFlags &= ~PSF_SELECTPASTE; + CheckRadioButton(hDlg, IDC_PS_PASTE, IDC_PS_PASTELINK, IDC_PS_PASTE); + FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE); + } + else if (lpPS->dwFlags & PSF_SELECTPASTELINK) + { + // FTogglePaste will set the PSF_SELECTPASTELINK flag, so clear it. + lpPS->dwFlags &= ~PSF_SELECTPASTELINK; + CheckRadioButton(hDlg, IDC_PS_PASTE, IDC_PS_PASTELINK, IDC_PS_PASTELINK); + FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK); + } + else // Items are not available to be be Pasted or Paste-Linked + { + // Enable or disable DisplayAsIcon and set the result text and image + EnableDisplayAsIcon(hDlg, lpPS); + SetPasteSpecialHelpResults(hDlg, lpPS); + SetDlgItemText(hDlg, IDC_PS_SOURCETEXT, lpPS->szSourceOfDataOD); + CheckRadioButton(hDlg, IDC_PS_PASTE, IDC_PS_PASTELINK, 0); + bEnabled = FALSE; + } + StandardEnableDlgItem(hDlg, IDOK, bEnabled); + + return TRUE; +} + +/* + * FPasteSpecialInit + * + * Purpose: + * WM_INITIDIALOG handler for the Paste Special dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ +BOOL FPasteSpecialInit(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + // Copy the structure at lParam into our instance memory. + HFONT hFont; + LPPASTESPECIAL lpPS = (LPPASTESPECIAL)LpvStandardInit(hDlg, sizeof(PASTESPECIAL), &hFont); + + // PvStandardInit sent a termination to us already. + if (NULL == lpPS) + return FALSE; + + LPOLEUIPASTESPECIAL lpOPS = (LPOLEUIPASTESPECIAL)lParam; + + // Copy other information from lpOPS that we might modify. + lpPS->lpOPS = lpOPS; + lpPS->nIDD = IDD_PASTESPECIAL; + lpPS->dwFlags = lpOPS->dwFlags; + + // If we got a font, send it to the necessary controls. + if (NULL!=hFont) + { + SendDlgItemMessage(hDlg, IDC_PS_SOURCETEXT, WM_SETFONT, (WPARAM)hFont, 0L); + SendDlgItemMessage(hDlg, IDC_PS_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L); + } + + // Hide the help button if required + if (!(lpPS->lpOPS->dwFlags & PSF_SHOWHELP)) + StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE); + + // Show or hide the Change icon button + if (lpPS->dwFlags & PSF_HIDECHANGEICON) + DestroyWindow(GetDlgItem(hDlg, IDC_PS_CHANGEICON)); + + // Hide all DisplayAsIcon related controls if it should be disabled + if (lpPS->dwFlags & PSF_DISABLEDISPLAYASICON) + { + StandardShowDlgItem(hDlg, IDC_PS_DISPLAYASICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE); + } + + // clear PSF_CHECKDISPLAYASICON -> it's an output parameter only + lpPS->dwFlags &= ~ PSF_CHECKDISPLAYASICON; + + // Change the caption if required + if (NULL != lpOPS->lpszCaption) + SetWindowText(hDlg, lpOPS->lpszCaption); + + // Load 'Unknown Source' and 'Unknown Type' strings + int n = LoadString(_g_hOleStdResInst, IDS_PSUNKNOWNTYPE, lpPS->szUnknownType, PS_UNKNOWNSTRLEN); + if (n) + n = LoadString(_g_hOleStdResInst, IDS_PSUNKNOWNSRC, lpPS->szUnknownSource, PS_UNKNOWNSTRLEN); + if (!n) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L); + return FALSE; + } + + if (!FPasteSpecialReInit(hDlg, lpPS)) + return FALSE; + + // Give initial focus to the list box + SetFocus(GetDlgItem(hDlg, IDC_PS_DISPLAYLIST)); + + // Set property to handle clipboard change notifications + SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST); + SetProp(hDlg, NEXTCBVIEWER, SetClipboardViewer(hDlg)); + + lpPS->fClipboardChanged = FALSE; + + /* + * PERFORM OTHER INITIALIZATION HERE. + */ + + // Call the hook with lCustData in lParam + UStandardHook(lpPS, hDlg, WM_INITDIALOG, wParam, lpOPS->lCustData); + return TRUE; +} + +/* + * FTogglePasteType + * + * Purpose: + * Toggles between Paste and Paste Link. The Paste list and PasteLink + * list are always invisible. The Display List is filled from either + * the Paste list or the PasteLink list depending on which Paste radio + * button is selected. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * dwOption Paste or PasteSpecial option + * + * Return Value: + * BOOL Returns TRUE if the option has already been selected. + * Otherwise the option is selected and FALSE is returned + */ +BOOL FTogglePasteType(HWND hDlg, LPPASTESPECIAL lpPS, DWORD dwOption) +{ + DWORD dwTemp; + HWND hList, hListDisplay; + DWORD dwData; + int i, nItems; + LPTSTR lpsz; + + // Skip all this if the button is already selected + if (lpPS->dwFlags & dwOption) + return TRUE; + + dwTemp = PSF_SELECTPASTE | PSF_SELECTPASTELINK; + lpPS->dwFlags = (lpPS->dwFlags & ~dwTemp) | dwOption; + + // Hide IconDisplay. This prevents flashing if the icon display is changed + StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE); + + hListDisplay = GetDlgItem(hDlg, IDC_PS_DISPLAYLIST); + + // If Paste was selected + if (lpPS->dwFlags & PSF_SELECTPASTE) + { + // Set the Source of the object in the clipboard + SetDlgItemText(hDlg, IDC_PS_SOURCETEXT, lpPS->szSourceOfDataOD); + + // If an icon is available + if (lpPS->hMetaPictOD) + // Set the icon display + SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGESET, + 0, (LPARAM)lpPS->hMetaPictOD); + + hList = GetDlgItem(hDlg, IDC_PS_PASTELIST); + // We are switching from PasteLink to Paste. Remember current selection + // in PasteLink list so it can be restored. + lpPS->nPasteLinkListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L); + if (lpPS->nPasteLinkListCurSel == LB_ERR) + lpPS->nPasteLinkListCurSel = 0; + // Remember if user selected Paste or PasteLink + lpPS->fLink = FALSE; + } + else // If PasteLink was selected + { + // Set the Source of the object in the clipboard + SetDlgItemText(hDlg, IDC_PS_SOURCETEXT, lpPS->szSourceOfDataLSD); + + // If an icon is available + if (lpPS->hMetaPictLSD) + // Set the icon display + SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGESET, + 0, (LPARAM)lpPS->hMetaPictLSD); + + hList = GetDlgItem(hDlg, IDC_PS_PASTELINKLIST); + // We are switching from Paste to PasteLink. Remember current selection + // in Paste list so it can be restored. + lpPS->nPasteListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L); + if (lpPS->nPasteListCurSel == LB_ERR) + lpPS->nPasteListCurSel = 0; + // Remember if user selected Paste or PasteLink + lpPS->fLink = TRUE; + } + + // Turn drawing off while the Display List is being filled + SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)FALSE, 0L); + + // Move data to Display list box + SendMessage(hListDisplay, LB_RESETCONTENT, 0, 0L); + nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L); + lpsz = (LPTSTR)GlobalLock(lpPS->hBuff); + for (i = 0; i < nItems; i++) + { + SendMessage(hList, LB_GETTEXT, (WPARAM)i, (LPARAM)lpsz); + dwData = SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L); + SendMessage(hListDisplay, LB_INSERTSTRING, (WPARAM)i, (LPARAM)lpsz); + SendMessage(hListDisplay, LB_SETITEMDATA, (WPARAM)i, dwData); + } + GlobalUnlock(lpPS->hBuff); + + // Restore the selection in the Display List from user's last selection + if (lpPS->dwFlags & PSF_SELECTPASTE) + SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteListCurSel, 0L); + else + SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteLinkListCurSel, 0L); + + // Paint Display List + SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)TRUE, 0L); + InvalidateRect(hListDisplay, NULL, TRUE); + UpdateWindow(hListDisplay); + + // Auto give the focus to the Display List + if (GetForegroundWindow() == hDlg) + SetFocus(hListDisplay); + + // Enable/Disable DisplayAsIcon and set the help result text and bitmap corresponding to + // the current selection + ChangeListSelection(hDlg, lpPS, hListDisplay); + + return FALSE; +} + +/* + * ChangeListSelection + * + * Purpose: + * When the user changes the selection in the list, DisplayAsIcon is enabled or disabled, + * Result text and bitmap are updated and the index of the arrPasteEntries[] corresponding + * to the current format selection is saved. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * hList HWND of the List + * + * Return Value: + * No return value + */ +void ChangeListSelection(HWND hDlg, LPPASTESPECIAL lpPS, HWND hList) +{ + LPPASTELISTITEMDATA lpItemData; + int nCurSel; + + EnableDisplayAsIcon(hDlg, lpPS); + SetPasteSpecialHelpResults(hDlg, lpPS); + + // Remember index of arrPasteEntries[] corresponding to the current selection + nCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L); + if (nCurSel == LB_ERR) + return; + lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA, + (WPARAM)nCurSel, 0L); + if ((LRESULT)lpItemData == LB_ERR) + return; + lpPS->nSelectedIndex = lpItemData->nPasteEntriesIndex; +} + +/* + * EnableDisplayAsIcon + * + * Purpose: + * Enable or disable the DisplayAsIcon button depending on whether + * the current selection can be displayed as an icon or not. The following table describes + * the state of DisplayAsIcon. The calling application is termed CONTAINER, the source + * of data on the clipboard is termed SOURCE. + * Y = Yes; N = No; Blank = State does not matter; + * ===================================================================== + * SOURCE SOURCE CONTAINER DisplayAsIcon + * specifies specifies specifies Initial State + * DVASPECT_ICON OLEMISC_ONLYICONIC OLEUIPASTE_ENABLEICON + * + * N Unchecked&Disabled + * Y Y Checked&Disabled + * Y N Y Checked&Enabled + * N N Y Unchecked&Enabled + * ===================================================================== + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * No return value + */ +void EnableDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS) +{ + int nIndex; + BOOL fCntrEnableIcon; + BOOL fSrcOnlyIconic = (lpPS->fLink) ? lpPS->fSrcOnlyIconicLSD : lpPS->fSrcOnlyIconicOD; + BOOL fSrcAspectIcon = (lpPS->fLink) ? lpPS->fSrcAspectIconLSD : lpPS->fSrcAspectIconOD; + HWND hList; + LPPASTELISTITEMDATA lpItemData; + HGLOBAL hMetaPict = (lpPS->fLink) ? lpPS->hMetaPictLSD : lpPS->hMetaPictOD; + + hList = GetDlgItem(hDlg, IDC_PS_DISPLAYLIST); + + // Get data corresponding to the current selection in the listbox + nIndex = (int)SendMessage(hList, LB_GETCURSEL, 0, 0); + if (nIndex != LB_ERR) + { + lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA, (WPARAM)nIndex, 0L); + if ((LRESULT)lpItemData != LB_ERR) + fCntrEnableIcon = lpItemData->fCntrEnableIcon; + else fCntrEnableIcon = FALSE; + } + else fCntrEnableIcon = FALSE; + + // If there is an icon available + if (hMetaPict != NULL) + { + if (!fCntrEnableIcon) // Does CONTAINER specify OLEUIPASTE_ENABLEICON? + { + // Uncheck & Disable DisplayAsIcon + lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, FALSE); + StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, FALSE); + + // Hide IconDisplay and ChangeIcon button + StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE); + } + else if (fSrcOnlyIconic) // Does SOURCE specify OLEMISC_ONLYICONIC? + { + // Check & Disable DisplayAsIcon + lpPS->dwFlags |= PSF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, TRUE); + StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, FALSE); + + // Show IconDisplay and ChangeIcon button + StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_SHOWNORMAL); + StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_SHOWNORMAL); + } + else if (fSrcAspectIcon) // Does SOURCE specify DVASPECT_ICON? + { + // Check & Enable DisplayAsIcon + lpPS->dwFlags |= PSF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, TRUE); + StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, TRUE); + + // Show IconDisplay and ChangeIcon button + StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_SHOWNORMAL); + StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_SHOWNORMAL); + } + else + { + //Uncheck and Enable DisplayAsIcon + lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, FALSE); + StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, TRUE); + + // Hide IconDisplay and ChangeIcon button + StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE); + + } + } + else // No icon available + { + // Unchecked & Disabled + lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON; + CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, FALSE); + StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, FALSE); + + // Hide IconDisplay and ChangeIcon button + StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE); + StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE); + } +} + +/* + * ToggleDisplayAsIcon + * + * Purpose: + * Toggles the DisplayAsIcon button. Hides or shows the Icon Display and + * the ChangeIcon button and changes the help result text and bitmap. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * None + * + */ +void ToggleDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS) +{ + BOOL fCheck; + int i; + + fCheck = IsDlgButtonChecked(hDlg, IDC_PS_DISPLAYASICON); + + if (fCheck) + lpPS->dwFlags |= PSF_CHECKDISPLAYASICON; + else lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON; + + // Set the help result text and bitmap + SetPasteSpecialHelpResults(hDlg, lpPS); + + // Show or hide the Icon Display and ChangeIcon button depending + // on the check state + i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE; + StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, i); + StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, i); +} + +/* + * ChangeIcon + * + * Purpose: + * Brings up the ChangeIcon dialog which allows the user to change + * the icon and label. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * None + * + */ + +void ChangeIcon(HWND hDlg, LPPASTESPECIAL lpPS) +{ + OLEUICHANGEICON ci; + UINT uRet; + CLSID clsid = (lpPS->fLink) ? lpPS->clsidLSD : lpPS->clsidOD; + + //Initialize the structure + memset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci)); + + ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY, + IBXM_IMAGEGET, 0, 0L); + ci.cbStruct = sizeof(ci); + ci.hWndOwner = hDlg; + ci.clsid = clsid; + ci.dwFlags = CIF_SELECTCURRENT; + + // Only show help in the ChangeIcon dialog if we're showing it in this dialog. + if (lpPS->dwFlags & PSF_SHOWHELP) + ci.dwFlags |= CIF_SHOWHELP; + + // Let the hook in to customize Change Icon if desired. + uRet = UStandardHook(lpPS, hDlg, uMsgChangeIcon, 0, (LPARAM)&ci); + + if (0 == uRet) + uRet=(UINT)(OLEUI_OK==OleUIChangeIcon(&ci)); + + // Update the display if necessary. + if (0!=uRet) + { + /* + * OleUIChangeIcon will have already freed our + * current hMetaPict that we passed in when OK is + * pressed in that dialog. So we use 0L as lParam + * here so the IconBox doesn't try to free the + * metafilepict again. + */ + SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY, + IBXM_IMAGESET, 0, (LPARAM)ci.hMetaPict); + // Remember the new icon chosen by the user. Note that Paste and PasteLink have separate + // icons - changing one does not change the other. + if (lpPS->fLink) + lpPS->hMetaPictLSD = ci.hMetaPict; + else + lpPS->hMetaPictOD = ci.hMetaPict; + } +} + +/* + *SetPasteSpecialHelpResults + * + * Purpose: + * Sets the help result text and bitmap according to the current + * list selection. The following state table indicates which ResultText + * and ResultImage are selected. If %s in the lpstrFormatName is present, + * it is assumed that an object is being pasted/paste-linked, otherwise it + * is assumed that data is being pasted/paste-linked. + * Y = Yes; N = No; Blank = State does not matter; + * The numbers in the the ResultText and ResultImage columns refer to the table + * entries that follow. + * ===================================================================== + * Paste/ lpstrFormatName in DisplayAsIcon Result Result + * PasteLink arrPasteEntry[]contains %s checked Text Image + * (Is Object == Y, Is Data == N) + * Paste N 1 1 + * Paste Y N 2 2 + * Paste Y Y 3 3 + * PasteLink N 4 4 + * PasteLink Y N 5 4 + * PasteLink Y Y 6 5 + * ===================================================================== + * Result Text: + * + * 1. "Inserts the contents of the Clipboard into your document as <native type name, + * and optionally an additional help sentence>" + * 2. "Inserts the contents of the Clipboard into your document so that you may + * activate it using <object app name>" + * 3. "Inserts the contents of the Clipboard into your document so that you may + * activate it using <object app name>. It will be displayed as an icon." + * 4. "Inserts the contents of the Clipboard into your document as <native type name>. + * Paste Link creates a link to the source file so that changes to the source file + * will be reflected in your document." + * 5. "Inserts a picture of the Clipboard contents into your document. Paste Link + * creates a link to the source file so that changes to the source file will be + * reflected in your document." + * 6. "Inserts an icon into your document which represents the Clipboard contents. + * Paste Link creates a link to the source file so that changes to the source file + * will be reflected in your document." + * ===================================================================== + * Result Image: + * + * 1. Clipboard Image + * 2. Paste image, non-iconic. + * 3. Paste image, iconic. + * 4. Paste Link image, non-iconic + * 5. Paste Link image, iconic + * ==================================================================== + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * No return value + */ +void SetPasteSpecialHelpResults(HWND hDlg, LPPASTESPECIAL lpPS) +{ + LPTSTR psz1, psz2, psz3, psz4; + UINT i, iString, iImage, cch; + int nPasteEntriesIndex; + BOOL fDisplayAsIcon; + BOOL fIsObject; + HWND hList; + LPPASTELISTITEMDATA lpItemData; + LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; + LPTSTR szFullUserTypeName = (lpPS->fLink) ? + lpPS->szFullUserTypeNameLSD : lpPS->szFullUserTypeNameOD; + LPTSTR szInsert; + + hList = GetDlgItem(hDlg, IDC_PS_DISPLAYLIST); + + i=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L); + if (i != LB_ERR) + { + lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, i, 0L); + if ((LRESULT)lpItemData == LB_ERR) return; + nPasteEntriesIndex = lpItemData->nPasteEntriesIndex; + // Check if there is a '%s' in the lpstrFormatName, then an object is being + // pasted/pastelinked. Otherwise Data is being pasted-pastelinked. + fIsObject = FHasPercentS(lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName, + lpPS); + } + else + return; + + // Is DisplayAsIcon checked? + fDisplayAsIcon=(0L!=(lpPS->dwFlags & PSF_CHECKDISPLAYASICON)); + + szInsert = szFullUserTypeName; + + if (lpPS->dwFlags & PSF_SELECTPASTE) // If user selected Paste + { + if (fIsObject) + { + iString = fDisplayAsIcon ? IDS_PSPASTEOBJECTASICON : IDS_PSPASTEOBJECT; + iImage = fDisplayAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED; + szInsert = lpPS->szAppName; + } + else + { + iString = IDS_PSPASTEDATA; + iImage = RESULTIMAGE_PASTE; + } + } + else if (lpPS->dwFlags & PSF_SELECTPASTELINK) // User selected PasteLink + { + if (fIsObject) + { + iString = fDisplayAsIcon ? IDS_PSPASTELINKOBJECTASICON : IDS_PSPASTELINKOBJECT; + iImage = fDisplayAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK; + } + else + { + iString = IDS_PSPASTELINKDATA; + iImage = RESULTIMAGE_LINK; + } + + } + else // Should never occur. + { + iString = IDS_PSNONOLE; + iImage = RESULTIMAGE_PASTE; + } + + // hBuff contains enough space for the 4 buffers required to build up the help + // result text. + cch = (UINT)(GlobalSize(lpPS->hBuff) / sizeof(TCHAR)) / 4; + + psz1 = (LPTSTR)GlobalLock(lpPS->hBuff); + psz2 = psz1 + cch; + psz3 = psz2 + cch; + psz4 = psz3 + cch; + + // Default is an empty string. + *psz1 = 0; + + if (0 != LoadString(_g_hOleStdResInst, iString, psz1, cch) && + nPasteEntriesIndex != -1) + { + // Insert the FullUserTypeName of the source object into the partial result text + // specified by the container. + wsprintf(psz3, lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrResultText, + (LPTSTR)szInsert); + // Insert the above partial result text into the standard result text. + wsprintf(psz4, psz1, (LPTSTR)psz3); + psz1 = psz4; + } + + // If LoadString failed, we simply clear out the results (*psz1 = 0 above) + SetDlgItemText(hDlg, IDC_PS_RESULTTEXT, psz1); + + GlobalUnlock(lpPS->hBuff); + + // Change the result bitmap + SendDlgItemMessage(hDlg, IDC_PS_RESULTIMAGE, RIM_IMAGESET, iImage, 0L); +} + +/* + * FAddPasteListItem + * + * Purpose: + * Adds an item to the list box + * + * Parameters: + * hList HWND List into which item is to be added + * fInsertFirst BOOL Insert in the beginning of the list? + * nPasteEntriesIndex int Index of Paste Entry array this list item corresponsds to + * lpPS Paste Special Dialog Structure + * lpszBuf LPSTR Scratch buffer to build up string for list entry + * lpszFullUserTypeName LPSTR full user type name for object entry + * + * Return Value: + * BOOL TRUE if sucessful. + * FALSE if unsucessful. + */ +BOOL FAddPasteListItem( + HWND hList, BOOL fInsertFirst, int nPasteEntriesIndex, + LPPASTESPECIAL lpPS, LPTSTR lpszBuf, LPTSTR lpszFullUserTypeName) +{ + LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; + LPPASTELISTITEMDATA lpItemData; + int nIndex; + + // Allocate memory for each list box item + lpItemData = (LPPASTELISTITEMDATA)OleStdMalloc(sizeof(PASTELISTITEMDATA)); + if (NULL == lpItemData) + return FALSE; + + // Fill data associated with each list box item + lpItemData->nPasteEntriesIndex = nPasteEntriesIndex; + lpItemData->fCntrEnableIcon = ((lpOPS->arrPasteEntries[nPasteEntriesIndex].dwFlags & + OLEUIPASTE_ENABLEICON) ? TRUE : FALSE); + + // Build list box entry string, insert the string and add the data the corresponds to it + wsprintf( + lpszBuf, + lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName, + lpszFullUserTypeName + ); + + // only add to listbox if not a duplicate + if (LB_ERR!=SendMessage(hList,LB_FINDSTRING, 0, (LPARAM)lpszBuf)) + { + // item is already in list; SKIP this one + OleStdFree((LPVOID)lpItemData); + return TRUE; // this is NOT an error + } + + nIndex = (int)SendMessage( + hList, + (fInsertFirst ? LB_INSERTSTRING : LB_ADDSTRING), + 0, + (LPARAM)lpszBuf + ); + SendMessage( + hList, + LB_SETITEMDATA, + nIndex, + (LPARAM)(LPPASTELISTITEMDATA)lpItemData + ); + return TRUE; +} + + +/* + * FFillPasteList + * + * Purpose: + * Fills the invisible paste list with the formats offered by the clipboard object and + * asked for by the container. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * BOOL TRUE if sucessful and if formats could be found. + * FALSE if unsucessful or if no formats could be found. + */ +BOOL FFillPasteList(HWND hDlg, LPPASTESPECIAL lpPS) +{ + LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; + HWND hList; + int i, j; + int nItems = 0; + int nDefFormat = -1; + BOOL fTryObjFmt = FALSE; + BOOL fInsertFirst; + BOOL fExclude; + + hList = GetDlgItem(hDlg, IDC_PS_PASTELIST); + SendMessage(hList, LB_RESETCONTENT, 0, 0); + + // Loop over the target's priority list of formats + for (i = 0; i < lpOPS->cPasteEntries; i++) + { + if (lpOPS->arrPasteEntries[i].dwFlags != OLEUIPASTE_PASTEONLY && + !(lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_PASTE)) + continue; + + fInsertFirst = FALSE; + + if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfFileName + || lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfEmbeddedObject + || lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfEmbedSource) + { + if (! fTryObjFmt) + { + fTryObjFmt = TRUE; // only use 1st object format + fInsertFirst = TRUE; // OLE obj format should always be 1st + + //Check if this CLSID is in the exclusion list. + fExclude=FALSE; + + for (j=0; j < (int)lpOPS->cClsidExclude; j++) + { + if (IsEqualCLSID(lpPS->clsidOD, lpOPS->lpClsidExclude[j])) + { + fExclude=TRUE; + break; + } + } + + if (fExclude) + continue; // don't add the object entry to list + + } + else + { + continue; // already added an object format to list + } + } + + // add to list if entry is marked TRUE + if (lpOPS->arrPasteEntries[i].dwScratchSpace) + { + if (nDefFormat < 0) + nDefFormat = (fInsertFirst ? 0 : nItems); + else if (fInsertFirst) + nDefFormat++; // adjust for obj fmt inserted 1st in list + + LPTSTR lpszBuf = (LPTSTR)GlobalLock(lpPS->hBuff); + if (lpszBuf) + { + if (!FAddPasteListItem(hList, fInsertFirst, i, lpPS, + lpszBuf, lpPS->szFullUserTypeNameOD)) + { + GlobalUnlock(lpPS->hBuff); + goto error; + } + GlobalUnlock(lpPS->hBuff); + } + nItems++; + } + } + + // initialize selection to first format matched in list + if (nDefFormat >= 0) + lpPS->nPasteListCurSel = nDefFormat; + + // Clean up + + // If no items have been added to the list box (none of the formats + // offered by the source matched those acceptable to the container), + // return FALSE + if (nItems > 0) + return TRUE; + else + return FALSE; + +error: + FreeListData(hList); + + return FALSE; +} + + +/* + * FFillPasteLinkList + * + * Purpose: + * Fills the invisible paste link list with the formats offered by the clipboard object and + * asked for by the container. + * + * Parameters: + * hDlg HWND of the dialog + * lpPS Paste Special Dialog Structure + * + * Return Value: + * BOOL TRUE if sucessful and if formats could be found. + * FALSE if unsucessful or if no formats could be found. + */ +BOOL FFillPasteLinkList(HWND hDlg, LPPASTESPECIAL lpPS) +{ + LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; + LPDATAOBJECT lpSrcDataObj = lpOPS->lpSrcDataObj; + LPENUMFORMATETC lpEnumFmtEtc = NULL; + OLEUIPASTEFLAG pasteFlag; + UINT arrLinkTypesSupported[PS_MAXLINKTYPES]; // Array of flags that + // indicate which link types + // are supported by source. + FORMATETC fmtetc; + int i, j; + int nItems = 0; + BOOL fLinkTypeSupported = FALSE; + HWND hList; + int nDefFormat = -1; + BOOL fTryObjFmt = FALSE; + BOOL fInsertFirst; + HRESULT hrErr; + + // Remember which link type formats are offered by lpSrcDataObj. + memset(&fmtetc, 0, sizeof(FORMATETC)); + for (i = 0; i < lpOPS->cLinkTypes; i++) + { + if (lpOPS->arrLinkTypes[i] == _g_cfLinkSource) + { + OLEDBG_BEGIN2(TEXT("OleQueryLinkFromData called\r\n")) + hrErr = OleQueryLinkFromData(lpSrcDataObj); + OLEDBG_END2 + if(NOERROR == hrErr) + { + arrLinkTypesSupported[i] = 1; + fLinkTypeSupported = TRUE; + } + else + arrLinkTypesSupported[i] = 0; + } + else + { + fmtetc.cfFormat = lpOPS->arrLinkTypes[i]; + fmtetc.dwAspect = DVASPECT_CONTENT; + fmtetc.tymed = 0xFFFFFFFF; // All tymed values + fmtetc.lindex = -1; + OLEDBG_BEGIN2(TEXT("IDataObject::QueryGetData called\r\n")) + hrErr = lpSrcDataObj->QueryGetData(&fmtetc); + OLEDBG_END2 + if(NOERROR == hrErr) + { + arrLinkTypesSupported[i] = 1; + fLinkTypeSupported = TRUE; + } + else arrLinkTypesSupported[i] = 0; + } + } + // No link types are offered by lpSrcDataObj + if (! fLinkTypeSupported) + { + nItems = 0; + goto cleanup; + } + + hList = GetDlgItem(hDlg, IDC_PS_PASTELINKLIST); + SendMessage(hList, LB_RESETCONTENT, 0, 0); + + // Enumerate the formats acceptable to container + for (i = 0; i < lpOPS->cPasteEntries; i++) + { + fLinkTypeSupported = FALSE; + + // If container will accept any link type offered by source object + if (lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_LINKANYTYPE) + fLinkTypeSupported = TRUE; + else + { + // Check if any of the link types offered by the source + // object are acceptable to the container + // This code depends on the LINKTYPE enum values being powers of 2 + for (pasteFlag = OLEUIPASTE_LINKTYPE1, j = 0; + j < lpOPS->cLinkTypes; + (UINT&)pasteFlag *= 2, j++) + { + if ((lpOPS->arrPasteEntries[i].dwFlags & pasteFlag) && + arrLinkTypesSupported[j]) + { + fLinkTypeSupported = TRUE; + break; + } + } + } + + fInsertFirst = FALSE; + + if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfFileName + || lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfLinkSource) + { + if (! fTryObjFmt) + { + fTryObjFmt = TRUE; // only use 1st object format + fInsertFirst = TRUE; // OLE obj format should always be 1st + } + else + { + continue; // already added an object format to list + } + } + + // add to list if entry is marked TRUE + if (fLinkTypeSupported && lpOPS->arrPasteEntries[i].dwScratchSpace) + { + if (nDefFormat < 0) + nDefFormat = (fInsertFirst ? 0 : nItems); + else if (fInsertFirst) + nDefFormat++; // adjust for obj fmt inserted 1st in list + + LPTSTR lpszBuf = (LPTSTR)GlobalLock(lpPS->hBuff); + if (lpszBuf) + { + if (!FAddPasteListItem(hList, fInsertFirst, i, lpPS, + lpszBuf, lpPS->szFullUserTypeNameLSD)) + { + GlobalUnlock(lpPS->hBuff); + goto error; + } + GlobalUnlock(lpPS->hBuff); + } + nItems++; + } + } // end FOR + + nItems = (int)SendMessage(hList, LB_GETCOUNT, 0, 0L); + + // initialize selection to first format matched in list + if (nDefFormat >= 0) + lpPS->nPasteLinkListCurSel = nDefFormat; + +cleanup: + // Clean up + + // If no items have been added to the list box (none of the formats + // offered by the source matched those acceptable to the destination), + // return FALSE + if (nItems > 0) + return TRUE; + else + return FALSE; + +error: + FreeListData(hList); + + return FALSE; +} + +/* + * FreeListData + * + * Purpose: + * Free the local memory associated with each list box item + * + * Parameters: + * hList HWND of the list + * + * Return Value: + * None + */ +void FreeListData(HWND hList) +{ + int nItems, i; + LPPASTELISTITEMDATA lpItemData; + + nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L); + for (i = 0; i < nItems; i++) + { + lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L); + if ((LRESULT)lpItemData != LB_ERR) + OleStdFree((LPVOID)lpItemData); + } +} + +/* + * FHasPercentS + * + * Purpose: + * Determines if string contains %s. + * + * Parameters: + * lpsz LPCSTR string in which occurence of '%s' is looked for + * + * Return Value: + * BOOL TRUE if %s is found, else FALSE. + */ +BOOL FHasPercentS(LPCTSTR lpsz, LPPASTESPECIAL lpPS) +{ + int n = 0; + LPTSTR lpszTmp; + + if (!lpsz) return FALSE; + // Copy input string to buffer. This allows caller to pass a + // code-based string. Code segments may be swapped out in low memory situations + // and so code-based strings need to be copied before string elements can be accessed. + lpszTmp = (LPTSTR)GlobalLock(lpPS->hBuff); + lstrcpy(lpszTmp, lpsz); + + while (*lpszTmp) + { + if (*lpszTmp == '%') + { + lpszTmp = CharNext(lpszTmp); + if (*lpszTmp == 's') // if %s, return + { + GlobalUnlock(lpPS->hBuff); + return TRUE; + } + else if (*lpszTmp == '%') // if %%, skip to next character + lpszTmp = CharNext(lpszTmp); + } + else + lpszTmp = CharNext(lpszTmp); + } + + GlobalUnlock(lpPS->hBuff); + return FALSE; +} + +/* + * AllocateScratchMem + * + * Purpose: + * Allocates scratch memory for use by the PasteSpecial dialog. The memory is + * is used as the buffer for building up strings using wsprintf. Strings are built up + * using the buffer while inserting items into the Paste & PasteLink lists and while + * setting the help result text. It must be big enough to handle the string that results after + * replacing the %s in the lpstrFormatName and lpstrResultText in arrPasteEntries[] + * by the FullUserTypeName. It must also be big enough to build the dialog's result text + * after %s substitutions by the FullUserTypeName or the ApplicationName. + * + * Parameters: + * lpPS Paste Special Dialog Structure + * + * Return Value: + * HGLOBAL Handle to allocated global memory + */ +HGLOBAL AllocateScratchMem(LPPASTESPECIAL lpPS) +{ + LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS; + int nLen, i; + int nSubstitutedText = 0; + int nAlloc = 0; + + // Get the maximum length of the FullUserTypeNames specified by OBJECTDESCRIPTOR + // and the LINKSRCDESCRIPTOR and the Application Name. Any of these may be substituted + // for %s in the result-text/list entries. + if (lpPS->szFullUserTypeNameOD) + nSubstitutedText = lstrlen(lpPS->szFullUserTypeNameOD); + if (lpPS->szFullUserTypeNameLSD) + nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szFullUserTypeNameLSD)); + if (lpPS->szAppName) + nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szAppName)); + + // Get the maximum length of lpstrFormatNames & lpstrResultText in arrPasteEntries + nLen = 0; + for (i = 0; i < lpOPS->cPasteEntries; i++) + { + nLen = max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrFormatName)); + nLen = max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrResultText)); + } + + // Get the maximum length of lpstrFormatNames and lpstrResultText after %s has + // been substituted (At most one %s can appear in each string). + // Add 1 to hold NULL terminator. + nAlloc = (nLen+nSubstitutedText+1)*sizeof(TCHAR); + + // Allocate scratch memory to be used to build strings + // nAlloc is big enough to hold any of the lpstrResultText or lpstrFormatName in arrPasteEntries[] + // after %s substitution. + // We also need space to build up the help result text. 512 is the maximum length of the + // standard dialog help text before substitutions. 512+nAlloc is the maximum length + // after %s substition. + // SetPasteSpecialHelpResults() requires 4 such buffers to build up the result text + return GlobalAlloc(GHND, (DWORD)4*(512 * sizeof(TCHAR) + nAlloc)); +} diff --git a/private/ole2ui32/precomp.h b/private/ole2ui32/precomp.h new file mode 100644 index 000000000..40edf741d --- /dev/null +++ b/private/ole2ui32/precomp.h @@ -0,0 +1,29 @@ +/* + * PRECOMP.H + * + * This file is used to precompile the OLEDLG.H header file + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +// only STRICT compiles are supported +#ifndef STRICT +#define STRICT +#endif + +#include "oledlg.h" +#include "olestd.h" +#include "resource.h" +#include "commctrl.h" +#ifndef WM_NOTIFY + +// WM_NOTIFY is new in later versions of Win32 +#define WM_NOTIFY 0x004e +typedef struct tagNMHDR +{ + HWND hwndFrom; + UINT idFrom; + UINT code; +} NMHDR; +#endif //!WM_NOTIFY + diff --git a/private/ole2ui32/res/egares.bmp b/private/ole2ui32/res/egares.bmp Binary files differnew file mode 100644 index 000000000..fc28bf55c --- /dev/null +++ b/private/ole2ui32/res/egares.bmp diff --git a/private/ole2ui32/res/hivgares.bmp b/private/ole2ui32/res/hivgares.bmp Binary files differnew file mode 100644 index 000000000..49aee5a26 --- /dev/null +++ b/private/ole2ui32/res/hivgares.bmp diff --git a/private/ole2ui32/res/ole2ui.rc2 b/private/ole2ui32/res/ole2ui.rc2 new file mode 100644 index 000000000..ceb4878a9 --- /dev/null +++ b/private/ole2ui32/res/ole2ui.rc2 @@ -0,0 +1,145 @@ +// +// OLE2UI.RC2 - resources App Studio does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by App Studio +#endif //APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +IDD_INSERTOBJECT RT_HELPINFO +BEGIN + IDC_IO_CREATENEW, 0, IDC_IO_CREATENEW, IDD_INSERTOBJECT, + IDC_IO_CREATEFROMFILE, 0, IDC_IO_CREATEFROMFILE, IDD_INSERTOBJECT, + IDC_IO_LINKFILE, 0, IDC_IO_LINKFILE, IDD_INSERTOBJECT, + IDC_IO_FILETEXT, 0, IDC_IO_FILE, IDD_INSERTOBJECT, + IDC_IO_OBJECTTYPELIST, 0, IDC_IO_OBJECTTYPELIST, IDD_INSERTOBJECT, + IDC_IO_OBJECTTYPETEXT, 0, IDC_IO_OBJECTTYPELIST, IDD_INSERTOBJECT, + IDC_IO_DISPLAYASICON, 0, IDC_IO_DISPLAYASICON, IDD_INSERTOBJECT, + IDC_IO_CHANGEICON, 0, IDC_IO_CHANGEICON, IDD_INSERTOBJECT, + IDC_IO_FILE, 0, IDC_IO_FILE, IDD_INSERTOBJECT, + IDC_IO_FILEDISPLAY, 0, IDC_IO_FILEDISPLAY, IDD_INSERTOBJECT, + IDC_IO_RESULTIMAGE, 0, IDC_IO_RESULTIMAGE, IDD_INSERTOBJECT, + IDC_IO_RESULTTEXT, 0, IDC_IO_RESULTTEXT, IDD_INSERTOBJECT, + IDC_IO_ICONDISPLAY, 0, IDC_IO_ICONDISPLAY, IDD_INSERTOBJECT, + IDC_IO_FILETYPE, 0, IDC_IO_FILETYPE, IDD_INSERTOBJECT, + IDC_IO_INSERTCONTROL, 0, IDC_IO_INSERTCONTROL, IDD_INSERTOBJECT, + IDC_IO_ADDCONTROL, 0, IDC_IO_ADDCONTROL, IDD_INSERTOBJECT, + IDC_IO_CONTROLTYPELIST, 0, IDC_IO_CONTROLTYPELIST, IDD_INSERTOBJECT, + 0, 0, 0, 0 +END + +IDD_CHANGEICON RT_HELPINFO +BEGIN + IDC_CI_CURRENT, 0, IDC_CI_CURRENT, IDD_CHANGEICON, + IDC_CI_CURRENTICON, 0, IDC_CI_CURRENTICON, IDD_CHANGEICON, + IDC_CI_DEFAULT, 0, IDC_CI_DEFAULT, IDD_CHANGEICON, + IDC_CI_DEFAULTICON, 0, IDC_CI_DEFAULTICON, IDD_CHANGEICON, + IDC_CI_FROMFILE, 0, IDC_CI_FROMFILE, IDD_CHANGEICON, + IDC_CI_FROMFILEEDIT, 0, IDC_CI_FROMFILEEDIT, IDD_CHANGEICON, + IDC_CI_ICONLIST, 0, IDC_CI_ICONLIST, IDD_CHANGEICON, + IDC_CI_LABEL, 0, IDC_CI_LABEL, IDD_CHANGEICON, + IDC_CI_LABELEDIT, 0, IDC_CI_LABELEDIT, IDD_CHANGEICON, + IDC_CI_BROWSE, 0, IDC_CI_BROWSE, IDD_CHANGEICON, + IDC_CI_ICONDISPLAY, 0, IDC_CI_ICONDISPLAY, IDD_CHANGEICON, + 0, 0, 0, 0 +END + +IDD_CONVERT RT_HELPINFO +BEGIN + IDC_CV_OBJECTTYPE, 0, IDC_CV_OBJECTTYPE, IDD_CONVERT, + IDC_CV_DISPLAYASICON, 0, IDC_CV_DISPLAYASICON, IDD_CONVERT, + IDC_CV_CHANGEICON, 0, IDC_CV_CHANGEICON, IDD_CONVERT, + IDC_CV_ACTIVATELIST, 0, IDC_CV_ACTIVATELIST, IDD_CONVERT, + IDC_CV_CONVERTTO, 0, IDC_CV_CONVERTTO, IDD_CONVERT, + IDC_CV_ACTIVATEAS, 0, IDC_CV_ACTIVATEAS, IDD_CONVERT, + IDC_CV_RESULTTEXT, 0, IDC_CV_RESULTTEXT, IDD_CONVERT, + IDC_CV_CONVERTLIST, 0, IDC_CV_CONVERTLIST, IDD_CONVERT, + IDC_CV_ICONDISPLAY, 0, IDC_CV_ICONDISPLAY, IDD_CONVERT, + 0, 0, 0, 0 +END + +IDD_PASTESPECIAL RT_HELPINFO +BEGIN + IDC_PS_PASTE, 0, IDC_PS_PASTE, IDD_PASTESPECIAL, + IDC_PS_PASTELINK, 0, IDC_PS_PASTELINK, IDD_PASTESPECIAL, + IDC_PS_SOURCETEXT, 0, IDC_PS_SOURCETEXT, IDD_PASTESPECIAL, + IDC_PS_DISPLAYLIST, 0, IDC_PS_DISPLAYLIST, IDD_PASTESPECIAL, + IDC_PS_DISPLAYASICON, 0, IDC_PS_DISPLAYASICON, IDD_PASTESPECIAL, + IDC_PS_ICONDISPLAY, 0, IDC_PS_ICONDISPLAY, IDD_PASTESPECIAL, + IDC_PS_CHANGEICON, 0, IDC_PS_CHANGEICON, IDD_PASTESPECIAL, + IDC_PS_RESULTIMAGE, 0, IDC_PS_RESULTIMAGE, IDD_PASTESPECIAL, + IDC_PS_RESULTTEXT, 0, IDC_PS_RESULTTEXT, IDD_PASTESPECIAL, + 0, 0, 0, 0 +END + +IDD_EDITLINKS RT_HELPINFO +BEGIN + IDC_EL_CHANGESOURCE, 0, IDC_EL_CHANGESOURCE, IDD_EDITLINKS, + IDC_EL_AUTOMATIC, 0, IDC_EL_AUTOMATIC, IDD_EDITLINKS, + IDC_EL_CANCELLINK, 0, IDC_EL_CANCELLINK, IDD_EDITLINKS, + IDC_EL_UPDATENOW, 0, IDC_EL_UPDATENOW, IDD_EDITLINKS, + IDC_EL_OPENSOURCE, 0, IDC_EL_OPENSOURCE, IDD_EDITLINKS, + IDC_EL_MANUAL, 0, IDC_EL_MANUAL, IDD_EDITLINKS, + IDC_EL_LINKSOURCE, 0, IDC_EL_LINKSOURCE, IDD_EDITLINKS, + IDC_EL_LINKTYPE, 0, IDC_EL_LINKTYPE, IDD_EDITLINKS, + IDC_EL_LINKSLISTBOX, 0, IDC_EL_LINKSLISTBOX, IDD_EDITLINKS, + IDC_EL_COL1, 0, IDC_EL_LINKSLISTBOX, IDD_EDITLINKS, + IDC_EL_COL2, 0, IDC_EL_LINKSLISTBOX, IDD_EDITLINKS, + IDC_EL_COL3, 0, IDC_EL_LINKSLISTBOX, IDD_EDITLINKS, + 0, 0, 0, 0 +END + +IDD_CHANGESOURCE RT_HELPINFO +BEGIN + //TODO: need to get id of the item + 0, 0, 0, 0 +END + +IDD_BUSY RT_HELPINFO +BEGIN + IDC_BZ_RETRY, 0, IDC_BZ_RETRY, IDD_BUSY, + IDC_BZ_ICON, 0, IDC_BZ_ICON, IDD_BUSY, + IDC_BZ_SWITCHTO, 0, IDC_BZ_SWITCHTO, IDD_BUSY, + 0, 0, 0, 0 +END + +IDD_GNRLPROPS RT_HELPINFO +BEGIN + IDC_GP_OBJECTNAME, 0, IDC_GP_OBJECTNAME, IDD_GNRLPROPS, + IDC_GP_OBJECTTYPE, 0, IDC_GP_OBJECTTYPE, IDD_GNRLPROPS, + IDC_GP_OBJECTSIZE, 0, IDC_GP_OBJECTSIZE, IDD_GNRLPROPS, + IDC_GP_CONVERT, 0, IDC_GP_CONVERT, IDD_GNRLPROPS, + IDC_GP_OBJECTLOCATION, 0, IDC_GP_OBJECTLOCATION, IDD_GNRLPROPS, + 0, 0, 0, 0 +END + +IDD_VIEWPROPS RT_HELPINFO +BEGIN + IDC_VP_PERCENT, 0, IDC_VP_PERCENT, IDD_VIEWPROPS, + IDC_VP_CHANGEICON, 0, IDC_VP_CHANGEICON, IDD_VIEWPROPS, + IDC_VP_EDITABLE, 0, IDC_VP_EDITABLE, IDD_VIEWPROPS, + IDC_VP_ASICON, 0, IDC_VP_ASICON, IDD_VIEWPROPS, + IDC_VP_RELATIVE, 0, IDC_VP_RELATIVE, IDD_VIEWPROPS, + IDC_VP_SPIN, 0, IDC_VP_SPIN, IDD_VIEWPROPS, + IDC_VP_ICONDISPLAY, 0, IDC_VP_ICONDISPLAY, IDD_VIEWPROPS, + 0, 0, 0, 0 +END + +IDD_LINKPROPS RT_HELPINFO +BEGIN + IDC_LP_OPENSOURCE, 0, IDC_LP_OPENSOURCE, IDD_LINKPROPS, + IDC_LP_UPDATENOW, 0, IDC_LP_UPDATENOW, IDD_LINKPROPS, + IDC_LP_BREAKLINK, 0, IDC_LP_BREAKLINK, IDD_LINKPROPS, + IDC_LP_LINKSOURCE, 0, IDC_LP_LINKSOURCE, IDD_LINKPROPS, + IDC_LP_CHANGESOURCE, 0, IDC_LP_CHANGESOURCE, IDD_LINKPROPS, + IDC_LP_AUTOMATIC, 0, IDC_LP_AUTOMATIC, IDD_LINKPROPS, + IDC_LP_MANUAL, 0, IDC_LP_MANUAL, IDD_LINKPROPS, + IDC_LP_DATE, 0, IDC_LP_DATE, IDD_LINKPROPS, + IDC_LP_TIME, 0, IDC_LP_TIME, IDD_LINKPROPS, + 0, 0, 0, 0 +END + +///////////////////////////////////////////////////////////////////////////// diff --git a/private/ole2ui32/res/vgares.bmp b/private/ole2ui32/res/vgares.bmp Binary files differnew file mode 100644 index 000000000..08e0b041b --- /dev/null +++ b/private/ole2ui32/res/vgares.bmp diff --git a/private/ole2ui32/resimage.cpp b/private/ole2ui32/resimage.cpp new file mode 100644 index 000000000..4b98c4c85 --- /dev/null +++ b/private/ole2ui32/resimage.cpp @@ -0,0 +1,355 @@ +/* + * RESIMAGE.CPP + * + * Implementation of the Results Image control for OLE 2.0 UI dialogs. + * We need a separate control for dialogs in order to control the repaints + * properly and to provide a clean message interface for the dialog + * implementations. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "resimage.h" +#include "uiclass.h" +OLEDBGDATA + +//Reference counter indicating how many times fResultImageInitialize has been +//successfully called +static UINT uRegistered = 0; + +//Bitmap and image dimensions for result images. +static HBITMAP hBmpResults = NULL; +static UINT cxBmpResult; +static UINT cyBmpResult; + +/* + * FResultImageInitialize + * + * Purpose: + * Attempts to load result bitmaps for the current display driver + * for use in OLE 2.0 UI dialogs. Also registers the ResultImage + * control class. + * + * Parameters: + * hInst HINSTANCE instance of the DLL. + * + * hPrevInst HINSTANCE of the previous instance. Used to + * determine whether to register window classes or not. + * + * Return Value: + * BOOL TRUE if all initialization succeeded, FALSE otherwise. + */ + +#pragma code_seg(".text$initseg") + +BOOL FResultImageInitialize(HINSTANCE hInst, HINSTANCE hPrevInst) +{ + int cx, iBmp; + HDC hDC; + BITMAP bm; + + WNDCLASS wc; + + /* + * Determine the aspect ratio of the display we're currently + * running on and load the appropriate bitmap into the global + * hBmpResults (used from the ResultImage control only). + * + * By retrieving the logical Y extent of the display driver, you + * only have limited possibilities: + * LOGPIXELSY Display + * ---------------------------------------- + * 48 CGA (unsupported) + * 72 EGA + * 96 VGA + * 120 8514/a (i.e. HiRes VGA) + */ + + hDC=GetDC(NULL); + + if (NULL==hDC) + return FALSE; + + cx=GetDeviceCaps(hDC, LOGPIXELSY); + ReleaseDC(NULL, hDC); + + /* + * Instead of single comparisons, check ranges instead, so in case + * we get something funky, we'll act reasonable. + */ + if (72 >=cx) iBmp=IDB_RESULTSEGA; + if (72 < cx && 120 > cx) iBmp=IDB_RESULTSVGA; + if (120 <=cx) iBmp=IDB_RESULTSHIRESVGA; + + if (NULL == hBmpResults) + { + hBmpResults=LoadBitmap(hInst, MAKEINTRESOURCE(iBmp)); + + if (NULL==hBmpResults) + { + //On error, fail loading the DLL + OleDbgOut1(TEXT("FResultImageInitialize: Failed LoadBitmap.\r\n")); + return FALSE; + } + OleDbgOut4(TEXT("FResultImageInitialize: Loaded hBmpResults\r\n")); + + // Now that we have the bitmap, calculate image dimensions + GetObject(hBmpResults, sizeof(BITMAP), &bm); + cxBmpResult = bm.bmWidth/CIMAGESX; + cyBmpResult = bm.bmHeight; + } + + + // Only register class if we're the first instance + if (hPrevInst) + uRegistered++; + else + { + // Static flag fRegistered guards against calling this function more + // than once in the same instance + + if (0 == uRegistered) + { + wc.lpfnWndProc =ResultImageWndProc; + wc.cbClsExtra =0; + wc.cbWndExtra =CBRESULTIMAGEWNDEXTRA; + wc.hInstance =hInst; + wc.hIcon =NULL; + wc.hCursor =LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground =NULL; + wc.lpszMenuName =NULL; + wc.style =CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW; + + wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE1); + uRegistered = RegisterClass(&wc) ? 1 : 0; + + wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE2); + uRegistered = RegisterClass(&wc) ? 1 : 0; + + wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE3); + uRegistered = RegisterClass(&wc) ? 1 : 0; + } + else + uRegistered++; + } + + return (uRegistered > 0); +} + +#pragma code_seg() + + +/* + * ResultImageUninitialize + * + * Purpose: + * Cleans up anything done in FResultImageInitialize, such as freeing + * the bitmaps. Call from WEP. + * + * Parameters: + * None + * + * Return Value: + * None + */ + +void ResultImageUninitialize(void) +{ + --uRegistered; + if (0 == uRegistered) + { + if (NULL != hBmpResults) + { + DeleteObject(hBmpResults); + hBmpResults = NULL; + } + } +} + + +/* + * ResultImageWndProc + * + * Purpose: + * Window Procedure for the ResultImage custom control. Only handles + * WM_CREATE, WM_PAINT, and private messages to manipulate the bitmap. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ + +LONG CALLBACK ResultImageWndProc(HWND hWnd, UINT iMsg, + WPARAM wParam, LPARAM lParam) +{ + UINT iBmp; + PAINTSTRUCT ps; + HDC hDC; + + //Handle standard Windows messages. + switch (iMsg) + { + case WM_CREATE: + SetWindowWord(hWnd, RIWW_IMAGEINDEX, RESULTIMAGE_NONE); + return 0L; + + case WM_PAINT: + iBmp = GetWindowWord(hWnd, RIWW_IMAGEINDEX); + hDC = BeginPaint(hWnd, &ps); + + RECT rc; + UINT x, y; + HDC hDCDlg; + HBRUSH hBr; + LOGBRUSH lb; + HWND hDlg; + + /* + * Our job before using TransparentBlt is to figure out + * where to position the result image. We place it centered + * on this control, so get our rect's center and subtract + * half of the image dimensions. + */ + GetClientRect(hWnd, &rc); + x = (rc.right+rc.left-cxBmpResult)/2; + y = (rc.bottom+rc.top-cyBmpResult)/2; + + // Get the backgroup color the dialog is using. + hDlg=GetParent(hWnd); + hDCDlg=GetDC(hDlg); + hBr = (HBRUSH)SendMessage(hDlg, + WM_CTLCOLORDLG, + (WPARAM)hDCDlg, + (LPARAM)hDlg); + ReleaseDC(hDlg, hDCDlg); + GetObject(hBr, sizeof(LOGBRUSH), &lb); + SetBkColor(hDC, lb.lbColor); + + + if (RESULTIMAGE_NONE != iBmp) + { + + TransparentBlt(hDC, x, y, hBmpResults, iBmp*cxBmpResult, 0, + cxBmpResult, cyBmpResult, RGBTRANSPARENT); + } + else + { + FillRect(hDC, &rc, hBr); + } + EndPaint(hWnd, &ps); + break; + + case RIM_IMAGESET: + // wParam contains the new index. + iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX); + + // Validate the index before changing it and repainting + if (RESULTIMAGE_NONE==wParam || + ((RESULTIMAGE_MIN <= wParam) && (RESULTIMAGE_MAX >= wParam))) + { + SetWindowWord(hWnd, RIWW_IMAGEINDEX, (WORD)wParam); + InvalidateRect(hWnd, NULL, FALSE); + UpdateWindow(hWnd); + } + // Return the previous index. + return iBmp; + + case RIM_IMAGEGET: + // Return the current index. + iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX); + return (LONG)iBmp; + + default: + return DefWindowProc(hWnd, iMsg, wParam, lParam); + } + + return 0L; +} + + +/* + * TransparentBlt + * + * Purpose: + * Given a DC, a bitmap, and a color to assume as transparent in that + * bitmap, BitBlts the bitmap to the DC letting the existing background + * show in place of the transparent color. + * + * Parameters: + * hDC HDC on which to draw. + * x, y UINT location at which to draw the bitmap + * hBmp HBITMIP to draw from + * xOrg, yOrg UINT coordinates from which to draw the bitamp + * cx, cy UINT dimensions of the bitmap to Blt. + * cr COLORREF to consider as transparent. + * + * Return Value: + * None + */ + +void TransparentBlt(HDC hDC, UINT x, UINT y, HBITMAP hBmp, UINT xOrg, UINT yOrg, + UINT cx, UINT cy, COLORREF cr) +{ + HDC hDCSrc, hDCMid, hMemDC; + HBITMAP hBmpMono, hBmpT; + HBRUSH hBr, hBrT; + COLORREF crBack, crText; + + if (NULL == hBmp) + return; + + // Get three intermediate DC's + hDCSrc = CreateCompatibleDC(hDC); + hDCMid = CreateCompatibleDC(hDC); + hMemDC = CreateCompatibleDC(hDC); + + SelectObject(hDCSrc, hBmp); + + // Create a monochrome bitmap for masking + hBmpMono=CreateCompatibleBitmap(hDCMid, cx, cy); + SelectObject(hDCMid, hBmpMono); + + // Create a middle bitmap + hBmpT=CreateCompatibleBitmap(hDC, cx, cy); + SelectObject(hMemDC, hBmpT); + + // Create a monochrome mask where we have 0's in the image, 1's elsewhere. + crBack=SetBkColor(hDCSrc, cr); + BitBlt(hDCMid, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY); + SetBkColor(hDCSrc, crBack); + + // Put the unmodified image in the temporary bitmap + BitBlt(hMemDC, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY); + + // Create an select a brush of the background color + hBr = CreateSolidBrush(GetBkColor(hDC)); + hBrT = (HBRUSH)SelectObject(hMemDC, hBr); + + // Force conversion of the monochrome to stay black and white. + crText=SetTextColor(hMemDC, 0L); + crBack=SetBkColor(hMemDC, RGB(255, 255, 255)); + + /* + * Where the monochrome mask is 1, Blt the brush; where the mono mask + * is 0, leave the destination untouches. This results in painting + * around the image with the background brush. We do this first + * in the temporary bitmap, then put the whole thing to the screen. + */ + BitBlt(hMemDC, 0, 0, cx, cy, hDCMid, 0, 0, ROP_DSPDxax); + BitBlt(hDC, x, y, cx, cy, hMemDC, 0, 0, SRCCOPY); + + SetTextColor(hMemDC, crText); + SetBkColor(hMemDC, crBack); + + SelectObject(hMemDC, hBrT); + DeleteObject(hBr); + + DeleteDC(hMemDC); + DeleteDC(hDCSrc); + DeleteDC(hDCMid); + DeleteObject(hBmpT); + DeleteObject(hBmpMono); +} diff --git a/private/ole2ui32/resimage.h b/private/ole2ui32/resimage.h new file mode 100644 index 000000000..57c4881b4 --- /dev/null +++ b/private/ole2ui32/resimage.h @@ -0,0 +1,56 @@ +/* + * RESIMAGE.H + * + * Structures and definitions for the ResultImage control. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef _RESIMAGE_H_ +#define _RESIMAGE_H_ + +/* + * Indices into the bitmaps to extract the right image. Each bitmap + * contains five images arranged vertically, so the offset to the correct + * image is (iImage*cy) + */ + +#define RESULTIMAGE_NONE 0xFFFF +#define RESULTIMAGE_PASTE 0 +#define RESULTIMAGE_EMBED 1 +#define RESULTIMAGE_EMBEDICON 2 +#define RESULTIMAGE_LINK 3 +#define RESULTIMAGE_LINKICON 4 +#define RESULTIMAGE_LINKTOLINK 5 +#define RESULTIMAGE_LINKTOLINKICON 6 +#define RESULTIMAGE_EDITABLE 7 + +#define RESULTIMAGE_MIN 0 +#define RESULTIMAGE_MAX 7 + +// Total number of images in each bitmap. +#define CIMAGESX (RESULTIMAGE_MAX+1) + +// The color to use for transparancy (cyan) +#define RGBTRANSPARENT RGB(0, 255, 255) + +// Function prototypes +LONG CALLBACK ResultImageWndProc(HWND, UINT, WPARAM, LPARAM); + +BOOL FResultImageInitialize(HINSTANCE, HINSTANCE); +void ResultImageUninitialize(void); +void TransparentBlt(HDC, UINT, UINT, HBITMAP, UINT, UINT, UINT, UINT, COLORREF); + +// Window extra bytes contain the bitmap index we deal with currently. +#define CBRESULTIMAGEWNDEXTRA sizeof(UINT) +#define RIWW_IMAGEINDEX 0 + +// Control messages +#define RIM_IMAGESET (WM_USER+0) +#define RIM_IMAGEGET (WM_USER+1) + +// Special ROP code for TransparentBlt. +#define ROP_DSPDxax 0x00E20746 + +#endif //_RESIMAGE_H_ diff --git a/private/ole2ui32/resource.h b/private/ole2ui32/resource.h new file mode 100644 index 000000000..600e51a73 --- /dev/null +++ b/private/ole2ui32/resource.h @@ -0,0 +1,102 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by oledlg.rc +// +#define IDB_RESULTSEGA 10 +#define IDB_RESULTSVGA 11 +#define IDB_RESULTSHIRESVGA 12 +#define IDS_FILTERS 64 +#define IDS_ICONFILTERS 65 +#define IDS_BROWSE 66 +#define IDS_OCX_FILTERS 67 +#define IDS_INSERT 68 +#define IDS_CHNGSRCOKBUTTON 69 +#define IDS_IORESULTNEW 256 +#define IDS_IORESULTNEWICON 257 +#define IDS_IORESULTFROMFILE1 258 +#define IDS_IORESULTFROMFILE2 259 +#define IDS_IORESULTFROMFILEICON2 260 +#define IDS_IORESULTLINKFILE1 261 +#define IDS_IORESULTLINKFILE2 262 +#define IDS_IORESULTLINKFILEICON1 263 +#define IDS_IORESULTLINKFILEICON2 264 +#define IDS_CINOICONSINFILE 288 +#define IDS_CIINVALIDFILE 289 +#define IDS_CIFILEACCESS 290 +#define IDS_CIFILESHARE 291 +#define IDS_CIFILEOPENFAIL 292 +#define IDS_OLE2UIUNKNOWN 300 +#define IDS_OLE2UILINK 301 +#define IDS_OLE2UIOBJECT 302 +#define IDS_OLE2UIEDIT 303 +#define IDS_OLE2UICONVERT 304 +#define IDS_OLE2UIEDITLINKCMD_1VERB 305 +#define IDS_OLE2UIEDITOBJECTCMD_1VERB 306 +#define IDS_OLE2UIEDITLINKCMD_NVERB 307 +#define IDS_OLE2UIEDITOBJECTCMD_NVERB 308 +#define IDS_OLE2UIEDITNOOBJCMD 309 +#define IDS_DEFICONLABEL 310 +#define IDS_OLE2UIPASTELINKEDTYPE 311 +#define IDS_PSPASTEDATA 400 +#define IDS_PSPASTEOBJECT 401 +#define IDS_PSPASTEOBJECTASICON 402 +#define IDS_PSPASTELINKDATA 403 +#define IDS_PSPASTELINKOBJECT 404 +#define IDS_PSPASTELINKOBJECTASICON 405 +#define IDS_PSNONOLE 406 +#define IDS_PSUNKNOWNTYPE 407 +#define IDS_PSUNKNOWNSRC 408 +#define IDS_PSUNKNOWNAPP 409 +#define IDS_CVRESULTCONVERTLINK 500 +#define IDS_CVRESULTCONVERTTO 501 +#define IDS_CVRESULTNOCHANGE 502 +#define IDS_CVRESULTDISPLAYASICON 503 +#define IDS_CVRESULTACTIVATEAS 504 +#define IDS_CVRESULTACTIVATEDIFF 505 +#define IDS_BZRESULTTEXTBUSY 601 +#define IDS_BZRESULTTEXTNOTRESPONDING 602 +#define IDS_OLESTDNOCREATEFILE 700 +#define IDS_OLESTDNOOPENFILE 701 +#define IDS_OLESTDDISKFULL 702 +#define IDS_LINK_AUTO 800 +#define IDS_LINK_MANUAL 801 +#define IDS_LINK_UNKNOWN 802 +#define IDS_LINKS 803 +#define IDS_FAILED 804 +#define IDS_CHANGESOURCE 805 +#define IDS_INVALIDSOURCE 806 +#define IDS_ERR_GETLINKSOURCE 807 +#define IDS_ERR_GETLINKUPDATEOPTIONS 808 +#define IDS_ERR_ADDSTRING 809 +#define IDS_CHANGEADDITIONALLINKS 810 +#define IDS_CLOSE 811 +#define IDS_OBJECTPROPERTIES 812 +#define IDS_LINKOBJECTPROPERTIES 813 +#define IDS_LINKPROPS 814 +#define IDS_CONFIRMBREAKLINK 815 +#define IDS_BYTES 816 +#define IDS_ORDERKB 817 +#define IDS_ORDERMB 818 +#define IDS_ORDERGB 819 +#define IDS_ORDERTB 820 +#define IDS_OBJECTSIZE 821 +#define IDS_CANNOTLOADOCX 822 +#define IDS_NODLLREGISTERSERVER 823 +#define IDS_DLLREGISTERFAILED 824 +#define IDS_ADDCONTROL 825 +#define IDS_RANGEERROR 826 +#define IDS_INVALIDPERCENTAGE 827 +#define IDS_VIEWPROPS 828 +#define RT_HELPINFO 4096 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 110 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1047 +#define _APS_NEXT_SYMED_VALUE 102 +#endif +#endif diff --git a/private/ole2ui32/targtdev.cpp b/private/ole2ui32/targtdev.cpp new file mode 100644 index 000000000..0dbbab08f --- /dev/null +++ b/private/ole2ui32/targtdev.cpp @@ -0,0 +1,32 @@ +/************************************************************************* +** +** OLE 2 Standard Utilities +** +** olestd.c +** +** This file contains utilities that are useful for dealing with +** target devices. +** +** (c) Copyright Microsoft Corp. 1992 All Rights Reserved +** +*************************************************************************/ + +#include "precomp.h" + +STDAPI_(BOOL) OleStdCompareTargetDevice( + DVTARGETDEVICE* ptdLeft, DVTARGETDEVICE* ptdRight) +{ + if (ptdLeft == ptdRight) + // same address of td; must be same (handles NULL case) + return TRUE; + else if ((ptdRight == NULL) || (ptdLeft == NULL)) + return FALSE; + else if (ptdLeft->tdSize != ptdRight->tdSize) + // different sizes, not equal + return FALSE; + else if (memcmp(ptdLeft, ptdRight, ptdLeft->tdSize) != 0) + // not same target device, not equal + return FALSE; + + return TRUE; +} diff --git a/private/ole2ui32/template.cpp b/private/ole2ui32/template.cpp new file mode 100644 index 000000000..81244dc95 --- /dev/null +++ b/private/ole2ui32/template.cpp @@ -0,0 +1,229 @@ +/* + * TEMPLATE.CPP + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + * + * + * CUSTOMIZATION INSTRUCTIONS: + * + * 1. Replace <FILE> with the uppercased filename for this file. + * Lowercase the <FILE>.h entry + * + * 2. Replace <NAME> with the mixed case dialog name in one word, + * such as InsertObject + * + * 3. Replace <FULLNAME> with the mixed case dialog name in multiple + * words, such as Insert Object + * + * 4. Replace <ABBREV> with the suffix for pointer variables, such + * as the IO in InsertObject's pIO or the CI in ChangeIcon's pCI. + * Check the alignment of the first variable declaration in the + * Dialog Proc after this. I will probably be misaligned with the + * rest of the variables. + * + * 5. Replace <STRUCT> with the uppercase structure name for this + * dialog sans OLEUI, such as INSERTOBJECT. Changes OLEUI<STRUCT> + * in most cases, but we also use this for IDD_<STRUCT> as the + * standard template resource ID. + * + * 6. Find <UFILL> fields and fill them out with whatever is appropriate. + * + * 7. Delete this header up to the start of the next comment. + */ + + +/* + * <FILE>.CPP + * + * Implements the OleUI<NAME> function which invokes the complete + * <FULLNAME> dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "common.h" + +#include "template.h" + +/* + * OleUI<NAME> + * + * Purpose: + * Invokes the standard OLE <FULLNAME> dialog box allowing the user + * to <UFILL> + * + * Parameters: + * lp<ABBREV> LPOLEUI<NAME> pointing to the in-out structure + * for this dialog. + * + * Return Value: + * UINT One of the following codes, indicating success or error: + * OLEUI_SUCCESS Success + * OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong + */ + +STDAPI_(UINT) OleUI<NAME>(LPOLEUI<STRUCT> lp<ABBREV>) +{ + UINT uRet; + HGLOBAL hMemDlg=NULL; + + uRet = UStandardValidation((LPOLEUISTANDARD)lp<ABBREV>, + sizeof(OLEUI<STRUCT>), &hMemDlg); + + if (OLEUI_SUCCESS!=uRet) + return uRet; + + /* + * PERFORM ANY STRUCTURE-SPECIFIC VALIDATION HERE! + * ON FAILURE: + * { + * return OLEUI_<ABBREV>ERR_<ERROR> + * } + */ + + //Now that we've validated everything, we can invoke the dialog. + uRet = UStandardInvocation(<NAME>DialogProc, (LPOLEUISTANDARD)lp<ABBREV> + , hMemDlg, MAKEINTRESOURCE(IDD_<STRUCT>)); + + /* + * IF YOU ARE CREATING ANYTHING BASED ON THE RESULTS, DO IT HERE. + */ + <UFILL> + + return uRet; +} + +/* + * <NAME>DialogProc + * + * Purpose: + * Implements the OLE <FULLNAME> dialog as invoked through the + * OleUI<NAME> function. + * + * Parameters: + * Standard + * + * Return Value: + * Standard + */ + +BOOL CALLBACK <NAME>DialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + P<STRUCT> p<ABBREV>; + BOOL fHook=FALSE; + + //Declare Win16/Win32 compatible WM_COMMAND parameters. + COMMANDPARAMS(wID, wCode, hWndMsg); + + //This will fail under WM_INITDIALOG, where we allocate it. + p<ABBREV>=(<STRUCT>)PvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook); + + //If the hook processed the message, we're done. + if (0!=uHook) + return (BOOL)uHook; + + //Process the temination message + if (iMsg==uMsgEndDialog) + { + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) + { + case WM_DESTROY: + if (p<ABBREV>) + { + //Free any specific allocations before calling StandardCleanup + StandardCleanup((PVOID)p<ABBREV>, hDlg); + } + break; + case WM_INITDIALOG: + F<NAME>Init(hDlg, wParam, lParam); + return TRUE; + + case WM_COMMAND: + switch (wID) + { + case IDOK: + /* + * PERFORM WHATEVER FUNCTIONS ARE DEFAULT HERE. + */ + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + break; + + case IDCANCEL: + /* + * PERFORM ANY UNDOs HERE, BUT NOT CLEANUP THAT WILL + * ALWAYS HAPPEN WHICH SHOULD BE IN uMsgEndDialog. + */ + SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L); + break; + + case ID_OLEUIHELP: + PostMessage(p<ABBREV>->lpO<ABBREV>->hWndOwner, uMsgHelp + , (WPARAM)hDlg, MAKELPARAM(IDD_<STRUCT>, 0)); + break; + } + break; + } + return FALSE; +} + + +/* + * F<NAME>Init + * + * Purpose: + * WM_INITIDIALOG handler for the <FULLNAME> dialog box. + * + * Parameters: + * hDlg HWND of the dialog + * wParam WPARAM of the message + * lParam LPARAM of the message + * + * Return Value: + * BOOL Value to return for WM_INITDIALOG. + */ + +BOOL F<NAME>Init(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + P<STRUCT> p<ABBREV>; + LPOLEUI<STRUCT> lpO<ABBREV>; + HFONT hFont; + + //1. Copy the structure at lParam into our instance memory. + p<ABBREV>=(PSTRUCT)PvStandardInit(hDlg, sizeof(<STRUCT>), TRUE, &hFont); + + //PvStandardInit send a termination to us already. + if (NULL==p<ABBREV>) + return FALSE; + + lpO<ABBREV>=(LPOLEUI<STRUCT>)lParam); + + p<ABBREV>->lpO<ABBREV>=lpO<ABBREV>; + + //Copy other information from lpO<ABBREV> that we might modify. + <UFILL> + + //2. If we got a font, send it to the necessary controls. + if (NULL!=hFont) + { + //Do this for as many controls as you need it for. + SendDlgItemMessage(hDlg, ID_<UFILL>, WM_SETFONT, (WPARAM)hFont, 0L); + } + + //3. Show or hide the help button + if (!(p<ABBREV>->lpO<ABBREV>->dwFlags & <ABBREV>F_SHOWHELP)) + StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE); + + /* + * PERFORM OTHER INITIALIZATION HERE. ON ANY LoadString + * FAILURE POST OLEUI_MSG_ENDDIALOG WITH OLEUI_ERR_LOADSTRING. + */ + + //n. Call the hook with lCustData in lParam + UStandardHook((PVOID)p<ABBREV>, hDlg, WM_INITDIALOG, wParam, lpO<ABBREV>->lCustData); + return TRUE; +} diff --git a/private/ole2ui32/template.h b/private/ole2ui32/template.h new file mode 100644 index 000000000..ab2cac951 --- /dev/null +++ b/private/ole2ui32/template.h @@ -0,0 +1,119 @@ +/* + * TEMPLATE.H + * + * CUSTOMIZATION INSTRUCTIONS: + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + * + * + * 1. Replace <FILE> with the uppercased filename for this file. + * Lowercase the <FILE>.h entry + * + * 2. Replace <NAME> with the mixed case dialog name in one word, + * such as InsertObject + * + * 3. Replace <FULLNAME> with the mixed case dialog name in multiple + * words, such as Insert Object + * + * 4. Replace <ABBREV> with the suffix for pointer variables, such + * as the IO in InsertObject's pIO or the CI in ChangeIcon's pCI. + * Check the alignment of the first variable declaration in the + * Dialog Proc after this. I will probably be misaligned with the + * rest of the variables. + * + * 5. Replace <STRUCT> with the uppercase structure name for this + * dialog sans OLEUI, such as INSERTOBJECT. Changes OLEUI<STRUCT> + * in most cases, but we also use this for IDD_<STRUCT> as the + * standard template resource ID. + * + * 6. Find <UFILL> fields and fill them out with whatever is appropriate. + * + * 7. Delete this header up to the start of the next comment. + * + */ + + +/* + * <FILE>.H + * + * Internal definitions, structures, and function prototypes for the + * OLE 2.0 UI <FULLNAME> dialog. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef <UFILL> +#define <UFILL> + +// UFILL> Move from here to INTERNAL to to OLE2UI.H + + +typedef struct tagOLEUI<STRUCT> +{ + // These IN fields are standard across all OLEUI dialog functions. + DWORD cbStruct; //Structure Size + DWORD dwFlags; //IN-OUT: Flags + HWND hWndOwner; //Owning window + LPCTSTR lpszCaption; //Dialog caption bar contents + LPFNOLEUIHOOK lpfnHook; //Hook callback + LPARAM lCustData; //Custom data to pass to hook + HINSTANCE hInstance; //Instance for customized template name + LPCTSTR lpszTemplate; //Customized template name + HRSRC hResource; //Customized template handle + + // Specifics for OLEUI<STRUCT>. All are IN-OUT unless otherwise spec. +} OLEUI<STRUCT>, *POLEUI<STRUCT>, FAR *LPOLEUI<STRUCT>; + + +// API Prototype +UINT FAR PASCAL OleUI<NAME>(LPOLEUI<STRUCT>); + + +// <FULLNAME> flags +#define <ABBREV>F_SHOWHELP 0x00000001L +<UFILL> + + +// <FULLNAME> specific error codes +// DEFINE AS OLEUI_<ABBREV>ERR_<ERROR> (OLEUI_ERR_STANDARDMAX+n) +<UFILL> + + +// <FULLNAME> Dialog identifiers +// FILL IN DIALOG IDs HERE +<UFILL> + + + + + +// INTERNAL INFORMATION STARTS HERE + +// Internally used structure +typedef struct tag<STRUCT> +{ + //Keep this item first as the Standard* functions depend on it here. + LPOLEUI<STRUCT> lpO<ABBREV>; //Original structure passed. + UINT nIDD; // IDD of dialog (used for help info) + + /* + * What we store extra in this structure besides the original caller's + * pointer are those fields that we need to modify during the life of + * the dialog but that we don't want to change in the original structure + * until the user presses OK. + */ + + <UFILL> +} <STRUCT>, *P<STRUCT>; + + +// Internal function prototypes +// <FILE>.CPP + +BOOL FAR PASCAL <NAME>DialogProc(HWND, UINT, WPARAM, LPARAM); +BOOL F<NAME>Init(HWND hDlg, WPARAM, LPARAM); +<UFILL> + + +#endif //<UFILL> diff --git a/private/ole2ui32/test/ansi/makefile b/private/ole2ui32/test/ansi/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ole2ui32/test/ansi/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ole2ui32/test/ansi/sources b/private/ole2ui32/test/ansi/sources new file mode 100644 index 000000000..ece5f65d4 --- /dev/null +++ b/private/ole2ui32/test/ansi/sources @@ -0,0 +1,53 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + + +!ENDIF + +BLDCRT=1 + +MAJORCOMP=toledlg +MINORCOMP= + +TARGETPATH=obj +C_DEFINES=-DWIN32 -DINC_OLE2 + +TARGETNAME=toledlg +TARGETTYPE=PROGRAM + +INCLUDES=$(BASEDIR)\private\cinc;..; +GPSIZE=32 + +386_OPTIMIZATION=/Oy- + +SOURCES=..\winmain.cxx \ + ..\about.cxx \ + ..\mwclass.cxx \ + ..\message.cxx \ + ..\linkcntr.cxx \ + ..\tole2ui.rc \ + ..\cdialog.cxx \ + ..\cwindow.cxx \ + + +LINKLIBS=$(BASEDIR)\public\sdk\lib\*\ole32.lib\ + $(BASEDIR)\public\sdk\lib\*\oledlg.lib + +UMTYPE=windows +UMENTRY=winmain diff --git a/private/ole2ui32/test/unicode/makefile b/private/ole2ui32/test/unicode/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ole2ui32/test/unicode/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ole2ui32/test/unicode/sources b/private/ole2ui32/test/unicode/sources new file mode 100644 index 000000000..668b5a089 --- /dev/null +++ b/private/ole2ui32/test/unicode/sources @@ -0,0 +1,53 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + + +!ENDIF + +BLDCRT=1 + +MAJORCOMP=toledlg +MINORCOMP= + +TARGETPATH=obj +C_DEFINES=-DWIN32 -DINC_OLE2 -DUNICODE + +TARGETNAME=toledlg +TARGETTYPE=PROGRAM + +INCLUDES=$(BASEDIR)\private\cinc;..; +GPSIZE=32 + +386_OPTIMIZATION=/Oy- + +SOURCES=..\winmain.cxx \ + ..\about.cxx \ + ..\mwclass.cxx \ + ..\message.cxx \ + ..\linkcntr.cxx \ + ..\tole2ui.rc \ + ..\cdialog.cxx \ + ..\cwindow.cxx \ + + +LINKLIBS=$(BASEDIR)\public\sdk\lib\*\ole32.lib\ + $(BASEDIR)\public\sdk\lib\*\oledlg.lib + +UMTYPE=windows +UMENTRY=winmain diff --git a/private/ole2ui32/uiclass.h b/private/ole2ui32/uiclass.h new file mode 100644 index 000000000..598c874c9 --- /dev/null +++ b/private/ole2ui32/uiclass.h @@ -0,0 +1,7 @@ +#define SZCLASSICONBOX1 "OLE2UIiconbox" +#define SZCLASSICONBOX2 "MFCUIA32iconbox" +#define SZCLASSICONBOX3 "MFCUIW32iconbox" +#define SZCLASSRESULTIMAGE1 "OLE2UIresimage" +#define SZCLASSRESULTIMAGE2 "MFCUIA32resimage" +#define SZCLASSRESULTIMAGE3 "MFCUIW32resimage" + diff --git a/private/ole2ui32/utility.cpp b/private/ole2ui32/utility.cpp new file mode 100644 index 000000000..3a663585d --- /dev/null +++ b/private/ole2ui32/utility.cpp @@ -0,0 +1,830 @@ +/* + * UTILITY.CPP + * + * Utility routines for functions inside OLEDLG.DLL + * + * General: + * ---------------------- + * HourGlassOn Displays the hourglass + * HourGlassOff Hides the hourglass + * + * Misc Tools: + * ---------------------- + * Browse Displays the "File..." or "Browse..." dialog. + * ReplaceCharWithNull Used to form filter strings for Browse. + * ErrorWithFile Creates an error message with embedded filename + * OpenFileError Give error message for OpenFile error return + * ChopText Chop a file path to fit within a specified width + * DoesFileExist Checks if file is valid + * + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#include "precomp.h" +#include "common.h" +#include <stdlib.h> +#include <commdlg.h> +#include <memory.h> +#include <cderr.h> +#include "utility.h" + +OLEDBGDATA + +/* + * HourGlassOn + * + * Purpose: + * Shows the hourglass cursor returning the last cursor in use. + * + * Parameters: + * None + * + * Return Value: + * HCURSOR Cursor in use prior to showing the hourglass. + */ + +HCURSOR WINAPI HourGlassOn(void) +{ + HCURSOR hCur; + + hCur=SetCursor(LoadCursor(NULL, IDC_WAIT)); + ShowCursor(TRUE); + + return hCur; +} + + +/* + * HourGlassOff + * + * Purpose: + * Turns off the hourglass restoring it to a previous cursor. + * + * Parameters: + * hCur HCURSOR as returned from HourGlassOn + * + * Return Value: + * None + */ + +void WINAPI HourGlassOff(HCURSOR hCur) +{ + ShowCursor(FALSE); + SetCursor(hCur); + return; +} + + +/* + * Browse + * + * Purpose: + * Displays the standard GetOpenFileName dialog with the title of + * "Browse." The types listed in this dialog are controlled through + * iFilterString. If it's zero, then the types are filled with "*.*" + * Otherwise that string is loaded from resources and used. + * + * Parameters: + * hWndOwner HWND owning the dialog + * lpszFile LPSTR specifying the initial file and the buffer in + * which to return the selected file. If there is no + * initial file the first character of this string should + * be NULL. + * lpszInitialDir LPSTR specifying the initial directory. If none is to + * set (ie, the cwd should be used), then this parameter + * should be NULL. + * cchFile UINT length of pszFile + * iFilterString UINT index into the stringtable for the filter string. + * dwOfnFlags DWORD flags to OR with OFN_HIDEREADONLY + * nBrowseID + * lpfnHook Callback Hook Proceedure. Set if OFN_ENABLE_HOOK is + * in dwOfnFlags else it should be NULL. + * + * Return Value: + * BOOL TRUE if the user selected a file and pressed OK. + * FALSE otherwise, such as on pressing Cancel. + */ + +BOOL WINAPI Browse(HWND hWndOwner, LPTSTR lpszFile, LPTSTR lpszInitialDir, UINT cchFile, + UINT iFilterString, DWORD dwOfnFlags, UINT nBrowseID, LPOFNHOOKPROC lpfnHook) +{ + UINT cch; + TCHAR szFilters[256]; + TCHAR szDlgTitle[128]; // that should be big enough + + if (NULL == lpszFile || 0 == cchFile) + return FALSE; + + /* + * Exact contents of the filter combobox is TBD. One idea + * is to take all the extensions in the RegDB and place them in here + * with the descriptive class name associate with them. This has the + * extra step of finding all extensions of the same class handler and + * building one extension string for all of them. Can get messy quick. + * UI demo has only *.* which we do for now. + */ + + if (0 != iFilterString) + { + cch = LoadString(_g_hOleStdResInst, iFilterString, szFilters, + sizeof(szFilters)/sizeof(TCHAR)); + } + else + { + szFilters[0] = 0; + cch = 1; + } + + if (0 == cch) + return FALSE; + + ReplaceCharWithNull(szFilters, szFilters[cch-1]); + + // Prior string must also be initialized, if there is one. + OPENFILENAME ofn; + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hWndOwner; + ofn.lpstrFile = lpszFile; + ofn.nMaxFile = cchFile; + ofn.lpstrFilter = szFilters; + ofn.nFilterIndex = 1; + ofn.lpfnHook = lpfnHook; + if (LoadString(_g_hOleStdResInst, IDS_BROWSE, szDlgTitle, sizeof(szDlgTitle)/sizeof(TCHAR))) + ofn.lpstrTitle = szDlgTitle; + ofn.hInstance = _g_hOleStdResInst; + if (NULL != lpszInitialDir) + ofn.lpstrInitialDir = lpszInitialDir; + ofn.Flags = OFN_HIDEREADONLY | dwOfnFlags; + if (bWin4) + ofn.Flags |= OFN_EXPLORER; + + // Lastly, parent to tweak OFN parameters + if (hWndOwner != NULL) + SendMessage(hWndOwner, uMsgBrowseOFN, nBrowseID, (LPARAM)&ofn); + + // On success, copy the chosen filename to the static display + BOOL bResult = StandardGetOpenFileName((LPOPENFILENAME)&ofn); + return bResult; +} + +/* + * ReplaceCharWithNull + * + * Purpose: + * Walks a null-terminated string and replaces a given character + * with a zero. Used to turn a single string for file open/save + * filters into the appropriate filter string as required by the + * common dialog API. + * + * Parameters: + * psz LPTSTR to the string to process. + * ch int character to replace. + * + * Return Value: + * int Number of characters replaced. -1 if psz is NULL. + */ + +int WINAPI ReplaceCharWithNull(LPTSTR psz, int ch) +{ + int cChanged = 0; + + if (psz == NULL) + return -1; + + while ('\0' != *psz) + { + if (ch == *psz) + { + *psz++ = '\0'; + cChanged++; + continue; + } + psz = CharNext(psz); + } + return cChanged; +} + +/* + * ErrorWithFile + * + * Purpose: + * Displays a message box built from a stringtable string containing + * one %s as a placeholder for a filename and from a string of the + * filename to place there. + * + * Parameters: + * hWnd HWND owning the message box. The caption of this + * window is the caption of the message box. + * hInst HINSTANCE from which to draw the idsErr string. + * idsErr UINT identifier of a stringtable string containing + * the error message with a %s. + * lpszFile LPSTR to the filename to include in the message. + * uFlags UINT flags to pass to MessageBox, like MB_OK. + * + * Return Value: + * int Return value from MessageBox. + */ + +int WINAPI ErrorWithFile(HWND hWnd, HINSTANCE hInst, UINT idsErr, + LPTSTR pszFile, UINT uFlags) +{ + int iRet=0; + HANDLE hMem; + const UINT cb = (2*MAX_PATH); + LPTSTR psz1, psz2, psz3; + + if (NULL == hInst || NULL == pszFile) + return iRet; + + // Allocate three 2*MAX_PATH byte work buffers + hMem=GlobalAlloc(GHND, (DWORD)(3*cb)*sizeof(TCHAR)); + + if (NULL==hMem) + return iRet; + + psz1 = (LPTSTR)GlobalLock(hMem); + psz2 = psz1+cb; + psz3 = psz2+cb; + + if (0 != LoadString(hInst, idsErr, psz1, cb)) + { + wsprintf(psz2, psz1, pszFile); + + // Steal the caption of the dialog + GetWindowText(hWnd, psz3, cb); + iRet=MessageBox(hWnd, psz2, psz3, uFlags); + } + + GlobalUnlock(hMem); + GlobalFree(hMem); + return iRet; +} + +// returns width of line of text. this is a support routine for ChopText +static LONG GetTextWSize(HDC hDC, LPTSTR lpsz) +{ + SIZE size; + + if (GetTextExtentPoint(hDC, lpsz, lstrlen(lpsz), (LPSIZE)&size)) + return size.cx; + else + return 0; +} + +LPTSTR FindChar(LPTSTR lpsz, TCHAR ch) +{ + while (*lpsz != 0) + { + if (*lpsz == ch) + return lpsz; + lpsz = CharNext(lpsz); + } + return NULL; +} + +LPTSTR FindReverseChar(LPTSTR lpsz, TCHAR ch) +{ + LPTSTR lpszLast = NULL; + while (*lpsz != 0) + { + if (*lpsz == ch) + lpszLast = lpsz; + lpsz = CharNext(lpsz); + } + return lpszLast; +} + +static void WINAPI Abbreviate(HDC hdc, int nWidth, LPTSTR lpch, int nMaxChars) +{ + /* string is too long to fit; chop it */ + /* set up new prefix & determine remaining space in control */ + LPTSTR lpszFileName = NULL; + LPTSTR lpszCur = CharNext(CharNext(lpch)); + lpszCur = FindChar(lpszCur, TEXT('\\')); + + // algorithm will insert \... so allocate extra 4 + LPTSTR lpszNew = (LPTSTR)OleStdMalloc((lstrlen(lpch)+5) * sizeof(TCHAR)); + if (lpszNew == NULL) + return; + + if (lpszCur != NULL) // at least one backslash + { + *lpszNew = (TCHAR)0; + *lpszCur = (TCHAR)0; + lstrcpy(lpszNew, lpch); + *lpszCur = TEXT('\\'); + // lpszNew now contains c: or \\servername + lstrcat(lpszNew, TEXT("\\...")); + // lpszNew now contains c:\... or \\servername\... + LPTSTR lpszEnd = lpszNew; + while (*lpszEnd != (TCHAR)0) + lpszEnd = CharNext(lpszEnd); + // lpszEnd is now at the end of c:\... or \\servername\... + + // move down directories until it fits or no more directories + while (lpszCur != NULL) + { + *lpszEnd = (TCHAR)0; + lstrcat(lpszEnd, lpszCur); + if (GetTextWSize(hdc, lpszNew) <= nWidth && + lstrlen(lpszNew) < nMaxChars) + { + lstrcpyn(lpch, lpszNew, nMaxChars); + OleStdFree(lpszNew); + return; + } + lpszCur = CharNext(lpszCur); // advance past backslash + lpszCur = FindChar(lpszCur, TEXT('\\')); + } + + // try just ...filename and then shortening filename + lpszFileName = FindReverseChar(lpch, TEXT('\\')); + } + else + lpszFileName = lpch; + + while (*lpszFileName != (TCHAR)0) + { + lstrcpy(lpszNew, TEXT("...")); + lstrcat(lpszNew, lpszFileName); + if (GetTextWSize(hdc, lpszNew) <= nWidth && lstrlen(lpszNew) < nMaxChars) + { + lstrcpyn(lpch, lpszNew, nMaxChars); + OleStdFree(lpszNew); + return; + } + lpszFileName = CharNext(lpszFileName); + } + + OleStdFree(lpszNew); + + // not even a single character fit + *lpch = (TCHAR)0; +} + +/* + * ChopText + * + * Purpose: + * Parse a string (pathname) and convert it to be within a specified + * length by chopping the least significant part + * + * Parameters: + * hWnd window handle in which the string resides + * nWidth max width of string in pixels + * use width of hWnd if zero + * lpch pointer to beginning of the string + * nMaxChars maximum allowable number of characters (0 ignore) + * + * Return Value: + * pointer to the modified string + */ +LPTSTR WINAPI ChopText(HWND hWnd, int nWidth, LPTSTR lpch, int nMaxChars) +{ + HDC hdc; + HFONT hfont; + HFONT hfontOld = NULL; + RECT rc; + + if (!hWnd || !lpch) + return NULL; + + if (nMaxChars == 0) + nMaxChars = 32768; // big number + + /* Get length of static field. */ + if (!nWidth) + { + GetClientRect(hWnd, (LPRECT)&rc); + nWidth = rc.right - rc.left; + } + + /* Set up DC appropriately for the static control */ + hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL); + hfont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0L); + + if (NULL != hfont) // WM_GETFONT returns NULL if window uses system font + hfontOld = (HFONT)SelectObject(hdc, hfont); + + /* check horizontal extent of string */ + if (GetTextWSize(hdc, lpch) > nWidth || lstrlen(lpch) >= nMaxChars) + Abbreviate(hdc, nWidth, lpch, nMaxChars); + + if (NULL != hfont) + SelectObject(hdc, hfontOld); + DeleteDC(hdc); + + return lpch; +} + +/* + * OpenFileError + * + * Purpose: + * display message for error returned from OpenFile + * + * Parameters: + * hDlg HWND of the dialog. + * nErrCode UINT error code returned in OFSTRUCT passed to OpenFile + * lpszFile LPSTR file name passed to OpenFile + * + * Return Value: + * None + */ +void WINAPI OpenFileError(HWND hDlg, UINT nErrCode, LPTSTR lpszFile) +{ + switch (nErrCode) + { + case 0x0005: // Access denied + ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIFILEACCESS, lpszFile, + MB_OK | MB_ICONEXCLAMATION); + break; + + case 0x0020: // Sharing violation + ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIFILESHARE, lpszFile, + MB_OK | MB_ICONEXCLAMATION); + break; + + case 0x0002: // File not found + case 0x0003: // Path not found + ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIINVALIDFILE, lpszFile, + MB_OK | MB_ICONEXCLAMATION); + break; + + default: + ErrorWithFile(hDlg, _g_hOleStdResInst, IDS_CIFILEOPENFAIL, lpszFile, + MB_OK | MB_ICONEXCLAMATION); + break; + } +} + +/* + * DoesFileExist + * + * Purpose: + * Determines if a file path exists + * + * Parameters: + * lpszFile LPTSTR - file name + * cchMax UINT - size of the lpszFile string buffer in characters. + * + * Return Value: + * BOOL TRUE if file exists, else FALSE. + * + * NOTE: lpszFile may be changed as a result of this call to match the first + * matching file name found by this routine. + * + */ +BOOL WINAPI DoesFileExist(LPTSTR lpszFile, UINT cchMax) +{ + static const TCHAR *arrIllegalNames[] = + { + TEXT("LPT1"), TEXT("LPT2"), TEXT("LPT3"), + TEXT("COM1"), TEXT("COM2"), TEXT("COM3"), TEXT("COM4"), + TEXT("CON"), TEXT("AUX"), TEXT("PRN") + }; + + // check is the name is an illegal name (eg. the name of a device) + for (int i = 0; i < (sizeof(arrIllegalNames)/sizeof(arrIllegalNames[0])); i++) + { + if (lstrcmpi(lpszFile, arrIllegalNames[i])==0) + return FALSE; + } + + // First try to find the file with an exact match + + // check the file's attributes + DWORD dwAttrs = GetFileAttributes(lpszFile); + if (dwAttrs == 0xFFFFFFFF) // file wasn't found + { + // look in path for file + TCHAR szTempFileName[MAX_PATH]; + LPTSTR lpszFilePart; + BOOL fFound = SearchPath(NULL, lpszFile, NULL, MAX_PATH, szTempFileName, &lpszFilePart) != 0; + if (!fFound) + { + // File wasn't found in the search path + // Try to append a .* and use FindFirstFile to try for a match in the current directory + UINT cchFile = lstrlen(lpszFile); + if (cchFile + 4 < MAX_PATH) + { + WIN32_FIND_DATA sFindFileData; + lstrcpy(szTempFileName,lpszFile); + lstrcpy(&szTempFileName[cchFile], TEXT("*.*")); + HANDLE hFindFile = FindFirstFile(szTempFileName, &sFindFileData); + if (INVALID_HANDLE_VALUE != hFindFile) + { + // found something + while (0 != sFindFileData.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_TEMPORARY)) + { + // found a directory or a temporary file try again + if (!FindNextFile(hFindFile, &sFindFileData)) + { + // Could only match a directory or temporary file. + FindClose(hFindFile); + return(FALSE); + } + } + // Copy the name of the found file into the end of the path in the + // temporary buffer (if any). + // First scan back for the last file separator. + UINT cchPath = lstrlen(szTempFileName); + while (cchPath) + { + if (_T('\\') == szTempFileName[cchPath - 1] + || _T('/') == szTempFileName[cchPath - 1]) + { + break; + } + cchPath--; + } + lstrcpyn(&szTempFileName[cchPath], sFindFileData.cFileName, MAX_PATH - cchPath); + fFound = TRUE; + FindClose(hFindFile); + } + } + } + if (fFound) + { + // copy the temporary buffer into szFile + lstrcpyn(lpszFile, szTempFileName, cchMax -1); + } + return(fFound); + } + else if (dwAttrs & (FILE_ATTRIBUTE_DIRECTORY| + FILE_ATTRIBUTE_TEMPORARY)) + { + return FALSE; + } + return TRUE; +} + +/* + * FormatStrings + * + * Purpose: + * Simple message formatting API compatible w/ different languages + * + * Note: + * Shamelessly stolen/modified from MFC source code + * + */ + +void WINAPI FormatStrings(LPTSTR lpszDest, LPCTSTR lpszFormat, + LPCTSTR* rglpsz, int nString) +{ + LPCTSTR pchSrc = lpszFormat; + while (*pchSrc != '\0') + { + if (pchSrc[0] == '%' && (pchSrc[1] >= '1' && pchSrc[1] <= '9')) + { + int i = pchSrc[1] - '1'; + pchSrc += 2; + if (i >= nString) + *lpszDest++ = '?'; + else if (rglpsz[i] != NULL) + { + lstrcpy(lpszDest, rglpsz[i]); + lpszDest += lstrlen(lpszDest); + } + } + else + { +#ifndef _UNICODE + if (IsDBCSLeadByte(*pchSrc)) + *lpszDest++ = *pchSrc++; // copy first of 2 bytes +#endif + *lpszDest++ = *pchSrc++; + } + } + *lpszDest = '\0'; +} + +void WINAPI FormatString1(LPTSTR lpszDest, LPCTSTR lpszFormat, LPCTSTR lpsz1) +{ + FormatStrings(lpszDest, lpszFormat, &lpsz1, 1); +} + +void WINAPI FormatString2(LPTSTR lpszDest, LPCTSTR lpszFormat, LPCTSTR lpsz1, + LPCTSTR lpsz2) +{ + LPCTSTR rglpsz[2]; + rglpsz[0] = lpsz1; + rglpsz[1] = lpsz2; + FormatStrings(lpszDest, lpszFormat, rglpsz, 2); +} + +// Replacement for stdlib atol, +// which didn't work and doesn't take far pointers. +// Must be tolerant of leading spaces. +// +// +LONG WINAPI Atol(LPTSTR lpsz) +{ + signed int sign = +1; + UINT base = 10; + LONG l = 0; + + if (NULL==lpsz) + { + OleDbgAssert (0); + return 0; + } + while (*lpsz == ' ' || *lpsz == '\t' || *lpsz == '\n') + lpsz++; + + if (*lpsz=='-') + { + lpsz++; + sign = -1; + } + if (lpsz[0] == TEXT('0') && lpsz[1] == TEXT('x')) + { + base = 16; + lpsz+=2; + } + + if (base == 10) + { + while (*lpsz >= '0' && *lpsz <= '9') + { + l = l * base + *lpsz - '0'; + lpsz++; + } + } + else + { + OleDbgAssert(base == 16); + while (*lpsz >= '0' && *lpsz <= '9' || + *lpsz >= 'A' && *lpsz <= 'F' || + *lpsz >= 'a' && *lpsz <= 'f') + { + l = l * base; + if (*lpsz >= '0' && *lpsz <= '9') + l += *lpsz - '0'; + else if (*lpsz >= 'a' && *lpsz <= 'f') + l += *lpsz - 'a' + 10; + else + l += *lpsz - 'A' + 10; + lpsz++; + } + } + return l * sign; +} + +BOOL WINAPI IsValidClassID(REFCLSID clsid) +{ + return clsid != CLSID_NULL; +} + +/* PopupMessage + * ------------ + * + * Purpose: + * Popup messagebox and get some response from the user. It is the same + * as MessageBox() except that the title and message string are loaded + * from the resource file. + * + * Parameters: + * hwndParent parent window of message box + * idTitle id of title string + * idMessage id of message string + * fuStyle style of message box + */ +int WINAPI PopupMessage(HWND hwndParent, UINT idTitle, UINT idMessage, UINT fuStyle) +{ + TCHAR szTitle[256]; + TCHAR szMsg[256]; + + LoadString(_g_hOleStdResInst, idTitle, szTitle, sizeof(szTitle)/sizeof(TCHAR)); + LoadString(_g_hOleStdResInst, idMessage, szMsg, sizeof(szMsg)/sizeof(TCHAR)); + return MessageBox(hwndParent, szMsg, szTitle, fuStyle); +} + +/* DiffPrefix + * ---------- + * + * Purpose: + * Compare (case-insensitive) two strings and return the prefixes of the + * the strings formed by removing the common suffix string from them. + * Integrity of tokens (directory name, filename and object names) are + * preserved. Note that the prefixes are converted to upper case + * characters. + * + * Parameters: + * lpsz1 string 1 + * lpsz2 string 2 + * lplpszPrefix1 prefix of string 1 + * lplpszPrefix2 prefix of string 2 + * + * Returns: + * + */ +void WINAPI DiffPrefix(LPCTSTR lpsz1, LPCTSTR lpsz2, TCHAR FAR* FAR* lplpszPrefix1, TCHAR FAR* FAR* lplpszPrefix2) +{ + LPTSTR lpstr1; + LPTSTR lpstr2; + TCHAR szTemp1[MAX_PATH]; + TCHAR szTemp2[MAX_PATH]; + + OleDbgAssert(lpsz1); + OleDbgAssert(lpsz2); + OleDbgAssert(*lpsz1); + OleDbgAssert(*lpsz2); + OleDbgAssert(lplpszPrefix1); + OleDbgAssert(lplpszPrefix2); + + // need to copy into temporary for case insensitive compare + lstrcpy(szTemp1, lpsz1); + lstrcpy(szTemp2, lpsz2); + CharLower(szTemp1); + CharLower(szTemp2); + + // do comparison + lpstr1 = szTemp1 + lstrlen(szTemp1); + lpstr2 = szTemp2 + lstrlen(szTemp2); + + while ((lpstr1 > szTemp1) && (lpstr2 > szTemp2)) + { + lpstr1 = CharPrev(szTemp1, lpstr1); + lpstr2 = CharPrev(szTemp2, lpstr2); + if (*lpstr1 != *lpstr2) + { + lpstr1 = CharNext(lpstr1); + lpstr2 = CharNext(lpstr2); + break; + } + } + + // scan forward to first delimiter + while (*lpstr1 && *lpstr1 != '\\' && *lpstr1 != '!') + lpstr1 = CharNext(lpstr1); + while (*lpstr2 && *lpstr2 != '\\' && *lpstr2 != '!') + lpstr2 = CharNext(lpstr2); + + *lpstr1 = '\0'; + *lpstr2 = '\0'; + + // initialize in case of failure + *lplpszPrefix1 = NULL; + *lplpszPrefix2 = NULL; + + // allocate memory for the result + *lplpszPrefix1 = (LPTSTR)OleStdMalloc((lstrlen(lpsz1)+1) * sizeof(TCHAR)); + if (!*lplpszPrefix1) + return; + + *lplpszPrefix2 = (LPTSTR)OleStdMalloc((lstrlen(lpsz2)+1) * sizeof(TCHAR)); + if (!*lplpszPrefix2) + { + OleStdFree(*lplpszPrefix1); + *lplpszPrefix1 = NULL; + return; + } + + // copy result + lstrcpyn(*lplpszPrefix1, lpsz1, lstrlen(szTemp1)+1); + lstrcpyn(*lplpszPrefix2, lpsz2, lstrlen(szTemp2)+1); +} + +UINT WINAPI GetFileName(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax) +{ + // always capture the complete file name including extension (if present) + LPTSTR lpszTemp = (LPTSTR)lpszPathName; + for (LPCTSTR lpsz = lpszPathName; *lpsz != '\0'; lpsz = CharNext(lpsz)) + { + // remember last directory/drive separator + if (*lpsz == '\\' || *lpsz == '/' || *lpsz == ':') + lpszTemp = CharNext(lpsz); + } + + // lpszTitle can be NULL which just returns the number of bytes + if (lpszTitle == NULL) + return lstrlen(lpszTemp)+1; + + // otherwise copy it into the buffer provided + lstrcpyn(lpszTitle, lpszTemp, nMax); + return 0; +} + +BOOL WINAPI IsValidMetaPict(HGLOBAL hMetaPict) +{ + BOOL fReturn = FALSE; + LPMETAFILEPICT pMF = (LPMETAFILEPICT) GlobalLock(hMetaPict); + if (pMF != NULL) + { + if (!IsBadReadPtr( pMF, sizeof(METAFILEPICT))) + { + if (GetMetaFileBitsEx(pMF->hMF, 0, 0)) + { + fReturn = TRUE; + } + } + GlobalUnlock(hMetaPict); + } + return(fReturn); +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/private/ole2ui32/utility.h b/private/ole2ui32/utility.h new file mode 100644 index 000000000..e3bbe183a --- /dev/null +++ b/private/ole2ui32/utility.h @@ -0,0 +1,66 @@ +/* + * UTILITY.H + * + * Miscellaneous prototypes and definitions for OLE UI dialogs. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + + +#ifndef _UTILITY_H_ +#define _UTILITY_H_ + +#define CF_CLIPBOARDMIN 0xc000 +#define CF_CLIPBOARDMAX 0xffff + +// Function prototypes +// UTILITY.CPP +HCURSOR WINAPI HourGlassOn(void); +void WINAPI HourGlassOff(HCURSOR); + +BOOL WINAPI Browse(HWND, LPTSTR, LPTSTR, UINT, UINT, DWORD, UINT, LPOFNHOOKPROC); +int WINAPI ReplaceCharWithNull(LPTSTR, int); +int WINAPI ErrorWithFile(HWND, HINSTANCE, UINT, LPTSTR, UINT); +BOOL WINAPI DoesFileExist(LPTSTR lpszFile, UINT cchMax); +LONG WINAPI Atol(LPTSTR lpsz); +BOOL WINAPI IsValidClassID(REFCLSID); +UINT WINAPI GetFileName(LPCTSTR, LPTSTR, UINT); +BOOL WINAPI IsValidMetaPict(HGLOBAL hMetaPict); + +LPTSTR FindChar(LPTSTR lpsz, TCHAR ch); +LPTSTR FindReverseChar(LPTSTR lpsz, TCHAR ch); + +LPTSTR FAR PASCAL PointerToNthField(LPTSTR, int, TCHAR); +BOOL FAR PASCAL GetAssociatedExecutable(LPTSTR, LPTSTR); +LPTSTR WINAPI ChopText(HWND hwndStatic, int nWidth, LPTSTR lpch, + int nMaxChars); +void WINAPI OpenFileError(HWND hDlg, UINT nErrCode, LPTSTR lpszFile); +int WINAPI PopupMessage(HWND hwndParent, UINT idTitle, UINT idMessage, UINT fuStyle); +void WINAPI DiffPrefix(LPCTSTR lpsz1, LPCTSTR lpsz2, TCHAR FAR* FAR* lplpszPrefix1, TCHAR FAR* FAR* lplpszPrefix2); + +// string formatting APIs +void WINAPI FormatStrings(LPTSTR, LPCTSTR, LPCTSTR*, int); +void WINAPI FormatString1(LPTSTR, LPCTSTR, LPCTSTR); +void WINAPI FormatString2(LPTSTR, LPCTSTR, LPCTSTR, LPCTSTR); + +// global instance to load strings/resources from +extern HINSTANCE _g_hOleStdInst; +extern HINSTANCE _g_hOleStdResInst; + +// standard OLE 2.0 clipboard formats +extern UINT _g_cfObjectDescriptor; +extern UINT _g_cfLinkSrcDescriptor; +extern UINT _g_cfEmbedSource; +extern UINT _g_cfEmbeddedObject; +extern UINT _g_cfLinkSource; +extern UINT _g_cfOwnerLink; +extern UINT _g_cfFileName; + +// Metafile utility functions +STDAPI_(void) OleUIMetafilePictIconFree(HGLOBAL); +STDAPI_(BOOL) OleUIMetafilePictIconDraw(HDC, LPCRECT, HGLOBAL, BOOL); +STDAPI_(UINT) OleUIMetafilePictExtractLabel(HGLOBAL, LPTSTR, UINT, LPDWORD); +STDAPI_(HICON) OleUIMetafilePictExtractIcon(HGLOBAL); +STDAPI_(BOOL) OleUIMetafilePictExtractIconSource(HGLOBAL, LPTSTR, UINT FAR *); + +#endif //_UTILITY_H_ diff --git a/private/ole2ui32/win32s/makefile b/private/ole2ui32/win32s/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ole2ui32/win32s/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ole2ui32/win32s/oledlg.def b/private/ole2ui32/win32s/oledlg.def new file mode 100644 index 000000000..3165d10db --- /dev/null +++ b/private/ole2ui32/win32s/oledlg.def @@ -0,0 +1,46 @@ +;/////////////////////////////////////////////////////////////////////////// +; +; ole2ui.def +; +; Definition file for oledlg.dll +; c) Copyright Microsoft Corp. 1992 - 1994 All Rights Reserved +; + +DESCRIPTION 'OLEDLG - OLE 2 Common Dialog Support Library.' +EXPORTS + +; Narrow APIs: + +; OLE Menu APIs +OleUIAddVerbMenuA @1 +OleUICanConvertOrActivateAs @2 + +; OLE Common Dialog APIs +OleUIInsertObjectA @3 +OleUIPasteSpecialA @4 +OleUIEditLinksA @5 +OleUIChangeIconA @6 +OleUIConvertA @7 +OleUIBusyA @8 +OleUIUpdateLinksA @9 +OleUIPromptUserA @10 +OleUIObjectPropertiesA @11 +OleUIChangeSourceA @12 + +; Wide APIs: + +; OLE Menu APIs +OleUIAddVerbMenuW + +; OLE Common Dialog APIs +OleUIInsertObjectW=ReturnError +OleUIPasteSpecialW=ReturnError +OleUIEditLinksW=ReturnError +OleUIChangeIconW=ReturnError +OleUIConvertW=ReturnError +OleUIBusyW=ReturnError +OleUIUpdateLinksW +OleUIPromptUserW +OleUIObjectPropertiesW=ReturnError +OleUIChangeSourceW=ReturnError + diff --git a/private/ole2ui32/win32s/sources b/private/ole2ui32/win32s/sources new file mode 100644 index 000000000..7e4402456 --- /dev/null +++ b/private/ole2ui32/win32s/sources @@ -0,0 +1,78 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + + +!ENDIF + + +DLLENTRY=DllMain + +DLLDEF=obj\*\oledlg.def + +MAJORCOMP=oledlg +MINORCOMP= + +TARGETNAME=oledlg +TARGETPATH=obj +C_DEFINES=-DWIN32 -DWINVER=0x400 +TARGETTYPE=DYNLINK + +UMTYPE=windows + +INCLUDES=.. + +PRECOMPILED_INCLUDE=..\precomp.h +PRECOMPILED_PCH=precomp.pch +PRECOMPILED_OBJ=precomp.obj + + +386_OPTIMIZATION=/Oy- + +SOURCES= ..\chngsrc.cpp \ + ..\objprop.cpp \ + ..\busy.cpp \ + ..\common.cpp \ + ..\convert.cpp \ + ..\drawicon.cpp \ + ..\icon.cpp \ + ..\iconbox.cpp \ + ..\insobj.cpp \ + ..\links.cpp \ + ..\ole2ui.cpp \ + ..\olestd.cpp \ + ..\pastespl.cpp \ + ..\targtdev.cpp \ + ..\oleutl.cpp \ + ..\resimage.cpp \ + ..\utility.cpp \ + ..\dllfuncs.cpp \ + ..\geticon.cpp \ + ..\wrapstub.cpp \ + ..\ole2ui.rc + +USE_CRTDLL=1 + +LINKLIBS= \ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\user32.lib \ + $(BASEDIR)\public\sdk\lib\*\gdi32.lib \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib \ + $(BASEDIR)\public\sdk\lib\*\ole32.lib \ + $(BASEDIR)\public\sdk\lib\*\uuid.lib + diff --git a/private/ole2ui32/winres.h b/private/ole2ui32/winres.h new file mode 100644 index 000000000..42eee2602 --- /dev/null +++ b/private/ole2ui32/winres.h @@ -0,0 +1,300 @@ +// Microsoft Foundation Classes C++ library. +// Copyright (C) 1992 Microsoft Corporation, +// All rights reserved. + +// This source code is only intended as a supplement to the +// Microsoft Foundation Classes Reference and Microsoft +// QuickHelp and/or WinHelp documentation provided with the library. +// See these sources for detailed information regarding the +// Microsoft Foundation Classes product. + +// winres.h - Windows resource definitions +// extracted from WINDOWS.H +// Version 3.10 +// Copyright (c) 1985-1992, Microsoft Corp. All rights reserved. +// + +#define VS_VERSION_INFO 1 + +#ifdef APSTUDIO_INVOKED +#define APSTUDIO_HIDDEN_SYMBOLS // Ignore following symbols +#endif + +#define OBM_CLOSE 32754 +#define OBM_UPARROW 32753 +#define OBM_DNARROW 32752 +#define OBM_RGARROW 32751 +#define OBM_LFARROW 32750 +#define OBM_REDUCE 32749 +#define OBM_ZOOM 32748 +#define OBM_RESTORE 32747 +#define OBM_REDUCED 32746 +#define OBM_ZOOMD 32745 +#define OBM_RESTORED 32744 +#define OBM_UPARROWD 32743 +#define OBM_DNARROWD 32742 +#define OBM_RGARROWD 32741 +#define OBM_LFARROWD 32740 +#define OBM_MNARROW 32739 +#define OBM_COMBO 32738 +#define OBM_UPARROWI 32737 +#define OBM_DNARROWI 32736 +#define OBM_RGARROWI 32735 +#define OBM_LFARROWI 32734 +#define OBM_OLD_CLOSE 32767 +#define OBM_SIZE 32766 +#define OBM_OLD_UPARROW 32765 +#define OBM_OLD_DNARROW 32764 +#define OBM_OLD_RGARROW 32763 +#define OBM_OLD_LFARROW 32762 +#define OBM_BTSIZE 32761 +#define OBM_CHECK 32760 +#define OBM_CHECKBOXES 32759 +#define OBM_BTNCORNERS 32758 +#define OBM_OLD_REDUCE 32757 +#define OBM_OLD_ZOOM 32756 +#define OBM_OLD_RESTORE 32755 +#define OCR_NORMAL 32512 +#define OCR_IBEAM 32513 +#define OCR_WAIT 32514 +#define OCR_CROSS 32515 +#define OCR_UP 32516 +#define OCR_SIZE 32640 +#define OCR_ICON 32641 +#define OCR_SIZENWSE 32642 +#define OCR_SIZENESW 32643 +#define OCR_SIZEWE 32644 +#define OCR_SIZENS 32645 +#define OCR_SIZEALL 32646 +#define OCR_ICOCUR 32647 +#define OIC_SAMPLE 32512 +#define OIC_HAND 32513 +#define OIC_QUES 32514 +#define OIC_BANG 32515 +#define OIC_NOTE 32516 + +#define WS_OVERLAPPED 0x00000000L +#define WS_POPUP 0x80000000L +#define WS_CHILD 0x40000000L +#define WS_CLIPSIBLINGS 0x04000000L +#define WS_CLIPCHILDREN 0x02000000L +#define WS_VISIBLE 0x10000000L +#define WS_DISABLED 0x08000000L +#define WS_MINIMIZE 0x20000000L +#define WS_MAXIMIZE 0x01000000L +#define WS_CAPTION 0x00C00000L +#define WS_BORDER 0x00800000L +#define WS_DLGFRAME 0x00400000L +#define WS_VSCROLL 0x00200000L +#define WS_HSCROLL 0x00100000L +#define WS_SYSMENU 0x00080000L +#define WS_THICKFRAME 0x00040000L +#define WS_MINIMIZEBOX 0x00020000L +#define WS_MAXIMIZEBOX 0x00010000L +#define WS_GROUP 0x00020000L +#define WS_TABSTOP 0x00010000L + +// other aliases +#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) +#define WS_POPUPWINDOW (WS_POPUP | WS_BORDER | WS_SYSMENU) +#define WS_CHILDWINDOW (WS_CHILD) +#define WS_TILED WS_OVERLAPPED +#define WS_ICONIC WS_MINIMIZE +#define WS_SIZEBOX WS_THICKFRAME +#define WS_TILEDWINDOW WS_OVERLAPPEDWINDOW + +#define VK_LBUTTON 0x01 +#define VK_RBUTTON 0x02 +#define VK_CANCEL 0x03 +#define VK_MBUTTON 0x04 +#define VK_BACK 0x08 +#define VK_TAB 0x09 +#define VK_CLEAR 0x0C +#define VK_RETURN 0x0D +#define VK_SHIFT 0x10 +#define VK_CONTROL 0x11 +#define VK_MENU 0x12 +#define VK_PAUSE 0x13 +#define VK_CAPITAL 0x14 +#define VK_ESCAPE 0x1B +#define VK_SPACE 0x20 +#define VK_PRIOR 0x21 +#define VK_NEXT 0x22 +#define VK_END 0x23 +#define VK_HOME 0x24 +#define VK_LEFT 0x25 +#define VK_UP 0x26 +#define VK_RIGHT 0x27 +#define VK_DOWN 0x28 +#define VK_SELECT 0x29 +#define VK_PRINT 0x2A +#define VK_EXECUTE 0x2B +#define VK_SNAPSHOT 0x2C +#define VK_INSERT 0x2D +#define VK_DELETE 0x2E +#define VK_HELP 0x2F +#define VK_NUMPAD0 0x60 +#define VK_NUMPAD1 0x61 +#define VK_NUMPAD2 0x62 +#define VK_NUMPAD3 0x63 +#define VK_NUMPAD4 0x64 +#define VK_NUMPAD5 0x65 +#define VK_NUMPAD6 0x66 +#define VK_NUMPAD7 0x67 +#define VK_NUMPAD8 0x68 +#define VK_NUMPAD9 0x69 +#define VK_MULTIPLY 0x6A +#define VK_ADD 0x6B +#define VK_SEPARATOR 0x6C +#define VK_SUBTRACT 0x6D +#define VK_DECIMAL 0x6E +#define VK_DIVIDE 0x6F +#define VK_F1 0x70 +#define VK_F2 0x71 +#define VK_F3 0x72 +#define VK_F4 0x73 +#define VK_F5 0x74 +#define VK_F6 0x75 +#define VK_F7 0x76 +#define VK_F8 0x77 +#define VK_F9 0x78 +#define VK_F10 0x79 +#define VK_F11 0x7A +#define VK_F12 0x7B +#define VK_F13 0x7C +#define VK_F14 0x7D +#define VK_F15 0x7E +#define VK_F16 0x7F +#define VK_F17 0x80 +#define VK_F18 0x81 +#define VK_F19 0x82 +#define VK_F20 0x83 +#define VK_F21 0x84 +#define VK_F22 0x85 +#define VK_F23 0x86 +#define VK_F24 0x87 +#define VK_NUMLOCK 0x90 +#define VK_SCROLL 0x91 + +#define SC_SIZE 0xF000 +#define SC_MOVE 0xF010 +#define SC_MINIMIZE 0xF020 +#define SC_MAXIMIZE 0xF030 +#define SC_NEXTWINDOW 0xF040 +#define SC_PREVWINDOW 0xF050 +#define SC_CLOSE 0xF060 +#define SC_VSCROLL 0xF070 +#define SC_HSCROLL 0xF080 +#define SC_MOUSEMENU 0xF090 +#define SC_KEYMENU 0xF100 +#define SC_ARRANGE 0xF110 +#define SC_RESTORE 0xF120 +#define SC_TASKLIST 0xF130 +#define SC_SCREENSAVE 0xF140 +#define SC_HOTKEY 0xF150 + +#define DS_ABSALIGN 0x01L +#define DS_SYSMODAL 0x02L +#define DS_LOCALEDIT 0x20L +#define DS_SETFONT 0x40L +#define DS_MODALFRAME 0x80L +#define DS_NOIDLEMSG 0x100L + +#ifdef _MAC +#define DS_WINDOWSUI 0x8000L +#endif + +#define SS_LEFT 0x00000000L +#define SS_CENTER 0x00000001L +#define SS_RIGHT 0x00000002L +#define SS_ICON 0x00000003L +#define SS_BLACKRECT 0x00000004L +#define SS_GRAYRECT 0x00000005L +#define SS_WHITERECT 0x00000006L +#define SS_BLACKFRAME 0x00000007L +#define SS_GRAYFRAME 0x00000008L +#define SS_WHITEFRAME 0x00000009L +#define SS_SIMPLE 0x0000000BL +#define SS_LEFTNOWORDWRAP 0x0000000CL +#define SS_NOPREFIX 0x00000080L + +#define BS_PUSHBUTTON 0x00000000L +#define BS_DEFPUSHBUTTON 0x00000001L +#define BS_CHECKBOX 0x00000002L +#define BS_AUTOCHECKBOX 0x00000003L +#define BS_RADIOBUTTON 0x00000004L +#define BS_3STATE 0x00000005L +#define BS_AUTO3STATE 0x00000006L +#define BS_GROUPBOX 0x00000007L +#define BS_USERBUTTON 0x00000008L +#define BS_AUTORADIOBUTTON 0x00000009L +#define BS_OWNERDRAW 0x0000000BL +#define BS_LEFTTEXT 0x00000020L + +#define ES_LEFT 0x00000000L +#define ES_CENTER 0x00000001L +#define ES_RIGHT 0x00000002L +#define ES_MULTILINE 0x00000004L +#define ES_UPPERCASE 0x00000008L +#define ES_LOWERCASE 0x00000010L +#define ES_PASSWORD 0x00000020L +#define ES_AUTOVSCROLL 0x00000040L +#define ES_AUTOHSCROLL 0x00000080L +#define ES_NOHIDESEL 0x00000100L +#define ES_OEMCONVERT 0x00000400L +#define ES_READONLY 0x00000800L +#define ES_WANTRETURN 0x00001000L + +#define SBS_HORZ 0x0000L +#define SBS_VERT 0x0001L +#define SBS_TOPALIGN 0x0002L +#define SBS_LEFTALIGN 0x0002L +#define SBS_BOTTOMALIGN 0x0004L +#define SBS_RIGHTALIGN 0x0004L +#define SBS_SIZEBOXTOPLEFTALIGN 0x0002L +#define SBS_SIZEBOXBOTTOMRIGHTALIGN 0x0004L +#define SBS_SIZEBOX 0x0008L + +#define LBS_NOTIFY 0x0001L +#define LBS_SORT 0x0002L +#define LBS_NOREDRAW 0x0004L +#define LBS_MULTIPLESEL 0x0008L +#define LBS_OWNERDRAWFIXED 0x0010L +#define LBS_OWNERDRAWVARIABLE 0x0020L +#define LBS_HASSTRINGS 0x0040L +#define LBS_USETABSTOPS 0x0080L +#define LBS_NOINTEGRALHEIGHT 0x0100L +#define LBS_MULTICOLUMN 0x0200L +#define LBS_WANTKEYBOARDINPUT 0x0400L +#define LBS_EXTENDEDSEL 0x0800L +#define LBS_DISABLENOSCROLL 0x1000L +#define LBS_STANDARD (LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER) + +#define CBS_SIMPLE 0x0001L +#define CBS_DROPDOWN 0x0002L +#define CBS_DROPDOWNLIST 0x0003L +#define CBS_OWNERDRAWFIXED 0x0010L +#define CBS_OWNERDRAWVARIABLE 0x0020L +#define CBS_AUTOHSCROLL 0x0040L +#define CBS_OEMCONVERT 0x0080L +#define CBS_SORT 0x0100L +#define CBS_HASSTRINGS 0x0200L +#define CBS_NOINTEGRALHEIGHT 0x0400L +#define CBS_DISABLENOSCROLL 0x0800L + +// operation messages sent to DLGINIT +#define WM_USER 0x0400 +#define LB_ADDSTRING (WM_USER+1) +#define CB_ADDSTRING (WM_USER+3) + +#ifdef APSTUDIO_INVOKED +#undef APSTUDIO_HIDDEN_SYMBOLS +#endif + +#define IDOK 1 +#define IDCANCEL 2 +#define IDABORT 3 +#define IDRETRY 4 +#define IDIGNORE 5 +#define IDYES 6 +#define IDNO 7 diff --git a/private/ole2ui32/wrapstub.cpp b/private/ole2ui32/wrapstub.cpp new file mode 100644 index 000000000..fdcf69ccb --- /dev/null +++ b/private/ole2ui32/wrapstub.cpp @@ -0,0 +1,1777 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1994. +// +// File: wrapstub.cpp +// +// Contents: ANSI to Unicode wrappers and Unicode stubs +// +// Classes: WrappedIOleUILinkContainer +// WrappedIOleUIObjInfo +// WrappedIOleUILinkInfo +// +// Functions: +#ifdef UNICODE +// OleUIAddVerbMenuA +// OleUIInsertObjectA +// OleUIPasteSpecialA +// OleUIEditLinksA +// OleUIChangeIconA +// OleUIConvertA +// OleUIBusyA +// OleUIUpdateLinksA +// OleUIObjectPropertiesA +// OleUIChangeSourceA +// OleUIPromptUserA +#else +// OleUIAddVerbMenuW +// OleUIInsertObjectW +// OleUIPasteSpecialW +// OleUIEditLinksW +// OleUIChangeIconW +// OleUIConvertW +// OleUIBusyW +// OleUIUpdateLinksW +// OleUIObjectPropertiesW +// OleUIChangeSourceW +// OleUIPromptUserW +#endif +// +// History: 11-02-94 stevebl Created +// +//---------------------------------------------------------------------------- + +#include "precomp.h" +#include "common.h" + +#ifdef UNICODE +// ANSI to Unicode Wrappers + +//+--------------------------------------------------------------------------- +// +// Function: OleUIAddVerbMenuA +// +// Synopsis: converts call to ANSI version into call to Unicode version +// +// Arguments: [lpOleObj] - +// [lpszShortType] - [in] on heap +// [hMenu] - +// [uPos] - +// [uIDVerbMin] - +// [uIDVerbMax] - +// [bAddConvert] - +// [idConvert] - +// [lphMenu] - +// +// History: 11-04-94 stevebl Created +// +//---------------------------------------------------------------------------- + +STDAPI_(BOOL) OleUIAddVerbMenuA(LPOLEOBJECT lpOleObj, LPCSTR lpszShortType, + HMENU hMenu, UINT uPos, UINT uIDVerbMin, UINT uIDVerbMax, + BOOL bAddConvert, UINT idConvert, HMENU FAR *lphMenu) +{ + LPWSTR lpwszShortType = NULL; + if (lpszShortType && !IsBadReadPtr(lpszShortType, 1)) + { + UINT uSize = ATOWLEN(lpszShortType); + lpwszShortType = (LPWSTR)OleStdMalloc(sizeof(WCHAR) * uSize); + if (lpwszShortType) + { + ATOW(lpwszShortType, lpszShortType, uSize); + } + } + + // NOTE - if OleStdMalloc fails, this routine must still go ahead and + // succeed as best as it can since there is no way to report failure. + + BOOL fReturn = OleUIAddVerbMenuW(lpOleObj, lpwszShortType, hMenu, uPos, + uIDVerbMin, uIDVerbMax, bAddConvert, idConvert, lphMenu); + + if (lpwszShortType) + OleStdFree((LPVOID)lpwszShortType); + + return(fReturn); +} + +//+--------------------------------------------------------------------------- +// +// Function: OleUIInsertObjectA +// +// Synopsis: converts call to ANSI version into call to Unicode version +// +// Arguments: [psA] - ANSI structure +// +// History: 11-04-94 stevebl Created +// +// Structure members converted or passed back out (everything is passed in): +// lpszCaption [in] on stack +// lpszTemplate [in] on stack +// lpszFile [in, out] on stack +// dwFlags [out] +// clsid [out] +// lpIStorage [out] +// ppvObj [out] +// sc [out] +// hMetaPict [out] +// +//---------------------------------------------------------------------------- + +STDAPI_(UINT) OleUIInsertObjectA(LPOLEUIINSERTOBJECTA psA) +{ + UINT uRet = UStandardValidation((LPOLEUISTANDARD)psA, sizeof(*psA), NULL); + + // If the caller is using a private template, UStandardValidation will + // always return OLEUI_ERR_FINDTEMPLATEFAILURE here. This is because we + // haven't converted the template name to UNICODE yet, so the + // FindResource call in UStandardValidation won't find the caller's + // template. This is OK for two reasons: (1) it's the last thing that + // UStandardValidation checks so by this time it's basically done its + // job, and (2) UStandardValidation will be called again when we forward + // this call on to the Unicode version. + if (OLEUI_SUCCESS != uRet && OLEUI_ERR_FINDTEMPLATEFAILURE != uRet) + return uRet; + + if (NULL != psA->lpszFile && + (psA->cchFile <= 0 || psA->cchFile > MAX_PATH)) + { + return(OLEUI_IOERR_CCHFILEINVALID); + } + + // NULL is NOT valid for lpszFile + if (psA->lpszFile == NULL) + { + return(OLEUI_IOERR_LPSZFILEINVALID); + } + + if (IsBadWritePtr(psA->lpszFile, psA->cchFile*sizeof(char))) + return(OLEUI_IOERR_LPSZFILEINVALID); + + OLEUIINSERTOBJECTW sW; + WCHAR szCaption[MAX_PATH], szTemplate[MAX_PATH], szFile[MAX_PATH]; + + memcpy(&sW, psA, sizeof(OLEUIINSERTOBJECTW)); + if (psA->lpszCaption) + { + ATOW(szCaption, psA->lpszCaption, MAX_PATH); + sW.lpszCaption = szCaption; + } + if (0 != HIWORD(psA->lpszTemplate)) + { + ATOW(szTemplate, psA->lpszTemplate, MAX_PATH); + sW.lpszTemplate = szTemplate; + } + if (psA->lpszFile) + { + ATOW(szFile, psA->lpszFile, MAX_PATH); + sW.lpszFile = szFile; + } + + uRet = OleUIInsertObjectW(&sW); + + if (psA->lpszFile) + { + WTOA(psA->lpszFile, sW.lpszFile, psA->cchFile); + } + memcpy(&psA->clsid, &sW.clsid, sizeof(CLSID)); + psA->dwFlags = sW.dwFlags; + psA->lpIStorage = sW.lpIStorage; + psA->ppvObj = sW.ppvObj; + psA->sc = sW.sc; + psA->hMetaPict = sW.hMetaPict; + return(uRet); +} + +//+--------------------------------------------------------------------------- +// +// Function: OleUIPasteSpecialA +// +// Synopsis: convers call to ANSI version into call to Unicode version +// +// Arguments: [psA] - ANSI structure +// +// History: 11-04-94 stevebl Created +// +// Structure members converted or passed back out (everything is passed in): +// lpszCaption [in] on stack +// lpszTemplate [in] on stack +// arrPasteEntries [in] on heap +// arrPasteEntries[n].lpstrFormatName [in] on heap +// dwFlags [out] +// nSelectedIndex [out] +// fLink [out] +// hMetaPict [out] +// sizel [out] +// +//---------------------------------------------------------------------------- + + +STDAPI_(UINT) OleUIPasteSpecialA(LPOLEUIPASTESPECIALA psA) +{ + UINT uRet = UStandardValidation((LPOLEUISTANDARD)psA, sizeof(*psA), NULL); + + // If the caller is using a private template, UStandardValidation will + // always return OLEUI_ERR_FINDTEMPLATEFAILURE here. This is because we + // haven't converted the template name to UNICODE yet, so the + // FindResource call in UStandardValidation won't find the caller's + // template. This is OK for two reasons: (1) it's the last thing that + // UStandardValidation checks so by this time it's basically done its + // job, and (2) UStandardValidation will be called again when we forward + // this call on to the Unicode version. + if (OLEUI_SUCCESS != uRet && OLEUI_ERR_FINDTEMPLATEFAILURE != uRet) + return uRet; + + // Validate PasteSpecial specific fields + if (NULL == psA->arrPasteEntries || IsBadReadPtr(psA->arrPasteEntries, psA->cPasteEntries * sizeof(OLEUIPASTEENTRYA))) + return(OLEUI_IOERR_ARRPASTEENTRIESINVALID); + + OLEUIPASTESPECIALW sW; + WCHAR szCaption[MAX_PATH], szTemplate[MAX_PATH]; + uRet = OLEUI_ERR_LOCALMEMALLOC; + UINT uIndex; + + memcpy(&sW, psA, sizeof(OLEUIPASTESPECIALW)); + + if (psA->lpszCaption) + { + ATOW(szCaption, psA->lpszCaption, MAX_PATH); + sW.lpszCaption = szCaption; + } + if (0 != HIWORD(psA->lpszTemplate)) + { + ATOW(szTemplate, psA->lpszTemplate, MAX_PATH); + sW.lpszTemplate = szTemplate; + } + if (psA->cPasteEntries) + { + sW.arrPasteEntries = new OLEUIPASTEENTRYW[psA->cPasteEntries]; + if (NULL == sW.arrPasteEntries) + { + return(uRet); + } + for (uIndex = psA->cPasteEntries; uIndex--;) + { + sW.arrPasteEntries[uIndex].lpstrFormatName = NULL; + sW.arrPasteEntries[uIndex].lpstrResultText = NULL; + } + for (uIndex = psA->cPasteEntries; uIndex--;) + { + sW.arrPasteEntries[uIndex].fmtetc = psA->arrPasteEntries[uIndex].fmtetc; + sW.arrPasteEntries[uIndex].dwFlags = psA->arrPasteEntries[uIndex].dwFlags; + sW.arrPasteEntries[uIndex].dwScratchSpace = psA->arrPasteEntries[uIndex].dwScratchSpace; + if (psA->arrPasteEntries[uIndex].lpstrFormatName) + { + UINT uLength = ATOWLEN(psA->arrPasteEntries[uIndex].lpstrFormatName); + sW.arrPasteEntries[uIndex].lpstrFormatName = new WCHAR[uLength]; + if (NULL == sW.arrPasteEntries[uIndex].lpstrFormatName) + { + goto oom_error; + } + ATOW((WCHAR *)sW.arrPasteEntries[uIndex].lpstrFormatName, + psA->arrPasteEntries[uIndex].lpstrFormatName, + uLength); + } + if (psA->arrPasteEntries[uIndex].lpstrResultText) + { + UINT uLength = ATOWLEN(psA->arrPasteEntries[uIndex].lpstrResultText); + sW.arrPasteEntries[uIndex].lpstrResultText = new WCHAR[uLength]; + if (NULL == sW.arrPasteEntries[uIndex].lpstrResultText) + { + goto oom_error; + } + ATOW((WCHAR *)sW.arrPasteEntries[uIndex].lpstrResultText, + psA->arrPasteEntries[uIndex].lpstrResultText, + uLength); + } + } + } + + uRet = OleUIPasteSpecialW(&sW); + psA->lpSrcDataObj = sW.lpSrcDataObj; + psA->dwFlags = sW.dwFlags; + psA->nSelectedIndex = sW.nSelectedIndex; + psA->fLink = sW.fLink; + psA->hMetaPict = sW.hMetaPict; + psA->sizel = sW.sizel; + +oom_error: + for (uIndex = psA->cPasteEntries; uIndex--;) + { + if (sW.arrPasteEntries[uIndex].lpstrFormatName) + { + delete[] (WCHAR*)sW.arrPasteEntries[uIndex].lpstrFormatName; + } + if (sW.arrPasteEntries[uIndex].lpstrResultText) + { + delete[] (WCHAR *)sW.arrPasteEntries[uIndex].lpstrResultText; + } + } + delete[] sW.arrPasteEntries; + return(uRet); +} + +//+--------------------------------------------------------------------------- +// +// Class: WrappedIOleUILinkContainer +// +// Purpose: Wraps IOleUILinkContainerA with IOleUILinkContainerW methods +// so it can be passed on to Unicode methods within OLE2UI32. +// +// Interface: QueryInterface -- +// AddRef -- +// Release -- +// GetNextLink -- +// SetLinkUpdateOptions -- +// GetLinkUpdateOptions -- +// SetLinkSource -- requires string conversion +// GetLinkSource -- requires string conversion +// OpenLinkSource -- +// UpdateLink -- +// CancelLink -- +// WrappedIOleUILinkContainer -- constructor +// ~WrappedIOleUILinkContainer -- destructor +// +// History: 11-04-94 stevebl Created +// +// Notes: This is a private interface wrapper. QueryInterface is not +// supported and the wrapped interface may not be used outside +// of the OLE2UI32 code. +// +//---------------------------------------------------------------------------- + +class WrappedIOleUILinkContainer: public IOleUILinkContainerW +{ +public: + // *** IUnknown methods *** // + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj); + STDMETHOD_(ULONG,AddRef) (THIS); + STDMETHOD_(ULONG,Release) (THIS); + + // *** IOleUILinkContainer *** // + STDMETHOD_(DWORD,GetNextLink) (THIS_ DWORD dwLink); + STDMETHOD(SetLinkUpdateOptions) (THIS_ DWORD dwLink, + DWORD dwUpdateOpt); + STDMETHOD(GetLinkUpdateOptions) (THIS_ DWORD dwLink, + DWORD FAR* lpdwUpdateOpt); + STDMETHOD(SetLinkSource) (THIS_ DWORD dwLink, LPWSTR lpszDisplayName, + ULONG lenFileName, ULONG FAR* pchEaten, BOOL fValidateSource); + STDMETHOD(GetLinkSource) (THIS_ DWORD dwLink, + LPWSTR FAR* lplpszDisplayName, ULONG FAR* lplenFileName, + LPWSTR FAR* lplpszFullLinkType, LPWSTR FAR* lplpszShortLinkType, + BOOL FAR* lpfSourceAvailable, BOOL FAR* lpfIsSelected); + STDMETHOD(OpenLinkSource) (THIS_ DWORD dwLink); + STDMETHOD(UpdateLink) (THIS_ DWORD dwLink, + BOOL fErrorMessage, BOOL fErrorAction); + STDMETHOD(CancelLink) (THIS_ DWORD dwLink); + + // *** Constructor and Destructor *** // + WrappedIOleUILinkContainer(IOleUILinkContainerA *pilc); + ~WrappedIOleUILinkContainer(); +private: + IOleUILinkContainerA * m_pilc; + ULONG m_uRefCount; +}; + +// *** IUnknown methods *** // +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkContainer::QueryInterface(THIS_ REFIID riid, LPVOID FAR* ppvObj) +{ + return(E_NOTIMPL); +} + +ULONG STDMETHODCALLTYPE WrappedIOleUILinkContainer::AddRef() +{ + return(m_uRefCount++); +} + +ULONG STDMETHODCALLTYPE WrappedIOleUILinkContainer::Release() +{ + ULONG uRet = --m_uRefCount; + if (0 == uRet) + { + delete(this); + } + return(uRet); +} + +// *** IOleUILinkContainer *** // +DWORD STDMETHODCALLTYPE WrappedIOleUILinkContainer::GetNextLink(DWORD dwLink) +{ + return(m_pilc->GetNextLink(dwLink)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkContainer::SetLinkUpdateOptions (DWORD dwLink, + DWORD dwUpdateOpt) +{ + return(m_pilc->SetLinkUpdateOptions(dwLink, dwUpdateOpt)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkContainer::GetLinkUpdateOptions (DWORD dwLink, + DWORD FAR* lpdwUpdateOpt) +{ + return(m_pilc->GetLinkUpdateOptions(dwLink, lpdwUpdateOpt)); +} + +//+--------------------------------------------------------------------------- +// +// Member: WrappedIOleUILinkContainer::SetLinkSource +// +// Synopsis: forwards Unicode method call on to the ANSI version +// +// Arguments: [dwLink] - +// [lpszDisplayName] - [in] converted on stack +// [lenFileName] - +// [pchEaten] - +// [fValidateSource] - +// +// History: 11-04-94 stevebl Created +// +//---------------------------------------------------------------------------- + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkContainer::SetLinkSource (DWORD dwLink, LPWSTR lpszDisplayName, + ULONG lenFileName, ULONG FAR* pchEaten, BOOL fValidateSource) +{ + char szDisplayName[MAX_PATH]; + char * lpszDisplayNameA; + if (lpszDisplayName) + { + WTOA(szDisplayName, lpszDisplayName, MAX_PATH); + lpszDisplayNameA = szDisplayName; + } + else + lpszDisplayNameA = NULL; + + return(m_pilc->SetLinkSource(dwLink, lpszDisplayNameA, lenFileName, pchEaten, fValidateSource)); +} + +//+--------------------------------------------------------------------------- +// +// Member: WrappedIOleUILinkContainer::GetLinkSource +// +// Synopsis: forwards Unicode method call on to the ANSI version +// +// Arguments: [dwLink] - +// [lplpszDisplayName] - [out] converted on heap +// [lplenFileName] - +// [lplpszFullLinkType] - [out] converted on heap +// [lplpszShortLinkType] - [out] converted on heap +// [lpfSourceAvailable] - +// [lpfIsSelected] - +// +// History: 11-04-94 stevebl Created +// +//---------------------------------------------------------------------------- + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkContainer::GetLinkSource (DWORD dwLink, + LPWSTR FAR* lplpszDisplayName, ULONG FAR* lplenFileName, + LPWSTR FAR* lplpszFullLinkType, LPWSTR FAR* lplpszShortLinkType, + BOOL FAR* lpfSourceAvailable, BOOL FAR* lpfIsSelected) +{ + LPSTR lpszDisplayName = NULL; + LPSTR lpszFullLinkType = NULL; + LPSTR lpszShortLinkType = NULL; + LPSTR * lplpszDisplayNameA = NULL; + LPSTR * lplpszFullLinkTypeA = NULL; + LPSTR * lplpszShortLinkTypeA = NULL; + if (lplpszDisplayName) + { + lplpszDisplayNameA = &lpszDisplayName; + } + if (lplpszFullLinkType) + { + lplpszFullLinkTypeA = &lpszFullLinkType; + } + if (lplpszShortLinkType) + { + lplpszShortLinkTypeA = &lpszShortLinkType; + } + HRESULT hrReturn = m_pilc->GetLinkSource(dwLink, + lplpszDisplayNameA, + lplenFileName, + lplpszFullLinkTypeA, + lplpszShortLinkTypeA, + lpfSourceAvailable, + lpfIsSelected); + if (lplpszDisplayName) + { + *lplpszDisplayName = NULL; + if (lpszDisplayName) + { + UINT uLen = ATOWLEN(lpszDisplayName); + *lplpszDisplayName = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (*lplpszDisplayName) + { + ATOW(*lplpszDisplayName, lpszDisplayName, uLen); + } + else + hrReturn = E_OUTOFMEMORY; + OleStdFree((LPVOID)lpszDisplayName); + } + } + if (lplpszFullLinkType) + { + *lplpszFullLinkType = NULL; + if (lpszFullLinkType) + { + UINT uLen = ATOWLEN(lpszFullLinkType); + *lplpszFullLinkType = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (*lplpszFullLinkType) + { + ATOW(*lplpszFullLinkType, lpszFullLinkType, uLen); + } + else + hrReturn = E_OUTOFMEMORY; + OleStdFree((LPVOID)lpszFullLinkType); + } + } + if (lplpszShortLinkType) + { + *lplpszShortLinkType = NULL; + if (lpszShortLinkType) + { + UINT uLen = ATOWLEN(lpszShortLinkType); + *lplpszShortLinkType = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (*lplpszShortLinkType) + { + ATOW(*lplpszShortLinkType, lpszShortLinkType, uLen); + } + else + hrReturn = E_OUTOFMEMORY; + OleStdFree((LPVOID)lpszShortLinkType); + } + } + return(hrReturn); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkContainer::OpenLinkSource (DWORD dwLink) +{ + return(m_pilc->OpenLinkSource(dwLink)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkContainer::UpdateLink (DWORD dwLink, + BOOL fErrorMessage, BOOL fErrorAction) +{ + return(m_pilc->UpdateLink(dwLink, fErrorMessage, fErrorAction)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkContainer::CancelLink (DWORD dwLink) +{ + return(m_pilc->CancelLink(dwLink)); +} + +WrappedIOleUILinkContainer::WrappedIOleUILinkContainer(IOleUILinkContainerA *pilc) +{ + m_pilc = pilc; + m_pilc->AddRef(); + m_uRefCount=1; +} + +WrappedIOleUILinkContainer::~WrappedIOleUILinkContainer() +{ + m_pilc->Release(); +} + +//+--------------------------------------------------------------------------- +// +// Function: OleUIEditLinksA +// +// Synopsis: converts call to ANSI version into call to Unicode version +// +// Arguments: [psA] - ANSI structure +// +// History: 11-04-94 stevebl Created +// +// Notes: Uses the WrappedIOleUILinkContainer interface wrapper. +// +// Structure members converted or passed back out (everything is passed in): +// lpszCaption [in] on stack +// lpszTemplate [in] on stack +// dwFlags [out] +// lpOleUILinkContainer [in] wrapped interface +// +//---------------------------------------------------------------------------- + +STDAPI_(UINT) OleUIEditLinksA(LPOLEUIEDITLINKSA psA) +{ + UINT uRet = UStandardValidation((LPOLEUISTANDARD)psA, sizeof(*psA), NULL); + + // If the caller is using a private template, UStandardValidation will + // always return OLEUI_ERR_FINDTEMPLATEFAILURE here. This is because we + // haven't converted the template name to UNICODE yet, so the + // FindResource call in UStandardValidation won't find the caller's + // template. This is OK for two reasons: (1) it's the last thing that + // UStandardValidation checks so by this time it's basically done its + // job, and (2) UStandardValidation will be called again when we forward + // this call on to the Unicode version. + if (OLEUI_SUCCESS != uRet && OLEUI_ERR_FINDTEMPLATEFAILURE != uRet) + return uRet; + + uRet = OLEUI_SUCCESS; + + // Validate interface. + if (NULL == psA->lpOleUILinkContainer) + { + uRet = OLEUI_ELERR_LINKCNTRNULL; + } + else if(IsBadReadPtr(psA->lpOleUILinkContainer, sizeof(IOleUILinkContainerA))) + { + uRet = OLEUI_ELERR_LINKCNTRINVALID; + } + + if (OLEUI_SUCCESS != uRet) + { + return(uRet); + } + + + OLEUIEDITLINKSW sW; + WCHAR szCaption[MAX_PATH], szTemplate[MAX_PATH]; + uRet = OLEUI_ERR_LOCALMEMALLOC; + + memcpy(&sW, psA, sizeof(OLEUIEDITLINKSW)); + if (psA->lpszCaption) + { + ATOW(szCaption, psA->lpszCaption, MAX_PATH); + sW.lpszCaption = szCaption; + } + if (0 != HIWORD(psA->lpszTemplate)) + { + ATOW(szTemplate, psA->lpszTemplate, MAX_PATH); + sW.lpszTemplate = szTemplate; + } + + sW.lpOleUILinkContainer = new WrappedIOleUILinkContainer(psA->lpOleUILinkContainer); + if (NULL == sW.lpOleUILinkContainer) + { + return(uRet); + } + + uRet = OleUIEditLinksW(&sW); + + psA->dwFlags = sW.dwFlags; + sW.lpOleUILinkContainer->Release(); + return(uRet); +} + +//+--------------------------------------------------------------------------- +// +// Function: OleUIChangeIconA +// +// Synopsis: converts call to ANSI version into call to Unicode version +// +// Arguments: [psA] - ANSI structure +// +// History: 11-04-94 stevebl Created +// +// Structure members converted or passed back out (everything is passed in): +// lpszCaption [in] on stack +// lpszTemplate [in] on stack +// szIconExe [in] array embedded in structure +// dwFlags [out] +// hMetaPict [out] +// +//---------------------------------------------------------------------------- + +STDAPI_(UINT) OleUIChangeIconA(LPOLEUICHANGEICONA psA) +{ + UINT uRet = UStandardValidation((LPOLEUISTANDARD)psA, sizeof(*psA), NULL); + + // If the caller is using a private template, UStandardValidation will + // always return OLEUI_ERR_FINDTEMPLATEFAILURE here. This is because we + // haven't converted the template name to UNICODE yet, so the + // FindResource call in UStandardValidation won't find the caller's + // template. This is OK for two reasons: (1) it's the last thing that + // UStandardValidation checks so by this time it's basically done its + // job, and (2) UStandardValidation will be called again when we forward + // this call on to the Unicode version. + if (OLEUI_SUCCESS != uRet && OLEUI_ERR_FINDTEMPLATEFAILURE != uRet) + return uRet; + + OLEUICHANGEICONW sW; + WCHAR szCaption[MAX_PATH], szTemplate[MAX_PATH]; + + memcpy(&sW, psA, sizeof(OLEUICHANGEICONA)); + + sW.cbStruct = sizeof(OLEUICHANGEICONW); + + if (psA->lpszCaption) + { + ATOW(szCaption, psA->lpszCaption, MAX_PATH); + sW.lpszCaption = szCaption; + } + if (0 != HIWORD(psA->lpszTemplate)) + { + ATOW(szTemplate, psA->lpszTemplate, MAX_PATH); + sW.lpszTemplate = szTemplate; + } + ATOW(sW.szIconExe, psA->szIconExe, MAX_PATH); + sW.cchIconExe = psA->cchIconExe; + + + uRet = OleUIChangeIconW(&sW); + + psA->dwFlags = sW.dwFlags; + psA->hMetaPict = sW.hMetaPict; + return(uRet); +} + +//+--------------------------------------------------------------------------- +// +// Function: OleUIConvertA +// +// Synopsis: converts a call to ANSI version into call to Unicode version +// +// Arguments: [psA] - ANSI structure +// +// History: 11-04-94 stevebl Created +// +// Structure members converted or passed back out (everything is passed in): +// lpszCaption [in] on stack +// lpszTemplate [in] on stack +// lpszUserType [in] on heap +// [out] always freed and returned as NULL +// lpszDefLabel [in] on heap +// lpszDefLabel [out] always freed and returned as NULL +// dwFlags [out] +// clsidNew [out] +// dvAspect [out] +// hMetaPict [out] +// +//---------------------------------------------------------------------------- + +STDAPI_(UINT) OleUIConvertA(LPOLEUICONVERTA psA) +{ + UINT uRet = UStandardValidation((LPOLEUISTANDARD)psA, sizeof(*psA), NULL); + + // If the caller is using a private template, UStandardValidation will + // always return OLEUI_ERR_FINDTEMPLATEFAILURE here. This is because we + // haven't converted the template name to UNICODE yet, so the + // FindResource call in UStandardValidation won't find the caller's + // template. This is OK for two reasons: (1) it's the last thing that + // UStandardValidation checks so by this time it's basically done its + // job, and (2) UStandardValidation will be called again when we forward + // this call on to the Unicode version. + if (OLEUI_SUCCESS != uRet && OLEUI_ERR_FINDTEMPLATEFAILURE != uRet) + return uRet; + + if ((NULL != psA->lpszUserType) + && (IsBadReadPtr(psA->lpszUserType, 1))) + return(OLEUI_CTERR_STRINGINVALID); + + if ( (NULL != psA->lpszDefLabel) + && (IsBadReadPtr(psA->lpszDefLabel, 1)) ) + return(OLEUI_CTERR_STRINGINVALID); + + OLEUICONVERTW sW; + WCHAR szCaption[MAX_PATH], szTemplate[MAX_PATH]; + uRet = OLEUI_ERR_LOCALMEMALLOC; + + memcpy(&sW, psA, sizeof(OLEUICONVERTW)); + if (psA->lpszCaption) + { + ATOW(szCaption, psA->lpszCaption, MAX_PATH); + sW.lpszCaption = szCaption; + } + if (0 != HIWORD(psA->lpszTemplate)) + { + ATOW(szTemplate, psA->lpszTemplate, MAX_PATH); + sW.lpszTemplate = szTemplate; + } + sW.lpszUserType = sW.lpszDefLabel = NULL; + if (psA->lpszUserType) + { + UINT uLen = ATOWLEN(psA->lpszUserType); + sW.lpszUserType = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (!sW.lpszUserType) + { + goto oom_error; + } + ATOW(sW.lpszUserType, psA->lpszUserType, uLen); + } + if (psA->lpszDefLabel) + { + UINT uLen = ATOWLEN(psA->lpszDefLabel); + sW.lpszDefLabel = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (!sW.lpszDefLabel) + { + goto oom_error; + } + ATOW(sW.lpszDefLabel, psA->lpszDefLabel, uLen); + } + + uRet = OleUIConvertW(&sW); + + psA->dwFlags = sW.dwFlags; + memcpy(&psA->clsidNew, &sW.clsidNew, sizeof(CLSID)); + psA->dvAspect = sW.dvAspect; + psA->hMetaPict = sW.hMetaPict; + psA->fObjectsIconChanged = sW.fObjectsIconChanged; +oom_error: + if (sW.lpszUserType) + { + OleStdFree((LPVOID)sW.lpszUserType); + } + if (sW.lpszDefLabel) + { + OleStdFree((LPVOID)sW.lpszDefLabel); + } + if (psA->lpszUserType) + { + OleStdFree((LPVOID)psA->lpszUserType); + psA->lpszUserType = NULL; + } + if (psA->lpszDefLabel) + { + OleStdFree((LPVOID)psA->lpszDefLabel); + psA->lpszDefLabel = NULL; + } + return(uRet); +} + +//+--------------------------------------------------------------------------- +// +// Function: OleUIBusyA +// +// Synopsis: converts call to ANSI version into call to Unicode version +// +// Arguments: [psA] - ANSI structure +// +// History: 11-04-94 stevebl Created +// +// Structure members converted or passed back out (everything is passed in): +// lpszCaption [in] on stack +// lpszTemplate [in] on stack +// dwFlags [out] +// +//---------------------------------------------------------------------------- + +STDAPI_(UINT) OleUIBusyA(LPOLEUIBUSYA psA) +{ + UINT uRet = UStandardValidation((LPOLEUISTANDARD)psA, sizeof(*psA), NULL); + + // If the caller is using a private template, UStandardValidation will + // always return OLEUI_ERR_FINDTEMPLATEFAILURE here. This is because we + // haven't converted the template name to UNICODE yet, so the + // FindResource call in UStandardValidation won't find the caller's + // template. This is OK for two reasons: (1) it's the last thing that + // UStandardValidation checks so by this time it's basically done its + // job, and (2) UStandardValidation will be called again when we forward + // this call on to the Unicode version. + if (OLEUI_SUCCESS != uRet && OLEUI_ERR_FINDTEMPLATEFAILURE != uRet) + return uRet; + + OLEUIBUSYW sW; + WCHAR szCaption[MAX_PATH], szTemplate[MAX_PATH]; + + memcpy(&sW, psA, sizeof(OLEUIBUSYW)); + if (psA->lpszCaption) + { + ATOW(szCaption, psA->lpszCaption, MAX_PATH); + sW.lpszCaption = szCaption; + } + if (0 != HIWORD(psA->lpszTemplate)) + { + ATOW(szTemplate, psA->lpszTemplate, MAX_PATH); + sW.lpszTemplate = szTemplate; + } + uRet = OleUIBusyW(&sW); + + psA->dwFlags = sW.dwFlags; + return(uRet); +} + +//+--------------------------------------------------------------------------- +// +// Function: OleUIUpdateLinksA +// +// Synopsis: converts call to ANSI version into call to Unicode version +// +// Arguments: [lpOleUILinkCntr] - [in] wrapped with Unicode version +// [hwndParent] - +// [lpszTitle] - [in] on stack +// [cLinks] - +// +// History: 11-04-94 stevebl Created +// +//---------------------------------------------------------------------------- + +STDAPI_(BOOL) OleUIUpdateLinksA(LPOLEUILINKCONTAINERA lpOleUILinkCntr, + HWND hwndParent, LPSTR lpszTitle, int cLinks) +{ + WrappedIOleUILinkContainer * lpWrappedOleUILinkCntr = NULL; + + if (NULL != lpszTitle && IsBadReadPtr(lpszTitle, 1)) + return(FALSE); + + if (NULL == lpOleUILinkCntr || IsBadReadPtr(lpOleUILinkCntr, sizeof(IOleUILinkContainerA))) + return(FALSE); + + lpWrappedOleUILinkCntr = new WrappedIOleUILinkContainer(lpOleUILinkCntr); + if (NULL == lpWrappedOleUILinkCntr) + return(FALSE); // ran out of memory + + WCHAR wszTitle[MAX_PATH]; + WCHAR *lpwszTitle; + if (lpszTitle) + { + ATOW(wszTitle, lpszTitle, MAX_PATH); + lpwszTitle = wszTitle; + } + else + lpwszTitle = NULL; + BOOL fReturn = OleUIUpdateLinksW(lpWrappedOleUILinkCntr, hwndParent, lpwszTitle, cLinks); + + lpWrappedOleUILinkCntr->Release(); + + return(fReturn); +} + +//+--------------------------------------------------------------------------- +// +// Class: WrappedIOleUIObjInfo +// +// Purpose: Wraps IOleUIObjInfoA with IOleUIObjInfoW methods +// so it can be passed on to Unicode methods within OLE2UI32. +// +// Interface: QueryInterface -- +// AddRef -- +// Release -- +// GetObjectInfo -- requires string conversion +// GetConvertInfo -- +// ConvertObject -- +// GetViewInfo -- +// SetViewInfo -- +// WrappedIOleUIObjInfo -- constructor +// ~WrappedIOleUIObjInfo -- destructor +// +// History: 11-08-94 stevebl Created +// +// Notes: This is a private interface wrapper. QueryInterface is not +// supported and the wrapped interface may not be used outside +// of the OLE2UI32 code. +// +//---------------------------------------------------------------------------- + +class WrappedIOleUIObjInfo: public IOleUIObjInfoW +{ +public: + // *** IUnknown methods *** // + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj); + STDMETHOD_(ULONG,AddRef) (THIS); + STDMETHOD_(ULONG,Release) (THIS); + + // *** extra for General Properties *** // + STDMETHOD(GetObjectInfo) (THIS_ DWORD dwObject, + DWORD FAR* lpdwObjSize, LPWSTR FAR* lplpszLabel, + LPWSTR FAR* lplpszType, LPWSTR FAR* lplpszShortType, + LPWSTR FAR* lplpszLocation); + STDMETHOD(GetConvertInfo) (THIS_ DWORD dwObject, + CLSID FAR* lpClassID, WORD FAR* lpwFormat, + CLSID FAR* lpConvertDefaultClassID, + LPCLSID FAR* lplpClsidExclude, UINT FAR* lpcClsidExclude); + STDMETHOD(ConvertObject) (THIS_ DWORD dwObject, REFCLSID clsidNew); + + // *** extra for View Properties *** // + STDMETHOD(GetViewInfo) (THIS_ DWORD dwObject, + HGLOBAL FAR* phMetaPict, DWORD* pdvAspect, int* pnCurrentScale); + STDMETHOD(SetViewInfo) (THIS_ DWORD dwObject, + HGLOBAL hMetaPict, DWORD dvAspect, + int nCurrentScale, BOOL bRelativeToOrig); + // *** Constructor and Destructor *** // + WrappedIOleUIObjInfo(IOleUIObjInfoA * pioi); + ~WrappedIOleUIObjInfo(); +private: + IOleUIObjInfoA * m_pioi; + ULONG m_uRefCount; +}; + +// *** IUnknown methods *** // +HRESULT STDMETHODCALLTYPE WrappedIOleUIObjInfo::QueryInterface(THIS_ REFIID riid, LPVOID FAR* ppvObj) +{ + return(E_NOTIMPL); +} + +ULONG STDMETHODCALLTYPE WrappedIOleUIObjInfo::AddRef() +{ + return(m_uRefCount++); +} + +ULONG STDMETHODCALLTYPE WrappedIOleUIObjInfo::Release() +{ + ULONG uRet = --m_uRefCount; + if (0 == uRet) + { + delete(this); + } + return(uRet); +} + +//+--------------------------------------------------------------------------- +// +// Member: WrappedIOleUIObjInfo::GetObjectInfo +// +// Synopsis: forwards Unicode method call on to the ANSI version +// +// Arguments: [dwObject] - +// [lpdwObjSize] - +// [lplpszLabel] - [out] converted on heap +// [lplpszType] - [out] converted on heap +// [lplpszShortType] - [out] converted on heap +// [lplpszLocation] - [out] converted on heap +// +// History: 11-09-94 stevebl Created +// +//---------------------------------------------------------------------------- + +HRESULT STDMETHODCALLTYPE WrappedIOleUIObjInfo::GetObjectInfo(DWORD dwObject, + DWORD FAR* lpdwObjSize, LPWSTR FAR* lplpszLabel, + LPWSTR FAR* lplpszType, LPWSTR FAR* lplpszShortType, + LPWSTR FAR* lplpszLocation) +{ + LPSTR lpszLabel = NULL; + LPSTR lpszType = NULL; + LPSTR lpszShortType = NULL; + LPSTR lpszLocation = NULL; + LPSTR * lplpszLabelA = NULL; + LPSTR * lplpszTypeA = NULL; + LPSTR * lplpszShortTypeA = NULL; + LPSTR * lplpszLocationA = NULL; + if (lplpszLabel) + { + lplpszLabelA = &lpszLabel; + } + if (lplpszType) + { + lplpszTypeA = &lpszType; + } + if (lplpszShortType) + { + lplpszShortTypeA = &lpszShortType; + } + if (lplpszLocation) + { + lplpszLocationA = &lpszLocation; + } + HRESULT hrReturn = m_pioi->GetObjectInfo(dwObject, + lpdwObjSize, + lplpszLabelA, + lplpszTypeA, + lplpszShortTypeA, + lplpszLocationA); + if (lplpszLabel) + { + *lplpszLabel = NULL; + if (lpszLabel) + { + UINT uLen = ATOWLEN(lpszLabel); + *lplpszLabel = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (*lplpszLabel) + { + ATOW(*lplpszLabel, lpszLabel, uLen); + } + else + hrReturn = E_OUTOFMEMORY; + OleStdFree((LPVOID)lpszLabel); + } + } + if (lplpszType) + { + *lplpszType = NULL; + if (lpszType) + { + UINT uLen = ATOWLEN(lpszType); + *lplpszType = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (*lplpszType) + { + ATOW(*lplpszType, lpszType, uLen); + } + else + hrReturn = E_OUTOFMEMORY; + OleStdFree((LPVOID)lpszType); + } + } + if (lplpszShortType) + { + *lplpszShortType = NULL; + if (lpszShortType) + { + UINT uLen = ATOWLEN(lpszShortType); + *lplpszShortType = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (*lplpszShortType) + { + ATOW(*lplpszShortType, lpszShortType, uLen); + } + else + hrReturn = E_OUTOFMEMORY; + OleStdFree((LPVOID)lpszShortType); + } + } + if (lplpszLocation) + { + *lplpszLocation = NULL; + if (lpszLocation) + { + UINT uLen = ATOWLEN(lpszLocation); + *lplpszLocation = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (*lplpszLocation) + { + ATOW(*lplpszLocation, lpszLocation, uLen); + } + else + hrReturn = E_OUTOFMEMORY; + OleStdFree((LPVOID)lpszLocation); + } + } + return(hrReturn); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUIObjInfo::GetConvertInfo(DWORD dwObject, + CLSID FAR* lpClassID, WORD FAR* lpwFormat, + CLSID FAR* lpConvertDefaultClassID, + LPCLSID FAR* lplpClsidExclude, UINT FAR* lpcClsidExclude) +{ + return(m_pioi->GetConvertInfo(dwObject, + lpClassID, + lpwFormat, + lpConvertDefaultClassID, + lplpClsidExclude, + lpcClsidExclude)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUIObjInfo::ConvertObject(DWORD dwObject, REFCLSID clsidNew) +{ + return(m_pioi->ConvertObject(dwObject, clsidNew)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUIObjInfo::GetViewInfo(DWORD dwObject, + HGLOBAL FAR* phMetaPict, DWORD* pdvAspect, int* pnCurrentScale) +{ + return(m_pioi->GetViewInfo(dwObject, phMetaPict, pdvAspect, pnCurrentScale)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUIObjInfo::SetViewInfo(DWORD dwObject, + HGLOBAL hMetaPict, DWORD dvAspect, + int nCurrentScale, BOOL bRelativeToOrig) +{ + return(m_pioi->SetViewInfo(dwObject, hMetaPict, dvAspect, nCurrentScale, bRelativeToOrig)); +} + +WrappedIOleUIObjInfo::WrappedIOleUIObjInfo(IOleUIObjInfoA *pioi) +{ + m_pioi = pioi; + m_pioi->AddRef(); + m_uRefCount=1; +} + +WrappedIOleUIObjInfo::~WrappedIOleUIObjInfo() +{ + m_pioi->Release(); +} + + +//+--------------------------------------------------------------------------- +// +// Class: WrappedIOleUILinkInfo +// +// Purpose: Wraps IOleUILinkInfoA with IOleUILinkInfoW methods +// so it can be passed on to Unicode methods within OLE2UI32. +// +// Interface: QueryInterface -- +// AddRef -- +// Release -- +// GetNextLink -- +// SetLinkUpdateOptions -- +// GetLinkUpdateOptions -- +// SetLinkSource -- requires string conversion +// GetLinkSource -- requires string conversion +// OpenLinkSource -- +// UpdateLink -- +// CancelLink -- +// GetLastUpdate -- +// WrappedIOleUILinkInfo -- constructor +// ~WrappedIOleUILinkInfo -- destructor +// +// History: 11-08-94 stevebl Created +// +// Notes: This is a private interface wrapper. QueryInterface is not +// supported and the wrapped interface may not be used outside +// of the OLE2UI32 code. +// +//---------------------------------------------------------------------------- + +class WrappedIOleUILinkInfo: public IOleUILinkInfoW +{ +public: + // *** IUnknown methods *** // + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj); + STDMETHOD_(ULONG,AddRef) (THIS); + STDMETHOD_(ULONG,Release) (THIS); + + // *** IOleUILinkContainer *** // + STDMETHOD_(DWORD,GetNextLink) (THIS_ DWORD dwLink); + STDMETHOD(SetLinkUpdateOptions) (THIS_ DWORD dwLink, + DWORD dwUpdateOpt); + STDMETHOD(GetLinkUpdateOptions) (THIS_ DWORD dwLink, + DWORD FAR* lpdwUpdateOpt); + STDMETHOD(SetLinkSource) (THIS_ DWORD dwLink, LPWSTR lpszDisplayName, + ULONG lenFileName, ULONG FAR* pchEaten, BOOL fValidateSource); + STDMETHOD(GetLinkSource) (THIS_ DWORD dwLink, + LPWSTR FAR* lplpszDisplayName, ULONG FAR* lplenFileName, + LPWSTR FAR* lplpszFullLinkType, LPWSTR FAR* lplpszShortLinkType, + BOOL FAR* lpfSourceAvailable, BOOL FAR* lpfIsSelected); + STDMETHOD(OpenLinkSource) (THIS_ DWORD dwLink); + STDMETHOD(UpdateLink) (THIS_ DWORD dwLink, + BOOL fErrorMessage, BOOL fErrorAction); + STDMETHOD(CancelLink) (THIS_ DWORD dwLink); + + // *** extra for Link Properties ***// + STDMETHOD(GetLastUpdate) (THIS_ DWORD dwLink, + FILETIME FAR* lpLastUpdate); + + // *** Constructor and Destructor *** // + WrappedIOleUILinkInfo(IOleUILinkInfoA *pili); + ~WrappedIOleUILinkInfo(); +private: + IOleUILinkInfoA * m_pili; + ULONG m_uRefCount; +}; + +// *** IUnknown methods *** // +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkInfo::QueryInterface(THIS_ REFIID riid, LPVOID FAR* ppvObj) +{ + return(E_NOTIMPL); +} + +ULONG STDMETHODCALLTYPE WrappedIOleUILinkInfo::AddRef() +{ + return(m_uRefCount++); +} + +ULONG STDMETHODCALLTYPE WrappedIOleUILinkInfo::Release() +{ + ULONG uRet = --m_uRefCount; + if (0 == uRet) + { + delete(this); + } + return(uRet); +} + +// *** IOleUILinkInfo *** // +DWORD STDMETHODCALLTYPE WrappedIOleUILinkInfo::GetNextLink(DWORD dwLink) +{ + return(m_pili->GetNextLink(dwLink)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkInfo::SetLinkUpdateOptions (DWORD dwLink, + DWORD dwUpdateOpt) +{ + return(m_pili->SetLinkUpdateOptions(dwLink, dwUpdateOpt)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkInfo::GetLinkUpdateOptions (DWORD dwLink, + DWORD FAR* lpdwUpdateOpt) +{ + return(m_pili->GetLinkUpdateOptions(dwLink, lpdwUpdateOpt)); +} + +//+--------------------------------------------------------------------------- +// +// Member: WrappedIOleUILinkInfo::SetLinkSource +// +// Synopsis: forwards Unicode method call on to the ANSI version +// +// Arguments: [dwLink] - +// [lpszDisplayName] - [in] converted on stack +// [lenFileName] - +// [pchEaten] - +// [fValidateSource] - +// +// History: 11-04-94 stevebl Created +// +//---------------------------------------------------------------------------- + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkInfo::SetLinkSource (DWORD dwLink, LPWSTR lpszDisplayName, + ULONG lenFileName, ULONG FAR* pchEaten, BOOL fValidateSource) +{ + char szDisplayName[MAX_PATH]; + char * lpszDisplayNameA; + if (lpszDisplayName) + { + WTOA(szDisplayName, lpszDisplayName, MAX_PATH); + lpszDisplayNameA = szDisplayName; + } + else + lpszDisplayNameA = NULL; + + return(m_pili->SetLinkSource(dwLink, lpszDisplayNameA, lenFileName, pchEaten, fValidateSource)); +} + +//+--------------------------------------------------------------------------- +// +// Member: WrappedIOleUILinkInfo::GetLinkSource +// +// Synopsis: forwards Unicode method call on to the ANSI version +// +// Arguments: [dwLink] - +// [lplpszDisplayName] - [out] converted on heap +// [lplenFileName] - +// [lplpszFullLinkType] - [out] converted on heap +// [lplpszShortLinkType] - [out] converted on heap +// [lpfSourceAvailable] - +// [lpfIsSelected] - +// +// History: 11-04-94 stevebl Created +// +//---------------------------------------------------------------------------- + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkInfo::GetLinkSource (DWORD dwLink, + LPWSTR FAR* lplpszDisplayName, ULONG FAR* lplenFileName, + LPWSTR FAR* lplpszFullLinkType, LPWSTR FAR* lplpszShortLinkType, + BOOL FAR* lpfSourceAvailable, BOOL FAR* lpfIsSelected) +{ + LPSTR lpszDisplayName = NULL; + LPSTR lpszFullLinkType = NULL; + LPSTR lpszShortLinkType = NULL; + LPSTR * lplpszDisplayNameA = NULL; + LPSTR * lplpszFullLinkTypeA = NULL; + LPSTR * lplpszShortLinkTypeA = NULL; + if (lplpszDisplayName) + { + lplpszDisplayNameA = &lpszDisplayName; + } + if (lplpszFullLinkType) + { + lplpszFullLinkTypeA = &lpszFullLinkType; + } + if (lplpszShortLinkType) + { + lplpszShortLinkTypeA = &lpszShortLinkType; + } + HRESULT hrReturn = m_pili->GetLinkSource(dwLink, + lplpszDisplayNameA, + lplenFileName, + lplpszFullLinkTypeA, + lplpszShortLinkTypeA, + lpfSourceAvailable, + lpfIsSelected); + if (lplpszDisplayName) + { + *lplpszDisplayName = NULL; + if (lpszDisplayName) + { + UINT uLen = ATOWLEN(lpszDisplayName); + *lplpszDisplayName = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (*lplpszDisplayName) + { + ATOW(*lplpszDisplayName, lpszDisplayName, uLen); + } + else + hrReturn = E_OUTOFMEMORY; + OleStdFree((LPVOID)lpszDisplayName); + } + } + if (lplpszFullLinkType) + { + *lplpszFullLinkType = NULL; + if (lpszFullLinkType) + { + UINT uLen = ATOWLEN(lpszFullLinkType); + *lplpszFullLinkType = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (*lplpszFullLinkType) + { + ATOW(*lplpszFullLinkType, lpszFullLinkType, uLen); + } + else + hrReturn = E_OUTOFMEMORY; + OleStdFree((LPVOID)lpszFullLinkType); + } + } + if (lplpszShortLinkType) + { + *lplpszShortLinkType = NULL; + if (lpszShortLinkType) + { + UINT uLen = ATOWLEN(lpszShortLinkType); + *lplpszShortLinkType = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (*lplpszShortLinkType) + { + ATOW(*lplpszShortLinkType, lpszShortLinkType, uLen); + } + else + hrReturn = E_OUTOFMEMORY; + OleStdFree((LPVOID)lpszShortLinkType); + } + } + return(hrReturn); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkInfo::OpenLinkSource (DWORD dwLink) +{ + return(m_pili->OpenLinkSource(dwLink)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkInfo::UpdateLink (DWORD dwLink, + BOOL fErrorMessage, BOOL fErrorAction) +{ + return(m_pili->UpdateLink(dwLink, fErrorMessage, fErrorAction)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkInfo::CancelLink (DWORD dwLink) +{ + return(m_pili->CancelLink(dwLink)); +} + +HRESULT STDMETHODCALLTYPE WrappedIOleUILinkInfo::GetLastUpdate (DWORD dwLink, + FILETIME FAR* lpLastUpdate) +{ + return(m_pili->GetLastUpdate(dwLink, lpLastUpdate)); +} + +WrappedIOleUILinkInfo::WrappedIOleUILinkInfo(IOleUILinkInfoA *pili) +{ + m_pili = pili; + m_pili->AddRef(); + m_uRefCount=1; +} + +WrappedIOleUILinkInfo::~WrappedIOleUILinkInfo() +{ + m_pili->Release(); +} + + +//+--------------------------------------------------------------------------- +// +// Function: OleUIObjectPropertiesA +// +// Synopsis: converts call to ANSI version into call to Unicode version +// +// Arguments: [psA] - ANSI structure +// +// History: 11-04-94 stevebl Created +// +// Structure members converted or passed back out (everything is passed in): +// lpPS [in] +// lpObjInfo [in] wrapped with Unicode interface +// lpLinkInfo [in] wrapped with Unicode interface +// lpGP [in] (no data conversion, only type conversion) +// lpVP [in] (no data conversion, only type conversion) +// lpLP [in] (no data conversion, only type conversion) +// +// dwFlags [out] +// +//---------------------------------------------------------------------------- + +STDAPI_(UINT) OleUIObjectPropertiesA(LPOLEUIOBJECTPROPSA psA) +{ + if (NULL == psA) + { + return(OLEUI_ERR_STRUCTURENULL); + } + + if (IsBadWritePtr(psA, sizeof(OLEUIOBJECTPROPSA))) + return OLEUI_ERR_STRUCTUREINVALID; + + LPOLEUIOBJECTPROPSW psW; + UINT uRet = OLEUI_ERR_LOCALMEMALLOC; + + if (NULL == psA->lpObjInfo) + { + return(OLEUI_OPERR_OBJINFOINVALID); + } + + if (IsBadReadPtr(psA->lpObjInfo, sizeof(IOleUIObjInfoA))) + { + return(OLEUI_OPERR_OBJINFOINVALID); + } + + if (psA->dwFlags & OPF_OBJECTISLINK) + { + if (NULL == psA->lpLinkInfo) + { + return(OLEUI_OPERR_LINKINFOINVALID); + } + + if (IsBadReadPtr(psA->lpLinkInfo, sizeof(IOleUILinkInfoA))) + { + return(OLEUI_OPERR_LINKINFOINVALID); + } + } + + BOOL fWrappedIOleUILinkInfo = FALSE; + psW = (LPOLEUIOBJECTPROPSW) OleStdMalloc(sizeof(OLEUIOBJECTPROPSW)); + if (NULL != psW) + { + memcpy(psW, psA, sizeof(OLEUIOBJECTPROPSW)); + psW->lpObjInfo = new WrappedIOleUIObjInfo(psA->lpObjInfo); + if (NULL == psW->lpObjInfo) + { + OleStdFree(psW); + return(uRet); + } + if (psW->dwFlags & OPF_OBJECTISLINK) + { + psW->lpLinkInfo = new WrappedIOleUILinkInfo(psA->lpLinkInfo); + if (NULL == psW->lpLinkInfo) + { + psW->lpObjInfo->Release(); + OleStdFree(psW); + return(uRet); + } + fWrappedIOleUILinkInfo = TRUE; + } + uRet = InternalObjectProperties(psW, FALSE); + psA->dwFlags = psW->dwFlags; + psW->lpObjInfo->Release(); + if (fWrappedIOleUILinkInfo) + { + psW->lpLinkInfo->Release(); + } + OleStdFree(psW); + } + return(uRet); +} + +//+--------------------------------------------------------------------------- +// +// Function: OleUIChangeSourceA +// +// Synopsis: converts call to ANSI version into call to Unicode version +// +// Arguments: [psA] - ANSI structure +// +// History: 11-04-94 stevebl Created +// +// Structure members converted or passed back out (everything is passed in): +// lpszCaption [in] on stack +// lpszTemplate [in] on stack +// lpszDisplayName [in, out] on heap +// lpszFrom [out] on heap +// lpszTo [out] on heap +// lpOleUILinkContainer [in] wrapped interface +// dwFlags [out] +// nFileLength [out] +// +//---------------------------------------------------------------------------- + +STDAPI_(UINT) OleUIChangeSourceA(LPOLEUICHANGESOURCEA psA) +{ + UINT uRet = UStandardValidation((LPOLEUISTANDARD)psA, sizeof(*psA), NULL); + + // If the caller is using a private template, UStandardValidation will + // always return OLEUI_ERR_FINDTEMPLATEFAILURE here. This is because we + // haven't converted the template name to UNICODE yet, so the + // FindResource call in UStandardValidation won't find the caller's + // template. This is OK for two reasons: (1) it's the last thing that + // UStandardValidation checks so by this time it's basically done its + // job, and (2) UStandardValidation will be called again when we forward + // this call on to the Unicode version. + if (OLEUI_SUCCESS != uRet && OLEUI_ERR_FINDTEMPLATEFAILURE != uRet) + return uRet; + + // lpszFrom and lpszTo must be NULL (they are out only) + if (psA->lpszFrom != NULL) + { + return(OLEUI_CSERR_FROMNOTNULL); + } + if (psA->lpszTo != NULL) + { + return(OLEUI_CSERR_TONOTNULL); + } + + // lpszDisplayName must be valid or NULL + if (psA->lpszDisplayName != NULL && + IsBadReadPtr(psA->lpszDisplayName, 1)) + { + return(OLEUI_CSERR_SOURCEINVALID); + } + + OLEUICHANGESOURCEW sW; + WCHAR szCaption[MAX_PATH], szTemplate[MAX_PATH]; + uRet = OLEUI_ERR_LOCALMEMALLOC; + + memcpy(&sW, psA, sizeof(OLEUICHANGESOURCEW)); + if (psA->lpszCaption != NULL) + { + ATOW(szCaption, psA->lpszCaption, MAX_PATH); + sW.lpszCaption = szCaption; + } + if (0 != HIWORD(psA->lpszTemplate)) + { + ATOW(szTemplate, psA->lpszTemplate, MAX_PATH); + sW.lpszTemplate = szTemplate; + } + if (psA->lpszDisplayName) + { + UINT uLen = ATOWLEN(psA->lpszDisplayName); + sW.lpszDisplayName = (LPWSTR)OleStdMalloc(uLen * sizeof(WCHAR)); + if (!sW.lpszDisplayName) + { + return(uRet); + } + ATOW(sW.lpszDisplayName, psA->lpszDisplayName, uLen); + } + if (NULL != psA->lpOleUILinkContainer) + { + if (IsBadReadPtr(psA->lpOleUILinkContainer, sizeof(IOleUILinkContainerA))) + { + return(OLEUI_CSERR_LINKCNTRINVALID); + } + sW.lpOleUILinkContainer = new WrappedIOleUILinkContainer(psA->lpOleUILinkContainer); + if (NULL == sW.lpOleUILinkContainer) + { + return(uRet); + } + } + + uRet = OleUIChangeSourceW(&sW); + if (psA->lpszDisplayName) + { + OleStdFree((LPVOID)psA->lpszDisplayName); + psA->lpszDisplayName = NULL; + } + if (sW.lpszDisplayName) + { + UINT uLen = WTOALEN(sW.lpszDisplayName); + psA->lpszDisplayName = (LPSTR)OleStdMalloc(uLen * sizeof(char)); + if (!psA->lpszDisplayName) + { + uRet = OLEUI_ERR_LOCALMEMALLOC; + } + else + { + WTOA(psA->lpszDisplayName, sW.lpszDisplayName, uLen); + } + OleStdFree((LPVOID)sW.lpszDisplayName); + } + if (sW.lpszFrom) + { + UINT uLen = WTOALEN(sW.lpszFrom); + psA->lpszFrom = (LPSTR)OleStdMalloc(uLen * sizeof(char)); + if (!psA->lpszFrom) + { + uRet = OLEUI_ERR_LOCALMEMALLOC; + } + else + { + WTOA(psA->lpszFrom, sW.lpszFrom, uLen); + } + OleStdFree((LPVOID)sW.lpszFrom); + } + if (sW.lpszTo) + { + UINT uLen = WTOALEN(sW.lpszTo); + psA->lpszTo = (LPSTR)OleStdMalloc(uLen * sizeof(char)); + if (!psA->lpszTo) + { + uRet = OLEUI_ERR_LOCALMEMALLOC; + } + else + { + WTOA(psA->lpszTo, sW.lpszTo, uLen); + } + OleStdFree((LPVOID)sW.lpszTo); + } + psA->dwFlags = sW.dwFlags; + psA->nFileLength = sW.nFileLength; + if (NULL != sW.lpOleUILinkContainer) + { + sW.lpOleUILinkContainer->Release(); + } + return(uRet); +} + +int OleUIPromptUserInternal(int nTemplate, HWND hwndParent, LPTSTR szTitle, va_list arglist); + +//+--------------------------------------------------------------------------- +// +// Function: OleUIPromptUserA +// +// Synopsis: converts call to ANSI version into call to Unicode version +// +// Arguments: [nTemplate] - template ID +// [hwndParent] - parent's HWND +// [lpszTitle] - title of the window +// [...] - variable argument list +// +// History: 11-30-94 stevebl Created +// +// Notes: The first parameter passed in by this function is always the +// title for the dialog. It must be converted to Unicode before +// forwarding the call. The other parameters do not need to +// be converted because the template ID will indicate the dialog +// that contains the correct wsprintf formatting string for +// converting the other ANSI parameters to Unicode when the +// function calls wsprintf to build it's text. +// +//---------------------------------------------------------------------------- + +int FAR CDECL OleUIPromptUserA(int nTemplate, HWND hwndParent, ...) +{ + WCHAR wszTemp[MAX_PATH]; + WCHAR * wszTitle = NULL; + va_list arglist; + va_start(arglist, hwndParent); + LPSTR szTitle = va_arg(arglist, LPSTR); + if (szTitle != NULL) + { + ATOW(wszTemp, szTitle, MAX_PATH); + wszTitle = wszTemp; + } + int nRet = OleUIPromptUserInternal(nTemplate, hwndParent, wszTitle, arglist); + va_end(arglist); + + return(nRet); +} + +#else // UNICODE not defined +// Stubbed out Wide entry points + +STDAPI_(BOOL) OleUIAddVerbMenuW(LPOLEOBJECT lpOleObj, LPCWSTR lpszShortType, + HMENU hMenu, UINT uPos, UINT uIDVerbMin, UINT uIDVerbMax, + BOOL bAddConvert, UINT idConvert, HMENU FAR *lphMenu) +{ + // BUGBUG - there is really no way to specify an error return code + return(FALSE); +} + +//+--------------------------------------------------------------------------- +// +// Function: ReturnError +// +// Synopsis: Used to stub out the following entry points: +// OleUIInsertObjectW +// OleUIPasteSpecialW +// OleUIEditLinksW +// OleUIChangeIconW +// OleUIConvertW +// OleUIBusyW +// OleUIObjectPropertiesW +// OleUIChangeSourceW +// +// Returns: OLEUI_ERR_DIALOGFAILURE +// +// History: 12-29-94 stevebl Created +// +// Notes: The entry points listed above are all mapped to this function +// in the Chicago version of OLEDLG.DEF. +// +//---------------------------------------------------------------------------- + +STDAPI_(UINT) ReturnError(void * p) +{ + return(OLEUI_ERR_DIALOGFAILURE); +} + +STDAPI_(BOOL) OleUIUpdateLinksW(LPOLEUILINKCONTAINERW lpOleUILinkCntr, + HWND hwndParent, LPWSTR lpszTitle, int cLinks) +{ + return(FALSE); +} + +int FAR CDECL OleUIPromptUserW(int nTemplate, HWND hwndParent, LPWSTR lpszTitle, ...) +{ + return(2); // same as if user had cancelled the dialog +} +#endif // UNICODE |