- [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.

svn path=/trunk/; revision=42168
This commit is contained in:
James Tabor 2009-07-24 01:03:11 +00:00
parent 1a67e2e700
commit 9fd89d0e43
5 changed files with 264 additions and 130 deletions

View file

@ -25,6 +25,7 @@ GetClassInfoExA(
{
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 @@ GetClassInfoExA(
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 @@ GetClassInfoExW(
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 @@ GetClassInfoExW(
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 @@ GetClassLongA(HWND hWnd, int nIndex)
break;
case GCL_MENUNAME:
Ret = (ULONG_PTR)Class->AnsiMenuName;
Ret = (ULONG_PTR)Class->lpszClientAnsiMenuName;
break;
case GCL_STYLE:
@ -351,7 +365,7 @@ GetClassLongW ( HWND hWnd, int nIndex )
break;
case GCL_MENUNAME:
Ret = (ULONG_PTR)Class->MenuName;
Ret = (ULONG_PTR)Class->lpszClientUnicodeMenuName;
break;
case GCL_STYLE:

View file

@ -970,7 +970,7 @@ static void DefWndPrint( HWND hwnd, HDC hdc, ULONG uFlags)
* Client area
*/
if ( uFlags & PRF_CLIENT)
SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, uFlags);
}
static BOOL CALLBACK

View file

@ -116,8 +116,8 @@ typedef struct _CLS
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 @@ typedef struct _CLS
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 @@ NtUserGetWindowPlacement(
HWND hWnd,
WINDOWPLACEMENT *lpwndpl);
DWORD
PCLS
NTAPI
NtUserGetWOWClass(
DWORD Unknown0,
DWORD Unknown1);
HINSTANCE hInstance,
PUNICODE_STRING ClassName);
DWORD
NTAPI

View file

@ -63,11 +63,11 @@ static VOID
IntFreeClassMenuName(IN OUT PCLS Class)
{
/* free the menu name, if it was changed and allocated */
if (Class->MenuName != NULL && Class->MenuNameIsString)
if (Class->lpszClientUnicodeMenuName != NULL && Class->MenuNameIsString)
{
UserHeapFree(Class->MenuName);
Class->MenuName = NULL;
Class->AnsiMenuName = NULL;
UserHeapFree(Class->lpszClientUnicodeMenuName);
Class->lpszClientUnicodeMenuName = NULL;
Class->lpszClientAnsiMenuName = NULL;
}
}
@ -891,30 +891,31 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
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 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
}
}
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 @@ UserGetClassLongPtr(IN PCLS Class,
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 @@ IntSetClassMenuName(IN PCLS Class,
{
/* 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 @@ IntSetClassMenuName(IN PCLS Class,
/* 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 @@ UserGetClassInfo(IN PCLS Class,
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 @@ InvalidParameter:
&CapturedMenuName,
wpExtra,
Flags);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@ -2146,6 +2163,9 @@ NtUserSetClassWord(
INT nIndex,
WORD wNewWord)
{
/*
* NOTE: Obsoleted in 32-bit windows
*/
return(0);
}
@ -2195,7 +2215,6 @@ InvalidParameter:
_SEH2_END;
UserLeave();
return Ret;
}
@ -2208,107 +2227,134 @@ NtUserGetClassInfo(
LPWSTR *ppszMenuName,
BOOL Ansi)
{
UNICODE_STRING CapturedClassName;
PCLS Class;
RTL_ATOM ClassAtom;
PPROCESSINFO pi;
BOOL Ret = FALSE;
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();
/* 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);
pi = GetW32ProcessInfo();
if (pi == NULL)
{
ERR("GetW32ProcessInfo() returned NULL!\n");
goto Cleanup;
}
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);
_SEH2_TRY
{
/* probe the paramters */
CapturedClassName = ProbeForReadUnicodeString(ClassName);
if (CapturedClassName.Length & 1)
{
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;
}
}
SafeClassName.Buffer = CapturedClassName.Buffer;
SafeClassName.Length = 0;
SafeClassName.MaximumLength = 0;
}
if (ProbeForReadUint(&lpWndClassEx->cbSize) != sizeof(WNDCLASSEXW))
{
if (ProbeForReadUint(&lpWndClassEx->cbSize) != sizeof(WNDCLASSEXW))
{
InvalidParameter:
SetLastWin32Error(ERROR_INVALID_PARAMETER);
_SEH2_LEAVE;
}
SetLastWin32Error(ERROR_INVALID_PARAMETER);
Ret = FALSE;
_SEH2_LEAVE;
}
ProbeForWrite(lpWndClassEx,
sizeof(WNDCLASSEXW),
sizeof(ULONG));
ProbeForWrite( lpWndClassEx, sizeof(WNDCLASSEXW), sizeof(ULONG));
ClassAtom = IntGetClassAtom(&CapturedClassName,
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;
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)
{
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 @@ NtUserGetClassName (IN HWND hWnd,
return Ret;
}
DWORD APIENTRY
NtUserGetWOWClass(DWORD Unknown0,
DWORD Unknown1)
/* Return Pointer to Class structure. */
PCLS APIENTRY
NtUserGetWOWClass(HINSTANCE hInstance,
PUNICODE_STRING ClassName)
{
return(0);
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 */

View file

@ -1838,7 +1838,7 @@ AllocErr:
{
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);