Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2335 lines
72 KiB

/****************************** 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