Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /****************************** Module Header ******************************\
- * Module Name: msgbox.c
- *
- * Copyright (c) 1985 - 1999, Microsoft Corporation
- *
- * This module contains the MessageBox API and related functions.
- *
- * History:
- * 10-23-90 DarrinM Created.
- * 02-08-91 IanJa HWND revalidation added
- \***************************************************************************/
- #include "precomp.h"
- #pragma hdrstop
- //
- // Dimension constants -- D.U. == dialog units
- //
- #define DU_OUTERMARGIN 7
- #define DU_INNERMARGIN 10
- #define DU_BTNGAP 4 // D.U. of space between buttons
- #define DU_BTNHEIGHT 14 // D.U. of button height
- // This is used only in kernel\inctlpan.c, so move it there
- //
- // #define DU_BTNWIDTH 50 // D.U. of button width, minimum
- //
- LPBYTE MB_UpdateDlgHdr(LPDLGTEMPLATE lpDlgTmp, long lStyle, long lExtendedStyle, BYTE bItemCount,
- int iX, int iY, int iCX, int iCY, LPWSTR lpszCaption, int iCaptionLen);
- LPBYTE MB_UpdateDlgItem(LPDLGITEMTEMPLATE lpDlgItem, int iCtrlId, long lStyle, long lExtendedStyle,
- int iX, int iY, int iCX, int iCY, LPWSTR lpszText, UINT wTextLen,
- int iControlClass);
- UINT MB_GetIconOrdNum(UINT rgBits);
- LPBYTE MB_AddPushButtons(
- LPDLGITEMTEMPLATE lpDlgTmp,
- LPMSGBOXDATA lpmb,
- UINT wLEdge,
- UINT wBEdge);
- UINT MB_FindDlgTemplateSize( LPMSGBOXDATA lpmb );
- int MessageBoxWorker(LPMSGBOXDATA pMsgBoxParams);
- VOID EndTaskModalDialog(HWND hwndDlg);
- VOID StartTaskModalDialog(HWND hwndDlg);
- #ifdef _JANUS_
- #include "strid.h"
- #include <imagehlp.h>
- // constant strings
- CONST WCHAR szEMIKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Error Message Instrument\\";
- CONST WCHAR szEMIEnable[] = L"EnableLogging";
- CONST WCHAR szEMISeverity[] = L"LogSeverity";
- CONST WCHAR szDMREnable[] = L"EnableDefaultReply";
- CONST WCHAR szEventKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\Application\\Error Instrument\\";
- CONST WCHAR szEventMsgFile[] = L"EventMessageFile";
- CONST WCHAR szEventType[] = L"TypesSupported";
- #define TITLE_SIZE 64
- #define DATETIME_SIZE 32
- #define EMI_SEVERITY_ALL 0
- #define EMI_SEVERITY_USER 1
- #define EMI_SEVERITY_INFORMATION 2
- #define EMI_SEVERITY_QUESTION 3
- #define EMI_SEVERITY_WARNING 4
- #define EMI_SEVERITY_ERROR 5
- #define EMI_SEVERITY_MAX_VALUE 5
- // element of error message
- PVOID gpReturnAddr = 0;
- HANDLE gdwEMIThreadID = 0;
- typedef struct _ERROR_ELEMENT {
- WCHAR ProcessName[MAX_PATH];
- WCHAR WindowTitle[TITLE_SIZE];
- DWORD dwStyle;
- DWORD dwErrorCode;
- WCHAR CallerModuleName[MAX_PATH];
- PVOID BaseAddr;
- DWORD dwImageSize;
- PVOID ReturnAddr;
- LPWSTR lpszCaption;
- LPWSTR lpszText;
- } ERROR_ELEMENT, *LPERROR_ELEMENT;
- BOOL ErrorMessageInst(LPMSGBOXDATA pMsgBoxParams);
- BOOL InitInstrument(LPDWORD lpEMIControl);
- // eventlog stuff
- HANDLE gEventSource;
- NTSTATUS CreateLogSource();
- BOOL LogMessageBox(LPERROR_ELEMENT lpErrEle);
- #define EMIGETRETURNADDRESS() \
- { \
- if (gfEMIEnable) { \
- if (InterlockedCompareExchangePointer(&gdwEMIThreadID, \
- GETTHREADID(), \
- 0) \
- == 0) { \
- gpReturnAddr = (PVOID) 1; \
- } \
- } \
- }
- // _ReturnAddress();
- #else
- #define EMIGETRETURNADDRESS()
- #endif //_JANUS_
- #define MB_MASKSHIFT 4
- static CONST WCHAR szEmpty[] = L"";
- WCHAR szERROR[10];
- /***************************************************************************\
- * SendHelpMessage
- *
- *
- \***************************************************************************/
- VOID
- SendHelpMessage(
- HWND hwnd,
- int iType,
- int iCtrlId,
- HANDLE hItemHandle,
- DWORD dwContextId,
- MSGBOXCALLBACK lpfnCallback)
- {
- HELPINFO HelpInfo;
- long lValue;
- HelpInfo.cbSize = sizeof(HELPINFO);
- HelpInfo.iContextType = iType;
- HelpInfo.iCtrlId = iCtrlId;
- HelpInfo.hItemHandle = hItemHandle;
- HelpInfo.dwContextId = dwContextId;
- lValue = NtUserGetMessagePos();
- HelpInfo.MousePos.x = GET_X_LPARAM(lValue);
- HelpInfo.MousePos.y = GET_Y_LPARAM(lValue);
- // Check if there is an app supplied callback.
- if (lpfnCallback != NULL) {
- if (IsWOWProc(lpfnCallback)) {
- (*pfnWowMsgBoxIndirectCallback)(PtrToUlong(lpfnCallback), &HelpInfo);
- } else {
- (*lpfnCallback)(&HelpInfo);
- }
- } else {
- SendMessage(hwnd, WM_HELP, 0, (LPARAM)&HelpInfo);
- }
- }
- /***************************************************************************\
- * ServiceMessageBox
- *
- *
- \***************************************************************************/
- CONST int aidReturn[] = { 0, 0, IDABORT, IDCANCEL, IDIGNORE, IDNO, IDOK, IDRETRY, IDYES };
- int ServiceMessageBox(
- LPCWSTR pText,
- LPCWSTR pCaption,
- UINT wType,
- DWORD dwTimeout)
- {
- NTSTATUS Status;
- ULONG_PTR Parameters[4];
- ULONG Response = ResponseNotHandled;
- UNICODE_STRING Text, Caption;
- /*
- * For Terminal Services we must decided the session in which this message
- * box should be displayed. We do this by looking at the impersonation token
- * and use the session on which the client is running.
- */
- if (ISTS()) {
- HANDLE TokenHandle;
- ULONG ClientSessionId;
- ULONG ProcessSessionId;
- ULONG ReturnLength;
- BOOLEAN bResult;
- /*
- * Obtain access to the impersonation token if it's present.
- */
- Status = NtOpenThreadToken (
- GetCurrentThread(),
- TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
- TRUE,
- &TokenHandle
- );
- if (NT_SUCCESS(Status)) {
- /*
- * Query the Session ID out of the Token
- */
- Status = NtQueryInformationToken (
- TokenHandle,
- TokenSessionId,
- (PVOID)&ClientSessionId,
- sizeof(ClientSessionId),
- &ReturnLength
- );
- CloseHandle(TokenHandle);
- if (NT_SUCCESS(Status)) {
- /*
- * Get the process session Id. Use the Kernel32 API first because
- * the PEB is writable in case someone is hacking it.
- */
- if (!ProcessIdToSessionId(GetCurrentProcessId(), &ProcessSessionId)) {
- ProcessSessionId = NtCurrentPeb()->SessionId;
- }
- if (ClientSessionId != ProcessSessionId) {
- /*
- * This message box was intended for session other than the
- * one on which this process is running. Forward it to the
- * right session with WinStationSendMessage().
- */
- /*
- * Handle case where Caption or Title is NULL
- */
- if (pCaption == NULL) {
- pCaption = szEmpty;
- }
- if (pText == NULL) {
- pText = szEmpty;
- }
- /*
- * MessageBoxTimeout assumes the timeout value is in milliseconds,
- * but WinStationSendMessageW uses seconds.
- */
- if (dwTimeout != INFINITE) {
- dwTimeout /= 1000;
- }
- bResult = WinStationSendMessageW(SERVERNAME_CURRENT,
- ClientSessionId,
- (LPWSTR)pCaption,
- wcslen(pCaption) * sizeof(WCHAR),
- (LPWSTR)pText,
- wcslen(pText) * sizeof(WCHAR),
- wType,
- dwTimeout,
- &Response,
- FALSE // always wait
- );
- if (bResult != TRUE) {
- Response = aidReturn[ResponseNotHandled];
- } else {
- if (Response == IDTIMEOUT || Response == IDERROR) {
- Response = aidReturn[ResponseNotHandled];
- }
- }
- return (int)Response;
- }
- }
- }
- }
- /*
- * MessageBox is for this session, go call CSR.
- */
- RtlInitUnicodeString(&Text, pText);
- RtlInitUnicodeString(&Caption, pCaption);
- Parameters[0] = (ULONG_PTR)&Text;
- Parameters[1] = (ULONG_PTR)&Caption;
- Parameters[2] = wType;
- Parameters[3] = dwTimeout;
- /*
- * Compatibility: Pass the override bit to make sure this box always shows
- */
- Status = NtRaiseHardError(STATUS_SERVICE_NOTIFICATION | HARDERROR_OVERRIDE_ERRORMODE,
- ARRAY_SIZE(Parameters),
- 3,
- Parameters,
- OptionOk,
- &Response);
- if (!NT_SUCCESS(Status)) {
- RIPNTERR0(Status, RIP_VERBOSE, "");
- }
- return aidReturn[Response];
- }
- /***************************************************************************\
- * MessageBox (API)
- *
- * History:
- * 11-20-90 DarrinM Ported from Win 3.0 sources.
- \***************************************************************************/
- int MessageBoxA(
- HWND hwndOwner,
- LPCSTR lpszText,
- LPCSTR lpszCaption,
- UINT wStyle)
- {
- EMIGETRETURNADDRESS();
- return MessageBoxExA(hwndOwner, lpszText, lpszCaption, wStyle, 0);
- }
- int MessageBoxW(
- HWND hwndOwner,
- LPCWSTR lpszText,
- LPCWSTR lpszCaption,
- UINT wStyle)
- {
- EMIGETRETURNADDRESS();
- return MessageBoxExW(hwndOwner, lpszText, lpszCaption, wStyle, 0);
- }
- /***************************************************************************\
- * MessageBoxEx (API)
- *
- * History:
- * 11-20-90 DarrinM Ported from Win 3.0 sources.
- \***************************************************************************/
- int MessageBoxExA(
- HWND hwndOwner,
- LPCSTR lpszText,
- LPCSTR lpszCaption,
- UINT wStyle,
- WORD wLanguageId)
- {
- return MessageBoxTimeoutA(hwndOwner,
- lpszText,
- lpszCaption,
- wStyle,
- wLanguageId,
- INFINITE);
- }
- int MessageBoxExW(
- HWND hwndOwner,
- LPCWSTR lpszText,
- LPCWSTR lpszCaption,
- UINT wStyle,
- WORD wLanguageId)
- {
- return MessageBoxTimeoutW(hwndOwner,
- lpszText,
- lpszCaption,
- wStyle,
- wLanguageId,
- INFINITE);
- }
- /***************************************************************************\
- * MessageBoxTimeout (API)
- *
- * History:
- * 04-28-2001 JasonSch Wrote it.
- \***************************************************************************/
- int MessageBoxTimeoutW(
- HWND hwndOwner,
- LPCWSTR lpszText,
- LPCWSTR lpszCaption,
- UINT wStyle,
- WORD wLanguageId,
- DWORD dwTimeout)
- {
- MSGBOXDATA MsgBoxParams;
- #if DBG
- /*
- * MB_USERICON is valid for MessageBoxIndirect only.
- * MessageBoxWorker validates the other style bits
- */
- if (wStyle & MB_USERICON) {
- RIPMSG0(RIP_WARNING, "MessageBoxExW: Invalid flag: MB_USERICON");
- }
- #endif
- RtlZeroMemory(&MsgBoxParams, sizeof(MsgBoxParams));
- MsgBoxParams.cbSize = sizeof(MSGBOXPARAMS);
- MsgBoxParams.hwndOwner = hwndOwner;
- MsgBoxParams.hInstance = NULL;
- MsgBoxParams.lpszText = lpszText;
- MsgBoxParams.lpszCaption = lpszCaption;
- MsgBoxParams.dwStyle = wStyle;
- MsgBoxParams.wLanguageId = wLanguageId;
- MsgBoxParams.dwTimeout = dwTimeout;
- EMIGETRETURNADDRESS();
- return MessageBoxWorker(&MsgBoxParams);
- }
- int MessageBoxTimeoutA(
- HWND hwndOwner,
- LPCSTR lpszText,
- LPCSTR lpszCaption,
- UINT wStyle,
- WORD wLanguageId,
- DWORD dwTimeout)
- {
- int retval;
- LPWSTR lpwszText = NULL;
- LPWSTR lpwszCaption = NULL;
- if (lpszText) {
- if (!MBToWCS(lpszText, -1, &lpwszText, -1, TRUE))
- return 0;
- }
- if (lpszCaption) {
- if (!MBToWCS(lpszCaption, -1, &lpwszCaption, -1, TRUE)) {
- UserLocalFree(lpwszText);
- return 0;
- }
- }
- EMIGETRETURNADDRESS();
- retval = MessageBoxTimeoutW(hwndOwner,
- lpwszText,
- lpwszCaption,
- wStyle,
- wLanguageId,
- dwTimeout);
- UserLocalFree(lpwszText);
- if (lpwszCaption) {
- UserLocalFree(lpwszCaption);
- }
- return retval;
- }
- #define MessageBoxIndirectInit(MsgBoxParams, lpmbp) \
- do { \
- if (lpmbp->cbSize != sizeof(MSGBOXPARAMS)) { \
- RIPMSG1(RIP_WARNING, \
- "MessageBoxIndirect: Invalid cbSize 0x%x", \
- lpmbp->cbSize); \
- } \
- \
- RtlZeroMemory(&MsgBoxParams, sizeof(MSGBOXDATA)); \
- RtlCopyMemory(&MsgBoxParams, lpmbp, sizeof(MSGBOXPARAMS)); \
- } while (FALSE);
- /**************************************************************************\
- * MessageBoxIndirect (API)
- *
- * 09-30-1994 FritzS Created.
- \**************************************************************************/
- int MessageBoxIndirectA(
- CONST MSGBOXPARAMSA *lpmbp)
- {
- int retval;
- MSGBOXDATA MsgBoxParams;
- LPWSTR lpwszText = NULL;
- LPWSTR lpwszCaption = NULL;
- MessageBoxIndirectInit(MsgBoxParams, lpmbp);
- if (IS_PTR(MsgBoxParams.lpszText)) {
- if (!MBToWCS((LPSTR)MsgBoxParams.lpszText, -1, &lpwszText, -1, TRUE)) {
- return 0;
- }
- MsgBoxParams.lpszText = lpwszText;
- }
- if (IS_PTR(MsgBoxParams.lpszCaption)) {
- if (!MBToWCS((LPSTR)MsgBoxParams.lpszCaption, -1, &lpwszCaption, -1, TRUE)) {
- UserLocalFree(lpwszText);
- return 0;
- }
- MsgBoxParams.lpszCaption = lpwszCaption;
- }
- EMIGETRETURNADDRESS();
- retval = MessageBoxWorker(&MsgBoxParams);
- if (lpwszText) {
- UserLocalFree(lpwszText);
- }
- if (lpwszCaption) {
- UserLocalFree(lpwszCaption);
- }
- return retval;
- }
- int MessageBoxIndirectW(
- CONST MSGBOXPARAMSW *lpmbp)
- {
- MSGBOXDATA MsgBoxParams;
- MessageBoxIndirectInit(MsgBoxParams, lpmbp);
- EMIGETRETURNADDRESS();
- return MessageBoxWorker(&MsgBoxParams);
- }
- /***************************************************************************\
- * MessageBoxWorker (API)
- *
- * History:
- * 03-10-93 JohnL Created
- \***************************************************************************/
- int MessageBoxWorker(
- LPMSGBOXDATA pMsgBoxParams)
- {
- DWORD dwStyle = pMsgBoxParams->dwStyle;
- UINT wBtnCnt;
- UINT wDefButton;
- UINT i;
- UINT wBtnBeg;
- WCHAR szErrorBuf[64];
- LPWSTR apstrButton[4];
- int aidButton[4];
- BOOL fCancel = FALSE;
- int retValue;
- PMBSTRING pMBString;
- #if DBG
- if (dwStyle & ~MB_VALID) {
- RIPMSG2(RIP_WARNING, "MessageBoxWorker: Invalid flags, %#lx & ~%#lx != 0",
- dwStyle, MB_VALID);
- }
- #endif
- /*
- * dwTimeout == 0 means wait forever. This is mostly for compat reasons.
- */
- if (pMsgBoxParams->dwTimeout == 0) {
- pMsgBoxParams->dwTimeout = INFINITE;
- }
- /*
- * Be sure that MBStrings are already loaded.
- */
- UserAssert(gpsi->MBStrings[0].szName[0] != TEXT('\0'));
- #ifdef _JANUS_
- /*
- * Error message instrument start here
- * Check EMI enable
- */
- if (gfEMIEnable) {
- if (!ErrorMessageInst(pMsgBoxParams))
- RIPMSG0(RIP_WARNING, "MessageBoxWorker: Fail to instrument error msg");
- };
- /*
- * Default Message Return: on unattended systems the default button
- * can be returned automatically without putting up the message box
- */
- if (gfDMREnable) {
- /*
- * validate the style and default button as in the main code path
- */
- /*
- * Validate the "type" of message box requested.
- */
- if ((dwStyle & MB_TYPEMASK) > MB_LASTVALIDTYPE) {
- RIPERR0(ERROR_INVALID_MSGBOX_STYLE, RIP_VERBOSE, "");
- return 0;
- }
- wBtnCnt = mpTypeCcmd[dwStyle & MB_TYPEMASK] +
- ((dwStyle & MB_HELP) ? 1 : 0);
- /*
- * Set the default button value
- */
- wDefButton = (dwStyle & (UINT)MB_DEFMASK) / (UINT)(MB_DEFMASK & (MB_DEFMASK >> 3));
- if (wDefButton >= wBtnCnt) /* Check if valid */
- wDefButton = 0; /* Set the first button if error */
- /*
- * return the default button
- */
- wBtnBeg = mpTypeIich[dwStyle & (UINT)MB_TYPEMASK];
- pMBString = &gpsi->MBStrings[ SEBbuttons[wBtnBeg + wDefButton] ];
- return pMBString->uID;
- }
- #endif // _JANUS_
- /*
- * If lpszCaption is NULL, then use "Error!" string as the caption
- * string.
- * LATER: IanJa localize according to wLanguageId
- */
- if (pMsgBoxParams->lpszCaption == NULL) {
- /*
- * Load the default error string if we haven't done it yet
- */
- if (*szERROR == 0) {
- LoadStringW(hmodUser, STR_ERROR, szERROR, ARRAY_SIZE(szERROR));
- }
- if (pMsgBoxParams->wLanguageId == 0) {
- pMsgBoxParams->lpszCaption = szERROR;
- } else {
- LoadStringOrError(hmodUser,
- STR_ERROR,
- szErrorBuf,
- sizeof(szErrorBuf)/sizeof(WCHAR),
- pMsgBoxParams->wLanguageId);
- /*
- * If it didn't find the string, use the default language
- */
- if (*szErrorBuf) {
- pMsgBoxParams->lpszCaption = szErrorBuf;
- } else {
- pMsgBoxParams->lpszCaption = szERROR;
- RIPMSG1(RIP_WARNING, "MessageBoxWorker: STR_ERROR string resource for language %#lx not found",
- pMsgBoxParams->wLanguageId);
- }
- }
- }
- /*
- * MB_SERVICE_NOTIFICATION had to be redefined because
- * Win95 defined MB_TOPMOST using the same value.
- * So for old apps, we map it to the new value
- */
- if ((dwStyle & MB_TOPMOST) && !Is400Compat(GetClientInfo()->dwExpWinVer)) {
- dwStyle &= ~MB_TOPMOST;
- dwStyle |= MB_SERVICE_NOTIFICATION;
- pMsgBoxParams->dwStyle = dwStyle;
- RIPMSG1(RIP_WARNING, "MessageBoxWorker: MB_SERVICE_NOTIFICATION flag mapped. New dwStyle:%#lx", dwStyle);
- }
- /*
- * For backward compatiblity, use MB_SERVICE_NOTIFICATION if
- * it's going to the default desktop.
- */
- if (dwStyle & (MB_DEFAULT_DESKTOP_ONLY | MB_SERVICE_NOTIFICATION)) {
- /*
- * Allow services to put up popups without getting
- * access to the current desktop.
- */
- if (pMsgBoxParams->hwndOwner != NULL) {
- RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
- return 0;
- }
- return ServiceMessageBox(pMsgBoxParams->lpszText,
- pMsgBoxParams->lpszCaption,
- dwStyle & ~MB_SERVICE_NOTIFICATION,
- pMsgBoxParams->dwTimeout);
- }
- /*
- * Make sure we have a valid window handle.
- */
- if (pMsgBoxParams->hwndOwner && !IsWindow(pMsgBoxParams->hwndOwner)) {
- RIPERR0(ERROR_INVALID_WINDOW_HANDLE, RIP_VERBOSE, "");
- return 0;
- }
- /*
- * Validate the "type" of message box requested.
- */
- if ((dwStyle & MB_TYPEMASK) > MB_LASTVALIDTYPE) {
- RIPERR0(ERROR_INVALID_MSGBOX_STYLE, RIP_VERBOSE, "");
- return 0;
- }
- wBtnCnt = mpTypeCcmd[dwStyle & MB_TYPEMASK] +
- ((dwStyle & MB_HELP) ? 1 : 0);
- /*
- * Set the default button value
- */
- wDefButton = (dwStyle & (UINT)MB_DEFMASK) / (UINT)(MB_DEFMASK & (MB_DEFMASK >> 3));
- if (wDefButton >= wBtnCnt) /* Check if valid */
- wDefButton = 0; /* Set the first button if error */
- /*
- * Calculate the strings to use in the message box
- */
- wBtnBeg = mpTypeIich[dwStyle & (UINT)MB_TYPEMASK];
- for (i=0; i<wBtnCnt; i++) {
- pMBString = &gpsi->MBStrings[SEBbuttons[wBtnBeg + i]];
- /*
- * Pick up the string for the button.
- */
- if (pMsgBoxParams->wLanguageId == 0) {
- apstrButton[i] = KPWSTR_TO_PWSTR(pMBString->szName);
- } else {
- WCHAR szButtonBuf[64];
- // LATER is it possible to have button text greater than 64 chars
- /*
- * BUG: gpsi->wMaxBtnSize might be too short for the length of this string...
- */
- LoadStringOrError(hmodUser,
- pMBString->uStr,
- szButtonBuf,
- ARRAY_SIZE(szButtonBuf),
- pMsgBoxParams->wLanguageId);
- /*
- * If it didn't find the string, use the default language.
- */
- if (*szButtonBuf) {
- apstrButton[i] = TextAlloc(szButtonBuf);
- } else {
- apstrButton[i] = TextAlloc(KPWSTR_TO_PWSTR(pMBString->szName));
- RIPMSG2(RIP_WARNING, "MessageBoxWorker: string resource %#lx for language %#lx not found",
- pMBString->uStr,
- pMsgBoxParams->wLanguageId);
- }
- }
- aidButton[i] = pMBString->uID;
- if (aidButton[i] == IDCANCEL) {
- fCancel = TRUE;
- }
- }
- /*
- * Hackery: There are some apps that use MessageBox as initial error
- * indicators, such as mplay32, and we want this messagebox to be
- * visible regardless of waht was specified in the StartupInfo->wShowWindow
- * field. ccMail for instance starts all of its embedded objects hidden
- * but on win 3.1 the error message would show because they don't have
- * the startup info.
- */
- NtUserModifyUserStartupInfoFlags(STARTF_USESHOWWINDOW, 0);
- pMsgBoxParams->pidButton = aidButton;
- pMsgBoxParams->ppszButtonText = apstrButton;
- pMsgBoxParams->DefButton = wDefButton;
- pMsgBoxParams->cButtons = wBtnCnt;
- pMsgBoxParams->CancelId = ((dwStyle & MB_TYPEMASK) == 0) ? IDOK : (fCancel ? IDCANCEL : 0);
- retValue = SoftModalMessageBox(pMsgBoxParams);
- if (pMsgBoxParams->wLanguageId != 0) {
- for (i = 0; i < wBtnCnt; i++) {
- UserLocalFree(apstrButton[i]);
- }
- }
- return retValue;
- }
- #define MAX_RES_STRING 256
- /***************************************************************************\
- * SoftModalMessageBox
- \***************************************************************************/
- int SoftModalMessageBox(
- LPMSGBOXDATA lpmb)
- {
- LPBYTE lpDlgTmp;
- int cyIcon, cxIcon;
- int cxButtons;
- int cxMBMax;
- int cxText, cyText, xText;
- int cxBox, cyBox;
- int cxFoo, cxCaption;
- int xMB, yMB;
- HDC hdc;
- DWORD wIconOrdNum;
- DWORD wCaptionLen;
- DWORD wTextLen;
- WORD OrdNum[2]; // Must be an array or WORDs
- RECT rc;
- RECT rcWork;
- HCURSOR hcurOld;
- DWORD dwStyleMsg, dwStyleText;
- DWORD dwExStyleMsg = 0;
- DWORD dwStyleDlg;
- HWND hwndOwner;
- LPWSTR lpsz;
- int iRetVal = 0;
- HICON hIcon;
- HGLOBAL hTemplate = NULL;
- HGLOBAL hCaption = NULL;
- HGLOBAL hText = NULL;
- HINSTANCE hInstMsg = lpmb->hInstance;
- SIZE size;
- HFONT hFontOld = NULL;
- int cntMBox;
- PMONITOR pMonitor;
- ConnectIfNecessary(0);
- dwStyleMsg = lpmb->dwStyle;
- if (dwStyleMsg & MB_RIGHT) {
- dwExStyleMsg |= WS_EX_RIGHT;
- }
- if (!IS_PTR(lpmb->lpszCaption)) {
- /*
- * Won't ever be NULL because MessageBox sticks "Error!" on error.
- */
- if (hInstMsg && (hCaption = UserLocalAlloc(HEAP_ZERO_MEMORY, MAX_RES_STRING * sizeof(WCHAR)))) {
- lpsz = (LPWSTR)hCaption;
- LoadString(hInstMsg, PTR_TO_ID(lpmb->lpszCaption), lpsz, MAX_RES_STRING);
- } else {
- lpsz = NULL;
- }
- lpmb->lpszCaption = lpsz ? lpsz : szEmpty;
- }
- if (!IS_PTR(lpmb->lpszText)) {
- // NULL not allowed
- if (hInstMsg && (hText = UserLocalAlloc(HEAP_ZERO_MEMORY, MAX_RES_STRING * sizeof(WCHAR)))) {
- lpsz = (LPWSTR)hText;
- LoadString(hInstMsg, PTR_TO_ID(lpmb->lpszText), lpsz, MAX_RES_STRING);
- } else {
- lpsz = NULL;
- }
- lpmb->lpszText = lpsz ? lpsz : szEmpty;
- }
- //
- // Mirroring of MessageBox'es is only enabled if :-
- //
- // * MB_RTLREADING style has been specified in the MessageBox styles OR
- // * The first two code points of the MessageBox text are Right-To-Left
- // marks (RLMs = U+200f).
- // The feature of enable RTL mirroring if two consecutive RLMs are found
- // in the MB text is to acheive a no-code-change for localization of
- // of MessageBoxes for BiDi Apps. [samera]
- //
- if ((dwStyleMsg & MB_RTLREADING) ||
- (lpmb->lpszText != NULL && (lpmb->lpszText[0] == UNICODE_RLM) &&
- (lpmb->lpszText[1] == UNICODE_RLM))) {
- //
- // Set Mirroring so that MessageBox and its child controls
- // get mirrored. Otherwise, the message box and its child controls
- // are Left-To-Right.
- //
- dwExStyleMsg |= WS_EX_LAYOUTRTL;
- //
- // And turn off any conflicting flags.
- //
- dwExStyleMsg &= ~WS_EX_RIGHT;
- if (dwStyleMsg & MB_RTLREADING) {
- dwStyleMsg &= ~MB_RTLREADING;
- dwStyleMsg ^= MB_RIGHT;
- }
- }
- if ((dwStyleMsg & MB_ICONMASK) == MB_USERICON)
- hIcon = LoadIcon(hInstMsg, lpmb->lpszIcon);
- else
- hIcon = NULL;
- // For compatibility reasons, we still allow the message box to come up.
- hwndOwner = lpmb->hwndOwner;
- // For PowerBuilder4.0, we must make their messageboxes owned popups. Or, else
- // they get WM_ACTIVATEAPP and they install multiple keyboard hooks and get into
- // infinite loop later.
- // Bug #15896 -- WIN95B -- 2/17/95 -- SANKAR --
- if (!hwndOwner)
- {
- WCHAR pwszLibFileName[MAX_PATH];
- static WCHAR szPB040[] = L"PB040"; // Module name of PowerBuilder4.0
- WCHAR *pw1;
- //Is this a win3.1 or older app?
- if (!Is400Compat(GETAPPVER())) {
- if (GetModuleFileName(NULL, pwszLibFileName, sizeof(pwszLibFileName)/sizeof(WCHAR)) == 0) goto getthedc;
- pw1 = pwszLibFileName + wcslen(pwszLibFileName) - 1;
- while (pw1 > pwszLibFileName) {
- if (*pw1 == TEXT('.')) *pw1-- = 0;
- else if (*pw1 == TEXT(':')) {pw1++; break;}
- else if (*pw1 == TEXT('\\')) {pw1++; break;}
- else pw1--;
- }
- // Is this the PowerBuilder 4.0 module?
- if (!_wcsicmp(pw1, szPB040))
- hwndOwner = NtUserGetForegroundWindow(); // Make the MsgBox owned.
- }
- }
- getthedc:
- // Check if we're out of cache DCs until robustness...
- if (!(hdc = NtUserGetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE))) {
- /*
- * The above call might fail for TIF_RESTRICTED processes
- * so check for the DC from the owner window
- */
- if (!(hdc = NtUserGetDCEx(hwndOwner, NULL, DCX_WINDOW | DCX_CACHE)))
- goto SMB_Exit;
- }
- // Figure out the types and dimensions of buttons
- cxButtons = (lpmb->cButtons * gpsi->wMaxBtnSize) + ((lpmb->cButtons - 1) * XPixFromXDU(DU_BTNGAP, gpsi->cxMsgFontChar));
- // Ditto for the icon, if there is one. If not, cxIcon & cyIcon are 0.
- if (wIconOrdNum = MB_GetIconOrdNum(dwStyleMsg)) {
- cxIcon = SYSMET(CXICON) + XPixFromXDU(DU_INNERMARGIN, gpsi->cxMsgFontChar);
- cyIcon = SYSMET(CYICON);
- } else
- cxIcon = cyIcon = 0;
- hFontOld = SelectObject(hdc, KHFONT_TO_HFONT(gpsi->hCaptionFont));
- // Find the max between the caption text and the buttons
- wCaptionLen = wcslen(lpmb->lpszCaption);
- GetTextExtentPoint(hdc, lpmb->lpszCaption, wCaptionLen, &size);
- cxCaption = size.cx + 2*SYSMET(CXSIZE);
- //
- // The max width of the message box is 5/8 of the work area for most
- // countries. We will then try 6/8 and 7/8 if it won't fit. Then
- // we will use whole screen.
- //
- pMonitor = GetDialogMonitor(hwndOwner, MONITOR_DEFAULTTOPRIMARY);
- CopyRect(&rcWork, KPRECT_TO_PRECT(&pMonitor->rcWork));
- cxMBMax = MultDiv(rcWork.right - rcWork.left, 5, 8);
- cxFoo = 2*XPixFromXDU(DU_OUTERMARGIN, gpsi->cxMsgFontChar);
- SelectObject(hdc, KHFONT_TO_HFONT(gpsi->hMsgFont));
- //
- // If the text doesn't fit in 5/8, try 7/8 of the screen
- //
- ReSize:
- //
- // The message box is as big as needed to hold the caption/text/buttons,
- // but not bigger than the maximum width.
- //
- cxBox = cxMBMax - 2*SYSMET(CXFIXEDFRAME);
- // Ask DrawText for the right cx and cy
- rc.left = 0;
- rc.top = 0;
- rc.right = cxBox - cxFoo - cxIcon;
- rc.bottom = rcWork.bottom - rcWork.top;
- cyText = DrawTextExW(hdc, (LPWSTR)lpmb->lpszText, -1, &rc,
- DT_CALCRECT | DT_WORDBREAK | DT_EXPANDTABS |
- DT_NOPREFIX | DT_EXTERNALLEADING | DT_EDITCONTROL, NULL);
- //
- // Make sure we have enough width to hold the buttons, in addition to
- // the icon+text. Always force the buttons. If they don't fit, it's
- // because the working area is small.
- //
- //
- // The buttons are centered underneath the icon/text.
- //
- cxText = rc.right - rc.left + cxIcon + cxFoo;
- cxBox = min(cxBox, max(cxText, cxCaption));
- cxBox = max(cxBox, cxButtons + cxFoo);
- cxText = cxBox - cxFoo - cxIcon;
- //
- // Now we know the text width for sure. Really calculate how high the
- // text will be.
- //
- rc.left = 0;
- rc.top = 0;
- rc.right = cxText;
- rc.bottom = rcWork.bottom - rcWork.top;
- cyText = DrawTextExW(hdc, (LPWSTR)lpmb->lpszText, -1, &rc, DT_CALCRECT | DT_WORDBREAK
- | DT_EXPANDTABS | DT_NOPREFIX | DT_EXTERNALLEADING | DT_EDITCONTROL, NULL);
- // Find the window size.
- cxBox += 2*SYSMET(CXFIXEDFRAME);
- cyBox = 2*SYSMET(CYFIXEDFRAME) + SYSMET(CYCAPTION) + YPixFromYDU(2*DU_OUTERMARGIN +
- DU_INNERMARGIN + DU_BTNHEIGHT, gpsi->cyMsgFontChar);
- cyBox += max(cyIcon, cyText);
- //
- // If the message box doesn't fit on the working area, we'll try wider
- // sizes successively: 6/8 of work then 7/8 of screen.
- //
- if (cyBox > rcWork.bottom - rcWork.top) {
- int cxTemp;
- cxTemp = MultDiv(rcWork.right - rcWork.left, 6, 8);
- if (cxMBMax == MultDiv(rcWork.right - rcWork.left, 5, 8)) {
- cxMBMax = cxTemp;
- goto ReSize;
- } else if (cxMBMax == cxTemp) {
- // then let's try with rcMonitor
- CopyRect(&rcWork, KPRECT_TO_PRECT(&pMonitor->rcMonitor));
- cxMBMax = MultDiv(rcWork.right - rcWork.left, 7, 8);
- goto ReSize;
- }
- }
- if (hFontOld) {
- SelectFont(hdc, hFontOld);
- }
- NtUserReleaseDC(NULL, hdc);
- // Find the window position
- cntMBox = GetClientInfo()->pDeskInfo->cntMBox;
- xMB = (rcWork.left + rcWork.right - cxBox) / 2 + (cntMBox * SYSMET(CXSIZE));
- xMB = max(xMB, rcWork.left);
- yMB = (rcWork.top + rcWork.bottom - cyBox) / 2 + (cntMBox * SYSMET(CYSIZE));
- yMB = max(yMB, rcWork.top);
- //
- // Bottom, right justify if we're going off the screen--but leave a
- // little gap.
- //
- if (xMB + cxBox > rcWork.right) {
- xMB = rcWork.right - SYSMET(CXEDGE) - cxBox;
- }
- //
- // Pin to the working area. If it won't fit, then pin to the screen
- // height. Bottom justify it at least if too big even for that, so
- // that the buttons are visible.
- //
- if (yMB + cyBox > rcWork.bottom) {
- yMB = rcWork.bottom - SYSMET(CYEDGE) - cyBox;
- if (yMB < rcWork.top) {
- yMB = pMonitor->rcMonitor.bottom - SYSMET(CYEDGE) - cyBox;
- }
- }
- wTextLen = wcslen(lpmb->lpszText);
- // Find out the memory required for the Dlg template and try to alloc it
- hTemplate = UserLocalAlloc(HEAP_ZERO_MEMORY, MB_FindDlgTemplateSize(lpmb));
- if (!hTemplate) {
- goto SMB_Exit;
- }
- lpDlgTmp = (LPBYTE)hTemplate;
- //
- // Setup the dialog style for the message box
- //
- dwStyleDlg = WS_POPUPWINDOW | WS_CAPTION | DS_ABSALIGN | DS_NOIDLEMSG |
- DS_SETFONT | DS_3DLOOK;
- if ((dwStyleMsg & MB_MODEMASK) == MB_SYSTEMMODAL) {
- dwStyleDlg |= DS_SYSMODAL | DS_SETFOREGROUND;
- } else {
- dwStyleDlg |= DS_MODALFRAME | WS_SYSMENU;
- }
- if (dwStyleMsg & MB_SETFOREGROUND) {
- dwStyleDlg |= DS_SETFOREGROUND;
- }
- // Add the Header of the Dlg Template
- // BOGUS !!! don't ADD bools
- lpDlgTmp = MB_UpdateDlgHdr((LPDLGTEMPLATE) lpDlgTmp, dwStyleDlg, dwExStyleMsg,
- (BYTE) (lpmb->cButtons + (wIconOrdNum != 0) + (lpmb->lpszText != NULL)),
- xMB, yMB, cxBox, cyBox, (LPWSTR)lpmb->lpszCaption, wCaptionLen);
- //
- // Center the buttons
- //
- cxFoo = (cxBox - 2*SYSMET(CXFIXEDFRAME) - cxButtons) / 2;
- lpDlgTmp = MB_AddPushButtons((LPDLGITEMTEMPLATE)lpDlgTmp, lpmb, cxFoo,
- cyBox - SYSMET(CYCAPTION) - (2 * SYSMET(CYFIXEDFRAME)) -
- YPixFromYDU(DU_OUTERMARGIN, gpsi->cyMsgFontChar));
- // Add Icon, if any, to the Dlg template
- //
- // The icon is always top justified. If the text is shorter than the
- // height of the icon, we center it. Otherwise the text will start at
- // the top.
- //
- if (wIconOrdNum) {
- OrdNum[0] = 0xFFFF; // To indicate that an Ordinal number follows
- OrdNum[1] = (WORD) wIconOrdNum;
- lpDlgTmp = MB_UpdateDlgItem((LPDLGITEMTEMPLATE)lpDlgTmp, IDUSERICON, // Control Id
- SS_ICON | WS_GROUP | WS_CHILD | WS_VISIBLE, 0,
- XPixFromXDU(DU_OUTERMARGIN, gpsi->cxMsgFontChar), // X co-ordinate
- YPixFromYDU(DU_OUTERMARGIN, gpsi->cyMsgFontChar), // Y co-ordinate
- 0, 0, // For Icons, CX and CY are ignored, can be zero
- OrdNum, // Ordinal number of Icon
- ARRAY_SIZE(OrdNum), // Length of OrdNum
- STATICCODE);
- }
- // Add the Text of the Message to the Dlg Template
- if (lpmb->lpszText) {
- //
- // Center the text if shorter than the icon.
- //
- if (cyText >= cyIcon)
- cxFoo = 0;
- else
- cxFoo = (cyIcon - cyText) / 2;
- dwStyleText = SS_NOPREFIX | WS_GROUP | WS_CHILD | WS_VISIBLE | SS_EDITCONTROL;
- if (dwStyleMsg & MB_RIGHT) {
- dwStyleText |= SS_RIGHT;
- xText = cxBox - (SYSMET(CXSIZE) + cxText);
- } else {
- dwStyleText |= SS_LEFT;
- xText = cxIcon + XPixFromXDU(DU_INNERMARGIN, gpsi->cxMsgFontChar);
- }
- MB_UpdateDlgItem((LPDLGITEMTEMPLATE)lpDlgTmp, -1, dwStyleText, dwExStyleMsg, xText,
- YPixFromYDU(DU_OUTERMARGIN, gpsi->cyMsgFontChar) + cxFoo,
- cxText, cyText,
- (LPWSTR)lpmb->lpszText, wTextLen, STATICCODE);
- }
- // The dialog template is ready
- //
- // Set the normal cursor
- //
- hcurOld = NtUserSetCursor(LoadCursor(NULL, IDC_ARROW));
- lpmb->lpszIcon = (LPWSTR) hIcon;
- if (!(lpmb->dwStyle & MB_USERICON))
- {
- int wBeep = (LOWORD(lpmb->dwStyle & MB_ICONMASK)) >> MB_MASKSHIFT;
- if (wBeep < USER_SOUND_MAX) {
- NtUserCallOneParam(wBeep, SFI_PLAYEVENTSOUND);
- }
- }
- iRetVal = (int)InternalDialogBox(hmodUser, hTemplate, hwndOwner,
- MB_DlgProc, (LPARAM) lpmb, FALSE);
- //
- // Fix up return value
- if (iRetVal == -1)
- iRetVal = 0; /* Messagebox should also return error */
- //
- // If the messagebox contains only OK button, then its ID is changed as
- // IDCANCEL in MB_DlgProc; So, we must change it back to IDOK irrespective
- // of whether ESC is pressed or Carriage return is pressed;
- //
- if (((dwStyleMsg & MB_TYPEMASK) == MB_OK) && iRetVal)
- iRetVal = IDOK;
- //
- // Restore the previous cursor
- //
- if (hcurOld)
- NtUserSetCursor(hcurOld);
- SMB_Exit:
- if (hTemplate) {
- UserLocalFree(hTemplate);
- }
- if (hCaption) {
- UserLocalFree(hCaption);
- }
- if (hText) {
- UserLocalFree(hText);
- }
- return iRetVal;
- }
- /***************************************************************************\
- * MB_CopyToClipboard
- *
- * Called in response to WM_COPY, it will save the title, message and button's
- * texts to the clipboard in CF_UNICODETEXT format.
- *
- * ---------------------------
- * Caption
- * ---------------------------
- * Text
- * ---------------------------
- * Button1 ... ButtonN
- * ---------------------------
- *
- *
- * History:
- * 08-03-97 MCostea Created
- \***************************************************************************/
- VOID
- MB_CopyToClipboard(
- HWND hwndDlg)
- {
- LPCWSTR lpszRead;
- LPWSTR lpszAll, lpszWrite;
- HANDLE hData;
- static CONST WCHAR szLine[] = L"---------------------------\r\n";
- UINT cBufSize, i, cWrote;
- LPMSGBOXDATA lpmb;
- if (!(lpmb = (LPMSGBOXDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA))) {
- return;
- }
- if (!OpenClipboard(hwndDlg)) {
- return;
- }
- /*
- * Calculate the buffer size:
- * - the message text can be all \n, that will become \r\n
- * - there are a few extra \r\n (that's why 8)
- */
- cBufSize = (lpmb->lpszCaption ? wcslen(lpmb->lpszCaption) : 0) +
- (lpmb->lpszText ? 2*wcslen(lpmb->lpszText) : 0) +
- 4*sizeof(szLine) +
- lpmb->cButtons * gpsi->wMaxBtnSize +
- 8;
- cBufSize *= sizeof(WCHAR);
- if (!(hData = UserGlobalAlloc(LHND, (LONG)(cBufSize))) ) {
- goto CloseClip;
- }
- USERGLOBALLOCK(hData, lpszAll);
- UserAssert(lpszAll);
- cWrote = wsprintf(lpszAll, L"%s%s\r\n%s",
- szLine,
- lpmb->lpszCaption ? lpmb->lpszCaption : L"",
- szLine);
- lpszWrite = lpszAll + cWrote;
- lpszRead = lpmb->lpszText;
- /*
- * Change \n to \r\n in the text
- */
- for (i = 0; *lpszRead; i++) {
- if (*lpszRead == L'\n')
- *lpszWrite++ = L'\r';
- *lpszWrite++ = *lpszRead++;
- }
- cWrote = wsprintf(lpszWrite, L"\r\n%s", szLine);
- lpszWrite += cWrote;
- /*
- * Remove & from the button texts
- */
- for (i = 0; i<lpmb->cButtons; i++) {
- lpszRead = lpmb->ppszButtonText[i];
- while (*lpszRead) {
- if (*lpszRead != L'&') {
- *lpszWrite++ = *lpszRead;
- }
- lpszRead++;
- }
- *lpszWrite++ = L' ';
- *lpszWrite++ = L' ';
- *lpszWrite++ = L' ';
- }
- wsprintf(lpszWrite, L"\r\n%s\0", szLine);
- USERGLOBALUNLOCK(hData);
- NtUserEmptyClipboard();
- /*
- * If we just called EmptyClipboard in the context of a 16 bit
- * app then we also have to tell WOW to nix its 16 handle copy of
- * clipboard data. WOW does its own clipboard caching because
- * some 16 bit apps use clipboard data even after the clipboard
- * has been emptied. See the note in the server code.
- *
- * Note: this is another place (besides client\editec.c) where
- * EmptyClipboard is called* for a 16 bit app not going through WOW.
- * If we added others we might want to move this into EmptyClipboard
- * and have two versions.
- */
- if (GetClientInfo()->CI_flags & CI_16BIT) {
- pfnWowEmptyClipBoard();
- }
- SetClipboardData(CF_UNICODETEXT, hData);
- CloseClip:
- NtUserCloseClipboard();
- }
- /***************************************************************************\
- * MB_UpdateDlgHdr
- *
- * History:
- * 11-20-90 DarrinM Ported from Win 3.0 sources.
- \***************************************************************************/
- LPBYTE MB_UpdateDlgHdr(
- LPDLGTEMPLATE lpDlgTmp,
- long lStyle,
- long lExtendedStyle,
- BYTE bItemCount,
- int iX,
- int iY,
- int iCX,
- int iCY,
- LPWSTR lpszCaption,
- int cchCaptionLen)
- {
- LPTSTR lpStr;
- RECT rc;
- /*
- * Adjust the rectangle dimensions.
- */
- rc.left = iX + SYSMET(CXFIXEDFRAME);
- rc.top = iY + SYSMET(CYFIXEDFRAME);
- rc.right = iX + iCX - SYSMET(CXFIXEDFRAME);
- rc.bottom = iY + iCY - SYSMET(CYFIXEDFRAME);
- /*
- * Adjust for the caption.
- */
- rc.top += SYSMET(CYCAPTION);
- lpDlgTmp->style = lStyle;
- lpDlgTmp->dwExtendedStyle = lExtendedStyle;
- lpDlgTmp->cdit = bItemCount;
- lpDlgTmp->x = XDUFromXPix(rc.left, gpsi->cxMsgFontChar);
- lpDlgTmp->y = YDUFromYPix(rc.top, gpsi->cyMsgFontChar);
- lpDlgTmp->cx = XDUFromXPix(rc.right - rc.left, gpsi->cxMsgFontChar);
- lpDlgTmp->cy = YDUFromYPix(rc.bottom - rc.top, gpsi->cyMsgFontChar);
- /*
- * Move pointer to variable length fields. No menu resource for
- * message box, a zero window class (means dialog box class).
- */
- lpStr = (LPWSTR)(lpDlgTmp + 1);
- *lpStr++ = 0; // Menu
- lpStr = (LPWSTR)NextWordBoundary(lpStr);
- *lpStr++ = 0; // Class
- lpStr = (LPWSTR)NextWordBoundary(lpStr);
- /*
- * NOTE: iCaptionLen may be less than the length of the Caption string;
- * So, DO NOT USE lstrcpy();
- */
- RtlCopyMemory(lpStr, lpszCaption, cchCaptionLen*sizeof(WCHAR));
- lpStr += cchCaptionLen;
- *lpStr++ = TEXT('\0'); // Null terminate the caption str
- /*
- * Font height of 0x7FFF means use the message box font
- */
- *lpStr++ = 0x7FFF;
- return NextDWordBoundary(lpStr);
- }
- /***************************************************************************\
- * MB_AddPushButtons
- *
- * History:
- * 11-20-90 DarrinM Ported from Win 3.0 sources.
- \***************************************************************************/
- LPBYTE MB_AddPushButtons(
- LPDLGITEMTEMPLATE lpDlgTmp,
- LPMSGBOXDATA lpmb,
- UINT wLEdge,
- UINT wBEdge)
- {
- UINT wYValue;
- UINT i;
- UINT wHeight;
- UINT wCount = lpmb->cButtons;
- wHeight = YPixFromYDU(DU_BTNHEIGHT, gpsi->cyMsgFontChar);
- wYValue = wBEdge - wHeight; // Y co-ordinate for push buttons
- for (i = 0; i < wCount; i++) {
- lpDlgTmp = (LPDLGITEMTEMPLATE)MB_UpdateDlgItem(
- lpDlgTmp, /* Ptr to template */
- lpmb->pidButton[i], /* Control Id */
- WS_TABSTOP | WS_CHILD | WS_VISIBLE | (i == 0 ? WS_GROUP : 0) |
- ((UINT)i == lpmb->DefButton ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON),
- 0,
- wLEdge, /* X co-ordinate */
- wYValue, /* Y co-ordinate */
- gpsi->wMaxBtnSize, /* CX */
- wHeight, /* CY */
- lpmb->ppszButtonText[i], /* String for button */
- (UINT)wcslen(lpmb->ppszButtonText[i]),/* Length */
- BUTTONCODE);
- /*
- * Get the X co-ordinate for the next Push button
- */
- wLEdge += gpsi->wMaxBtnSize + XPixFromXDU(DU_BTNGAP, gpsi->cxMsgFontChar);
- }
- return (LPBYTE)lpDlgTmp;
- }
- /***************************************************************************\
- * MB_UpdateDlgItem
- *
- * History:
- * 11-20-90 DarrinM Ported from Win 3.0 sources.
- \***************************************************************************/
- LPBYTE MB_UpdateDlgItem(
- LPDLGITEMTEMPLATE lpDlgItem,
- int iCtrlId,
- long lStyle,
- long lExtendedStyle,
- int iX,
- int iY,
- int iCX,
- int iCY,
- LPWSTR lpszText,
- UINT cchTextLen,
- int iControlClass)
- {
- LPWSTR lpStr;
- BOOL fIsOrdNum;
- lpDlgItem->x = XDUFromXPix(iX, gpsi->cxMsgFontChar);
- lpDlgItem->y = YDUFromYPix(iY, gpsi->cyMsgFontChar);
- lpDlgItem->cx = XDUFromXPix(iCX,gpsi->cxMsgFontChar);
- lpDlgItem->cy = YDUFromYPix(iCY,gpsi->cyMsgFontChar);
- lpDlgItem->id = (WORD)iCtrlId;
- lpDlgItem->style = lStyle;
- lpDlgItem->dwExtendedStyle = lExtendedStyle;
- /*
- * We have to avoid the following nasty rounding off problem:
- * (e.g) If iCX=192 and cxSysFontChar=9, then cx becomes 85; When the
- * static text is drawn, from 85 dlg units we get 191 pixels; So, the text
- * is truncated;
- * So, to avoid this, check if this is a static text and if so,
- * add one more dialog unit to cx and cy;
- * --Fix for Bug #4481 --SANKAR-- 09-29-89--
- */
- /*
- * Also, make sure we only do this to static text items. davidds
- */
- /*
- * Now static text uses SS_NOPREFIX = 0x80;
- * So, test the lStyle field only with 0x0F instead of 0xFF;
- * Fix for Bugs #5933 and 5935 --SANKAR-- 11-28-89
- */
- if (iControlClass == STATICCODE &&
- (((lStyle & 0x0F) == SS_LEFT) || ((lStyle & 0x0F) == SS_RIGHT))) {
- /*
- * This is static text
- */
- lpDlgItem->cx++;
- lpDlgItem->cy++;
- }
- /*
- * Move ptr to the variable fields
- */
- lpStr = (LPWSTR)(lpDlgItem + 1);
- /*
- * Store the Control Class value
- */
- *lpStr++ = 0xFFFF;
- *lpStr++ = (BYTE)iControlClass;
- lpStr = (LPWSTR)NextWordBoundary(lpStr); // WORD-align lpszText
- /*
- * Check if the String contains Ordinal number or not
- */
- fIsOrdNum = ((*lpszText == 0xFFFF) && (cchTextLen == sizeof(DWORD)/sizeof(WCHAR)));
- /*
- * NOTE: cchTextLen may be less than the length of lpszText. So,
- * DO NOT USE lstrcpy() for the copy.
- */
- RtlCopyMemory(lpStr, lpszText, cchTextLen*sizeof(WCHAR));
- lpStr = lpStr + cchTextLen;
- if (!fIsOrdNum) {
- *lpStr = TEXT('\0'); // NULL terminate the string
- lpStr = (LPWSTR)NextWordBoundary(lpStr + 1);
- }
- *lpStr++ = 0; // sizeof control data (there is none)
- return NextDWordBoundary(lpStr);
- }
- /***************************************************************************\
- * MB_FindDlgTemplateSize
- *
- * This routine computes the amount of memory that will be needed for the
- * messagebox's dialog template structure. The dialog template has several
- * required and optional records. The dialog manager expects each record to
- * be DWORD aligned so any necessary padding is also accounted for.
- *
- * (header - required)
- * DLGTEMPLATE (header) + 1 menu byte + 1 pad + 1 class byte + 1 pad
- * szCaption + 0 term + DWORD alignment
- *
- * (static icon control - optional)
- * DLGITEMTEMPLATE + 1 class byte + 1 pad + (0xFF00 + icon ordinal # [szText]) +
- * UINT alignment + 1 control data length byte (0) + DWORD alignment
- *
- * (pushbutton controls - variable, but at least one required)
- * DLGITEMTEMPLATE + 1 class byte + 1 pad + length of button text +
- * UINT alignment + 1 control data length byte (0) + DWORD alignment
- *
- * (static text control - optional)
- * DLGITEMTEMPLATE + 1 class byte + 1 pad + length of text +
- * UINT alignment + 1 control data length byte (0) + DWORD alignment
- *
- * History:
- * 11-20-90 DarrinM Ported from Win 3.0 sources.
- \***************************************************************************/
- UINT
- MB_FindDlgTemplateSize(
- LPMSGBOXDATA lpmb)
- {
- ULONG_PTR cbLen;
- UINT cbT;
- UINT i;
- UINT wCount;
- wCount = lpmb->cButtons;
- /*
- * Start with dialog header's size.
- */
- cbLen = (ULONG_PTR)NextWordBoundary(sizeof(DLGTEMPLATE) + sizeof(WCHAR));
- cbLen = (ULONG_PTR)NextWordBoundary(cbLen + sizeof(WCHAR));
- cbLen += wcslen(lpmb->lpszCaption) * sizeof(WCHAR) + sizeof(WCHAR);
- cbLen += sizeof(WORD); // Font height
- cbLen = (ULONG_PTR)NextDWordBoundary(cbLen);
- /*
- * Check if an Icon is present.
- */
- if (lpmb->dwStyle & MB_ICONMASK)
- cbLen += (ULONG_PTR)NextDWordBoundary(sizeof(DLGITEMTEMPLATE) + 7 * sizeof(WCHAR));
- /*
- * Find the number of buttons in the msg box.
- */
- for (i = 0; i < wCount; i++) {
- cbLen = (ULONG_PTR)NextWordBoundary(cbLen + sizeof(DLGITEMTEMPLATE) +
- (2 * sizeof(WCHAR)));
- cbT = (wcslen(lpmb->ppszButtonText[i]) + 1) * sizeof(WCHAR);
- cbLen = (ULONG_PTR)NextWordBoundary(cbLen + cbT);
- cbLen += sizeof(WCHAR);
- cbLen = (ULONG_PTR)NextDWordBoundary(cbLen);
- }
- /*
- * Add in the space required for the text message (if there is one).
- */
- if (lpmb->lpszText != NULL) {
- cbLen = (ULONG_PTR)NextWordBoundary(cbLen + sizeof(DLGITEMTEMPLATE) +
- (2 * sizeof(WCHAR)));
- cbT = (wcslen(lpmb->lpszText) + 1) * sizeof(WCHAR);
- cbLen = (ULONG_PTR)NextWordBoundary(cbLen + cbT);
- cbLen += sizeof(WCHAR);
- cbLen = (ULONG_PTR)NextDWordBoundary(cbLen);
- }
- return (UINT)cbLen;
- }
- /***************************************************************************\
- * MB_GetIconOrdNum
- *
- * History:
- * 11-20-90 DarrinM Ported from Win 3.0 sources.
- \***************************************************************************/
- UINT MB_GetIconOrdNum(
- UINT rgBits)
- {
- switch (rgBits & MB_ICONMASK) {
- case MB_USERICON:
- case MB_ICONHAND:
- return PtrToUlong(IDI_HAND);
- case MB_ICONQUESTION:
- return PtrToUlong(IDI_QUESTION);
- case MB_ICONEXCLAMATION:
- return PtrToUlong(IDI_EXCLAMATION);
- case MB_ICONASTERISK:
- return PtrToUlong(IDI_ASTERISK);
- }
- return 0;
- }
- /***************************************************************************\
- * MB_GetString
- *
- * History:
- * 1-24-95 JerrySh Created.
- \***************************************************************************/
- LPWSTR MB_GetString(
- UINT wBtn)
- {
- if (wBtn < MAX_SEB_STYLES)
- return GETGPSIMBPSTR(wBtn);
- RIPMSG1(RIP_ERROR, "Invalid wBtn: %d", wBtn);
- return NULL;
- }
- /***************************************************************************\
- * MB_DlgProc
- *
- * Returns: TRUE - message processed
- * FALSE - message not processed
- *
- * History:
- * 11-20-90 DarrinM Ported from Win 3.0 sources.
- \***************************************************************************/
- INT_PTR MB_DlgProc(
- HWND hwndDlg,
- UINT wMsg,
- WPARAM wParam,
- LPARAM lParam)
- {
- HWND hwndT;
- int iCount;
- LPMSGBOXDATA lpmb;
- HWND hwndOwner;
- PVOID lpfnCallback;
- PWND pwnd;
- BOOL bTimedOut = FALSE;
- switch (wMsg) {
- case WM_CTLCOLORDLG:
- case WM_CTLCOLORSTATIC:
- if ((pwnd = ValidateHwnd(hwndDlg)) == NULL)
- return 0L;
- return DefWindowProcWorker(pwnd, WM_CTLCOLORMSGBOX,
- wParam, lParam, FALSE);
- case WM_TIMER:
- if (!bTimedOut) {
- bTimedOut = TRUE;
- EndTaskModalDialog(hwndDlg);
- EndDialog(hwndDlg, IDTIMEOUT);
- }
- break;
- case WM_NCDESTROY:
- if ((lpmb = (LPMSGBOXDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA))) {
- if (lpmb->dwTimeout != INFINITE) {
- NtUserKillTimer(hwndDlg, 0);
- lpmb->dwTimeout = INFINITE;
- }
- }
- if ((pwnd = ValidateHwnd(hwndDlg)) == NULL) {
- return 0L;
- }
- return DefWindowProcWorker(pwnd, wMsg,
- wParam, lParam, FALSE);
- case WM_INITDIALOG:
- lpmb = (LPMSGBOXDATA)lParam;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (ULONG_PTR)lParam);
- NtUserCallHwnd(hwndDlg, SFI_SETMSGBOX);
- if (lpmb->dwStyle & MB_HELP) {
- NtUserSetWindowContextHelpId(hwndDlg, lpmb->dwContextHelpId);
- }
- if (lpmb->dwStyle & MB_TOPMOST) {
- NtUserSetWindowPos(hwndDlg,
- HWND_TOPMOST,
- 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE);
- }
- if (lpmb->dwStyle & MB_USERICON) {
- SendDlgItemMessage(hwndDlg, IDUSERICON, STM_SETICON, (WPARAM)(lpmb->lpszIcon), 0);
- iCount = ALERT_SYSTEM_WARNING;
- } else {
- /*
- * Generate an alert notification
- */
- switch (lpmb->dwStyle & MB_ICONMASK) {
- case MB_ICONWARNING:
- iCount = ALERT_SYSTEM_WARNING;
- break;
- case MB_ICONQUESTION:
- iCount = ALERT_SYSTEM_QUERY;
- break;
- case MB_ICONERROR:
- iCount = ALERT_SYSTEM_ERROR;
- break;
- case MB_ICONINFORMATION:
- default:
- iCount = ALERT_SYSTEM_INFORMATIONAL;
- break;
- }
- }
- NotifyWinEvent(EVENT_SYSTEM_ALERT, hwndDlg, OBJID_ALERT, iCount);
- if (lpmb->hwndOwner == NULL &&
- (lpmb->dwStyle & MB_MODEMASK) == MB_TASKMODAL) {
- StartTaskModalDialog(hwndDlg);
- }
- /*
- * Set focus on the default button
- */
- hwndT = GetWindow(hwndDlg, GW_CHILD);
- iCount = lpmb->DefButton;
- while (iCount--)
- hwndT = GetWindow(hwndT, GW_HWNDNEXT);
- NtUserSetFocus(hwndT);
- //
- // Need the dialog's HWND later, but we reuse hwndDlg.
- //
- hwndT = hwndDlg;
- //
- // If this dialogbox does not contain a IDCANCEL button, then
- // remove the CLOSE command from the system menu.
- // Bug #4445, --SANKAR-- 09-13-89 --
- //
- if (lpmb->CancelId == 0) {
- HMENU hMenu;
- if (hMenu = NtUserGetSystemMenu(hwndDlg, FALSE)) {
- NtUserDeleteMenu(hMenu, SC_CLOSE, (UINT)MF_BYCOMMAND);
- }
- }
- if ((lpmb->dwStyle & MB_TYPEMASK) == MB_OK) {
- //
- // Make the ID of OK button to be CANCEL, because we want
- // the ESC to terminate the dialogbox; GetDlgItem32() will
- // not fail, because this is MB_OK messagebox!
- //
- hwndDlg = GetDlgItem(hwndDlg, IDOK);
- if (hwndDlg != NULL) {
- // hwndDlg->hMenu = (HMENU)IDCANCEL;
- SetWindowLongPtr(hwndDlg, GWLP_ID, IDCANCEL);
- } else {
- RIPMSG0(RIP_WARNING, "MB_DlgProc- IDOK control not found");
- }
- }
- if (lpmb->dwTimeout != INFINITE) {
- if (NtUserSetTimer(hwndT, 0, lpmb->dwTimeout, NULL) == 0) {
- /*
- * Couldn't create the timer, so "clear" out the timeout value
- * for future reference.
- */
- lpmb->dwTimeout = INFINITE;
- }
- }
- /*
- * We have changed the input focus
- */
- return FALSE;
- case WM_HELP:
- // When user hits an F1 key, it results in this message.
- // It is possible that this MsgBox has a callback instead of a
- // parent. So, we must behave as if the user hit the HELP button.
- goto MB_GenerateHelp;
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDOK:
- case IDCANCEL:
- //
- // Check if a control exists with the given ID; This
- // check is needed because DlgManager returns IDCANCEL
- // blindly when ESC is pressed even if a button with
- // IDCANCEL is not present.
- // Bug #4445 --SANKAR--09-13-1989--
- //
- if (!GetDlgItem(hwndDlg, LOWORD(wParam)))
- return FALSE;
- // else FALL THRO....This is intentional.
- case IDABORT:
- case IDIGNORE:
- case IDNO:
- case IDRETRY:
- case IDYES:
- case IDTRYAGAIN:
- case IDCONTINUE:
- EndTaskModalDialog(hwndDlg);
- EndDialog(hwndDlg, LOWORD(wParam));
- break;
- case IDHELP:
- MB_GenerateHelp:
- // Generate the WM_HELP message and send it to owner or callback
- hwndOwner = NULL;
- // Check if there is an app supplied callback for this MsgBox
- lpmb = (LPMSGBOXDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- if ((lpfnCallback = lpmb->lpfnMsgBoxCallback) == NULL) {
- // If not, see if we need to inform the parent.
- hwndOwner = GetWindow(hwndDlg, GW_OWNER);
- }
- /*
- * See if we need to generate the Help message or call back.
- */
- if (hwndOwner || lpfnCallback) {
- SendHelpMessage(hwndOwner,
- HELPINFO_WINDOW,
- IDHELP,
- hwndDlg,
- NtUserGetWindowContextHelpId(hwndDlg),
- lpfnCallback);
- }
- break;
- default:
- return FALSE;
- break;
- }
- break;
- case WM_COPY:
- MB_CopyToClipboard(hwndDlg);
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- /***************************************************************************\
- * StartTaskModalDialog
- *
- * History:
- * 11-20-90 DarrinM Ported from Win 3.0 sources.
- \***************************************************************************/
- VOID
- StartTaskModalDialog(
- HWND hwndDlg)
- {
- int cHwnd;
- HWND *phwnd;
- HWND *phwndList, *phwndEnd;
- HWND hwnd;
- PWND pwnd;
- LPMSGBOXDATA lpmb;
- /*
- * Get the hwnd list. It is returned in a block of memory allocated with
- * UserLocalAlloc.
- */
- if ((cHwnd = BuildHwndList(NULL, NULL, FALSE, GetCurrentThreadId(), &phwndList)) == 0) {
- return;
- }
- lpmb = (LPMSGBOXDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- lpmb->phwndList = phwndList;
- phwndEnd = phwndList + cHwnd;
- for (phwnd = phwndList; phwnd < phwndEnd; phwnd++) {
- if ((hwnd = *phwnd) == NULL || (pwnd = RevalidateHwnd(hwnd)) == NULL)
- continue;
- /*
- * if the window belongs to the current task and is enabled, disable
- * it. All other windows are NULL'd out, to prevent their being
- * enabled later
- */
- if (!TestWF(pwnd, WFDISABLED) && DIFFWOWHANDLE(hwnd, hwndDlg)) {
- NtUserEnableWindow(hwnd, FALSE);
- } else {
- *phwnd = NULL;
- }
- }
- }
- /***************************************************************************\
- * EndTaskModalDialog
- *
- * History:
- * 11-20-90 DarrinM Ported from Win 3.0 sources.
- \***************************************************************************/
- VOID
- EndTaskModalDialog(
- HWND hwndDlg)
- {
- HWND *phwnd;
- HWND *phwndList;
- HWND hwnd;
- LPMSGBOXDATA lpmb;
- lpmb = (LPMSGBOXDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- phwndList = lpmb->phwndList;
- if (phwndList == NULL) {
- return;
- }
- lpmb->phwndList = NULL;
- for (phwnd = phwndList; *phwnd != (HWND)1; phwnd++) {
- if ((hwnd = *phwnd) != NULL) {
- NtUserEnableWindow(hwnd, TRUE);
- }
- }
- UserLocalFree(phwndList);
- }
- #ifdef _JANUS_
- /***************************************************************************\
- * ErrorMessageInst
- *
- * Instrument routine for recording error msg
- *
- * Returns: TRUE - Instrument error msg Success
- * FALSE - Fail
- *
- * History:
- * 8-5-98 Chienho Created
- \***************************************************************************/
- BOOL ErrorMessageInst(
- LPMSGBOXDATA pMsgBoxParams)
- {
- ERROR_ELEMENT ErrEle;
- WCHAR *pwcs;
- PVOID ImageBase;
- PIMAGE_NT_HEADERS NtHeaders;
- BOOL rc;
- WCHAR szUnknown[32];
- /*
- * Check if the MessageBox style is within the logged severity level
- */
- switch (pMsgBoxParams->dwStyle & MB_ICONMASK) {
- case MB_ICONHAND:
- /*
- * when EMI is enabled, we at least log error messages
- */
- break;
- case MB_ICONEXCLAMATION:
- if (gdwEMIControl > EMI_SEVERITY_WARNING) {
- rc = TRUE;
- goto End;
- }
- break;
- case MB_ICONQUESTION:
- if (gdwEMIControl > EMI_SEVERITY_QUESTION) {
- rc = TRUE;
- goto End;
- }
- break;
- case MB_ICONASTERISK:
- if (gdwEMIControl > EMI_SEVERITY_INFORMATION) {
- rc = TRUE;
- goto End;
- }
- break;
- case MB_USERICON:
- if (gdwEMIControl > EMI_SEVERITY_USER) {
- rc = TRUE;
- goto End;
- }
- break;
- default:
- if (gdwEMIControl > EMI_SEVERITY_ALL) {
- rc = TRUE;
- goto End;
- }
- break;
- }
- if (gdwEMIThreadID != GETTHREADID()) {
- rc = FALSE;
- goto End;
- }
- RtlZeroMemory(&ErrEle, sizeof(ErrEle));
- /*
- * get last error first, check with FormatMessage???
- */
- ErrEle.dwErrorCode = GetLastError();
- /*
- * get return address
- */
- ErrEle.ReturnAddr = gpReturnAddr;
- /*
- * get the process image name
- */
- GetCurrentProcessName(ErrEle.ProcessName, ARRAY_SIZE(ErrEle.ProcessName));
- /*
- * Load the "unknown" string
- */
- LoadString(hmodUser, STR_UNKNOWN, szUnknown, ARRAYSIZE(szUnknown));
- /*
- * get the window title
- */
- GetWindowTextW(pMsgBoxParams->hwndOwner, ErrEle.WindowTitle, TITLE_SIZE);
- if (!(*(ErrEle.WindowTitle))) {
- lstrcpy(ErrEle.WindowTitle, szUnknown);
- }
- /*
- * get messagebox data
- */
- ErrEle.lpszText = (LPWSTR)pMsgBoxParams->lpszText;
- ErrEle.lpszCaption = (LPWSTR)pMsgBoxParams->lpszCaption;
- ErrEle.dwStyle = pMsgBoxParams->dwStyle;
- /*
- * resolve the module name of caller
- */
- if (!RtlPcToFileHeader((PVOID)ErrEle.ReturnAddr, &ImageBase)) {
- RIPMSG0(RIP_WARNING, "ErrorMessageInst: Can't find Caller");
- ErrEle.BaseAddr = (PVOID)-1;
- ErrEle.dwImageSize = -1;
- lstrcpy(ErrEle.CallerModuleName, szUnknown);
- } else {
- ErrEle.BaseAddr = ImageBase;
- if (GetModuleFileName((HMODULE)ImageBase, ErrEle.CallerModuleName, MAX_PATH)) {
- pwcs = wcsrchr(ErrEle.CallerModuleName, TEXT('\\'));
- if (pwcs) {
- pwcs++;
- lstrcpy(ErrEle.CallerModuleName, pwcs);
- }
- } else {
- lstrcpy(ErrEle.CallerModuleName, szUnknown);
- }
- NtHeaders = RtlImageNtHeader(ImageBase);
- if (NtHeaders == NULL) {
- ErrEle.dwImageSize = -1;
- } else {
- ErrEle.dwImageSize = NtHeaders->OptionalHeader.SizeOfImage;
- }
- }
- /*
- * Register the event if we haven't done so already.
- * Since RegisterEventSource is supported by a service, we must not hold
- * any locks while making this call. Hence we might have several threads
- * registering the event simultaneously.
- */
- if (!gEventSource) {
- gEventSource = RegisterEventSourceW(NULL, L"Error Instrument");
- if (!gEventSource) {
- ErrEle.dwErrorCode = GetLastError();
- rc = FALSE;
- }
- }
- /*
- * report event
- */
- if (gEventSource) {
- rc = LogMessageBox(&ErrEle);
- }
- /*
- * allow to process another event log again
- */
- InterlockedExchangePointer(&gdwEMIThreadID, 0);
- End:
- return rc;
- }
- /***************************************************************************\
- * InitInstrument
- *
- * Returns: TRUE - Initialization Success
- * FALSE - Initialization Fail
- *
- \***************************************************************************/
- BOOL InitInstrument(
- LPDWORD lpEMIControl)
- {
- NTSTATUS Status;
- HKEY hKeyEMI = NULL;
- UNICODE_STRING UnicodeStringEMIKey;
- UNICODE_STRING UnicodeStringEnable;
- UNICODE_STRING UnicodeStringStyle;
- OBJECT_ATTRIBUTES ObjA;
- DWORD EMIEnable = 0; //means disable
- DWORD EMISeverity;
- struct {
- KEY_VALUE_PARTIAL_INFORMATION;
- LARGE_INTEGER;
- } EMIValueInfo;
- DWORD dwDisposition;
- RtlInitUnicodeString(&UnicodeStringEMIKey, szEMIKey);
- InitializeObjectAttributes(&ObjA, &UnicodeStringEMIKey, OBJ_CASE_INSENSITIVE, NULL, NULL);
- Status = NtOpenKey(&hKeyEMI, KEY_READ, &ObjA);
- if (!NT_SUCCESS(Status)) {
- /*
- * Key doesn't exist, assume disable
- */
- return FALSE;
- }
- /*
- * read the logging enable and setting
- */
- RtlInitUnicodeString(&UnicodeStringEnable, szEMIEnable);
- Status = NtQueryValueKey(hKeyEMI,
- &UnicodeStringEnable,
- KeyValuePartialInformation,
- &EMIValueInfo,
- sizeof(EMIValueInfo),
- &dwDisposition);
- if (NT_SUCCESS(Status)) {
- RtlCopyMemory(&EMIEnable, &EMIValueInfo.Data, sizeof(EMIEnable));
- RtlInitUnicodeString(&UnicodeStringStyle, szEMISeverity);
- Status = NtQueryValueKey(hKeyEMI,
- &UnicodeStringStyle,
- KeyValuePartialInformation,
- &EMIValueInfo,
- sizeof(EMIValueInfo),
- &dwDisposition);
- if (NT_SUCCESS(Status)) {
- RtlCopyMemory(&EMISeverity, &EMIValueInfo.Data, sizeof(EMISeverity));
- /*
- * Validate data
- */
- if (EMISeverity > EMI_SEVERITY_MAX_VALUE) {
- EMISeverity = EMI_SEVERITY_MAX_VALUE;
- }
- } else {
- /*
- * default severity for instrument
- */
- EMISeverity = EMI_SEVERITY_WARNING;
- }
- *lpEMIControl = EMISeverity;
- }
- /*
- * read default message reply enable
- */
- RtlInitUnicodeString(&UnicodeStringEnable, szDMREnable);
- Status = NtQueryValueKey(hKeyEMI,
- &UnicodeStringEnable,
- KeyValuePartialInformation,
- &EMIValueInfo,
- sizeof(EMIValueInfo),
- &dwDisposition);
- if (NT_SUCCESS(Status)) {
- RtlCopyMemory(&gfDMREnable, &EMIValueInfo.Data, sizeof(gfDMREnable));
- }
- NtClose(hKeyEMI);
- if (EMIEnable) {
- /*
- * add eventlog file
- */
- if (NT_SUCCESS(CreateLogSource())) {
- return TRUE;
- }
- }
- return FALSE;
- }
- /***************************************************************************\
- * CreateLogSource
- *
- * Create the event source for eventlog
- * Return : NTSTATUS
- *
- \***************************************************************************/
- NTSTATUS CreateLogSource()
- {
- NTSTATUS Status;
- UNICODE_STRING UnicodeStringEventKey;
- OBJECT_ATTRIBUTES ObjA;
- HKEY hKeyEvent = NULL;
- UNICODE_STRING UnicodeString;
- DWORD dwDisposition;
- RtlInitUnicodeString(&UnicodeStringEventKey, szEventKey);
- InitializeObjectAttributes(&ObjA, &UnicodeStringEventKey, OBJ_CASE_INSENSITIVE, NULL, NULL);
- if (NT_SUCCESS(Status = NtOpenKey(&hKeyEvent, KEY_READ, &ObjA))) {
- struct {
- KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
- WCHAR awchMsgFileName[256];
- } MsgFile;
- RtlInitUnicodeString(&UnicodeString, szEventMsgFile);
- Status = NtQueryValueKey(hKeyEvent,
- &UnicodeString,
- KeyValuePartialInformation,
- &MsgFile,
- sizeof MsgFile,
- &dwDisposition);
- if (NT_SUCCESS(Status)) {
- Status = lstrcmpi((LPWSTR)MsgFile.KeyInfo.Data, L"%SystemRoot%\\System32\\user32.dll");
- }
- NtClose(hKeyEvent);
- }
- return Status;
- }
- /***************************************************************************\
- * LogMessageBox
- *
- * Output error message record into eventlog
- *
- \***************************************************************************/
- BOOL LogMessageBox(
- LPERROR_ELEMENT lpErrEle)
- {
- LPWSTR lps[8];
- DWORD dwData[2];
- WCHAR BaseAddress[19];
- WCHAR ImageSize[19];
- WCHAR ReturnAddress[19];
- PTOKEN_USER pTokenUser = NULL;
- PSID pSid = NULL;
- BOOL rc;
- lps[0] = lpErrEle->ProcessName;
- lps[1] = lpErrEle->WindowTitle;
- lps[2] = lpErrEle->lpszCaption;
- lps[3] = lpErrEle->lpszText;
- lps[4] = lpErrEle->CallerModuleName;
- wsprintf(BaseAddress, L"%-#16p", lpErrEle->BaseAddr);
- lps[5] = BaseAddress;
- wsprintf(ImageSize, L"%-#16lX", lpErrEle->dwImageSize);
- lps[6] = ImageSize;
- wsprintf(ReturnAddress, L"%-#16p", lpErrEle->ReturnAddr);
- lps[7] = ReturnAddress;
- dwData[0] = lpErrEle->dwStyle;
- dwData[1] = lpErrEle->dwErrorCode;
- if (GetUserSid(&pTokenUser)) {
- pSid = pTokenUser->User.Sid;
- }
- UserAssert(gEventSource != NULL);
- rc = ReportEventW(gEventSource,
- EVENTLOG_INFORMATION_TYPE,
- 0,
- STATUS_LOG_ERROR_MSG,
- pSid,
- ARRAY_SIZE(lps),
- sizeof(dwData),
- lps,
- dwData);
- if (pTokenUser) {
- VirtualFree(pTokenUser, 0, MEM_RELEASE);
- }
- return rc;
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment