/* * ReactOS kernel * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* $Id$ * * PROJECT: ReactOS user32.dll * FILE: lib/user32/windows/messagebox.c * PURPOSE: Input * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * Thomas Weidenmueller (w3seek@users.sourceforge.net) * UPDATE HISTORY: * 2003/07/28 Added some NT features * 2003/07/27 Code ported from wine * 09-05-2001 CSH Created */ /* INCLUDES ******************************************************************/ #include #include WINE_DEFAULT_DEBUG_CHANNEL(user32); /* DEFINES *******************************************************************/ #define MSGBOX_IDICON (1088) #define MSGBOX_IDTEXT (100) #define IDI_HANDA MAKEINTRESOURCEA(32513) #define IDI_HANDW MAKEINTRESOURCEW(32513) #define IDI_QUESTIONA MAKEINTRESOURCEA(32514) #define IDI_QUESTIONW MAKEINTRESOURCEW(32514) #define IDI_EXCLAMATIONA MAKEINTRESOURCEA(32515) #define IDI_EXCLAMATIONW MAKEINTRESOURCEW(32515) #define IDI_ASTERISKA MAKEINTRESOURCEA(32516) #define IDI_ASTERISKW MAKEINTRESOURCEW(32516) #define IDI_WINLOGOA MAKEINTRESOURCEA(32517) #define IDI_WINLOGOW MAKEINTRESOURCEW(32517) #define BTN_CX (75) #define BTN_CY (23) #define MSGBOXEX_SPACING (16) #define MSGBOXEX_BUTTONSPACING (6) #define MSGBOXEX_MARGIN (12) #define MSGBOXEX_MAXBTNSTR (32) #define MSGBOXEX_MAXBTNS (4) typedef struct _MSGBOXINFO { HICON Icon; HFONT Font; DWORD ContextHelpId; MSGBOXCALLBACK Callback; DWORD Style; int DefBtn; int nButtons; LONG *Btns; UINT Timeout; } MSGBOXINFO, *PMSGBOXINFO; /* INTERNAL FUNCTIONS ********************************************************/ static INT_PTR CALLBACK MessageBoxProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { int i; PMSGBOXINFO mbi; HELPINFO hi; HWND owner; switch(message) { case WM_INITDIALOG: mbi = (PMSGBOXINFO)lParam; if(!GetPropW(hwnd, L"ROS_MSGBOX")) { SetPropW(hwnd, L"ROS_MSGBOX", (HANDLE)lParam); if(mbi->Icon) SendDlgItemMessageW(hwnd, MSGBOX_IDICON, STM_SETICON, (WPARAM)mbi->Icon, 0); SetWindowContextHelpId(hwnd, mbi->ContextHelpId); /* set control fonts */ SendDlgItemMessageW(hwnd, MSGBOX_IDTEXT, WM_SETFONT, (WPARAM)mbi->Font, 0); for(i = 0; i < mbi->nButtons; i++) { SendDlgItemMessageW(hwnd, mbi->Btns[i], WM_SETFONT, (WPARAM)mbi->Font, 0); } switch(mbi->Style & MB_TYPEMASK) { case MB_ABORTRETRYIGNORE: case MB_YESNO: RemoveMenu(GetSystemMenu(hwnd, FALSE), SC_CLOSE, MF_BYCOMMAND); break; } SetFocus(GetDlgItem(hwnd, mbi->DefBtn)); if(mbi->Timeout && (mbi->Timeout != (UINT)-1)) SetTimer(hwnd, 0, mbi->Timeout, NULL); } return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: case IDCANCEL: case IDABORT: case IDRETRY: case IDIGNORE: case IDYES: case IDNO: case IDTRYAGAIN: case IDCONTINUE: EndDialog(hwnd, wParam); return 0; case IDHELP: /* send WM_HELP message to messagebox window */ hi.cbSize = sizeof(HELPINFO); hi.iContextType = HELPINFO_WINDOW; hi.iCtrlId = LOWORD(wParam); hi.hItemHandle = (HANDLE)lParam; hi.dwContextId = 0; GetCursorPos(&hi.MousePos); SendMessageW(hwnd, WM_HELP, 0, (LPARAM)&hi); return 0; } return 0; case WM_HELP: mbi = (PMSGBOXINFO)GetPropW(hwnd, L"ROS_MSGBOX"); if(!mbi) return 0; memcpy(&hi, (void *)lParam, sizeof(hi)); hi.dwContextId = GetWindowContextHelpId(hwnd); if (mbi->Callback) mbi->Callback(&hi); else { owner = GetWindow(hwnd, GW_OWNER); if(owner) SendMessageW(GetWindow(hwnd, GW_OWNER), WM_HELP, 0, (LPARAM)&hi); } return 0; case WM_CLOSE: mbi = (PMSGBOXINFO)GetPropW(hwnd, L"ROS_MSGBOX"); if(!mbi) return 0; switch(mbi->Style & MB_TYPEMASK) { case MB_ABORTRETRYIGNORE: case MB_YESNO: return 1; } EndDialog(hwnd, IDCANCEL); return 1; case WM_TIMER: if(wParam == 0) { EndDialog(hwnd, 32000); } return 0; } return 0; } static int MessageBoxTimeoutIndirectW( CONST MSGBOXPARAMSW *lpMsgBoxParams, UINT Timeout) { DLGTEMPLATE *tpl; DLGITEMTEMPLATE *iico, *itxt; NONCLIENTMETRICSW nclm; WCHAR capbuf[32]; LPVOID buf; BYTE *dest; LPCWSTR caption, text; HFONT hFont; HICON Icon; HDC hDC; int bufsize, ret, caplen, textlen, btnlen, i, btnleft, btntop, lmargin, nButtons = 0; LONG Buttons[MSGBOXEX_MAXBTNS]; WCHAR ButtonText[MSGBOXEX_MAXBTNS][MSGBOXEX_MAXBTNSTR]; DLGITEMTEMPLATE *ibtn[MSGBOXEX_MAXBTNS]; RECT btnrect, txtrect, rc; SIZE btnsize; MSGBOXINFO mbi; BOOL defbtn = FALSE; DWORD units = GetDialogBaseUnits(); if(!lpMsgBoxParams->lpszCaption || !HIWORD((LPWSTR)lpMsgBoxParams->lpszCaption)) { LoadStringW(User32Instance, IDS_ERROR, &capbuf[0], 32); caption = &capbuf[0]; } else caption = (LPWSTR)lpMsgBoxParams->lpszCaption; if(!lpMsgBoxParams->lpszText || !HIWORD(lpMsgBoxParams->lpszText)) text = L""; else text = lpMsgBoxParams->lpszText; caplen = strlenW(caption); textlen = strlenW(text); /* Create selected buttons */ switch(lpMsgBoxParams->dwStyle & MB_TYPEMASK) { case MB_OKCANCEL: Buttons[0] = IDOK; Buttons[1] = IDCANCEL; nButtons = 2; break; case MB_CANCELTRYCONTINUE: Buttons[0] = IDCANCEL; Buttons[1] = IDTRYAGAIN; Buttons[2] = IDCONTINUE; nButtons = 3; break; case MB_ABORTRETRYIGNORE: Buttons[0] = IDABORT; Buttons[1] = IDRETRY; Buttons[2] = IDIGNORE; nButtons = 3; break; case MB_YESNO: Buttons[0] = IDYES; Buttons[1] = IDNO; nButtons = 2; break; case MB_YESNOCANCEL: Buttons[0] = IDYES; Buttons[1] = IDNO; Buttons[2] = IDCANCEL; nButtons = 3; break; case MB_RETRYCANCEL: Buttons[0] = IDRETRY; Buttons[1] = IDCANCEL; nButtons = 2; break; case MB_OK: /* fall through */ default: Buttons[0] = IDOK; nButtons = 1; break; } /* Create Help button */ if(lpMsgBoxParams->dwStyle & MB_HELP) Buttons[nButtons++] = IDHELP; switch(lpMsgBoxParams->dwStyle & MB_ICONMASK) { case MB_ICONEXCLAMATION: Icon = LoadIconW(0, IDI_EXCLAMATIONW); MessageBeep(MB_ICONEXCLAMATION); break; case MB_ICONQUESTION: Icon = LoadIconW(0, IDI_QUESTIONW); MessageBeep(MB_ICONQUESTION); break; case MB_ICONASTERISK: Icon = LoadIconW(0, IDI_ASTERISKW); MessageBeep(MB_ICONASTERISK); break; case MB_ICONHAND: Icon = LoadIconW(0, IDI_HANDW); MessageBeep(MB_ICONHAND); break; case MB_USERICON: Icon = LoadIconW(lpMsgBoxParams->hInstance, lpMsgBoxParams->lpszIcon); MessageBeep(MB_OK); break; default: /* By default, Windows 95/98/NT does not associate an icon to message boxes. * So ReactOS should do the same. */ Icon = (HICON)0; MessageBeep(MB_OK); break; } /* Basic space */ bufsize = sizeof(DLGTEMPLATE) + 2 * sizeof(WORD) + /* menu and class */ (caplen + 1) * sizeof(WCHAR); /* title */ /* Space for icon */ if (NULL != Icon) { bufsize = (bufsize + 3) & ~3; bufsize += sizeof(DLGITEMTEMPLATE) + 4 * sizeof(WORD) + sizeof(WCHAR); } /* Space for text */ bufsize = (bufsize + 3) & ~3; bufsize += sizeof(DLGITEMTEMPLATE) + 3 * sizeof(WORD) + (textlen + 1) * sizeof(WCHAR); for(i = 0; i < nButtons; i++) { switch(Buttons[i]) { case IDOK: LoadStringW(User32Instance, IDS_OK, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDCANCEL: LoadStringW(User32Instance, IDS_CANCEL, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDYES: LoadStringW(User32Instance, IDS_YES, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDNO: LoadStringW(User32Instance, IDS_NO, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDTRYAGAIN: LoadStringW(User32Instance, IDS_TRYAGAIN, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDCONTINUE: LoadStringW(User32Instance, IDS_CONTINUE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDABORT: LoadStringW(User32Instance, IDS_ABORT, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDRETRY: LoadStringW(User32Instance, IDS_RETRY, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDIGNORE: LoadStringW(User32Instance, IDS_IGNORE, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; case IDHELP: LoadStringW(User32Instance, IDS_HELP, ButtonText[i], MSGBOXEX_MAXBTNSTR - 1); break; default: ButtonText[i][0] = (WCHAR)0; break; } /* Space for buttons */ bufsize = (bufsize + 3) & ~3; bufsize += sizeof(DLGITEMTEMPLATE) + 3 * sizeof(WORD) + (wcslen(ButtonText[i]) + 1) * sizeof(WCHAR); } buf = RtlAllocateHeap(GetProcessHeap(), 0, bufsize); if(!buf) { return 0; } iico = itxt = NULL; hDC = CreateCompatibleDC(0); nclm.cbSize = sizeof(nclm); SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(nclm), &nclm, 0); hFont = CreateFontIndirectW (&nclm.lfMessageFont); tpl = (DLGTEMPLATE *)buf; tpl->style = WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_SYSMENU | DS_CENTER | DS_MODALFRAME | DS_NOIDLEMSG; tpl->dwExtendedStyle = WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT; if(lpMsgBoxParams->dwStyle & MB_TOPMOST) tpl->dwExtendedStyle |= WS_EX_TOPMOST; if(lpMsgBoxParams->dwStyle & MB_RIGHT) tpl->dwExtendedStyle |= WS_EX_RIGHT; tpl->x = 100; tpl->y = 100; tpl->cdit = nButtons + ((Icon != (HICON)0) ? 1 : 0) + 1; dest = (BYTE *)(tpl + 1); *(WORD*)dest = 0; /* no menu */ *(((WORD*)dest) + 1) = 0; /* use default window class */ dest += 2 * sizeof(WORD); memcpy(dest, caption, caplen * sizeof(WCHAR)); dest += caplen * sizeof(WCHAR); *(WCHAR*)dest = L'\0'; dest += sizeof(WCHAR); /* Create icon */ if(Icon) { dest = (BYTE*)(((ULONG_PTR)dest + 3) & ~3); iico = (DLGITEMTEMPLATE *)dest; iico->style = WS_CHILD | WS_VISIBLE | SS_ICON; iico->dwExtendedStyle = 0; iico->id = MSGBOX_IDICON; dest += sizeof(DLGITEMTEMPLATE); *(WORD*)dest = 0xFFFF; dest += sizeof(WORD); *(WORD*)dest = 0x0082; /* static control */ dest += sizeof(WORD); *(WORD*)dest = 0xFFFF; dest += sizeof(WORD); *(WCHAR*)dest = 0; dest += sizeof(WCHAR); *(WORD*)dest = 0; dest += sizeof(WORD); } /* create static for text */ dest = (BYTE*)(((UINT_PTR)dest + 3) & ~3); itxt = (DLGITEMTEMPLATE *)dest; itxt->style = WS_CHILD | WS_VISIBLE | SS_NOPREFIX; if(lpMsgBoxParams->dwStyle & MB_RIGHT) itxt->style |= SS_RIGHT; else itxt->style |= SS_LEFT; itxt->dwExtendedStyle = 0; itxt->id = MSGBOX_IDTEXT; dest += sizeof(DLGITEMTEMPLATE); *(WORD*)dest = 0xFFFF; dest += sizeof(WORD); *(WORD*)dest = 0x0082; /* static control */ dest += sizeof(WORD); memcpy(dest, text, textlen * sizeof(WCHAR)); dest += textlen * sizeof(WCHAR); *(WCHAR*)dest = 0; dest += sizeof(WCHAR); *(WORD*)dest = 0; dest += sizeof(WORD); /* create buttons */ btnsize.cx = BTN_CX; btnsize.cy = BTN_CY; btnrect.left = btnrect.top = 0; for(i = 0; i < nButtons; i++) { dest = (BYTE*)(((UINT_PTR)dest + 3) & ~3); ibtn[i] = (DLGITEMTEMPLATE *)dest; ibtn[i]->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP; if(!defbtn && (i == ((lpMsgBoxParams->dwStyle & MB_DEFMASK) >> 8))) { ibtn[i]->style |= BS_DEFPUSHBUTTON; mbi.DefBtn = Buttons[i]; defbtn = TRUE; } else ibtn[i]->style |= BS_PUSHBUTTON; ibtn[i]->dwExtendedStyle = 0; ibtn[i]->id = Buttons[i]; dest += sizeof(DLGITEMTEMPLATE); *(WORD*)dest = 0xFFFF; dest += sizeof(WORD); *(WORD*)dest = 0x0080; /* button control */ dest += sizeof(WORD); btnlen = strlenW(ButtonText[i]); memcpy(dest, ButtonText[i], btnlen * sizeof(WCHAR)); dest += btnlen * sizeof(WCHAR); *(WORD*)dest = 0; dest += sizeof(WORD); *(WORD*)dest = 0; dest += sizeof(WORD); SelectObject(hDC, hFont); DrawTextW(hDC, ButtonText[i], btnlen, &btnrect, DT_LEFT | DT_SINGLELINE | DT_CALCRECT); btnsize.cx = max(btnsize.cx, btnrect.right); btnsize.cy = max(btnsize.cy, btnrect.bottom); } /* make first button the default button if no other is */ if(!defbtn) { ibtn[0]->style &= ~BS_PUSHBUTTON; ibtn[0]->style |= BS_DEFPUSHBUTTON; mbi.DefBtn = Buttons[0]; } /* calculate position and size of controls */ txtrect.right = GetSystemMetrics(SM_CXSCREEN) / 5 * 4; if(Icon) txtrect.right -= GetSystemMetrics(SM_CXICON) + MSGBOXEX_SPACING; txtrect.top = txtrect.left = txtrect.bottom = 0; SelectObject(hDC, hFont); if (textlen != 0) { DrawTextW(hDC, text, textlen, &txtrect, DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT); } else { txtrect.right = txtrect.left + 1; txtrect.bottom = txtrect.top + 1; } txtrect.right++; /* calculate position and size of the icon */ rc.left = rc.bottom = rc.right = 0; btntop = 0; if(iico) { rc.right = GetSystemMetrics(SM_CXICON); rc.bottom = GetSystemMetrics(SM_CYICON); #ifdef MSGBOX_ICONVCENTER rc.top = MSGBOXEX_MARGIN + (max(txtrect.bottom, rc.bottom) / 2) - (GetSystemMetrics(SM_CYICON) / 2); rc.top = max(MSGBOXEX_SPACING, rc.top); #else rc.top = MSGBOXEX_MARGIN; #endif btnleft = (nButtons * (btnsize.cx + MSGBOXEX_BUTTONSPACING)) - MSGBOXEX_BUTTONSPACING; if(btnleft > txtrect.right + rc.right + MSGBOXEX_SPACING) { #ifdef MSGBOX_TEXTHCENTER lmargin = MSGBOXEX_MARGIN + ((btnleft - txtrect.right - rc.right - MSGBOXEX_SPACING) / 2); #else lmargin = MSGBOXEX_MARGIN; #endif btnleft = MSGBOXEX_MARGIN; } else { lmargin = MSGBOXEX_MARGIN; btnleft = MSGBOXEX_MARGIN + ((txtrect.right + rc.right + MSGBOXEX_SPACING) / 2) - (btnleft / 2); } rc.left = lmargin; iico->x = (rc.left * 4) / LOWORD(units); iico->y = (rc.top * 8) / HIWORD(units); iico->cx = (rc.right * 4) / LOWORD(units); iico->cy = (rc.bottom * 8) / HIWORD(units); btntop = rc.top + rc.bottom + MSGBOXEX_SPACING; rc.left += rc.right + MSGBOXEX_SPACING; } else { btnleft = (nButtons * (btnsize.cx + MSGBOXEX_BUTTONSPACING)) - MSGBOXEX_BUTTONSPACING; if(btnleft > txtrect.right) { #ifdef MSGBOX_TEXTHCENTER lmargin = MSGBOXEX_MARGIN + ((btnleft - txtrect.right) / 2); #else lmargin = MSGBOXEX_MARGIN; #endif btnleft = MSGBOXEX_MARGIN; } else { lmargin = MSGBOXEX_MARGIN; btnleft = MSGBOXEX_MARGIN + (txtrect.right / 2) - (btnleft / 2); } rc.left = lmargin; } /* calculate position of the text */ rc.top = MSGBOXEX_MARGIN + (rc.bottom / 2) - (txtrect.bottom / 2); rc.top = max(rc.top, MSGBOXEX_MARGIN); /* calculate position of the buttons */ btntop = max(rc.top + txtrect.bottom + MSGBOXEX_SPACING, btntop); for(i = 0; i < nButtons; i++) { ibtn[i]->x = (btnleft * 4) / LOWORD(units); ibtn[i]->y = (btntop * 8) / HIWORD(units); ibtn[i]->cx = (btnsize.cx * 4) / LOWORD(units); ibtn[i]->cy = (btnsize.cy * 8) / HIWORD(units); btnleft += btnsize.cx + MSGBOXEX_BUTTONSPACING; } /* calculate size and position of the messagebox window */ btnleft = max(btnleft - MSGBOXEX_BUTTONSPACING, rc.left + txtrect.right); btnleft += MSGBOXEX_MARGIN; btntop += btnsize.cy + MSGBOXEX_MARGIN; /* set size and position of the message static */ itxt->x = (rc.left * 4) / LOWORD(units); itxt->y = (rc.top * 8) / HIWORD(units); itxt->cx = (((btnleft - rc.left - MSGBOXEX_MARGIN) * 4) / LOWORD(units)); itxt->cy = ((txtrect.bottom * 8) / HIWORD(units)); /* set size of the window */ tpl->cx = (btnleft * 4) / LOWORD(units); tpl->cy = (btntop * 8) / HIWORD(units); /* finally show the messagebox */ mbi.Icon = Icon; mbi.Font = hFont; mbi.ContextHelpId = lpMsgBoxParams->dwContextHelpId; mbi.Callback = lpMsgBoxParams->lpfnMsgBoxCallback; mbi.Style = lpMsgBoxParams->dwStyle; mbi.nButtons = nButtons; mbi.Btns = &Buttons[0]; mbi.Timeout = Timeout; if(hDC) DeleteDC(hDC); ret = DialogBoxIndirectParamW(lpMsgBoxParams->hInstance, tpl, lpMsgBoxParams->hwndOwner, MessageBoxProc, (LPARAM)&mbi); if(hFont) DeleteObject(hFont); RtlFreeHeap(GetProcessHeap(), 0, buf); return ret; } /* FUNCTIONS *****************************************************************/ /* * @implemented */ int WINAPI MessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) { return MessageBoxExA(hWnd, lpText, lpCaption, uType, LANG_NEUTRAL); } /* * @implemented */ int WINAPI MessageBoxExA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId) { MSGBOXPARAMSA msgbox; msgbox.cbSize = sizeof(msgbox); msgbox.hwndOwner = hWnd; msgbox.hInstance = 0; msgbox.lpszText = lpText; msgbox.lpszCaption = lpCaption; msgbox.dwStyle = uType; msgbox.lpszIcon = NULL; msgbox.dwContextHelpId = 0; msgbox.lpfnMsgBoxCallback = NULL; msgbox.dwLanguageId = wLanguageId; return MessageBoxIndirectA(&msgbox); } /* * @implemented */ int WINAPI MessageBoxExW( HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, WORD wLanguageId) { MSGBOXPARAMSW msgbox; msgbox.cbSize = sizeof(msgbox); msgbox.hwndOwner = hWnd; msgbox.hInstance = 0; msgbox.lpszText = lpText; msgbox.lpszCaption = lpCaption; msgbox.dwStyle = uType; msgbox.lpszIcon = NULL; msgbox.dwContextHelpId = 0; msgbox.lpfnMsgBoxCallback = NULL; msgbox.dwLanguageId = wLanguageId; return MessageBoxTimeoutIndirectW(&msgbox, (UINT)-1); } /* * @implemented */ int WINAPI MessageBoxIndirectA( CONST MSGBOXPARAMSA *lpMsgBoxParams) { MSGBOXPARAMSW msgboxW; UNICODE_STRING textW, captionW, iconW; int ret; if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszText)) { RtlCreateUnicodeStringFromAsciiz(&textW, (PCSZ)lpMsgBoxParams->lpszText); /* * UNICODE_STRING objects are always allocated with an extra byte so you * can null-term if you want */ textW.Buffer[textW.Length / sizeof(WCHAR)] = L'\0'; } else textW.Buffer = (LPWSTR)lpMsgBoxParams->lpszText; if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszCaption)) { RtlCreateUnicodeStringFromAsciiz(&captionW, (PCSZ)lpMsgBoxParams->lpszCaption); /* * UNICODE_STRING objects are always allocated with an extra byte so you * can null-term if you want */ captionW.Buffer[captionW.Length / sizeof(WCHAR)] = L'\0'; } else captionW.Buffer = (LPWSTR)lpMsgBoxParams->lpszCaption; if(lpMsgBoxParams->dwStyle & MB_USERICON) { if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszIcon)) { RtlCreateUnicodeStringFromAsciiz(&iconW, (PCSZ)lpMsgBoxParams->lpszIcon); /* * UNICODE_STRING objects are always allocated with an extra byte so you * can null-term if you want */ iconW.Buffer[iconW.Length / sizeof(WCHAR)] = L'\0'; } else iconW.Buffer = (LPWSTR)lpMsgBoxParams->lpszIcon; } else iconW.Buffer = NULL; msgboxW.cbSize = sizeof(msgboxW); msgboxW.hwndOwner = lpMsgBoxParams->hwndOwner; msgboxW.hInstance = lpMsgBoxParams->hInstance; msgboxW.lpszText = textW.Buffer; msgboxW.lpszCaption = captionW.Buffer; msgboxW.dwStyle = lpMsgBoxParams->dwStyle; msgboxW.lpszIcon = iconW.Buffer; msgboxW.dwContextHelpId = lpMsgBoxParams->dwContextHelpId; msgboxW.lpfnMsgBoxCallback = lpMsgBoxParams->lpfnMsgBoxCallback; msgboxW.dwLanguageId = lpMsgBoxParams->dwLanguageId; ret = MessageBoxTimeoutIndirectW(&msgboxW, (UINT)-1); if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszText)) RtlFreeUnicodeString(&textW); if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszCaption)) RtlFreeUnicodeString(&captionW); if ((lpMsgBoxParams->dwStyle & MB_USERICON) && HIWORD((UINT_PTR)iconW.Buffer)) RtlFreeUnicodeString(&iconW); return ret; } /* * @implemented */ int WINAPI MessageBoxIndirectW( CONST MSGBOXPARAMSW *lpMsgBoxParams) { return MessageBoxTimeoutIndirectW(lpMsgBoxParams, (UINT)-1); } /* * @implemented */ int WINAPI MessageBoxW( HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) { return MessageBoxExW(hWnd, lpText, lpCaption, uType, LANG_NEUTRAL); } /* * @implemented */ int WINAPI MessageBoxTimeoutA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId, DWORD dwTime) { MSGBOXPARAMSW msgboxW; UNICODE_STRING textW, captionW; int ret; if (HIWORD((UINT_PTR)lpText)) RtlCreateUnicodeStringFromAsciiz(&textW, (PCSZ)lpText); else textW.Buffer = (LPWSTR)lpText; if (HIWORD((UINT_PTR)lpCaption)) RtlCreateUnicodeStringFromAsciiz(&captionW, (PCSZ)lpCaption); else captionW.Buffer = (LPWSTR)lpCaption; msgboxW.cbSize = sizeof(msgboxW); msgboxW.hwndOwner = hWnd; msgboxW.hInstance = 0; msgboxW.lpszText = textW.Buffer; msgboxW.lpszCaption = captionW.Buffer; msgboxW.dwStyle = uType; msgboxW.lpszIcon = NULL; msgboxW.dwContextHelpId = 0; msgboxW.lpfnMsgBoxCallback = NULL; msgboxW.dwLanguageId = wLanguageId; ret = MessageBoxTimeoutIndirectW(&msgboxW, (UINT)dwTime); if (HIWORD(textW.Buffer)) RtlFreeUnicodeString(&textW); if (HIWORD(captionW.Buffer)) RtlFreeUnicodeString(&captionW); return ret; } /* * @implemented */ int WINAPI MessageBoxTimeoutW( HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, WORD wLanguageId, DWORD dwTime) { MSGBOXPARAMSW msgbox; msgbox.cbSize = sizeof(msgbox); msgbox.hwndOwner = hWnd; msgbox.hInstance = 0; msgbox.lpszText = lpText; msgbox.lpszCaption = lpCaption; msgbox.dwStyle = uType; msgbox.lpszIcon = NULL; msgbox.dwContextHelpId = 0; msgbox.lpfnMsgBoxCallback = NULL; msgbox.dwLanguageId = wLanguageId; return MessageBoxTimeoutIndirectW(&msgbox, (UINT)dwTime); } /* * @unimplemented */ DWORD WINAPI SoftModalMessageBox(DWORD Unknown0) { UNIMPLEMENTED; return 0; } /* * @implemented */ BOOL WINAPI MessageBeep(UINT uType) { #if 0 LPWSTR EventName; switch(uType) { case 0xFFFFFFFF: if(waveOutGetNumDevs() == 0) return Beep(500, 100); // Beep through speaker /* fall through */ case MB_OK: EventName = L"SystemDefault"; break; case MB_ICONASTERISK: EventName = L"SystemAsterisk"; break; case MB_ICONEXCLAMATION: EventName = L"SystemExclamation"; break; case MB_ICONHAND: EventName = L"SystemHand"; break; case MB_ICONQUESTION: EventName = L"SystemQuestion"; break; } return PlaySoundW((LPCWSTR)EventName, NULL, SND_ALIAS | SND_NOWAIT | SND_NOSTOP | SND_ASYNC); #else return Beep(500, 100); // Beep through speaker #endif } /* * @implemented */ LPWSTR WINAPI MB_GetString(DWORD string) { UNIMPLEMENTED; return NULL; } /* EOF */