[USER32] Specify the font to be used for the message-box in its dialog template,...
[reactos.git] / win32ss / user / user32 / windows / messagebox.c
index 59ae555..db812b1 100644 (file)
@@ -19,9 +19,9 @@
 /*
  *
  * PROJECT:         ReactOS user32.dll
- * FILE:            lib/user32/windows/messagebox.c
+ * FILE:            win32ss/user/user32/windows/messagebox.c
  * PURPOSE:         Input
- * PROGRAMMER     Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
  *                  Thomas Weidenmueller (w3seek@users.sourceforge.net)
  * UPDATE HISTORY:
  *      2003/07/28  Added some NT features
  *      09-05-2001  CSH  Created
  */
 
-/* INCLUDES ******************************************************************/
-
 #include <user32.h>
 
-#include <wine/debug.h>
-
 WINE_DEFAULT_DEBUG_CHANNEL(user32);
 
 /* DEFINES *******************************************************************/
 
 #define MSGBOX_IDICON   (1088)
-#define MSGBOX_IDTEXT   (100)
+#define MSGBOX_IDTEXT   (0xffff)
 
-#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)
 
+
+/* MessageBox metrics */
+
 #define BTN_CX (75)
 #define BTN_CY (23)
 
-#define MSGBOXEX_SPACING    (16)
+#define MSGBOXEX_SPACING        (16)
 #define MSGBOXEX_BUTTONSPACING  (6)
-#define MSGBOXEX_MARGIN (12)
-#define MSGBOXEX_MAXBTNSTR  (32)
-#define MSGBOXEX_MAXBTNS    (4)
-
-typedef struct _MSGBOXINFO {
-  MSGBOXPARAMSW; // Wine passes this too.
-  // ReactOS
-  HICON Icon;
-  HFONT Font;
-  int DefBtn;
-  int nButtons;
-  LONG *Btns;
-  UINT Timeout;
+#define MSGBOXEX_MARGIN         (12)
+#define MSGBOXEX_MAXBTNSTR      (32)
+#define MSGBOXEX_MAXBTNS        (4)
+
+/* Rescale logical coordinates */
+#define RESCALE_X(_x, _units)   (((_x) * 4 + (_units).cx - 1) / (_units).cx)
+#define RESCALE_Y(_y, _units)   (((_y) * 8 + (_units).cy - 1) / (_units).cy)
+
+
+/* MessageBox button helpers */
+
+#define DECLARE_MB_1(_btn0) \
+    { 1, { ID##_btn0, 0, 0 }, { IDS_##_btn0, 0, 0 } }
+
+#define DECLARE_MB_2(_btn0, _btn1) \
+    { 2, { ID##_btn0, ID##_btn1, 0 }, { IDS_##_btn0, IDS_##_btn1, 0 } }
+
+#define DECLARE_MB_3(_btn0, _btn1, _btn2) \
+    { 3, { ID##_btn0, ID##_btn1, ID##_btn2 }, { IDS_##_btn0, IDS_##_btn1, IDS_##_btn2 } }
+
+typedef struct _MSGBTNINFO
+{
+    LONG btnCnt;
+    LONG btnIdx[MSGBOXEX_MAXBTNS];
+    UINT btnIds[MSGBOXEX_MAXBTNS];
+} MSGBTNINFO, *PMSGBTNINFO;
+
+/* Default MessageBox buttons */
+static const MSGBTNINFO MsgBtnInfo[] =
+{
+    /* MB_OK (0) */
+    DECLARE_MB_1(OK),
+    /* MB_OKCANCEL (1) */
+    DECLARE_MB_2(OK, CANCEL),
+    /* MB_ABORTRETRYIGNORE (2) */
+    DECLARE_MB_3(ABORT, RETRY, IGNORE),
+    /* MB_YESNOCANCEL (3) */
+    DECLARE_MB_3(YES, NO, CANCEL),
+    /* MB_YESNO (4) */
+    DECLARE_MB_2(YES, NO),
+    /* MB_RETRYCANCEL (5) */
+    DECLARE_MB_2(RETRY, CANCEL),
+    /* MB_CANCELTRYCONTINUE (6) */
+    DECLARE_MB_3(CANCEL, TRYAGAIN, CONTINUE)
+};
+
+typedef struct _MSGBOXINFO
+{
+    MSGBOXPARAMSW; // Wine passes this too.
+    // ReactOS
+    HICON Icon;
+    int DefBtn;
+    int nButtons;
+    LONG *Btns;
+    UINT Timeout;
 } MSGBOXINFO, *PMSGBOXINFO;
 
 /* INTERNAL FUNCTIONS ********************************************************/
@@ -83,49 +119,45 @@ static VOID MessageBoxTextToClipboard(HWND DialogWindow)
     LPWSTR pszBuffer, pszBufferPos, pMessageBoxText, pszTitle, pszText, pszButton;
     WCHAR szButton[MSGBOXEX_MAXBTNSTR];
     HGLOBAL hGlobal;
-    
-    static const WCHAR szLine[30] = 
-    {'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-',
-    '-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0};
-    
+
+    static const WCHAR szLine[] = L"---------------------------\r\n";
+
     mbi = (PMSGBOXINFO)GetPropW(DialogWindow, L"ROS_MSGBOX");
     hwndText = GetDlgItem(DialogWindow, MSGBOX_IDTEXT);
     cchTitle = GetWindowTextLengthW(DialogWindow) + 1;
     cchText = GetWindowTextLengthW(hwndText) + 1;
-    
-    if(!mbi)
+
+    if (!mbi)
         return;
-    
+
     pMessageBoxText = (LPWSTR)RtlAllocateHeap(GetProcessHeap(), 0, (cchTitle + cchText) * sizeof(WCHAR));
-    
-    if(pMessageBoxText == NULL)
+
+    if (pMessageBoxText == NULL)
     {
         RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText);
         return;
     }
-      
+
     pszTitle = pMessageBoxText;
     pszText = pMessageBoxText + cchTitle;
-    
 
-    
-    if(GetWindowTextW(DialogWindow, pszTitle, cchTitle) == 0 ||
-       GetWindowTextW(hwndText, pszText, cchText) == 0)
+    if (GetWindowTextW(DialogWindow, pszTitle, cchTitle) == 0 ||
+        GetWindowTextW(hwndText, pszText, cchText) == 0)
     {
         RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText);
         return;
     }
-    
-    /* 
+
+    /*
      * Calculate the total buffer size.
      */
     cchTotal = 6 + cchTitle + cchText + (lstrlenW(szLine) * 4) + (mbi->nButtons * MSGBOXEX_MAXBTNSTR + 3);
-    
+
     hGlobal = GlobalAlloc(GHND, cchTotal * sizeof(WCHAR));
-    
+
     pszBuffer = (LPWSTR)GlobalLock(hGlobal);
-    
-    if(pszBuffer == NULL)
+
+    if (pszBuffer == NULL)
     {
         RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText);
         GlobalFree(hGlobal);
@@ -142,22 +174,22 @@ static VOID MessageBoxTextToClipboard(HWND DialogWindow)
      */
     cchBuffer = wsprintfW(pszBuffer, L"%s%s\r\n%s%s\r\n%s", szLine, pszTitle, szLine, pszText, szLine);
     pszBufferPos = pszBuffer + cchBuffer;
-    
-    for(i = 0; i < mbi->nButtons; i++)
+
+    for (i = 0; i < mbi->nButtons; i++)
     {
         GetDlgItemTextW(DialogWindow, mbi->Btns[i], szButton, MSGBOXEX_MAXBTNSTR);
-        
+
         cchButton = strlenW(szButton);
         pszButton = szButton;
-        
+
         /* Skip '&' character. */
-        if(szButton[0] == '&')
+        if (szButton[0] == '&')
         {
             pszButton = pszButton + 1;
             cchButton = cchButton - 1;
         }
 
-        for(n = 0; n < cchButton; n++)
+        for (n = 0; n < cchButton; n++)
             *(pszBufferPos++) = pszButton[n];
 
         /* Add spaces. */
@@ -165,12 +197,12 @@ static VOID MessageBoxTextToClipboard(HWND DialogWindow)
         *(pszBufferPos++) = L' ';
         *(pszBufferPos++) = L' ';
     }
-    
+
     wsprintfW(pszBufferPos, L"\r\n%s", szLine);
-    
+
     GlobalUnlock(hGlobal);
 
-    if(OpenClipboard(DialogWindow))
+    if (OpenClipboard(DialogWindow))
     {
         EmptyClipboard();
         SetClipboardData(CF_UNICODETEXT, hGlobal);
@@ -183,232 +215,223 @@ static VOID MessageBoxTextToClipboard(HWND DialogWindow)
     RtlFreeHeap(GetProcessHeap(), 0, pMessageBoxText);
 }
 
-static INT_PTR CALLBACK MessageBoxProc( HWND hwnd, UINT message,
-                                        WPARAM wParam, LPARAM lParam )
+static INT_PTR CALLBACK MessageBoxProc(
+    HWND hwnd, UINT message,
+    WPARAM wParam, LPARAM lParam)
 {
-  int i, Alert;
-  PMSGBOXINFO mbi;
-  HELPINFO hi;
-  HWND owner;
+    int Alert;
+    PMSGBOXINFO mbi;
+    HELPINFO hi;
+    HWND owner;
 
-  switch(message) {
+    switch (message)
+    {
     case WM_INITDIALOG:
-      mbi = (PMSGBOXINFO)lParam;
+    {
+        mbi = (PMSGBOXINFO)lParam;
 
-      SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)mbi);
-      NtUserxSetMessageBox(hwnd);
+        SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)mbi);
+        NtUserxSetMessageBox(hwnd);
 
-      if(!GetPropW(hwnd, L"ROS_MSGBOX"))
-      {
-        SetPropW(hwnd, L"ROS_MSGBOX", (HANDLE)lParam);
+        if (!GetPropW(hwnd, L"ROS_MSGBOX"))
+        {
+            SetPropW(hwnd, L"ROS_MSGBOX", (HANDLE)lParam);
 
-        if (mbi->dwContextHelpId)
-          SetWindowContextHelpId(hwnd, mbi->dwContextHelpId);
+            if (mbi->dwContextHelpId)
+                SetWindowContextHelpId(hwnd, mbi->dwContextHelpId);
 
-        if (mbi->Icon)
-        {
-          SendDlgItemMessageW(hwnd, MSGBOX_IDICON, STM_SETICON, (WPARAM)mbi->Icon, 0);
-          Alert = ALERT_SYSTEM_WARNING;
-        }
-        else // Setup the rest of the alerts.
-        {
-          switch(mbi->dwStyle & MB_ICONMASK)
-          {
-             case MB_ICONWARNING:
+            if (mbi->Icon)
+            {
+                SendDlgItemMessageW(hwnd, MSGBOX_IDICON, STM_SETICON, (WPARAM)mbi->Icon, 0);
                 Alert = ALERT_SYSTEM_WARNING;
-             break;
-             case MB_ICONERROR:
-                Alert = ALERT_SYSTEM_ERROR;
-             break;
-             case MB_ICONQUESTION:
-                Alert = ALERT_SYSTEM_QUERY;
-             break;
-             default:
-                Alert = ALERT_SYSTEM_INFORMATIONAL;
-             /* fall through */
-          }
+            }
+            else // Setup the rest of the alerts.
+            {
+                switch (mbi->dwStyle & MB_ICONMASK)
+                {
+                case MB_ICONWARNING:
+                    Alert = ALERT_SYSTEM_WARNING;
+                    break;
+                case MB_ICONERROR:
+                    Alert = ALERT_SYSTEM_ERROR;
+                    break;
+                case MB_ICONQUESTION:
+                    Alert = ALERT_SYSTEM_QUERY;
+                    break;
+                default:
+                    Alert = ALERT_SYSTEM_INFORMATIONAL;
+                    /* fall through */
+                }
+            }
+            /* Send out the alert notifications. */
+            NotifyWinEvent(EVENT_SYSTEM_ALERT, hwnd, OBJID_ALERT, Alert);
+
+            switch (mbi->dwStyle & 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);
         }
-        /* Send out the alert notifications. */
-        NotifyWinEvent(EVENT_SYSTEM_ALERT, hwnd, OBJID_ALERT, Alert);
+        return 0;
+    }
 
-        /* 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->dwStyle & MB_TYPEMASK)
+    case WM_COMMAND:
+        switch (LOWORD(wParam))
         {
-          case MB_ABORTRETRYIGNORE:
-          case MB_YESNO:
-            RemoveMenu(GetSystemMenu(hwnd, FALSE), SC_CLOSE, MF_BYCOMMAND);
-            break;
+            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;
         }
-        SetFocus(GetDlgItem(hwnd, mbi->DefBtn));
-        if(mbi->Timeout && (mbi->Timeout != (UINT)-1))
-          SetTimer(hwnd, 0, mbi->Timeout, NULL);
-      }
-      return 0;
+        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_COPY:
         MessageBoxTextToClipboard(hwnd);
         return 0;
 
     case WM_HELP:
-      mbi = (PMSGBOXINFO)GetPropW(hwnd, L"ROS_MSGBOX");
-      if(!mbi)
+    {
+        mbi = (PMSGBOXINFO)GetPropW(hwnd, L"ROS_MSGBOX");
+        if (!mbi)
+            return 0;
+        memcpy(&hi, (void *)lParam, sizeof(hi));
+        hi.dwContextId = GetWindowContextHelpId(hwnd);
+
+        if (mbi->lpfnMsgBoxCallback)
+            mbi->lpfnMsgBoxCallback(&hi);
+        else
+        {
+            owner = GetWindow(hwnd, GW_OWNER);
+            if (owner)
+                SendMessageW(GetWindow(hwnd, GW_OWNER), WM_HELP, 0, (LPARAM)&hi);
+        }
         return 0;
-      memcpy(&hi, (void *)lParam, sizeof(hi));
-      hi.dwContextId = GetWindowContextHelpId(hwnd);
-
-      if (mbi->lpfnMsgBoxCallback)
-        mbi->lpfnMsgBoxCallback(&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->dwStyle & MB_TYPEMASK)
-      {
+    {
+        mbi = (PMSGBOXINFO)GetPropW(hwnd, L"ROS_MSGBOX");
+        if (!mbi)
+            return 0;
+        switch (mbi->dwStyle & MB_TYPEMASK)
+        {
         case MB_ABORTRETRYIGNORE:
         case MB_YESNO:
-          return 1;
-      }
-      EndDialog(hwnd, IDCANCEL);
-      return 1;
+            return 1;
+        }
+        EndDialog(hwnd, IDCANCEL);
+        return 1;
+    }
 
     case WM_TIMER:
-      if(wParam == 0)
-      {
-        EndDialog(hwnd, 32000);
-      }
-      return 0;
-  }
-  return 0;
+        if (wParam == 0)
+        {
+            EndDialog(hwnd, 32000);
+        }
+        return 0;
+    }
+    return 0;
 }
 
 static int
 MessageBoxTimeoutIndirectW(
-  CONST MSGBOXPARAMSW *lpMsgBoxParams, UINT Timeout)
+    CONST MSGBOXPARAMSW *lpMsgBoxParams, UINT Timeout)
 {
     DLGTEMPLATE *tpl;
     DLGITEMTEMPLATE *iico, *itxt;
     NONCLIENTMETRICSW nclm;
-    WCHAR capbuf[32];
     LPVOID buf;
     BYTE *dest;
     LPCWSTR caption, text;
-    HFONT hFont;
+    HFONT hFont, hOldFont;
     HICON Icon;
+    HWND hDCWnd;
     HDC hDC;
-    int bufsize, ret, caplen, textlen, btnlen, i, btnleft, btntop, lmargin, nButtons = 0;
-    LONG Buttons[MSGBOXEX_MAXBTNS];
-    WCHAR ButtonText[MSGBOXEX_MAXBTNS][MSGBOXEX_MAXBTNSTR];
+    SIZE units;
+    int bufsize, ret, caplen, textlen, i, btnleft, btntop, lmargin;
+    MSGBTNINFO Buttons;
+    LPCWSTR ButtonText[MSGBOXEX_MAXBTNS];
+    int ButtonLen[MSGBOXEX_MAXBTNS];
     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))
+    if (!lpMsgBoxParams->lpszCaption)
     {
-      LoadStringW(User32Instance, IDS_ERROR, &capbuf[0], 32);
-      caption = &capbuf[0];
+        /* No caption, use the default one */
+        caplen = LoadStringW(User32Instance, IDS_ERROR, (LPWSTR)&caption, 0);
+    }
+    else if (IS_INTRESOURCE(lpMsgBoxParams->lpszCaption))
+    {
+        /* User-defined resource string */
+        caplen = LoadStringW(lpMsgBoxParams->hInstance, PtrToUlong(lpMsgBoxParams->lpszCaption), (LPWSTR)&caption, 0);
     }
     else
-      caption = (LPWSTR)lpMsgBoxParams->lpszCaption;
+    {
+        /* UNICODE string pointer */
+        caption = lpMsgBoxParams->lpszCaption;
+        caplen = strlenW(caption);
+    }
 
-    if(!lpMsgBoxParams->lpszText || !HIWORD(lpMsgBoxParams->lpszText))
-      text = L"";
+    if (!lpMsgBoxParams->lpszText)
+    {
+        /* No text, use blank */
+        text = L"";
+        textlen = 0;
+    }
+    else if (IS_INTRESOURCE(lpMsgBoxParams->lpszText))
+    {
+        /* User-defined resource string */
+        textlen = LoadStringW(lpMsgBoxParams->hInstance, PtrToUlong(lpMsgBoxParams->lpszText), (LPWSTR)&text, 0);
+    }
     else
-      text = lpMsgBoxParams->lpszText;
+    {
+        /* UNICODE string pointer */
+        text = lpMsgBoxParams->lpszText;
+        textlen = strlenW(text);
+    }
+
+    /* Create the selected buttons; unknown types will fall back to MB_OK */
+    i = (lpMsgBoxParams->dwStyle & MB_TYPEMASK);
+    if (i >= ARRAYSIZE(MsgBtnInfo))
+        i = MB_OK;
 
-    caplen = strlenW(caption);
-    textlen = strlenW(text);
+    /* Get buttons IDs */
+    Buttons = MsgBtnInfo[i];
 
-    /* Create selected buttons */
-    switch(lpMsgBoxParams->dwStyle & MB_TYPEMASK)
+    /* Add the Help button */
+    if (lpMsgBoxParams->dwStyle & MB_HELP)
     {
-        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;
+        Buttons.btnIdx[Buttons.btnCnt] = IDHELP;
+        Buttons.btnIds[Buttons.btnCnt] = IDS_HELP;
+        Buttons.btnCnt++;
     }
-    /* Create Help button */
-    if(lpMsgBoxParams->dwStyle & MB_HELP)
-      Buttons[nButtons++] = IDHELP;
 
-    switch(lpMsgBoxParams->dwStyle & MB_ICONMASK)
+    switch (lpMsgBoxParams->dwStyle & MB_ICONMASK)
     {
       case MB_ICONEXCLAMATION:
         Icon = LoadIconW(0, IDI_EXCLAMATIONW);
@@ -441,8 +464,9 @@ MessageBoxTimeoutIndirectW(
 
     /* Basic space */
     bufsize = sizeof(DLGTEMPLATE) +
-              2 * sizeof(WORD) +                         /* menu and class */
-              (caplen + 1) * sizeof(WCHAR);              /* title */
+              2 * sizeof(WORD) +                /* menu and class */
+              (caplen + 1) * sizeof(WCHAR) +    /* title */
+              sizeof(WORD);                     /* font height */
 
     /* Space for icon */
     if (NULL != Icon)
@@ -459,77 +483,52 @@ MessageBoxTimeoutIndirectW(
                3 * sizeof(WORD) +
                (textlen + 1) * sizeof(WCHAR);
 
-
-    for(i = 0; i < nButtons; i++)
+    for (i = 0; i < Buttons.btnCnt; 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;
-      }
+        /* Get the default text of the buttons */
+        if (Buttons.btnIds[i])
+        {
+            ButtonLen[i] = LoadStringW(User32Instance, Buttons.btnIds[i], (LPWSTR)&ButtonText[i], 0);
+        }
+        else
+        {
+            ButtonText[i] = L"";
+            ButtonLen[i]  = 0;
+        }
 
       /* Space for buttons */
       bufsize = (bufsize + 3) & ~3;
       bufsize += sizeof(DLGITEMTEMPLATE) +
                  3 * sizeof(WORD) +
-                 (wcslen(ButtonText[i]) + 1) * sizeof(WCHAR);
+                 (ButtonLen[i] + 1) * sizeof(WCHAR);
     }
 
     buf = RtlAllocateHeap(GetProcessHeap(), 0, bufsize);
-    if(!buf)
-    {
-      return 0;
-    }
-    iico = itxt = NULL;
+    if (!buf)
+        return 0;
 
-    hDC = CreateCompatibleDC(0);
+    iico = itxt = NULL;
 
     nclm.cbSize = sizeof(nclm);
-    SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(nclm), &nclm, 0);
-    hFont = CreateFontIndirectW (&nclm.lfMessageFont);
+    SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(nclm), &nclm, 0);
+    hFont = CreateFontIndirectW(&nclm.lfMessageFont);
+    if (!hFont)
+    {
+        ERR("Cannot retrieve nclm.lfMessageFont!\n");
+        goto Quit;
+    }
 
     tpl = (DLGTEMPLATE *)buf;
 
-    tpl->style = WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_SYSMENU | DS_CENTER | DS_MODALFRAME | DS_NOIDLEMSG;
+    tpl->style = WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_SYSMENU | DS_CENTER | DS_SETFONT | 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;
+    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;
+    tpl->cdit = Buttons.btnCnt + ((Icon != (HICON)0) ? 1 : 0) + 1;
 
     dest = (BYTE *)(tpl + 1);
 
@@ -541,36 +540,43 @@ MessageBoxTimeoutIndirectW(
     *(WCHAR*)dest = L'\0';
     dest += sizeof(WCHAR);
 
+    /*
+     * A font point size (height) of 0x7FFF means that we use
+     * the message box font (NONCLIENTMETRICSW.lfMessageFont).
+     */
+    *(WORD*)dest = 0x7FFF;
+    dest += sizeof(WORD);
+
     /* Create icon */
-    if(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);
+        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;
+    if (lpMsgBoxParams->dwStyle & MB_RIGHT)
+        itxt->style |= SS_RIGHT;
     else
-      itxt->style |= SS_LEFT;
+        itxt->style |= SS_LEFT;
     itxt->dwExtendedStyle = 0;
     itxt->id = MSGBOX_IDTEXT;
     dest += sizeof(DLGITEMTEMPLATE);
@@ -585,158 +591,192 @@ MessageBoxTimeoutIndirectW(
     *(WORD*)dest = 0;
     dest += sizeof(WORD);
 
+    hDCWnd = NULL;
+    hDC = GetDCEx(hDCWnd, NULL, DCX_WINDOW | DCX_CACHE);
+    if (!hDC)
+    {
+        /* Retry with the DC of the owner window */
+        hDCWnd = lpMsgBoxParams->hwndOwner;
+        hDC = GetDCEx(hDCWnd, NULL, DCX_WINDOW | DCX_CACHE);
+    }
+    if (!hDC)
+    {
+        ERR("GetDCEx() failed, bail out!\n");
+        goto Quit;
+    }
+    hOldFont = SelectObject(hDC, hFont);
+
+    units.cx = GdiGetCharDimensions(hDC, NULL, &units.cy);
+    if (!units.cx)
+    {
+        DWORD defUnits;
+        ERR("GdiGetCharDimensions() failed, falling back to default values!\n");
+        defUnits = GetDialogBaseUnits();
+        units.cx = LOWORD(defUnits);
+        units.cy = HIWORD(defUnits);
+    }
+
     /* create buttons */
     btnsize.cx = BTN_CX;
     btnsize.cy = BTN_CY;
     btnrect.left = btnrect.top = 0;
-    for(i = 0; i < nButtons; i++)
+
+    for (i = 0; i < Buttons.btnCnt; 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);
+        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.btnIdx[i];
+            defbtn = TRUE;
+        }
+        else
+        {
+            ibtn[i]->style |= BS_PUSHBUTTON;
+        }
+        ibtn[i]->dwExtendedStyle = 0;
+        ibtn[i]->id = Buttons.btnIdx[i];
+        dest += sizeof(DLGITEMTEMPLATE);
+        *(WORD*)dest = 0xFFFF;
+        dest += sizeof(WORD);
+        *(WORD*)dest = 0x0080; /* button control */
+        dest += sizeof(WORD);
+        memcpy(dest, ButtonText[i], ButtonLen[i] * sizeof(WCHAR));
+        dest += ButtonLen[i] * sizeof(WCHAR);
+        *(WORD*)dest = 0;
+        dest += sizeof(WORD);
+        *(WORD*)dest = 0;
+        dest += sizeof(WORD);
+
+        // btnrect.right = btnrect.bottom = 0; // FIXME: Is it needed??
+        DrawTextW(hDC, ButtonText[i], ButtonLen[i], &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)
+    if (!defbtn)
     {
-      ibtn[0]->style &= ~BS_PUSHBUTTON;
-      ibtn[0]->style |= BS_DEFPUSHBUTTON;
-      mbi.DefBtn = Buttons[0];
+        ibtn[0]->style &= ~BS_PUSHBUTTON;
+        ibtn[0]->style |= BS_DEFPUSHBUTTON;
+        mbi.DefBtn = Buttons.btnIdx[0];
     }
 
     /* calculate position and size of controls */
     txtrect.right = GetSystemMetrics(SM_CXSCREEN) / 5 * 4;
-    if(Icon)
-      txtrect.right -= GetSystemMetrics(SM_CXICON) + MSGBOXEX_SPACING;
+    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);
+        DrawTextW(hDC, text, textlen, &txtrect, DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_EXPANDTABS | DT_EXTERNALLEADING | DT_EDITCONTROL | DT_CALCRECT);
     }
     else
     {
-      txtrect.right = txtrect.left + 1;
-      txtrect.bottom = txtrect.top + 1;
+        txtrect.right = txtrect.left + 1;
+        txtrect.bottom = txtrect.top + 1;
     }
     txtrect.right++;
 
+    if (hOldFont)
+        SelectObject(hDC, hOldFont);
+
+    ReleaseDC(hDCWnd, hDC);
+
+    if (hFont)
+        DeleteObject(hFont);
+
     /* calculate position and size of the icon */
     rc.left = rc.bottom = rc.right = 0;
     btntop = 0;
 
-    if(iico)
+    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;
+        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 = (Buttons.btnCnt * (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 = RESCALE_X(rc.left, units);
+        iico->y = RESCALE_Y(rc.top, units);
+        iico->cx = RESCALE_X(rc.right, units);
+        iico->cy = RESCALE_Y(rc.bottom, 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;
+        btnleft = (Buttons.btnCnt * (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++)
+    for (i = 0; i < Buttons.btnCnt; 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;
+        ibtn[i]->x = RESCALE_X(btnleft, units);
+        ibtn[i]->y = RESCALE_Y(btntop, units);
+        ibtn[i]->cx = RESCALE_X(btnsize.cx, units);
+        ibtn[i]->cy = RESCALE_Y(btnsize.cy, 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));
+    itxt->x = RESCALE_X(rc.left, units);
+    itxt->y = RESCALE_Y(rc.top, units);
+    itxt->cx = RESCALE_X(btnleft - rc.left - MSGBOXEX_MARGIN, units);
+    itxt->cy = RESCALE_Y(txtrect.bottom, units);
     /* set size of the window */
-    tpl->cx = (btnleft * 4) / LOWORD(units);
-    tpl->cy = (btntop * 8) / HIWORD(units);
+    tpl->cx = RESCALE_X(btnleft, units);
+    tpl->cy = RESCALE_Y(btntop, units);
 
     /* finally show the messagebox */
     mbi.Icon = Icon;
-    mbi.Font = hFont;
     mbi.dwContextHelpId = lpMsgBoxParams->dwContextHelpId;
     mbi.lpfnMsgBoxCallback = lpMsgBoxParams->lpfnMsgBoxCallback;
     mbi.dwStyle = lpMsgBoxParams->dwStyle;
-    mbi.nButtons = nButtons;
-    mbi.Btns = &Buttons[0];
+    mbi.nButtons = Buttons.btnCnt;
+    mbi.Btns = Buttons.btnIdx;
     mbi.Timeout = Timeout;
 
     /* Pass on to Justin Case so he can peek the message? */
@@ -748,15 +788,10 @@ MessageBoxTimeoutIndirectW(
     mbi.lpszIcon     = lpMsgBoxParams->lpszIcon;
     mbi.dwLanguageId = lpMsgBoxParams->dwLanguageId;
 
-    if(hDC)
-      DeleteDC(hDC);
-
-    ret =  DialogBoxIndirectParamW(lpMsgBoxParams->hInstance, tpl, lpMsgBoxParams->hwndOwner,
-                                   MessageBoxProc, (LPARAM)&mbi);
-
-    if(hFont)
-      DeleteObject(hFont);
+    ret = DialogBoxIndirectParamW(lpMsgBoxParams->hInstance, tpl, lpMsgBoxParams->hwndOwner,
+                                  MessageBoxProc, (LPARAM)&mbi);
 
+Quit:
     RtlFreeHeap(GetProcessHeap(), 0, buf);
     return ret;
 }
@@ -770,14 +805,28 @@ MessageBoxTimeoutIndirectW(
 int
 WINAPI
 MessageBoxA(
-  HWND hWnd,
-  LPCSTR lpText,
-  LPCSTR lpCaption,
-  UINT uType)
+    IN HWND hWnd,
+    IN LPCSTR lpText,
+    IN LPCSTR lpCaption,
+    IN UINT uType)
 {
     return MessageBoxExA(hWnd, lpText, lpCaption, uType, LANG_NEUTRAL);
 }
 
+/*
+ * @implemented
+ */
+int
+WINAPI
+MessageBoxW(
+    IN HWND hWnd,
+    IN LPCWSTR lpText,
+    IN LPCWSTR lpCaption,
+    IN UINT uType)
+{
+    return MessageBoxExW(hWnd, lpText, lpCaption, uType, LANG_NEUTRAL);
+}
+
 
 /*
  * @implemented
@@ -785,11 +834,11 @@ MessageBoxA(
 int
 WINAPI
 MessageBoxExA(
-  HWND hWnd,
-  LPCSTR lpText,
-  LPCSTR lpCaption,
-  UINT uType,
-  WORD wLanguageId)
+    IN HWND hWnd,
+    IN LPCSTR lpText,
+    IN LPCSTR lpCaption,
+    IN UINT uType,
+    IN WORD wLanguageId)
 {
     MSGBOXPARAMSA msgbox;
 
@@ -807,18 +856,17 @@ MessageBoxExA(
     return MessageBoxIndirectA(&msgbox);
 }
 
-
 /*
  * @implemented
  */
 int
 WINAPI
 MessageBoxExW(
-  HWND hWnd,
-  LPCWSTR lpText,
-  LPCWSTR lpCaption,
-  UINT uType,
-  WORD wLanguageId)
+    IN HWND hWnd,
+    IN LPCWSTR lpText,
+    IN LPCWSTR lpCaption,
+    IN UINT uType,
+    IN WORD wLanguageId)
 {
     MSGBOXPARAMSW msgbox;
 
@@ -843,13 +891,13 @@ MessageBoxExW(
 int
 WINAPI
 MessageBoxIndirectA(
-  CONST MSGBOXPARAMSA *lpMsgBoxParams)
+    IN CONST MSGBOXPARAMSA* lpMsgBoxParams)
 {
     MSGBOXPARAMSW msgboxW;
     UNICODE_STRING textW, captionW, iconW;
     int ret;
 
-    if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszText))
+    if (!IS_INTRESOURCE(lpMsgBoxParams->lpszText))
     {
         RtlCreateUnicodeStringFromAsciiz(&textW, (PCSZ)lpMsgBoxParams->lpszText);
         /*
@@ -861,7 +909,7 @@ MessageBoxIndirectA(
     else
         textW.Buffer = (LPWSTR)lpMsgBoxParams->lpszText;
 
-    if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszCaption))
+    if (!IS_INTRESOURCE(lpMsgBoxParams->lpszCaption))
     {
         RtlCreateUnicodeStringFromAsciiz(&captionW, (PCSZ)lpMsgBoxParams->lpszCaption);
         /*
@@ -873,9 +921,9 @@ MessageBoxIndirectA(
     else
         captionW.Buffer = (LPWSTR)lpMsgBoxParams->lpszCaption;
 
-    if(lpMsgBoxParams->dwStyle & MB_USERICON)
+    if (lpMsgBoxParams->dwStyle & MB_USERICON)
     {
-        if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszIcon))
+        if (!IS_INTRESOURCE(lpMsgBoxParams->lpszIcon))
         {
             RtlCreateUnicodeStringFromAsciiz(&iconW, (PCSZ)lpMsgBoxParams->lpszIcon);
             /*
@@ -903,68 +951,53 @@ MessageBoxIndirectA(
 
     ret = MessageBoxTimeoutIndirectW(&msgboxW, (UINT)-1);
 
-    if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszText))
+    if (!IS_INTRESOURCE(lpMsgBoxParams->lpszText))
         RtlFreeUnicodeString(&textW);
 
-    if (HIWORD((UINT_PTR)lpMsgBoxParams->lpszCaption))
+    if (!IS_INTRESOURCE(lpMsgBoxParams->lpszCaption))
         RtlFreeUnicodeString(&captionW);
 
-    if ((lpMsgBoxParams->dwStyle & MB_USERICON) && HIWORD((UINT_PTR)iconW.Buffer))
+    if ((lpMsgBoxParams->dwStyle & MB_USERICON) && !IS_INTRESOURCE(iconW.Buffer))
         RtlFreeUnicodeString(&iconW);
 
     return ret;
 }
 
-
 /*
  * @implemented
  */
 int
 WINAPI
 MessageBoxIndirectW(
-  CONST MSGBOXPARAMSW *lpMsgBoxParams)
+    IN 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)
+    IN HWND hWnd,
+    IN LPCSTR lpText,
+    IN LPCSTR lpCaption,
+    IN UINT uType,
+    IN WORD wLanguageId,
+    IN DWORD dwTimeout)
 {
     MSGBOXPARAMSW msgboxW;
     UNICODE_STRING textW, captionW;
     int ret;
 
-    if (HIWORD((UINT_PTR)lpText))
+    if (!IS_INTRESOURCE(lpText))
         RtlCreateUnicodeStringFromAsciiz(&textW, (PCSZ)lpText);
     else
         textW.Buffer = (LPWSTR)lpText;
 
-    if (HIWORD((UINT_PTR)lpCaption))
+    if (!IS_INTRESOURCE(lpCaption))
         RtlCreateUnicodeStringFromAsciiz(&captionW, (PCSZ)lpCaption);
     else
         captionW.Buffer = (LPWSTR)lpCaption;
@@ -980,12 +1013,12 @@ MessageBoxTimeoutA(
     msgboxW.lpfnMsgBoxCallback = NULL;
     msgboxW.dwLanguageId = wLanguageId;
 
-    ret = MessageBoxTimeoutIndirectW(&msgboxW, (UINT)dwTime);
+    ret = MessageBoxTimeoutIndirectW(&msgboxW, (UINT)dwTimeout);
 
-    if (HIWORD(textW.Buffer))
+    if (!IS_INTRESOURCE(textW.Buffer))
         RtlFreeUnicodeString(&textW);
 
-    if (HIWORD(captionW.Buffer))
+    if (!IS_INTRESOURCE(captionW.Buffer))
         RtlFreeUnicodeString(&captionW);
 
     return ret;
@@ -997,12 +1030,12 @@ MessageBoxTimeoutA(
 int
 WINAPI
 MessageBoxTimeoutW(
-  HWND hWnd,
-  LPCWSTR lpText,
-  LPCWSTR lpCaption,
-  UINT uType,
-  WORD wLanguageId,
-  DWORD dwTime)
+    IN HWND hWnd,
+    IN LPCWSTR lpText,
+    IN LPCWSTR lpCaption,
+    IN UINT uType,
+    IN WORD wLanguageId,
+    IN DWORD dwTimeout)
 {
     MSGBOXPARAMSW msgbox;
 
@@ -1017,7 +1050,7 @@ MessageBoxTimeoutW(
     msgbox.lpfnMsgBoxCallback = NULL;
     msgbox.dwLanguageId = wLanguageId;
 
-    return MessageBoxTimeoutIndirectW(&msgbox, (UINT)dwTime);
+    return MessageBoxTimeoutIndirectW(&msgbox, (UINT)dwTimeout);
 }
 
 
@@ -1038,7 +1071,7 @@ SoftModalMessageBox(DWORD Unknown0)
  */
 BOOL
 WINAPI
-MessageBeep(UINT uType)
+MessageBeep(IN UINT uType)
 {
     return NtUserxMessageBeep(uType);
 }
@@ -1046,11 +1079,27 @@ MessageBeep(UINT uType)
 
 /*
  * @implemented
+ *
+ * See: https://msdn.microsoft.com/en-us/library/windows/desktop/dn910915(v=vs.85).aspx
+ * and: http://undoc.airesoft.co.uk/user32.dll/MB_GetString.php
+ * for more information.
  */
-LPWSTR WINAPI MB_GetString(DWORD string)
+LPCWSTR
+WINAPI
+MB_GetString(IN UINT wBtn)
 {
-    UNIMPLEMENTED;
-    return NULL;
+    LPCWSTR btnStr = NULL;
+
+    /*
+     * The allowable IDs are between "IDOK - 1" (0) and "IDCONTINUE - 1" (10) inclusive.
+     * See psdk/winuser.h and user32/include/resource.h .
+     */
+    if (wBtn > IDCONTINUE - 1)
+        return NULL;
+
+    wBtn += 800; // See user32/include/resource.h
+    LoadStringW(User32Instance, wBtn, (LPWSTR)&btnStr, 0);
+    return btnStr;
 }
 
 /* EOF */