diff --git a/dlls/ole32/moniker.c b/dlls/ole32/moniker.c index fb2ee6da85679864c1d7f4cc9304c9caabf4d08f..a1ffa6ef992b7ea84169872922790a079b1e32e7 100644 --- a/dlls/ole32/moniker.c +++ b/dlls/ole32/moniker.c @@ -3,6 +3,7 @@ * * Copyright 1998 Marcus Meissner * Copyright 1999 Noomen Hamza + * Copyright 2005 Robert Shearman (for CodeWeavers) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,9 +23,6 @@ * - 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> @@ -38,62 +36,129 @@ #include "winbase.h" #include "winuser.h" #include "wtypes.h" -#include "wine/debug.h" #include "ole2.h" +#include "wine/list.h" +#include "wine/debug.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; +struct rot_entry +{ + struct list entry; + MInterfacePointer* object; /* marshaled running object*/ + MInterfacePointer* moniker; /* marshaled moniker that identifies this object */ + MInterfacePointer* moniker_data; /* moniker comparison data that identifies this object */ + DWORD cookie; /* cookie identifying this object */ + FILETIME last_modified; +}; /* 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 */ +typedef struct RunningObjectTableImpl +{ + const IRunningObjectTableVtbl *lpVtbl; + ULONG ref; + struct list rot; /* list of ROT entries */ + CRITICAL_SECTION lock; } RunningObjectTableImpl; static RunningObjectTableImpl* runningObjectTableInstance = NULL; -static HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl*,DWORD,IMoniker*,DWORD *); -/* define the EnumMonikerImpl structure */ -typedef struct EnumMonikerImpl{ - IEnumMonikerVtbl *lpVtbl; - ULONG ref; +static inline HRESULT WINAPI +IrotRegister(DWORD *cookie) +{ + static DWORD last_cookie = 1; + *cookie = InterlockedIncrement(&last_cookie); + return S_OK; +} - RunObject* TabMoniker; /* pointer to the first object in the table */ - DWORD TabSize; /* current table size */ - DWORD TabLastIndx; /* last used index element in the table. */ - DWORD TabCurrentPos; /* enum position in the list */ +/* define the EnumMonikerImpl structure */ +typedef struct EnumMonikerImpl +{ + const IEnumMonikerVtbl *lpVtbl; + ULONG ref; + MInterfacePointer **monikers; + ULONG moniker_count; + ULONG pos; } EnumMonikerImpl; /* IEnumMoniker Local functions*/ -static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(RunObject* runObjTab, - ULONG TabSize, - ULONG TabLastIndx, - ULONG TabCurrentPos, - IEnumMoniker ** ppenumMoniker); +static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers, + ULONG moniker_count, ULONG pos, IEnumMoniker **ppenumMoniker); + +static HRESULT create_stream_on_mip_ro(const MInterfacePointer *mip, IStream **stream) +{ + HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData); + void *pv = GlobalLock(hglobal); + memcpy(pv, mip->abData, mip->ulCntData); + GlobalUnlock(hglobal); + return CreateStreamOnHGlobal(hglobal, TRUE, stream); +} + +static inline void rot_entry_delete(struct rot_entry *rot_entry) +{ + /* FIXME: revoke entry from rpcss's copy of the ROT */ + if (rot_entry->object) + { + IStream *stream; + HRESULT hr; + hr = create_stream_on_mip_ro(rot_entry->object, &stream); + if (hr == S_OK) + { + CoReleaseMarshalData(stream); + IUnknown_Release(stream); + } + } + if (rot_entry->moniker) + { + IStream *stream; + HRESULT hr; + hr = create_stream_on_mip_ro(rot_entry->moniker, &stream); + if (hr == S_OK) + { + CoReleaseMarshalData(stream); + IUnknown_Release(stream); + } + } + HeapFree(GetProcessHeap(), 0, rot_entry->object); + HeapFree(GetProcessHeap(), 0, rot_entry->moniker); + HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data); + HeapFree(GetProcessHeap(), 0, rot_entry); +} + +/* moniker_data must be freed with HeapFree when no longer in use */ +static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer **moniker_data) +{ + HRESULT hr; + IROTData *pROTData = NULL; + ULONG size = 0; + hr = IMoniker_QueryInterface(pMoniker, &IID_IROTData, (void *)&pROTData); + if (hr != S_OK) + { + ERR("Failed to query moniker for IROTData interface, hr = 0x%08lx\n", hr); + return hr; + } + IROTData_GetComparisonData(pROTData, NULL, 0, &size); + *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); + (*moniker_data)->ulCntData = size; + hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size); + if (hr != S_OK) + { + ERR("Failed to copy comparison data into buffer, hr = 0x%08lx\n", hr); + HeapFree(GetProcessHeap(), 0, *moniker_data); + return hr; + } + return S_OK; +} + /*********************************************************************** * RunningObjectTable_QueryInterface */ @@ -106,8 +171,6 @@ RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface, TRACE("(%p,%p,%p)\n",This,riid,ppvObject); /* validate arguments */ - if (This==0) - return CO_E_NOTINITIALIZED; if (ppvObject==0) return E_INVALIDARG; @@ -145,13 +208,20 @@ RunningObjectTableImpl_AddRef(IRunningObjectTable* iface) static HRESULT WINAPI RunningObjectTableImpl_Destroy(void) { + struct list *cursor, *cursor2; + TRACE("()\n"); if (runningObjectTableInstance==NULL) return E_INVALIDARG; /* free the ROT table memory */ - HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab); + LIST_FOR_EACH_SAFE(cursor, cursor2, &runningObjectTableInstance->rot) + { + struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry); + list_remove(&rot_entry->entry); + rot_entry_delete(rot_entry); + } /* free the ROT structure memory */ HeapFree(GetProcessHeap(),0,runningObjectTableInstance); @@ -166,7 +236,6 @@ RunningObjectTableImpl_Destroy(void) static ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface) { - DWORD i; RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; ULONG ref; @@ -174,24 +243,19 @@ RunningObjectTableImpl_Release(IRunningObjectTable* iface) 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++) + /* uninitialize ROT structure if there's no more references to it */ + if (ref == 0) + { + struct list *cursor, *cursor2; + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->rot) { - if (( This->runObjTab[i].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0) - IUnknown_Release(This->runObjTab[i].pObj); - - IMoniker_Release(This->runObjTab[i].pmkObj); + struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry); + list_remove(&rot_entry->entry); + rot_entry_delete(rot_entry); } - /* 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; + /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only + * when RunningObjectTableImpl_UnInitialize function is called + */ } return ref; @@ -210,8 +274,11 @@ static HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags, IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister) { - HRESULT res=S_OK; RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + struct rot_entry *rot_entry; + HRESULT hr = S_OK; + IStream *pStream = NULL; + DWORD mshlflags; TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister); @@ -222,51 +289,107 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags, if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) && (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) && (grfFlags) ) + { + ERR("Invalid combination of ROTFLAGS: %lx\n", 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; + rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry)); + if (!rot_entry) + return E_OUTOFMEMORY; - if (This->runObjTabRegister == 0xFFFFFFFF){ + CoFileTimeNow(&rot_entry->last_modified); - FIXME("runObjTabRegister: %ld is out of data limite \n",This->runObjTabRegister); - return E_FAIL; + /* marshal object */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; + } + mshlflags = (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK; + hr = CoMarshalInterface(pStream, &IID_IUnknown, punkObject, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, mshlflags); + /* FIXME: a cleaner way would be to create an IStream class that writes + * directly to an MInterfacePointer */ + if (hr == S_OK) + { + HGLOBAL hglobal; + hr = GetHGlobalFromStream(pStream, &hglobal); + if (hr == S_OK) + { + SIZE_T size = GlobalSize(hglobal); + const void *pv = GlobalLock(hglobal); + rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); + rot_entry->object->ulCntData = size; + memcpy(&rot_entry->object->abData, pv, size); + GlobalUnlock(hglobal); + } + } + IStream_Release(pStream); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; } - This->runObjTabRegister++; - This->runObjTabLastIndx++; - if (This->runObjTabLastIndx == This->runObjTabSize){ /* table is full ! so it must be resized */ + hr = get_moniker_comparison_data(pmkObjectName, &rot_entry->moniker_data); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; + } - 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; + hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; } - /* 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); + /* marshal moniker */ + hr = CoMarshalInterface(pStream, &IID_IMoniker, (IUnknown *)pmkObjectName, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG); + /* FIXME: a cleaner way would be to create an IStream class that writes + * directly to an MInterfacePointer */ + if (hr == S_OK) + { + HGLOBAL hglobal; + hr = GetHGlobalFromStream(pStream, &hglobal); + if (hr == S_OK) + { + SIZE_T size = GlobalSize(hglobal); + const void *pv = GlobalLock(hglobal); + rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); + rot_entry->moniker->ulCntData = size; + memcpy(&rot_entry->moniker->abData, pv, size); + GlobalUnlock(hglobal); + } + } + IStream_Release(pStream); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; } - - IMoniker_AddRef(pmkObjectName); - return res; + /* FIXME: not the right signature of IrotRegister function */ + hr = IrotRegister(&rot_entry->cookie); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; + } + + /* gives a registration identifier to the registered object*/ + *pdwRegister = rot_entry->cookie; + + EnterCriticalSection(&This->lock); + /* FIXME: see if object was registered before and return MK_S_MONIKERALREADYREGISTERED */ + list_add_tail(&This->rot, &rot_entry->entry); + LeaveCriticalSection(&This->lock); + + return hr; } /*********************************************************************** @@ -278,33 +401,26 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags, static HRESULT WINAPI RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister) { - - DWORD index,j; RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + struct rot_entry *rot_entry; 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; + EnterCriticalSection(&This->lock); + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) + { + if (rot_entry->cookie == dwRegister) + { + list_remove(&rot_entry->entry); + LeaveCriticalSection(&This->lock); - /* 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); + rot_entry_delete(rot_entry); + return S_OK; + } } - - 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--; + LeaveCriticalSection(&This->lock); - return S_OK; + return E_INVALIDARG; } /*********************************************************************** @@ -317,10 +433,34 @@ static HRESULT WINAPI RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName) { RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + MInterfacePointer *moniker_data; + HRESULT hr; + struct rot_entry *rot_entry; TRACE("(%p,%p)\n",This,pmkObjectName); - return RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL); + hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); + if (hr != S_OK) + return hr; + + hr = S_FALSE; + EnterCriticalSection(&This->lock); + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) + { + if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && + !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData)) + { + hr = S_OK; + break; + } + } + LeaveCriticalSection(&This->lock); + + /* FIXME: call IrotIsRunning */ + + HeapFree(GetProcessHeap(), 0, moniker_data); + + return hr; } /*********************************************************************** @@ -334,27 +474,51 @@ static HRESULT WINAPI RunningObjectTableImpl_GetObject( IRunningObjectTable* iface, IMoniker *pmkObjectName, IUnknown **ppunkObject) { - DWORD index; RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + MInterfacePointer *moniker_data; + HRESULT hr; + struct rot_entry *rot_entry; TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject); - if (ppunkObject==NULL) + if (ppunkObject == NULL) return E_POINTER; - *ppunkObject=0; + *ppunkObject = NULL; - /* 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; + hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); + if (hr != S_OK) + return hr; + + EnterCriticalSection(&This->lock); + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) + { + if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && + !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData)) + { + IStream *pStream; + hr = create_stream_on_mip_ro(rot_entry->object, &pStream); + if (hr == S_OK) + { + hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject); + IStream_Release(pStream); + } + + LeaveCriticalSection(&This->lock); + HeapFree(GetProcessHeap(), 0, moniker_data); + + return hr; + } } + LeaveCriticalSection(&This->lock); - /* add a reference to the object then set output object argument */ - IUnknown_AddRef(This->runObjTab[index].pObj); - *ppunkObject=This->runObjTab[index].pObj; + /* FIXME: call IrotGetObject */ + WARN("Moniker unavailable - app may require interprocess running object table\n"); + hr = MK_E_UNAVAILABLE; - return S_OK; + HeapFree(GetProcessHeap(), 0, moniker_data); + + return hr; } /*********************************************************************** @@ -368,19 +532,26 @@ static HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, DWORD dwRegister, FILETIME *pfiletime) { - DWORD index=-1; RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + struct rot_entry *rot_entry; 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; + EnterCriticalSection(&This->lock); + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) + { + if (rot_entry->cookie == dwRegister) + { + rot_entry->last_modified = *pfiletime; + LeaveCriticalSection(&This->lock); + return S_OK; + } + } + LeaveCriticalSection(&This->lock); - /* set the new value of the last time change */ - This->runObjTab[index].lastModifObj= (*pfiletime); + /* FIXME: call IrotNoteChangeTime */ - return S_OK; + return E_INVALIDARG; } /*********************************************************************** @@ -394,21 +565,39 @@ static HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, IMoniker *pmkObjectName, FILETIME *pfiletime) { - DWORD index=-1; + HRESULT hr = MK_E_UNAVAILABLE; RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + MInterfacePointer *moniker_data; + struct rot_entry *rot_entry; 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; + hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); + if (hr != S_OK) + return hr; - (*pfiletime)= This->runObjTab[index].lastModifObj; + hr = MK_E_UNAVAILABLE; - return S_OK; + EnterCriticalSection(&This->lock); + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) + { + if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && + !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData)) + { + *pfiletime = rot_entry->last_modified; + hr = S_OK; + break; + } + } + LeaveCriticalSection(&This->lock); + + /* FIXME: if (hr != S_OK) call IrotGetTimeOfLastChange */ + + HeapFree(GetProcessHeap(), 0, moniker_data); + return hr; } /*********************************************************************** @@ -421,44 +610,35 @@ static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker **ppenumMoniker) { - /* create the unique instance of the EnumMonkikerImpl structure - * and copy the Monikers referenced in the ROT so that they can be - * enumerated by the Enum interface - */ - HRESULT rc = 0; + HRESULT hr; RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + MInterfacePointer **monikers; + ULONG moniker_count = 0; + const struct rot_entry *rot_entry; + ULONG i = 0; - rc=EnumMonikerImpl_CreateEnumROTMoniker(This->runObjTab, - This->runObjTabSize, - This->runObjTabLastIndx, 0, - ppenumMoniker); - return rc; -} + EnterCriticalSection(&This->lock); -/*********************************************************************** - * GetObjectIndex - */ -static HRESULT WINAPI -RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This, - DWORD identReg, IMoniker* pmk, DWORD *indx) -{ - - DWORD i; + LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry ) + moniker_count++; - TRACE("(%p,%ld,%p,%p)\n",This,identReg,pmk,indx); + monikers = HeapAlloc(GetProcessHeap(), 0, moniker_count * sizeof(*monikers)); - 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++); + LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry ) + { + SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[rot_entry->moniker->ulCntData]); + monikers[i] = HeapAlloc(GetProcessHeap(), 0, size); + memcpy(monikers[i], rot_entry->moniker, size); + i++; + } - if (i==This->runObjTabLastIndx) return S_FALSE; + LeaveCriticalSection(&This->lock); + + /* FIXME: call IrotEnumRunning and append data */ - if (indx != NULL) *indx=i; + hr = EnumMonikerImpl_CreateEnumROTMoniker(monikers, moniker_count, 0, ppenumMoniker); - return S_OK; + return hr; } /****************************************************************************** @@ -560,7 +740,7 @@ HRESULT WINAPI RunningObjectTableImpl_Initialize(void) /* create the unique instance of the RunningObjectTableImpl structure */ runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl)); - if (runningObjectTableInstance == 0) + if (!runningObjectTableInstance) return E_OUTOFMEMORY; /* initialize the virtual table function */ @@ -571,15 +751,8 @@ HRESULT WINAPI RunningObjectTableImpl_Initialize(void) /* 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; + list_init(&runningObjectTableInstance->rot); + InitializeCriticalSection(&runningObjectTableInstance->lock); return S_OK; } @@ -647,7 +820,6 @@ static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface) */ static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface) { - DWORD i; EnumMonikerImpl *This = (EnumMonikerImpl *)iface; ULONG ref; @@ -656,20 +828,16 @@ static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface) ref = InterlockedDecrement(&This->ref); /* unitialize rot structure if there's no more reference to it*/ - if (ref == 0) { - - /* release all registered objects in Moniker list */ - for(i=0; i < This->TabLastIndx ;i++) - { - IMoniker_Release(This->TabMoniker[i].pmkObj); - } + if (ref == 0) + { + ULONG i; - /* there're no more elements in the table */ + TRACE("(%p) Deleting\n",This); - TRACE("(%p) Deleting\n",This); - HeapFree (GetProcessHeap(), 0, This->TabMoniker); /* free Moniker list */ - HeapFree (GetProcessHeap(), 0, This); /* free Enum Instance */ - + for (i = 0; i < This->moniker_count; i++) + HeapFree(GetProcessHeap(), 0, This->monikers[i]); + HeapFree(GetProcessHeap(), 0, This->monikers); + HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -681,16 +849,28 @@ static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IM { ULONG i; EnumMonikerImpl *This = (EnumMonikerImpl *)iface; - TRACE("(%p) TabCurrentPos %ld Tablastindx %ld\n",This, This->TabCurrentPos, This->TabLastIndx); + HRESULT hr = S_OK; + + TRACE("(%p) TabCurrentPos %ld Tablastindx %ld\n", This, This->pos, This->moniker_count); /* retrieve the requested number of moniker from the current position */ - for(i=0; (This->TabCurrentPos < This->TabLastIndx) && (i < celt); i++) - rgelt[i]=(IMoniker*)This->TabMoniker[This->TabCurrentPos++].pmkObj; + for(i = 0; (This->pos < This->moniker_count) && (i < celt); i++) + { + IStream *stream; + hr = create_stream_on_mip_ro(This->monikers[This->pos++], &stream); + if (hr != S_OK) break; + hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]); + IStream_Release(stream); + if (hr != S_OK) break; + } - if (pceltFetched!=NULL) + if (pceltFetched != NULL) *pceltFetched= i; - if (i==celt) + if (hr != S_OK) + return hr; + + if (i == celt) return S_OK; else return S_FALSE; @@ -706,10 +886,10 @@ static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt) TRACE("(%p)\n",This); - if (This->TabCurrentPos+celt >= This->TabLastIndx) - return S_FALSE; + if (This->pos + celt >= This->moniker_count) + return S_FALSE; - This->TabCurrentPos+=celt; + This->pos += celt; return S_OK; } @@ -721,7 +901,7 @@ static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface) { EnumMonikerImpl *This = (EnumMonikerImpl *)iface; - This->TabCurrentPos = 0; /* set back to start of list */ + This->pos = 0; /* set back to start of list */ TRACE("(%p)\n",This); @@ -734,16 +914,25 @@ static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface) static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum) { EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + MInterfacePointer **monikers = HeapAlloc(GetProcessHeap(), 0, sizeof(*monikers)*This->moniker_count); + ULONG i; TRACE("(%p)\n",This); + + for (i = 0; i < This->moniker_count; i++) + { + SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[This->monikers[i]->ulCntData]); + monikers[i] = HeapAlloc(GetProcessHeap(), 0, size); + memcpy(monikers[i], This->monikers[i], size); + } + /* copy the enum structure */ - return EnumMonikerImpl_CreateEnumROTMoniker(This->TabMoniker, This->TabSize, - This->TabLastIndx, This->TabCurrentPos, - ppenum); + return EnumMonikerImpl_CreateEnumROTMoniker(monikers, This->moniker_count, + This->pos, ppenum); } /* Virtual function table for the IEnumMoniker class. */ -static IEnumMonikerVtbl VT_EnumMonikerImpl = +static const IEnumMonikerVtbl VT_EnumMonikerImpl = { EnumMonikerImpl_QueryInterface, EnumMonikerImpl_AddRef, @@ -759,24 +948,18 @@ static IEnumMonikerVtbl VT_EnumMonikerImpl = * Used by EnumRunning to create the structure and EnumClone * to copy the structure */ -HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(RunObject* TabMoniker, - ULONG TabSize, - ULONG TabLastIndx, - ULONG TabCurrentPos, - IEnumMoniker ** ppenumMoniker) +static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers, + ULONG moniker_count, + ULONG current_pos, + IEnumMoniker **ppenumMoniker) { - int i; EnumMonikerImpl* This = NULL; - if (TabCurrentPos > TabSize) - return E_INVALIDARG; - - if (ppenumMoniker == NULL) + if (!ppenumMoniker) return E_INVALIDARG; This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl)); - - if (!ppenumMoniker) return E_OUTOFMEMORY; + if (!This) return E_OUTOFMEMORY; TRACE("(%p)\n", This); @@ -785,20 +968,9 @@ HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(RunObject* TabMoniker, /* the initial reference is set to "1" */ This->ref = 1; /* set the ref count to one */ - This->TabCurrentPos=0; /* Set the list start posn to start */ - This->TabSize=TabSize; /* Need the same size table as ROT */ - This->TabLastIndx=TabLastIndx; /* end element */ - This->TabMoniker=HeapAlloc(GetProcessHeap(),0,This->TabSize*sizeof(RunObject)); - - if (This->TabMoniker==NULL) { - HeapFree(GetProcessHeap(), 0, This); - return E_OUTOFMEMORY; - } - for (i=0; i < This->TabLastIndx; i++){ - - This->TabMoniker[i]=TabMoniker[i]; - IMoniker_AddRef(TabMoniker[i].pmkObj); - } + This->pos = 0; /* Set the list start posn to start */ + This->moniker_count = moniker_count; /* Need the same size table as ROT */ + This->monikers = monikers; *ppenumMoniker = (IEnumMoniker*)This; diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c index 55e9b264791266842f5e1df2e25fa298c9c89818..1b780ef583135146d0596933d6bae3c11e7c3882 100644 --- a/dlls/ole32/tests/marshal.c +++ b/dlls/ole32/tests/marshal.c @@ -1540,6 +1540,33 @@ static void test_out_of_process_com() } #endif +static void test_ROT() +{ + static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-', + '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-', + '2','0','4','6','E','5','8','6','C','9','2','5',0}; + HRESULT hr; + IMoniker *pMoniker = NULL; + IRunningObjectTable *pROT = NULL; + DWORD dwCookie; + + cLocks = 0; + + hr = CreateFileMoniker(wszFileName, &pMoniker); + ok_ole_success(hr, CreateClassMoniker); + hr = GetRunningObjectTable(0, &pROT); + ok_ole_success(hr, GetRunningObjectTable); + hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie); + ok_ole_success(hr, IRunningObjectTable_Register); + + ok_more_than_one_lock(); + + hr = IRunningObjectTable_Revoke(pROT, dwCookie); + ok_ole_success(hr, IRunningObjectTable_Revoke); + + ok_no_locks(); +} + START_TEST(marshal) { HMODULE hOle32 = GetModuleHandle("ole32"); @@ -1575,10 +1602,13 @@ START_TEST(marshal) test_bad_marshal_stream(); test_proxy_interfaces(); test_stubbuffer(&IID_IClassFactory); - /* FIXME: test GIT */ test_message_reentrancy(); /* test_out_of_process_com(); */ + + test_ROT(); + /* FIXME: test GIT */ + CoUninitialize(); return;