Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

msgbox.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: msgbox.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains the MessageBox API and related functions. 00007 * 00008 * History: 00009 * 10-23-90 DarrinM Created. 00010 * 02-08-91 IanJa HWND revalidation added 00011 \***************************************************************************/ 00012 00013 #include "precomp.h" 00014 #pragma hdrstop 00015 00016 // 00017 // Dimension constants -- D.U. == dialog units 00018 // 00019 #define DU_OUTERMARGIN 7 00020 #define DU_INNERMARGIN 10 00021 00022 #define DU_BTNGAP 4 // D.U. of space between buttons 00023 #define DU_BTNHEIGHT 14 // D.U. of button height 00024 // This is used only in kernel\inctlpan.c, so move it there 00025 // 00026 // #define DU_BTNWIDTH 50 // D.U. of button width, minimum 00027 // 00028 00029 LPBYTE MB_UpdateDlgHdr(LPDLGTEMPLATE lpDlgTmp, long lStyle, long lExtendedStyle, BYTE bItemCount, 00030 int iX, int iY, int iCX, int iCY, LPWSTR lpszCaption, int iCaptionLen); 00031 LPBYTE MB_UpdateDlgItem(LPDLGITEMTEMPLATE lpDlgItem, int iCtrlId, long lStyle, long lExtendedStyle, 00032 int iX, int iY, int iCX, int iCY, LPWSTR lpszText, UINT wTextLen, 00033 int iControlClass); 00034 UINT MB_GetIconOrdNum(UINT rgBits); 00035 LPBYTE MB_AddPushButtons( 00036 LPDLGITEMTEMPLATE lpDlgTmp, 00037 LPMSGBOXDATA lpmb, 00038 UINT wLEdge, 00039 UINT wBEdge, 00040 DWORD dwStyleMsg); 00041 UINT MB_FindDlgTemplateSize( LPMSGBOXDATA lpmb ); 00042 int MessageBoxWorker(LPMSGBOXDATA pMsgBoxParams); 00043 VOID EndTaskModalDialog(HWND hwndDlg); 00044 VOID StartTaskModalDialog(HWND hwndDlg); 00045 00046 #ifdef _JANUS_ 00047 00048 // the definition for message file 00049 #include "strid.h" 00050 #include "imagehlp.h" 00051 00052 // constant strings 00053 CONST WCHAR szEMIKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Error Message Instrument\\"; 00054 CONST WCHAR szEMIEnable[] = L"EnableLogging"; 00055 CONST WCHAR szEMISeverity[] = L"LogSeverity"; 00056 CONST WCHAR szDMREnable[] = L"EnableDefaultReply"; 00057 CONST WCHAR szUnknown[] = L"Unknown"; 00058 CONST WCHAR szEventKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\EventLog\\Application\\Error Instrument\\"; 00059 CONST WCHAR szEventMsgFile[] = L"EventMessageFile"; 00060 CONST WCHAR szEventType[] = L"TypesSupported"; 00061 00062 #define TITLE_SIZE 64 00063 #define DATETIME_SIZE 32 00064 00065 #define EMI_SEVERITY_ALL 0 00066 #define EMI_SEVERITY_USER 1 00067 #define EMI_SEVERITY_INFORMATION 2 00068 #define EMI_SEVERITY_QUESTION 3 00069 #define EMI_SEVERITY_WARNING 4 00070 #define EMI_SEVERITY_ERROR 5 00071 #define EMI_SEVERITY_MAX_VALUE 5 00072 00073 // element of error message 00074 PVOID gpReturnAddr = 0; 00075 HANDLE gdwEMIThreadID = 0; 00076 typedef struct _ERROR_ELEMENT { 00077 WCHAR ProcessName[MAX_PATH]; 00078 WCHAR WindowTitle[TITLE_SIZE]; 00079 DWORD dwStyle; 00080 DWORD dwErrorCode; 00081 WCHAR CallerModuleName[MAX_PATH]; 00082 PVOID BaseAddr; 00083 DWORD dwImageSize; 00084 PVOID ReturnAddr; 00085 LPWSTR lpszCaption; 00086 LPWSTR lpszText; 00087 } ERROR_ELEMENT, *LPERROR_ELEMENT; 00088 00089 BOOL ErrorMessageInst(LPMSGBOXDATA pMsgBoxParams); 00090 BOOL InitInstrument(LPDWORD lpEMIControl); 00091 00092 // eventlog stuff 00093 FARPROC gfnRegisterEventSource; 00094 FARPROC gfnDeregisterEventSource; 00095 FARPROC gfnReportEvent; 00096 FARPROC gfnGetTokenInformation; 00097 FARPROC gfnOpenProcessToken; 00098 FARPROC gfnOpenThreadToken; 00099 HANDLE gEventSource; 00100 NTSTATUS CreateLogSource(); 00101 HANDLE RegisterLogSource(LPWSTR lpszSource); 00102 BOOL LogMessageBox(LPERROR_ELEMENT lpErrEle); 00103 BOOL GetUserSid(PTOKEN_USER *ppTokenUser); 00104 BOOL GetTokenHandle(PHANDLE pTokenHandle); 00105 00106 #define EMIGETRETURNADDRESS() \ 00107 { \ 00108 if (gfEMIEnable) { \ 00109 if (InterlockedCompareExchangePointer(&gdwEMIThreadID, \ 00110 GETTHREADID(), \ 00111 0) \ 00112 == 0) { \ 00113 gpReturnAddr = _ReturnAddress(); \ 00114 } \ 00115 } \ 00116 } 00117 #else 00118 #define EMIGETRETURNADDRESS() 00119 #endif //_JANUS_ 00120 00121 00122 00123 #define MB_MASKSHIFT 4 00124 00125 CONST WCHAR szEmpty[] = L""; 00126 WCHAR szERROR[10]; 00127 ATOM atomBwlProp; 00128 ATOM atomMsgBoxCallback; 00129 00130 /***************************************************************************\ 00131 * SendHelpMessage 00132 * 00133 * 00134 \***************************************************************************/ 00135 00136 void SendHelpMessage( 00137 HWND hwnd, 00138 int iType, 00139 int iCtrlId, 00140 HANDLE hItemHandle, 00141 DWORD dwContextId, 00142 MSGBOXCALLBACK lpfnCallback) 00143 { 00144 HELPINFO HelpInfo; 00145 long lValue; 00146 00147 HelpInfo.cbSize = sizeof(HELPINFO); 00148 HelpInfo.iContextType = iType; 00149 HelpInfo.iCtrlId = iCtrlId; 00150 HelpInfo.hItemHandle = hItemHandle; 00151 HelpInfo.dwContextId = dwContextId; 00152 00153 lValue = NtUserGetMessagePos(); 00154 HelpInfo.MousePos.x = GET_X_LPARAM(lValue); 00155 HelpInfo.MousePos.y = GET_Y_LPARAM(lValue); 00156 00157 // Check if there is an app supplied callback. 00158 if(lpfnCallback != NULL) { 00159 if (IsWOWProc(lpfnCallback)) { 00160 (*pfnWowMsgBoxIndirectCallback)(PtrToUlong(lpfnCallback), &HelpInfo); 00161 } else { 00162 (*lpfnCallback)(&HelpInfo); 00163 } 00164 } else { 00165 SendMessage(hwnd, WM_HELP, 0, (LPARAM)&HelpInfo); 00166 } 00167 } 00168 00169 00170 /***************************************************************************\ 00171 * ServiceMessageBox 00172 * 00173 * 00174 \***************************************************************************/ 00175 00176 CONST int aidReturn[] = { 0, 0, IDABORT, IDCANCEL, IDIGNORE, IDNO, IDOK, IDRETRY, IDYES }; 00177 00178 int ServiceMessageBox( 00179 LPCWSTR pText, 00180 LPCWSTR pCaption, 00181 UINT wType) 00182 { 00183 NTSTATUS Status; 00184 ULONG_PTR Parameters[3]; 00185 ULONG Response = ResponseNotHandled; 00186 UNICODE_STRING Text, Caption; 00187 00188 /* 00189 * For Terminal Services we must decided the session in which this message 00190 * box should be displayed. We do this by looking at the impersonation token 00191 * and use the session on which the client is running. 00192 */ 00193 if (ISTS()) { 00194 HANDLE TokenHandle; 00195 NTSTATUS Status; 00196 ULONG ClientSessionId; 00197 ULONG ProcessSessionId; 00198 ULONG ReturnLength; 00199 BOOLEAN bResult; 00200 00201 /* 00202 * Obtain access to the impersonation token if it's present. 00203 */ 00204 Status = NtOpenThreadToken ( 00205 GetCurrentThread(), 00206 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 00207 TRUE, 00208 &TokenHandle 00209 ); 00210 if ( NT_SUCCESS(Status) ) { 00211 /* 00212 * Query the Session ID out of the Token 00213 */ 00214 Status = NtQueryInformationToken ( 00215 TokenHandle, 00216 TokenSessionId, 00217 (PVOID)&ClientSessionId, 00218 sizeof(ClientSessionId), 00219 &ReturnLength 00220 ); 00221 CloseHandle(TokenHandle); 00222 if (NT_SUCCESS(Status)) { 00223 /* 00224 * Get the process session Id. Use the Kernel32 API first because 00225 * the PEB is writable in case someone is hacking it. 00226 */ 00227 if (!ProcessIdToSessionId(GetCurrentProcessId(), &ProcessSessionId)) { 00228 ProcessSessionId = NtCurrentPeb()->SessionId; 00229 } 00230 00231 if (ClientSessionId != ProcessSessionId) 00232 { 00233 /* 00234 * Make sure WinSta.Dll is loaded 00235 */ 00236 if (ghinstWinStaDll == NULL) { 00237 ghinstWinStaDll = LoadLibrary(L"winsta.dll"); 00238 00239 /* 00240 * Get the function pointer if WinSta.Dll loaded. 00241 */ 00242 if (ghinstWinStaDll != NULL) { 00243 gfnWinStationSendMessageW = GetProcAddress(ghinstWinStaDll, "WinStationSendMessageW"); 00244 } 00245 } 00246 00247 /* 00248 * This message box was intended for session other than the 00249 * one on which this process is running. Forward it to the 00250 * right session with WinStationSendMessage(). 00251 */ 00252 if (gfnWinStationSendMessageW != NULL) { 00253 00254 /* 00255 * Handle case where Caption or Title is NULL 00256 */ 00257 if (pCaption == NULL) 00258 pCaption = szEmpty; 00259 if (pText == NULL) 00260 pText = szEmpty; 00261 00262 bResult = (BOOLEAN)gfnWinStationSendMessageW( 00263 SERVERNAME_CURRENT, 00264 ClientSessionId, 00265 pCaption, 00266 wcslen( pCaption ) * sizeof( WCHAR ), 00267 pText, 00268 wcslen( pText ) * sizeof( WCHAR ), 00269 wType, 00270 -1, // Wait forever 00271 &Response, 00272 FALSE // always wait 00273 ); 00274 if (bResult != TRUE) 00275 Response = aidReturn[ResponseNotHandled]; 00276 else { 00277 if (Response == IDTIMEOUT || Response == IDERROR) { 00278 Response = aidReturn[ResponseNotHandled]; 00279 } 00280 } 00281 00282 return (int)Response; 00283 } 00284 } 00285 } 00286 } 00287 } 00288 00289 /* 00290 * MessageBox is for this session, go call CSR. 00291 */ 00292 RtlInitUnicodeString(&Text, pText); 00293 RtlInitUnicodeString(&Caption, pCaption); 00294 Parameters[0] = (ULONG_PTR)&Text; 00295 Parameters[1] = (ULONG_PTR)&Caption; 00296 Parameters[2] = wType; 00297 00298 /* 00299 * Compatibility: Pass the override bit to make sure this box always shows 00300 */ 00301 Status = NtRaiseHardError(STATUS_SERVICE_NOTIFICATION | HARDERROR_OVERRIDE_ERRORMODE, 00302 ARRAY_SIZE(Parameters), 00303 3, 00304 Parameters, 00305 OptionOk, 00306 &Response); 00307 00308 if (!NT_SUCCESS(Status)) { 00309 RIPNTERR0(Status, RIP_VERBOSE, ""); 00310 } 00311 00312 return aidReturn[Response]; 00313 } 00314 00315 00316 /***************************************************************************\ 00317 * MessageBox (API) 00318 * 00319 * History: 00320 * 11-20-90 DarrinM Ported from Win 3.0 sources. 00321 \***************************************************************************/ 00322 00323 int MessageBoxA( 00324 HWND hwndOwner, 00325 LPCSTR lpszText, 00326 LPCSTR lpszCaption, 00327 UINT wStyle) 00328 { 00329 EMIGETRETURNADDRESS(); 00330 return MessageBoxExA(hwndOwner, lpszText, lpszCaption, wStyle, 0); 00331 } 00332 00333 int MessageBoxW( 00334 HWND hwndOwner, 00335 LPCWSTR lpszText, 00336 LPCWSTR lpszCaption, 00337 UINT wStyle) 00338 { 00339 EMIGETRETURNADDRESS(); 00340 return MessageBoxExW(hwndOwner, lpszText, lpszCaption, wStyle, 0); 00341 } 00342 00343 00344 /***************************************************************************\ 00345 * MessageBoxEx (API) 00346 * 00347 * History: 00348 * 11-20-90 DarrinM Ported from Win 3.0 sources. 00349 \***************************************************************************/ 00350 00351 int MessageBoxExA( 00352 HWND hwndOwner, 00353 LPCSTR lpszText, 00354 LPCSTR lpszCaption, 00355 UINT wStyle, 00356 WORD wLanguageId) 00357 { 00358 int retval; 00359 LPWSTR lpwszText = NULL; 00360 LPWSTR lpwszCaption = NULL; 00361 00362 if (lpszText) { 00363 if (!MBToWCS(lpszText, -1, &lpwszText, -1, TRUE)) 00364 return 0; 00365 } 00366 00367 if (lpszCaption) { 00368 if (!MBToWCS(lpszCaption, -1, &lpwszCaption, -1, TRUE)) { 00369 UserLocalFree(lpwszText); 00370 return 0; 00371 } 00372 } 00373 00374 EMIGETRETURNADDRESS(); 00375 retval = MessageBoxExW(hwndOwner, 00376 lpwszText, 00377 lpwszCaption, 00378 wStyle, 00379 wLanguageId); 00380 00381 UserLocalFree(lpwszText); 00382 if (lpwszCaption) 00383 UserLocalFree(lpwszCaption); 00384 00385 return retval; 00386 } 00387 00388 int MessageBoxExW( 00389 HWND hwndOwner, 00390 LPCWSTR lpszText, 00391 LPCWSTR lpszCaption, 00392 UINT wStyle, 00393 WORD wLanguageId) 00394 { 00395 MSGBOXDATA MsgBoxParams; 00396 00397 00398 #if DBG 00399 /* 00400 * MB_USERICON is valid for MessageBoxIndirect only. 00401 * MessageBoxWorker validates the other style bits 00402 */ 00403 if (wStyle & MB_USERICON) { 00404 RIPMSG0(RIP_WARNING, "MessageBoxExW: Invalid flag: MB_USERICON"); 00405 } 00406 #endif 00407 00408 RtlZeroMemory(&MsgBoxParams, sizeof(MsgBoxParams)); 00409 MsgBoxParams.cbSize = sizeof(MSGBOXPARAMS); 00410 MsgBoxParams.hwndOwner = hwndOwner; 00411 MsgBoxParams.hInstance = NULL; 00412 MsgBoxParams.lpszText = lpszText; 00413 MsgBoxParams.lpszCaption = lpszCaption; 00414 MsgBoxParams.dwStyle = wStyle; 00415 MsgBoxParams.wLanguageId = wLanguageId; 00416 00417 EMIGETRETURNADDRESS(); 00418 return MessageBoxWorker(&MsgBoxParams); 00419 } 00420 00421 /**************************************************************************\ 00422 * MessageBoxIndirect (API) 00423 * 00424 * 09-30-94 FritzS Created 00425 \**************************************************************************/ 00426 00427 int MessageBoxIndirectA( 00428 CONST MSGBOXPARAMSA *lpmbp) 00429 { 00430 int retval; 00431 MSGBOXDATA MsgBoxParams; 00432 LPWSTR lpwszText = NULL; 00433 LPWSTR lpwszCaption = NULL; 00434 00435 if (lpmbp->cbSize != sizeof(MSGBOXPARAMS)) { 00436 RIPMSG0(RIP_WARNING, "MessageBoxIndirect: Invalid cbSize"); 00437 } 00438 00439 RtlZeroMemory(&MsgBoxParams, sizeof(MsgBoxParams)); 00440 RtlCopyMemory(&MsgBoxParams, lpmbp, sizeof(MSGBOXPARAMS)); 00441 00442 if (IS_PTR(MsgBoxParams.lpszText)) { 00443 if (!MBToWCS((LPSTR)MsgBoxParams.lpszText, -1, &lpwszText, -1, TRUE)) 00444 return 0; 00445 MsgBoxParams.lpszText = lpwszText; 00446 } 00447 if (IS_PTR(MsgBoxParams.lpszCaption)) { 00448 if (!MBToWCS((LPSTR)MsgBoxParams.lpszCaption, -1, &lpwszCaption, -1, TRUE)) { 00449 UserLocalFree(lpwszText); 00450 return 0; 00451 } 00452 MsgBoxParams.lpszCaption = lpwszCaption; 00453 } 00454 00455 EMIGETRETURNADDRESS(); 00456 retval = MessageBoxWorker(&MsgBoxParams); 00457 00458 if (lpwszText) 00459 UserLocalFree(lpwszText); 00460 if (lpwszCaption) 00461 UserLocalFree(lpwszCaption); 00462 00463 return retval; 00464 } 00465 00466 int MessageBoxIndirectW( 00467 CONST MSGBOXPARAMSW *lpmbp) 00468 { 00469 MSGBOXDATA MsgBoxParams; 00470 00471 if (lpmbp->cbSize != sizeof(MSGBOXPARAMS)) { 00472 RIPMSG0(RIP_WARNING, "MessageBoxIndirect: Invalid cbSize"); 00473 } 00474 00475 RtlZeroMemory(&MsgBoxParams, sizeof(MsgBoxParams)); 00476 RtlCopyMemory(&MsgBoxParams, lpmbp, sizeof(MSGBOXPARAMS)); 00477 00478 EMIGETRETURNADDRESS(); 00479 return MessageBoxWorker(&MsgBoxParams); 00480 } 00481 00482 /***************************************************************************\ 00483 * MessageBoxWorker (API) 00484 * 00485 * History: 00486 * 03-10-93 JohnL Created 00487 \***************************************************************************/ 00488 00489 int MessageBoxWorker( 00490 LPMSGBOXDATA pMsgBoxParams) 00491 { 00492 DWORD dwStyle = pMsgBoxParams->dwStyle; 00493 UINT wBtnCnt; 00494 UINT wDefButton; 00495 UINT i; 00496 UINT wBtnBeg; 00497 WCHAR szErrorBuf[64]; 00498 LPWSTR apstrButton[4]; 00499 int aidButton[4]; 00500 BOOL fCancel = FALSE; 00501 int retValue; 00502 MBSTRING* pMBString; 00503 00504 #if DBG 00505 if (dwStyle & ~MB_VALID) { 00506 RIPMSG2(RIP_WARNING, "MessageBoxWorker: Invalid flags, %#lx & ~%#lx != 0", 00507 dwStyle, MB_VALID); 00508 } 00509 #endif 00510 00511 #ifdef _JANUS_ 00512 /* 00513 * Error message instrument start here 00514 * Check EMI enable 00515 */ 00516 00517 if (gfEMIEnable) { 00518 if (!ErrorMessageInst(pMsgBoxParams)) 00519 RIPMSG0(RIP_WARNING, "MessageBoxWorker: Fail to instrument error msg"); 00520 }; 00521 00522 /* 00523 * Default Message Return: on unattended systems the default button 00524 * can be returned automatically without putting up the message box 00525 */ 00526 00527 if (gfDMREnable) { 00528 /* 00529 * validate the style and default button as in the main code path 00530 */ 00531 00532 /* 00533 * Validate the "type" of message box requested. 00534 */ 00535 if ((dwStyle & MB_TYPEMASK) > MB_LASTVALIDTYPE) { 00536 RIPERR0(ERROR_INVALID_MSGBOX_STYLE, RIP_VERBOSE, ""); 00537 return 0; 00538 } 00539 00540 wBtnCnt = mpTypeCcmd[dwStyle & MB_TYPEMASK] + 00541 ((dwStyle & MB_HELP) ? 1 : 0); 00542 00543 /* 00544 * Set the default button value 00545 */ 00546 wDefButton = (dwStyle & (UINT)MB_DEFMASK) / (UINT)(MB_DEFMASK & (MB_DEFMASK >> 3)); 00547 00548 if (wDefButton >= wBtnCnt) /* Check if valid */ 00549 wDefButton = 0; /* Set the first button if error */ 00550 00551 /* 00552 * return the default button 00553 */ 00554 return aidButton[ wDefButton ]; 00555 } 00556 #endif // _JANUS_ 00557 00558 /* 00559 * If lpszCaption is NULL, then use "Error!" string as the caption 00560 * string. 00561 * LATER: IanJa localize according to wLanguageId 00562 */ 00563 if (pMsgBoxParams->lpszCaption == NULL) { 00564 /* 00565 * Load the default error string if we haven't done it yet 00566 */ 00567 if (*szERROR == 0) { 00568 LoadStringW(hmodUser, STR_ERROR, szERROR, ARRAY_SIZE(szERROR)); 00569 } 00570 if (pMsgBoxParams->wLanguageId == 0) { 00571 pMsgBoxParams->lpszCaption = szERROR; 00572 } else { 00573 LoadStringOrError(hmodUser, 00574 STR_ERROR, 00575 szErrorBuf, 00576 sizeof(szErrorBuf)/sizeof(WCHAR), 00577 pMsgBoxParams->wLanguageId); 00578 00579 /* 00580 * If it didn't find the string, use the default language 00581 */ 00582 if (*szErrorBuf) { 00583 pMsgBoxParams->lpszCaption = szErrorBuf; 00584 } else { 00585 pMsgBoxParams->lpszCaption = szERROR; 00586 00587 RIPMSG1(RIP_WARNING, "MessageBoxWorker: STR_ERROR string resource for language %#lx not found", 00588 pMsgBoxParams->wLanguageId); 00589 } 00590 } 00591 } 00592 00593 /* 00594 * MB_SERVICE_NOTIFICATION had to be redefined because 00595 * Win95 defined MB_TOPMOST using the same value. 00596 * So for old apps, we map it to the new value 00597 */ 00598 00599 if((dwStyle & MB_TOPMOST) && (GetClientInfo()->dwExpWinVer < VER40)) { 00600 dwStyle &= ~MB_TOPMOST; 00601 dwStyle |= MB_SERVICE_NOTIFICATION; 00602 pMsgBoxParams->dwStyle = dwStyle; 00603 00604 RIPMSG1(RIP_WARNING, "MessageBoxWorker: MB_SERVICE_NOTIFICATION flag mapped. New dwStyle:%#lx", dwStyle); 00605 } 00606 00607 /* 00608 * For backward compatiblity, use MB_SERVICE_NOTIFICATION if 00609 * it's going to the default desktop. 00610 */ 00611 if (dwStyle & (MB_DEFAULT_DESKTOP_ONLY | MB_SERVICE_NOTIFICATION)) { 00612 00613 /* 00614 * Allow services to put up popups without getting 00615 * access to the current desktop. 00616 */ 00617 if (pMsgBoxParams->hwndOwner != NULL) { 00618 RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, ""); 00619 return 0; 00620 } 00621 00622 return ServiceMessageBox(pMsgBoxParams->lpszText, 00623 pMsgBoxParams->lpszCaption, 00624 dwStyle & ~MB_SERVICE_NOTIFICATION); 00625 } 00626 00627 /* 00628 * Make sure we have a valid window handle. 00629 */ 00630 if (pMsgBoxParams->hwndOwner && !IsWindow(pMsgBoxParams->hwndOwner)) { 00631 RIPERR0(ERROR_INVALID_WINDOW_HANDLE, RIP_VERBOSE, ""); 00632 return 0; 00633 } 00634 00635 /* 00636 * Validate the "type" of message box requested. 00637 */ 00638 if ((dwStyle & MB_TYPEMASK) > MB_LASTVALIDTYPE) { 00639 RIPERR0(ERROR_INVALID_MSGBOX_STYLE, RIP_VERBOSE, ""); 00640 return 0; 00641 } 00642 00643 wBtnCnt = mpTypeCcmd[dwStyle & MB_TYPEMASK] + 00644 ((dwStyle & MB_HELP) ? 1 : 0); 00645 00646 /* 00647 * Set the default button value 00648 */ 00649 wDefButton = (dwStyle & (UINT)MB_DEFMASK) / (UINT)(MB_DEFMASK & (MB_DEFMASK >> 3)); 00650 00651 if (wDefButton >= wBtnCnt) /* Check if valid */ 00652 wDefButton = 0; /* Set the first button if error */ 00653 00654 /* 00655 * Calculate the strings to use in the message box 00656 */ 00657 wBtnBeg = mpTypeIich[dwStyle & (UINT)MB_TYPEMASK]; 00658 for (i=0; i<wBtnCnt; i++) { 00659 00660 pMBString = &gpsi->MBStrings[SEBbuttons[wBtnBeg + i]]; 00661 /* 00662 * Pick up the string for the button. 00663 */ 00664 if (pMsgBoxParams->wLanguageId == 0) { 00665 apstrButton[i] = pMBString->szName; 00666 } else { 00667 WCHAR szButtonBuf[64]; 00668 // LATER is it possible to have button text greater than 64 chars 00669 00670 /* 00671 * BUG: gpsi->wMaxBtnSize might be too short for the length of this string... 00672 */ 00673 LoadStringOrError(hmodUser, 00674 pMBString->uStr, 00675 szButtonBuf, 00676 sizeof(szButtonBuf)/sizeof(WCHAR), 00677 pMsgBoxParams->wLanguageId); 00678 00679 /* 00680 * If it didn't find the string, use the default language. 00681 */ 00682 if (*szButtonBuf) { 00683 apstrButton[i] = TextAlloc(szButtonBuf); 00684 } else { 00685 apstrButton[i] = TextAlloc(pMBString->szName); 00686 00687 RIPMSG2(RIP_WARNING, "MessageBoxWorker: string resource %#lx for language %#lx not found", 00688 pMBString->uStr, 00689 pMsgBoxParams->wLanguageId); 00690 } 00691 } 00692 aidButton[i] = pMBString->uID; 00693 if (aidButton[i] == IDCANCEL) { 00694 fCancel = TRUE; 00695 } 00696 } 00697 00698 /* 00699 * Hackery: There are some apps that use MessageBox as initial error 00700 * indicators, such as mplay32, and we want this messagebox to be 00701 * visible regardless of waht was specified in the StartupInfo->wShowWindow 00702 * field. ccMail for instance starts all of its embedded objects hidden 00703 * but on win 3.1 the error message would show because they don't have 00704 * the startup info. 00705 */ 00706 NtUserModifyUserStartupInfoFlags(STARTF_USESHOWWINDOW, 0); 00707 00708 pMsgBoxParams->pidButton = aidButton; 00709 pMsgBoxParams->ppszButtonText = apstrButton; 00710 pMsgBoxParams->DefButton = wDefButton; 00711 pMsgBoxParams->cButtons = wBtnCnt; 00712 pMsgBoxParams->CancelId = ((dwStyle & MB_TYPEMASK) == 0) ? IDOK : (fCancel ? IDCANCEL : 0); 00713 retValue = SoftModalMessageBox(pMsgBoxParams); 00714 00715 if (pMsgBoxParams->wLanguageId != 0) { 00716 for (i=0; i<wBtnCnt; i++) 00717 UserLocalFree(apstrButton[i]); 00718 } 00719 00720 return retValue; 00721 } 00722 00723 #define MAX_RES_STRING 256 00724 00725 /***************************************************************************\ 00726 * 00727 * SoftModalMessageBox() 00728 * 00729 \***************************************************************************/ 00730 int SoftModalMessageBox(LPMSGBOXDATA lpmb) { 00731 LPBYTE lpDlgTmp; 00732 int cyIcon, cxIcon; 00733 int cxButtons; 00734 int cxMBMax; 00735 int cxText, cyText, xText; 00736 int cxBox, cyBox; 00737 int cxFoo, cxCaption; 00738 int xMB, yMB; 00739 HDC hdc; 00740 DWORD wIconOrdNum; 00741 DWORD wCaptionLen; 00742 DWORD wTextLen; 00743 WORD OrdNum[2]; // Must be an array or WORDs 00744 RECT rc; 00745 RECT rcWork; 00746 HCURSOR hcurOld; 00747 DWORD dwStyleMsg, dwStyleText; 00748 DWORD dwExStyleMsg = 0; 00749 DWORD dwStyleDlg; 00750 HWND hwndOwner; 00751 LPWSTR lpsz; 00752 int iRetVal = 0; 00753 HICON hIcon; 00754 HGLOBAL hTemplate = NULL; 00755 HGLOBAL hCaption = NULL; 00756 HGLOBAL hText = NULL; 00757 HINSTANCE hInstMsg = lpmb->hInstance; 00758 SIZE size; 00759 HFONT hFontOld = NULL; 00760 int cntMBox; 00761 PMONITOR pMonitor; 00762 00763 ConnectIfNecessary(); 00764 00765 dwStyleMsg = lpmb->dwStyle; 00766 00767 // 00768 // This code is disabled since Mirroring will take care of this. 00769 // 00770 #ifndef USE_MIRRORING 00771 if (dwStyleMsg & MB_RTLREADING) { 00772 dwExStyleMsg |= WS_EX_RTLREADING; 00773 } 00774 #endif 00775 if (dwStyleMsg & MB_RIGHT) { 00776 dwExStyleMsg |= WS_EX_RIGHT; 00777 } 00778 00779 if (!IS_PTR(lpmb->lpszCaption)) { 00780 00781 // won't ever be NULL because MessageBox sticks "Error!" in in that case 00782 if (hInstMsg && (hCaption = LocalAlloc(LPTR, MAX_RES_STRING * sizeof(WCHAR)))) { 00783 lpsz = (LPWSTR) hCaption; 00784 LoadString(hInstMsg, PTR_TO_ID(lpmb->lpszCaption), lpsz, MAX_RES_STRING); 00785 } else 00786 lpsz = NULL; 00787 00788 lpmb->lpszCaption = lpsz ? lpsz : szEmpty; 00789 } 00790 00791 if (!IS_PTR(lpmb->lpszText)) { 00792 // NULL not allowed 00793 if (hInstMsg && (hText = LocalAlloc(LPTR, MAX_RES_STRING * sizeof(WCHAR)))) { 00794 lpsz = (LPWSTR) hText; 00795 LoadString(hInstMsg, PTR_TO_ID(lpmb->lpszText), lpsz, MAX_RES_STRING); 00796 } else 00797 lpsz = NULL; 00798 00799 lpmb->lpszText = lpsz ? lpsz : szEmpty; 00800 } 00801 00802 #ifdef USE_MIRRORING 00803 // 00804 // Mirroring of MessageBox'es is only enabled if :- 00805 // 00806 // * MB_RTLREADING style has been specified in the MessageBox styles OR 00807 // * The first two code points of the MessageBox text are Right-To-Left 00808 // marks (RLMs = U+200f). 00809 // The feature of enable RTL mirroring if two consecutive RLMs are found 00810 // in the MB text is to acheive a no-code-change for localization of 00811 // of MessageBoxes for BiDi Apps. [samera] 00812 // 00813 if ((dwStyleMsg & MB_RTLREADING) || 00814 (lpmb->lpszText != NULL && (lpmb->lpszText[0] == UNICODE_RLM) && 00815 (lpmb->lpszText[1] == UNICODE_RLM))) { 00816 // 00817 // Set Mirroring so that MessageBox and its child controls 00818 // get mirrored. Otherwise, the message box and its child controls 00819 // are Left-To-Right. 00820 // 00821 dwExStyleMsg |= WS_EX_LAYOUTRTL; 00822 00823 // 00824 // And turn off any conflicting flags. 00825 // 00826 dwExStyleMsg &= ~WS_EX_RIGHT; 00827 if (dwStyleMsg & MB_RTLREADING) { 00828 dwStyleMsg &= ~MB_RTLREADING; 00829 dwStyleMsg ^= MB_RIGHT; 00830 } 00831 } 00832 #endif 00833 00834 00835 if ((dwStyleMsg & MB_ICONMASK) == MB_USERICON) 00836 hIcon = LoadIcon(hInstMsg, lpmb->lpszIcon); 00837 else 00838 hIcon = NULL; 00839 00840 // For compatibility reasons, we still allow the message box to come up. 00841 hwndOwner = lpmb->hwndOwner; 00842 00843 // For PowerBuilder4.0, we must make their messageboxes owned popups. Or, else 00844 // they get WM_ACTIVATEAPP and they install multiple keyboard hooks and get into 00845 // infinite loop later. 00846 // Bug #15896 -- WIN95B -- 2/17/95 -- SANKAR -- 00847 if(!hwndOwner) 00848 { 00849 WCHAR pwszLibFileName[MAX_PATH]; 00850 static WCHAR szPB040[] = L"PB040"; // Module name of PowerBuilder4.0 00851 WCHAR *pw1; 00852 00853 //Is this a win3.1 or older app? 00854 if(GetClientInfo()->dwExpWinVer <= VER31) 00855 { 00856 if (GetModuleFileName(NULL, pwszLibFileName, sizeof(pwszLibFileName)/sizeof(WCHAR)) == 0) goto getthedc; 00857 pw1 = pwszLibFileName + wcslen(pwszLibFileName) - 1; 00858 while (pw1 > pwszLibFileName) { 00859 if (*pw1 == TEXT('.')) *pw1-- = 0; 00860 else if (*pw1 == TEXT(':')) {pw1++; break;} 00861 else if (*pw1 == TEXT('\\')) {pw1++; break;} 00862 else pw1--; 00863 } 00864 // Is this the PowerBuilder 4.0 module? 00865 if(!_wcsicmp(pw1, szPB040)) 00866 hwndOwner = NtUserGetForegroundWindow(); // Make the MsgBox owned. 00867 } 00868 } 00869 getthedc: 00870 // Check if we're out of cache DCs until robustness... 00871 if (!(hdc = NtUserGetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE))) { 00872 00873 /* 00874 * The above call might fail for TIF_RESTRICTED processes 00875 * so check for the DC from the owner window 00876 */ 00877 if (!(hdc = NtUserGetDCEx(hwndOwner, NULL, DCX_WINDOW | DCX_CACHE))) 00878 goto SMB_Exit; 00879 } 00880 00881 // Figure out the types and dimensions of buttons 00882 00883 cxButtons = (lpmb->cButtons * gpsi->wMaxBtnSize) + ((lpmb->cButtons - 1) * XPixFromXDU(DU_BTNGAP, gpsi->cxMsgFontChar)); 00884 00885 // Ditto for the icon, if there is one. If not, cxIcon & cyIcon are 0. 00886 00887 if (wIconOrdNum = MB_GetIconOrdNum(dwStyleMsg)) { 00888 cxIcon = SYSMET(CXICON) + XPixFromXDU(DU_INNERMARGIN, gpsi->cxMsgFontChar); 00889 cyIcon = SYSMET(CYICON); 00890 } else 00891 cxIcon = cyIcon = 0; 00892 00893 hFontOld = SelectObject(hdc, gpsi->hCaptionFont); 00894 00895 // Find the max between the caption text and the buttons 00896 wCaptionLen = wcslen(lpmb->lpszCaption); 00897 GetTextExtentPoint(hdc, lpmb->lpszCaption, wCaptionLen, &size); 00898 cxCaption = size.cx + 2*SYSMET(CXSIZE); 00899 00900 // 00901 // The max width of the message box is 5/8 of the work area for most 00902 // countries. We will then try 6/8 and 7/8 if it won't fit. Then 00903 // we will use whole screen. 00904 // 00905 pMonitor = GetDialogMonitor(hwndOwner, MONITOR_DEFAULTTOPRIMARY); 00906 CopyRect(&rcWork, &pMonitor->rcWork); 00907 cxMBMax = MultDiv(rcWork.right - rcWork.left, 5, 8); 00908 00909 cxFoo = 2*XPixFromXDU(DU_OUTERMARGIN, gpsi->cxMsgFontChar); 00910 00911 SelectObject(hdc, gpsi->hMsgFont); 00912 00913 // 00914 // If the text doesn't fit in 5/8, try 7/8 of the screen 00915 // 00916 ReSize: 00917 // 00918 // The message box is as big as needed to hold the caption/text/buttons, 00919 // but not bigger than the maximum width. 00920 // 00921 00922 cxBox = cxMBMax - 2*SYSMET(CXFIXEDFRAME); 00923 00924 // Ask DrawText for the right cx and cy 00925 rc.left = 0; 00926 rc.top = 0; 00927 rc.right = cxBox - cxFoo - cxIcon; 00928 rc.bottom = rcWork.bottom - rcWork.top; 00929 cyText = DrawTextExW(hdc, (LPWSTR)lpmb->lpszText, -1, &rc, 00930 DT_CALCRECT | DT_WORDBREAK | DT_EXPANDTABS | 00931 DT_NOPREFIX | DT_EXTERNALLEADING | DT_EDITCONTROL, NULL); 00932 // 00933 // Make sure we have enough width to hold the buttons, in addition to 00934 // the icon+text. Always force the buttons. If they don't fit, it's 00935 // because the working area is small. 00936 // 00937 // 00938 // The buttons are centered underneath the icon/text. 00939 // 00940 cxText = rc.right - rc.left + cxIcon + cxFoo; 00941 cxBox = min(cxBox, max(cxText, cxCaption)); 00942 cxBox = max(cxBox, cxButtons + cxFoo); 00943 cxText = cxBox - cxFoo - cxIcon; 00944 00945 // 00946 // Now we know the text width for sure. Really calculate how high the 00947 // text will be. 00948 // 00949 rc.left = 0; 00950 rc.top = 0; 00951 rc.right = cxText; 00952 rc.bottom = rcWork.bottom - rcWork.top; 00953 cyText = DrawTextExW(hdc, (LPWSTR)lpmb->lpszText, -1, &rc, DT_CALCRECT | DT_WORDBREAK 00954 | DT_EXPANDTABS | DT_NOPREFIX | DT_EXTERNALLEADING | DT_EDITCONTROL, NULL); 00955 00956 // Find the window size. 00957 cxBox += 2*SYSMET(CXFIXEDFRAME); 00958 cyBox = 2*SYSMET(CYFIXEDFRAME) + SYSMET(CYCAPTION) + YPixFromYDU(2*DU_OUTERMARGIN + 00959 DU_INNERMARGIN + DU_BTNHEIGHT, gpsi->cyMsgFontChar); 00960 00961 cyBox += max(cyIcon, cyText); 00962 00963 // 00964 // If the message box doesn't fit on the working area, we'll try wider 00965 // sizes successively: 6/8 of work then 7/8 of screen. 00966 // 00967 if (cyBox > rcWork.bottom - rcWork.top) 00968 { 00969 int cxTemp; 00970 00971 cxTemp = MultDiv(rcWork.right - rcWork.left, 6, 8); 00972 00973 if (cxMBMax == MultDiv(rcWork.right - rcWork.left, 5, 8)) 00974 { 00975 cxMBMax = cxTemp; 00976 goto ReSize; 00977 } 00978 else if (cxMBMax == cxTemp) 00979 { 00980 // then let's try with rcMonitor 00981 CopyRect(&rcWork, &pMonitor->rcMonitor); 00982 cxMBMax = MultDiv(rcWork.right - rcWork.left, 7, 8); 00983 goto ReSize; 00984 } 00985 } 00986 00987 if (hFontOld) 00988 SelectFont(hdc, hFontOld); 00989 NtUserReleaseDC(NULL, hdc); 00990 00991 // Find the window position 00992 cntMBox = GetClientInfo()->pDeskInfo->cntMBox; 00993 00994 xMB = (rcWork.left + rcWork.right - cxBox) / 2 + (cntMBox * SYSMET(CXSIZE)); 00995 xMB = max(xMB, rcWork.left); 00996 yMB = (rcWork.top + rcWork.bottom - cyBox) / 2 + (cntMBox * SYSMET(CYSIZE)); 00997 yMB = max(yMB, rcWork.top); 00998 00999 // Bottom, right justify if we're going off the screen--but leave a 01000 // little gap 01001 01002 if (xMB + cxBox > rcWork.right) 01003 xMB = rcWork.right - SYSMET(CXEDGE) - cxBox; 01004 01005 // 01006 // Pin to the working area. If it won't fit, then pin to the screen 01007 // height. Bottom justify it at least if too big even for that, so 01008 // that the buttons are visible. 01009 // 01010 if (yMB + cyBox > rcWork.bottom) { 01011 yMB = rcWork.bottom - SYSMET(CYEDGE) - cyBox; 01012 if (yMB < rcWork.top) { 01013 yMB = pMonitor->rcMonitor.bottom - SYSMET(CYEDGE) - cyBox; 01014 } 01015 } 01016 01017 wTextLen = wcslen(lpmb->lpszText); 01018 01019 // Find out the memory required for the Dlg template and try to alloc it 01020 hTemplate = LocalAlloc(LMEM_ZEROINIT, MB_FindDlgTemplateSize(lpmb)); 01021 01022 if (!hTemplate) 01023 goto SMB_Exit; 01024 01025 lpDlgTmp = (LPBYTE) hTemplate; 01026 01027 // 01028 // Setup the dialog style for the message box 01029 // 01030 dwStyleDlg = WS_POPUPWINDOW | WS_CAPTION | DS_ABSALIGN | DS_NOIDLEMSG | 01031 DS_SETFONT | DS_3DLOOK; 01032 01033 if ((dwStyleMsg & MB_MODEMASK) == MB_SYSTEMMODAL) 01034 dwStyleDlg |= DS_SYSMODAL | DS_SETFOREGROUND; 01035 else 01036 dwStyleDlg |= DS_MODALFRAME | WS_SYSMENU; 01037 01038 if (dwStyleMsg & MB_SETFOREGROUND) 01039 dwStyleDlg |= DS_SETFOREGROUND; 01040 01041 // Add the Header of the Dlg Template 01042 // BOGUS !!! don't ADD bools 01043 lpDlgTmp = MB_UpdateDlgHdr((LPDLGTEMPLATE) lpDlgTmp, dwStyleDlg, dwExStyleMsg, 01044 (BYTE) (lpmb->cButtons + (wIconOrdNum != 0) + (lpmb->lpszText != NULL)), 01045 xMB, yMB, cxBox, cyBox, (LPWSTR)lpmb->lpszCaption, wCaptionLen); 01046 01047 // 01048 // Center the buttons 01049 // 01050 01051 cxFoo = (cxBox - 2*SYSMET(CXFIXEDFRAME) - cxButtons) / 2; 01052 01053 lpDlgTmp = MB_AddPushButtons((LPDLGITEMTEMPLATE)lpDlgTmp, lpmb, cxFoo, 01054 cyBox - SYSMET(CYCAPTION) - (2 * SYSMET(CYFIXEDFRAME)) - 01055 YPixFromYDU(DU_OUTERMARGIN, gpsi->cyMsgFontChar), dwStyleMsg); 01056 01057 // Add Icon, if any, to the Dlg template 01058 // 01059 // The icon is always top justified. If the text is shorter than the 01060 // height of the icon, we center it. Otherwise the text will start at 01061 // the top. 01062 // 01063 if (wIconOrdNum) { 01064 OrdNum[0] = 0xFFFF; // To indicate that an Ordinal number follows 01065 OrdNum[1] = (WORD) wIconOrdNum; 01066 01067 lpDlgTmp = MB_UpdateDlgItem((LPDLGITEMTEMPLATE)lpDlgTmp, IDUSERICON, // Control Id 01068 SS_ICON | WS_GROUP | WS_CHILD | WS_VISIBLE, 0, 01069 XPixFromXDU(DU_OUTERMARGIN, gpsi->cxMsgFontChar), // X co-ordinate 01070 YPixFromYDU(DU_OUTERMARGIN, gpsi->cyMsgFontChar), // Y co-ordinate 01071 0, 0, // For Icons, CX and CY are ignored, can be zero 01072 OrdNum, // Ordinal number of Icon 01073 sizeof(OrdNum)/sizeof(WCHAR), // Length of OrdNum 01074 STATICCODE); 01075 } 01076 01077 // Add the Text of the Message to the Dlg Template 01078 if (lpmb->lpszText) { 01079 // 01080 // Center the text if shorter than the icon. 01081 // 01082 if (cyText >= cyIcon) 01083 cxFoo = 0; 01084 else 01085 cxFoo = (cyIcon - cyText) / 2; 01086 01087 dwStyleText = SS_NOPREFIX | WS_GROUP | WS_CHILD | WS_VISIBLE | SS_EDITCONTROL; 01088 if (dwStyleMsg & MB_RIGHT) { 01089 dwStyleText |= SS_RIGHT; 01090 xText = cxBox - (SYSMET(CXSIZE) + cxText); 01091 } else { 01092 dwStyleText |= SS_LEFT; 01093 xText = cxIcon + XPixFromXDU(DU_INNERMARGIN, gpsi->cxMsgFontChar); 01094 } 01095 01096 MB_UpdateDlgItem((LPDLGITEMTEMPLATE)lpDlgTmp, -1, dwStyleText, dwExStyleMsg, xText, 01097 YPixFromYDU(DU_OUTERMARGIN, gpsi->cyMsgFontChar) + cxFoo, 01098 cxText, cyText, 01099 (LPWSTR)lpmb->lpszText, wTextLen, STATICCODE); 01100 } 01101 01102 // The dialog template is ready 01103 01104 // 01105 // Set the normal cursor 01106 // 01107 hcurOld = NtUserSetCursor(LoadCursor(NULL, IDC_ARROW)); 01108 01109 lpmb->lpszIcon = (LPWSTR) hIcon; // BUGBUG - How to diff this from a resource? 01110 01111 if (!(lpmb->dwStyle & MB_USERICON)) 01112 { 01113 int wBeep = (LOWORD(lpmb->dwStyle & MB_ICONMASK)) >> MB_MASKSHIFT; 01114 if (wBeep < USER_SOUND_MAX) { 01115 NtUserCallOneParam(wBeep, SFI_PLAYEVENTSOUND); 01116 } 01117 } 01118 01119 iRetVal = (int)InternalDialogBox(hmodUser, hTemplate, hwndOwner, 01120 MB_DlgProcW, (LPARAM) lpmb, FALSE); 01121 01122 // 01123 // Fix up return value 01124 if (iRetVal == -1) 01125 iRetVal = 0; /* Messagebox should also return error */ 01126 01127 // 01128 // If the messagebox contains only OK button, then its ID is changed as 01129 // IDCANCEL in MB_DlgProc; So, we must change it back to IDOK irrespective 01130 // of whether ESC is pressed or Carriage return is pressed; 01131 // 01132 if (((dwStyleMsg & MB_TYPEMASK) == MB_OK) && iRetVal) 01133 iRetVal = IDOK; 01134 01135 01136 // 01137 // Restore the previous cursor 01138 // 01139 if (hcurOld) 01140 NtUserSetCursor(hcurOld); 01141 01142 SMB_Exit: 01143 if (hTemplate) 01144 UserLocalFree(hTemplate); 01145 01146 if (hCaption) { 01147 UserLocalFree(hCaption); 01148 } 01149 01150 if (hText) { 01151 UserLocalFree(hText); 01152 } 01153 01154 return(iRetVal); 01155 } 01156 01157 /***************************************************************************\ 01158 * MB_CopyToClipboard 01159 * 01160 * Called in response to WM_COPY, it will save the title, message and button's 01161 * texts to the clipboard in CF_UNICODETEXT format. 01162 * 01163 * --------------------------- 01164 * Caption 01165 * --------------------------- 01166 * Text 01167 * --------------------------- 01168 * Button1 ... ButtonN 01169 * --------------------------- 01170 * 01171 * 01172 * History: 01173 * 08-03-97 MCostea Created 01174 \***************************************************************************/ 01175 01176 void MB_CopyToClipboard( 01177 HWND hwndDlg) 01178 { 01179 LPCWSTR lpszRead; 01180 LPWSTR lpszAll, lpszWrite; 01181 HANDLE hData; 01182 static WCHAR szLine[] = L"---------------------------\r\n"; 01183 UINT cBufSize, i, cWrote; 01184 LPMSGBOXDATA lpmb; 01185 01186 if (!(lpmb = (LPMSGBOXDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA))) 01187 return; 01188 01189 if (!OpenClipboard(hwndDlg)) 01190 return; 01191 01192 /* 01193 * Calculate the buffer size: 01194 * - the message text can be all \n, that will become \r\n 01195 * - there are a few extra \r\n (that's why 8) 01196 */ 01197 cBufSize = (lpmb->lpszCaption ? wcslen(lpmb->lpszCaption) : 0) + 01198 (lpmb->lpszText ? 2*wcslen(lpmb->lpszText) : 0) + 01199 4*sizeof(szLine) + 01200 lpmb->cButtons * gpsi->wMaxBtnSize + 01201 8; 01202 01203 cBufSize *= sizeof(WCHAR); 01204 01205 if (!(hData = UserGlobalAlloc(LHND, (LONG)(cBufSize))) ) { 01206 goto CloseClip; 01207 } 01208 01209 USERGLOBALLOCK(hData, lpszAll); 01210 UserAssert(lpszAll); 01211 01212 cWrote = wsprintf(lpszAll, L"%s%s\r\n%s", 01213 szLine, 01214 lpmb->lpszCaption ? lpmb->lpszCaption : L"", 01215 szLine); 01216 01217 lpszWrite = lpszAll + cWrote; 01218 lpszRead = lpmb->lpszText; 01219 /* 01220 * Change \n to \r\n in the text 01221 */ 01222 for (i = 0; *lpszRead; i++) { 01223 01224 if (*lpszRead == L'\n') 01225 *lpszWrite++ = L'\r'; 01226 01227 *lpszWrite++ = *lpszRead++; 01228 } 01229 01230 cWrote = wsprintf(lpszWrite, L"\r\n%s", szLine); 01231 lpszWrite += cWrote; 01232 01233 /* 01234 * Remove & from the button texts 01235 */ 01236 for (i = 0; i<lpmb->cButtons; i++) { 01237 01238 lpszRead = lpmb->ppszButtonText[i]; 01239 while (*lpszRead) { 01240 if (*lpszRead != L'&') { 01241 *lpszWrite++ = *lpszRead; 01242 } 01243 lpszRead++; 01244 } 01245 *lpszWrite++ = L' '; 01246 *lpszWrite++ = L' '; 01247 *lpszWrite++ = L' '; 01248 } 01249 wsprintf(lpszWrite, L"\r\n%s\0", szLine); 01250 01251 USERGLOBALUNLOCK(hData); 01252 01253 NtUserEmptyClipboard(); 01254 /* 01255 * If we just called EmptyClipboard in the context of a 16 bit 01256 * app then we also have to tell WOW to nix its 16 handle copy of 01257 * clipboard data. WOW does its own clipboard caching because 01258 * some 16 bit apps use clipboard data even after the clipboard 01259 * has been emptied. See the note in the server code. 01260 * 01261 * Note: this is another place (besides client\editec.c) where 01262 * EmptyClipboard is called* for a 16 bit app not going through WOW. 01263 * If we added others we might want to move this into EmptyClipboard 01264 * and have two versions. 01265 */ 01266 if (GetClientInfo()->CI_flags & CI_16BIT) { 01267 pfnWowEmptyClipBoard(); 01268 } 01269 01270 SetClipboardData(CF_UNICODETEXT, hData); 01271 01272 CloseClip: 01273 NtUserCloseClipboard(); 01274 01275 } 01276 01277 /***************************************************************************\ 01278 * MB_UpdateDlgHdr 01279 * 01280 * History: 01281 * 11-20-90 DarrinM Ported from Win 3.0 sources. 01282 \***************************************************************************/ 01283 01284 LPBYTE MB_UpdateDlgHdr( 01285 LPDLGTEMPLATE lpDlgTmp, 01286 long lStyle, 01287 long lExtendedStyle, 01288 BYTE bItemCount, 01289 int iX, 01290 int iY, 01291 int iCX, 01292 int iCY, 01293 LPWSTR lpszCaption, 01294 int cchCaptionLen) 01295 { 01296 LPTSTR lpStr; 01297 RECT rc; 01298 01299 /* 01300 * Adjust the rectangle dimensions. 01301 */ 01302 rc.left = iX + SYSMET(CXFIXEDFRAME); 01303 rc.top = iY + SYSMET(CYFIXEDFRAME); 01304 rc.right = iX + iCX - SYSMET(CXFIXEDFRAME); 01305 rc.bottom = iY + iCY - SYSMET(CYFIXEDFRAME); 01306 01307 01308 /* 01309 * Adjust for the caption. 01310 */ 01311 rc.top += SYSMET(CYCAPTION); 01312 01313 lpDlgTmp->style = lStyle; 01314 lpDlgTmp->dwExtendedStyle = lExtendedStyle; 01315 lpDlgTmp->cdit = bItemCount; 01316 lpDlgTmp->x = XDUFromXPix(rc.left, gpsi->cxMsgFontChar); 01317 lpDlgTmp->y = YDUFromYPix(rc.top, gpsi->cyMsgFontChar); 01318 lpDlgTmp->cx = XDUFromXPix(rc.right - rc.left, gpsi->cxMsgFontChar); 01319 lpDlgTmp->cy = YDUFromYPix(rc.bottom - rc.top, gpsi->cyMsgFontChar); 01320 01321 /* 01322 * Move pointer to variable length fields. No menu resource for 01323 * message box, a zero window class (means dialog box class). 01324 */ 01325 lpStr = (LPWSTR)(lpDlgTmp + 1); 01326 *lpStr++ = 0; // Menu 01327 lpStr = (LPWSTR)NextWordBoundary(lpStr); 01328 *lpStr++ = 0; // Class 01329 lpStr = (LPWSTR)NextWordBoundary(lpStr); 01330 01331 /* 01332 * NOTE: iCaptionLen may be less than the length of the Caption string; 01333 * So, DO NOT USE lstrcpy(); 01334 */ 01335 RtlCopyMemory(lpStr, lpszCaption, cchCaptionLen*sizeof(WCHAR)); 01336 lpStr += cchCaptionLen; 01337 *lpStr++ = TEXT('\0'); // Null terminate the caption str 01338 01339 /* 01340 * Font height of 0x7FFF means use the message box font 01341 */ 01342 *lpStr++ = 0x7FFF; 01343 01344 return NextDWordBoundary(lpStr); 01345 } 01346 01347 /***************************************************************************\ 01348 * MB_AddPushButtons 01349 * 01350 * History: 01351 * 11-20-90 DarrinM Ported from Win 3.0 sources. 01352 \***************************************************************************/ 01353 01354 LPBYTE MB_AddPushButtons( 01355 LPDLGITEMTEMPLATE lpDlgTmp, 01356 LPMSGBOXDATA lpmb, 01357 UINT wLEdge, 01358 UINT wBEdge, 01359 DWORD dwStyleMsg) 01360 { 01361 UINT wYValue; 01362 UINT i; 01363 UINT wHeight; 01364 UINT wCount = lpmb->cButtons; 01365 #ifdef USE_MIRRORING 01366 UNREFERENCED_PARAMETER(dwStyleMsg); 01367 #endif 01368 01369 wHeight = YPixFromYDU(DU_BTNHEIGHT, gpsi->cyMsgFontChar); 01370 01371 wYValue = wBEdge - wHeight; // Y co-ordinate for push buttons 01372 01373 #ifndef USE_MIRRORING 01374 /* 01375 * Since USE_MIRRORING is enabled now, this code is disabled 01376 * since Mirroring will take care of this. [samera] 01377 */ 01378 if ((dwStyleMsg & MB_RTLREADING) && (wCount > 1)) { 01379 wLEdge += ((wCount-1) * 01380 (gpsi->wMaxBtnSize + XPixFromXDU(DU_BTNGAP, gpsi->cxMsgFontChar))); 01381 } 01382 #endif 01383 01384 for (i = 0; i < wCount; i++) { 01385 01386 lpDlgTmp = (LPDLGITEMTEMPLATE)MB_UpdateDlgItem( 01387 lpDlgTmp, /* Ptr to template */ 01388 lpmb->pidButton[i], /* Control Id */ 01389 WS_TABSTOP | WS_CHILD | WS_VISIBLE | (i == 0 ? WS_GROUP : 0) | 01390 ((UINT)i == lpmb->DefButton ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON), 01391 0, 01392 wLEdge, /* X co-ordinate */ 01393 wYValue, /* Y co-ordinate */ 01394 gpsi->wMaxBtnSize, /* CX */ 01395 wHeight, /* CY */ 01396 lpmb->ppszButtonText[i], /* String for button */ 01397 (UINT)wcslen(lpmb->ppszButtonText[i]),/* Length */ 01398 BUTTONCODE); 01399 01400 /* 01401 * Get the X co-ordinate for the next Push button 01402 */ 01403 #ifndef USE_MIRRORING 01404 /* 01405 * Since USE_MIRRORING is enabled now, this code is disabled 01406 * since Mirroring will take care of this. [samera] 01407 */ 01408 if (dwStyleMsg & MB_RTLREADING) 01409 wLEdge -= gpsi->wMaxBtnSize + XPixFromXDU(DU_BTNGAP, gpsi->cxMsgFontChar); 01410 else 01411 #endif 01412 wLEdge += gpsi->wMaxBtnSize + XPixFromXDU(DU_BTNGAP, gpsi->cxMsgFontChar); 01413 } 01414 01415 return (LPBYTE)lpDlgTmp; 01416 } 01417 01418 /***************************************************************************\ 01419 * MB_UpdateDlgItem 01420 * 01421 * History: 01422 * 11-20-90 DarrinM Ported from Win 3.0 sources. 01423 \***************************************************************************/ 01424 01425 LPBYTE MB_UpdateDlgItem( 01426 LPDLGITEMTEMPLATE lpDlgItem, 01427 int iCtrlId, 01428 long lStyle, 01429 long lExtendedStyle, 01430 int iX, 01431 int iY, 01432 int iCX, 01433 int iCY, 01434 LPWSTR lpszText, 01435 UINT cchTextLen, 01436 int iControlClass) 01437 { 01438 LPWSTR lpStr; 01439 BOOL fIsOrdNum; 01440 01441 01442 lpDlgItem->x = XDUFromXPix(iX, gpsi->cxMsgFontChar); 01443 lpDlgItem->y = YDUFromYPix(iY, gpsi->cyMsgFontChar); 01444 lpDlgItem->cx = XDUFromXPix(iCX,gpsi->cxMsgFontChar); 01445 lpDlgItem->cy = YDUFromYPix(iCY,gpsi->cyMsgFontChar); 01446 lpDlgItem->id = (WORD)iCtrlId; 01447 lpDlgItem->style = lStyle; 01448 lpDlgItem->dwExtendedStyle = lExtendedStyle; 01449 01450 /* 01451 * We have to avoid the following nasty rounding off problem: 01452 * (e.g) If iCX=192 and cxSysFontChar=9, then cx becomes 85; When the 01453 * static text is drawn, from 85 dlg units we get 191 pixels; So, the text 01454 * is truncated; 01455 * So, to avoid this, check if this is a static text and if so, 01456 * add one more dialog unit to cx and cy; 01457 * --Fix for Bug #4481 --SANKAR-- 09-29-89-- 01458 */ 01459 01460 /* 01461 * Also, make sure we only do this to static text items. davidds 01462 */ 01463 01464 /* 01465 * Now static text uses SS_NOPREFIX = 0x80; 01466 * So, test the lStyle field only with 0x0F instead of 0xFF; 01467 * Fix for Bugs #5933 and 5935 --SANKAR-- 11-28-89 01468 */ 01469 if (iControlClass == STATICCODE && 01470 (((lStyle & 0x0F) == SS_LEFT) || ((lStyle & 0x0F) == SS_RIGHT))) { 01471 01472 /* 01473 * This is static text 01474 */ 01475 lpDlgItem->cx++; 01476 lpDlgItem->cy++; 01477 } 01478 01479 /* 01480 * Move ptr to the variable fields 01481 */ 01482 lpStr = (LPWSTR)(lpDlgItem + 1); 01483 01484 /* 01485 * Store the Control Class value 01486 */ 01487 *lpStr++ = 0xFFFF; 01488 *lpStr++ = (BYTE)iControlClass; 01489 lpStr = (LPWSTR)NextWordBoundary(lpStr); // WORD-align lpszText 01490 01491 /* 01492 * Check if the String contains Ordinal number or not 01493 */ 01494 fIsOrdNum = ((*lpszText == 0xFFFF) && (cchTextLen == sizeof(DWORD)/sizeof(WCHAR))); 01495 01496 /* 01497 * NOTE: cchTextLen may be less than the length of lpszText. So, 01498 * DO NOT USE lstrcpy() for the copy. 01499 */ 01500 RtlCopyMemory(lpStr, lpszText, cchTextLen*sizeof(WCHAR)); 01501 lpStr = lpStr + cchTextLen; 01502 if (!fIsOrdNum) { 01503 *lpStr = TEXT('\0'); // NULL terminate the string 01504 lpStr = (LPWSTR)NextWordBoundary(lpStr + 1); 01505 } 01506 01507 *lpStr++ = 0; // sizeof control data (there is none) 01508 01509 return NextDWordBoundary(lpStr); 01510 } 01511 01512 01513 /***************************************************************************\ 01514 * MB_FindDlgTemplateSize 01515 * 01516 * This routine computes the amount of memory that will be needed for the 01517 * messagebox's dialog template structure. The dialog template has several 01518 * required and optional records. The dialog manager expects each record to 01519 * be DWORD aligned so any necessary padding is also accounted for. 01520 * 01521 * (header - required) 01522 * DLGTEMPLATE (header) + 1 menu byte + 1 pad + 1 class byte + 1 pad 01523 * szCaption + 0 term + DWORD alignment 01524 * 01525 * (static icon control - optional) 01526 * DLGITEMTEMPLATE + 1 class byte + 1 pad + (0xFF00 + icon ordinal # [szText]) + 01527 * UINT alignment + 1 control data length byte (0) + DWORD alignment 01528 * 01529 * (pushbutton controls - variable, but at least one required) 01530 * DLGITEMTEMPLATE + 1 class byte + 1 pad + length of button text + 01531 * UINT alignment + 1 control data length byte (0) + DWORD alignment 01532 * 01533 * (static text control - optional) 01534 * DLGITEMTEMPLATE + 1 class byte + 1 pad + length of text + 01535 * UINT alignment + 1 control data length byte (0) + DWORD alignment 01536 * 01537 * History: 01538 * 11-20-90 DarrinM Ported from Win 3.0 sources. 01539 \***************************************************************************/ 01540 01541 UINT MB_FindDlgTemplateSize( LPMSGBOXDATA lpmb ) 01542 { 01543 ULONG_PTR cbLen; 01544 UINT cbT; 01545 UINT i; 01546 UINT wCount; 01547 01548 wCount = lpmb->cButtons; 01549 01550 /* 01551 * Start with dialog header's size. 01552 */ 01553 cbLen = (ULONG_PTR)NextWordBoundary(sizeof(DLGTEMPLATE) + sizeof(WCHAR)); 01554 cbLen = (ULONG_PTR)NextWordBoundary(cbLen + sizeof(WCHAR)); 01555 cbLen += wcslen(lpmb->lpszCaption) * sizeof(WCHAR) + sizeof(WCHAR); 01556 cbLen += sizeof(WORD); // Font height 01557 cbLen = (ULONG_PTR)NextDWordBoundary(cbLen); 01558 01559 /* 01560 * Check if an Icon is present. 01561 */ 01562 if (lpmb->dwStyle & MB_ICONMASK) 01563 cbLen += (ULONG_PTR)NextDWordBoundary(sizeof(DLGITEMTEMPLATE) + 7 * sizeof(WCHAR)); 01564 01565 /* 01566 * Find the number of buttons in the msg box. 01567 */ 01568 for (i = 0; i < wCount; i++) { 01569 cbLen = (ULONG_PTR)NextWordBoundary(cbLen + sizeof(DLGITEMTEMPLATE) + 01570 (2 * sizeof(WCHAR))); 01571 cbT = (wcslen(lpmb->ppszButtonText[i]) + 1) * sizeof(WCHAR); 01572 cbLen = (ULONG_PTR)NextWordBoundary(cbLen + cbT); 01573 cbLen += sizeof(WCHAR); 01574 cbLen = (ULONG_PTR)NextDWordBoundary(cbLen); 01575 } 01576 01577 /* 01578 * Add in the space required for the text message (if there is one). 01579 */ 01580 if (lpmb->lpszText != NULL) { 01581 cbLen = (ULONG_PTR)NextWordBoundary(cbLen + sizeof(DLGITEMTEMPLATE) + 01582 (2 * sizeof(WCHAR))); 01583 cbT = (wcslen(lpmb->lpszText) + 1) * sizeof(WCHAR); 01584 cbLen = (ULONG_PTR)NextWordBoundary(cbLen + cbT); 01585 cbLen += sizeof(WCHAR); 01586 cbLen = (ULONG_PTR)NextDWordBoundary(cbLen); 01587 } 01588 01589 return (UINT)cbLen; 01590 } 01591 01592 /***************************************************************************\ 01593 * MB_GetIconOrdNum 01594 * 01595 * History: 01596 * 11-20-90 DarrinM Ported from Win 3.0 sources. 01597 \***************************************************************************/ 01598 01599 UINT MB_GetIconOrdNum( 01600 UINT rgBits) 01601 { 01602 switch (rgBits & MB_ICONMASK) { 01603 case MB_USERICON: 01604 case MB_ICONHAND: 01605 return PtrToUlong(IDI_HAND); 01606 01607 case MB_ICONQUESTION: 01608 return PtrToUlong(IDI_QUESTION); 01609 01610 case MB_ICONEXCLAMATION: 01611 return PtrToUlong(IDI_EXCLAMATION); 01612 01613 case MB_ICONASTERISK: 01614 return PtrToUlong(IDI_ASTERISK); 01615 } 01616 01617 return 0; 01618 } 01619 01620 /***************************************************************************\ 01621 * MB_GetString 01622 * 01623 * History: 01624 * 1-24-95 JerrySh Created. 01625 \***************************************************************************/ 01626 01627 LPWSTR MB_GetString( 01628 UINT wBtn) 01629 { 01630 if (wBtn < MAX_SEB_STYLES) 01631 return GETGPSIMBPSTR(wBtn); 01632 01633 RIPMSG1(RIP_ERROR, "Invalid wBtn: %d", wBtn); 01634 01635 return NULL; 01636 } 01637 01638 /***************************************************************************\ 01639 * MB_DlgProc 01640 * 01641 * Returns: TRUE - message processed 01642 * FALSE - message not processed 01643 * 01644 * History: 01645 * 11-20-90 DarrinM Ported from Win 3.0 sources. 01646 \***************************************************************************/ 01647 01648 INT_PTR MB_DlgProcWorker( 01649 HWND hwndDlg, 01650 UINT wMsg, 01651 WPARAM wParam, 01652 LPARAM lParam, 01653 BOOL fAnsi) 01654 { 01655 HWND hwndT; 01656 int iCount; 01657 LPMSGBOXDATA lpmb; 01658 HWND hwndOwner; 01659 PVOID lpfnCallback; 01660 PWND pwnd; 01661 01662 switch (wMsg) { 01663 case WM_CTLCOLORDLG: 01664 case WM_CTLCOLORSTATIC: 01665 if ((pwnd = ValidateHwnd(hwndDlg)) == NULL) 01666 return 0L; 01667 return DefWindowProcWorker(pwnd, WM_CTLCOLORMSGBOX, 01668 wParam, lParam, fAnsi); 01669 01670 case WM_INITDIALOG: 01671 01672 lpmb = (LPMSGBOXDATA)lParam; 01673 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (ULONG_PTR)lParam); 01674 01675 NtUserCallHwnd(hwndDlg, SFI_SETMSGBOX); 01676 01677 /* 01678 * Create the message box atoms, if we haven't done it yet 01679 */ 01680 if (atomBwlProp == 0) { 01681 atomBwlProp = AddAtomW(WINDOWLIST_PROP_NAME); 01682 atomMsgBoxCallback = AddAtomW(MSGBOX_CALLBACK); 01683 01684 if (atomBwlProp == 0 || atomMsgBoxCallback == 0) { 01685 RIPMSG0(RIP_WARNING, "MB_DlgProcWorker: AddAtomW failed. Out of memory?"); 01686 } 01687 } 01688 01689 if (lpmb->dwStyle & MB_HELP) { 01690 NtUserSetWindowContextHelpId(hwndDlg, lpmb->dwContextHelpId); 01691 //See if there is an app supplied callback. 01692 if(lpmb->lpfnMsgBoxCallback) 01693 SetProp(hwndDlg, MAKEINTATOM(atomMsgBoxCallback), 01694 lpmb->lpfnMsgBoxCallback); 01695 } 01696 01697 if (lpmb->dwStyle & MB_TOPMOST) 01698 NtUserSetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 01699 01700 if (lpmb->dwStyle & MB_USERICON) { 01701 SendDlgItemMessage(hwndDlg, IDUSERICON, STM_SETICON, (WPARAM)(lpmb->lpszIcon), 0); 01702 iCount = ALERT_SYSTEM_WARNING; 01703 } else { 01704 /* 01705 * Generate an alert notification 01706 */ 01707 switch (lpmb->dwStyle & MB_ICONMASK) { 01708 case MB_ICONWARNING: 01709 iCount = ALERT_SYSTEM_WARNING; 01710 break; 01711 01712 case MB_ICONQUESTION: 01713 iCount = ALERT_SYSTEM_QUERY; 01714 break; 01715 01716 case MB_ICONERROR: 01717 iCount = ALERT_SYSTEM_ERROR; 01718 break; 01719 01720 case MB_ICONINFORMATION: 01721 default: 01722 iCount = ALERT_SYSTEM_INFORMATIONAL; 01723 break; 01724 } 01725 } 01726 01727 if (FWINABLE()) { 01728 NotifyWinEvent(EVENT_SYSTEM_ALERT, hwndDlg, OBJID_ALERT, iCount); 01729 } 01730 01731 #ifdef LATER 01732 // darrinm - 06/17/91 01733 // SYSMODAL dialogs are history for now. 01734 01735 /* 01736 * Check if the Dialog box is a Sys Modal Dialog Box 01737 */ 01738 if (GetWindowLong(hwndDlg, GWL_STYLE) & DS_SYSMODAL, FALSE) 01739 SetSysModalWindow(hwndDlg); 01740 #endif 01741 01742 if ((lpmb->hwndOwner == NULL) && 01743 ((lpmb->dwStyle & MB_MODEMASK) == MB_TASKMODAL)) { 01744 StartTaskModalDialog(hwndDlg); 01745 } 01746 01747 /* 01748 * Set focus on the default button 01749 */ 01750 hwndT = GetWindow(hwndDlg, GW_CHILD); 01751 iCount = lpmb->DefButton; 01752 while (iCount--) 01753 hwndT = GetWindow(hwndT, GW_HWNDNEXT); 01754 01755 NtUserSetFocus(hwndT); 01756 01757 // 01758 // If this dialogbox does not contain a IDCANCEL button, then 01759 // remove the CLOSE command from the system menu. 01760 // Bug #4445, --SANKAR-- 09-13-89 -- 01761 // 01762 if (lpmb->CancelId == 0) 01763 { 01764 HMENU hMenu; 01765 if (hMenu = NtUserGetSystemMenu(hwndDlg, FALSE)) 01766 NtUserDeleteMenu(hMenu, SC_CLOSE, (UINT)MF_BYCOMMAND); 01767 } 01768 01769 if ((lpmb->dwStyle & MB_TYPEMASK) == MB_OK) 01770 { 01771 // 01772 // Make the ID of OK button to be CANCEL, because we want 01773 // the ESC to terminate the dialogbox; GetDlgItem32() will 01774 // not fail, because this is MB_OK messagebox! 01775 // 01776 01777 hwndDlg = GetDlgItem(hwndDlg, IDOK); 01778 01779 if (hwndDlg != NULL) { 01780 // hwndDlg->hMenu = (HMENU)IDCANCEL; 01781 SetWindowLongPtr(hwndDlg, GWLP_ID, IDCANCEL); 01782 } else { 01783 RIPMSG0(RIP_WARNING, "MB_DlgProcWorker - IDOK control not found"); 01784 } 01785 } 01786 01787 /* 01788 * We have changed the input focus 01789 */ 01790 return FALSE; 01791 01792 case WM_HELP: 01793 // When user hits an F1 key, it results in this message. 01794 // It is possible that this MsgBox has a callback instead of a 01795 // parent. So, we must behave as if the user hit the HELP button. 01796 01797 goto MB_GenerateHelp; 01798 01799 case WM_COMMAND: 01800 switch (LOWORD(wParam)) { 01801 case IDOK: 01802 case IDCANCEL: 01803 // 01804 // Check if a control exists with the given ID; This 01805 // check is needed because DlgManager returns IDCANCEL 01806 // blindly when ESC is pressed even if a button with 01807 // IDCANCEL is not present. 01808 // Bug #4445 --SANKAR--09-13-1989-- 01809 // 01810 if (!GetDlgItem(hwndDlg, LOWORD(wParam))) 01811 return FALSE; 01812 01813 01814 // else FALL THRO....This is intentional. 01815 case IDABORT: 01816 case IDIGNORE: 01817 case IDNO: 01818 case IDRETRY: 01819 case IDYES: 01820 case IDTRYAGAIN: 01821 case IDCONTINUE: 01822 EndTaskModalDialog(hwndDlg); 01823 EndDialog(hwndDlg, LOWORD(wParam)); 01824 break; 01825 case IDHELP: 01826 MB_GenerateHelp: 01827 // Generate the WM_HELP message and send it to owner or callback 01828 hwndOwner = NULL; 01829 01830 // Check if there is an app supplied callback for this MsgBox 01831 if(!(lpfnCallback = (PVOID)GetProp(hwndDlg, 01832 MAKEINTATOM(atomMsgBoxCallback)))) { 01833 // If not, see if we need to inform the parent. 01834 hwndOwner = GetWindow(hwndDlg, GW_OWNER); 01835 #ifdef LATER 01836 // Chicagoism 01837 if (hwndOwner && hwndOwner == GetDesktopWindow()) 01838 hwndOwner = NULL; 01839 #endif 01840 } 01841 01842 // See if we need to generate the Help message or call back. 01843 if (hwndOwner || lpfnCallback) { 01844 SendHelpMessage(hwndOwner, HELPINFO_WINDOW, IDHELP, 01845 hwndDlg, NtUserGetWindowContextHelpId(hwndDlg), lpfnCallback); 01846 } 01847 break; 01848 01849 default: 01850 return(FALSE); 01851 break; 01852 } 01853 break; 01854 01855 case WM_COPY: 01856 MB_CopyToClipboard(hwndDlg); 01857 break; 01858 01859 default: 01860 return FALSE; 01861 } 01862 01863 return TRUE; 01864 } 01865 01866 INT_PTR WINAPI MB_DlgProcA( 01867 HWND hwnd, 01868 UINT message, 01869 WPARAM wParam, 01870 LPARAM lParam) 01871 { 01872 return MB_DlgProcWorker(hwnd, message, wParam, lParam, TRUE); 01873 } 01874 01875 INT_PTR WINAPI MB_DlgProcW( 01876 HWND hwnd, 01877 UINT message, 01878 WPARAM wParam, 01879 LPARAM lParam) 01880 { 01881 return MB_DlgProcWorker(hwnd, message, wParam, lParam, FALSE); 01882 } 01883 01884 01885 /***************************************************************************\ 01886 * StartTaskModalDialog 01887 * 01888 * History: 01889 * 11-20-90 DarrinM Ported from Win 3.0 sources. 01890 \***************************************************************************/ 01891 01892 void StartTaskModalDialog( 01893 HWND hwndDlg) 01894 { 01895 int cHwnd; 01896 HWND *phwnd; 01897 HWND *phwndList, *phwndEnd; 01898 HWND hwnd; 01899 PWND pwnd; 01900 01901 /* 01902 * Get the hwnd list. It is returned in a block of memory 01903 * allocated with LocalAlloc. 01904 */ 01905 if ((cHwnd = BuildHwndList(NULL, NULL, FALSE, GetCurrentThreadId(), &phwndList)) == 0) { 01906 return; 01907 } 01908 /* 01909 * If atomBwlProp couldn't be added in WM_INITDIALOG processing, SetProp will fail 01910 * and we need to free the hwndList as EndTaskModalDialog will not be able to do that 01911 * MCostea 226543 01912 */ 01913 if (!SetProp(hwndDlg, MAKEINTATOM(atomBwlProp), (HANDLE)phwndList)) { 01914 UserLocalFree(phwndList); 01915 return; 01916 } 01917 01918 phwndEnd = phwndList + cHwnd; 01919 for (phwnd = phwndList; phwnd < phwndEnd; phwnd++) { 01920 if ((hwnd = *phwnd) == NULL || (pwnd = RevalidateHwnd(hwnd)) == NULL) 01921 continue; 01922 01923 /* 01924 * if the window belongs to the current task and is enabled, disable 01925 * it. All other windows are NULL'd out, to prevent their being 01926 * enabled later 01927 */ 01928 if (!TestWF(pwnd, WFDISABLED) && DIFFWOWHANDLE(hwnd, hwndDlg)) { 01929 NtUserEnableWindow(hwnd, FALSE); 01930 } else { 01931 *phwnd = NULL; 01932 } 01933 } 01934 } 01935 01936 01937 /***************************************************************************\ 01938 * EndTaskModalDialog 01939 * 01940 * History: 01941 * 11-20-90 DarrinM Ported from Win 3.0 sources. 01942 \***************************************************************************/ 01943 01944 void EndTaskModalDialog( 01945 HWND hwndDlg) 01946 { 01947 HWND *phwnd; 01948 HWND *phwndList; 01949 HWND hwnd; 01950 01951 phwndList = (HWND *)GetProp(hwndDlg, MAKEINTATOM(atomBwlProp)); 01952 01953 if (phwndList == NULL) 01954 return; 01955 01956 RemoveProp(hwndDlg, MAKEINTATOM(atomBwlProp)); 01957 01958 for (phwnd = phwndList; *phwnd != (HWND)1; phwnd++) { 01959 if ((hwnd = *phwnd) != NULL) { 01960 NtUserEnableWindow(hwnd, TRUE); 01961 } 01962 } 01963 01964 UserLocalFree(phwndList); 01965 } 01966 01967 #ifdef _JANUS_ 01968 /***************************************************************************\ 01969 * ErrorMessageInst 01970 * 01971 * Instrument routine for recording error msg 01972 * 01973 * Returns: TRUE - Instrument error msg Success 01974 * FALSE - Fail 01975 * 01976 * History: 01977 * 8-5-98 Chienho Created 01978 \***************************************************************************/ 01979 01980 BOOL ErrorMessageInst( 01981 LPMSGBOXDATA pMsgBoxParams) 01982 { 01983 ERROR_ELEMENT ErrEle; 01984 WCHAR *pwcs; 01985 PVOID ImageBase; 01986 PIMAGE_NT_HEADERS NtHeaders; 01987 BOOL rc; 01988 01989 /* 01990 * Check if the MessageBox style is within the logged severity level 01991 */ 01992 switch (pMsgBoxParams->dwStyle & MB_ICONMASK) { 01993 case MB_ICONHAND: 01994 /* 01995 * when EMI is enabled, we at least log error messages 01996 */ 01997 break; 01998 case MB_ICONEXCLAMATION: 01999 if (gdwEMIControl > EMI_SEVERITY_WARNING) { 02000 rc = TRUE; 02001 goto End; 02002 } 02003 break; 02004 case MB_ICONQUESTION: 02005 if (gdwEMIControl > EMI_SEVERITY_QUESTION) { 02006 rc = TRUE; 02007 goto End; 02008 } 02009 break; 02010 case MB_ICONASTERISK: 02011 if (gdwEMIControl > EMI_SEVERITY_INFORMATION) { 02012 rc = TRUE; 02013 goto End; 02014 } 02015 break; 02016 case MB_USERICON: 02017 if (gdwEMIControl > EMI_SEVERITY_USER) { 02018 rc = TRUE; 02019 goto End; 02020 } 02021 break; 02022 default: 02023 if (gdwEMIControl > EMI_SEVERITY_ALL) { 02024 rc = TRUE; 02025 goto End; 02026 } 02027 break; 02028 } 02029 02030 if (gdwEMIThreadID != GETTHREADID()) { 02031 rc = FALSE; 02032 goto End; 02033 } 02034 RtlZeroMemory(&ErrEle, sizeof(ErrEle)); 02035 02036 /* 02037 * get last error first, check with FormatMessage??? 02038 */ 02039 ErrEle.dwErrorCode = GetLastError(); 02040 02041 /* 02042 * get return address 02043 */ 02044 02045 ErrEle.ReturnAddr = gpReturnAddr; 02046 02047 /* 02048 * get the process image name 02049 */ 02050 if (GetModuleFileName(NULL, ErrEle.ProcessName, MAX_PATH)) { 02051 pwcs = wcsrchr(ErrEle.ProcessName, TEXT('\\')); 02052 if (pwcs) { 02053 pwcs++; 02054 lstrcpy(ErrEle.ProcessName, pwcs); 02055 } 02056 } else { 02057 lstrcpy(ErrEle.ProcessName, szUnknown); 02058 } 02059 02060 /* 02061 * get the window title 02062 */ 02063 GetWindowTextW(pMsgBoxParams->hwndOwner, ErrEle.WindowTitle, TITLE_SIZE); 02064 if (!(*(ErrEle.WindowTitle))) { 02065 lstrcpy(ErrEle.WindowTitle, szUnknown); 02066 } 02067 02068 /* 02069 * get messagebox data 02070 */ 02071 ErrEle.lpszText = (LPWSTR)pMsgBoxParams->lpszText; 02072 ErrEle.lpszCaption = (LPWSTR)pMsgBoxParams->lpszCaption; 02073 ErrEle.dwStyle = pMsgBoxParams->dwStyle; 02074 02075 /* 02076 * resolve the module name of caller 02077 */ 02078 if (!RtlPcToFileHeader((PVOID)ErrEle.ReturnAddr, &ImageBase)) { 02079 RIPMSG0(RIP_WARNING, "ErrorMessageInst: Can't find Caller"); 02080 ErrEle.BaseAddr = (PVOID)-1; 02081 ErrEle.dwImageSize = -1; 02082 lstrcpy(ErrEle.CallerModuleName, szUnknown); 02083 } else { 02084 ErrEle.BaseAddr = ImageBase; 02085 if (GetModuleFileName((HMODULE)ImageBase, ErrEle.CallerModuleName, MAX_PATH)) { 02086 pwcs = wcsrchr(ErrEle.CallerModuleName, TEXT('\\')); 02087 if (pwcs) { 02088 pwcs++; 02089 lstrcpy(ErrEle.CallerModuleName, pwcs); 02090 } 02091 } else { 02092 lstrcpy(ErrEle.CallerModuleName, szUnknown); 02093 } 02094 NtHeaders = RtlImageNtHeader(ImageBase); 02095 if (NtHeaders == NULL) { 02096 ErrEle.dwImageSize = -1; 02097 } else { 02098 ErrEle.dwImageSize = NtHeaders->OptionalHeader.SizeOfImage; 02099 } 02100 } 02101 /* 02102 * Register the event if we haven't done so already. 02103 * Since RegisterEventSource is supported by a service, we must not hold 02104 * any locks while making this call. Hence we might have several threads 02105 * registering the event simultaneously. 02106 */ 02107 02108 if (!gEventSource) { 02109 gEventSource = RegisterLogSource(L"Error Instrument"); 02110 if (!gEventSource) { 02111 ErrEle.dwErrorCode = GetLastError(); 02112 rc = FALSE; 02113 } 02114 } 02115 02116 /* 02117 * report event 02118 */ 02119 if(gEventSource) { 02120 rc = LogMessageBox(&ErrEle); 02121 } 02122 02123 /* 02124 * allow to process another event log again 02125 */ 02126 02127 InterlockedExchangePointer(&gdwEMIThreadID, 0); 02128 02129 End: 02130 return rc; 02131 } 02132 02133 /***************************************************************************\ 02134 * InitInstrument 02135 * 02136 * Returns: TRUE - Initialization Success 02137 * FALSE - Initialization Fail 02138 * 02139 \***************************************************************************/ 02140 BOOL InitInstrument( 02141 LPDWORD lpEMIControl) 02142 { 02143 NTSTATUS Status; 02144 HKEY hKeyEMI = NULL; 02145 UNICODE_STRING UnicodeStringEMIKey; 02146 UNICODE_STRING UnicodeStringEnable; 02147 UNICODE_STRING UnicodeStringStyle; 02148 OBJECT_ATTRIBUTES ObjA; 02149 DWORD EMIEnable = 0; //means disable 02150 DWORD EMISeverity; 02151 struct { 02152 KEY_VALUE_PARTIAL_INFORMATION; 02153 LARGE_INTEGER; 02154 } EMIValueInfo; 02155 DWORD dwDisposition; 02156 02157 RtlInitUnicodeString(&UnicodeStringEMIKey, szEMIKey); 02158 InitializeObjectAttributes(&ObjA, &UnicodeStringEMIKey, OBJ_CASE_INSENSITIVE, NULL, NULL); 02159 02160 Status = NtOpenKey(&hKeyEMI, KEY_READ, &ObjA); 02161 if (!NT_SUCCESS(Status)) { 02162 /* 02163 * Key doesn't exist, assume disable 02164 */ 02165 return FALSE; 02166 } 02167 02168 /* 02169 * read the logging enable and setting 02170 */ 02171 RtlInitUnicodeString(&UnicodeStringEnable, szEMIEnable); 02172 Status = NtQueryValueKey(hKeyEMI, 02173 &UnicodeStringEnable, 02174 KeyValuePartialInformation, 02175 &EMIValueInfo, 02176 sizeof(EMIValueInfo), 02177 &dwDisposition); 02178 02179 if (NT_SUCCESS(Status)) { 02180 02181 RtlCopyMemory(&EMIEnable, &EMIValueInfo.Data, sizeof(EMIEnable)); 02182 02183 RtlInitUnicodeString(&UnicodeStringStyle, szEMISeverity); 02184 Status = NtQueryValueKey(hKeyEMI, 02185 &UnicodeStringStyle, 02186 KeyValuePartialInformation, 02187 &EMIValueInfo, 02188 sizeof(EMIValueInfo), 02189 &dwDisposition); 02190 02191 if (NT_SUCCESS(Status)) { 02192 RtlCopyMemory(&EMISeverity, &EMIValueInfo.Data, sizeof(EMISeverity)); 02193 /* 02194 * Validate data 02195 */ 02196 if (EMISeverity > EMI_SEVERITY_MAX_VALUE) { 02197 EMISeverity = EMI_SEVERITY_MAX_VALUE; 02198 } 02199 } else { 02200 /* 02201 * default severity for instrument 02202 */ 02203 EMISeverity = EMI_SEVERITY_WARNING; 02204 } 02205 *lpEMIControl = EMISeverity; 02206 } 02207 02208 /* 02209 * read default message reply enable 02210 */ 02211 RtlInitUnicodeString(&UnicodeStringEnable, szDMREnable); 02212 Status = NtQueryValueKey(hKeyEMI, 02213 &UnicodeStringEnable, 02214 KeyValuePartialInformation, 02215 &EMIValueInfo, 02216 sizeof(EMIValueInfo), 02217 &dwDisposition); 02218 02219 if (NT_SUCCESS(Status)) { 02220 RtlCopyMemory(&gfDMREnable, &EMIValueInfo.Data, sizeof(gfDMREnable)); 02221 } 02222 02223 NtClose(hKeyEMI); 02224 02225 if (EMIEnable) { 02226 02227 /* 02228 * add eventlog file 02229 */ 02230 if (NT_SUCCESS(CreateLogSource())) { 02231 return TRUE; 02232 } 02233 } 02234 return FALSE; 02235 } 02236 02237 /***************************************************************************\ 02238 * CreateLogSource 02239 * 02240 * Create the event source for eventlog 02241 * Return : NTSTATUS 02242 * 02243 \***************************************************************************/ 02244 NTSTATUS CreateLogSource() 02245 { 02246 NTSTATUS Status; 02247 UNICODE_STRING UnicodeStringEventKey; 02248 OBJECT_ATTRIBUTES ObjA; 02249 HKEY hKeyEvent = NULL; 02250 UNICODE_STRING UnicodeString; 02251 DWORD dwDisposition; 02252 02253 02254 RtlInitUnicodeString(&UnicodeStringEventKey, szEventKey); 02255 InitializeObjectAttributes(&ObjA, &UnicodeStringEventKey, OBJ_CASE_INSENSITIVE, NULL, NULL); 02256 02257 if (NT_SUCCESS(Status = NtOpenKey(&hKeyEvent, KEY_READ, &ObjA))) { 02258 02259 struct { 02260 KEY_VALUE_PARTIAL_INFORMATION KeyInfo; 02261 WCHAR awchMsgFileName[256]; 02262 } MsgFile; 02263 02264 RtlInitUnicodeString(&UnicodeString, szEventMsgFile); 02265 02266 Status = NtQueryValueKey(hKeyEvent, 02267 &UnicodeString, 02268 KeyValuePartialInformation, 02269 &MsgFile, 02270 sizeof MsgFile, 02271 &dwDisposition); 02272 if (NT_SUCCESS(Status)) { 02273 Status = lstrcmpi((LPWSTR)MsgFile.KeyInfo.Data, L"%SystemRoot%\\System32\\user32.dll"); 02274 } 02275 NtClose(hKeyEvent); 02276 } 02277 02278 return Status; 02279 } 02280 02281 /***************************************************************************\ 02282 * RegisterLogSource 02283 * 02284 * Get eventlog apis from advapi32.dll and register the event source 02285 * Return : HANDLE of event source 02286 * 02287 \***************************************************************************/ 02288 HANDLE RegisterLogSource( 02289 LPWSTR lpszSourceName) 02290 { 02291 /* 02292 * If we haven't already dynamically linked to advadpi32.dll, do it now. 02293 */ 02294 if (gfnRegisterEventSource == NULL) { 02295 HINSTANCE hAdvApi; 02296 FARPROC fnRegisterEventSource; 02297 FARPROC fnDeregisterEventSource; 02298 FARPROC fnReportEvent; 02299 FARPROC fnGetTokenInformation; 02300 FARPROC fnOpenProcessToken; 02301 FARPROC fnOpenThreadToken; 02302 02303 /* 02304 * Try to load the DLL and function pointers. 02305 */ 02306 if ((hAdvApi = LoadLibrary(L"advapi32.dll")) == NULL) { 02307 return NULL; 02308 } 02309 fnRegisterEventSource = GetProcAddress(hAdvApi, "RegisterEventSourceW"); 02310 fnDeregisterEventSource = GetProcAddress(hAdvApi, "DeregisterEventSource"); 02311 fnReportEvent = GetProcAddress(hAdvApi, "ReportEventW"); 02312 fnGetTokenInformation = GetProcAddress(hAdvApi, "GetTokenInformation"); 02313 fnOpenProcessToken = GetProcAddress(hAdvApi, "OpenProcessToken"); 02314 fnOpenThreadToken = GetProcAddress(hAdvApi, "OpenThreadToken"); 02315 if (!fnRegisterEventSource || !fnDeregisterEventSource || !fnReportEvent || 02316 !fnGetTokenInformation || !fnOpenProcessToken || !fnOpenThreadToken) { 02317 FreeLibrary(hAdvApi); 02318 return NULL; 02319 } 02320 02321 /* 02322 * Update the global function pointers if they're not set already. 02323 */ 02324 if (gfnRegisterEventSource == NULL) { 02325 gfnReportEvent = fnReportEvent; 02326 gfnDeregisterEventSource = fnDeregisterEventSource; 02327 gfnGetTokenInformation = fnGetTokenInformation; 02328 gfnOpenProcessToken = fnOpenProcessToken; 02329 gfnOpenThreadToken = fnOpenThreadToken; 02330 // This must be last since we test it above 02331 gfnRegisterEventSource = fnRegisterEventSource; 02332 ghAdvApi = hAdvApi; 02333 hAdvApi = NULL; 02334 } 02335 02336 /* 02337 * If another thread beat us to it, free the library. 02338 */ 02339 if (hAdvApi) { 02340 FreeLibrary(hAdvApi); 02341 } 02342 } 02343 02344 /* 02345 * Let's be paranoid and verify we loaded everything correctly. 02346 */ 02347 UserAssert(gfnRegisterEventSource != NULL); 02348 UserAssert(gfnDeregisterEventSource != NULL); 02349 UserAssert(gfnReportEvent != NULL); 02350 UserAssert(gfnGetTokenInformation != NULL); 02351 UserAssert(gfnOpenProcessToken != NULL); 02352 UserAssert(gfnOpenThreadToken != NULL); 02353 02354 /* 02355 * Call the real function. 02356 */ 02357 return (HANDLE)gfnRegisterEventSource(NULL, lpszSourceName); 02358 } 02359 /***************************************************************************\ 02360 * LogMessageBox 02361 * 02362 * Output error message record into eventlog 02363 * 02364 \***************************************************************************/ 02365 BOOL LogMessageBox( 02366 LPERROR_ELEMENT lpErrEle) 02367 { 02368 02369 LPWSTR lps[8]; 02370 DWORD dwData[2]; 02371 WCHAR BaseAddress[19]; 02372 WCHAR ImageSize[19]; 02373 WCHAR ReturnAddress[19]; 02374 PTOKEN_USER pTokenUser = NULL; 02375 PSID pSid = NULL; 02376 BOOL rc; 02377 02378 lps[0] = lpErrEle->ProcessName; 02379 lps[1] = lpErrEle->WindowTitle; 02380 lps[2] = lpErrEle->lpszCaption; 02381 lps[3] = lpErrEle->lpszText; 02382 lps[4] = lpErrEle->CallerModuleName; 02383 wsprintf(BaseAddress, L"%-#16p", lpErrEle->BaseAddr); 02384 lps[5] = BaseAddress; 02385 wsprintf(ImageSize, L"%-#16lX", lpErrEle->dwImageSize); 02386 lps[6] = ImageSize; 02387 wsprintf(ReturnAddress, L"%-#16p", lpErrEle->ReturnAddr); 02388 lps[7] = ReturnAddress; 02389 02390 dwData[0] = lpErrEle->dwStyle; 02391 dwData[1] = lpErrEle->dwErrorCode; 02392 02393 if( GetUserSid(&pTokenUser) ) 02394 pSid = pTokenUser->User.Sid; 02395 02396 UserAssert(gEventSource != NULL); 02397 rc = (BOOL)gfnReportEvent(gEventSource, EVENTLOG_INFORMATION_TYPE, 0, 02398 STATUS_LOG_ERROR_MSG, pSid, sizeof(lps) / sizeof(*lps), 02399 sizeof(dwData), lps, dwData); 02400 02401 if( pTokenUser ) { 02402 02403 VirtualFree( pTokenUser, 0, MEM_RELEASE ); 02404 } 02405 02406 return rc; 02407 } 02408 02409 /***************************************************************************\ 02410 * GetUserSid 02411 * 02412 * Well, actually it gets a pointer to a newly allocated TOKEN_USER, 02413 * which contains a SID, somewhere. 02414 * Caller must remember to free it when it's been used. 02415 * 02416 * History: 02417 * 10-16-98 Chienho stole from spooler 02418 * 02419 \***************************************************************************/ 02420 BOOL GetUserSid( 02421 PTOKEN_USER *ppTokenUser) 02422 { 02423 HANDLE TokenHandle; 02424 PTOKEN_USER pTokenUser = NULL; 02425 DWORD cbTokenUser = 0; 02426 DWORD cbNeeded; 02427 BOOL bRet = FALSE; 02428 02429 if ( !GetTokenHandle( &TokenHandle) ) { 02430 return FALSE; 02431 } 02432 02433 bRet = (BOOL)gfnGetTokenInformation( TokenHandle, 02434 TokenUser, 02435 pTokenUser, 02436 cbTokenUser, 02437 &cbNeeded); 02438 02439 /* We've passed a NULL pointer and 0 for the amount of memory 02440 * allocated. We expect to fail with bRet = FALSE and 02441 * GetLastError = ERROR_INSUFFICIENT_BUFFER. If we do not 02442 * have these conditions we will return FALSE 02443 */ 02444 02445 if ( !bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) ) { 02446 02447 pTokenUser = VirtualAlloc(NULL, cbNeeded, MEM_COMMIT, PAGE_READWRITE); 02448 02449 if ( pTokenUser == NULL ) { 02450 02451 goto GetUserSidDone; 02452 } 02453 02454 cbTokenUser = cbNeeded; 02455 02456 bRet = (BOOL)gfnGetTokenInformation( TokenHandle, 02457 TokenUser, 02458 pTokenUser, 02459 cbTokenUser, 02460 &cbNeeded ); 02461 02462 } else { 02463 02464 /* 02465 * Any other case -- return FALSE 02466 */ 02467 bRet = FALSE; 02468 } 02469 02470 GetUserSidDone: 02471 if ( bRet == TRUE ) { 02472 02473 *ppTokenUser = pTokenUser; 02474 02475 } else if ( pTokenUser ) { 02476 02477 VirtualFree( pTokenUser, 0, MEM_RELEASE ); 02478 } 02479 02480 CloseHandle( TokenHandle ); 02481 02482 return bRet; 02483 } 02484 02485 /***************************************************************************\ 02486 * GetTokenHandle 02487 * 02488 * Get handle of token for current thread 02489 * 02490 \***************************************************************************/ 02491 BOOL 02492 GetTokenHandle( 02493 PHANDLE pTokenHandle 02494 ) 02495 { 02496 if (!gfnOpenThreadToken(GetCurrentThread(), 02497 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 02498 TRUE, 02499 pTokenHandle)) { 02500 02501 if (GetLastError() == ERROR_NO_TOKEN) { 02502 02503 /* This means we are not impersonating anybody. 02504 * Instead, lets get the token out of the process. 02505 */ 02506 02507 if (!gfnOpenProcessToken(GetCurrentProcess(), 02508 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 02509 pTokenHandle)) { 02510 02511 return FALSE; 02512 } 02513 02514 } else 02515 02516 return FALSE; 02517 } 02518 02519 return TRUE; 02520 } 02521 02522 #endif //_JANUS_

Generated on Sat May 15 19:40:53 2004 for test by doxygen 1.3.7