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.
39 #include "wine/debug.h"
42 #include "compobj_private.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
46 #define BLOCK_TAB_SIZE 20 /* represent the first size table and it's increment block size */
48 /* define the structure of the running object table elements */
49 typedef struct RunObject
{
51 IUnknown
* pObj
; /* points on a running object*/
52 IMoniker
* pmkObj
; /* points on a moniker who identifies this object */
53 FILETIME lastModifObj
;
54 DWORD identRegObj
; /* registration key relative to this object */
55 DWORD regTypeObj
; /* registration type : strong or weak */
58 /* define the RunningObjectTableImpl structure */
59 typedef struct RunningObjectTableImpl
{
61 ICOM_VFIELD(IRunningObjectTable
);
64 RunObject
* runObjTab
; /* pointer to the first object in the table */
65 DWORD runObjTabSize
; /* current table size */
66 DWORD runObjTabLastIndx
; /* first free index element in the table. */
67 DWORD runObjTabRegister
; /* registration key of the next registered object */
69 } RunningObjectTableImpl
;
71 RunningObjectTableImpl
* runningObjectTableInstance
=0;
73 /* IRunningObjectTable prototype functions : */
74 /* IUnknown functions*/
75 static HRESULT WINAPI
RunningObjectTableImpl_QueryInterface(IRunningObjectTable
* iface
,REFIID riid
,void** ppvObject
);
76 static ULONG WINAPI
RunningObjectTableImpl_AddRef(IRunningObjectTable
* iface
);
77 static ULONG WINAPI
RunningObjectTableImpl_Release(IRunningObjectTable
* iface
);
78 /* IRunningObjectTable functions */
79 static HRESULT WINAPI
RunningObjectTableImpl_Register(IRunningObjectTable
* iface
, DWORD grfFlags
,IUnknown
* punkObject
,IMoniker
* pmkObjectName
,DWORD
* pdwRegister
);
80 static HRESULT WINAPI
RunningObjectTableImpl_Revoke(IRunningObjectTable
* iface
, DWORD dwRegister
);
81 static HRESULT WINAPI
RunningObjectTableImpl_IsRunning(IRunningObjectTable
* iface
, IMoniker
* pmkObjectName
);
82 static HRESULT WINAPI
RunningObjectTableImpl_GetObject(IRunningObjectTable
* iface
, IMoniker
* pmkObjectName
,IUnknown
** ppunkObject
);
83 static HRESULT WINAPI
RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable
* iface
, DWORD dwRegister
,FILETIME
* pfiletime
);
84 static HRESULT WINAPI
RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable
* iface
, IMoniker
* pmkObjectName
,FILETIME
* pfiletime
);
85 static HRESULT WINAPI
RunningObjectTableImpl_EnumRunning(IRunningObjectTable
* iface
, IEnumMoniker
** ppenumMoniker
);
87 HRESULT WINAPI
RunningObjectTableImpl_Initialize();
88 HRESULT WINAPI
RunningObjectTableImpl_UnInitialize();
89 HRESULT WINAPI
RunningObjectTableImpl_Destroy();
90 HRESULT WINAPI
RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl
* This
,DWORD identReg
,IMoniker
* pmk
,DWORD
*indx
);
92 /* Virtual function table for the IRunningObjectTable class. */
93 static ICOM_VTABLE(IRunningObjectTable
) VT_RunningObjectTableImpl
=
95 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
96 RunningObjectTableImpl_QueryInterface
,
97 RunningObjectTableImpl_AddRef
,
98 RunningObjectTableImpl_Release
,
99 RunningObjectTableImpl_Register
,
100 RunningObjectTableImpl_Revoke
,
101 RunningObjectTableImpl_IsRunning
,
102 RunningObjectTableImpl_GetObject
,
103 RunningObjectTableImpl_NoteChangeTime
,
104 RunningObjectTableImpl_GetTimeOfLastChange
,
105 RunningObjectTableImpl_EnumRunning
108 /***********************************************************************
109 * RunningObjectTable_QueryInterface
111 HRESULT WINAPI
RunningObjectTableImpl_QueryInterface(IRunningObjectTable
* iface
,REFIID riid
,void** ppvObject
)
113 ICOM_THIS(RunningObjectTableImpl
,iface
);
115 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
117 /* validate arguments */
119 return CO_E_NOTINITIALIZED
;
126 if (IsEqualIID(&IID_IUnknown
, riid
))
127 *ppvObject
= (IRunningObjectTable
*)This
;
129 if (IsEqualIID(&IID_IRunningObjectTable
, riid
))
130 *ppvObject
= (IRunningObjectTable
*)This
;
133 return E_NOINTERFACE
;
135 RunningObjectTableImpl_AddRef(iface
);
140 /***********************************************************************
141 * RunningObjectTable_AddRef
143 ULONG WINAPI
RunningObjectTableImpl_AddRef(IRunningObjectTable
* iface
)
145 ICOM_THIS(RunningObjectTableImpl
,iface
);
147 TRACE("(%p)\n",This
);
149 return ++(This
->ref
);
152 /***********************************************************************
153 * RunningObjectTable_Initialize
155 HRESULT WINAPI
RunningObjectTableImpl_Destroy()
159 if (runningObjectTableInstance
==NULL
)
162 /* free the ROT table memory */
163 HeapFree(GetProcessHeap(),0,runningObjectTableInstance
->runObjTab
);
165 /* free the ROT structure memory */
166 HeapFree(GetProcessHeap(),0,runningObjectTableInstance
);
171 /***********************************************************************
172 * RunningObjectTable_Release
174 ULONG WINAPI
RunningObjectTableImpl_Release(IRunningObjectTable
* iface
)
177 ICOM_THIS(RunningObjectTableImpl
,iface
);
179 TRACE("(%p)\n",This
);
183 /* unitialize ROT structure if there's no more reference to it*/
186 /* release all registered objects */
187 for(i
=0;i
<This
->runObjTabLastIndx
;i
++)
189 if (( This
->runObjTab
[i
].regTypeObj
& ROTFLAGS_REGISTRATIONKEEPSALIVE
) != 0)
190 IUnknown_Release(This
->runObjTab
[i
].pObj
);
192 IMoniker_Release(This
->runObjTab
[i
].pmkObj
);
194 /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
195 * when RunningObjectTableImpl_UnInitialize function is called
198 /* there's no more elements in the table */
199 This
->runObjTabRegister
=0;
200 This
->runObjTabLastIndx
=0;
208 /***********************************************************************
209 * RunningObjectTable_Initialize
211 HRESULT WINAPI
RunningObjectTableImpl_Initialize()
215 /* create the unique instance of the RunningObjectTableImpl structure */
216 runningObjectTableInstance
= HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl
));
218 if (runningObjectTableInstance
== 0)
219 return E_OUTOFMEMORY
;
221 /* initialize the virtual table function */
222 runningObjectTableInstance
->lpVtbl
= &VT_RunningObjectTableImpl
;
224 /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */
225 /* the ROT referred many times not in the same time (all the objects in the ROT will */
226 /* be removed every time the ROT is removed ) */
227 runningObjectTableInstance
->ref
= 1;
229 /* allocate space memory for the table which contains all the running objects */
230 runningObjectTableInstance
->runObjTab
= HeapAlloc(GetProcessHeap(), 0, sizeof(RunObject
[BLOCK_TAB_SIZE
]));
232 if (runningObjectTableInstance
->runObjTab
== NULL
)
233 return E_OUTOFMEMORY
;
235 runningObjectTableInstance
->runObjTabSize
=BLOCK_TAB_SIZE
;
236 runningObjectTableInstance
->runObjTabRegister
=1;
237 runningObjectTableInstance
->runObjTabLastIndx
=0;
242 /***********************************************************************
243 * RunningObjectTable_UnInitialize
245 HRESULT WINAPI
RunningObjectTableImpl_UnInitialize()
249 if (runningObjectTableInstance
==NULL
)
252 RunningObjectTableImpl_Release((IRunningObjectTable
*)runningObjectTableInstance
);
254 RunningObjectTableImpl_Destroy();
259 /***********************************************************************
260 * RunningObjectTable_Register
262 HRESULT WINAPI
RunningObjectTableImpl_Register(IRunningObjectTable
* iface
,
263 DWORD grfFlags
, /* Registration options */
264 IUnknown
*punkObject
, /* Pointer to the object being registered */
265 IMoniker
*pmkObjectName
, /* Pointer to the moniker of the object being registered */
266 DWORD
*pdwRegister
) /* Pointer to the value identifying the registration */
269 ICOM_THIS(RunningObjectTableImpl
,iface
);
271 TRACE("(%p,%ld,%p,%p,%p)\n",This
,grfFlags
,punkObject
,pmkObjectName
,pdwRegister
);
273 /* there's only two types of register : strong and or weak registration (only one must be passed on parameter) */
274 if ( ( (grfFlags
& ROTFLAGS_REGISTRATIONKEEPSALIVE
) || !(grfFlags
& ROTFLAGS_ALLOWANYCLIENT
)) &&
275 (!(grfFlags
& ROTFLAGS_REGISTRATIONKEEPSALIVE
) || (grfFlags
& ROTFLAGS_ALLOWANYCLIENT
)) &&
279 if (punkObject
==NULL
|| pmkObjectName
==NULL
|| pdwRegister
==NULL
)
282 /* verify if the object to be registered was registered before */
283 if (RunningObjectTableImpl_GetObjectIndex(This
,-1,pmkObjectName
,NULL
)==S_OK
)
284 res
= MK_S_MONIKERALREADYREGISTERED
;
286 /* put the new registered object in the first free element in the table */
287 This
->runObjTab
[This
->runObjTabLastIndx
].pObj
= punkObject
;
288 This
->runObjTab
[This
->runObjTabLastIndx
].pmkObj
= pmkObjectName
;
289 This
->runObjTab
[This
->runObjTabLastIndx
].regTypeObj
= grfFlags
;
290 This
->runObjTab
[This
->runObjTabLastIndx
].identRegObj
= This
->runObjTabRegister
;
291 CoFileTimeNow(&(This
->runObjTab
[This
->runObjTabLastIndx
].lastModifObj
));
293 /* gives a registration identifier to the registered object*/
294 (*pdwRegister
)= This
->runObjTabRegister
;
296 if (This
->runObjTabRegister
== 0xFFFFFFFF){
298 FIXME("runObjTabRegister: %ld is out of data limite \n",This
->runObjTabRegister
);
301 This
->runObjTabRegister
++;
302 This
->runObjTabLastIndx
++;
304 if (This
->runObjTabLastIndx
== This
->runObjTabSize
){ /* table is full ! so it must be resized */
306 This
->runObjTabSize
+=BLOCK_TAB_SIZE
; /* newsize table */
307 This
->runObjTab
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,This
->runObjTab
,
308 This
->runObjTabSize
* sizeof(RunObject
));
309 if (!This
->runObjTab
)
310 return E_OUTOFMEMORY
;
312 /* add a reference to the object in the strong registration case */
313 if ((grfFlags
& ROTFLAGS_REGISTRATIONKEEPSALIVE
) !=0 ) {
314 TRACE("strong registration, reffing %p\n", punkObject
);
315 /* this is wrong; we should always add a reference to the object */
316 IUnknown_AddRef(punkObject
);
319 IMoniker_AddRef(pmkObjectName
);
324 /***********************************************************************
325 * RunningObjectTable_Revoke
327 HRESULT WINAPI
RunningObjectTableImpl_Revoke( IRunningObjectTable
* iface
,
328 DWORD dwRegister
) /* Value identifying registration to be revoked*/
332 ICOM_THIS(RunningObjectTableImpl
,iface
);
334 TRACE("(%p,%ld)\n",This
,dwRegister
);
336 /* verify if the object to be revoked was registered before or not */
337 if (RunningObjectTableImpl_GetObjectIndex(This
,dwRegister
,NULL
,&index
)==S_FALSE
)
341 /* release the object if it was registered with a strong registrantion option */
342 if ((This
->runObjTab
[index
].regTypeObj
& ROTFLAGS_REGISTRATIONKEEPSALIVE
)!=0) {
343 TRACE("releasing %p\n", This
->runObjTab
[index
].pObj
);
344 /* this is also wrong; we should always release the object (see above) */
345 IUnknown_Release(This
->runObjTab
[index
].pObj
);
348 IMoniker_Release(This
->runObjTab
[index
].pmkObj
);
350 /* remove the object from the table */
351 for(j
=index
; j
<This
->runObjTabLastIndx
-1; j
++)
352 This
->runObjTab
[j
]= This
->runObjTab
[j
+1];
354 This
->runObjTabLastIndx
--;
359 /***********************************************************************
360 * RunningObjectTable_IsRunning
362 HRESULT WINAPI
RunningObjectTableImpl_IsRunning( IRunningObjectTable
* iface
,
363 IMoniker
*pmkObjectName
) /* Pointer to the moniker of the object whose status is desired */
365 ICOM_THIS(RunningObjectTableImpl
,iface
);
367 TRACE("(%p,%p)\n",This
,pmkObjectName
);
369 return RunningObjectTableImpl_GetObjectIndex(This
,-1,pmkObjectName
,NULL
);
372 /***********************************************************************
373 * RunningObjectTable_GetObject
375 HRESULT WINAPI
RunningObjectTableImpl_GetObject( IRunningObjectTable
* iface
,
376 IMoniker
*pmkObjectName
,/* Pointer to the moniker on the object */
377 IUnknown
**ppunkObject
) /* Address of output variable that receives the IUnknown interface pointer */
380 ICOM_THIS(RunningObjectTableImpl
,iface
);
382 TRACE("(%p,%p,%p)\n",This
,pmkObjectName
,ppunkObject
);
384 if (ppunkObject
==NULL
)
389 /* verify if the object was registered before or not */
390 if (RunningObjectTableImpl_GetObjectIndex(This
,-1,pmkObjectName
,&index
)==S_FALSE
) {
391 WARN("Moniker unavailable - needs to work interprocess?\n");
392 return MK_E_UNAVAILABLE
;
395 /* add a reference to the object then set output object argument */
396 IUnknown_AddRef(This
->runObjTab
[index
].pObj
);
397 *ppunkObject
=This
->runObjTab
[index
].pObj
;
402 /***********************************************************************
403 * RunningObjectTable_NoteChangeTime
405 HRESULT WINAPI
RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable
* iface
,
406 DWORD dwRegister
, /* Value identifying registration being updated */
407 FILETIME
*pfiletime
) /* Pointer to structure containing object's last change time */
410 ICOM_THIS(RunningObjectTableImpl
,iface
);
412 TRACE("(%p,%ld,%p)\n",This
,dwRegister
,pfiletime
);
414 /* verify if the object to be changed was registered before or not */
415 if (RunningObjectTableImpl_GetObjectIndex(This
,dwRegister
,NULL
,&index
)==S_FALSE
)
418 /* set the new value of the last time change */
419 This
->runObjTab
[index
].lastModifObj
= (*pfiletime
);
424 /***********************************************************************
425 * RunningObjectTable_GetTimeOfLastChange
427 HRESULT WINAPI
RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable
* iface
,
428 IMoniker
*pmkObjectName
, /* Pointer to moniker on the object whose status is desired */
429 FILETIME
*pfiletime
) /* Pointer to structure that receives object's last change time */
432 ICOM_THIS(RunningObjectTableImpl
,iface
);
434 TRACE("(%p,%p,%p)\n",This
,pmkObjectName
,pfiletime
);
436 if (pmkObjectName
==NULL
|| pfiletime
==NULL
)
439 /* verify if the object was registered before or not */
440 if (RunningObjectTableImpl_GetObjectIndex(This
,-1,pmkObjectName
,&index
)==S_FALSE
)
441 return MK_E_UNAVAILABLE
;
443 (*pfiletime
)= This
->runObjTab
[index
].lastModifObj
;
448 /***********************************************************************
449 * RunningObjectTable_EnumRunning
451 HRESULT WINAPI
RunningObjectTableImpl_EnumRunning(IRunningObjectTable
* iface
,
452 IEnumMoniker
**ppenumMoniker
) /* Address of output variable that receives the IEnumMoniker interface pointer */
454 FIXME("(%p,%p) needs the IEnumMoniker implementation \n",iface
,ppenumMoniker
);
458 /***********************************************************************
461 HRESULT WINAPI
RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl
* This
,
469 TRACE("(%p,%ld,%p,%p)\n",This
,identReg
,pmk
,indx
);
472 /* search object identified by a moniker */
473 for(i
=0 ; (i
< This
->runObjTabLastIndx
) &&(!IMoniker_IsEqual(This
->runObjTab
[i
].pmkObj
,pmk
)==S_OK
);i
++);
475 /* search object identified by a register identifier */
476 for(i
=0;((i
<This
->runObjTabLastIndx
)&&(This
->runObjTab
[i
].identRegObj
!=identReg
));i
++);
478 if (i
==This
->runObjTabLastIndx
) return S_FALSE
;
480 if (indx
!= NULL
) *indx
=i
;
485 /******************************************************************************
486 * GetRunningObjectTable (OLE2.30)
488 HRESULT WINAPI
GetRunningObjectTable16(DWORD reserved
, LPRUNNINGOBJECTTABLE
*pprot
)
490 FIXME("(%ld,%p),stub!\n",reserved
,pprot
);
494 /***********************************************************************
495 * GetRunningObjectTable (OLE32.@)
497 HRESULT WINAPI
GetRunningObjectTable(DWORD reserved
, LPRUNNINGOBJECTTABLE
*pprot
)
499 IID riid
=IID_IRunningObjectTable
;
507 if(runningObjectTableInstance
==NULL
)
508 return CO_E_NOTINITIALIZED
;
510 res
= RunningObjectTableImpl_QueryInterface((IRunningObjectTable
*)runningObjectTableInstance
,&riid
,(void**)pprot
);
515 /******************************************************************************
518 HRESULT WINAPI
OleRun(LPUNKNOWN pUnknown
)
520 IRunnableObject
*runable
;
521 ICOM_THIS(IRunnableObject
,pUnknown
);
524 ret
= IRunnableObject_QueryInterface(This
,&IID_IRunnableObject
,(LPVOID
*)&runable
);
526 return 0; /* Appears to return no error. */
527 ret
= IRunnableObject_Run(runable
,NULL
);
528 IRunnableObject_Release(runable
);
532 /******************************************************************************
533 * MkParseDisplayName [OLE32.@]
535 HRESULT WINAPI
MkParseDisplayName(LPBC pbc
, LPCOLESTR szUserName
,
536 LPDWORD pchEaten
, LPMONIKER
*ppmk
)
538 FIXME("(%p, %s, %p, %p): stub.\n", pbc
, debugstr_w(szUserName
), pchEaten
, *ppmk
);
539 if (!(IsValidInterface((LPUNKNOWN
) pbc
)))
545 /******************************************************************************
546 * CreateClassMoniker [OLE32.@]
548 HRESULT WINAPI
CreateClassMoniker(REFCLSID rclsid
, IMoniker
** ppmk
)
550 FIXME("%s\n", debugstr_guid( rclsid
));