wine/dlls/ole32/moniker.c
2004-12-13 21:19:01 +00:00

555 lines
20 KiB
C

/*
* Monikers
*
* Copyright 1998 Marcus Meissner
* Copyright 1999 Noomen Hamza
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* TODO:
* - IRunningObjectTable should work interprocess, but currently doesn't.
* Native (on Win2k at least) uses an undocumented RPC interface, IROT, to
* communicate with RPCSS which contains the table of marshalled data.
* - IRunningObjectTable should use marshalling instead of simple ref
* counting as there is the possibility of using the running object table
* to access objects in other apartments.
*/
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#define COBJMACROS
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wtypes.h"
#include "wine/debug.h"
#include "ole2.h"
#include "compobj_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
#define BLOCK_TAB_SIZE 20 /* represent the first size table and it's increment block size */
/* define the structure of the running object table elements */
typedef struct RunObject{
IUnknown* pObj; /* points on a running object*/
IMoniker* pmkObj; /* points on a moniker who identifies this object */
FILETIME lastModifObj;
DWORD identRegObj; /* registration key relative to this object */
DWORD regTypeObj; /* registration type : strong or weak */
}RunObject;
/* define the RunningObjectTableImpl structure */
typedef struct RunningObjectTableImpl{
IRunningObjectTableVtbl *lpVtbl;
ULONG ref;
RunObject* runObjTab; /* pointer to the first object in the table */
DWORD runObjTabSize; /* current table size */
DWORD runObjTabLastIndx; /* first free index element in the table. */
DWORD runObjTabRegister; /* registration key of the next registered object */
} RunningObjectTableImpl;
RunningObjectTableImpl* runningObjectTableInstance=0;
/* IRunningObjectTable prototype functions : */
/* IUnknown functions*/
static HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject);
static ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface);
static ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface);
/* IRunningObjectTable functions */
static HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,IUnknown* punkObject,IMoniker* pmkObjectName,DWORD* pdwRegister);
static HRESULT WINAPI RunningObjectTableImpl_Revoke(IRunningObjectTable* iface, DWORD dwRegister);
static HRESULT WINAPI RunningObjectTableImpl_IsRunning(IRunningObjectTable* iface, IMoniker* pmkObjectName);
static HRESULT WINAPI RunningObjectTableImpl_GetObject(IRunningObjectTable* iface, IMoniker* pmkObjectName,IUnknown** ppunkObject);
static HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, DWORD dwRegister,FILETIME* pfiletime);
static HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, IMoniker* pmkObjectName,FILETIME* pfiletime);
static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker** ppenumMoniker);
/* Local functions*/
HRESULT WINAPI RunningObjectTableImpl_Initialize(void);
HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void);
HRESULT WINAPI RunningObjectTableImpl_Destroy(void);
HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,DWORD identReg,IMoniker* pmk,DWORD *indx);
/* Virtual function table for the IRunningObjectTable class. */
static IRunningObjectTableVtbl VT_RunningObjectTableImpl =
{
RunningObjectTableImpl_QueryInterface,
RunningObjectTableImpl_AddRef,
RunningObjectTableImpl_Release,
RunningObjectTableImpl_Register,
RunningObjectTableImpl_Revoke,
RunningObjectTableImpl_IsRunning,
RunningObjectTableImpl_GetObject,
RunningObjectTableImpl_NoteChangeTime,
RunningObjectTableImpl_GetTimeOfLastChange,
RunningObjectTableImpl_EnumRunning
};
/***********************************************************************
* RunningObjectTable_QueryInterface
*/
HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject)
{
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
/* validate arguments */
if (This==0)
return CO_E_NOTINITIALIZED;
if (ppvObject==0)
return E_INVALIDARG;
*ppvObject = 0;
if (IsEqualIID(&IID_IUnknown, riid))
*ppvObject = (IRunningObjectTable*)This;
else
if (IsEqualIID(&IID_IRunningObjectTable, riid))
*ppvObject = (IRunningObjectTable*)This;
if ((*ppvObject)==0)
return E_NOINTERFACE;
RunningObjectTableImpl_AddRef(iface);
return S_OK;
}
/***********************************************************************
* RunningObjectTable_AddRef
*/
ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
{
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
TRACE("(%p)\n",This);
return InterlockedIncrement(&This->ref);
}
/***********************************************************************
* RunningObjectTable_Initialize
*/
HRESULT WINAPI RunningObjectTableImpl_Destroy()
{
TRACE("()\n");
if (runningObjectTableInstance==NULL)
return E_INVALIDARG;
/* free the ROT table memory */
HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab);
/* free the ROT structure memory */
HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
return S_OK;
}
/***********************************************************************
* RunningObjectTable_Release
*/
ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface)
{
DWORD i;
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
ULONG ref;
TRACE("(%p)\n",This);
ref = InterlockedDecrement(&This->ref);
/* unitialize ROT structure if there's no more reference to it*/
if (ref == 0) {
/* release all registered objects */
for(i=0;i<This->runObjTabLastIndx;i++)
{
if (( This->runObjTab[i].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0)
IUnknown_Release(This->runObjTab[i].pObj);
IMoniker_Release(This->runObjTab[i].pmkObj);
}
/* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
* when RunningObjectTableImpl_UnInitialize function is called
*/
/* there's no more elements in the table */
This->runObjTabRegister=0;
This->runObjTabLastIndx=0;
}
return ref;
}
/***********************************************************************
* RunningObjectTable_Initialize
*/
HRESULT WINAPI RunningObjectTableImpl_Initialize()
{
TRACE("()\n");
/* create the unique instance of the RunningObjectTableImpl structure */
runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));
if (runningObjectTableInstance == 0)
return E_OUTOFMEMORY;
/* initialize the virtual table function */
runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl;
/* the initial reference is set to "1" ! because if set to "0" it will be not practis when */
/* the ROT referred many times not in the same time (all the objects in the ROT will */
/* be removed every time the ROT is removed ) */
runningObjectTableInstance->ref = 1;
/* allocate space memory for the table which contains all the running objects */
runningObjectTableInstance->runObjTab = HeapAlloc(GetProcessHeap(), 0, sizeof(RunObject[BLOCK_TAB_SIZE]));
if (runningObjectTableInstance->runObjTab == NULL)
return E_OUTOFMEMORY;
runningObjectTableInstance->runObjTabSize=BLOCK_TAB_SIZE;
runningObjectTableInstance->runObjTabRegister=1;
runningObjectTableInstance->runObjTabLastIndx=0;
return S_OK;
}
/***********************************************************************
* RunningObjectTable_UnInitialize
*/
HRESULT WINAPI RunningObjectTableImpl_UnInitialize()
{
TRACE("()\n");
if (runningObjectTableInstance==NULL)
return E_POINTER;
RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance);
RunningObjectTableImpl_Destroy();
return S_OK;
}
/***********************************************************************
* RunningObjectTable_Register
*/
HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface,
DWORD grfFlags, /* Registration options */
IUnknown *punkObject, /* Pointer to the object being registered */
IMoniker *pmkObjectName, /* Pointer to the moniker of the object being registered */
DWORD *pdwRegister) /* Pointer to the value identifying the registration */
{
HRESULT res=S_OK;
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
/* there's only two types of register : strong and or weak registration (only one must be passed on parameter) */
if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
(!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
(grfFlags) )
return E_INVALIDARG;
if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
return E_INVALIDARG;
/* verify if the object to be registered was registered before */
if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL)==S_OK)
res = MK_S_MONIKERALREADYREGISTERED;
/* put the new registered object in the first free element in the table */
This->runObjTab[This->runObjTabLastIndx].pObj = punkObject;
This->runObjTab[This->runObjTabLastIndx].pmkObj = pmkObjectName;
This->runObjTab[This->runObjTabLastIndx].regTypeObj = grfFlags;
This->runObjTab[This->runObjTabLastIndx].identRegObj = This->runObjTabRegister;
CoFileTimeNow(&(This->runObjTab[This->runObjTabLastIndx].lastModifObj));
/* gives a registration identifier to the registered object*/
(*pdwRegister)= This->runObjTabRegister;
if (This->runObjTabRegister == 0xFFFFFFFF){
FIXME("runObjTabRegister: %ld is out of data limite \n",This->runObjTabRegister);
return E_FAIL;
}
This->runObjTabRegister++;
This->runObjTabLastIndx++;
if (This->runObjTabLastIndx == This->runObjTabSize){ /* table is full ! so it must be resized */
This->runObjTabSize+=BLOCK_TAB_SIZE; /* newsize table */
This->runObjTab=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->runObjTab,
This->runObjTabSize * sizeof(RunObject));
if (!This->runObjTab)
return E_OUTOFMEMORY;
}
/* add a reference to the object in the strong registration case */
if ((grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) !=0 ) {
TRACE("strong registration, reffing %p\n", punkObject);
/* this is wrong; we should always add a reference to the object */
IUnknown_AddRef(punkObject);
}
IMoniker_AddRef(pmkObjectName);
return res;
}
/***********************************************************************
* RunningObjectTable_Revoke
*/
HRESULT WINAPI RunningObjectTableImpl_Revoke( IRunningObjectTable* iface,
DWORD dwRegister) /* Value identifying registration to be revoked*/
{
DWORD index,j;
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
TRACE("(%p,%ld)\n",This,dwRegister);
/* verify if the object to be revoked was registered before or not */
if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
return E_INVALIDARG;
/* release the object if it was registered with a strong registrantion option */
if ((This->runObjTab[index].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE)!=0) {
TRACE("releasing %p\n", This->runObjTab[index].pObj);
/* this is also wrong; we should always release the object (see above) */
IUnknown_Release(This->runObjTab[index].pObj);
}
IMoniker_Release(This->runObjTab[index].pmkObj);
/* remove the object from the table */
for(j=index; j<This->runObjTabLastIndx-1; j++)
This->runObjTab[j]= This->runObjTab[j+1];
This->runObjTabLastIndx--;
return S_OK;
}
/***********************************************************************
* RunningObjectTable_IsRunning
*/
HRESULT WINAPI RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface,
IMoniker *pmkObjectName) /* Pointer to the moniker of the object whose status is desired */
{
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
TRACE("(%p,%p)\n",This,pmkObjectName);
return RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL);
}
/***********************************************************************
* RunningObjectTable_GetObject
*/
HRESULT WINAPI RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
IMoniker *pmkObjectName,/* Pointer to the moniker on the object */
IUnknown **ppunkObject) /* Address of output variable that receives the IUnknown interface pointer */
{
DWORD index;
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
if (ppunkObject==NULL)
return E_POINTER;
*ppunkObject=0;
/* verify if the object was registered before or not */
if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE) {
WARN("Moniker unavailable - needs to work interprocess?\n");
return MK_E_UNAVAILABLE;
}
/* add a reference to the object then set output object argument */
IUnknown_AddRef(This->runObjTab[index].pObj);
*ppunkObject=This->runObjTab[index].pObj;
return S_OK;
}
/***********************************************************************
* RunningObjectTable_NoteChangeTime
*/
HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
DWORD dwRegister, /* Value identifying registration being updated */
FILETIME *pfiletime) /* Pointer to structure containing object's last change time */
{
DWORD index=-1;
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
TRACE("(%p,%ld,%p)\n",This,dwRegister,pfiletime);
/* verify if the object to be changed was registered before or not */
if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
return E_INVALIDARG;
/* set the new value of the last time change */
This->runObjTab[index].lastModifObj= (*pfiletime);
return S_OK;
}
/***********************************************************************
* RunningObjectTable_GetTimeOfLastChange
*/
HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
IMoniker *pmkObjectName, /* Pointer to moniker on the object whose status is desired */
FILETIME *pfiletime) /* Pointer to structure that receives object's last change time */
{
DWORD index=-1;
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
if (pmkObjectName==NULL || pfiletime==NULL)
return E_INVALIDARG;
/* verify if the object was registered before or not */
if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE)
return MK_E_UNAVAILABLE;
(*pfiletime)= This->runObjTab[index].lastModifObj;
return S_OK;
}
/***********************************************************************
* RunningObjectTable_EnumRunning
*/
HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
IEnumMoniker **ppenumMoniker) /* Address of output variable that receives the IEnumMoniker interface pointer */
{
FIXME("(%p,%p) needs the IEnumMoniker implementation \n",iface,ppenumMoniker);
return E_NOTIMPL;
}
/***********************************************************************
* GetObjectIndex
*/
HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,
DWORD identReg,
IMoniker* pmk,
DWORD *indx)
{
DWORD i;
TRACE("(%p,%ld,%p,%p)\n",This,identReg,pmk,indx);
if (pmk!=NULL)
/* search object identified by a moniker */
for(i=0 ; (i < This->runObjTabLastIndx) &&(!IMoniker_IsEqual(This->runObjTab[i].pmkObj,pmk)==S_OK);i++);
else
/* search object identified by a register identifier */
for(i=0;((i<This->runObjTabLastIndx)&&(This->runObjTab[i].identRegObj!=identReg));i++);
if (i==This->runObjTabLastIndx) return S_FALSE;
if (indx != NULL) *indx=i;
return S_OK;
}
/******************************************************************************
* GetRunningObjectTable (OLE2.30)
*/
HRESULT WINAPI GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
{
FIXME("(%ld,%p),stub!\n",reserved,pprot);
return E_NOTIMPL;
}
/***********************************************************************
* GetRunningObjectTable (OLE32.@)
*/
HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
{
IID riid=IID_IRunningObjectTable;
HRESULT res;
TRACE("()\n");
if (reserved!=0)
return E_UNEXPECTED;
if(runningObjectTableInstance==NULL)
return CO_E_NOTINITIALIZED;
res = RunningObjectTableImpl_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot);
return res;
}
/******************************************************************************
* OleRun [OLE32.@]
*/
HRESULT WINAPI OleRun(LPUNKNOWN pUnknown)
{
IRunnableObject *runable;
IRunnableObject *This = (IRunnableObject *)pUnknown;
LRESULT ret;
ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable);
if (ret)
return 0; /* Appears to return no error. */
ret = IRunnableObject_Run(runable,NULL);
IRunnableObject_Release(runable);
return ret;
}
/******************************************************************************
* MkParseDisplayName [OLE32.@]
*/
HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
LPDWORD pchEaten, LPMONIKER *ppmk)
{
FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk);
if (!(IsValidInterface((LPUNKNOWN) pbc)))
return E_INVALIDARG;
return MK_E_SYNTAX;
}
/******************************************************************************
* CreateClassMoniker [OLE32.@]
*/
HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker ** ppmk)
{
FIXME("%s\n", debugstr_guid( rclsid ));
if( ppmk )
*ppmk = NULL;
return E_NOTIMPL;
}