|
|
/*
* 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(PtrToUlong(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_PTR 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. */ // char szDebug[100];
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 hWndChild = (HWND)((LPHELPINFO)lParam)->hItemHandle; //skip read-only controls (requested by Help folks)
//basically the help strings for items like ObjectName on GnrlProps
//give useless information.
//If we do not make this check now the other option is to turn ON
//the #if 0 inside the switch. That is ugly.
if (hWndChild!=hDlg ) { int iCtrlId = ((LPHELPINFO)lParam)->iCtrlId; // wsprintfA(szDebug,"\n @@@ hWnd= %lx, hChld = %lx, ctrlId = %d ", hDlg, hWndChild, iCtrlId);
// OutputDebugStringA(szDebug);
switch (iCtrlId) { // list of control IDs that should not have help
case -1: //IDC_STATIC
case 0xffff: //IDC_STATIC
case IDC_CI_GROUP: case IDC_GP_OBJECTICON: break; default: StandardHelp(hWndChild, lpCommon->nIDD);
} } *puHookResult = TRUE; //We handled the message.
break; } //case WM_HELP
case WM_CONTEXTMENU: { POINT pt; int iCtrlId; HWND hwndChild = NULL; if( hDlg == (HWND) wParam ) { GetCursorPos(&pt); ScreenToClient(hDlg, &pt); hwndChild = ChildWindowFromPointEx(hDlg, pt, CWP_SKIPINVISIBLE); //hWndChild will now be either hDlg or hWnd of the ctrl
}
if ( hwndChild != hDlg ) { if (hwndChild) { iCtrlId = GetDlgCtrlID(hwndChild); } else { iCtrlId = GetDlgCtrlID((HWND)wParam); } // wsprintfA(szDebug, "\n ### hWnd= %lx, hChld = %lx, ctrlId = %d ", hDlg, hwndChild, iCtrlId);
// OutputDebugStringA(szDebug);
switch (iCtrlId) { // list of control IDs that should not have help
case -1: // IDC_STATIC
case 0xffff: // IDC_STATIC
case IDC_CI_GROUP: case IDC_GP_OBJECTICON: break; default: StandardContextMenu(wParam, lParam, lpCommon->nIDD); } }
*puHookResult = TRUE; //We handled the message.
break; } // case WM_CONTEXTMENU
case WM_CTLCOLOREDIT: { // make readonly edits have gray background
if (bWin4 && (GetWindowLong((HWND)lParam, GWL_STYLE) & ES_READONLY)) { *puHookResult = (UINT)SendMessage(hDlg, WM_CTLCOLORSTATIC, wParam, lParam); } break; } } //switch (iMsg)
} //*puHookResult == 0
} //NULL != puHookResult
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)RemoveProp(hDlg, FONTPROP); if (NULL != hFont) { DeleteObject(hFont); }
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
#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; } /*
int id=GetDlgCtrlID( hWnd); wsprintfA(szDebug,"\n HH @@@### hWnd= %lx, ctrlId = %d %lx", hWnd,id,id); OutputDebugStringA(szDebug); */ WinHelp(hWnd, HELPFILE, HELP_WM_HELP, (ULONG_PTR)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; } /*
int id=GetDlgCtrlID((HWND)wParam); wsprintfA(szDebug,"\n CC $$$*** hWnd= %lx, ctrlId = %d %lx ",(HWND)wParam,id,id); OutputDebugStringA(szDebug); */ WinHelp((HWND)wParam, HELPFILE, HELP_CONTEXTMENU, (ULONG_PTR)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; }
|