https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6a944b556ae9ca0609975…
commit 6a944b556ae9ca0609975ee387a57f000cb862e4
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Sun Dec 2 18:51:44 2018 +0900
Commit: GitHub <noreply(a)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.mz(a)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)"