Author: jimtabor Date: Fri Jul 24 03:03:11 2009 New Revision: 42168
URL: http://svn.reactos.org/svn/reactos?rev=42168&view=rev Log: - [Win32k] More work on classes. Fixed SEH abuse and implemented NtUserGetWOWClass. Minor bug fixes and modifications that help function compatibility based on wine. - Tested wine (some improvements and losses): Msi seems to be fixed, did not test before these changes. My guess is Jeffrey Morlan fixed it in 42163, so a Big Thank You!!! Tested Firefox 1.15.xx and AbiWord 2.6.8.
Modified: trunk/reactos/dll/win32/user32/windows/class.c trunk/reactos/dll/win32/user32/windows/defwnd.c trunk/reactos/include/reactos/win32k/ntuser.h trunk/reactos/subsystems/win32/win32k/ntuser/class.c trunk/reactos/subsystems/win32/win32k/ntuser/window.c
Modified: trunk/reactos/dll/win32/user32/windows/class.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/cl... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/class.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/user32/windows/class.c [iso-8859-1] Fri Jul 24 03:03:11 2009 @@ -25,6 +25,7 @@ { UNICODE_STRING ClassName = {0}; BOOL Ret; + LPCSTR pszMenuName;
TRACE("%p class/atom: %s/%04x %p\n", hInstance, IS_ATOM(lpszClass) ? NULL : lpszClass, @@ -62,8 +63,13 @@ Ret = NtUserGetClassInfo(hInstance, &ClassName, (LPWNDCLASSEXW)lpwcx, - NULL, + (LPWSTR *)&pszMenuName, TRUE); + if (Ret) + { + lpwcx->lpszClassName = lpszClass; +// lpwcx->lpszMenuName = pszMenuName; + }
if (!IS_ATOM(lpszClass)) { @@ -85,6 +91,8 @@ LPWNDCLASSEXW lpwcx) { UNICODE_STRING ClassName = {0}; + BOOL Ret; + LPWSTR pszMenuName;
TRACE("%p class/atom: %S/%04x %p\n", hInstance, IS_ATOM(lpszClass) ? NULL : lpszClass, @@ -115,11 +123,17 @@ lpszClass); }
- return NtUserGetClassInfo(hInstance, + Ret = NtUserGetClassInfo( hInstance, &ClassName, lpwcx, - NULL, + &pszMenuName, FALSE); + if (Ret) + { + lpwcx->lpszClassName = lpszClass; +// lpwcx->lpszMenuName = pszMenuName; + } + return Ret; }
@@ -238,7 +252,7 @@ break;
case GCL_MENUNAME: - Ret = (ULONG_PTR)Class->AnsiMenuName; + Ret = (ULONG_PTR)Class->lpszClientAnsiMenuName; break;
case GCL_STYLE: @@ -351,7 +365,7 @@ break;
case GCL_MENUNAME: - Ret = (ULONG_PTR)Class->MenuName; + Ret = (ULONG_PTR)Class->lpszClientUnicodeMenuName; break;
case GCL_STYLE:
Modified: trunk/reactos/dll/win32/user32/windows/defwnd.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/de... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/defwnd.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/user32/windows/defwnd.c [iso-8859-1] Fri Jul 24 03:03:11 2009 @@ -970,7 +970,7 @@ * Client area */ if ( uFlags & PRF_CLIENT) - SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT); + SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, uFlags); }
static BOOL CALLBACK
Modified: trunk/reactos/include/reactos/win32k/ntuser.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/win32k/ntus... ============================================================================== --- trunk/reactos/include/reactos/win32k/ntuser.h [iso-8859-1] (original) +++ trunk/reactos/include/reactos/win32k/ntuser.h [iso-8859-1] Fri Jul 24 03:03:11 2009 @@ -116,8 +116,8 @@ struct _DESKTOP *rpdeskParent; PVOID pdce; DWORD CSF_flags; - PSTR lpszClientAnsiMenuName; - PWSTR lpszClientUnicodeMenuName; + PSTR lpszClientAnsiMenuName; // For client use + PWSTR lpszClientUnicodeMenuName; // " " " PCALLPROC spcpdFirst; struct _CLS *pclsBase; struct _CLS *pclsClone; @@ -135,11 +135,11 @@ HANDLE hIcon; /* FIXME - Use pointer! */ HANDLE hCursor; /* FIXME - Use pointer! */ HBRUSH hbrBackground; - PWSTR MenuName; - PSTR AnsiMenuName; + PWSTR lpszMenuName; // kernel use + PSTR lpszAnsiClassName; // " HANDLE hIconSm; /* FIXME - Use pointer! */
- UINT Destroying : 1; + UINT Destroying : 1; // CSF_WOWDEFERDESTROY UINT Unicode : 1; UINT System : 1; // CSF_SYSTEMCLASS UINT Global : 1; // CS_GLOBALCLASS @@ -1962,11 +1962,11 @@ HWND hWnd, WINDOWPLACEMENT *lpwndpl);
-DWORD +PCLS NTAPI NtUserGetWOWClass( - DWORD Unknown0, - DWORD Unknown1); + HINSTANCE hInstance, + PUNICODE_STRING ClassName);
DWORD NTAPI
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/class.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/class.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/class.c [iso-8859-1] Fri Jul 24 03:03:11 2009 @@ -63,11 +63,11 @@ IntFreeClassMenuName(IN OUT PCLS Class) { /* free the menu name, if it was changed and allocated */ - if (Class->MenuName != NULL && Class->MenuNameIsString) - { - UserHeapFree(Class->MenuName); - Class->MenuName = NULL; - Class->AnsiMenuName = NULL; + if (Class->lpszClientUnicodeMenuName != NULL && Class->MenuNameIsString) + { + UserHeapFree(Class->lpszClientUnicodeMenuName); + Class->lpszClientUnicodeMenuName = NULL; + Class->lpszClientAnsiMenuName = NULL; } }
@@ -891,30 +891,31 @@ Class->hCursor = lpwcx->hCursor; /* FIXME */ Class->hbrBackground = lpwcx->hbrBackground;
+ /* make a copy of the string */ if (pszMenuNameBuffer != NULL) { Class->MenuNameIsString = TRUE;
- Class->MenuName = pszMenuNameBuffer; - RtlCopyMemory(Class->MenuName, + Class->lpszClientUnicodeMenuName = pszMenuNameBuffer; + RtlCopyMemory(Class->lpszClientUnicodeMenuName, MenuName->Buffer, MenuName->Length); - Class->MenuName[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL; + Class->lpszClientUnicodeMenuName[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
pszMenuNameBuffer += (MenuName->Length / sizeof(WCHAR)) + 1; } else - Class->MenuName = MenuName->Buffer; + Class->lpszClientUnicodeMenuName = MenuName->Buffer;
/* save an ansi copy of the string */ if (pszMenuNameBuffer != NULL) { ANSI_STRING AnsiString;
- Class->AnsiMenuName = (PSTR)pszMenuNameBuffer; + Class->lpszClientAnsiMenuName = (PSTR)pszMenuNameBuffer; AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(MenuName); - AnsiString.Buffer = Class->AnsiMenuName; + AnsiString.Buffer = Class->lpszClientAnsiMenuName; Status = RtlUnicodeStringToAnsiString(&AnsiString, MenuName, FALSE); @@ -927,7 +928,11 @@ } } else - Class->AnsiMenuName = (PSTR)MenuName->Buffer; + Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer; + + /* Save kernel use menu name and ansi class name */ + Class->lpszMenuName = Class->lpszClientUnicodeMenuName; // Fixme! + //Class->lpszAnsiClassName = Fixme!
if (!(dwFlags & CSF_ANSIPROC)) Class->Unicode = TRUE; @@ -1467,9 +1472,9 @@ case GCLP_MENUNAME: /* NOTE: Returns pointer in kernel heap! */ if (Ansi) - Ret = (ULONG_PTR)Class->AnsiMenuName; + Ret = (ULONG_PTR)Class->lpszClientAnsiMenuName; else - Ret = (ULONG_PTR)Class->MenuName; + Ret = (ULONG_PTR)Class->lpszClientUnicodeMenuName; break;
case GCL_STYLE: @@ -1547,16 +1552,16 @@ { /* update the base class */ IntFreeClassMenuName(Class); - Class->MenuName = strBufW; - Class->AnsiMenuName = AnsiString.Buffer; + Class->lpszClientUnicodeMenuName = strBufW; + Class->lpszClientAnsiMenuName = AnsiString.Buffer; Class->MenuNameIsString = TRUE;
/* update the clones */ Class = Class->pclsClone; while (Class != NULL) { - Class->MenuName = strBufW; - Class->AnsiMenuName = AnsiString.Buffer; + Class->lpszClientUnicodeMenuName = strBufW; + Class->lpszClientAnsiMenuName = AnsiString.Buffer; Class->MenuNameIsString = TRUE;
Class = Class->pclsNext; @@ -1577,16 +1582,16 @@
/* update the base class */ IntFreeClassMenuName(Class); - Class->MenuName = MenuName->Buffer; - Class->AnsiMenuName = (PSTR)MenuName->Buffer; + Class->lpszClientUnicodeMenuName = MenuName->Buffer; + Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer; Class->MenuNameIsString = FALSE;
/* update the clones */ Class = Class->pclsClone; while (Class != NULL) { - Class->MenuName = MenuName->Buffer; - Class->AnsiMenuName = (PSTR)MenuName->Buffer; + Class->lpszClientUnicodeMenuName = MenuName->Buffer; + Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer; Class->MenuNameIsString = FALSE;
Class = Class->pclsNext; @@ -1810,18 +1815,31 @@ 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. + */ if (Ansi) - ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->AnsiMenuName; + ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->lpszClientAnsiMenuName; else - lpwcx->lpszMenuName = Class->MenuName; + lpwcx->lpszMenuName = Class->lpszClientUnicodeMenuName; + + if ( Class->lpszClientUnicodeMenuName != NULL && + Class->MenuNameIsString) + { + lpwcx->lpszMenuName = UserHeapAddressToUser(Ansi ? + (PVOID)Class->lpszClientAnsiMenuName : + (PVOID)Class->lpszClientUnicodeMenuName); + }
if (hInstance == hModClient) lpwcx->hInstance = NULL; else lpwcx->hInstance = hInstance;
- lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->atomClassName); /* FIXME - return the string? */ + /* FIXME - return the string? Okay! This is performed in User32!*/ + //lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->atomClassName);
lpwcx->hIconSm = Class->hIconSm; /* FIXME - get handle from pointer */
@@ -2010,7 +2028,6 @@ &CapturedMenuName, wpExtra, Flags); - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -2146,6 +2163,9 @@ INT nIndex, WORD wNewWord) { +/* + * NOTE: Obsoleted in 32-bit windows + */ return(0); }
@@ -2195,7 +2215,6 @@ _SEH2_END;
UserLeave(); - return Ret; }
@@ -2208,107 +2227,134 @@ LPWSTR *ppszMenuName, BOOL Ansi) { - UNICODE_STRING CapturedClassName; - PCLS Class; - RTL_ATOM ClassAtom; - PPROCESSINFO pi; - BOOL Ret = FALSE; - - /* NOTE: need exclusive lock because getting the wndproc might require the - creation of a call procedure handle */ - UserEnterExclusive(); - - pi = GetW32ProcessInfo(); - if (pi == NULL) - { - ERR("GetW32ProcessInfo() returned NULL!\n"); - goto Cleanup; - } - _SEH2_TRY - { - /* probe the paramters */ - CapturedClassName = ProbeForReadUnicodeString(ClassName); - - if (CapturedClassName.Length == 0) - TRACE("hInst %p atom %04X lpWndClassEx %p Ansi %d\n", hInstance, CapturedClassName.Buffer, lpWndClassEx, Ansi); - else - TRACE("hInst %p class %wZ lpWndClassEx %p Ansi %d\n", hInstance, &CapturedClassName, lpWndClassEx, Ansi); - - if (CapturedClassName.Length & 1) - { + UNICODE_STRING CapturedClassName, SafeClassName; + WNDCLASSEXW Safewcexw; + PCLS Class; + RTL_ATOM ClassAtom = 0; + PPROCESSINFO pi; + 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) + { + ERR("GetW32ProcessInfo() returned NULL!\n"); + goto Cleanup; + } + + _SEH2_TRY + { + /* probe the paramters */ + CapturedClassName = ProbeForReadUnicodeString(ClassName); + + if (CapturedClassName.Length == 0) + TRACE("hInst %p atom %04X lpWndClassEx %p Ansi %d\n", hInstance, CapturedClassName.Buffer, lpWndClassEx, Ansi); + else + TRACE("hInst %p class %wZ lpWndClassEx %p Ansi %d\n", hInstance, &CapturedClassName, lpWndClassEx, Ansi); + + if (CapturedClassName.Length & 1) + { + goto InvalidParameter; + } + + if (CapturedClassName.Length != 0) + { + ProbeForRead( CapturedClassName.Buffer, + CapturedClassName.Length, + sizeof(WCHAR)); + + RtlInitUnicodeString( &SafeClassName, CapturedClassName.Buffer); + + SafeClassName.Buffer = ExAllocatePoolWithTag( PagedPool, + SafeClassName.MaximumLength, + TAG_STRING); + RtlCopyMemory( SafeClassName.Buffer, + CapturedClassName.Buffer, + SafeClassName.MaximumLength); + } + else + { + if (!IS_ATOM(CapturedClassName.Buffer)) + { + ERR("NtUserGetClassInfo() got ClassName instead of Atom!\n"); goto InvalidParameter; - } - - if (CapturedClassName.Length != 0) - { - ProbeForRead(CapturedClassName.Buffer, - CapturedClassName.Length, - sizeof(WCHAR)); - } - else - { - if (!IS_ATOM(CapturedClassName.Buffer)) - { - ERR("NtUserGetClassInfo() got ClassName instead of Atom!\n"); - goto InvalidParameter; - } - } - - if (ProbeForReadUint(&lpWndClassEx->cbSize) != sizeof(WNDCLASSEXW)) - { + } + + SafeClassName.Buffer = CapturedClassName.Buffer; + SafeClassName.Length = 0; + SafeClassName.MaximumLength = 0; + } + + if (ProbeForReadUint(&lpWndClassEx->cbSize) != sizeof(WNDCLASSEXW)) + { InvalidParameter: - SetLastWin32Error(ERROR_INVALID_PARAMETER); - _SEH2_LEAVE; - } - - ProbeForWrite(lpWndClassEx, - sizeof(WNDCLASSEXW), - sizeof(ULONG)); - - ClassAtom = IntGetClassAtom(&CapturedClassName, + SetLastWin32Error(ERROR_INVALID_PARAMETER); + Ret = FALSE; + _SEH2_LEAVE; + } + + ProbeForWrite( lpWndClassEx, sizeof(WNDCLASSEXW), sizeof(ULONG)); + + RtlCopyMemory( &Safewcexw, lpWndClassEx, sizeof(WNDCLASSEXW)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); + Ret = FALSE; + } + _SEH2_END; + + if (Ret) + { + ClassAtom = IntGetClassAtom( &SafeClassName, hInstance, pi, - &Class, + &Class, NULL); - if (ClassAtom != (RTL_ATOM)0) - { - if (hInstance == NULL) - hInstance = hModClient; - - Ret = UserGetClassInfo(Class, - lpWndClassEx, - Ansi, - hInstance); - - if (Ret) - { - lpWndClassEx->lpszClassName = CapturedClassName.Buffer; - /* FIXME - handle Class->Desktop == NULL!!!!! */ - - if (Class->MenuName != NULL && Class->MenuNameIsString) - { - lpWndClassEx->lpszMenuName = UserHeapAddressToUser(Ansi ? - (PVOID)Class->AnsiMenuName : - (PVOID)Class->MenuName); - } - // From Wine: - /* We must return the atom of the class here instead of just TRUE. */ - /* Undocumented behavior! Return the class atom as a BOOL! */ - Ret = (BOOL)ClassAtom; - } - } - else - SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { + if (ClassAtom != (RTL_ATOM)0) + { + if (hInstance == NULL) hInstance = hModClient; + + Ret = UserGetClassInfo( Class, + &Safewcexw, + Ansi, + hInstance); + } + else + { SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); - } - _SEH2_END; + Ret = FALSE; + } + } + _SEH2_TRY + { + if (Ret) + { + /* Emulate Function. */ + if (ppszMenuName) *ppszMenuName = (LPWSTR)Safewcexw.lpszMenuName; + + RtlCopyMemory(lpWndClassEx, &Safewcexw, sizeof(WNDCLASSEXW)); + + // From Wine: + /* We must return the atom of the class here instead of just TRUE. */ + /* Undocumented behavior! Return the class atom as a BOOL! */ + Ret = (BOOL)ClassAtom; + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); + Ret = FALSE; + } + _SEH2_END;
Cleanup: - UserLeave(); - return Ret; + if (SafeClassName.Length) ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING); + UserLeave(); + return Ret; }
@@ -2355,11 +2401,85 @@ return Ret; }
-DWORD APIENTRY -NtUserGetWOWClass(DWORD Unknown0, - DWORD Unknown1) -{ - return(0); +/* Return Pointer to Class structure. */ +PCLS APIENTRY +NtUserGetWOWClass(HINSTANCE hInstance, + PUNICODE_STRING ClassName) +{ + UNICODE_STRING SafeClassName; + PPROCESSINFO pi; + PCLS Class = NULL; + RTL_ATOM ClassAtom = 0; + BOOL Hit = FALSE; + + UserEnterExclusive(); + + pi = GetW32ProcessInfo(); + if (pi == NULL) + { + ERR("GetW32ProcessInfo() returned NULL!\n"); + goto Cleanup; + } + + _SEH2_TRY + { + if (ClassName->Length != 0) + { + ProbeForRead( ClassName->Buffer, + ClassName->Length, + sizeof(WCHAR)); + + RtlInitUnicodeString( &SafeClassName, ClassName->Buffer); + + SafeClassName.Buffer = ExAllocatePoolWithTag( PagedPool, + SafeClassName.MaximumLength, + TAG_STRING); + RtlCopyMemory( SafeClassName.Buffer, + ClassName->Buffer, + SafeClassName.MaximumLength); + } + else + { + if (!IS_ATOM(ClassName->Buffer)) + { + ERR("NtUserGetWOWClass() got ClassName instead of Atom!\n"); + Hit = TRUE; + } + else + { + SafeClassName.Buffer = ClassName->Buffer; + SafeClassName.Length = 0; + SafeClassName.MaximumLength = 0; + } + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); + Hit = TRUE; + } + _SEH2_END; + + if (!Hit) + { + ClassAtom = IntGetClassAtom( &SafeClassName, + hInstance, + pi, + &Class, + NULL); + if (!ClassAtom) + { + SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); + } + } + +Cleanup: + if (SafeClassName.Length) ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING); + UserLeave(); +// +// Don't forget to use DesktopPtrToUser( ? ) with return pointer in user space. +// + return Class; }
/* EOF */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] Fri Jul 24 03:03:11 2009 @@ -1838,7 +1838,7 @@ { UNICODE_STRING MenuName;
- RtlInitUnicodeString( &MenuName, Wnd->pcls->MenuName); + RtlInitUnicodeString( &MenuName, Wnd->pcls->lpszMenuName);
hMenu = co_IntCallLoadMenu( Wnd->pcls->hModule, &MenuName); if (hMenu) IntSetMenu(Window, hMenu, &MenuChanged);