diff --git a/reactos/include/user32/callback.h b/reactos/include/user32/callback.h index bf778de256e..3e8ec9a7dcb 100644 --- a/reactos/include/user32/callback.h +++ b/reactos/include/user32/callback.h @@ -11,7 +11,8 @@ #define USER32_CALLBACK_SENDWINDOWPOSCHANGED (7) #define USER32_CALLBACK_SENDSTYLECHANGING (8) #define USER32_CALLBACK_SENDSTYLECHANGED (9) -#define USER32_CALLBACK_MAXIMUM (9) +#define USER32_CALLBACK_LOADSYSMENUTEMPLATE (10) +#define USER32_CALLBACK_MAXIMUM (10) typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS { @@ -119,5 +120,7 @@ NTSTATUS STDCALL User32SendSTYLECHANGINGMessageForKernel(PVOID Arguments, ULONG ArgumentLength); NTSTATUS STDCALL User32SendSTYLECHANGEDMessageForKernel(PVOID Arguments, ULONG ArgumentLength); +NTSTATUS STDCALL +User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength); #endif /* __INCLUDE_USER32_CALLBACK_H */ diff --git a/reactos/include/win32k/ntuser.h b/reactos/include/win32k/ntuser.h index aee61679afa..20aae784974 100644 --- a/reactos/include/win32k/ntuser.h +++ b/reactos/include/win32k/ntuser.h @@ -177,7 +177,6 @@ NtUserCallOneParam( #define TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW 0x56 #define TWOPARAM_ROUTINE_VALIDATERGN 0x57 #define TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID 0x58 -#define TWOPARAM_ROUTINE_SETWINSTASYSMENU 0x59 DWORD STDCALL NtUserCallTwoParam( diff --git a/reactos/lib/user32/misc/dllmain.c b/reactos/lib/user32/misc/dllmain.c index 1338029fcb9..653d26b4cca 100644 --- a/reactos/lib/user32/misc/dllmain.c +++ b/reactos/lib/user32/misc/dllmain.c @@ -111,6 +111,8 @@ Init(VOID) (PVOID)User32SendSTYLECHANGINGMessageForKernel; NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_SENDSTYLECHANGED] = (PVOID)User32SendSTYLECHANGEDMessageForKernel; + NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_LOADSYSMENUTEMPLATE] = + (PVOID)User32LoadSysMenuTemplateForKernel; /* Allocate an index for user32 thread local data. */ User32TlsIndex = TlsAlloc(); diff --git a/reactos/lib/user32/misc/winsta.c b/reactos/lib/user32/misc/winsta.c index 4db1d3a3e10..fdef2c49bd1 100644 --- a/reactos/lib/user32/misc/winsta.c +++ b/reactos/lib/user32/misc/winsta.c @@ -1,4 +1,4 @@ -/* $Id: winsta.c,v 1.10 2003/08/21 16:04:26 weiden Exp $ +/* $Id: winsta.c,v 1.11 2003/08/21 20:29:43 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -67,29 +67,13 @@ CreateWindowStationW(LPWSTR lpwinsta, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa) { - HWINSTA res; UNICODE_STRING WindowStationName; - HMENU SysMenuTemplate; - HMODULE hUser32; RtlInitUnicodeString(&WindowStationName, lpwinsta); - res = NtUserCreateWindowStation(&WindowStationName, + return NtUserCreateWindowStation(&WindowStationName, dwDesiredAccess, lpsa, 0, 0, 0); - - hUser32 = GetModuleHandleW(L"user32.dll"); - SysMenuTemplate = LoadMenuW(hUser32, L"SYSMENU"); - - if(SysMenuTemplate) - { - NtUserCallTwoParam((DWORD)res, (DWORD)SysMenuTemplate, - TWOPARAM_ROUTINE_SETWINSTASYSMENU); - /* we don't need the menu anymore, it's been cloned */ - DestroyMenu(SysMenuTemplate); - } - - return res; } diff --git a/reactos/lib/user32/windows/menu.c b/reactos/lib/user32/windows/menu.c index eae294fa0b3..282d7e950b7 100644 --- a/reactos/lib/user32/windows/menu.c +++ b/reactos/lib/user32/windows/menu.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: menu.c,v 1.26 2003/08/20 10:08:53 weiden Exp $ +/* $Id: menu.c,v 1.27 2003/08/21 20:29:43 weiden Exp $ * * PROJECT: ReactOS user32.dll * FILE: lib/user32/windows/menu.c @@ -36,6 +36,7 @@ #include #include +#include #include "user32/regcontrol.h" #include "../controls/controls.h" @@ -241,6 +242,17 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode ) } +NTSTATUS STDCALL +User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength) +{ + LRESULT Result; + HMODULE hUser32; + hUser32 = GetModuleHandleW(L"user32.dll"); + Result = (LRESULT)LoadMenuW(hUser32, L"SYSMENU"); + return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); +} + + BOOL MenuInit(VOID) { @@ -811,7 +823,6 @@ InsertMenuItemW( (MENU_ITEM_TYPE(mi.fType) == MF_STRING) && mi.dwTypeData) { len = lstrlenW(lpmii->dwTypeData); - mi.dwTypeData = RtlAllocateHeap(hHeap, 0, (len + 1) * sizeof(WCHAR)); if(!mi.dwTypeData) { diff --git a/reactos/subsys/win32k/include/callback.h b/reactos/subsys/win32k/include/callback.h index b562072738e..5e82752b41e 100644 --- a/reactos/subsys/win32k/include/callback.h +++ b/reactos/subsys/win32k/include/callback.h @@ -41,4 +41,7 @@ IntSendSTYLECHANGINGMessage(HWND Wnd, DWORD WhichStyle, STYLESTRUCT* Style); LRESULT STDCALL IntSendSTYLECHANGEDMessage(HWND Wnd, DWORD WhichStyle, STYLESTRUCT* Style); +HMENU STDCALL +IntLoadSysMenuTemplate(); + #endif /* __SUBSYS_WIN32K_INCLUDE_CALLBACK_H */ diff --git a/reactos/subsys/win32k/include/menu.h b/reactos/subsys/win32k/include/menu.h index 250bf8a6c6b..aed364eb274 100644 --- a/reactos/subsys/win32k/include/menu.h +++ b/reactos/subsys/win32k/include/menu.h @@ -62,7 +62,7 @@ BOOL FASTCALL IntDestroyMenuObject(PMENU_OBJECT MenuObject, BOOL bRecurse, BOOL RemoveFromProcess); PMENU_OBJECT FASTCALL -IntCreateMenu(PHANDLE Handle, BOOL AsSysMenuTemplate); +IntCreateMenu(PHANDLE Handle); PMENU_OBJECT FASTCALL IntCloneMenu(PMENU_OBJECT Source); diff --git a/reactos/subsys/win32k/ntuser/callback.c b/reactos/subsys/win32k/ntuser/callback.c index 3a4b98bb94b..4f5ccb03085 100644 --- a/reactos/subsys/win32k/ntuser/callback.c +++ b/reactos/subsys/win32k/ntuser/callback.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: callback.c,v 1.12 2003/08/19 11:48:49 weiden Exp $ +/* $Id: callback.c,v 1.13 2003/08/21 20:29:43 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -380,4 +380,26 @@ IntCallTrampolineWindowProc(WNDPROC Proc, } } +HMENU STDCALL +IntLoadSysMenuTemplate() +{ + LRESULT Result; + NTSTATUS Status; + PVOID ResultPointer; + ULONG ResultLength; + + ResultPointer = &Result; + ResultLength = sizeof(LRESULT); + Status = NtW32Call(USER32_CALLBACK_LOADSYSMENUTEMPLATE, + NULL, + 0, + &ResultPointer, + &ResultLength); + if (!NT_SUCCESS(Status)) + { + return(0); + } + return (HMENU)Result; +} + /* EOF */ diff --git a/reactos/subsys/win32k/ntuser/menu.c b/reactos/subsys/win32k/ntuser/menu.c index b807eb4e513..ac071ac5a67 100644 --- a/reactos/subsys/win32k/ntuser/menu.c +++ b/reactos/subsys/win32k/ntuser/menu.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: menu.c,v 1.23 2003/08/21 15:26:19 weiden Exp $ +/* $Id: menu.c,v 1.24 2003/08/21 20:29:43 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -225,8 +225,8 @@ IntDestroyMenuObject(PMENU_OBJECT MenuObject, BOOL bRecurse, BOOL RemoveFromProc if(MenuObject) { - if(RemoveFromProcess) - W32Process = PsGetWin32Process(); + W32Process = PsGetWin32Process(); + /* remove all menu items */ ExAcquireFastMutexUnsafe (&MenuObject->MenuItemsLock); IntDeleteMenuItems(MenuObject, bRecurse); /* do not destroy submenus */ @@ -249,21 +249,14 @@ IntDestroyMenuObject(PMENU_OBJECT MenuObject, BOOL bRecurse, BOOL RemoveFromProc } PMENU_OBJECT FASTCALL -IntCreateMenu(PHANDLE Handle, BOOL AsSysMenuTemplate) +IntCreateMenu(PHANDLE Handle) { PW32PROCESS Win32Process = PsGetWin32Process(); - + PMENU_OBJECT MenuObject = (PMENU_OBJECT)ObmCreateObject( Win32Process->WindowStation->HandleTable, Handle, otMenu, sizeof(MENU_OBJECT)); - - if(AsSysMenuTemplate && !Win32Process->WindowStation->SystemMenuTemplate) - { - Win32Process->WindowStation->SystemMenuTemplate = (HANDLE)*Handle; - } - else - AsSysMenuTemplate = FALSE; - + if(!MenuObject) { *Handle = 0; @@ -283,23 +276,102 @@ IntCreateMenu(PHANDLE Handle, BOOL AsSysMenuTemplate) MenuObject->MenuItemCount = 0; MenuObject->MenuItemList = NULL; ExInitializeFastMutex(&MenuObject->MenuItemsLock); - - if(!AsSysMenuTemplate) - { - /* Insert menu item into process menu handle list */ - ExAcquireFastMutexUnsafe (&Win32Process->MenuListLock); - InsertTailList (&Win32Process->MenuListHead, &MenuObject->ListEntry); - ExReleaseFastMutexUnsafe (&Win32Process->MenuListLock); + + /* Insert menu item into process menu handle list */ + ExAcquireFastMutexUnsafe (&Win32Process->MenuListLock); + InsertTailList (&Win32Process->MenuListHead, &MenuObject->ListEntry); + ExReleaseFastMutexUnsafe (&Win32Process->MenuListLock); + + return MenuObject; +} + +BOOL FASTCALL +IntCloneMenuItems(PMENU_OBJECT Destination, PMENU_OBJECT Source) +{ + PMENU_ITEM MenuItem, NewMenuItem, Old = NULL; + DbgPrint("IntCloneMenuItems(1) = %d\n", Source->MenuItemCount); + if(!Source->MenuItemCount) + return FALSE; +DbgPrint("IntCloneMenuItems(2)\n"); + ExAcquireFastMutexUnsafe(&Destination->MenuItemsLock); + ExAcquireFastMutexUnsafe(&Source->MenuItemsLock); +DbgPrint("IntCloneMenuItems(3)\n"); + MenuItem = Source->MenuItemList; + while(MenuItem) + {DbgPrint("IntCloneMenuItems(%d)\n", Source->MenuItemCount + 1); + Old = NewMenuItem; + NewMenuItem = ExAllocatePool(PagedPool, sizeof(MENU_ITEM)); + if(!NewMenuItem) + { + goto finish; + } + + NewMenuItem->fType = MenuItem->fType; + NewMenuItem->fState = MenuItem->fState; + NewMenuItem->wID = MenuItem->wID; + NewMenuItem->hSubMenu = MenuItem->hSubMenu; + NewMenuItem->hbmpChecked = MenuItem->hbmpChecked; + NewMenuItem->hbmpUnchecked = MenuItem->hbmpUnchecked; + NewMenuItem->dwItemData = MenuItem->dwItemData; + NewMenuItem->dwTypeData = MenuItem->dwTypeData; + if((MENU_ITEM_TYPE(NewMenuItem->fType) == MF_STRING) && + NewMenuItem->dwTypeData) + { + DbgPrint("Copy menu item %ws\n", (LPWSTR)MenuItem->dwTypeData); + NewMenuItem->dwTypeData = (LPWSTR)ExAllocatePool(PagedPool, (MenuItem->cch + 1) * sizeof(WCHAR)); + if(!NewMenuItem->dwTypeData) + { + ExFreePool(NewMenuItem); + goto finish; + } + memcpy(NewMenuItem->dwTypeData, MenuItem->dwTypeData, (MenuItem->cch + 1) * sizeof(WCHAR)); + } + NewMenuItem->cch = MenuItem->cch; + NewMenuItem->hbmpItem = MenuItem->hbmpItem; + + Old->Next = NewMenuItem; + NewMenuItem->Next = NULL; + Source->MenuItemCount++; + MenuItem = MenuItem->Next; } - return MenuObject; +finish: + ExReleaseFastMutexUnsafe(&Source->MenuItemsLock); + ExReleaseFastMutexUnsafe(&Destination->MenuItemsLock); + return TRUE; } PMENU_OBJECT FASTCALL IntCloneMenu(PMENU_OBJECT Source) { - DbgPrint("IntCloneMenu()\n"); - return NULL; + HANDLE Handle; + + if(!Source) + return NULL; + + PMENU_OBJECT MenuObject = (PMENU_OBJECT)ObmCreateObject( + PsGetWin32Process()->WindowStation->HandleTable, Handle, + otMenu, sizeof(MENU_OBJECT)); + if(!MenuObject) + return NULL; + + MenuObject->Self = Handle; + MenuObject->RtoL = Source->RtoL; + MenuObject->MenuInfo.cbSize = sizeof(MENUINFO); /* not used */ + MenuObject->MenuInfo.fMask = Source->MenuInfo.fMask; + MenuObject->MenuInfo.dwStyle = Source->MenuInfo.dwStyle; + MenuObject->MenuInfo.cyMax = Source->MenuInfo.cyMax; + MenuObject->MenuInfo.hbrBack = Source->MenuInfo.hbrBack; + MenuObject->MenuInfo.dwContextHelpID = Source->MenuInfo.dwContextHelpID; + MenuObject->MenuInfo.dwMenuData = Source->MenuInfo.dwMenuData; + + MenuObject->MenuItemCount = 0; + MenuObject->MenuItemList = NULL; + ExInitializeFastMutex(&MenuObject->MenuItemsLock); + + IntCloneMenuItems(MenuObject, Source); + + return MenuObject; } BOOL FASTCALL @@ -981,12 +1053,12 @@ NtUserCreateMenu(VOID) { PWINSTATION_OBJECT WinStaObject; HANDLE Handle; - + NTSTATUS Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(), KernelMode, 0, &WinStaObject); - + if (!NT_SUCCESS(Status)) { DPRINT("Validation of window station handle (0x%X) failed\n", @@ -995,7 +1067,8 @@ NtUserCreateMenu(VOID) return (HMENU)0; } - IntCreateMenu(&Handle, FALSE); + IntCreateMenu(&Handle); + ObDereferenceObject(WinStaObject); return (HMENU)Handle; } diff --git a/reactos/subsys/win32k/ntuser/misc.c b/reactos/subsys/win32k/ntuser/misc.c index 0df53331c55..0272b1b2384 100644 --- a/reactos/subsys/win32k/ntuser/misc.c +++ b/reactos/subsys/win32k/ntuser/misc.c @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.8 2003/08/21 16:04:26 weiden Exp $ +/* $Id: misc.c,v 1.9 2003/08/21 20:29:43 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -137,12 +137,6 @@ NtUserCallTwoParam( IntReleaseWindowObject(WindowObject); return (DWORD)TRUE; - - case TWOPARAM_ROUTINE_SETWINSTASYSMENU: - if(!Param1 || !Param2) - return (DWORD)FALSE; - /* FIXME clone menu and assign it to the window station */ - return (DWORD)TRUE; } DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam()\n Param1=0x%x Parm2=0x%x\n", diff --git a/reactos/subsys/win32k/ntuser/window.c b/reactos/subsys/win32k/ntuser/window.c index 7afb941d14f..bbe1a4f3da4 100644 --- a/reactos/subsys/win32k/ntuser/window.c +++ b/reactos/subsys/win32k/ntuser/window.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: window.c,v 1.99 2003/08/21 16:04:26 weiden Exp $ +/* $Id: window.c,v 1.100 2003/08/21 20:29:44 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -306,9 +306,15 @@ IntGetSystemMenu(PWINDOW_OBJECT WindowObject, BOOL bRevert) { PMENU_OBJECT MenuObject, NewMenuObject; PW32PROCESS W32Process; + HMENU NewMenu; if(bRevert) { + W32Process = PsGetWin32Process(); + + if(!W32Process->WindowStation) + return (HMENU)0; + if(WindowObject->SystemMenu) { MenuObject = IntGetMenuObject(WindowObject->SystemMenu); @@ -317,7 +323,7 @@ IntGetSystemMenu(PWINDOW_OBJECT WindowObject, BOOL bRevert) IntDestroyMenuObject(MenuObject, FALSE, TRUE); } } - W32Process = PsGetWin32Process(); + if(W32Process->WindowStation->SystemMenuTemplate) { /* clone system menu */ @@ -334,6 +340,24 @@ IntGetSystemMenu(PWINDOW_OBJECT WindowObject, BOOL bRevert) } IntReleaseMenuObject(MenuObject); } + else + { + NewMenu = IntLoadSysMenuTemplate(); + if(!NewMenu) + return (HMENU)0; + MenuObject = IntGetMenuObject(NewMenu); + if(!MenuObject) + return (HMENU)0; + + NewMenuObject = IntCloneMenu(MenuObject); + if(NewMenuObject) + { + WindowObject->SystemMenu = NewMenuObject->Self; + NewMenuObject->IsSystemMenu = TRUE; + IntReleaseMenuObject(NewMenuObject); + } + IntDestroyMenuObject(MenuObject, FALSE, TRUE); + } return (HMENU)0; } else