4 * Copyright 1998 Marcus Meissner
5 * Copyright 1999 Noomen Hamza
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * - IRunningObjectTable should work interprocess, but currently doesn't.
23 * Native (on Win2k at least) uses an undocumented RPC interface, IROT, to
24 * communicate with RPCSS which contains the table of marshalled data.
25 * - IRunningObjectTable should use marshalling instead of simple ref
26 * counting as there is the possibility of using the running object table
27 * to access objects in other apartments.
41 #include "wine/debug.h"
44 #include "compobj_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(ole);
48 #define BLOCK_TAB_SIZE 20 /* represent the first size table and it's increment block size */
50 /* define the structure of the running object table elements */
51 typedef struct RunObject{
53 IUnknown* pObj; /* points on a running object*/
54 IMoniker* pmkObj; /* points on a moniker who identifies this object */
55 FILETIME lastModifObj;
56 DWORD identRegObj; /* registration key relative to this object */
57 DWORD regTypeObj; /* registration type : strong or weak */
60 /* define the RunningObjectTableImpl structure */
61 typedef struct RunningObjectTableImpl{
63 IRunningObjectTableVtbl *lpVtbl;
66 RunObject* runObjTab; /* pointer to the first object in the table */
67 DWORD runObjTabSize; /* current table size */
68 DWORD runObjTabLastIndx; /* first free index element in the table. */
69 DWORD runObjTabRegister; /* registration key of the next registered object */
71 } RunningObjectTableImpl;
73 static RunningObjectTableImpl* runningObjectTableInstance = NULL;
75 /* IRunningObjectTable prototype functions : */
76 /* IUnknown functions*/
77 static HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject);
78 static ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface);
79 static ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface);
80 /* IRunningObjectTable functions */
81 static HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,IUnknown* punkObject,IMoniker* pmkObjectName,DWORD* pdwRegister);
82 static HRESULT WINAPI RunningObjectTableImpl_Revoke(IRunningObjectTable* iface, DWORD dwRegister);
83 static HRESULT WINAPI RunningObjectTableImpl_IsRunning(IRunningObjectTable* iface, IMoniker* pmkObjectName);
84 static HRESULT WINAPI RunningObjectTableImpl_GetObject(IRunningObjectTable* iface, IMoniker* pmkObjectName,IUnknown** ppunkObject);
85 static HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, DWORD dwRegister,FILETIME* pfiletime);
86 static HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, IMoniker* pmkObjectName,FILETIME* pfiletime);
87 static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker** ppenumMoniker);
89 HRESULT WINAPI RunningObjectTableImpl_Initialize(void);
90 HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void);
91 HRESULT WINAPI RunningObjectTableImpl_Destroy(void);
92 HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,DWORD identReg,IMoniker* pmk,DWORD *indx);
94 /* Virtual function table for the IRunningObjectTable class. */
95 static IRunningObjectTableVtbl VT_RunningObjectTableImpl =
97 RunningObjectTableImpl_QueryInterface,
98 RunningObjectTableImpl_AddRef,
99 RunningObjectTableImpl_Release,
100 RunningObjectTableImpl_Register,
101 RunningObjectTableImpl_Revoke,
102 RunningObjectTableImpl_IsRunning,
103 RunningObjectTableImpl_GetObject,
104 RunningObjectTableImpl_NoteChangeTime,
105 RunningObjectTableImpl_GetTimeOfLastChange,
106 RunningObjectTableImpl_EnumRunning
109 /***********************************************************************
110 * RunningObjectTable_QueryInterface
112 HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject)
114 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
116 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
118 /* validate arguments */
120 return CO_E_NOTINITIALIZED;
127 if (IsEqualIID(&IID_IUnknown, riid))
128 *ppvObject = (IRunningObjectTable*)This;
130 if (IsEqualIID(&IID_IRunningObjectTable, riid))
131 *ppvObject = (IRunningObjectTable*)This;
134 return E_NOINTERFACE;
136 RunningObjectTableImpl_AddRef(iface);
141 /***********************************************************************
142 * RunningObjectTable_AddRef
144 ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
146 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
148 TRACE("(%p)\n",This);
150 return InterlockedIncrement(&This->ref);
153 /***********************************************************************
154 * RunningObjectTable_Initialize
156 HRESULT WINAPI RunningObjectTableImpl_Destroy(void)
160 if (runningObjectTableInstance==NULL)
163 /* free the ROT table memory */
164 HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab);
166 /* free the ROT structure memory */
167 HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
168 runningObjectTableInstance = NULL;
173 /***********************************************************************
174 * RunningObjectTable_Release
176 ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface)
179 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
182 TRACE("(%p)\n",This);
184 ref = InterlockedDecrement(&This->ref);
186 /* unitialize ROT structure if there's no more reference to it*/
189 /* release all registered objects */
190 for(i=0;i<This->runObjTabLastIndx;i++)
192 if (( This->runObjTab[i].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0)
193 IUnknown_Release(This->runObjTab[i].pObj);
195 IMoniker_Release(This->runObjTab[i].pmkObj);
197 /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
198 * when RunningObjectTableImpl_UnInitialize function is called
201 /* there's no more elements in the table */
202 This->runObjTabRegister=0;
203 This->runObjTabLastIndx=0;
209 /***********************************************************************
210 * RunningObjectTable_Initialize
212 HRESULT WINAPI RunningObjectTableImpl_Initialize()
216 /* create the unique instance of the RunningObjectTableImpl structure */
217 runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));
219 if (runningObjectTableInstance == 0)
220 return E_OUTOFMEMORY;
222 /* initialize the virtual table function */
223 runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl;
225 /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */
226 /* the ROT referred many times not in the same time (all the objects in the ROT will */
227 /* be removed every time the ROT is removed ) */
228 runningObjectTableInstance->ref = 1;
230 /* allocate space memory for the table which contains all the running objects */
231 runningObjectTableInstance->runObjTab = HeapAlloc(GetProcessHeap(), 0, sizeof(RunObject[BLOCK_TAB_SIZE]));
233 if (runningObjectTableInstance->runObjTab == NULL)
234 return E_OUTOFMEMORY;
236 runningObjectTableInstance->runObjTabSize=BLOCK_TAB_SIZE;
237 runningObjectTableInstance->runObjTabRegister=1;
238 runningObjectTableInstance->runObjTabLastIndx=0;
243 /***********************************************************************
244 * RunningObjectTable_UnInitialize
246 HRESULT WINAPI RunningObjectTableImpl_UnInitialize()
250 if (runningObjectTableInstance==NULL)
253 RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance);
255 RunningObjectTableImpl_Destroy();
260 /***********************************************************************
261 * RunningObjectTable_Register
263 HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface,
264 DWORD grfFlags, /* Registration options */
265 IUnknown *punkObject, /* Pointer to the object being registered */
266 IMoniker *pmkObjectName, /* Pointer to the moniker of the object being registered */
267 DWORD *pdwRegister) /* Pointer to the value identifying the registration */
270 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
272 TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
274 /* there's only two types of register : strong and or weak registration (only one must be passed on parameter) */
275 if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
276 (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
280 if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
283 /* verify if the object to be registered was registered before */
284 if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL)==S_OK)
285 res = MK_S_MONIKERALREADYREGISTERED;
287 /* put the new registered object in the first free element in the table */
288 This->runObjTab[This->runObjTabLastIndx].pObj = punkObject;
289 This->runObjTab[This->runObjTabLastIndx].pmkObj = pmkObjectName;
290 This->runObjTab[This->runObjTabLastIndx].regTypeObj = grfFlags;
291 This->runObjTab[This->runObjTabLastIndx].identRegObj = This->runObjTabRegister;
292 CoFileTimeNow(&(This->runObjTab[This->runObjTabLastIndx].lastModifObj));
294 /* gives a registration identifier to the registered object*/
295 (*pdwRegister)= This->runObjTabRegister;
297 if (This->runObjTabRegister == 0xFFFFFFFF){
299 FIXME("runObjTabRegister: %ld is out of data limite \n",This->runObjTabRegister);
302 This->runObjTabRegister++;
303 This->runObjTabLastIndx++;
305 if (This->runObjTabLastIndx == This->runObjTabSize){ /* table is full ! so it must be resized */
307 This->runObjTabSize+=BLOCK_TAB_SIZE; /* newsize table */
308 This->runObjTab=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->runObjTab,
309 This->runObjTabSize * sizeof(RunObject));
310 if (!This->runObjTab)
311 return E_OUTOFMEMORY;
313 /* add a reference to the object in the strong registration case */
314 if ((grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) !=0 ) {
315 TRACE("strong registration, reffing %p\n", punkObject);
316 /* this is wrong; we should always add a reference to the object */
317 IUnknown_AddRef(punkObject);
320 IMoniker_AddRef(pmkObjectName);
325 /***********************************************************************
326 * RunningObjectTable_Revoke
328 HRESULT WINAPI RunningObjectTableImpl_Revoke( IRunningObjectTable* iface,
329 DWORD dwRegister) /* Value identifying registration to be revoked*/
333 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
335 TRACE("(%p,%ld)\n",This,dwRegister);
337 /* verify if the object to be revoked was registered before or not */
338 if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
342 /* release the object if it was registered with a strong registrantion option */
343 if ((This->runObjTab[index].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE)!=0) {
344 TRACE("releasing %p\n", This->runObjTab[index].pObj);
345 /* this is also wrong; we should always release the object (see above) */
346 IUnknown_Release(This->runObjTab[index].pObj);
349 IMoniker_Release(This->runObjTab[index].pmkObj);
351 /* remove the object from the table */
352 for(j=index; j<This->runObjTabLastIndx-1; j++)
353 This->runObjTab[j]= This->runObjTab[j+1];
355 This->runObjTabLastIndx--;
360 /***********************************************************************
361 * RunningObjectTable_IsRunning
363 HRESULT WINAPI RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface,
364 IMoniker *pmkObjectName) /* Pointer to the moniker of the object whose status is desired */
366 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
368 TRACE("(%p,%p)\n",This,pmkObjectName);
370 return RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL);
373 /***********************************************************************
374 * RunningObjectTable_GetObject
376 HRESULT WINAPI RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
377 IMoniker *pmkObjectName,/* Pointer to the moniker on the object */
378 IUnknown **ppunkObject) /* Address of output variable that receives the IUnknown interface pointer */
381 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
383 TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
385 if (ppunkObject==NULL)
390 /* verify if the object was registered before or not */
391 if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE) {
392 WARN("Moniker unavailable - needs to work interprocess?\n");
393 return MK_E_UNAVAILABLE;
396 /* add a reference to the object then set output object argument */
397 IUnknown_AddRef(This->runObjTab[index].pObj);
398 *ppunkObject=This->runObjTab[index].pObj;
403 /***********************************************************************
404 * RunningObjectTable_NoteChangeTime
406 HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
407 DWORD dwRegister, /* Value identifying registration being updated */
408 FILETIME *pfiletime) /* Pointer to structure containing object's last change time */
411 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
413 TRACE("(%p,%ld,%p)\n",This,dwRegister,pfiletime);
415 /* verify if the object to be changed was registered before or not */
416 if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
419 /* set the new value of the last time change */
420 This->runObjTab[index].lastModifObj= (*pfiletime);
425 /***********************************************************************
426 * RunningObjectTable_GetTimeOfLastChange
428 HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
429 IMoniker *pmkObjectName, /* Pointer to moniker on the object whose status is desired */
430 FILETIME *pfiletime) /* Pointer to structure that receives object's last change time */
433 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
435 TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
437 if (pmkObjectName==NULL || pfiletime==NULL)
440 /* verify if the object was registered before or not */
441 if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE)
442 return MK_E_UNAVAILABLE;
444 (*pfiletime)= This->runObjTab[index].lastModifObj;
449 /***********************************************************************
450 * RunningObjectTable_EnumRunning
452 HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
453 IEnumMoniker **ppenumMoniker) /* Address of output variable that receives the IEnumMoniker interface pointer */
455 FIXME("(%p,%p) needs the IEnumMoniker implementation \n",iface,ppenumMoniker);
459 /***********************************************************************
462 HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,
470 TRACE("(%p,%ld,%p,%p)\n",This,identReg,pmk,indx);
473 /* search object identified by a moniker */
474 for(i=0 ; (i < This->runObjTabLastIndx) &&(!IMoniker_IsEqual(This->runObjTab[i].pmkObj,pmk)==S_OK);i++);
476 /* search object identified by a register identifier */
477 for(i=0;((i<This->runObjTabLastIndx)&&(This->runObjTab[i].identRegObj!=identReg));i++);
479 if (i==This->runObjTabLastIndx) return S_FALSE;
481 if (indx != NULL) *indx=i;
486 /******************************************************************************
487 * GetRunningObjectTable (OLE2.30)
489 HRESULT WINAPI GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
491 FIXME("(%ld,%p),stub!\n",reserved,pprot);
495 /***********************************************************************
496 * GetRunningObjectTable (OLE32.@)
498 HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
500 IID riid=IID_IRunningObjectTable;
508 if(runningObjectTableInstance==NULL)
509 return CO_E_NOTINITIALIZED;
511 res = RunningObjectTableImpl_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot);
516 /******************************************************************************
519 HRESULT WINAPI OleRun(LPUNKNOWN pUnknown)
521 IRunnableObject *runable;
522 IRunnableObject *This = (IRunnableObject *)pUnknown;
525 ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable);
527 return 0; /* Appears to return no error. */
528 ret = IRunnableObject_Run(runable,NULL);
529 IRunnableObject_Release(runable);
533 /******************************************************************************
534 * MkParseDisplayName [OLE32.@]
536 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
537 LPDWORD pchEaten, LPMONIKER *ppmk)
539 FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk);
540 if (!(IsValidInterface((LPUNKNOWN) pbc)))
546 /******************************************************************************
547 * CreateClassMoniker [OLE32.@]
549 HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker ** ppmk)
551 FIXME("%s\n", debugstr_guid( rclsid ));