https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6a944b556ae9ca0609975ee387a57f000cb862e4

commit 6a944b556ae9ca0609975ee387a57f000cb862e4
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Sun Dec 2 18:51:44 2018 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Sun Dec 2 18:51:44 2018 +0900

    [USER32] Add Ghost window class (#1082)
    
    CORE-11944
---
 win32ss/user/user32/CMakeLists.txt        |   1 +
 win32ss/user/user32/controls/ghost.c      | 620 ++++++++++++++++++++++++++++++
 win32ss/user/user32/controls/regcontrol.c |   7 +-
 win32ss/user/user32/include/controls.h    |   3 +
 win32ss/user/user32/include/regcontrol.h  |   1 +
 win32ss/user/user32/include/resource.h    |   4 +
 win32ss/user/user32/lang/bg-BG.rc         |   3 +
 win32ss/user/user32/lang/cs-CZ.rc         |   3 +
 win32ss/user/user32/lang/da-DK.rc         |   3 +
 win32ss/user/user32/lang/de-DE.rc         |   3 +
 win32ss/user/user32/lang/el-GR.rc         |   3 +
 win32ss/user/user32/lang/en-US.rc         |   3 +
 win32ss/user/user32/lang/es-ES.rc         |   3 +
 win32ss/user/user32/lang/fr-FR.rc         |   3 +
 win32ss/user/user32/lang/he-IL.rc         |   3 +
 win32ss/user/user32/lang/hu-HU.rc         |   3 +
 win32ss/user/user32/lang/id-ID.rc         |   3 +
 win32ss/user/user32/lang/it-IT.rc         |   3 +
 win32ss/user/user32/lang/ja-JP.rc         |   3 +
 win32ss/user/user32/lang/lt-LT.rc         |   3 +
 win32ss/user/user32/lang/nl-NL.rc         |   3 +
 win32ss/user/user32/lang/no-NO.rc         |   3 +
 win32ss/user/user32/lang/pl-PL.rc         |   3 +
 win32ss/user/user32/lang/pt-BR.rc         |   3 +
 win32ss/user/user32/lang/ro-RO.rc         |   3 +
 win32ss/user/user32/lang/ru-RU.rc         |   3 +
 win32ss/user/user32/lang/sk-SK.rc         |   3 +
 win32ss/user/user32/lang/sv-SE.rc         |   3 +
 win32ss/user/user32/lang/tr-TR.rc         |   3 +
 win32ss/user/user32/lang/uk-UA.rc         |   3 +
 win32ss/user/user32/lang/zh-CN.rc         |   3 +
 31 files changed, 708 insertions(+), 3 deletions(-)

diff --git a/win32ss/user/user32/CMakeLists.txt 
b/win32ss/user/user32/CMakeLists.txt
index fdc280a1a0..b048231fb0 100644
--- a/win32ss/user/user32/CMakeLists.txt
+++ b/win32ss/user/user32/CMakeLists.txt
@@ -11,6 +11,7 @@ list(APPEND SOURCE
     controls/button.c
     controls/combo.c
     controls/edit.c
+    controls/ghost.c
     controls/icontitle.c
     controls/listbox.c
     controls/regcontrol.c
diff --git a/win32ss/user/user32/controls/ghost.c 
b/win32ss/user/user32/controls/ghost.c
new file mode 100644
index 0000000000..ccc9a6c528
--- /dev/null
+++ b/win32ss/user/user32/controls/ghost.c
@@ -0,0 +1,620 @@
+/*
+ * PROJECT:     ReactOS user32.dll
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Ghost window class
+ * COPYRIGHT:   Copyright 2018 Katayama Hirofumi MZ 
(katayama.hirofumi...@gmail.com)
+ */
+
+#include <user32.h>
+#include <strsafe.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(ghost);
+
+#define GHOST_TIMER_ID  0xFACEDEAD
+#define GHOST_INTERVAL  1000        // one second
+#define GHOST_PROP      L"GhostProp"
+
+const struct builtin_class_descr GHOST_builtin_class =
+{
+    L"Ghost",                   /* name */
+    0,                          /* style  */
+    GhostWndProcA,              /* procA */
+    GhostWndProcW,              /* procW */
+    0,                          /* extra */
+    IDC_WAIT,                   /* cursor */
+    NULL                        /* brush */
+};
+
+static HBITMAP
+IntCreate32BppBitmap(INT cx, INT cy)
+{
+    HBITMAP hbm = NULL;
+    BITMAPINFO bi;
+    HDC hdc;
+    LPVOID pvBits;
+
+    ZeroMemory(&bi, sizeof(bi));
+    bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bi.bmiHeader.biWidth = cx;
+    bi.bmiHeader.biHeight = cy;
+    bi.bmiHeader.biPlanes = 1;
+    bi.bmiHeader.biBitCount = 32;
+
+    hdc = CreateCompatibleDC(NULL);
+    if (hdc)
+    {
+        hbm = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, &pvBits, NULL, 0);
+        DeleteDC(hdc);
+    }
+    return hbm;
+}
+
+static HBITMAP
+IntGetWindowBitmap(HWND hwnd, INT cx, INT cy)
+{
+    HBITMAP hbm = NULL;
+    HDC hdc, hdcMem;
+    HGDIOBJ hbmOld;
+
+    hdc = GetWindowDC(hwnd);
+    if (!hdc)
+        return NULL;
+
+    hdcMem = CreateCompatibleDC(hdc);
+    if (!hdcMem)
+        goto earth;
+
+    hbm = IntCreate32BppBitmap(cx, cy);
+    if (hbm)
+    {
+        hbmOld = SelectObject(hdcMem, hbm);
+        BitBlt(hdcMem, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY | CAPTUREBLT);
+        SelectObject(hdcMem, hbmOld);
+    }
+
+    DeleteDC(hdcMem);
+
+earth:
+    ReleaseDC(hwnd, hdc);
+
+    return hbm;
+}
+
+static VOID
+IntMakeGhostImage(HBITMAP hbm)
+{
+    BITMAP bm;
+    DWORD i, *pdw;
+
+    GetObject(hbm, sizeof(bm), &bm);
+
+    if (bm.bmBitsPixel != 32 || !bm.bmBits)
+    {
+        ERR("bm.bmBitsPixel == %d, bm.bmBits == %p\n",
+            bm.bmBitsPixel, bm.bmBits);
+        return;
+    }
+
+    pdw = bm.bmBits;
+    for (i = 0; i < bm.bmWidth * bm.bmHeight; ++i)
+    {
+        *pdw = *pdw | 0x00C0C0C0;   // bitwise-OR with ARGB #C0C0C0
+        ++pdw;
+    }
+}
+
+/****************************************************************************/
+
+typedef struct GHOST_DATA
+{
+    HWND hwndTarget;
+    HBITMAP hbm32bpp;
+    BOOL bDestroyTarget;
+} GHOST_DATA;
+
+static GHOST_DATA *
+Ghost_GetData(HWND hwnd)
+{
+    return (GHOST_DATA *)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
+}
+
+static HWND
+Ghost_GetTarget(HWND hwnd)
+{
+    GHOST_DATA *pData = Ghost_GetData(hwnd);
+    if (!pData)
+        return NULL;
+    return pData->hwndTarget;
+}
+
+static LPWSTR
+Ghost_GetText(HWND hwndTarget, INT *pcchTextW, INT cchExtra)
+{
+    LPWSTR pszTextW = NULL, pszTextNewW;
+    INT cchNonExtra, cchTextW = *pcchTextW;
+
+    pszTextNewW = HeapAlloc(GetProcessHeap(), 0, cchTextW * sizeof(WCHAR));
+    for (;;)
+    {
+        if (!pszTextNewW)
+        {
+            ERR("HeapAlloc failed\n");
+            if (pszTextW)
+                HeapFree(GetProcessHeap(), 0, pszTextW);
+            return NULL;
+        }
+        pszTextW = pszTextNewW;
+
+        cchNonExtra = cchTextW - cchExtra;
+        if (InternalGetWindowText(hwndTarget, pszTextW,
+                                  cchNonExtra) < cchNonExtra - 1)
+        {
+            break;
+        }
+
+        cchTextW *= 2;
+        pszTextNewW = HeapReAlloc(GetProcessHeap(), 0, pszTextW,
+                                  cchTextW * sizeof(WCHAR));
+    }
+
+    *pcchTextW = cchTextW;
+    return pszTextW;
+}
+
+static BOOL
+Ghost_OnCreate(HWND hwnd, CREATESTRUCTW *lpcs)
+{
+    HBITMAP hbm32bpp;
+    HWND hwndTarget, hwndPrev;
+    GHOST_DATA *pData;
+    RECT rc;
+    DWORD style, exstyle;
+    WCHAR szTextW[320], szNotRespondingW[32];
+    LPWSTR pszTextW;
+    INT cchTextW, cchExtraW, cchNonExtraW;
+    PWND pWnd = ValidateHwnd(hwnd);
+    if (pWnd)
+    {
+        if (!pWnd->fnid)
+        {
+            NtUserSetWindowFNID(hwnd, FNID_GHOST);
+        }
+        else if (pWnd->fnid != FNID_GHOST)
+        {
+             ERR("Wrong window class for Ghost! fnId 0x%x\n", pWnd->fnid);
+             return FALSE;
+        }
+    }
+
+    // get the target
+    hwndTarget = (HWND)lpcs->lpCreateParams;
+    if (!IsWindowVisible(hwndTarget) ||     // invisible?
+        GetParent(hwndTarget) ||            // child?
+        !IsHungAppWindow(hwndTarget))       // not hung?
+    {
+        return FALSE;
+    }
+
+    // check prop
+    if (GetPropW(hwndTarget, GHOST_PROP))
+        return FALSE;
+
+    // set prop
+    SetPropW(hwndTarget, GHOST_PROP, hwnd);
+
+    // create user data
+    pData = HeapAlloc(GetProcessHeap(), 0, sizeof(GHOST_DATA));
+    if (!pData)
+    {
+        ERR("HeapAlloc failed\n");
+        return FALSE;
+    }
+
+    // get window image
+    GetWindowRect(hwndTarget, &rc);
+    hbm32bpp = IntGetWindowBitmap(hwndTarget,
+                                  rc.right - rc.left,
+                                  rc.bottom - rc.top);
+    if (!hbm32bpp)
+    {
+        ERR("hbm32bpp was NULL\n");
+        HeapFree(GetProcessHeap(), 0, pData);
+        return FALSE;
+    }
+    // make a ghost image
+    IntMakeGhostImage(hbm32bpp);
+
+    // set user data
+    pData->hwndTarget = hwndTarget;
+    pData->hbm32bpp = hbm32bpp;
+    pData->bDestroyTarget = FALSE;
+    SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)pData);
+
+    // get style
+    style = GetWindowLongPtrW(hwndTarget, GWL_STYLE);
+    exstyle = GetWindowLongPtrW(hwndTarget, GWL_EXSTYLE);
+
+    // get text
+    cchTextW = ARRAYSIZE(szTextW);
+    cchExtraW = ARRAYSIZE(szNotRespondingW);
+    cchNonExtraW = cchTextW - cchExtraW;
+    if (InternalGetWindowText(hwndTarget, szTextW,
+                              cchNonExtraW) < cchNonExtraW - 1)
+    {
+        pszTextW = szTextW;
+    }
+    else
+    {
+        cchTextW *= 2;
+        pszTextW = Ghost_GetText(hwndTarget, &cchTextW, cchExtraW);
+        if (!pszTextW)
+        {
+            ERR("Ghost_GetText failed\n");
+            DeleteObject(hbm32bpp);
+            HeapFree(GetProcessHeap(), 0, pData);
+            return FALSE;
+        }
+    }
+
+    // don't use scrollbars.
+    style &= ~(WS_HSCROLL | WS_VSCROLL | WS_VISIBLE);
+
+    // set style
+    SetWindowLongPtrW(hwnd, GWL_STYLE, style);
+    SetWindowLongPtrW(hwnd, GWL_EXSTYLE, exstyle);
+
+    // set text with " (Not Responding)"
+    LoadStringW(User32Instance, IDS_NOT_RESPONDING,
+                szNotRespondingW, ARRAYSIZE(szNotRespondingW));
+    StringCchCatW(pszTextW, cchTextW, szNotRespondingW);
+    SetWindowTextW(hwnd, pszTextW);
+
+    // free the text buffer
+    if (szTextW != pszTextW)
+        HeapFree(GetProcessHeap(), 0, pszTextW);
+
+    // get previous window of target
+    hwndPrev = GetWindow(hwndTarget, GW_HWNDPREV);
+
+    // hide target
+    ShowWindowAsync(hwndTarget, SW_HIDE);
+
+    // shrink the ghost to zero size and insert.
+    // this will avoid effects.
+    SetWindowPos(hwnd, hwndPrev, 0, 0, 0, 0,
+                 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER |
+                 SWP_DRAWFRAME);
+
+    // resume the position and size of ghost
+    MoveWindow(hwnd, rc.left, rc.top,
+               rc.right - rc.left, rc.bottom - rc.top, TRUE);
+
+    // make ghost visible
+    SetWindowLongPtrW(hwnd, GWL_STYLE, style | WS_VISIBLE);
+
+    // redraw
+    InvalidateRect(hwnd, NULL, TRUE);
+
+    // start timer
+    SetTimer(hwnd, GHOST_TIMER_ID, GHOST_INTERVAL, NULL);
+
+    return TRUE;
+}
+
+static void
+Ghost_Unenchant(HWND hwnd, BOOL bDestroyTarget)
+{
+    GHOST_DATA *pData = Ghost_GetData(hwnd);
+    if (!pData)
+        return;
+
+    pData->bDestroyTarget |= bDestroyTarget;
+    DestroyWindow(hwnd);
+}
+
+static void
+Ghost_OnDraw(HWND hwnd, HDC hdc)
+{
+    BITMAP bm;
+    HDC hdcMem;
+    GHOST_DATA *pData = Ghost_GetData(hwnd);
+
+    if (!pData || !GetObject(pData->hbm32bpp, sizeof(bm), &bm))
+        return;
+
+    hdcMem = CreateCompatibleDC(hdc);
+    if (hdcMem)
+    {
+        HGDIOBJ hbmOld = SelectObject(hdcMem, pData->hbm32bpp);
+        BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight,
+               hdcMem, 0, 0, SRCCOPY | CAPTUREBLT);
+        SelectObject(hdcMem, hbmOld);
+        DeleteDC(hdcMem);
+    }
+}
+
+static void
+Ghost_OnNCPaint(HWND hwnd, HRGN hrgn, BOOL bUnicode)
+{
+    HDC hdc;
+
+    // do the default behaivour
+    if (bUnicode)
+        DefWindowProcW(hwnd, WM_NCPAINT, (WPARAM)hrgn, 0);
+    else
+        DefWindowProcA(hwnd, WM_NCPAINT, (WPARAM)hrgn, 0);
+
+    // draw the ghost image
+    hdc = GetWindowDC(hwnd);
+    if (hdc)
+    {
+        Ghost_OnDraw(hwnd, hdc);
+        ReleaseDC(hwnd, hdc);
+    }
+}
+
+static void
+Ghost_OnPaint(HWND hwnd)
+{
+    PAINTSTRUCT ps;
+    HDC hdc = BeginPaint(hwnd, &ps);
+    if (hdc)
+    {
+        // don't draw at here
+        EndPaint(hwnd, &ps);
+    }
+}
+
+static void
+Ghost_OnMove(HWND hwnd, int x, int y)
+{
+    RECT rc;
+    HWND hwndTarget = Ghost_GetTarget(hwnd);
+
+    GetWindowRect(hwnd, &rc);
+
+    // move the target
+    SetWindowPos(hwndTarget, NULL, rc.left, rc.top, 0, 0,
+                 SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE |
+                 SWP_NOSENDCHANGING);
+}
+
+static void
+Ghost_OnDestroy(HWND hwnd)
+{
+    KillTimer(hwnd, GHOST_TIMER_ID);
+}
+
+static void
+Ghost_DestroyTarget(GHOST_DATA *pData)
+{
+    HWND hwndTarget = pData->hwndTarget;
+    DWORD pid;
+    HANDLE hProcess;
+
+    pData->hwndTarget = NULL;
+    GetWindowThreadProcessId(hwndTarget, &pid);
+
+    hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
+    if (hProcess)
+    {
+        TerminateProcess(hProcess, -1);
+        CloseHandle(hProcess);
+    }
+
+    DestroyWindow(hwndTarget);
+}
+
+static void
+Ghost_OnNCDestroy(HWND hwnd)
+{
+    // delete the user data
+    GHOST_DATA *pData = Ghost_GetData(hwnd);
+    if (pData)
+    {
+        SetWindowLongPtrW(hwnd, GWLP_USERDATA, 0);
+
+        // delete image
+        DeleteObject(pData->hbm32bpp);
+        pData->hbm32bpp = NULL;
+
+        // remove prop
+        RemovePropW(pData->hwndTarget, GHOST_PROP);
+
+        // show target
+        ShowWindowAsync(pData->hwndTarget, SW_SHOWNOACTIVATE);
+
+        // destroy target if necessary
+        if (pData->bDestroyTarget)
+        {
+            Ghost_DestroyTarget(pData);
+        }
+
+        HeapFree(GetProcessHeap(), 0, pData);
+    }
+
+    NtUserSetWindowFNID(hwnd, FNID_DESTROY);
+
+    PostQuitMessage(0);
+}
+
+static void
+Ghost_OnClose(HWND hwnd)
+{
+    INT id;
+    WCHAR szAskTerminate[128];
+    WCHAR szHungUpTitle[128];
+
+    // stop timer
+    KillTimer(hwnd, GHOST_TIMER_ID);
+
+    LoadStringW(User32Instance, IDS_ASK_TERMINATE,
+                szAskTerminate, ARRAYSIZE(szAskTerminate));
+    LoadStringW(User32Instance, IDS_HUNG_UP_TITLE,
+                szHungUpTitle, ARRAYSIZE(szHungUpTitle));
+
+    id = MessageBoxW(hwnd, szAskTerminate, szHungUpTitle,
+                     MB_ICONINFORMATION | MB_YESNO);
+    if (id == IDYES)
+    {
+        // destroy the target
+        Ghost_Unenchant(hwnd, TRUE);
+        return;
+    }
+
+    // restart timer
+    SetTimer(hwnd, GHOST_TIMER_ID, GHOST_INTERVAL, NULL);
+}
+
+static void
+Ghost_OnTimer(HWND hwnd, UINT id)
+{
+    HWND hwndTarget;
+    GHOST_DATA *pData = Ghost_GetData(hwnd);
+
+    if (id != GHOST_TIMER_ID || !pData)
+        return;
+
+    // stop the timer
+    KillTimer(hwnd, id);
+
+    hwndTarget = pData->hwndTarget;
+    if (!IsWindow(hwndTarget) || !IsHungAppWindow(hwndTarget))
+    {
+        // resume if window is destroyed or responding
+        Ghost_Unenchant(hwnd, FALSE);
+        return;
+    }
+
+    // restart the timer
+    SetTimer(hwnd, GHOST_TIMER_ID, GHOST_INTERVAL, NULL);
+}
+
+static HICON
+Ghost_GetIcon(HWND hwnd, INT fType)
+{
+    GHOST_DATA *pData = Ghost_GetData(hwnd);
+    HICON hIcon = NULL;
+
+    if (!pData)
+        return NULL;
+
+    // same as the original icon
+    switch (fType)
+    {
+        case ICON_BIG:
+        {
+            hIcon = (HICON)GetClassLongPtrW(pData->hwndTarget, GCLP_HICON);
+            break;
+        }
+
+        case ICON_SMALL:
+        {
+            hIcon = (HICON)GetClassLongPtrW(pData->hwndTarget, GCLP_HICONSM);
+            break;
+        }
+    }
+
+    return hIcon;
+}
+
+LRESULT WINAPI
+GhostWndProc_common(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
+                    BOOL unicode)
+{
+    switch (uMsg)
+    {
+        case WM_CREATE:
+            if (!Ghost_OnCreate(hwnd, (CREATESTRUCTW *)lParam))
+                return -1;
+            break;
+
+        case WM_NCPAINT:
+            Ghost_OnNCPaint(hwnd, (HRGN)wParam, unicode);
+            return 0;
+
+        case WM_ERASEBKGND:
+            Ghost_OnDraw(hwnd, (HDC)wParam);
+            return TRUE;
+
+        case WM_PAINT:
+            Ghost_OnPaint(hwnd);
+            break;
+
+        case WM_MOVE:
+            Ghost_OnMove(hwnd, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
+            break;
+
+        case WM_SIZE:
+            break;
+
+        case WM_SIZING:
+            return TRUE;
+
+        case WM_SYSCOMMAND:
+            switch ((UINT)wParam)
+            {
+                case SC_MAXIMIZE:
+                case SC_SIZE:
+                    // sizing-related
+                    return 0;
+            }
+            if (unicode)
+                return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+            else
+                return DefWindowProcA(hwnd, uMsg, wParam, lParam);
+
+        case WM_CLOSE:
+            Ghost_OnClose(hwnd);
+            break;
+
+        case WM_TIMER:
+            Ghost_OnTimer(hwnd, (UINT)wParam);
+            break;
+
+        case WM_NCMOUSEMOVE:
+            if (unicode)
+                DefWindowProcW(hwnd, uMsg, wParam, lParam);
+            else
+                DefWindowProcA(hwnd, uMsg, wParam, lParam);
+            SetCursor(LoadCursor(NULL, IDC_WAIT));
+            return 0;
+
+        case WM_GETICON:
+            return (LRESULT)Ghost_GetIcon(hwnd, (INT)wParam);
+
+        case WM_COMMAND:
+            if (LOWORD(wParam) == 3333)
+                Ghost_Unenchant(hwnd, FALSE);
+            break;
+
+        case WM_DESTROY:
+            Ghost_OnDestroy(hwnd);
+            break;
+
+        case WM_NCDESTROY:
+            Ghost_OnNCDestroy(hwnd);
+            break;
+
+        default:
+        {
+            if (unicode)
+                return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+            else
+                return DefWindowProcA(hwnd, uMsg, wParam, lParam);
+        }
+    }
+    return 0;
+}
+
+LRESULT CALLBACK
+GhostWndProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    return GhostWndProc_common(hwnd, uMsg, wParam, lParam, FALSE);
+}
+
+LRESULT CALLBACK
+GhostWndProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    return GhostWndProc_common(hwnd, uMsg, wParam, lParam, TRUE);
+}
diff --git a/win32ss/user/user32/controls/regcontrol.c 
b/win32ss/user/user32/controls/regcontrol.c
index ff9c9c9609..3360841ffc 100644
--- a/win32ss/user/user32/controls/regcontrol.c
+++ b/win32ss/user/user32/controls/regcontrol.c
@@ -64,6 +64,7 @@ static const struct
     { &EDIT_builtin_class,      FNID_EDIT,      ICLS_EDIT},
 /*    { &ICONTITLE_builtin_class, FNID_ICONTITLE, ICLS_ICONTITLE}, // moved to 
win32k */
     { &STATIC_builtin_class,    FNID_STATIC,    ICLS_STATIC},
+    { &GHOST_builtin_class,     FNID_GHOST,     ICLS_GHOST},
 };
 
 BOOL WINAPI RegisterSystemControls(VOID)
@@ -175,8 +176,8 @@ BOOL WINAPI RegisterClientPFN(VOID)
   pfnClientW.pfnStaticWndProc         = StaticWndProcW;
   pfnClientA.pfnImeWndProc            = ImeWndProcA;
   pfnClientW.pfnImeWndProc            = ImeWndProcW;
-  pfnClientA.pfnGhostWndProc          = DefWindowProcA;
-  pfnClientW.pfnGhostWndProc          = DefWindowProcW;
+  pfnClientA.pfnGhostWndProc          = GhostWndProcA;
+  pfnClientW.pfnGhostWndProc          = GhostWndProcW;
   pfnClientA.pfnHkINLPCWPSTRUCT       = DefWindowProcA;
   pfnClientW.pfnHkINLPCWPSTRUCT       = DefWindowProcW;
   pfnClientA.pfnHkINLPCWPRETSTRUCT    = DefWindowProcA;
@@ -199,7 +200,7 @@ BOOL WINAPI RegisterClientPFN(VOID)
   pfnClientWorker.pfnMDIClientWndProc = MDIClientWndProc_common;
   pfnClientWorker.pfnStaticWndProc    = StaticWndProc_common;
   pfnClientWorker.pfnImeWndProc       = ImeWndProc_common;
-  pfnClientWorker.pfnGhostWndProc     = User32DefWindowProc;
+  pfnClientWorker.pfnGhostWndProc     = GhostWndProc_common;
   pfnClientWorker.pfnCtfHookProc      = User32DefWindowProc;
 
   Status = NtUserInitializeClientPfnArrays( &pfnClientA,
diff --git a/win32ss/user/user32/include/controls.h 
b/win32ss/user/user32/include/controls.h
index 15ddd867ae..317e2f9733 100644
--- a/win32ss/user/user32/include/controls.h
+++ b/win32ss/user/user32/include/controls.h
@@ -104,6 +104,9 @@ LRESULT WINAPI ComboWndProc_common( HWND hwnd, UINT 
message, WPARAM wParam, LPAR
 LRESULT WINAPI EditWndProcA(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam);
 LRESULT WINAPI EditWndProcW(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam);
 LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM 
lParam, BOOL unicode);
+LRESULT WINAPI GhostWndProcA( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam );
+LRESULT WINAPI GhostWndProcW( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam );
+LRESULT WINAPI GhostWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, 
LPARAM lParam, BOOL unicode);
 LRESULT WINAPI ListBoxWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM 
lParam );
 LRESULT WINAPI ListBoxWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM 
lParam );
 LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,WPARAM wParam, 
LPARAM lParam, BOOL unicode);
diff --git a/win32ss/user/user32/include/regcontrol.h 
b/win32ss/user/user32/include/regcontrol.h
index 2b5330cd6c..f1b3b69bf0 100644
--- a/win32ss/user/user32/include/regcontrol.h
+++ b/win32ss/user/user32/include/regcontrol.h
@@ -38,6 +38,7 @@ extern const struct builtin_class_descr 
MDICLIENT_builtin_class;
 extern const struct builtin_class_descr MENU_builtin_class;
 extern const struct builtin_class_descr SCROLL_builtin_class;
 extern const struct builtin_class_descr STATIC_builtin_class;
+extern const struct builtin_class_descr GHOST_builtin_class;
 
 ATOM WINAPI RegisterClassExWOWW(WNDCLASSEXW *,LPDWORD,WORD,DWORD,BOOL);
 BOOL FASTCALL VersionRegisterClass(PCWSTR,LPCWSTR,HANDLE,HMODULE *);
diff --git a/win32ss/user/user32/include/resource.h 
b/win32ss/user/user32/include/resource.h
index 3d0088fec2..9c1b3694f8 100644
--- a/win32ss/user/user32/include/resource.h
+++ b/win32ss/user/user32/include/resource.h
@@ -8,6 +8,9 @@
 #pragma once
 
 #define IDS_ERROR    (2)
+#define IDS_NOT_RESPONDING  (3)
+#define IDS_ASK_TERMINATE   (4)
+#define IDS_HUNG_UP_TITLE   (5)
 
 /*
  * Button names IDs.
@@ -26,3 +29,4 @@
 #define IDS_HELP     (808)
 #define IDS_TRYAGAIN (809)
 #define IDS_CONTINUE (810)
+
diff --git a/win32ss/user/user32/lang/bg-BG.rc 
b/win32ss/user/user32/lang/bg-BG.rc
index 01413b769d..b1a4c308b1 100644
--- a/win32ss/user/user32/lang/bg-BG.rc
+++ b/win32ss/user/user32/lang/bg-BG.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Грешка"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "Добре"
     IDS_CANCEL "Отказ"
     IDS_ABORT "Прекъсване"
diff --git a/win32ss/user/user32/lang/cs-CZ.rc 
b/win32ss/user/user32/lang/cs-CZ.rc
index 6c74db4b84..aeade5a416 100644
--- a/win32ss/user/user32/lang/cs-CZ.rc
+++ b/win32ss/user/user32/lang/cs-CZ.rc
@@ -63,6 +63,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Chyba"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Storno"
     IDS_ABORT "&Přerušit"
diff --git a/win32ss/user/user32/lang/da-DK.rc 
b/win32ss/user/user32/lang/da-DK.rc
index aa4948bf8b..447b4e2f06 100644
--- a/win32ss/user/user32/lang/da-DK.rc
+++ b/win32ss/user/user32/lang/da-DK.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Fejl"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Fortryd"
     IDS_ABORT "&Afbryd"
diff --git a/win32ss/user/user32/lang/de-DE.rc 
b/win32ss/user/user32/lang/de-DE.rc
index 4435576d94..38ccbdfe4a 100644
--- a/win32ss/user/user32/lang/de-DE.rc
+++ b/win32ss/user/user32/lang/de-DE.rc
@@ -60,6 +60,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Fehler"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Abbrechen"
     IDS_ABORT "&Abbrechen"
diff --git a/win32ss/user/user32/lang/el-GR.rc 
b/win32ss/user/user32/lang/el-GR.rc
index 843406588a..d750968c93 100644
--- a/win32ss/user/user32/lang/el-GR.rc
+++ b/win32ss/user/user32/lang/el-GR.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Σφάλμα"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "’κυρο"
     IDS_ABORT "&Ματαίωση"
diff --git a/win32ss/user/user32/lang/en-US.rc 
b/win32ss/user/user32/lang/en-US.rc
index 41e64bf2a6..24f3bbaee8 100644
--- a/win32ss/user/user32/lang/en-US.rc
+++ b/win32ss/user/user32/lang/en-US.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Error"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Cancel"
     IDS_ABORT "&Abort"
diff --git a/win32ss/user/user32/lang/es-ES.rc 
b/win32ss/user/user32/lang/es-ES.rc
index 51b635829c..1b2e4548ca 100644
--- a/win32ss/user/user32/lang/es-ES.rc
+++ b/win32ss/user/user32/lang/es-ES.rc
@@ -60,6 +60,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Error"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "Aceptar"
     IDS_CANCEL "Cancelar"
     IDS_ABORT "&Abortar"
diff --git a/win32ss/user/user32/lang/fr-FR.rc 
b/win32ss/user/user32/lang/fr-FR.rc
index 609617302b..ee1cfdf412 100644
--- a/win32ss/user/user32/lang/fr-FR.rc
+++ b/win32ss/user/user32/lang/fr-FR.rc
@@ -60,6 +60,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Erreur"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Annuler"
     IDS_ABORT "&Abandonner"
diff --git a/win32ss/user/user32/lang/he-IL.rc 
b/win32ss/user/user32/lang/he-IL.rc
index 93b49a1b3f..d09463ddd6 100644
--- a/win32ss/user/user32/lang/he-IL.rc
+++ b/win32ss/user/user32/lang/he-IL.rc
@@ -59,6 +59,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "שגיאה"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "אישור"
     IDS_CANCEL "ביטול"
     IDS_ABORT "&בטל"
diff --git a/win32ss/user/user32/lang/hu-HU.rc 
b/win32ss/user/user32/lang/hu-HU.rc
index c91da00f16..64194f4d15 100644
--- a/win32ss/user/user32/lang/hu-HU.rc
+++ b/win32ss/user/user32/lang/hu-HU.rc
@@ -60,6 +60,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Hiba"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Mégse"
     IDS_ABORT "&Megszakít"
diff --git a/win32ss/user/user32/lang/id-ID.rc 
b/win32ss/user/user32/lang/id-ID.rc
index 31f9b4c634..b3e26d9a53 100644
--- a/win32ss/user/user32/lang/id-ID.rc
+++ b/win32ss/user/user32/lang/id-ID.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Salah"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Batal"
     IDS_ABORT "&Batal"
diff --git a/win32ss/user/user32/lang/it-IT.rc 
b/win32ss/user/user32/lang/it-IT.rc
index 40dd1b948c..14a5c8d5f8 100644
--- a/win32ss/user/user32/lang/it-IT.rc
+++ b/win32ss/user/user32/lang/it-IT.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Errore"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Annulla"
     IDS_ABORT "&Interrompi"
diff --git a/win32ss/user/user32/lang/ja-JP.rc 
b/win32ss/user/user32/lang/ja-JP.rc
index a9451dc530..cf5e221c84 100644
--- a/win32ss/user/user32/lang/ja-JP.rc
+++ b/win32ss/user/user32/lang/ja-JP.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "エラー"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "キャンセル"
     IDS_ABORT "中止(&A)"
diff --git a/win32ss/user/user32/lang/lt-LT.rc 
b/win32ss/user/user32/lang/lt-LT.rc
index 4bc6a221f3..30cdd31211 100644
--- a/win32ss/user/user32/lang/lt-LT.rc
+++ b/win32ss/user/user32/lang/lt-LT.rc
@@ -60,6 +60,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Klaida"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "Gerai"
     IDS_CANCEL "Atsisakyti"
     IDS_ABORT "N&utraukti"
diff --git a/win32ss/user/user32/lang/nl-NL.rc 
b/win32ss/user/user32/lang/nl-NL.rc
index 6ca628e2f9..28635a19c4 100644
--- a/win32ss/user/user32/lang/nl-NL.rc
+++ b/win32ss/user/user32/lang/nl-NL.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Fout"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Annuleren"
     IDS_ABORT "&Afbreken"
diff --git a/win32ss/user/user32/lang/no-NO.rc 
b/win32ss/user/user32/lang/no-NO.rc
index 7ba5d89482..5f2ef946ff 100644
--- a/win32ss/user/user32/lang/no-NO.rc
+++ b/win32ss/user/user32/lang/no-NO.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Feil"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Avbryt"
     IDS_ABORT "&Avbryt"
diff --git a/win32ss/user/user32/lang/pl-PL.rc 
b/win32ss/user/user32/lang/pl-PL.rc
index 9754bca593..749216c8aa 100644
--- a/win32ss/user/user32/lang/pl-PL.rc
+++ b/win32ss/user/user32/lang/pl-PL.rc
@@ -63,6 +63,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Błąd"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Anuluj"
     IDS_ABORT "&Przerwij"
diff --git a/win32ss/user/user32/lang/pt-BR.rc 
b/win32ss/user/user32/lang/pt-BR.rc
index 1917efb4db..e28731e47a 100644
--- a/win32ss/user/user32/lang/pt-BR.rc
+++ b/win32ss/user/user32/lang/pt-BR.rc
@@ -60,6 +60,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Erro"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Cancelar"
     IDS_ABORT "&Abortar"
diff --git a/win32ss/user/user32/lang/ro-RO.rc 
b/win32ss/user/user32/lang/ro-RO.rc
index 8a80fde59e..039dfdcf18 100644
--- a/win32ss/user/user32/lang/ro-RO.rc
+++ b/win32ss/user/user32/lang/ro-RO.rc
@@ -63,6 +63,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Eroare"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "Con&firmă"
     IDS_CANCEL "A&nulează"
     IDS_ABORT "Aba&ndon"
diff --git a/win32ss/user/user32/lang/ru-RU.rc 
b/win32ss/user/user32/lang/ru-RU.rc
index 3f1542667f..517c503c3f 100644
--- a/win32ss/user/user32/lang/ru-RU.rc
+++ b/win32ss/user/user32/lang/ru-RU.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Ошибка"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Отмена"
     IDS_ABORT "Пр&ервать"
diff --git a/win32ss/user/user32/lang/sk-SK.rc 
b/win32ss/user/user32/lang/sk-SK.rc
index cd02052dba..c749e4e770 100644
--- a/win32ss/user/user32/lang/sk-SK.rc
+++ b/win32ss/user/user32/lang/sk-SK.rc
@@ -60,6 +60,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Chyba"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Zrušiť"
     IDS_ABORT "&Prerušiť"
diff --git a/win32ss/user/user32/lang/sv-SE.rc 
b/win32ss/user/user32/lang/sv-SE.rc
index 841e2a02ca..04c7f44f07 100644
--- a/win32ss/user/user32/lang/sv-SE.rc
+++ b/win32ss/user/user32/lang/sv-SE.rc
@@ -60,6 +60,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Fel"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Avbryt"
     IDS_ABORT "&Avbryt"
diff --git a/win32ss/user/user32/lang/tr-TR.rc 
b/win32ss/user/user32/lang/tr-TR.rc
index 2d081a0456..f318ffaf0d 100644
--- a/win32ss/user/user32/lang/tr-TR.rc
+++ b/win32ss/user/user32/lang/tr-TR.rc
@@ -60,6 +60,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Yanlışlık"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "Tamam"
     IDS_CANCEL "İptal"
     IDS_ABORT "&Durdur"
diff --git a/win32ss/user/user32/lang/uk-UA.rc 
b/win32ss/user/user32/lang/uk-UA.rc
index 42caa463a6..9c79df5c50 100644
--- a/win32ss/user/user32/lang/uk-UA.rc
+++ b/win32ss/user/user32/lang/uk-UA.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "Помилка"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "OK"
     IDS_CANCEL "Скасувати"
     IDS_ABORT "П&ерервати"
diff --git a/win32ss/user/user32/lang/zh-CN.rc 
b/win32ss/user/user32/lang/zh-CN.rc
index 8ea0703984..2992309b3e 100644
--- a/win32ss/user/user32/lang/zh-CN.rc
+++ b/win32ss/user/user32/lang/zh-CN.rc
@@ -58,6 +58,9 @@ END
 STRINGTABLE
 BEGIN
     IDS_ERROR "错误"
+    IDS_NOT_RESPONDING " (Not Responding)"
+    IDS_ASK_TERMINATE "This application is hung up. May I terminate this app?"
+    IDS_HUNG_UP_TITLE "Hung up!"
     IDS_OK "确定"
     IDS_CANCEL "取消"
     IDS_ABORT "中止(&A)"

Reply via email to