- [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}; UNICODE_STRING ClassName = {0};
BOOL Ret; BOOL Ret;
LPCSTR pszMenuName;
TRACE("%p class/atom: %s/%04x %p\n", hInstance, TRACE("%p class/atom: %s/%04x %p\n", hInstance,
IS_ATOM(lpszClass) ? NULL : lpszClass, IS_ATOM(lpszClass) ? NULL : lpszClass,
@ -62,8 +63,13 @@ GetClassInfoExA(
Ret = NtUserGetClassInfo(hInstance, Ret = NtUserGetClassInfo(hInstance,
&ClassName, &ClassName,
(LPWNDCLASSEXW)lpwcx, (LPWNDCLASSEXW)lpwcx,
NULL, (LPWSTR *)&pszMenuName,
TRUE); TRUE);
if (Ret)
{
lpwcx->lpszClassName = lpszClass;
// lpwcx->lpszMenuName = pszMenuName;
}
if (!IS_ATOM(lpszClass)) if (!IS_ATOM(lpszClass))
{ {
@ -85,6 +91,8 @@ GetClassInfoExW(
LPWNDCLASSEXW lpwcx) LPWNDCLASSEXW lpwcx)
{ {
UNICODE_STRING ClassName = {0}; UNICODE_STRING ClassName = {0};
BOOL Ret;
LPWSTR pszMenuName;
TRACE("%p class/atom: %S/%04x %p\n", hInstance, TRACE("%p class/atom: %S/%04x %p\n", hInstance,
IS_ATOM(lpszClass) ? NULL : lpszClass, IS_ATOM(lpszClass) ? NULL : lpszClass,
@ -115,11 +123,17 @@ GetClassInfoExW(
lpszClass); lpszClass);
} }
return NtUserGetClassInfo(hInstance, Ret = NtUserGetClassInfo( hInstance,
&ClassName, &ClassName,
lpwcx, lpwcx,
NULL, &pszMenuName,
FALSE); FALSE);
if (Ret)
{
lpwcx->lpszClassName = lpszClass;
// lpwcx->lpszMenuName = pszMenuName;
}
return Ret;
} }
@ -238,7 +252,7 @@ GetClassLongA(HWND hWnd, int nIndex)
break; break;
case GCL_MENUNAME: case GCL_MENUNAME:
Ret = (ULONG_PTR)Class->AnsiMenuName; Ret = (ULONG_PTR)Class->lpszClientAnsiMenuName;
break; break;
case GCL_STYLE: case GCL_STYLE:
@ -351,7 +365,7 @@ GetClassLongW ( HWND hWnd, int nIndex )
break; break;
case GCL_MENUNAME: case GCL_MENUNAME:
Ret = (ULONG_PTR)Class->MenuName; Ret = (ULONG_PTR)Class->lpszClientUnicodeMenuName;
break; break;
case GCL_STYLE: case GCL_STYLE:

View file

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

View file

@ -116,8 +116,8 @@ typedef struct _CLS
struct _DESKTOP *rpdeskParent; struct _DESKTOP *rpdeskParent;
PVOID pdce; PVOID pdce;
DWORD CSF_flags; DWORD CSF_flags;
PSTR lpszClientAnsiMenuName; PSTR lpszClientAnsiMenuName; // For client use
PWSTR lpszClientUnicodeMenuName; PWSTR lpszClientUnicodeMenuName; // " " "
PCALLPROC spcpdFirst; PCALLPROC spcpdFirst;
struct _CLS *pclsBase; struct _CLS *pclsBase;
struct _CLS *pclsClone; struct _CLS *pclsClone;
@ -135,11 +135,11 @@ typedef struct _CLS
HANDLE hIcon; /* FIXME - Use pointer! */ HANDLE hIcon; /* FIXME - Use pointer! */
HANDLE hCursor; /* FIXME - Use pointer! */ HANDLE hCursor; /* FIXME - Use pointer! */
HBRUSH hbrBackground; HBRUSH hbrBackground;
PWSTR MenuName; PWSTR lpszMenuName; // kernel use
PSTR AnsiMenuName; PSTR lpszAnsiClassName; // "
HANDLE hIconSm; /* FIXME - Use pointer! */ HANDLE hIconSm; /* FIXME - Use pointer! */
UINT Destroying : 1; UINT Destroying : 1; // CSF_WOWDEFERDESTROY
UINT Unicode : 1; UINT Unicode : 1;
UINT System : 1; // CSF_SYSTEMCLASS UINT System : 1; // CSF_SYSTEMCLASS
UINT Global : 1; // CS_GLOBALCLASS UINT Global : 1; // CS_GLOBALCLASS
@ -1962,11 +1962,11 @@ NtUserGetWindowPlacement(
HWND hWnd, HWND hWnd,
WINDOWPLACEMENT *lpwndpl); WINDOWPLACEMENT *lpwndpl);
DWORD PCLS
NTAPI NTAPI
NtUserGetWOWClass( NtUserGetWOWClass(
DWORD Unknown0, HINSTANCE hInstance,
DWORD Unknown1); PUNICODE_STRING ClassName);
DWORD DWORD
NTAPI NTAPI

View file

@ -63,11 +63,11 @@ static VOID
IntFreeClassMenuName(IN OUT PCLS Class) IntFreeClassMenuName(IN OUT PCLS Class)
{ {
/* free the menu name, if it was changed and allocated */ /* 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); UserHeapFree(Class->lpszClientUnicodeMenuName);
Class->MenuName = NULL; Class->lpszClientUnicodeMenuName = NULL;
Class->AnsiMenuName = NULL; Class->lpszClientAnsiMenuName = NULL;
} }
} }
@ -891,30 +891,31 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
Class->hCursor = lpwcx->hCursor; /* FIXME */ Class->hCursor = lpwcx->hCursor; /* FIXME */
Class->hbrBackground = lpwcx->hbrBackground; Class->hbrBackground = lpwcx->hbrBackground;
/* make a copy of the string */ /* make a copy of the string */
if (pszMenuNameBuffer != NULL) if (pszMenuNameBuffer != NULL)
{ {
Class->MenuNameIsString = TRUE; Class->MenuNameIsString = TRUE;
Class->MenuName = pszMenuNameBuffer; Class->lpszClientUnicodeMenuName = pszMenuNameBuffer;
RtlCopyMemory(Class->MenuName, RtlCopyMemory(Class->lpszClientUnicodeMenuName,
MenuName->Buffer, MenuName->Buffer,
MenuName->Length); MenuName->Length);
Class->MenuName[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL; Class->lpszClientUnicodeMenuName[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
pszMenuNameBuffer += (MenuName->Length / sizeof(WCHAR)) + 1; pszMenuNameBuffer += (MenuName->Length / sizeof(WCHAR)) + 1;
} }
else else
Class->MenuName = MenuName->Buffer; Class->lpszClientUnicodeMenuName = MenuName->Buffer;
/* save an ansi copy of the string */ /* save an ansi copy of the string */
if (pszMenuNameBuffer != NULL) if (pszMenuNameBuffer != NULL)
{ {
ANSI_STRING AnsiString; ANSI_STRING AnsiString;
Class->AnsiMenuName = (PSTR)pszMenuNameBuffer; Class->lpszClientAnsiMenuName = (PSTR)pszMenuNameBuffer;
AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(MenuName); AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(MenuName);
AnsiString.Buffer = Class->AnsiMenuName; AnsiString.Buffer = Class->lpszClientAnsiMenuName;
Status = RtlUnicodeStringToAnsiString(&AnsiString, Status = RtlUnicodeStringToAnsiString(&AnsiString,
MenuName, MenuName,
FALSE); FALSE);
@ -927,7 +928,11 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
} }
} }
else 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)) if (!(dwFlags & CSF_ANSIPROC))
Class->Unicode = TRUE; Class->Unicode = TRUE;
@ -1467,9 +1472,9 @@ UserGetClassLongPtr(IN PCLS Class,
case GCLP_MENUNAME: case GCLP_MENUNAME:
/* NOTE: Returns pointer in kernel heap! */ /* NOTE: Returns pointer in kernel heap! */
if (Ansi) if (Ansi)
Ret = (ULONG_PTR)Class->AnsiMenuName; Ret = (ULONG_PTR)Class->lpszClientAnsiMenuName;
else else
Ret = (ULONG_PTR)Class->MenuName; Ret = (ULONG_PTR)Class->lpszClientUnicodeMenuName;
break; break;
case GCL_STYLE: case GCL_STYLE:
@ -1547,16 +1552,16 @@ IntSetClassMenuName(IN PCLS Class,
{ {
/* update the base class */ /* update the base class */
IntFreeClassMenuName(Class); IntFreeClassMenuName(Class);
Class->MenuName = strBufW; Class->lpszClientUnicodeMenuName = strBufW;
Class->AnsiMenuName = AnsiString.Buffer; Class->lpszClientAnsiMenuName = AnsiString.Buffer;
Class->MenuNameIsString = TRUE; Class->MenuNameIsString = TRUE;
/* update the clones */ /* update the clones */
Class = Class->pclsClone; Class = Class->pclsClone;
while (Class != NULL) while (Class != NULL)
{ {
Class->MenuName = strBufW; Class->lpszClientUnicodeMenuName = strBufW;
Class->AnsiMenuName = AnsiString.Buffer; Class->lpszClientAnsiMenuName = AnsiString.Buffer;
Class->MenuNameIsString = TRUE; Class->MenuNameIsString = TRUE;
Class = Class->pclsNext; Class = Class->pclsNext;
@ -1577,16 +1582,16 @@ IntSetClassMenuName(IN PCLS Class,
/* update the base class */ /* update the base class */
IntFreeClassMenuName(Class); IntFreeClassMenuName(Class);
Class->MenuName = MenuName->Buffer; Class->lpszClientUnicodeMenuName = MenuName->Buffer;
Class->AnsiMenuName = (PSTR)MenuName->Buffer; Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
Class->MenuNameIsString = FALSE; Class->MenuNameIsString = FALSE;
/* update the clones */ /* update the clones */
Class = Class->pclsClone; Class = Class->pclsClone;
while (Class != NULL) while (Class != NULL)
{ {
Class->MenuName = MenuName->Buffer; Class->lpszClientUnicodeMenuName = MenuName->Buffer;
Class->AnsiMenuName = (PSTR)MenuName->Buffer; Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
Class->MenuNameIsString = FALSE; Class->MenuNameIsString = FALSE;
Class = Class->pclsNext; Class = Class->pclsNext;
@ -1810,18 +1815,31 @@ UserGetClassInfo(IN PCLS Class,
lpwcx->hIcon = Class->hIcon; /* FIXME - get handle from pointer */ lpwcx->hIcon = Class->hIcon; /* FIXME - get handle from pointer */
lpwcx->hCursor = Class->hCursor; /* FIXME - get handle from pointer */ lpwcx->hCursor = Class->hCursor; /* FIXME - get handle from pointer */
lpwcx->hbrBackground = Class->hbrBackground; 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) if (Ansi)
((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->AnsiMenuName; ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->lpszClientAnsiMenuName;
else 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) if (hInstance == hModClient)
lpwcx->hInstance = NULL; lpwcx->hInstance = NULL;
else else
lpwcx->hInstance = hInstance; 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 */ lpwcx->hIconSm = Class->hIconSm; /* FIXME - get handle from pointer */
@ -2010,7 +2028,6 @@ InvalidParameter:
&CapturedMenuName, &CapturedMenuName,
wpExtra, wpExtra,
Flags); Flags);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -2146,6 +2163,9 @@ NtUserSetClassWord(
INT nIndex, INT nIndex,
WORD wNewWord) WORD wNewWord)
{ {
/*
* NOTE: Obsoleted in 32-bit windows
*/
return(0); return(0);
} }
@ -2195,7 +2215,6 @@ InvalidParameter:
_SEH2_END; _SEH2_END;
UserLeave(); UserLeave();
return Ret; return Ret;
} }
@ -2208,107 +2227,134 @@ NtUserGetClassInfo(
LPWSTR *ppszMenuName, LPWSTR *ppszMenuName,
BOOL Ansi) BOOL Ansi)
{ {
UNICODE_STRING CapturedClassName; UNICODE_STRING CapturedClassName, SafeClassName;
PCLS Class; WNDCLASSEXW Safewcexw;
RTL_ATOM ClassAtom; PCLS Class;
PPROCESSINFO pi; RTL_ATOM ClassAtom = 0;
BOOL Ret = FALSE; PPROCESSINFO pi;
BOOL Ret = TRUE;
/* NOTE: need exclusive lock because getting the wndproc might require the /* NOTE: need exclusive lock because getting the wndproc might require the
creation of a call procedure handle */ creation of a call procedure handle */
UserEnterExclusive(); UserEnterExclusive();
pi = GetW32ProcessInfo(); pi = GetW32ProcessInfo();
if (pi == NULL) if (pi == NULL)
{ {
ERR("GetW32ProcessInfo() returned NULL!\n"); ERR("GetW32ProcessInfo() returned NULL!\n");
goto Cleanup; goto Cleanup;
} }
_SEH2_TRY
{
/* probe the paramters */
CapturedClassName = ProbeForReadUnicodeString(ClassName);
if (CapturedClassName.Length == 0) _SEH2_TRY
TRACE("hInst %p atom %04X lpWndClassEx %p Ansi %d\n", hInstance, CapturedClassName.Buffer, lpWndClassEx, Ansi); {
else /* probe the paramters */
TRACE("hInst %p class %wZ lpWndClassEx %p Ansi %d\n", hInstance, &CapturedClassName, lpWndClassEx, Ansi); 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; goto InvalidParameter;
} }
if (CapturedClassName.Length != 0) SafeClassName.Buffer = CapturedClassName.Buffer;
{ SafeClassName.Length = 0;
ProbeForRead(CapturedClassName.Buffer, SafeClassName.MaximumLength = 0;
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)) if (ProbeForReadUint(&lpWndClassEx->cbSize) != sizeof(WNDCLASSEXW))
{ {
InvalidParameter: InvalidParameter:
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
_SEH2_LEAVE; Ret = FALSE;
} _SEH2_LEAVE;
}
ProbeForWrite(lpWndClassEx, ProbeForWrite( lpWndClassEx, sizeof(WNDCLASSEXW), sizeof(ULONG));
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, hInstance,
pi, pi,
&Class, &Class,
NULL); NULL);
if (ClassAtom != (RTL_ATOM)0) if (ClassAtom != (RTL_ATOM)0)
{ {
if (hInstance == NULL) if (hInstance == NULL) hInstance = hModClient;
hInstance = hModClient;
Ret = UserGetClassInfo(Class, Ret = UserGetClassInfo( Class,
lpWndClassEx, &Safewcexw,
Ansi, Ansi,
hInstance); hInstance);
}
if (Ret) else
{ {
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)
{
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
} Ret = FALSE;
_SEH2_END; }
}
_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: Cleanup:
UserLeave(); if (SafeClassName.Length) ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
return Ret; UserLeave();
return Ret;
} }
@ -2355,11 +2401,85 @@ NtUserGetClassName (IN HWND hWnd,
return Ret; return Ret;
} }
DWORD APIENTRY /* Return Pointer to Class structure. */
NtUserGetWOWClass(DWORD Unknown0, PCLS APIENTRY
DWORD Unknown1) 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 */ /* EOF */

View file

@ -1838,7 +1838,7 @@ AllocErr:
{ {
UNICODE_STRING MenuName; UNICODE_STRING MenuName;
RtlInitUnicodeString( &MenuName, Wnd->pcls->MenuName); RtlInitUnicodeString( &MenuName, Wnd->pcls->lpszMenuName);
hMenu = co_IntCallLoadMenu( Wnd->pcls->hModule, &MenuName); hMenu = co_IntCallLoadMenu( Wnd->pcls->hModule, &MenuName);
if (hMenu) IntSetMenu(Window, hMenu, &MenuChanged); if (hMenu) IntSetMenu(Window, hMenu, &MenuChanged);