Implementation for OleCreateMenuDescriptor, OleSetMenuDescriptor and
OleDestroyMenuDescriptor along with a bunch of internally used methods and data structures.
This commit is contained in:
parent
5a09711873
commit
0aef461def
587
ole/ole2.c
587
ole/ole2.c
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright 1995 Martin von Loewis
|
||||
* Copyright 1999 Francis Beaudet
|
||||
* Copyright 1999 Noel Borthwick
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -11,6 +12,8 @@
|
|||
#include "winerror.h"
|
||||
#include "ole2.h"
|
||||
#include "process.h"
|
||||
#include "hook.h"
|
||||
#include "commctrl.h"
|
||||
#include "wine/obj_clientserver.h"
|
||||
#include "debug.h"
|
||||
#include "ole2ver.h"
|
||||
|
@ -41,6 +44,28 @@ typedef struct tagTrackerWindowInfo
|
|||
IDropTarget* curDragTarget;
|
||||
} TrackerWindowInfo;
|
||||
|
||||
typedef struct tagOleMenuDescriptor /* OleMenuDescriptor */
|
||||
{
|
||||
HWND hwndFrame; /* The containers frame window */
|
||||
HWND hwndActiveObject; /* The active objects window */
|
||||
OLEMENUGROUPWIDTHS mgw; /* OLE menu group widths for the shared menu */
|
||||
HMENU hmenuCombined; /* The combined menu */
|
||||
BOOL bIsServerItem; /* True if the currently open popup belongs to the server */
|
||||
} OleMenuDescriptor;
|
||||
|
||||
typedef struct tagOleMenuHookItem /* OleMenu hook item in per thread hook list */
|
||||
{
|
||||
DWORD tid; /* Thread Id */
|
||||
HANDLE hHeap; /* Heap this is allocated from */
|
||||
HHOOK GetMsg_hHook; /* message hook for WH_GETMESSAGE */
|
||||
HHOOK CallWndProc_hHook; /* message hook for WH_CALLWNDPROC */
|
||||
} OleMenuHookItem;
|
||||
|
||||
/*
|
||||
* Dynamic pointer array of per thread message hooks (maintained by OleSetMenuDescriptor)
|
||||
*/
|
||||
static HDPA OLEMenu_MsgHookDPA = NULL;
|
||||
|
||||
/*
|
||||
* This is the lock count on the OLE library. It is controlled by the
|
||||
* OLEInitialize/OLEUninitialize methods.
|
||||
|
@ -57,6 +82,19 @@ static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32";
|
|||
*/
|
||||
static DropTargetNode* targetListHead = NULL;
|
||||
|
||||
/******************************************************************************
|
||||
* These are the prototypes of the utility methods used to manage a shared menu
|
||||
*/
|
||||
static void OLEMenu_Initialize();
|
||||
static void OLEMenu_UnInitialize();
|
||||
BOOL OLEMenu_InstallHooks( DWORD tid );
|
||||
BOOL OLEMenu_UnInstallHooks( DWORD tid );
|
||||
OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid, INT *pixHook );
|
||||
static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos );
|
||||
BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor );
|
||||
LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
/******************************************************************************
|
||||
* These are the prototypes of the utility methods used for OLE Drag n Drop
|
||||
*/
|
||||
|
@ -133,6 +171,11 @@ HRESULT WINAPI OleInitialize(LPVOID reserved)
|
|||
* Drag and Drop
|
||||
*/
|
||||
OLEDD_Initialize();
|
||||
|
||||
/*
|
||||
* OLE shared menu
|
||||
*/
|
||||
OLEMenu_Initialize();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -179,6 +222,11 @@ void WINAPI OleUninitialize(void)
|
|||
* Drag and Drop
|
||||
*/
|
||||
OLEDD_UnInitialize();
|
||||
|
||||
/*
|
||||
* OLE shared menu
|
||||
*/
|
||||
OLEMenu_UnInitialize();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -460,46 +508,575 @@ HRESULT WINAPI OleGetClipboard(
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Internal methods to manage the shared OLE menu in response to the
|
||||
* OLE***MenuDescriptor API
|
||||
*/
|
||||
|
||||
/***
|
||||
* OLEMenu_Initialize()
|
||||
*
|
||||
* Initializes the OLEMENU data structures.
|
||||
*/
|
||||
static void OLEMenu_Initialize()
|
||||
{
|
||||
/* Create a dynamic pointer array to store the hook handles */
|
||||
if ( !OLEMenu_MsgHookDPA )
|
||||
OLEMenu_MsgHookDPA = DPA_CreateEx( 2, GetProcessHeap() );
|
||||
}
|
||||
|
||||
/***
|
||||
* OLEMenu_UnInitialize()
|
||||
*
|
||||
* Releases the OLEMENU data structures.
|
||||
*/
|
||||
static void OLEMenu_UnInitialize()
|
||||
{
|
||||
/* Release the hook table */
|
||||
if ( OLEMenu_MsgHookDPA )
|
||||
DPA_Destroy( OLEMenu_MsgHookDPA );
|
||||
|
||||
OLEMenu_MsgHookDPA = NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* OLEMenu_InstallHooks
|
||||
* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
|
||||
*
|
||||
* RETURNS: TRUE if message hooks were succesfully installed
|
||||
* FALSE on failure
|
||||
*/
|
||||
BOOL OLEMenu_InstallHooks( DWORD tid )
|
||||
{
|
||||
OleMenuHookItem *pHookItem = NULL;
|
||||
|
||||
if ( !OLEMenu_MsgHookDPA ) /* No hook table? Create one */
|
||||
{
|
||||
/* Create a dynamic pointer array to store the hook handles */
|
||||
if ( !(OLEMenu_MsgHookDPA = DPA_CreateEx( 2, GetProcessHeap() )) )
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Create an entry for the hook table */
|
||||
if ( !(pHookItem = HeapAlloc(GetProcessHeap(), 0,
|
||||
sizeof(OleMenuHookItem)) ) )
|
||||
return FALSE;
|
||||
|
||||
pHookItem->tid = tid;
|
||||
pHookItem->hHeap = GetProcessHeap();
|
||||
|
||||
/* Install a thread scope message hook for WH_GETMESSAGE */
|
||||
pHookItem->GetMsg_hHook = SetWindowsHookExA( WH_GETMESSAGE, OLEMenu_GetMsgProc,
|
||||
0, GetCurrentThreadId() );
|
||||
if ( !pHookItem->GetMsg_hHook )
|
||||
goto CLEANUP;
|
||||
|
||||
/* Install a thread scope message hook for WH_CALLWNDPROC */
|
||||
pHookItem->CallWndProc_hHook = SetWindowsHookExA( WH_CALLWNDPROC, OLEMenu_CallWndProc,
|
||||
0, GetCurrentThreadId() );
|
||||
if ( !pHookItem->CallWndProc_hHook )
|
||||
goto CLEANUP;
|
||||
|
||||
/* Insert the hook table entry */
|
||||
if ( -1 == DPA_InsertPtr( OLEMenu_MsgHookDPA, 0, pHookItem ) )
|
||||
goto CLEANUP;
|
||||
|
||||
return TRUE;
|
||||
|
||||
CLEANUP:
|
||||
/* Unhook any hooks */
|
||||
if ( pHookItem->GetMsg_hHook )
|
||||
UnhookWindowsHookEx( pHookItem->GetMsg_hHook );
|
||||
if ( pHookItem->CallWndProc_hHook )
|
||||
UnhookWindowsHookEx( pHookItem->CallWndProc_hHook );
|
||||
/* Release the hook table entry */
|
||||
HeapFree(pHookItem->hHeap, 0, pHookItem );
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* OLEMenu_UnInstallHooks
|
||||
* UnInstall thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
|
||||
*
|
||||
* RETURNS: TRUE if message hooks were succesfully installed
|
||||
* FALSE on failure
|
||||
*/
|
||||
BOOL OLEMenu_UnInstallHooks( DWORD tid )
|
||||
{
|
||||
INT ixHook;
|
||||
OleMenuHookItem *pHookItem = NULL;
|
||||
|
||||
if ( !OLEMenu_MsgHookDPA ) /* No hooks set */
|
||||
return TRUE;
|
||||
|
||||
/* Lookup the hHook index for this tid */
|
||||
if ( !OLEMenu_IsHookInstalled( tid , &ixHook ) )
|
||||
return TRUE;
|
||||
|
||||
/* Remove the hook entry from the table(the pointer itself is not deleted) */
|
||||
if ( !( pHookItem = DPA_DeletePtr(OLEMenu_MsgHookDPA, ixHook) ) )
|
||||
return FALSE;
|
||||
|
||||
/* Uninstall the hooks installed for this thread */
|
||||
if ( !UnhookWindowsHookEx( pHookItem->GetMsg_hHook ) )
|
||||
goto CLEANUP;
|
||||
if ( !UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ) )
|
||||
goto CLEANUP;
|
||||
|
||||
/* Release the hook table entry */
|
||||
HeapFree(pHookItem->hHeap, 0, pHookItem );
|
||||
|
||||
return TRUE;
|
||||
|
||||
CLEANUP:
|
||||
/* Release the hook table entry */
|
||||
if (pHookItem)
|
||||
HeapFree(pHookItem->hHeap, 0, pHookItem );
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* OLEMenu_IsHookInstalled
|
||||
* Tests if OLEMenu hooks have been installed for a thread
|
||||
*
|
||||
* RETURNS: The pointer and index of the hook table entry for the tid
|
||||
* NULL and -1 for the index if no hooks were installed for this thread
|
||||
*/
|
||||
OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid, INT *pixHook )
|
||||
{
|
||||
INT ixHook;
|
||||
OleMenuHookItem *pHookItem = NULL;
|
||||
|
||||
if ( pixHook )
|
||||
*pixHook = -1;
|
||||
|
||||
if ( !OLEMenu_MsgHookDPA ) /* No hooks set */
|
||||
return NULL;
|
||||
|
||||
/* Do a simple linear search for an entry whose tid matches ours.
|
||||
* We really need a map but efficiency is not a concern here. */
|
||||
for( ixHook = 0; ; ixHook++ )
|
||||
{
|
||||
/* Retrieve the hook entry */
|
||||
if ( !( pHookItem = DPA_GetPtr(OLEMenu_MsgHookDPA, ixHook) ) )
|
||||
return NULL;
|
||||
|
||||
if ( tid == pHookItem->tid )
|
||||
{
|
||||
if ( pixHook )
|
||||
*pixHook = ixHook;
|
||||
return pHookItem;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* OLEMenu_FindMainMenuIndex
|
||||
*
|
||||
* Used by OLEMenu API to find the top level group a menu item belongs to.
|
||||
* On success pnPos contains the index of the item in the top level menu group
|
||||
*
|
||||
* RETURNS: TRUE if the ID was found, FALSE on failure
|
||||
*/
|
||||
static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos )
|
||||
{
|
||||
UINT i, nItems;
|
||||
|
||||
nItems = GetMenuItemCount( hMainMenu );
|
||||
|
||||
for (i = 0; i < nItems; i++)
|
||||
{
|
||||
HMENU hsubmenu;
|
||||
|
||||
/* Is the current item a submenu? */
|
||||
if ( (hsubmenu = GetSubMenu(hMainMenu, i)) )
|
||||
{
|
||||
/* If the handle is the same we're done */
|
||||
if ( hsubmenu == hPopupMenu )
|
||||
{
|
||||
if (pnPos)
|
||||
*pnPos = i;
|
||||
return TRUE;
|
||||
}
|
||||
/* Recursively search without updating pnPos */
|
||||
else if ( OLEMenu_FindMainMenuIndex( hsubmenu, hPopupMenu, NULL ) )
|
||||
{
|
||||
if (pnPos)
|
||||
*pnPos = i;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* OLEMenu_SetIsServerMenu
|
||||
*
|
||||
* Checks whether a popup menu belongs to a shared menu group which is
|
||||
* owned by the server, and sets the menu descriptor state accordingly.
|
||||
* All menu messages from these groups should be routed to the server.
|
||||
*
|
||||
* RETURNS: TRUE if the popup menu is part of a server owned group
|
||||
* FASE if the popup menu is part of a container owned group
|
||||
*/
|
||||
BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor )
|
||||
{
|
||||
UINT nPos = 0, nWidth, i;
|
||||
|
||||
pOleMenuDescriptor->bIsServerItem = FALSE;
|
||||
|
||||
/* Don't bother searching if the popup is the combined menu itself */
|
||||
if ( hmenu == pOleMenuDescriptor->hmenuCombined )
|
||||
return FALSE;
|
||||
|
||||
/* Find the menu item index in the shared OLE menu that this item belongs to */
|
||||
if ( !OLEMenu_FindMainMenuIndex( pOleMenuDescriptor->hmenuCombined, hmenu, &nPos ) )
|
||||
return FALSE;
|
||||
|
||||
/* The group widths array has counts for the number of elements
|
||||
* in the groups File, Edit, Container, Object, Window, Help.
|
||||
* The Edit, Object & Help groups belong to the server object
|
||||
* and the other three belong to the container.
|
||||
* Loop thru the group widths and locate the group we are a member of.
|
||||
*/
|
||||
for ( i = 0, nWidth = 0; i < 6; i++ )
|
||||
{
|
||||
nWidth += pOleMenuDescriptor->mgw.width[i];
|
||||
if ( nPos < nWidth )
|
||||
{
|
||||
/* Odd elements are server menu widths */
|
||||
pOleMenuDescriptor->bIsServerItem = (i%2) ? TRUE : FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pOleMenuDescriptor->bIsServerItem;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* OLEMenu_CallWndProc
|
||||
* Thread scope WH_CALLWNDPROC hook proc filter function (callback)
|
||||
* This is invoked from a message hook installed in OleSetMenuDescriptor.
|
||||
*/
|
||||
LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LPCWPSTRUCT pMsg = NULL;
|
||||
HOLEMENU hOleMenu = 0;
|
||||
OleMenuDescriptor *pOleMenuDescriptor = NULL;
|
||||
OleMenuHookItem *pHookItem = NULL;
|
||||
WORD fuFlags;
|
||||
|
||||
TRACE(ole,"%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
|
||||
|
||||
/* Check if we're being asked to process the message */
|
||||
if ( HC_ACTION != code )
|
||||
goto NEXTHOOK;
|
||||
|
||||
/* Retrieve the current message being dispatched from lParam */
|
||||
pMsg = (LPCWPSTRUCT)lParam;
|
||||
|
||||
/* Check if the message is destined for a window we are interested in:
|
||||
* If the window has an OLEMenu property we may need to dispatch
|
||||
* the menu message to its active objects window instead. */
|
||||
|
||||
hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
|
||||
if ( !hOleMenu )
|
||||
goto NEXTHOOK;
|
||||
|
||||
/* Get the menu descriptor */
|
||||
pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
|
||||
if ( !pOleMenuDescriptor ) /* Bad descriptor! */
|
||||
goto NEXTHOOK;
|
||||
|
||||
/* Process menu messages */
|
||||
switch( pMsg->message )
|
||||
{
|
||||
case WM_INITMENU:
|
||||
{
|
||||
/* Reset the menu descriptor state */
|
||||
pOleMenuDescriptor->bIsServerItem = FALSE;
|
||||
|
||||
/* Send this message to the server as well */
|
||||
SendMessageA( pOleMenuDescriptor->hwndActiveObject,
|
||||
pMsg->message, pMsg->wParam, pMsg->lParam );
|
||||
goto NEXTHOOK;
|
||||
}
|
||||
|
||||
case WM_INITMENUPOPUP:
|
||||
{
|
||||
/* Save the state for whether this is a server owned menu */
|
||||
OLEMenu_SetIsServerMenu( (HMENU)pMsg->wParam, pOleMenuDescriptor );
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MENUSELECT:
|
||||
{
|
||||
fuFlags = HIWORD(pMsg->wParam); /* Get flags */
|
||||
if ( fuFlags & MF_SYSMENU )
|
||||
goto NEXTHOOK;
|
||||
|
||||
/* Save the state for whether this is a server owned popup menu */
|
||||
else if ( fuFlags & MF_POPUP )
|
||||
OLEMenu_SetIsServerMenu( (HMENU)pMsg->lParam, pOleMenuDescriptor );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_DRAWITEM:
|
||||
{
|
||||
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) pMsg->lParam;
|
||||
if ( pMsg->wParam != 0 || lpdis->CtlType != ODT_MENU )
|
||||
goto NEXTHOOK; /* Not a menu message */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
goto NEXTHOOK;
|
||||
}
|
||||
|
||||
/* If the message was for the server dispatch it accordingly */
|
||||
if ( pOleMenuDescriptor->bIsServerItem )
|
||||
{
|
||||
SendMessageA( pOleMenuDescriptor->hwndActiveObject,
|
||||
pMsg->message, pMsg->wParam, pMsg->lParam );
|
||||
}
|
||||
|
||||
NEXTHOOK:
|
||||
if ( pOleMenuDescriptor )
|
||||
GlobalUnlock( hOleMenu );
|
||||
|
||||
/* Lookup the hook item for the current thread */
|
||||
if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId(), NULL ) ) )
|
||||
{
|
||||
/* This should never fail!! */
|
||||
WARN(ole, "could not retrieve hHook for current thread!\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Pass on the message to the next hooker */
|
||||
return CallNextHookEx( pHookItem->CallWndProc_hHook, code, wParam, lParam );
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* OLEMenu_GetMsgProc
|
||||
* Thread scope WH_GETMESSAGE hook proc filter function (callback)
|
||||
* This is invoked from a message hook installed in OleSetMenuDescriptor.
|
||||
*/
|
||||
LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LPMSG pMsg = NULL;
|
||||
HOLEMENU hOleMenu = 0;
|
||||
OleMenuDescriptor *pOleMenuDescriptor = NULL;
|
||||
OleMenuHookItem *pHookItem = NULL;
|
||||
WORD wCode;
|
||||
|
||||
TRACE(ole,"%i, %04x, %08x\n", code, wParam, (unsigned)lParam );
|
||||
|
||||
/* Check if we're being asked to process a messages */
|
||||
if ( HC_ACTION != code )
|
||||
goto NEXTHOOK;
|
||||
|
||||
/* Retrieve the current message being dispatched from lParam */
|
||||
pMsg = (LPMSG)lParam;
|
||||
|
||||
/* Check if the message is destined for a window we are interested in:
|
||||
* If the window has an OLEMenu property we may need to dispatch
|
||||
* the menu message to its active objects window instead. */
|
||||
|
||||
hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" );
|
||||
if ( !hOleMenu )
|
||||
goto NEXTHOOK;
|
||||
|
||||
/* Process menu messages */
|
||||
switch( pMsg->message )
|
||||
{
|
||||
case WM_COMMAND:
|
||||
{
|
||||
wCode = HIWORD(pMsg->wParam); /* Get notification code */
|
||||
if ( wCode )
|
||||
goto NEXTHOOK; /* Not a menu message */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto NEXTHOOK;
|
||||
}
|
||||
|
||||
/* Get the menu descriptor */
|
||||
pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
|
||||
if ( !pOleMenuDescriptor ) /* Bad descriptor! */
|
||||
goto NEXTHOOK;
|
||||
|
||||
/* If the message was for the server dispatch it accordingly */
|
||||
if ( pOleMenuDescriptor->bIsServerItem )
|
||||
{
|
||||
/* Change the hWnd in the message to the active objects hWnd.
|
||||
* The message loop which reads this message will automatically
|
||||
* dispatch it to the embedded objects window. */
|
||||
pMsg->hwnd = pOleMenuDescriptor->hwndActiveObject;
|
||||
}
|
||||
|
||||
NEXTHOOK:
|
||||
if ( pOleMenuDescriptor )
|
||||
GlobalUnlock( hOleMenu );
|
||||
|
||||
/* Lookup the hook item for the current thread */
|
||||
if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId(), NULL ) ) )
|
||||
{
|
||||
/* This should never fail!! */
|
||||
WARN(ole, "could not retrieve hHook for current thread!\n" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Pass on the message to the next hooker */
|
||||
return CallNextHookEx( pHookItem->GetMsg_hHook, code, wParam, lParam );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* OleCreateMenuDescriptor [OLE32.97]
|
||||
* Creates an OLE menu descriptor for OLE to use when dispatching
|
||||
* menu messages and commands.
|
||||
*
|
||||
* PARAMS:
|
||||
* hmenuCombined - Handle to the objects combined menu
|
||||
* lpMenuWidths - Pointer to array of 6 LONG's indicating menus per group
|
||||
*
|
||||
*/
|
||||
HOLEMENU WINAPI OleCreateMenuDescriptor(
|
||||
HMENU hmenuCombined,
|
||||
LPOLEMENUGROUPWIDTHS lpMenuWidths)
|
||||
{
|
||||
FIXME(ole,"(%x,%p),stub!\n", hmenuCombined, lpMenuWidths);
|
||||
HOLEMENU hOleMenu;
|
||||
OleMenuDescriptor *pOleMenuDescriptor;
|
||||
int i;
|
||||
|
||||
if ( !hmenuCombined || !lpMenuWidths )
|
||||
return 0;
|
||||
|
||||
/* Create an OLE menu descriptor */
|
||||
if ( !(hOleMenu = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
|
||||
sizeof(OleMenuDescriptor) ) ) )
|
||||
return 0;
|
||||
|
||||
pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
|
||||
if ( !pOleMenuDescriptor )
|
||||
return 0;
|
||||
|
||||
/* Initialize menu group widths and hmenu */
|
||||
for ( i = 0; i < 6; i++ )
|
||||
pOleMenuDescriptor->mgw.width[i] = lpMenuWidths->width[i];
|
||||
|
||||
pOleMenuDescriptor->hmenuCombined = hmenuCombined;
|
||||
pOleMenuDescriptor->bIsServerItem = FALSE;
|
||||
GlobalUnlock( hOleMenu );
|
||||
|
||||
return hOleMenu;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* OleDestroyMenuDescriptor [OLE32.99]
|
||||
* Destroy the shared menu descriptor
|
||||
*/
|
||||
HRESULT WINAPI OleDestroyMenuDescriptor(
|
||||
HOLEMENU hmenuDescriptor)
|
||||
{
|
||||
FIXME(ole,"(%x),stub!\n", (unsigned int)hmenuDescriptor);
|
||||
if ( hmenuDescriptor )
|
||||
GlobalFree( hmenuDescriptor );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* OleSetMenuDescriptor [OLE32.129]
|
||||
* Installs or removes OLE dispatching code for the containers frame window
|
||||
* FIXME: The lpFrame and lpActiveObject parameters are currently ignored
|
||||
* OLE should install context sensitive help F1 filtering for the app when
|
||||
* these are non null.
|
||||
*
|
||||
* PARAMS:
|
||||
* hOleMenu Handle to composite menu descriptor
|
||||
* hwndFrame Handle to containers frame window
|
||||
* hwndActiveObject Handle to objects in-place activation window
|
||||
* lpFrame Pointer to IOleInPlaceFrame on containers window
|
||||
* lpActiveObject Pointer to IOleInPlaceActiveObject on active in-place object
|
||||
*
|
||||
* RETURNS:
|
||||
* S_OK - menu installed correctly
|
||||
* E_FAIL, E_INVALIDARG, E_UNEXPECTED - failure
|
||||
*/
|
||||
HRESULT WINAPI OleSetMenuDescriptor(
|
||||
HOLEMENU hmenuDescriptor,
|
||||
HOLEMENU hOleMenu,
|
||||
HWND hwndFrame,
|
||||
HWND hwndActiveObject,
|
||||
LPOLEINPLACEFRAME lpFrame,
|
||||
LPOLEINPLACEACTIVEOBJECT lpActiveObject)
|
||||
{
|
||||
FIXME(ole,"(%x, %x, %x, %p, %p),stub!\n",
|
||||
(unsigned int)hmenuDescriptor,
|
||||
OleMenuDescriptor *pOleMenuDescriptor = NULL;
|
||||
|
||||
/* Check args */
|
||||
if ( !hwndFrame || (hOleMenu && !hwndActiveObject) )
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( lpFrame || lpActiveObject )
|
||||
{
|
||||
FIXME(ole,"(%x, %x, %x, %p, %p), Context sensitive help filtering not implemented!\n",
|
||||
(unsigned int)hOleMenu,
|
||||
hwndFrame,
|
||||
hwndActiveObject,
|
||||
lpFrame,
|
||||
lpActiveObject);
|
||||
}
|
||||
|
||||
/* Set up a message hook to intercept the containers frame window messages.
|
||||
* The message filter is responsible for dispatching menu messages from the
|
||||
* shared menu which are intended for the object.
|
||||
*/
|
||||
|
||||
if ( hOleMenu ) /* Want to install dispatching code */
|
||||
{
|
||||
/* If OLEMenu hooks are already installed for this thread, fail
|
||||
* Note: This effectively means that OleSetMenuDescriptor cannot
|
||||
* be called twice in succession on the same frame window
|
||||
* without first calling it with a null hOleMenu to uninstall */
|
||||
if ( OLEMenu_IsHookInstalled( GetCurrentThreadId(), NULL ) )
|
||||
return E_FAIL;
|
||||
|
||||
/* Get the menu descriptor */
|
||||
pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu );
|
||||
if ( !pOleMenuDescriptor )
|
||||
return E_UNEXPECTED;
|
||||
|
||||
/* Update the menu descriptor */
|
||||
pOleMenuDescriptor->hwndFrame = hwndFrame;
|
||||
pOleMenuDescriptor->hwndActiveObject = hwndActiveObject;
|
||||
|
||||
GlobalUnlock( hOleMenu );
|
||||
pOleMenuDescriptor = NULL;
|
||||
|
||||
/* Add a menu descriptor windows property to the frame window */
|
||||
SetPropA( hwndFrame, "PROP_OLEMenuDescriptor", hOleMenu );
|
||||
|
||||
/* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC */
|
||||
if ( !OLEMenu_InstallHooks( GetCurrentThreadId() ) )
|
||||
return E_FAIL;
|
||||
}
|
||||
else /* Want to uninstall dispatching code */
|
||||
{
|
||||
/* Uninstall the hooks */
|
||||
if ( !OLEMenu_UnInstallHooks( GetCurrentThreadId() ) )
|
||||
return E_FAIL;
|
||||
|
||||
/* Remove the menu descriptor property from the frame window */
|
||||
RemovePropA( hwndFrame, "PROP_OLEMenuDescriptor" );
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
Loading…
Reference in New Issue