📄 ole2.c
字号:
HRESULT hres;
TRACE("(%p)\n", pUnknown);
hres = IUnknown_QueryInterface(pUnknown, &IID_IRunnableObject, (void**)&runable);
if (FAILED(hres))
return S_OK; /* Appears to return no error. */
hres = IRunnableObject_Run(runable, NULL);
IRunnableObject_Release(runable);
return hres;
}
/******************************************************************************
* OleLoad [OLE32.@]
*/
HRESULT WINAPI OleLoad(
LPSTORAGE pStg,
REFIID riid,
LPOLECLIENTSITE pClientSite,
LPVOID* ppvObj)
{
IPersistStorage* persistStorage = NULL;
IUnknown* pUnk;
IOleObject* pOleObject = NULL;
STATSTG storageInfo;
HRESULT hres;
TRACE("(%p, %s, %p, %p)\n", pStg, debugstr_guid(riid), pClientSite, ppvObj);
*ppvObj = NULL;
/*
* TODO, Conversion ... OleDoAutoConvert
*/
/*
* Get the class ID for the object.
*/
hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME);
/*
* Now, try and create the handler for the object
*/
hres = CoCreateInstance(&storageInfo.clsid,
NULL,
CLSCTX_INPROC_HANDLER|CLSCTX_INPROC_SERVER,
riid,
(void**)&pUnk);
/*
* If that fails, as it will most times, load the default
* OLE handler.
*/
if (FAILED(hres))
{
hres = OleCreateDefaultHandler(&storageInfo.clsid,
NULL,
riid,
(void**)&pUnk);
}
/*
* If we couldn't find a handler... this is bad. Abort the whole thing.
*/
if (FAILED(hres))
return hres;
if (pClientSite)
{
hres = IUnknown_QueryInterface(pUnk, &IID_IOleObject, (void **)&pOleObject);
if (SUCCEEDED(hres))
{
DWORD dwStatus;
hres = IOleObject_GetMiscStatus(pOleObject, DVASPECT_CONTENT, &dwStatus);
}
}
if (SUCCEEDED(hres))
/*
* Initialize the object with it's IPersistStorage interface.
*/
hres = IOleObject_QueryInterface(pUnk,
&IID_IPersistStorage,
(void**)&persistStorage);
if (SUCCEEDED(hres))
{
hres = IPersistStorage_Load(persistStorage, pStg);
IPersistStorage_Release(persistStorage);
persistStorage = NULL;
}
if (SUCCEEDED(hres) && pClientSite)
/*
* Inform the new object of it's client site.
*/
hres = IOleObject_SetClientSite(pOleObject, pClientSite);
/*
* Cleanup interfaces used internally
*/
if (pOleObject)
IOleObject_Release(pOleObject);
if (SUCCEEDED(hres))
{
IOleLink *pOleLink;
HRESULT hres1;
hres1 = IUnknown_QueryInterface(pUnk, &IID_IOleLink, (void **)&pOleLink);
if (SUCCEEDED(hres1))
{
FIXME("handle OLE link\n");
IOleLink_Release(pOleLink);
}
}
if (FAILED(hres))
{
IUnknown_Release(pUnk);
pUnk = NULL;
}
*ppvObj = pUnk;
return hres;
}
/***********************************************************************
* OleSave [OLE32.@]
*/
HRESULT WINAPI OleSave(
LPPERSISTSTORAGE pPS,
LPSTORAGE pStg,
BOOL fSameAsLoad)
{
HRESULT hres;
CLSID objectClass;
TRACE("(%p,%p,%x)\n", pPS, pStg, fSameAsLoad);
/*
* First, we transfer the class ID (if available)
*/
hres = IPersistStorage_GetClassID(pPS, &objectClass);
if (SUCCEEDED(hres))
{
WriteClassStg(pStg, &objectClass);
}
/*
* Then, we ask the object to save itself to the
* storage. If it is successful, we commit the storage.
*/
hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad);
if (SUCCEEDED(hres))
{
IStorage_Commit(pStg,
STGC_DEFAULT);
}
return hres;
}
/******************************************************************************
* OleLockRunning [OLE32.@]
*/
HRESULT WINAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses)
{
IRunnableObject* runnable = NULL;
HRESULT hres;
TRACE("(%p,%x,%x)\n", pUnknown, fLock, fLastUnlockCloses);
hres = IUnknown_QueryInterface(pUnknown,
&IID_IRunnableObject,
(void**)&runnable);
if (SUCCEEDED(hres))
{
hres = IRunnableObject_LockRunning(runnable, fLock, fLastUnlockCloses);
IRunnableObject_Release(runnable);
return hres;
}
else
return E_INVALIDARG;
}
/**************************************************************************
* 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(void)
{
}
/***
* OLEMenu_UnInitialize()
*
* Releases the OLEMENU data structures.
*/
static void OLEMenu_UnInitialize(void)
{
}
/*************************************************************************
* OLEMenu_InstallHooks
* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC
*
* RETURNS: TRUE if message hooks were successfully installed
* FALSE on failure
*/
static BOOL OLEMenu_InstallHooks( DWORD tid )
{
OleMenuHookItem *pHookItem = NULL;
/* 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 */
pHookItem->next = hook_list;
hook_list = pHookItem;
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 successfully installed
* FALSE on failure
*/
static BOOL OLEMenu_UnInstallHooks( DWORD tid )
{
OleMenuHookItem *pHookItem = NULL;
OleMenuHookItem **ppHook = &hook_list;
while (*ppHook)
{
if ((*ppHook)->tid == tid)
{
pHookItem = *ppHook;
*ppHook = pHookItem->next;
break;
}
ppHook = &(*ppHook)->next;
}
if (!pHookItem) 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 */
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
*/
static OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid )
{
OleMenuHookItem *pHookItem = 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 (pHookItem = hook_list; pHookItem; pHookItem = pHookItem->next)
{
if ( tid == pHookItem->tid )
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
* FALSE if the popup menu is part of a container owned group
*/
static 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 through 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.
*/
static 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("%i, %04lx, %08lx\n", code, wParam, 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 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -