diff --git a/reactos/dll/win32/user32/controls/regcontrol.c b/reactos/dll/win32/user32/controls/regcontrol.c index 0cc49e7a2ed..47a45cebc7d 100644 --- a/reactos/dll/win32/user32/controls/regcontrol.c +++ b/reactos/dll/win32/user32/controls/regcontrol.c @@ -1,9 +1,8 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS User32 * PURPOSE: Built-in control registration - * FILE: lib/user32/controls/regcontrol.c + * FILE: dll/win32/user32/controls/regcontrol.c * PROGRAMER: Ge van Geldorp (ge@gse.nl) * REVISION HISTORY: 2003/06/16 GvG Created * NOTES: Adapted from Wine @@ -12,57 +11,76 @@ #include #include +WINE_DEFAULT_DEBUG_CHANNEL(user32); + +DWORD RegisterDefaultClasses = FALSE; static PFNCLIENT pfnClientA; static PFNCLIENT pfnClientW; static PFNCLIENTWORKER pfnClientWorker; +// +// FIXME! +// These are not "System Classes" but Global Classes that are registered +// every time a process is created, so these can be unregistered as the msdn +// documents states. +// static const struct { const struct builtin_class_descr *desc; - UINT ClsId; + WORD fnid; + WORD ClsId; } g_SysClasses[] = { - { &DIALOG_builtin_class, FNID_DIALOG }, - { &POPUPMENU_builtin_class, FNID_MENU }, - { &COMBO_builtin_class, FNID_COMBOBOX }, - { &COMBOLBOX_builtin_class, FNID_COMBOLBOX }, - { &MDICLIENT_builtin_class, FNID_MDICLIENT }, + { &DIALOG_builtin_class, FNID_DIALOG, ICLS_DIALOG}, +/* { &POPUPMENU_builtin_class, FNID_MENU, ICLS_MENU}, // moved to win32k */ + { &COMBO_builtin_class, FNID_COMBOBOX, ICLS_COMBOBOX}, + { &COMBOLBOX_builtin_class, FNID_COMBOLBOX, ICLS_COMBOLBOX}, + { &MDICLIENT_builtin_class, FNID_MDICLIENT, ICLS_MDICLIENT}, #if 0 - { &MENU_builtin_class, FNID_MENU }, + { &MENU_builtin_class, FNID_MENU, ICLS_MENU}, #endif - { &SCROLL_builtin_class, FNID_SCROLLBAR }, - { &BUTTON_builtin_class, FNID_BUTTON }, - { &LISTBOX_builtin_class, FNID_LISTBOX }, - { &EDIT_builtin_class, FNID_EDIT }, - { &ICONTITLE_builtin_class, FNID_ICONTITLE }, - { &STATIC_builtin_class, FNID_STATIC }, +/* { &SCROLL_builtin_class, FNID_SCROLLBAR, ICLS_SCROLLBAR}, // moved to win32k */ + { &BUTTON_builtin_class, FNID_BUTTON, ICLS_BUTTON}, + { &LISTBOX_builtin_class, FNID_LISTBOX, ICLS_LISTBOX}, + { &EDIT_builtin_class, FNID_EDIT, ICLS_EDIT}, +/* { &ICONTITLE_builtin_class, FNID_ICONTITLE, ICLS_ICONTITLE}, // moved to win32k */ + { &STATIC_builtin_class, FNID_STATIC, ICLS_STATIC}, }; BOOL WINAPI RegisterSystemControls(VOID) { - REGISTER_SYSCLASS cls[sizeof(g_SysClasses) / sizeof(g_SysClasses[0])]; + WNDCLASSEXW WndClass; UINT i; + ATOM atom; - ZeroMemory(cls, sizeof(cls)); + if (RegisterDefaultClasses) return TRUE; - for (i = 0; i != sizeof(cls) / sizeof(cls[0]); i++) + ZeroMemory(&WndClass, sizeof(WndClass)); + + WndClass.cbSize = sizeof(WndClass); + + for (i = 0; i != sizeof(g_SysClasses) / sizeof(g_SysClasses[0]); i++) { - if (IS_ATOM(g_SysClasses[i].desc->name)) - cls[i].ClassName.Buffer = (PWSTR)((ULONG_PTR)g_SysClasses[i].desc->name); - else - RtlInitUnicodeString(&cls[i].ClassName, g_SysClasses[i].desc->name); + WndClass.lpszClassName = g_SysClasses[i].desc->name; - cls[i].Style = g_SysClasses[i].desc->style; - cls[i].ProcW = g_SysClasses[i].desc->procW; - cls[i].ProcA = g_SysClasses[i].desc->procA; - cls[i].ExtraBytes = g_SysClasses[i].desc->extra; - cls[i].hCursor = LoadCursorW(NULL, g_SysClasses[i].desc->cursor); - cls[i].hBrush = g_SysClasses[i].desc->brush; - cls[i].ClassId = g_SysClasses[i].ClsId; + // Set Global bit! + WndClass.style = g_SysClasses[i].desc->style|CS_GLOBALCLASS; + WndClass.lpfnWndProc = g_SysClasses[i].desc->procW; + WndClass.cbWndExtra = g_SysClasses[i].desc->extra; + WndClass.hCursor = LoadCursorW(NULL, g_SysClasses[i].desc->cursor); + WndClass.hbrBackground= g_SysClasses[i].desc->brush; + + atom = RegisterClassExWOWW( &WndClass, + 0, + g_SysClasses[i].fnid, + 0, + FALSE); + if (atom) + RegisterDefaultClasses |= ICLASS_TO_MASK(g_SysClasses[i].ClsId); } - return NtUserRegisterSystemClasses(sizeof(cls) / sizeof(cls[0]), cls); + return TRUE; } LRESULT diff --git a/reactos/dll/win32/user32/include/regcontrol.h b/reactos/dll/win32/user32/include/regcontrol.h index 7c5057d7995..1dc2b6f1af3 100644 --- a/reactos/dll/win32/user32/include/regcontrol.h +++ b/reactos/dll/win32/user32/include/regcontrol.h @@ -26,6 +26,7 @@ struct builtin_class_descr HBRUSH brush; /* brush or system color */ }; +extern DWORD RegisterDefaultClasses; BOOL WINAPI RegisterSystemControls(VOID); extern const struct builtin_class_descr BUTTON_builtin_class; @@ -42,4 +43,6 @@ 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; +ATOM WINAPI RegisterClassExWOWW(WNDCLASSEXW *,LPDWORD,WORD,DWORD,BOOL); + #endif /* ROS_REGCONTROL_H */ diff --git a/reactos/dll/win32/user32/include/user32p.h b/reactos/dll/win32/user32/include/user32p.h index 2595589593e..010e97eee00 100644 --- a/reactos/dll/win32/user32/include/user32p.h +++ b/reactos/dll/win32/user32/include/user32p.h @@ -117,9 +117,6 @@ #define HideCaret(hwnd) \ NtUserHideCaret(hwnd) -#define NtUserRegisterSystemClasses(Count,SysClasses) \ - (BOOL)NtUserCallTwoParam((DWORD)Count, (DWORD)SysClasses, TWOPARAM_ROUTINE_ROS_REGSYSCLASSES) - /* Internal Thread Data */ extern HINSTANCE User32Instance; extern HINSTANCE hImmInstance; diff --git a/reactos/dll/win32/user32/include/window.h b/reactos/dll/win32/user32/include/window.h index 2e88d9a9dd2..43c08d44dfb 100644 --- a/reactos/dll/win32/user32/include/window.h +++ b/reactos/dll/win32/user32/include/window.h @@ -65,3 +65,4 @@ User32CreateWindowEx(DWORD dwExStyle, BOOL Unicode); HWND* WIN_ListChildren (HWND hWndparent); +ULONG_PTR FASTCALL IntGetWndProc(PWND, BOOL); diff --git a/reactos/dll/win32/user32/misc/dllmain.c b/reactos/dll/win32/user32/misc/dllmain.c index dc643e7379d..5773b25c0d4 100644 --- a/reactos/dll/win32/user32/misc/dllmain.c +++ b/reactos/dll/win32/user32/misc/dllmain.c @@ -291,8 +291,7 @@ DllMain( { case DLL_PROCESS_ATTACH: User32Instance = hInstanceDll; - if (!RegisterClientPFN() || - !RegisterSystemControls()) + if (!RegisterClientPFN()) { return FALSE; } diff --git a/reactos/dll/win32/user32/windows/class.c b/reactos/dll/win32/user32/windows/class.c index 8146857dca0..ef82f88196b 100644 --- a/reactos/dll/win32/user32/windows/class.c +++ b/reactos/dll/win32/user32/windows/class.c @@ -46,6 +46,12 @@ GetClassInfoExA( return FALSE; } + if (!RegisterDefaultClasses) + { + ERR("GetClassInfoExA RegisterSystemControls\n"); + RegisterSystemControls(); + } + if (IS_ATOM(lpszClass)) { ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass); @@ -113,6 +119,12 @@ GetClassInfoExW( return FALSE; } + if (!RegisterDefaultClasses) + { + ERR("GetClassInfoExW RegisterSystemControls\n"); + RegisterSystemControls(); + } + if (IS_ATOM(lpszClass)) { ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass); @@ -198,6 +210,126 @@ GetClassInfoW( return retval; } +// +// Based on find_winproc... Fixes many whine tests...... +// +ULONG_PTR FASTCALL +IntGetClsWndProc(PWND pWnd, PCLS Class, BOOL Ansi) +{ + INT i; + ULONG_PTR gcpd, Ret = 0; + // If server side, sweep through proc list and return the client side proc. + if (Class->CSF_flags & CSF_SERVERSIDEPROC) + { // Always scan through the list due to wine class "deftest". + for ( i = FNID_FIRST; i <= FNID_SWITCH; i++) + { + if (GETPFNSERVER(i) == Class->lpfnWndProc) + { + if (Ansi) + Ret = (ULONG_PTR)GETPFNCLIENTA(i); + else + Ret = (ULONG_PTR)GETPFNCLIENTW(i); + } + } + return Ret; + } + // Set return proc. + Ret = (ULONG_PTR)Class->lpfnWndProc; + // Return the proc if one of the FnId default class type. + if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON) + { + if (Ansi) + { // If match return the right proc by type. + if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc) + Ret = (ULONG_PTR)GETPFNCLIENTA(Class->fnid); + } + else + { + if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc) + Ret = (ULONG_PTR)GETPFNCLIENTW(Class->fnid); + } + } + // Return on change or Ansi/Unicode proc equal. + if ( Ret != (ULONG_PTR)Class->lpfnWndProc || + Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) ) + return Ret; + + /* We have an Ansi and Unicode swap! If Ansi create Unicode proc handle. + This will force CallWindowProc to deal with it. */ + gcpd = NtUserGetCPD( UserHMGetHandle(pWnd), + (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDWndtoCls, + Ret); + + return (gcpd ? gcpd : Ret); +} + +// +// Based on IntGetClsWndProc +// +ULONG_PTR FASTCALL +IntGetWndProc(PWND pWnd, BOOL Ansi) +{ + INT i; + ULONG_PTR gcpd, Ret = 0; + PCLS Class = DesktopPtrToUser(pWnd->pcls); + + if (!Class) return Ret; + + if (pWnd->state & WNDS_SERVERSIDEWINDOWPROC) + { + for ( i = FNID_FIRST; i <= FNID_SWITCH; i++) + { + if (GETPFNSERVER(i) == pWnd->lpfnWndProc) + { + if (Ansi) + Ret = (ULONG_PTR)GETPFNCLIENTA(i); + else + Ret = (ULONG_PTR)GETPFNCLIENTW(i); + } + } + return Ret; + } + // Wine Class tests: + /* Edit controls are special - they return a wndproc handle when + GetWindowLongPtr is called with a different A/W. + On the other hand there is no W->A->W conversion so this control + is treated specially. + */ + if (Class->fnid == FNID_EDIT) + Ret = (ULONG_PTR)pWnd->lpfnWndProc; + else + { + // Set return proc. + Ret = (ULONG_PTR)pWnd->lpfnWndProc; + + if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON) + { + if (Ansi) + { + if (GETPFNCLIENTW(Class->fnid) == pWnd->lpfnWndProc) + Ret = (ULONG_PTR)GETPFNCLIENTA(Class->fnid); + } + else + { + if (GETPFNCLIENTA(Class->fnid) == pWnd->lpfnWndProc) + Ret = (ULONG_PTR)GETPFNCLIENTW(Class->fnid); + } + } + // Return on the change. + if ( Ret != (ULONG_PTR)pWnd->lpfnWndProc) + return Ret; + } + + if ( Ansi == !!(pWnd->state & WNDS_ANSIWINDOWPROC) ) + return Ret; + + gcpd = NtUserGetCPD( UserHMGetHandle(pWnd), + (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDWindow, + Ret); + + return (gcpd ? gcpd : Ret); +} + /* * @implemented */ @@ -248,6 +380,7 @@ GetClassLongA(HWND hWnd, int nIndex) break; case GCL_HMODULE: + //ERR("Cls 0x%x GCL_HMODULE 0x%x\n", Wnd->pcls, Class->hModule); Ret = (ULONG_PTR)Class->hModule; break; @@ -279,9 +412,7 @@ GetClassLongA(HWND hWnd, int nIndex) break; case GCLP_WNDPROC: - /* We need to make a call to win32k as it may be required to - create a callproc handle */ - Wnd = NULL; + Ret = IntGetClsWndProc(Wnd, Class, TRUE); break; default: @@ -392,9 +523,7 @@ GetClassLongW ( HWND hWnd, int nIndex ) break; case GCLP_WNDPROC: - /* We need to make a call to win32k as it may be required to - create a callproc handle */ - Wnd = NULL; + Ret = IntGetClsWndProc(Wnd, Class, FALSE); break; default: @@ -523,7 +652,6 @@ GetWindowLongA ( HWND hWnd, int nIndex ) SetLastError(ERROR_INVALID_PARAMETER); return 0; } - return *((LONG *)((PCHAR)(Wnd + 1) + nIndex)); } else @@ -548,9 +676,12 @@ GetWindowLongA ( HWND hWnd, int nIndex ) return (LONG)parent; } case GWL_WNDPROC: - /* Call win32k for this as a callproc handle may need - to be created */ - return NtUserGetWindowLong(hWnd, nIndex, TRUE); + if (!TestWindowProcess(Wnd)) + { + SetLastError(ERROR_ACCESS_DENIED); + return 0; + } + return IntGetWndProc(Wnd, TRUE); default: SetLastError(ERROR_INVALID_PARAMETER); @@ -580,7 +711,6 @@ GetWindowLongW(HWND hWnd, int nIndex) SetLastError(ERROR_INVALID_PARAMETER); return 0; } - return *((LONG *)((PCHAR)(Wnd + 1) + nIndex)); } else @@ -605,9 +735,12 @@ GetWindowLongW(HWND hWnd, int nIndex) return (LONG)parent; } case GWL_WNDPROC: - /* Call win32k for this as a callproc handle may need - to be created */ - return NtUserGetWindowLong(hWnd, nIndex, FALSE); + if (!TestWindowProcess(Wnd)) + { + SetLastError(ERROR_ACCESS_DENIED); + return 0; + } + return IntGetWndProc(Wnd, FALSE); default: SetLastError(ERROR_INVALID_PARAMETER); @@ -834,7 +967,8 @@ ATOM WINAPI RegisterClassExWOWW(WNDCLASSEXW *lpwcx, LPDWORD pdwWowData, WORD fnID, - DWORD dwFlags) + DWORD dwFlags, + BOOL ChkRegCls) { ATOM Atom; WNDCLASSEXW WndClass; @@ -847,16 +981,31 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx, lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 || lpwcx->lpszClassName == NULL) { + ERR("RegisterClassExWOWW Invalid Parameter Error!\n"); SetLastError(ERROR_INVALID_PARAMETER); return 0; } + if (ChkRegCls) + { + if (!RegisterDefaultClasses) RegisterSystemControls(); + } + /* + * On real Windows this looks more like: + * if (lpwcx->hInstance == User32Instance && + * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400) + * But since I have no idea what the magic field in the + * TEB structure means, I rather decided to omit that. + * -- Filip Navara + + GetWin32ClientInfo()->dwExpWinVer & (WINVER == 0x400) + */ if (lpwcx->hInstance == User32Instance) { + ERR("RegisterClassExWOWW User32Instance!\n"); SetLastError(ERROR_INVALID_PARAMETER); return 0; } - /* Yes, this is correct. We should modify the passed structure. */ if (lpwcx->hInstance == NULL) ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL); @@ -875,11 +1024,13 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx, if (WndClass.lpszMenuName[0]) { RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName); + RtlUnicodeStringToAnsiString( &AnsiMenuName, &MenuName, TRUE); } } else { MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName; + AnsiMenuName.Buffer = (PCHAR)WndClass.lpszMenuName; } } @@ -894,8 +1045,6 @@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx, RtlInitUnicodeString(&ClassName, WndClass.lpszClassName); } - RtlUnicodeStringToAnsiString( &AnsiMenuName, &MenuName, TRUE); - clsMenuName.pszClientAnsiMenuName = AnsiMenuName.Buffer; clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer; clsMenuName.pusMenuName = &MenuName; @@ -922,89 +1071,42 @@ ATOM WINAPI RegisterClassExA(CONST WNDCLASSEXA *lpwcx) { RTL_ATOM Atom; - WNDCLASSEXA WndClass; - UNICODE_STRING ClassName; - UNICODE_STRING MenuName = {0}; - CLSMENUNAME clsMenuName; - ANSI_STRING AnsiMenuName; - - if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXA) || - lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 || - lpwcx->lpszClassName == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - if (lpwcx->hInstance == User32Instance) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - /* Yes, this is correct. We should modify the passed structure. */ - if (lpwcx->hInstance == NULL) - ((WNDCLASSEXA*)lpwcx)->hInstance = GetModuleHandleW(NULL); + WNDCLASSEXW WndClass; + WCHAR mname[MAX_BUFFER_LEN]; + WCHAR cname[MAX_BUFFER_LEN]; RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXA)); - if (NULL == WndClass.hIconSm) - { - WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon); - } - if (WndClass.lpszMenuName != NULL) { if (!IS_INTRESOURCE(WndClass.lpszMenuName)) { if (WndClass.lpszMenuName[0]) { - RtlCreateUnicodeStringFromAsciiz(&MenuName, WndClass.lpszMenuName); + if (!MultiByteToWideChar( CP_ACP, 0, lpwcx->lpszMenuName, -1, mname, MAX_ATOM_LEN + 1 )) return 0; + + WndClass.lpszMenuName = mname; } } - else - { - MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName; - } } - if (IS_ATOM(WndClass.lpszClassName)) + if (!IS_ATOM(WndClass.lpszClassName)) { - ClassName.Length = - ClassName.MaximumLength = 0; - ClassName.Buffer = (LPWSTR)WndClass.lpszClassName; - } - else - { - RtlCreateUnicodeStringFromAsciiz(&ClassName, WndClass.lpszClassName); + if (!MultiByteToWideChar( CP_ACP, 0, lpwcx->lpszClassName, -1, cname, MAX_ATOM_LEN + 1 )) return 0; + + WndClass.lpszClassName = cname; } - RtlUnicodeStringToAnsiString( &AnsiMenuName, &MenuName, TRUE); - - clsMenuName.pszClientAnsiMenuName = AnsiMenuName.Buffer; - clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer; - clsMenuName.pusMenuName = &MenuName; - - Atom = NtUserRegisterClassExWOW( (WNDCLASSEXW*)&WndClass, - &ClassName, - NULL, //PUNICODE_STRING ClsNVersion, - &clsMenuName, - 0, - CSF_ANSIPROC, - 0); + Atom = RegisterClassExWOWW( &WndClass, + 0, + 0, + CSF_ANSIPROC, + TRUE); TRACE("A atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n", Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground, lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass); - if (!IS_INTRESOURCE(WndClass.lpszMenuName)) - { - RtlFreeUnicodeString(&MenuName); - RtlFreeAnsiString(&AnsiMenuName); - } - if (!IS_ATOM(WndClass.lpszClassName)) - RtlFreeUnicodeString(&ClassName); - return (ATOM)Atom; } @@ -1015,90 +1117,12 @@ ATOM WINAPI RegisterClassExW(CONST WNDCLASSEXW *lpwcx) { ATOM Atom; - WNDCLASSEXW WndClass; - UNICODE_STRING ClassName; - UNICODE_STRING MenuName = {0}; - CLSMENUNAME clsMenuName; - ANSI_STRING AnsiMenuName; - if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) || - lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 || - lpwcx->lpszClassName == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } + Atom = RegisterClassExWOWW( (WNDCLASSEXW *)lpwcx, 0, 0, 0, TRUE); - /* - * On real Windows this looks more like: - * if (lpwcx->hInstance == User32Instance && - * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400) - * But since I have no idea what the magic field in the - * TEB structure means, I rather decided to omit that. - * -- Filip Navara - - GetWin32ClientInfo()->ulWindowsVersion & (WINVER == 400) - */ - if (lpwcx->hInstance == User32Instance) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - /* Yes, this is correct. We should modify the passed structure. */ - if (lpwcx->hInstance == NULL) - ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL); - - RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW)); - - if (NULL == WndClass.hIconSm) - { - WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon); - } - - if (WndClass.lpszMenuName != NULL) - { - if (!IS_INTRESOURCE(WndClass.lpszMenuName)) - { - if (WndClass.lpszMenuName[0]) - { - RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName); - } - } - else - { - MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName; - } - } - - if (IS_ATOM(WndClass.lpszClassName)) - { - ClassName.Length = - ClassName.MaximumLength = 0; - ClassName.Buffer = (LPWSTR)WndClass.lpszClassName; - } - else - { - RtlInitUnicodeString(&ClassName, WndClass.lpszClassName); - } - - RtlUnicodeStringToAnsiString( &AnsiMenuName, &MenuName, TRUE); - - clsMenuName.pszClientAnsiMenuName = AnsiMenuName.Buffer; - clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer; - clsMenuName.pusMenuName = &MenuName; - - Atom = NtUserRegisterClassExWOW( &WndClass, - &ClassName, - NULL, //PUNICODE_STRING ClsNVersion, - &clsMenuName, - 0, - 0, - 0); - - TRACE("W atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n", + TRACE("W atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d\n", Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground, - lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass); + lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra); return Atom; } @@ -1153,8 +1177,6 @@ SetClassLongA (HWND hWnd, BOOL Allocated = FALSE; DWORD Ret; - TRACE("%p %d %lx\n", hWnd, nIndex, dwNewLong); - /* FIXME - portability!!!! */ if (nIndex == GCL_MENUNAME && lpStr != NULL) diff --git a/reactos/dll/win32/user32/windows/message.c b/reactos/dll/win32/user32/windows/message.c index 54f7d38a86b..e5615808f6a 100644 --- a/reactos/dll/win32/user32/windows/message.c +++ b/reactos/dll/win32/user32/windows/message.c @@ -1221,6 +1221,58 @@ IntCallWindowProcA(BOOL IsAnsiProc, } +static LRESULT WINAPI +IntCallMessageProc(IN PWND Wnd, IN HWND hWnd, IN UINT Msg, IN WPARAM wParam, IN LPARAM lParam, IN BOOL Ansi) +{ + WNDPROC WndProc; + BOOL IsAnsi; + PCLS Class; + + Class = DesktopPtrToUser(Wnd->pcls); + WndProc = NULL; + /* + This is the message exchange for user32. If there's a need to monitor messages, + do it here! + */ + TRACE("HWND 0x%x, MSG %d, WPARAM 0x%x, LPARAM 0x%x, Ansi &d\n",hWnd,Msg,wParam,lParam,Ansi); +// if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON ) + if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_FIRST ) + { + if (Ansi) + { + if (GETPFNCLIENTW(Class->fnid) == Wnd->lpfnWndProc) + WndProc = GETPFNCLIENTA(Class->fnid); + } + else + { + if (GETPFNCLIENTA(Class->fnid) == Wnd->lpfnWndProc) + WndProc = GETPFNCLIENTW(Class->fnid); + } + + IsAnsi = Ansi; + + if (!WndProc) + { + IsAnsi = !Wnd->Unicode; + WndProc = Wnd->lpfnWndProc; + } + } + else + { + IsAnsi = !Wnd->Unicode; + WndProc = Wnd->lpfnWndProc; + } +/* + Message caller can be Ansi/Unicode and the receiver can be Unicode/Ansi or + the same. + */ + if (!Ansi) + return IntCallWindowProcW(IsAnsi, WndProc, hWnd, Msg, wParam, lParam); + else + return IntCallWindowProcA(IsAnsi, WndProc, hWnd, Msg, wParam, lParam); +} + + /* * @implemented */ @@ -1246,8 +1298,12 @@ CallWindowProcA(WNDPROC lpPrevWndFunc, CallProc = ValidateCallProc((HANDLE)lpPrevWndFunc); if (CallProc != NULL) { - return IntCallWindowProcA(!CallProc->Unicode, CallProc->pfnClientPrevious, - hWnd, Msg, wParam, lParam); + return IntCallWindowProcA(!(CallProc->wType & UserGetCPDA2U), + CallProc->pfnClientPrevious, + hWnd, + Msg, + wParam, + lParam); } else { @@ -1284,8 +1340,12 @@ CallWindowProcW(WNDPROC lpPrevWndFunc, CallProc = ValidateCallProc((HANDLE)lpPrevWndFunc); if (CallProc != NULL) { - return IntCallWindowProcW(!CallProc->Unicode, CallProc->pfnClientPrevious, - hWnd, Msg, wParam, lParam); + return IntCallWindowProcW(!(CallProc->wType & UserGetCPDA2U), + CallProc->pfnClientPrevious, + hWnd, + Msg, + wParam, + lParam); } else { @@ -1296,30 +1356,6 @@ CallWindowProcW(WNDPROC lpPrevWndFunc, } -static LRESULT WINAPI -IntCallMessageProc(IN PWND Wnd, IN HWND hWnd, IN UINT Msg, IN WPARAM wParam, IN LPARAM lParam, IN BOOL Ansi) -{ - WNDPROC WndProc; - BOOL IsAnsi; - - if (Wnd->IsSystem) - { - WndProc = (Ansi ? Wnd->WndProcExtra : Wnd->lpfnWndProc); - IsAnsi = Ansi; - } - else - { - WndProc = Wnd->lpfnWndProc; - IsAnsi = !Wnd->Unicode; - } - - if (!Ansi) - return IntCallWindowProcW(IsAnsi, WndProc, hWnd, Msg, wParam, lParam); - else - return IntCallWindowProcA(IsAnsi, WndProc, hWnd, Msg, wParam, lParam); -} - - /* * @implemented */ @@ -1353,8 +1389,7 @@ DispatchMessageA(CONST MSG *lpmsg) } else if (Wnd != NULL) { - // FIXME Need to test for calling proc inside win32k! - if ( (lpmsg->message != WM_PAINT) ) // && !(Wnd->state & WNDS_SERVERSIDEWINDOWPROC) ) + if ( (lpmsg->message != WM_PAINT) && !(Wnd->state & WNDS_SERVERSIDEWINDOWPROC) ) { Ret = IntCallMessageProc(Wnd, lpmsg->hwnd, @@ -1414,8 +1449,7 @@ DispatchMessageW(CONST MSG *lpmsg) } else if (Wnd != NULL) { - // FIXME Need to test for calling proc inside win32k! - if ( (lpmsg->message != WM_PAINT) ) // && !(Wnd->state & WNDS_SERVERSIDEWINDOWPROC) ) + if ( (lpmsg->message != WM_PAINT) && !(Wnd->state & WNDS_SERVERSIDEWINDOWPROC) ) { Ret = IntCallMessageProc(Wnd, lpmsg->hwnd, @@ -2328,9 +2362,12 @@ User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength) { } - CallbackArgs->Result = IntCallWindowProcW(CallbackArgs->IsAnsiProc, CallbackArgs->Proc, - UMMsg.hwnd, UMMsg.message, - UMMsg.wParam, UMMsg.lParam); + CallbackArgs->Result = IntCallWindowProcW( CallbackArgs->IsAnsiProc, + CallbackArgs->Proc, + UMMsg.hwnd, + UMMsg.message, + UMMsg.wParam, + UMMsg.lParam); if (! MsgiKMToUMReply(&KMMsg, &UMMsg, &CallbackArgs->Result)) { diff --git a/reactos/dll/win32/user32/windows/window.c b/reactos/dll/win32/user32/windows/window.c index c20cce8a0c9..fc385a6071a 100644 --- a/reactos/dll/win32/user32/windows/window.c +++ b/reactos/dll/win32/user32/windows/window.c @@ -174,6 +174,12 @@ User32CreateWindowEx(DWORD dwExStyle, DbgPrint("[window] User32CreateWindowEx style %d, exstyle %d, parent %d\n", dwStyle, dwExStyle, hWndParent); #endif + if (!RegisterDefaultClasses) + { + ERR("User32CreateWindowEx RegisterSystemControls\n"); + RegisterSystemControls(); + } + if (IS_ATOM(lpClassName)) { RtlInitUnicodeString(&ClassName, NULL); @@ -281,6 +287,12 @@ CreateWindowExA(DWORD dwExStyle, MDICREATESTRUCTA mdi; HWND hwnd; + if (!RegisterDefaultClasses) + { + ERR("CreateWindowExA RegisterSystemControls\n"); + RegisterSystemControls(); + } + if (dwExStyle & WS_EX_MDICHILD) { POINT mPos[2]; @@ -387,6 +399,12 @@ CreateWindowExW(DWORD dwExStyle, MDICREATESTRUCTW mdi; HWND hwnd; + if (!RegisterDefaultClasses) + { + ERR("CreateWindowExW RegisterSystemControls\n"); + RegisterSystemControls(); + } + if (dwExStyle & WS_EX_MDICHILD) { POINT mPos[2]; diff --git a/reactos/include/reactos/win32k/ntuser.h b/reactos/include/reactos/win32k/ntuser.h index 9bc679b4da1..64b12233edd 100644 --- a/reactos/include/reactos/win32k/ntuser.h +++ b/reactos/include/reactos/win32k/ntuser.h @@ -167,14 +167,14 @@ typedef struct _REGISTER_SYSCLASS { /* This is a reactos specific class used to initialize the system window classes during user32 initialization */ - UNICODE_STRING ClassName; + PWSTR ClassName; UINT Style; WNDPROC ProcW; - WNDPROC ProcA; UINT ExtraBytes; HICON hCursor; HBRUSH hBrush; - UINT ClassId; + WORD fiId; + WORD iCls; } REGISTER_SYSCLASS, *PREGISTER_SYSCLASS; typedef struct _CLSMENUNAME @@ -201,8 +201,8 @@ typedef struct tagSBINFO typedef enum _GETCPD { - UserGetCPDU2A = 0x01, - UserGetCPDA2U = 0X02, + UserGetCPDA2U = 0x01, // " Unicode " + UserGetCPDU2A = 0X02, // " Ansi " UserGetCPDClass = 0X10, UserGetCPDWindow = 0X20, UserGetCPDDialog = 0X40, @@ -214,11 +214,7 @@ typedef struct _CALLPROCDATA PROCDESKHEAD head; struct _CALLPROCDATA *spcpdNext; WNDPROC pfnClientPrevious; - union - { - GETCPD wType; - UINT Unicode : 1; - }; + GETCPD wType; } CALLPROCDATA, *PCALLPROCDATA; #define CSF_SERVERSIDEPROC 0x0001 @@ -247,11 +243,6 @@ typedef struct _CLS ULONG cWndReferenceCount; UINT style; WNDPROC lpfnWndProc; - union - { - WNDPROC WndProcExtra; - PCALLPROCDATA CallProc; - }; INT cbclsExtra; INT cbwndExtra; HINSTANCE hModule; @@ -265,12 +256,10 @@ typedef struct _CLS HANDLE hIconSm; /* FIXME - Use pointer! */ //PCURSOR spicnSm; - UINT Destroying : 1; // CSF_WOWDEFERDESTROY UINT Unicode : 1; // !CSF_ANSIPROC - UINT System : 1; // CSF_SYSTEMCLASS - UINT Global : 1; // CS_GLOBALCLASS + UINT Global : 1; // CS_GLOBALCLASS or CSF_SERVERSIDEPROC UINT MenuNameIsString : 1; - UINT NotUsed : 27; + UINT NotUsed : 29; } CLS, *PCLS; @@ -342,10 +331,12 @@ typedef struct _CLS /* Non SDK ExStyles */ #define WS_EX_MAKEVISIBLEWHENUNGHOSTED 0x00000800 +#define WS_EX_FORCELEGACYRESIZENCMETR 0x00800000 #define WS_EX_UISTATEACTIVE 0x04000000 #define WS_EX_REDIRECTED 0X20000000 #define WS_EX_UISTATEKBACCELHIDDEN 0X40000000 #define WS_EX_UISTATEFOCUSRECTHIDDEN 0X80000000 +#define WS_EX_SETANSICREATOR 0x80000000 // For WNDS_ANSICREATOR /* Non SDK Styles */ #define WS_MAXIMIZED WS_MAXIMIZE @@ -385,14 +376,6 @@ typedef struct _WND RECT rcWindow; RECT rcClient; WNDPROC lpfnWndProc; - union - { - /* Pointer to a call procedure handle */ - PCALLPROCDATA CallProc; - /* Extra Wnd proc (windows of system classes) */ - WNDPROC WndProcExtra; - }; - /* Pointer to the window class. */ PCLS pcls; HRGN hrgnUpdate; @@ -431,7 +414,6 @@ typedef struct _WND UINT Unicode : 1; // !(WNDS_ANSICREATOR|WNDS_ANSIWINDOWPROC) ? /* Indicates whether the window is derived from a system class */ - UINT IsSystem : 1; // System class ? UINT InternalPosInitialized : 1; UINT HideFocus : 1; // WS_EX_UISTATEFOCUSRECTHIDDEN ? UINT HideAccel : 1; // WS_EX_UISTATEKBACCELHIDDEN ? @@ -525,10 +507,21 @@ typedef LONG_PTR (NTAPI *PFN_FNID)(PWND, UINT, WPARAM, LPARAM, ULONG_PTR); #define FNID_LAST 0x02B9 #define FNID_NUM FNID_LAST - FNID_FIRST + 1 +#define FNID_NUMSERVERPROC FNID_SWITCH - FNID_FIRST + 1 #define FNID_DDEML 0x2000 // Registers DDEML #define FNID_DESTROY 0x4000 // This is sent when WM_NCDESTROY or in the support routine. // Seen during WM_CREATE on error exit too. +#define FNID_FREED 0x8000 // Window being Freed... + +#define ICLASS_TO_MASK(iCls) (1 << ((iCls))) + +#define GETPFNCLIENTA(fnid)\ + (WNDPROC)(*(((ULONG_PTR *)&gpsi->apfnClientA) + (fnid - FNID_FIRST))) +#define GETPFNCLIENTW(fnid)\ + (WNDPROC)(*(((ULONG_PTR *)&gpsi->apfnClientW) + (fnid - FNID_FIRST))) + +#define GETPFNSERVER(fnid) gpsi->aStoCidPfn[fnid - FNID_FIRST] // ICLS's for NtUserGetClassName FNID to ICLS, NtUserInitializeClientPfnArrays #define ICLS_BUTTON 0 @@ -641,7 +634,7 @@ typedef struct tagSERVERINFO DWORD dwSRVIFlags; ULONG_PTR cHandleEntries; PFN_FNID mpFnidPfn[FNID_NUM]; - WNDPROC aStoCidPfn[7]; + WNDPROC aStoCidPfn[FNID_NUMSERVERPROC]; USHORT mpFnid_serverCBWndProc[FNID_NUM]; PFNCLIENT apfnClientA; PFNCLIENT apfnClientW; @@ -1374,7 +1367,7 @@ NtUserCreateWindowEx( HWND NTAPI NtUserCreateWindowEx( - DWORD dwExStyle, + DWORD dwExStyle, // |= 0x80000000 == Ansi used to set WNDS_ANSICREATOR PLARGE_STRING plstrClassName, PLARGE_STRING plstrClsVesrion, PLARGE_STRING plstrWindowName, @@ -1387,7 +1380,7 @@ NtUserCreateWindowEx( HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam, - DWORD dwFlags, // |= 1 == Ansi + DWORD dwFlags, PVOID acbiBuffer); #endif @@ -3053,7 +3046,6 @@ typedef struct tagKMDDELPARAM #define TWOPARAM_ROUTINE_REGISTERLOGONPROC 0xfffd0062 #define TWOPARAM_ROUTINE_ROS_ISACTIVEICON 0x1001 #define TWOPARAM_ROUTINE_ROS_NCDESTROY 0x1002 -#define TWOPARAM_ROUTINE_ROS_REGSYSCLASSES 0x1003 #define TWOPARAM_ROUTINE_ROS_UPDATEUISTATE 0x1004 DWORD diff --git a/reactos/subsystems/win32/win32k/include/class.h b/reactos/subsystems/win32/win32k/include/class.h index 4859337e83a..5f8dd1cc77d 100644 --- a/reactos/subsystems/win32/win32k/include/class.h +++ b/reactos/subsystems/win32/win32k/include/class.h @@ -58,13 +58,13 @@ RTL_ATOM UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx, IN PUNICODE_STRING ClassName, IN PUNICODE_STRING MenuName, - IN WNDPROC wpExtra, IN DWORD fnID, IN DWORD dwFlags); BOOL UserUnregisterClass(IN PUNICODE_STRING ClassName, - IN HINSTANCE hInstance); + IN HINSTANCE hInstance, + OUT PCLSMENUNAME pClassMenuName); ULONG_PTR UserGetClassLongPtr(IN PCLS Class, @@ -83,20 +83,12 @@ FASTCALL IntCreateClass(IN CONST WNDCLASSEXW* lpwcx, IN PUNICODE_STRING ClassName, IN PUNICODE_STRING MenuName, - IN WNDPROC wpExtra, IN DWORD fnID, IN DWORD dwFlags, IN PDESKTOP Desktop, IN PPROCESSINFO pi); -PCALLPROCDATA -UserFindCallProc(IN PCLS Class, - IN WNDPROC WndProc, - IN BOOL bUnicode); - -BOOL -UserRegisterSystemClasses(IN ULONG Count, - IN PREGISTER_SYSCLASS SystemClasses); +BOOL FASTCALL UserRegisterSystemClasses(VOID); VOID UserAddCallProcToClass(IN OUT PCLS Class, @@ -110,6 +102,10 @@ BOOL IntCheckProcessDesktopClasses(IN PDESKTOP Desktop, IN BOOL FreeOnFailure); +BOOL FASTCALL LookupFnIdToiCls(int, int * ); +WNDPROC FASTCALL IntGetClassWndProc(PCLS, BOOL); +ULONG_PTR FASTCALL UserGetCPD(PVOID,GETCPD,ULONG_PTR); + #endif /* _WIN32K_CLASS_H */ /* EOF */ diff --git a/reactos/subsystems/win32/win32k/include/win32.h b/reactos/subsystems/win32/win32k/include/win32.h index 1e8706a73e0..8a823b81436 100644 --- a/reactos/subsystems/win32/win32k/include/win32.h +++ b/reactos/subsystems/win32/win32k/include/win32.h @@ -31,6 +31,37 @@ #define W32PF_MANUALGUICHECK (0x02000000) #define W32PF_CREATEDWINORDC (0x04000000) +/* THREADINFO Flags */ +#define TIF_INCLEANUP 0x00000001 +#define TIF_16BIT 0x00000002 +#define TIF_SYSTEMTHREAD 0x00000004 +#define TIF_CSRSSTHREAD 0x00000008 +#define TIF_TRACKRECTVISIBLE 0x00000010 +#define TIF_ALLOWFOREGROUNDACTIVATE 0x00000020 +#define TIF_DONTATTACHQUEUE 0x00000040 +#define TIF_DONTJOURNALATTACH 0x00000080 +#define TIF_WOW64 0x00000100 +#define TIF_INACTIVATEAPPMSG 0x00000200 +#define TIF_SPINNING 0x00000400 +#define TIF_PALETTEAWARE 0x00000800 +#define TIF_SHAREDWOW 0x00001000 +#define TIF_FIRSTIDLE 0x00002000 +#define TIF_WAITFORINPUTIDLE 0x00004000 +#define TIF_MOVESIZETRACKING 0x00008000 +#define TIF_VDMAPP 0x00010000 +#define TIF_DOSEMULATOR 0x00020000 +#define TIF_GLOBALHOOKER 0x00040000 +#define TIF_DELAYEDEVENT 0x00080000 +#define TIF_MSGPOSCHANGED 0x00100000 +#define TIF_SHUTDOWNCOMPLETE 0x00200000 +#define TIF_IGNOREPLAYBACKDELAY 0x00400000 +#define TIF_ALLOWOTHERACCOUNTHOOK 0x00800000 +#define TIF_GUITHREADINITIALIZED 0x02000000 +#define TIF_DISABLEIME 0x04000000 +#define TIF_INGETTEXTLENGTH 0x08000000 +#define TIF_ANSILENGTH 0x10000000 +#define TIF_DISABLEHOOKS 0x20000000 + extern BOOL ClientPfnInit; extern HINSTANCE hModClient; extern HANDLE hModuleWin; // This Win32k Instance. @@ -86,7 +117,7 @@ typedef struct _THREADINFO /* ReactOS */ LIST_ENTRY WindowListHead; LIST_ENTRY W32CallbackListHead; - BOOLEAN IsExiting; + BOOLEAN IsExiting; // Use TIF_INCLEANUP SINGLE_LIST_ENTRY ReferencesList; } THREADINFO; @@ -135,7 +166,7 @@ typedef struct _PROCESSINFO LIST_ENTRY PrivateFontListHead; FAST_MUTEX DriverObjListLock; LIST_ENTRY DriverObjListHead; - struct _KBL* KeyboardLayout; + struct _KBL* KeyboardLayout; // THREADINFO only W32HEAP_USER_MAPPING HeapMappings; } PROCESSINFO; diff --git a/reactos/subsystems/win32/win32k/include/window.h b/reactos/subsystems/win32/win32k/include/window.h index 46deb3f19ca..442d384ca43 100644 --- a/reactos/subsystems/win32/win32k/include/window.h +++ b/reactos/subsystems/win32/win32k/include/window.h @@ -67,14 +67,14 @@ typedef struct _WINDOW_OBJECT } WINDOW_OBJECT; /* PWINDOW_OBJECT already declared at top of file */ /* Window flags. */ -#define WINDOWOBJECT_NEED_SIZE (0x00000001) -#define WINDOWOBJECT_NEED_ERASEBKGND (0x00000002) -#define WINDOWOBJECT_NEED_NCPAINT (0x00000004) -#define WINDOWOBJECT_NEED_INTERNALPAINT (0x00000008) +#define WINDOWOBJECT_NEED_SIZE (0x00000001) // WNDS_SENDSIZEMOVEMSGS? +#define WINDOWOBJECT_NEED_ERASEBKGND (0x00000002) // WNDS_ERASEBACKGROUND +#define WINDOWOBJECT_NEED_NCPAINT (0x00000004) // WNDS_SENDNCPAINT +#define WINDOWOBJECT_NEED_INTERNALPAINT (0x00000008) // WNDS_INTERNALPAINT #define WINDOWOBJECT_RESTOREMAX (0x00000020) -#define WINDOWSTATUS_DESTROYING (0x1) -#define WINDOWSTATUS_DESTROYED (0x2) +#define WINDOWSTATUS_DESTROYING (0x1) // WNDS2_INDESTROY +#define WINDOWSTATUS_DESTROYED (0x2) // WNDS_DESTROYED #define HAS_DLGFRAME(Style, ExStyle) \ (((ExStyle) & WS_EX_DLGMODALFRAME) || \ @@ -172,6 +172,8 @@ IntDefWindowProc( PWINDOW_OBJECT Window, UINT Msg, WPARAM wParam, LPARAM lParam, VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG); PWND APIENTRY co_IntCreateWindowEx(DWORD,PUNICODE_STRING,PUNICODE_STRING,DWORD,LONG,LONG,LONG,LONG,HWND,HMENU,HINSTANCE,LPVOID,DWORD,BOOL); +WNDPROC FASTCALL IntGetWindowProc(PWND,BOOL); + #endif /* _WIN32K_WINDOW_H */ /* EOF */ diff --git a/reactos/subsystems/win32/win32k/main/dllmain.c b/reactos/subsystems/win32/win32k/main/dllmain.c index 5f243fe1b5a..3d07b97a43a 100644 --- a/reactos/subsystems/win32/win32k/main/dllmain.c +++ b/reactos/subsystems/win32/win32k/main/dllmain.c @@ -384,7 +384,7 @@ DriverEntry ( } hModuleWin = MmPageEntireDriver(DriverEntry); - + DPRINT("Win32k hInstance 0x%x!\n",hModuleWin); /* * Register Object Manager Callbacks */ diff --git a/reactos/subsystems/win32/win32k/ntuser/callproc.c b/reactos/subsystems/win32/win32k/ntuser/callproc.c index c62b95055fc..8215136b9a2 100644 --- a/reactos/subsystems/win32/win32k/ntuser/callproc.c +++ b/reactos/subsystems/win32/win32k/ntuser/callproc.c @@ -50,7 +50,7 @@ CloneCallProc(IN PDESKTOPINFO Desktop, { NewCallProc->head.h = Handle; NewCallProc->pfnClientPrevious = CallProc->pfnClientPrevious; - NewCallProc->Unicode = CallProc->Unicode; + NewCallProc->wType = CallProc->wType; NewCallProc->spcpdNext = NULL; } @@ -75,7 +75,7 @@ CreateCallProc(IN PDESKTOPINFO Desktop, { NewCallProc->head.h = Handle; NewCallProc->pfnClientPrevious = WndProc; - NewCallProc->Unicode = Unicode; + NewCallProc->wType |= Unicode ? UserGetCPDA2U : UserGetCPDU2A ; NewCallProc->spcpdNext = NULL; } @@ -106,7 +106,7 @@ UserGetCallProcInfo(IN HANDLE hCallProc, }*/ wpInfo->WindowProc = CallProc->pfnClientPrevious; - wpInfo->IsUnicode = CallProc->Unicode; + wpInfo->IsUnicode = !!(CallProc->wType & UserGetCPDA2U); return TRUE; } @@ -164,7 +164,7 @@ UserGetCPD( { CallProc = CreateCallProc( NULL, (WNDPROC)ProcIn, - (Flags & UserGetCPDU2A), + !!(Flags & UserGetCPDA2U), pti->ppi); if (CallProc) { diff --git a/reactos/subsystems/win32/win32k/ntuser/class.c b/reactos/subsystems/win32/win32k/ntuser/class.c index f27d56c1e09..04008afabea 100644 --- a/reactos/subsystems/win32/win32k/ntuser/class.c +++ b/reactos/subsystems/win32/win32k/ntuser/class.c @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: Window classes - * FILE: subsys/win32k/ntuser/class.c + * FILE: subsystems/win32/win32k/ntuser/class.c * PROGRAMER: Thomas Weidenmueller * REVISION HISTORY: * 06-06-2001 CSH Created @@ -17,43 +17,104 @@ #define WARN DPRINT1 #define ERR DPRINT1 -PCLS SystemClassList = NULL; -BOOL RegisteredSysClasses = FALSE; +REGISTER_SYSCLASS DefaultServerClasses[] = +{ +/* { ((PWSTR)((ULONG_PTR)(WORD)(0x8001))), + CS_GLOBALCLASS|CS_DBLCLKS, + NULL, + 0, + IDC_ARROW, + (HBRUSH)(COLOR_BACKGROUND+1), + FNID_DESKTOP, + ICLS_DESKTOP + },*/ + { ((PWSTR)((ULONG_PTR)(WORD)(0x8003))), + CS_VREDRAW|CS_HREDRAW|CS_SAVEBITS, + NULL, // Use User32 procs + sizeof(LONG), + IDC_ARROW, + NULL, + FNID_SWITCH, + ICLS_SWITCH + }, + { ((PWSTR)((ULONG_PTR)(WORD)(0x8000))), + CS_DBLCLKS|CS_SAVEBITS, + NULL, // Use User32 procs + sizeof(LONG), + IDC_ARROW, + (HBRUSH)(COLOR_MENU + 1), + FNID_MENU, + ICLS_MENU + }, + { L"ScrollBar", + CS_DBLCLKS|CS_VREDRAW|CS_HREDRAW|CS_PARENTDC, + NULL, // Use User32 procs + 0, + IDC_ARROW, + NULL, + FNID_SCROLLBAR, + ICLS_SCROLLBAR + }, + { ((PWSTR)((ULONG_PTR)(WORD)(0x8004))), // IconTitle is here for now... + 0, + NULL, // Use User32 procs + 0, + IDC_ARROW, + 0, + FNID_ICONTITLE, + ICLS_ICONTITLE + }, + { L"Message", + CS_GLOBALCLASS, + NULL, // Use User32 procs + 0, + IDC_ARROW, + NULL, + FNID_MESSAGEWND, + ICLS_HWNDMESSAGE + } +}; static struct { int FnId; int ClsId; } FnidToiCls[] = -{ - { FNID_BUTTON, ICLS_BUTTON}, - { FNID_EDIT, ICLS_EDIT}, - { FNID_STATIC, ICLS_STATIC}, - { FNID_LISTBOX, ICLS_LISTBOX}, +{ /* Function Ids to Class indexes. */ { FNID_SCROLLBAR, ICLS_SCROLLBAR}, + { FNID_ICONTITLE, ICLS_ICONTITLE}, + { FNID_MENU, ICLS_MENU}, + { FNID_DESKTOP, ICLS_DESKTOP}, + { FNID_SWITCH, ICLS_SWITCH}, + { FNID_MESSAGEWND, ICLS_HWNDMESSAGE}, + { FNID_BUTTON, ICLS_BUTTON}, { FNID_COMBOBOX, ICLS_COMBOBOX}, - { FNID_MDICLIENT, ICLS_MDICLIENT}, { FNID_COMBOLBOX, ICLS_COMBOLBOX}, { FNID_DIALOG, ICLS_DIALOG}, - { FNID_MENU, ICLS_MENU}, - { FNID_ICONTITLE, ICLS_ICONTITLE} + { FNID_EDIT, ICLS_EDIT}, + { FNID_LISTBOX, ICLS_LISTBOX}, + { FNID_MDICLIENT, ICLS_MDICLIENT}, + { FNID_STATIC, ICLS_STATIC}, + { FNID_IME, ICLS_IME}, + { FNID_GHOST, ICLS_GHOST}, + { FNID_TOOLTIPS, ICLS_TOOLTIPS} }; -static BOOL FASTCALL -LockupFnIdToiCls(int FnId, int *iCls ) +LookupFnIdToiCls(int FnId, int *iCls ) { int i; - for ( i = 0; i < (sizeof(FnidToiCls)/2)/sizeof(int); i++) + for ( i = 0; i < ARRAYSIZE(FnidToiCls); i++) { if (FnidToiCls[i].FnId == FnId) { - *iCls = FnidToiCls[i].ClsId; + if (iCls) *iCls = FnidToiCls[i].ClsId; return TRUE; } } + if (iCls) *iCls = 0; return FALSE; } @@ -74,6 +135,7 @@ IntFreeClassMenuName(IN OUT PCLS Class) static VOID IntDestroyClass(IN OUT PCLS Class) { + PDESKTOP pDesk; /* there shouldn't be any clones anymore */ ASSERT(Class->cWndReferenceCount == 0); ASSERT(Class->pclsClone == NULL); @@ -104,11 +166,13 @@ IntDestroyClass(IN OUT PCLS Class) IntFreeClassMenuName(Class); } + pDesk = Class->rpdeskParent; + Class->rpdeskParent = NULL; + /* free the structure */ - if (Class->rpdeskParent != NULL) + if (pDesk != NULL) { - DesktopHeapFree(Class->rpdeskParent, - Class); + DesktopHeapFree(pDesk, Class); } else { @@ -177,20 +241,6 @@ IntRegisterClassAtom(IN PUNICODE_STRING ClassName, else AtomName = ClassName->Buffer; - /* If an Atom, need to verify, if it was already added to the global atom list. */ - if (IS_ATOM(AtomName)) - { - *pAtom = (RTL_ATOM)((ULONG_PTR)AtomName); - Status = RtlQueryAtomInAtomTable( gAtomTable, - *pAtom, - NULL, - NULL, - NULL, - NULL); - - if (NT_SUCCESS(Status)) return TRUE; - } - Status = RtlAddAtomToAtomTable(gAtomTable, AtomName, pAtom); @@ -211,28 +261,6 @@ IntDeregisterClassAtom(IN RTL_ATOM Atom) Atom); } -PCALLPROCDATA -UserFindCallProc(IN PCLS Class, - IN WNDPROC WndProc, - IN BOOL bUnicode) -{ - PCALLPROCDATA CallProc; - - CallProc = Class->spcpdFirst; - while (CallProc != NULL) - { - if (CallProc->pfnClientPrevious == WndProc && - CallProc->Unicode == (UINT)bUnicode) - { - return CallProc; - } - - CallProc = CallProc->spcpdNext; - } - - return NULL; -} - VOID UserAddCallProcToClass(IN OUT PCLS Class, IN PCALLPROCDATA CallProc) @@ -286,133 +314,136 @@ IntSetClassAtom(IN OUT PCLS Class, return TRUE; } -static WNDPROC -IntGetClassWndProc(IN PCLS Class, - IN PPROCESSINFO pi, - IN BOOL Ansi) // This is what we are looking for?!? +// +// Same as User32:IntGetClsWndProc. +// +WNDPROC FASTCALL +IntGetClassWndProc(PCLS Class, BOOL Ansi) { - ASSERT(UserIsEnteredExclusive() == TRUE); - /* System Classes */ - if (Class->System) - { - // FIXME! System class have gpsi->apfnClientA/W to pick from. - return (Ansi ? Class->WndProcExtra : Class->lpfnWndProc); - } - else - { /* Unicode Proc */ - if (!Ansi == Class->Unicode) - { - return Class->lpfnWndProc; - } - else // Ansi? - { - PCLS BaseClass; + INT i; + WNDPROC gcpd = NULL, Ret = NULL; - /* make sure the call procedures are located on the desktop - of the base class! */ - BaseClass = Class->pclsBase; - Class = BaseClass; - - if (Class->CallProc != NULL) - { - return GetCallProcHandle(Class->CallProc); - } + if (Class->CSF_flags & CSF_SERVERSIDEPROC) + { + for ( i = FNID_FIRST; i <= FNID_SWITCH; i++) + { + if (GETPFNSERVER(i) == Class->lpfnWndProc) + { + if (Ansi) + Ret = GETPFNCLIENTA(i); else - { - PCALLPROCDATA NewCallProc; + Ret = GETPFNCLIENTW(i); + } + } + return Ret; + } + Ret = Class->lpfnWndProc; - if (pi == NULL) - return NULL; + if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON) + { + if (Ansi) + { + if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc) + Ret = GETPFNCLIENTA(Class->fnid); + } + else + { + if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc) + Ret = GETPFNCLIENTW(Class->fnid); + } + } - NewCallProc = UserFindCallProc(Class, - Class->lpfnWndProc, - Class->Unicode); - if (NewCallProc == NULL) - { - NewCallProc = CreateCallProc(NULL, - Class->lpfnWndProc, - Class->Unicode, - pi); - if (NewCallProc == NULL) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return NULL; - } + if ( Ret != Class->lpfnWndProc || + Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) ) + return Ret; - UserAddCallProcToClass(Class, - NewCallProc); - } + gcpd = (WNDPROC)UserGetCPD( Class, + (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDClass, + (ULONG_PTR)Ret); - Class->CallProc = NewCallProc; - - /* update the clones */ - Class = Class->pclsClone; - while (Class != NULL) - { - Class->CallProc = NewCallProc; - - Class = Class->pclsNext; - } - - return GetCallProcHandle(NewCallProc); - } - } - } + return (gcpd ? gcpd : Ret); } -static WNDPROC + +static +WNDPROC FASTCALL IntSetClassWndProc(IN OUT PCLS Class, IN WNDPROC WndProc, IN BOOL Ansi) { - WNDPROC Ret; + INT i; + PCALLPROCDATA pcpd; + WNDPROC Ret, chWndProc; - if (Class->System) - { - DPRINT1("Attempted to change window procedure of system window class 0x%p!\n", Class->atomClassName); - SetLastWin32Error(ERROR_ACCESS_DENIED); - return NULL; - } + Ret = IntGetClassWndProc(Class, Ansi); - /* update the base class first */ - Class = Class->pclsBase; + // If Server Side, downgrade to Client Side. + if (Class->CSF_flags & CSF_SERVERSIDEPROC) + { + if (Ansi) Class->CSF_flags |= CSF_ANSIPROC; + Class->CSF_flags &= ~CSF_SERVERSIDEPROC; + Class->Unicode = !Ansi; + } - /* resolve any callproc handle if possible */ - if (IsCallProcHandle(WndProc)) - { - WNDPROC_INFO wpInfo; + chWndProc = WndProc; - if (UserGetCallProcInfo((HANDLE)WndProc, - &wpInfo)) - { - WndProc = wpInfo.WindowProc; - /* FIXME - what if wpInfo.IsUnicode doesn't match Ansi? */ - } - } + // Check if CallProc handle and retrieve previous call proc address and set. + if (IsCallProcHandle(WndProc)) + { + pcpd = UserGetObject(gHandleTable, WndProc, otCallProc); + if (pcpd) chWndProc = pcpd->pfnClientPrevious; + } - Ret = IntGetClassWndProc(Class, - GetW32ProcessInfo(), - Ansi); - if (Ret == NULL) - { - return NULL; - } + Class->lpfnWndProc = chWndProc; - /* update the class info */ - Class->Unicode = !Ansi; - Class->lpfnWndProc = WndProc; + // Clear test proc. + chWndProc = NULL; - /* update the clones */ - Class = Class->pclsClone; - while (Class != NULL) - { - Class->Unicode = !Ansi; - Class->lpfnWndProc = WndProc; + // Switch from Client Side call to Server Side call if match. Ref: "deftest". + for ( i = FNID_FIRST; i <= FNID_SWITCH; i++) + { + if (GETPFNCLIENTW(i) == Class->lpfnWndProc) + { + chWndProc = GETPFNSERVER(i); + break; + } + if (GETPFNCLIENTA(i) == Class->lpfnWndProc) + { + chWndProc = GETPFNSERVER(i); + break; + } + } + // If match, set/reset to Server Side and clear ansi. + if (chWndProc) + { + Class->lpfnWndProc = chWndProc; + Class->Unicode = TRUE; + Class->CSF_flags &= ~CSF_ANSIPROC; + Class->CSF_flags |= CSF_SERVERSIDEPROC; + } + else + { + Class->Unicode = !Ansi; - Class = Class->pclsNext; - } + if (Ansi) + Class->CSF_flags |= CSF_ANSIPROC; + else + Class->CSF_flags &= ~CSF_ANSIPROC; + } - return Ret; + /* update the clones */ + chWndProc = Class->lpfnWndProc; + + Class = Class->pclsClone; + while (Class != NULL) + { + Class->Unicode = !Ansi; + Class->lpfnWndProc = chWndProc; + + Class = Class->pclsNext; + } + + return Ret; } static PCLS @@ -478,6 +509,7 @@ IntGetClassForDesktop(IN OUT PCLS BaseClass, RtlCopyMemory(Class, BaseClass, ClassSize); + DPRINT("Clone Class 0x%x hM 0x%x\n %S\n",Class, Class->hModule, Class->lpszClientUnicodeMenuName); /* update some pointers and link the class */ Class->rpdeskParent = Desktop; @@ -518,7 +550,6 @@ IntGetClassForDesktop(IN OUT PCLS BaseClass, SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); } } - return Class; } @@ -528,7 +559,6 @@ IntReferenceClass(IN OUT PCLS BaseClass, IN PDESKTOP Desktop) { PCLS Class; - ASSERT(BaseClass->pclsBase == BaseClass); Class = IntGetClassForDesktop(BaseClass, @@ -542,7 +572,8 @@ IntReferenceClass(IN OUT PCLS BaseClass, return Class; } -static VOID +static +VOID IntMakeCloneBaseClass(IN OUT PCLS Class, IN OUT PCLS *BaseClassLink, IN OUT PCLS *CloneLink) @@ -573,9 +604,6 @@ IntMakeCloneBaseClass(IN OUT PCLS Class, ASSERT(Clone->pclsClone == NULL); Clone->pclsBase = Class; - if (!Class->System) - Clone->CallProc = Class->CallProc; - Clone = Clone->pclsNext; } @@ -584,6 +612,7 @@ IntMakeCloneBaseClass(IN OUT PCLS Class, Class); } + VOID IntDereferenceClass(IN OUT PCLS Class, IN PDESKTOPINFO Desktop, @@ -593,21 +622,20 @@ IntDereferenceClass(IN OUT PCLS Class, BaseClass = Class->pclsBase; - if (--Class->cWndReferenceCount == 0) + if (--Class->cWndReferenceCount <= 0) { if (BaseClass == Class) { ASSERT(Class->pclsBase == Class); + DPRINT("IntDereferenceClass 0x%x\n", Class); /* check if there are clones of the class on other desktops, link the first clone in if possible. If there are no clones then leave the class on the desktop heap. It will get moved to the shared heap when the thread detaches. */ if (BaseClass->pclsClone != NULL) { - if (BaseClass->System) - PrevLink = &SystemClassList; - else if (BaseClass->Global) + if (BaseClass->Global) PrevLink = &pi->pclsPublicList; else PrevLink = &pi->pclsPrivateList; @@ -638,6 +666,8 @@ IntDereferenceClass(IN OUT PCLS Class, } else { + DPRINT("IntDereferenceClass1 0x%x\n", Class); + /* locate the cloned class and unlink it */ PrevLink = &BaseClass->pclsClone; CurrentClass = BaseClass->pclsClone; @@ -779,8 +809,6 @@ IntCheckProcessDesktopClasses(IN PDESKTOP Desktop, BOOL Ret = TRUE; pi = GetW32ProcessInfo(); - if (pi == NULL) - return TRUE; /* check all local classes */ IntCheckDesktopClasses(Desktop, @@ -793,13 +821,6 @@ IntCheckProcessDesktopClasses(IN PDESKTOP Desktop, &pi->pclsPublicList, FreeOnFailure, &Ret); - - /* check all system classes */ - IntCheckDesktopClasses(Desktop, - &SystemClassList, - FreeOnFailure, - &Ret); - if (!Ret) { DPRINT1("Failed to move process classes from desktop 0x%p to the shared heap!\n", Desktop); @@ -814,7 +835,6 @@ FASTCALL IntCreateClass(IN CONST WNDCLASSEXW* lpwcx, IN PUNICODE_STRING ClassName, IN PUNICODE_STRING MenuName, - IN WNDPROC wpExtra, IN DWORD fnID, IN DWORD dwFlags, IN PDESKTOP Desktop, @@ -823,11 +843,12 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx, SIZE_T ClassSize; PCLS Class = NULL; RTL_ATOM Atom; + WNDPROC WndProc; PWSTR pszMenuName = NULL; NTSTATUS Status = STATUS_SUCCESS; - TRACE("lpwcx=%p ClassName=%wZ MenuName=%wZ wpExtra=%p dwFlags=%08x Desktop=%p pi=%p\n", - lpwcx, ClassName, MenuName, wpExtra, dwFlags, Desktop, pi); + DPRINT("lpwcx=%p ClassName=%wZ MenuName=%wZ dwFlags=%08x Desktop=%p pi=%p\n", + lpwcx, ClassName, MenuName, dwFlags, Desktop, pi); if (!IntRegisterClassAtom(ClassName, &Atom)) @@ -860,8 +881,9 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx, if (Class != NULL) { - RtlZeroMemory(Class, - ClassSize); + int iCls = 0; + + RtlZeroMemory(Class, ClassSize); Class->rpdeskParent = Desktop; Class->pclsBase = Class; @@ -869,18 +891,9 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx, Class->fnid = fnID; Class->CSF_flags = dwFlags; - if (dwFlags & CSF_SYSTEMCLASS) + if (LookupFnIdToiCls(Class->fnid, &iCls)) { - int iCls; - - dwFlags &= ~CSF_ANSIPROC; - Class->WndProcExtra = wpExtra; - Class->System = TRUE; - /* Now set the Atom table, notice only non ntuser.c atoms can go in.*/ - if (LockupFnIdToiCls(Class->fnid, &iCls)) - { - gpsi->atomSysClass[iCls] = Class->atomClassName; - } + gpsi->atomSysClass[iCls] = Class->atomClassName; } _SEH2_TRY @@ -890,6 +903,7 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx, /* need to protect with SEH since accessing the WNDCLASSEX structure and string buffers might raise an exception! We don't want to leak memory... */ + // What?! If the user interface was written correctly this would not be an issue! Class->lpfnWndProc = lpwcx->lpfnWndProc; Class->style = lpwcx->style; Class->cbclsExtra = lpwcx->cbClsExtra; @@ -900,7 +914,6 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx, Class->hCursor = lpwcx->hCursor; /* FIXME */ Class->hbrBackground = lpwcx->hbrBackground; - /* make a copy of the string */ if (pszMenuNameBuffer != NULL) { @@ -943,7 +956,39 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx, Class->lpszMenuName = Class->lpszClientUnicodeMenuName; // Fixme! //Class->lpszAnsiClassName = Fixme! - if (!(dwFlags & CSF_ANSIPROC)) + /* Server Side overrides class calling type (A/W)! + User32 whine test_builtinproc: "deftest" + built-in winproc - window A/W type automatically detected */ + if (!(Class->CSF_flags & CSF_SERVERSIDEPROC)) + { + int i; + WndProc = NULL; + /* Due to the wine class "deftest" and most likely no FNID to reference + from, sort through the Server Side list and compare proc addresses + for match. This method will be used in related code. + */ + for ( i = FNID_FIRST; i <= FNID_SWITCH; i++) + { // Open Ansi or Unicode, just match, set and break. + if (GETPFNCLIENTW(i) == Class->lpfnWndProc) + { + WndProc = GETPFNSERVER(i); + break; + } + if (GETPFNCLIENTA(i) == Class->lpfnWndProc) + { + WndProc = GETPFNSERVER(i); + break; + } + } + if (WndProc) + { // If a hit, we are Server Side so set the right flags and proc. + Class->CSF_flags |= CSF_SERVERSIDEPROC; + Class->CSF_flags &= ~CSF_ANSIPROC; + Class->lpfnWndProc = WndProc; + } + } + + if (!(Class->CSF_flags & CSF_ANSIPROC)) Class->Unicode = TRUE; if (Class->style & CS_GLOBALCLASS) @@ -1000,7 +1045,7 @@ IntFindClass(IN RTL_ATOM Atom, { if (Class->atomClassName == Atom && (hInstance == NULL || Class->hModule == hInstance) && - !Class->Destroying) + !(Class->CSF_flags & CSF_WOWDEFERDESTROY)) { ASSERT(Class->pclsBase == Class); @@ -1064,7 +1109,7 @@ IntGetAtomFromStringOrAtom(IN PUNICODE_STRING ClassName, { if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { - SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS); + SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); } else { @@ -1139,16 +1184,6 @@ IntGetClassAtom(IN PUNICODE_STRING ClassName, hModClient, &pi->pclsPublicList, Link); - if (Class != NULL) - { - goto FoundClass; - } - - /* Step 5: try to find a system class */ - Class = IntFindClass(Atom, - NULL, - &SystemClassList, - Link); if (Class == NULL) { SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); @@ -1166,7 +1201,6 @@ RTL_ATOM UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx, IN PUNICODE_STRING ClassName, IN PUNICODE_STRING MenuName, - IN WNDPROC wpExtra, IN DWORD fnID, IN DWORD dwFlags) { @@ -1179,45 +1213,46 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx, /* NOTE: Accessing the buffers in ClassName and MenuName may raise exceptions! */ pti = GetW32ThreadInfo(); - if (pti == NULL || !RegisteredSysClasses) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return (RTL_ATOM)0; - } pi = pti->ppi; - /* try to find a previously registered class */ - ClassAtom = IntGetClassAtom(ClassName, - lpwcx->hInstance, - pi, - &Class, - NULL); - if (ClassAtom != (RTL_ATOM)0) + // Need only to test for two conditions not four....... Fix more whine tests.... + if ( IntGetAtomFromStringOrAtom( ClassName, &ClassAtom) && + ClassAtom != (RTL_ATOM)0 && + !(dwFlags & CSF_SERVERSIDEPROC) ) // Bypass Server Sides { - if (lpwcx->style & CS_GLOBALCLASS) - { - // global classes shall not have same names as system classes - if (Class->Global || Class->System) - { - DPRINT("Class 0x%p does already exist!\n", ClassAtom); - SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS); - return (RTL_ATOM)0; - } - } - else if ( !Class->Global && !Class->System) - { - // local class already exists - DPRINT("Class 0x%p does already exist!\n", ClassAtom); - SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS); - return (RTL_ATOM)0; - } + Class = IntFindClass( ClassAtom, + lpwcx->hInstance, + &pi->pclsPrivateList, + NULL); + + if (Class != NULL && !Class->Global) + { + // local class already exists + DPRINT1("Local Class 0x%p does already exist!\n", ClassAtom); + SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS); + return (RTL_ATOM)0; + } + + if (lpwcx->style & CS_GLOBALCLASS) + { + Class = IntFindClass( ClassAtom, + NULL, + &pi->pclsPublicList, + NULL); + + if (Class != NULL && Class->Global) + { + DPRINT1("Global Class 0x%p does already exist!\n", ClassAtom); + SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS); + return (RTL_ATOM)0; + } + } } Class = IntCreateClass(lpwcx, ClassName, MenuName, - wpExtra, fnID, dwFlags, pti->Desktop, @@ -1228,9 +1263,7 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx, PCLS *List; /* Register the class */ - if (Class->System) - List = &SystemClassList; - else if (Class->Global) + if (Class->Global) List = &pi->pclsPublicList; else List = &pi->pclsPrivateList; @@ -1241,13 +1274,18 @@ UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx, Ret = Class->atomClassName; } + else + { + DPRINT1("UserRegisterClass: Yes, that is right, you have no Class!\n"); + } return Ret; } BOOL UserUnregisterClass(IN PUNICODE_STRING ClassName, - IN HINSTANCE hInstance) + IN HINSTANCE hInstance, + OUT PCLSMENUNAME pClassMenuName) { PCLS *Link; PPROCESSINFO pi; @@ -1255,13 +1293,8 @@ UserUnregisterClass(IN PUNICODE_STRING ClassName, PCLS Class; pi = GetW32ProcessInfo(); - if (pi == NULL) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - TRACE("UserUnregisterClass(%wZ)\n", ClassName); + DPRINT("UserUnregisterClass(%wZ, 0x%x)\n", ClassName, hInstance); /* NOTE: Accessing the buffer in ClassName may raise an exception! */ ClassAtom = IntGetClassAtom(ClassName, @@ -1271,6 +1304,7 @@ UserUnregisterClass(IN PUNICODE_STRING ClassName, &Link); if (ClassAtom == (RTL_ATOM)0) { + DPRINT1("UserUnregisterClass: No Class found.\n"); return FALSE; } @@ -1279,6 +1313,7 @@ UserUnregisterClass(IN PUNICODE_STRING ClassName, if (Class->cWndReferenceCount != 0 || Class->pclsClone != NULL) { + DPRINT("UserUnregisterClass: Class has a Window. Ct %d : Clone 0x%x\n", Class->cWndReferenceCount, Class->pclsClone); SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS); return FALSE; } @@ -1291,11 +1326,14 @@ UserUnregisterClass(IN PUNICODE_STRING ClassName, if (NT_SUCCESS(IntDeregisterClassAtom(Class->atomClassName))) { + DPRINT("Class 0x%x\n", Class); + DPRINT("UserUnregisterClass: Good Exit!\n"); /* finally free the resources */ IntDestroyClass(Class); return TRUE; } - return FALSE; + DPRINT1("UserUnregisterClass: Can not deregister Class Atom.\n"); + return FALSE; } INT @@ -1491,9 +1529,7 @@ UserGetClassLongPtr(IN PCLS Class, break; case GCLP_WNDPROC: - Ret = (ULONG_PTR)IntGetClassWndProc(Class, - GetW32ProcessInfo(), - Ansi); + Ret = (ULONG_PTR)IntGetClassWndProc(Class, Ansi); break; case GCW_ATOM: @@ -1812,28 +1848,35 @@ UserGetClassInfo(IN PCLS Class, { PPROCESSINFO pi; + if (!Class) return FALSE; + lpwcx->style = Class->style; - pi = GetW32ProcessInfo(); - lpwcx->lpfnWndProc = IntGetClassWndProc(Class, - pi, - Ansi); + // If fnId is set, clear the global bit. See wine class test check_style. + if (Class->fnid) + lpwcx->style &= ~CS_GLOBALCLASS; + pi = GetW32ProcessInfo(); + + lpwcx->lpfnWndProc = IntGetClassWndProc(Class, Ansi); + lpwcx->cbClsExtra = Class->cbclsExtra; lpwcx->cbWndExtra = Class->cbwndExtra; lpwcx->hIcon = Class->hIcon; /* FIXME - get handle from pointer */ lpwcx->hCursor = Class->hCursor; /* FIXME - get handle from pointer */ lpwcx->hbrBackground = Class->hbrBackground; -/* - FIXME! - Cls: lpszMenuName and lpszAnsiClassName should be used by kernel space. - lpszClientXxxMenuName should already be mapped to user space. - */ + + /* Copy non-string to user first. */ if (Ansi) ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->lpszClientAnsiMenuName; else lpwcx->lpszMenuName = Class->lpszClientUnicodeMenuName; - +/* + FIXME! CLSMENUNAME has the answers! Copy the already made buffers from there! + Cls: lpszMenuName and lpszAnsiClassName should be used by kernel space. + lpszClientXxxMenuName should already be mapped to user space. + */ + /* Copy string ptr to user. */ if ( Class->lpszClientUnicodeMenuName != NULL && Class->MenuNameIsString) { @@ -1855,63 +1898,82 @@ UserGetClassInfo(IN PCLS Class, return TRUE; } +// +// +// BOOL -UserRegisterSystemClasses(IN ULONG Count, - IN PREGISTER_SYSCLASS SystemClasses) +FASTCALL +UserRegisterSystemClasses(VOID) { - /* NOTE: This routine may raise exceptions! */ UINT i; UNICODE_STRING ClassName, MenuName; - PPROCESSINFO pi = GetW32ProcessInfo(); + PPROCESSINFO ppi = GetW32ProcessInfo(); WNDCLASSEXW wc; PCLS Class; BOOL Ret = TRUE; + DWORD Flags = 0; - if ( hModClient == NULL) - return FALSE; - /* Init System Classes once only*/ - if (RegisteredSysClasses) + if (ppi->W32PF_flags & W32PF_CLASSESREGISTERED) return TRUE; + if ( hModClient == NULL) + return FALSE; + + RtlZeroMemory(&ClassName, sizeof(ClassName)); RtlZeroMemory(&MenuName, sizeof(MenuName)); - for (i = 0; i != Count; i++) + for (i = 0; i != ARRAYSIZE(DefaultServerClasses); i++) { - ClassName = ProbeForReadUnicodeString(&SystemClasses[i].ClassName); - if (ClassName.Length != 0) + if (!IS_ATOM(DefaultServerClasses[i].ClassName)) { - ProbeForRead(ClassName.Buffer, - ClassName.Length, - sizeof(WCHAR)); + RtlInitUnicodeString(&ClassName, DefaultServerClasses[i].ClassName); + } + else + { + ClassName.Buffer = DefaultServerClasses[i].ClassName; + ClassName.Length = 0; + ClassName.MaximumLength = 0; + } + + wc.cbSize = sizeof(wc); + wc.style = DefaultServerClasses[i].Style; + + Flags |= CSF_SERVERSIDEPROC; + + if (DefaultServerClasses[i].ProcW) + { + wc.lpfnWndProc = DefaultServerClasses[i].ProcW; + wc.hInstance = hModuleWin; + } + else + { + wc.lpfnWndProc = GETPFNSERVER(DefaultServerClasses[i].fiId); + wc.hInstance = hModClient; } - wc.cbSize = sizeof(wc); - wc.style = SystemClasses[i].Style; - wc.lpfnWndProc = SystemClasses[i].ProcW; wc.cbClsExtra = 0; - wc.cbWndExtra = SystemClasses[i].ExtraBytes; - wc.hInstance = hModClient; + wc.cbWndExtra = DefaultServerClasses[i].ExtraBytes; wc.hIcon = NULL; - wc.hCursor = SystemClasses[i].hCursor; - wc.hbrBackground = SystemClasses[i].hBrush; + wc.hCursor = DefaultServerClasses[i].hCursor; + wc.hbrBackground = DefaultServerClasses[i].hBrush; wc.lpszMenuName = NULL; wc.lpszClassName = ClassName.Buffer; wc.hIconSm = NULL; - Class = IntCreateClass(&wc, - &ClassName, - &MenuName, - SystemClasses[i].ProcA, - SystemClasses[i].ClassId, - CSF_SYSTEMCLASS, - NULL, - pi); + Class = IntCreateClass( &wc, + &ClassName, + &MenuName, + DefaultServerClasses[i].fiId, + Flags, + NULL, + ppi); if (Class != NULL) { - ASSERT(Class->System); - Class->pclsNext = SystemClassList; - (void)InterlockedExchangePointer((PVOID*)&SystemClassList, + Class->pclsNext = ppi->pclsPublicList; + (void)InterlockedExchangePointer((PVOID*)&ppi->pclsPublicList, Class); + + ppi->dwRegisteredClasses |= ICLASS_TO_MASK(DefaultServerClasses[i].iCls); } else { @@ -1919,9 +1981,7 @@ UserRegisterSystemClasses(IN ULONG Count, Ret = FALSE; } } - - if (Ret) - RegisteredSysClasses = TRUE; + if (Ret) ppi->W32PF_flags |= W32PF_CLASSESREGISTERED; return Ret; } @@ -1951,21 +2011,30 @@ NtUserRegisterClassExWOW( WNDCLASSEXW CapturedClassInfo = {0}; UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0}; RTL_ATOM Ret = (RTL_ATOM)0; - WNDPROC wpExtra = NULL; + PPROCESSINFO ppi = GetW32ProcessInfo(); if (Flags & ~(CSF_ANSIPROC)) { + DPRINT1("NtUserRegisterClassExWOW Bad Flags!\n"); SetLastWin32Error(ERROR_INVALID_FLAGS); return Ret; } UserEnterExclusive(); + DPRINT("NtUserRegisterClassExWOW ClsN %wZ\n",ClassName); + + if ( !(ppi->W32PF_flags & W32PF_CLASSESREGISTERED )) + { + UserRegisterSystemClasses(); + } + _SEH2_TRY { /* Probe the parameters and basic parameter checks */ if (ProbeForReadUint(&lpwcx->cbSize) != sizeof(WNDCLASSEXW)) { + DPRINT1("NtUserRegisterClassExWOW Wrong cbSize!\n"); goto InvalidParameter; } @@ -1994,6 +2063,7 @@ NtUserRegisterClassExWOW( CapturedClassInfo.cbWndExtra < 0 || CapturedClassInfo.hInstance == NULL) { + DPRINT1("NtUserRegisterClassExWOW Invalid Parameter Error!\n"); goto InvalidParameter; } @@ -2007,6 +2077,7 @@ NtUserRegisterClassExWOW( { if (!IS_ATOM(CapturedName.Buffer)) { + DPRINT1("NtUserRegisterClassExWOW ClassName Error!\n"); goto InvalidParameter; } } @@ -2020,24 +2091,39 @@ NtUserRegisterClassExWOW( else if (CapturedMenuName.Buffer != NULL && !IS_INTRESOURCE(CapturedMenuName.Buffer)) { + DPRINT1("NtUserRegisterClassExWOW MenuName Error!\n"); InvalidParameter: SetLastWin32Error(ERROR_INVALID_PARAMETER); _SEH2_LEAVE; } + + if (IsCallProcHandle(lpwcx->lpfnWndProc)) + {// Never seen this yet, but I'm sure it's a little haxxy trick! + // If this pops up we know what todo! + DPRINT1("NtUserRegisterClassExWOW WndProc is CallProc!!\n"); + } + + DPRINT("NtUserRegisterClassExWOW MnuN %wZ\n",&CapturedMenuName); + /* Register the class */ Ret = UserRegisterClass(&CapturedClassInfo, &CapturedName, &CapturedMenuName, - wpExtra, fnID, Flags); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + DPRINT1("NtUserRegisterClassExWOW Exception Error!\n"); SetLastNtError(_SEH2_GetExceptionCode()); } _SEH2_END; + if (!Ret) + { + DPRINT1("NtUserRegisterClassExWOW Null Return!\n"); + } + UserLeave(); return Ret; @@ -2067,7 +2153,9 @@ NtUserGetClassLong(IN HWND hWnd, Offset, Ansi); - if (Ret != 0 && Offset == GCLP_MENUNAME && Window->Wnd->pcls->MenuNameIsString) + if ( Ret != 0 && + Offset == GCLP_MENUNAME && + Window->Wnd->pcls->MenuNameIsString) { Ret = (ULONG_PTR)UserHeapAddressToUser((PVOID)Ret); } @@ -2093,8 +2181,6 @@ NtUserSetClassLong(HWND hWnd, UserEnterExclusive(); pi = GetW32ProcessInfo(); - if (pi == NULL) - goto Cleanup; Window = UserGetWindowObject(hWnd); if (Window != NULL) @@ -2209,7 +2295,8 @@ InvalidParameter: /* unregister the class */ Ret = UserUnregisterClass(&CapturedClassName, - hInstance); + hInstance, + NULL); // Null for now~ } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -2234,18 +2321,18 @@ NtUserGetClassInfo( WNDCLASSEXW Safewcexw; PCLS Class; RTL_ATOM ClassAtom = 0; - PPROCESSINFO pi; + PPROCESSINFO ppi; BOOL Ret = TRUE; /* NOTE: need exclusive lock because getting the wndproc might require the creation of a call procedure handle */ UserEnterExclusive(); - pi = GetW32ProcessInfo(); - if (pi == NULL) + ppi = GetW32ProcessInfo(); + + if ( !(ppi->W32PF_flags & W32PF_CLASSESREGISTERED )) { - ERR("GetW32ProcessInfo() returned NULL!\n"); - goto Cleanup; + UserRegisterSystemClasses(); } _SEH2_TRY @@ -2310,11 +2397,14 @@ InvalidParameter: } _SEH2_END; + // If null instance use client. + if (!hInstance) hInstance = hModClient; + if (Ret) { ClassAtom = IntGetClassAtom( &SafeClassName, hInstance, - pi, + ppi, &Class, NULL); if (ClassAtom != (RTL_ATOM)0) @@ -2354,14 +2444,12 @@ InvalidParameter: } _SEH2_END; -Cleanup: if (SafeClassName.Length) ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING); UserLeave(); return Ret; } - INT APIENTRY NtUserGetClassName (IN HWND hWnd, OUT PUNICODE_STRING ClassName, @@ -2418,11 +2506,6 @@ NtUserGetWOWClass(HINSTANCE hInstance, UserEnterExclusive(); pi = GetW32ProcessInfo(); - if (pi == NULL) - { - ERR("GetW32ProcessInfo() returned NULL!\n"); - goto Cleanup; - } _SEH2_TRY { @@ -2476,7 +2559,6 @@ NtUserGetWOWClass(HINSTANCE hInstance, } } -Cleanup: if (SafeClassName.Length) ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING); UserLeave(); // diff --git a/reactos/subsystems/win32/win32k/ntuser/desktop.c b/reactos/subsystems/win32/win32k/ntuser/desktop.c index 14f979b16a6..1b1dab69ff4 100644 --- a/reactos/subsystems/win32/win32k/ntuser/desktop.c +++ b/reactos/subsystems/win32/win32k/ntuser/desktop.c @@ -912,10 +912,7 @@ NtUserCreateDesktop( HWINSTA hWindowStation = NULL ; PUNICODE_STRING lpszDesktopName = NULL; UNICODE_STRING ClassName, WindowName, MenuName; - PPROCESSINFO pi = GetW32ProcessInfo(); - WNDCLASSEXW wc; - PCLS Class; - PWND pWnd; + PWND pWnd = NULL; DECLARE_RETURN(HDESK); DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName); @@ -1112,44 +1109,11 @@ NtUserCreateDesktop( Based on wine/server/window.c in get_desktop_window. */ - ClassName.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(AtomMessage))); + ClassName.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_HWNDMESSAGE]))); ClassName.Length = 0; RtlZeroMemory(&MenuName, sizeof(MenuName)); RtlZeroMemory(&WindowName, sizeof(WindowName)); - wc.cbSize = sizeof(wc); - wc.style = 0; - wc.lpfnWndProc = gpsi->apfnClientW.pfnMessageWindowProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hModClient; - wc.hIcon = NULL; - wc.hCursor = NULL; - wc.hbrBackground = 0; - wc.lpszMenuName = NULL; - wc.lpszClassName = ClassName.Buffer; - wc.hIconSm = NULL; - - Class = IntCreateClass( &wc, - &ClassName, - &MenuName, - NULL, - FNID_MESSAGEWND, - CSF_SYSTEMCLASS, - NULL, - pi); - if (Class != NULL) - { - ASSERT(Class->System); - Class->pclsNext = SystemClassList; - (void)InterlockedExchangePointer((PVOID*)&SystemClassList, - Class); - } - else - { - DPRINT1("!!! Registering Message system class failed!\n"); - } - pWnd = co_IntCreateWindowEx( 0, &ClassName, &WindowName, diff --git a/reactos/subsystems/win32/win32k/ntuser/message.c b/reactos/subsystems/win32/win32k/ntuser/message.c index 367bd9db81b..580c4de4246 100644 --- a/reactos/subsystems/win32/win32k/ntuser/message.c +++ b/reactos/subsystems/win32/win32k/ntuser/message.c @@ -303,6 +303,7 @@ IntCallWndProc co_HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, SameThread, (LPARAM)&CWP ); } } + static VOID FASTCALL @@ -1535,9 +1536,13 @@ co_IntSendMessageTimeoutSingle(HWND hWnd, RETURN( FALSE); } - Result = (ULONG_PTR)co_IntCallWindowProc(Window->Wnd->lpfnWndProc, !Window->Wnd->Unicode, hWnd, Msg, wParam, - lParamPacked,lParamBufferSize); - + Result = (ULONG_PTR)co_IntCallWindowProc( Window->Wnd->lpfnWndProc, + !Window->Wnd->Unicode, + hWnd, + Msg, + wParam, + lParamPacked, + lParamBufferSize); if(uResult) { *uResult = Result; @@ -1744,18 +1749,10 @@ co_IntDoSendMessage(HWND hWnd, IntCallWndProc( Window, hWnd, Msg, wParam, lParam); - if (Window->Wnd->IsSystem) - { - Info.Proc = (!Info.Ansi ? Window->Wnd->lpfnWndProc : Window->Wnd->WndProcExtra); - } - else - { - Info.Ansi = !Window->Wnd->Unicode; - Info.Proc = Window->Wnd->lpfnWndProc; - } + Info.Ansi = !Window->Wnd->Unicode; + Info.Proc = Window->Wnd->lpfnWndProc; IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, &Result); - } else { diff --git a/reactos/subsystems/win32/win32k/ntuser/monitor.c b/reactos/subsystems/win32/win32k/ntuser/monitor.c index 6067fc04e40..d1042debf47 100644 --- a/reactos/subsystems/win32/win32k/ntuser/monitor.c +++ b/reactos/subsystems/win32/win32k/ntuser/monitor.c @@ -195,7 +195,6 @@ IntAttachMonitor(IN PDEVOBJ *pGdiDevice, PMONITOR_OBJECT p; DPRINT("Additional monitor is beeing attached\n"); for (p = gMonitorList; p->Next != NULL; p = p->Next) - ; { p->Next = Monitor; } diff --git a/reactos/subsystems/win32/win32k/ntuser/ntstubs.c b/reactos/subsystems/win32/win32k/ntuser/ntstubs.c index 840e2e4abfd..967511c30b7 100644 --- a/reactos/subsystems/win32/win32k/ntuser/ntstubs.c +++ b/reactos/subsystems/win32/win32k/ntuser/ntstubs.c @@ -368,6 +368,10 @@ NtUserInitializeClientPfnArrays( RtlCopyMemory(&gpsi->apfnClientW, pfnClientW, sizeof(PFNCLIENT)); RtlCopyMemory(&gpsi->apfnClientWorker, pfnClientWorker, sizeof(PFNCLIENTWORKER)); + //// FIXME! HAX! Temporary until server side is finished. + //// Copy the client side procs for now. + RtlCopyMemory(&gpsi->aStoCidPfn, pfnClientW, sizeof(gpsi->aStoCidPfn)); + hModClient = hmodUser; ClientPfnInit = TRUE; } diff --git a/reactos/subsystems/win32/win32k/ntuser/simplecall.c b/reactos/subsystems/win32/win32k/ntuser/simplecall.c index f9fb61b6adb..e14966d2ffb 100644 --- a/reactos/subsystems/win32/win32k/ntuser/simplecall.c +++ b/reactos/subsystems/win32/win32k/ntuser/simplecall.c @@ -520,34 +520,6 @@ NtUserCallTwoParam( case TWOPARAM_ROUTINE_REGISTERLOGONPROC: RETURN( (DWORD)co_IntRegisterLogonProcess((HANDLE)Param1, (BOOL)Param2)); - - case TWOPARAM_ROUTINE_ROS_REGSYSCLASSES: - { - DWORD Ret = 0; - DWORD Count = Param1; - PREGISTER_SYSCLASS RegSysClassArray = (PREGISTER_SYSCLASS)Param2; - - if (Count != 0 && RegSysClassArray != NULL) - { - _SEH2_TRY - { - ProbeArrayForRead(RegSysClassArray, - sizeof(RegSysClassArray[0]), - Count, - 2); - - Ret = (DWORD)UserRegisterSystemClasses(Count, - RegSysClassArray); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastNtError(_SEH2_GetExceptionCode()); - } - _SEH2_END; - } - - RETURN( Ret); - } } DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n", Routine, Param1, Param2); diff --git a/reactos/subsystems/win32/win32k/ntuser/window.c b/reactos/subsystems/win32/win32k/ntuser/window.c index bdbbc1619c5..3b7820ab2d4 100644 --- a/reactos/subsystems/win32/win32k/ntuser/window.c +++ b/reactos/subsystems/win32/win32k/ntuser/window.c @@ -432,6 +432,7 @@ static LRESULT co_UserFreeWindow(PWINDOW_OBJECT Window, /* from now on no messages can be sent to this window anymore */ Window->Status |= WINDOWSTATUS_DESTROYED; Wnd->state |= WNDS_DESTROYED; + Wnd->fnid |= FNID_FREED; /* don't remove the WINDOWSTATUS_DESTROYING bit */ @@ -539,64 +540,148 @@ IntGetWindowBorderMeasures(PWINDOW_OBJECT Window, UINT *cx, UINT *cy) } } -static WNDPROC -IntGetWindowProc(IN PWINDOW_OBJECT Window, - IN BOOL Ansi) +// +// Same as User32:IntGetWndProc. +// +WNDPROC FASTCALL +IntGetWindowProc(PWND pWnd, + BOOL Ansi) { - PWND Wnd = Window->Wnd; + INT i; + PCLS Class; + WNDPROC gcpd, Ret = 0; - ASSERT(UserIsEnteredExclusive() == TRUE); + ASSERT(UserIsEnteredExclusive() == TRUE); - if (Wnd->IsSystem) - { - return (Ansi ? Wnd->WndProcExtra : Wnd->lpfnWndProc); - } - else - { - if (!Ansi == Wnd->Unicode) - { - return Wnd->lpfnWndProc; - } - else - { - if (Wnd->CallProc != NULL) - { - return GetCallProcHandle(Wnd->CallProc); - } - /* BUGBOY Comments: Maybe theres something Im not undestanding here, but why would a CallProc be created - on a function that I thought is only suppose to return the current Windows Proc? */ + Class = pWnd->pcls; + + if (pWnd->state & WNDS_SERVERSIDEWINDOWPROC) + { + for ( i = FNID_FIRST; i <= FNID_SWITCH; i++) + { + if (GETPFNSERVER(i) == pWnd->lpfnWndProc) + { + if (Ansi) + Ret = GETPFNCLIENTA(i); else - { - PCALLPROCDATA NewCallProc, CallProc; + Ret = GETPFNCLIENTW(i); + } + } + return Ret; + } - NewCallProc = UserFindCallProc(Wnd->pcls, - Wnd->lpfnWndProc, - Wnd->Unicode); - if (NewCallProc == NULL) - { - NewCallProc = CreateCallProc(Wnd->head.pti->pDeskInfo, - Wnd->lpfnWndProc, - Wnd->Unicode, - Wnd->head.pti->ppi); - if (NewCallProc == NULL) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return NULL; - } + if (Class->fnid == FNID_EDIT) + Ret = pWnd->lpfnWndProc; + else + { + Ret = pWnd->lpfnWndProc; - UserAddCallProcToClass(Wnd->pcls, - NewCallProc); - } + if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON) + { + if (Ansi) + { + if (GETPFNCLIENTW(Class->fnid) == pWnd->lpfnWndProc) + Ret = GETPFNCLIENTA(Class->fnid); + } + else + { + if (GETPFNCLIENTA(Class->fnid) == pWnd->lpfnWndProc) + Ret = GETPFNCLIENTW(Class->fnid); + } + } + if ( Ret != pWnd->lpfnWndProc) + return Ret; + } + if ( Ansi == !!(pWnd->state & WNDS_ANSIWINDOWPROC) ) + return Ret; - CallProc = Wnd->CallProc; - Wnd->CallProc = NewCallProc; + gcpd = (WNDPROC)UserGetCPD( + pWnd, + (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDWindow, + (ULONG_PTR)Ret); - return GetCallProcHandle((CallProc == NULL ? NewCallProc : CallProc)); - } - } - } + return (gcpd ? gcpd : Ret); } +static WNDPROC +IntSetWindowProc(PWND pWnd, + WNDPROC NewWndProc, + BOOL Ansi) +{ + INT i; + PCALLPROCDATA CallProc; + PCLS Class; + WNDPROC Ret, chWndProc = NULL; + + // Retrieve previous window proc. + Ret = IntGetWindowProc(pWnd, Ansi); + + Class = pWnd->pcls; + + if (IsCallProcHandle(NewWndProc)) + { + CallProc = UserGetObject(gHandleTable, NewWndProc, otCallProc); + if (CallProc) + { // Reset new WndProc. + NewWndProc = CallProc->pfnClientPrevious; + // Reset Ansi from CallProc handle. This is expected with wine "deftest". + Ansi = !!(CallProc->wType & UserGetCPDU2A); + } + } + // Switch from Client Side call to Server Side call if match. Ref: "deftest". + for ( i = FNID_FIRST; i <= FNID_SWITCH; i++) + { + if (GETPFNCLIENTW(i) == NewWndProc) + { + chWndProc = GETPFNSERVER(i); + break; + } + if (GETPFNCLIENTA(i) == NewWndProc) + { + chWndProc = GETPFNSERVER(i); + break; + } + } + // If match, set/reset to Server Side and clear ansi. + if (chWndProc) + { + pWnd->lpfnWndProc = chWndProc; + pWnd->Unicode = TRUE; + pWnd->state &= ~WNDS_ANSIWINDOWPROC; + pWnd->state |= WNDS_SERVERSIDEWINDOWPROC; + } + else + { + pWnd->Unicode = !Ansi; + // Handle the state change in here. + if (Ansi) + pWnd->state |= WNDS_ANSIWINDOWPROC; + else + pWnd->state &= ~WNDS_ANSIWINDOWPROC; + + if (pWnd->state & WNDS_SERVERSIDEWINDOWPROC) + pWnd->state &= ~WNDS_SERVERSIDEWINDOWPROC; + + if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON) + { + if (Ansi) + { + if (GETPFNCLIENTW(Class->fnid) == NewWndProc) + chWndProc = GETPFNCLIENTA(Class->fnid); + } + else + { + if (GETPFNCLIENTA(Class->fnid) == NewWndProc) + chWndProc = GETPFNCLIENTW(Class->fnid); + } + } + // Now set the new window proc. + pWnd->lpfnWndProc = (chWndProc ? chWndProc : NewWndProc); + } + return Ret; +} + +// Move this to user space! BOOL FASTCALL IntGetWindowInfo(PWINDOW_OBJECT Window, PWINDOWINFO pwi) { @@ -1026,7 +1111,7 @@ co_IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent) if (IntIsChildWindow(Wnd, WndNewParent)) { SetLastWin32Error( ERROR_INVALID_PARAMETER ); - return 0; + return NULL; } /* @@ -1582,8 +1667,16 @@ co_IntCreateWindowEx(DWORD dwExStyle, ParentWindowHandle = pti->Desktop->DesktopWindow; } + + if ( !(pti->ppi->W32PF_flags & W32PF_CLASSESREGISTERED )) + { + UserRegisterSystemClasses(); + } + OwnerWindowHandle = NULL; + DPRINT("co_IntCreateWindowEx %wZ\n", ClassName); + if (hWndParent == HWND_MESSAGE) { /* @@ -1633,6 +1726,8 @@ co_IntCreateWindowEx(DWORD dwExStyle, /* Check the class. */ + DPRINT("Class %wZ\n", ClassName); + ClassAtom = IntGetClassAtom(ClassName, hInstance, ti->ppi, @@ -1653,7 +1748,7 @@ co_IntCreateWindowEx(DWORD dwExStyle, SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS); RETURN((PWND)0); } - + DPRINT("ClassAtom %x\n", ClassAtom); Class = IntReferenceClass(Class, ClassLink, pti->Desktop); @@ -1683,6 +1778,7 @@ co_IntCreateWindowEx(DWORD dwExStyle, sizeof(WND) + Class->cbwndExtra); Window->Wnd->head.h = hWnd; Wnd = Window->Wnd; + Wnd->fnid = 0; Wnd->head.pti = ti; Wnd->head.rpdesk = pti->Desktop; @@ -1747,27 +1843,68 @@ AllocErr: Wnd->dwUserData = 0; - Wnd->IsSystem = Wnd->pcls->System; + if (Wnd->pcls->CSF_flags & CSF_SERVERSIDEPROC) + Wnd->state |= WNDS_SERVERSIDEWINDOWPROC; - /* BugBoy Comments: Comment below say that System classes are always created as UNICODE. - In windows, creating a window with the ANSI version of CreateWindow sets the window - to ansi as verified by testing with IsUnicodeWindow API. + /* BugBoy Comments: Comment below say that System classes are always created + as UNICODE. In windows, creating a window with the ANSI version of CreateWindow + sets the window to ansi as verified by testing with IsUnicodeWindow API. - No where can I see in code or through testing does the window change back to ANSI - after being created as UNICODE in ROS. I didnt do more testing to see what problems this would cause.*/ - // See NtUserDefSetText! We convert to Unicode all the time and never use Mix. (jt) - if (Wnd->pcls->System) + No where can I see in code or through testing does the window change back + to ANSI after being created as UNICODE in ROS. I didnt do more testing to + see what problems this would cause.*/ + + // Set WndProc from Class. + Wnd->lpfnWndProc = Wnd->pcls->lpfnWndProc; + + // GetWindowProc, test for non server side default classes and set WndProc. + if ( Wnd->pcls->fnid <= FNID_GHOST && Wnd->pcls->fnid >= FNID_BUTTON ) + { + if (bUnicodeWindow) + { + if (GETPFNCLIENTA(Wnd->pcls->fnid) == Wnd->lpfnWndProc) + Wnd->lpfnWndProc = GETPFNCLIENTW(Wnd->pcls->fnid); + } + else + { + if (GETPFNCLIENTW(Wnd->pcls->fnid) == Wnd->lpfnWndProc) + Wnd->lpfnWndProc = GETPFNCLIENTA(Wnd->pcls->fnid); + } + } + + // If not an Unicode caller, set Ansi creator bit. + if (!bUnicodeWindow) Wnd->state |= WNDS_ANSICREATOR; + + // Clone Class Ansi/Unicode proc type. + if (Wnd->pcls->CSF_flags & CSF_ANSIPROC) { - /* NOTE: Always create a unicode window for system classes! */ - Wnd->Unicode = TRUE; - Wnd->lpfnWndProc = Wnd->pcls->lpfnWndProc; - Wnd->WndProcExtra = Wnd->pcls->WndProcExtra; + Wnd->state |= WNDS_ANSIWINDOWPROC; + Wnd->Unicode = FALSE; } else - { - Wnd->Unicode = Wnd->pcls->Unicode; - Wnd->lpfnWndProc = Wnd->pcls->lpfnWndProc; - Wnd->CallProc = NULL; + { /* + It seems there can be both an Ansi creator and Unicode Class Window + WndProc, unless the following overriding conditions occur: + */ + if ( !bUnicodeWindow && + ( ClassAtom == gpsi->atomSysClass[ICLS_BUTTON] || + ClassAtom == gpsi->atomSysClass[ICLS_COMBOBOX] || + ClassAtom == gpsi->atomSysClass[ICLS_COMBOLBOX] || + ClassAtom == gpsi->atomSysClass[ICLS_DIALOG] || + ClassAtom == gpsi->atomSysClass[ICLS_EDIT] || + ClassAtom == gpsi->atomSysClass[ICLS_IME] || + ClassAtom == gpsi->atomSysClass[ICLS_LISTBOX] || + ClassAtom == gpsi->atomSysClass[ICLS_MDICLIENT] || + ClassAtom == gpsi->atomSysClass[ICLS_STATIC] ) ) + { // Override Class and set the window Ansi WndProc. + Wnd->state |= WNDS_ANSIWINDOWPROC; + Wnd->Unicode = FALSE; + } + else + { // Set the window Unicode WndProc. + Wnd->state &= ~WNDS_ANSIWINDOWPROC; + Wnd->Unicode = TRUE; + } } Window->OwnerThread = PsGetCurrentThread(); @@ -2270,8 +2407,6 @@ AllocErr: else { UserAddCallProcToClass(Wnd->pcls, CallProc); - Wnd->CallProc = CallProc; - Wnd->IsSystem = FALSE; } } @@ -2435,6 +2570,8 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWINDOW_OBJECT Window) if (!Wnd) return TRUE; // FIXME: Need to finish object rewrite or lock the thread when killing the window! + DPRINT("co_UserDestroyWindow \n"); + /* Check for owner thread */ if ((Window->OwnerThread != PsGetCurrentThread())) { @@ -2557,8 +2694,6 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWINDOW_OBJECT Window) } - - /* * @implemented */ @@ -2992,8 +3127,6 @@ PWINDOW_OBJECT FASTCALL UserGetAncestor(PWINDOW_OBJECT Wnd, UINT Type) return WndAncestor; } - - /* * @implemented */ @@ -3222,8 +3355,6 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent) return( hWndOldParent); } - - /* * NtUserSetParent * @@ -3269,8 +3400,6 @@ CLEANUP: END_CLEANUP; } - - /* * UserGetShellWindow * @@ -3493,9 +3622,6 @@ CLEANUP: END_CLEANUP; } - - - HWND FASTCALL UserGetWindow(HWND hWnd, UINT Relationship) { @@ -3548,8 +3674,6 @@ UserGetWindow(HWND hWnd, UINT Relationship) return hWndResult; } - - /* * NtUserGetWindow * @@ -3576,9 +3700,6 @@ CLEANUP: END_CLEANUP; } - - - /* * NtUserGetWindowLong * @@ -3638,8 +3759,7 @@ UserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi) break; case GWL_WNDPROC: - Result = (LONG)IntGetWindowProc(Window, - Ansi); + Result = (LONG)IntGetWindowProc(Wnd, Ansi); break; case GWL_HINSTANCE: @@ -3676,9 +3796,6 @@ UserGetWindowLong(HWND hWnd, DWORD Index, BOOL Ansi) return Result; } - - - /* * NtUserGetWindowLong * @@ -3706,102 +3823,6 @@ CLEANUP: END_CLEANUP; } -static WNDPROC -IntSetWindowProc(PWINDOW_OBJECT Window, - WNDPROC NewWndProc, - BOOL Ansi) -{ - WNDPROC Ret; - PCALLPROCDATA CallProc; - PWND Wnd = Window->Wnd; - - /* resolve any callproc handle if possible */ - if (IsCallProcHandle(NewWndProc)) - { - WNDPROC_INFO wpInfo; - - if (UserGetCallProcInfo((HANDLE)NewWndProc, - &wpInfo)) - { - NewWndProc = wpInfo.WindowProc; - /* FIXME - what if wpInfo.IsUnicode doesn't match Ansi? */ - } - } - - /* attempt to get the previous window proc */ - if (Wnd->IsSystem) - { - Ret = (Ansi ? Wnd->WndProcExtra : Wnd->lpfnWndProc); - } - else - { - if (!Ansi == Wnd->Unicode) - { - Ret = Wnd->lpfnWndProc; - } - else - { - CallProc = UserFindCallProc(Wnd->pcls, - Wnd->lpfnWndProc, - Wnd->Unicode); - if (CallProc == NULL) - { - CallProc = CreateCallProc(NULL, - Wnd->lpfnWndProc, - Wnd->Unicode, - Wnd->head.pti->ppi); - if (CallProc == NULL) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return NULL; - } - - UserAddCallProcToClass(Wnd->pcls, - CallProc); - } - /* BugBoy Comments: Added this if else, see below comments */ - if (!Wnd->CallProc) - { - Ret = Wnd->lpfnWndProc; - } - else - { - Ret = GetCallProcHandle(Wnd->CallProc); - } - - Wnd->CallProc = CallProc; - - /* BugBoy Comments: Above sets the current CallProc for the - window and below we set the Ret value to it. - SetWindowLong for WNDPROC should return the previous proc - Ret = GetCallProcHandle(Wnd->CallProc); */ - } - } - - if (Wnd->pcls->System) - { - /* check if the new procedure matches with the one in the - window class. If so, we need to restore both procedures! */ - Wnd->IsSystem = (NewWndProc == Wnd->pcls->lpfnWndProc || - NewWndProc == Wnd->pcls->WndProcExtra); - - if (Wnd->IsSystem) - { - Wnd->lpfnWndProc = Wnd->pcls->lpfnWndProc; - Wnd->WndProcExtra = Wnd->pcls->WndProcExtra; - Wnd->Unicode = !Ansi; - return Ret; - } - } - - ASSERT(!Wnd->IsSystem); - - /* update the window procedure */ - Wnd->lpfnWndProc = NewWndProc; - Wnd->Unicode = !Ansi; - - return Ret; -} LONG FASTCALL @@ -3835,7 +3856,17 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi) SetLastWin32Error(ERROR_INVALID_PARAMETER); return( 0); } + OldValue = *((LONG *)((PCHAR)(Wnd + 1) + Index)); +/* + if ( Index == DWLP_DLGPROC && Wnd->state & WNDS_DIALOGWINDOW) + { + OldValue = (LONG)IntSetWindowProc( Wnd, + (WNDPROC)NewValue, + Ansi); + if (!OldValue) return 0; + } +*/ *((LONG *)((PCHAR)(Wnd + 1) + Index)) = NewValue; } else @@ -3873,8 +3904,13 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi) case GWL_WNDPROC: { - /* FIXME: should check if window belongs to current process */ - OldValue = (LONG)IntSetWindowProc(Window, + if ( Wnd->head.pti->ppi != PsGetCurrentProcessWin32Process() || + Wnd->fnid & FNID_FREED) + { + SetLastWin32Error(ERROR_ACCESS_DENIED); + return( 0); + } + OldValue = (LONG)IntSetWindowProc(Wnd, (WNDPROC)NewValue, Ansi); break; @@ -3914,8 +3950,6 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi) return( OldValue); } - - /* * NtUserSetWindowLong *