diff options
Diffstat (limited to 'private/ole2ui32/common.cpp')
-rw-r--r-- | private/ole2ui32/common.cpp | 685 |
1 files changed, 685 insertions, 0 deletions
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; +} + |