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 static HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl*,DWORD,IMoniker*,DWORD *);
77 /***********************************************************************
78 * RunningObjectTable_QueryInterface
81 RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,
82 REFIID riid,void** ppvObject)
84 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
86 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
88 /* validate arguments */
90 return CO_E_NOTINITIALIZED;
97 if (IsEqualIID(&IID_IUnknown, riid) ||
98 IsEqualIID(&IID_IRunningObjectTable, riid))
99 *ppvObject = (IRunningObjectTable*)This;
102 return E_NOINTERFACE;
104 IRunningObjectTable_AddRef(iface);
109 /***********************************************************************
110 * RunningObjectTable_AddRef
113 RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
115 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
117 TRACE("(%p)\n",This);
119 return InterlockedIncrement(&This->ref);
122 /***********************************************************************
123 * RunningObjectTable_Initialize
125 static HRESULT WINAPI
126 RunningObjectTableImpl_Destroy(void)
130 if (runningObjectTableInstance==NULL)
133 /* free the ROT table memory */
134 HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab);
136 /* free the ROT structure memory */
137 HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
138 runningObjectTableInstance = NULL;
143 /***********************************************************************
144 * RunningObjectTable_Release
147 RunningObjectTableImpl_Release(IRunningObjectTable* iface)
150 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
153 TRACE("(%p)\n",This);
155 ref = InterlockedDecrement(&This->ref);
157 /* unitialize ROT structure if there's no more reference to it*/
160 /* release all registered objects */
161 for(i=0;i<This->runObjTabLastIndx;i++)
163 if (( This->runObjTab[i].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0)
164 IUnknown_Release(This->runObjTab[i].pObj);
166 IMoniker_Release(This->runObjTab[i].pmkObj);
168 /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
169 * when RunningObjectTableImpl_UnInitialize function is called
172 /* there's no more elements in the table */
173 This->runObjTabRegister=0;
174 This->runObjTabLastIndx=0;
180 /***********************************************************************
181 * RunningObjectTable_Register
184 * grfFlags [in] Registration options
185 * punkObject [in] the object being registered
186 * pmkObjectName [in] the moniker of the object being registered
187 * pdwRegister [in] the value identifying the registration
189 static HRESULT WINAPI
190 RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
191 IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister)
194 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
196 TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
199 * there's only two types of register : strong and or weak registration
200 * (only one must be passed on parameter)
202 if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
203 (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
207 if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
210 /* verify if the object to be registered was registered before */
211 if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL)==S_OK)
212 res = MK_S_MONIKERALREADYREGISTERED;
214 /* put the new registered object in the first free element in the table */
215 This->runObjTab[This->runObjTabLastIndx].pObj = punkObject;
216 This->runObjTab[This->runObjTabLastIndx].pmkObj = pmkObjectName;
217 This->runObjTab[This->runObjTabLastIndx].regTypeObj = grfFlags;
218 This->runObjTab[This->runObjTabLastIndx].identRegObj = This->runObjTabRegister;
219 CoFileTimeNow(&(This->runObjTab[This->runObjTabLastIndx].lastModifObj));
221 /* gives a registration identifier to the registered object*/
222 (*pdwRegister)= This->runObjTabRegister;
224 if (This->runObjTabRegister == 0xFFFFFFFF){
226 FIXME("runObjTabRegister: %ld is out of data limite \n",This->runObjTabRegister);
229 This->runObjTabRegister++;
230 This->runObjTabLastIndx++;
232 if (This->runObjTabLastIndx == This->runObjTabSize){ /* table is full ! so it must be resized */
234 This->runObjTabSize+=BLOCK_TAB_SIZE; /* newsize table */
235 This->runObjTab=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->runObjTab,
236 This->runObjTabSize * sizeof(RunObject));
237 if (!This->runObjTab)
238 return E_OUTOFMEMORY;
240 /* add a reference to the object in the strong registration case */
241 if ((grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) !=0 ) {
242 TRACE("strong registration, reffing %p\n", punkObject);
243 /* this is wrong; we should always add a reference to the object */
244 IUnknown_AddRef(punkObject);
247 IMoniker_AddRef(pmkObjectName);
252 /***********************************************************************
253 * RunningObjectTable_Revoke
256 * dwRegister [in] Value identifying registration to be revoked
258 static HRESULT WINAPI
259 RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister)
263 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
265 TRACE("(%p,%ld)\n",This,dwRegister);
267 /* verify if the object to be revoked was registered before or not */
268 if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
272 /* release the object if it was registered with a strong registrantion option */
273 if ((This->runObjTab[index].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE)!=0) {
274 TRACE("releasing %p\n", This->runObjTab[index].pObj);
275 /* this is also wrong; we should always release the object (see above) */
276 IUnknown_Release(This->runObjTab[index].pObj);
279 IMoniker_Release(This->runObjTab[index].pmkObj);
281 /* remove the object from the table */
282 for(j=index; j<This->runObjTabLastIndx-1; j++)
283 This->runObjTab[j]= This->runObjTab[j+1];
285 This->runObjTabLastIndx--;
290 /***********************************************************************
291 * RunningObjectTable_IsRunning
294 * pmkObjectName [in] moniker of the object whose status is desired
296 static HRESULT WINAPI
297 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName)
299 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
301 TRACE("(%p,%p)\n",This,pmkObjectName);
303 return RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL);
306 /***********************************************************************
307 * RunningObjectTable_GetObject
310 * pmkObjectName [in] Pointer to the moniker on the object
311 * ppunkObject [out] variable that receives the IUnknown interface pointer
313 static HRESULT WINAPI
314 RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
315 IMoniker *pmkObjectName, IUnknown **ppunkObject)
318 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
320 TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
322 if (ppunkObject==NULL)
327 /* verify if the object was registered before or not */
328 if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE) {
329 WARN("Moniker unavailable - needs to work interprocess?\n");
330 return MK_E_UNAVAILABLE;
333 /* add a reference to the object then set output object argument */
334 IUnknown_AddRef(This->runObjTab[index].pObj);
335 *ppunkObject=This->runObjTab[index].pObj;
340 /***********************************************************************
341 * RunningObjectTable_NoteChangeTime
344 * dwRegister [in] Value identifying registration being updated
345 * pfiletime [in] Pointer to structure containing object's last change time
347 static HRESULT WINAPI
348 RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
349 DWORD dwRegister, FILETIME *pfiletime)
352 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
354 TRACE("(%p,%ld,%p)\n",This,dwRegister,pfiletime);
356 /* verify if the object to be changed was registered before or not */
357 if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
360 /* set the new value of the last time change */
361 This->runObjTab[index].lastModifObj= (*pfiletime);
366 /***********************************************************************
367 * RunningObjectTable_GetTimeOfLastChange
370 * pmkObjectName [in] moniker of the object whose status is desired
371 * pfiletime [out] structure that receives object's last change time
373 static HRESULT WINAPI
374 RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
375 IMoniker *pmkObjectName, FILETIME *pfiletime)
378 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
380 TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
382 if (pmkObjectName==NULL || pfiletime==NULL)
385 /* verify if the object was registered before or not */
386 if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE)
387 return MK_E_UNAVAILABLE;
389 (*pfiletime)= This->runObjTab[index].lastModifObj;
394 /***********************************************************************
395 * RunningObjectTable_EnumRunning
398 * ppenumMoniker [out] receives the IEnumMoniker interface pointer
400 static HRESULT WINAPI
401 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
402 IEnumMoniker **ppenumMoniker)
404 FIXME("(%p,%p) needs the IEnumMoniker implementation \n",iface,ppenumMoniker);
408 /***********************************************************************
411 static HRESULT WINAPI
412 RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,
413 DWORD identReg, IMoniker* pmk, DWORD *indx)
418 TRACE("(%p,%ld,%p,%p)\n",This,identReg,pmk,indx);
421 /* search object identified by a moniker */
422 for(i=0 ; (i < This->runObjTabLastIndx) &&(!IMoniker_IsEqual(This->runObjTab[i].pmkObj,pmk)==S_OK);i++);
424 /* search object identified by a register identifier */
425 for(i=0;((i<This->runObjTabLastIndx)&&(This->runObjTab[i].identRegObj!=identReg));i++);
427 if (i==This->runObjTabLastIndx) return S_FALSE;
429 if (indx != NULL) *indx=i;
434 /******************************************************************************
435 * GetRunningObjectTable (OLE2.30)
438 GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
440 FIXME("(%ld,%p),stub!\n",reserved,pprot);
444 /***********************************************************************
445 * GetRunningObjectTable (OLE32.@)
448 GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
450 IID riid=IID_IRunningObjectTable;
458 if(runningObjectTableInstance==NULL)
459 return CO_E_NOTINITIALIZED;
461 res = IRunningObjectTable_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot);
466 /******************************************************************************
469 HRESULT WINAPI OleRun(LPUNKNOWN pUnknown)
471 IRunnableObject *runable;
472 IRunnableObject *This = (IRunnableObject *)pUnknown;
475 ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable);
477 return 0; /* Appears to return no error. */
478 ret = IRunnableObject_Run(runable,NULL);
479 IRunnableObject_Release(runable);
483 /******************************************************************************
484 * MkParseDisplayName [OLE32.@]
486 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
487 LPDWORD pchEaten, LPMONIKER *ppmk)
489 FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk);
491 if (!(IsValidInterface((LPUNKNOWN) pbc)))
497 /******************************************************************************
498 * CreateClassMoniker [OLE32.@]
500 HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker ** ppmk)
502 FIXME("%s\n", debugstr_guid( rclsid ));
508 /* Virtual function table for the IRunningObjectTable class. */
509 static IRunningObjectTableVtbl VT_RunningObjectTableImpl =
511 RunningObjectTableImpl_QueryInterface,
512 RunningObjectTableImpl_AddRef,
513 RunningObjectTableImpl_Release,
514 RunningObjectTableImpl_Register,
515 RunningObjectTableImpl_Revoke,
516 RunningObjectTableImpl_IsRunning,
517 RunningObjectTableImpl_GetObject,
518 RunningObjectTableImpl_NoteChangeTime,
519 RunningObjectTableImpl_GetTimeOfLastChange,
520 RunningObjectTableImpl_EnumRunning
523 /***********************************************************************
524 * RunningObjectTable_Initialize
526 HRESULT WINAPI RunningObjectTableImpl_Initialize(void)
530 /* create the unique instance of the RunningObjectTableImpl structure */
531 runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));
533 if (runningObjectTableInstance == 0)
534 return E_OUTOFMEMORY;
536 /* initialize the virtual table function */
537 runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl;
539 /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */
540 /* the ROT referred many times not in the same time (all the objects in the ROT will */
541 /* be removed every time the ROT is removed ) */
542 runningObjectTableInstance->ref = 1;
544 /* allocate space memory for the table which contains all the running objects */
545 runningObjectTableInstance->runObjTab = HeapAlloc(GetProcessHeap(), 0, sizeof(RunObject[BLOCK_TAB_SIZE]));
547 if (runningObjectTableInstance->runObjTab == NULL)
548 return E_OUTOFMEMORY;
550 runningObjectTableInstance->runObjTabSize=BLOCK_TAB_SIZE;
551 runningObjectTableInstance->runObjTabRegister=1;
552 runningObjectTableInstance->runObjTabLastIndx=0;
557 /***********************************************************************
558 * RunningObjectTable_UnInitialize
560 HRESULT WINAPI RunningObjectTableImpl_UnInitialize()
564 if (runningObjectTableInstance==NULL)
567 RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance);
569 RunningObjectTableImpl_Destroy();