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/c…
==============================================================================
--- 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/d…
==============================================================================
--- 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/ntu…
==============================================================================
--- 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/nt…
==============================================================================
--- 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/nt…
==============================================================================
--- 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);