- AddRef type info stored in StdDispatch.
[wine] / dlls / ole32 / moniker.c
1 /*
2  *      Monikers
3  *
4  *      Copyright 1998  Marcus Meissner
5  *      Copyright 1999  Noomen Hamza
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include <assert.h>
23 #include <string.h>
24
25 #include "winerror.h"
26 #include "winbase.h"
27 #include "wtypes.h"
28 #include "wine/debug.h"
29 #include "ole2.h"
30
31 #include "compobj_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(ole);
34
35 #define  BLOCK_TAB_SIZE 20 /* represent the first size table and it's increment block size */
36
37 /* define the structure of the running object table elements */
38 typedef struct RunObject{
39
40     IUnknown*  pObj; /* points on a running object*/
41     IMoniker*  pmkObj; /* points on a moniker who identifies this object */
42     FILETIME   lastModifObj;
43     DWORD      identRegObj; /* registration key relative to this object */
44     DWORD      regTypeObj; /* registration type : strong or weak */
45 }RunObject;
46
47 /* define the RunningObjectTableImpl structure */
48 typedef struct RunningObjectTableImpl{
49
50     ICOM_VFIELD(IRunningObjectTable);
51     ULONG      ref;
52
53     RunObject* runObjTab;            /* pointer to the first object in the table       */
54     DWORD      runObjTabSize;       /* current table size                            */
55     DWORD      runObjTabLastIndx;  /* first free index element in the table.        */
56     DWORD      runObjTabRegister; /* registration key of the next registered object */
57
58 } RunningObjectTableImpl;
59
60 RunningObjectTableImpl* runningObjectTableInstance=0;
61
62 /* IRunningObjectTable prototype functions : */
63 /* IUnknown functions*/
64 static HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject);
65 static ULONG   WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface);
66 static ULONG   WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface);
67 /* IRunningObjectTable functions */
68 static HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,IUnknown* punkObject,IMoniker* pmkObjectName,DWORD* pdwRegister);
69 static HRESULT WINAPI RunningObjectTableImpl_Revoke(IRunningObjectTable* iface, DWORD dwRegister);
70 static HRESULT WINAPI RunningObjectTableImpl_IsRunning(IRunningObjectTable* iface, IMoniker* pmkObjectName);
71 static HRESULT WINAPI RunningObjectTableImpl_GetObject(IRunningObjectTable* iface, IMoniker* pmkObjectName,IUnknown** ppunkObject);
72 static HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, DWORD dwRegister,FILETIME* pfiletime);
73 static HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, IMoniker* pmkObjectName,FILETIME* pfiletime);
74 static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker** ppenumMoniker);
75 /* Local functions*/
76 HRESULT WINAPI RunningObjectTableImpl_Initialize();
77 HRESULT WINAPI RunningObjectTableImpl_UnInitialize();
78 HRESULT WINAPI RunningObjectTableImpl_Destroy();
79 HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,DWORD identReg,IMoniker* pmk,DWORD *indx);
80
81 /* Virtual function table for the IRunningObjectTable class. */
82 static ICOM_VTABLE(IRunningObjectTable) VT_RunningObjectTableImpl =
83 {
84     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
85     RunningObjectTableImpl_QueryInterface,
86     RunningObjectTableImpl_AddRef,
87     RunningObjectTableImpl_Release,
88     RunningObjectTableImpl_Register,
89     RunningObjectTableImpl_Revoke,
90     RunningObjectTableImpl_IsRunning,
91     RunningObjectTableImpl_GetObject,
92     RunningObjectTableImpl_NoteChangeTime,
93     RunningObjectTableImpl_GetTimeOfLastChange,
94     RunningObjectTableImpl_EnumRunning
95 };
96
97 /***********************************************************************
98  *        RunningObjectTable_QueryInterface
99  */
100 HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject)
101 {
102     ICOM_THIS(RunningObjectTableImpl,iface);
103
104     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
105
106     /* validate arguments */
107     if (This==0)
108         return CO_E_NOTINITIALIZED;
109
110     if (ppvObject==0)
111         return E_INVALIDARG;
112
113     *ppvObject = 0;
114
115     if (IsEqualIID(&IID_IUnknown, riid))
116         *ppvObject = (IRunningObjectTable*)This;
117     else
118         if (IsEqualIID(&IID_IRunningObjectTable, riid))
119             *ppvObject = (IRunningObjectTable*)This;
120
121     if ((*ppvObject)==0)
122         return E_NOINTERFACE;
123
124     RunningObjectTableImpl_AddRef(iface);
125
126     return S_OK;
127 }
128
129 /***********************************************************************
130  *        RunningObjectTable_AddRef
131  */
132 ULONG   WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
133 {
134     ICOM_THIS(RunningObjectTableImpl,iface);
135
136     TRACE("(%p)\n",This);
137
138     return ++(This->ref);
139 }
140
141 /***********************************************************************
142  *        RunningObjectTable_Initialize
143  */
144 HRESULT WINAPI RunningObjectTableImpl_Destroy()
145 {
146     TRACE("()\n");
147
148     if (runningObjectTableInstance==NULL)
149         return E_INVALIDARG;
150
151     /* free the ROT table memory */
152     HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab);
153
154     /* free the ROT structure memory */
155     HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
156
157     return S_OK;
158 }
159
160 /***********************************************************************
161  *        RunningObjectTable_Release
162  */
163 ULONG   WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface)
164 {
165     DWORD i;
166     ICOM_THIS(RunningObjectTableImpl,iface);
167
168     TRACE("(%p)\n",This);
169
170     This->ref--;
171
172     /* unitialize ROT structure if there's no more reference to it*/
173     if (This->ref==0){
174
175         /* release all registered objects */
176         for(i=0;i<This->runObjTabLastIndx;i++)
177         {
178             if (( This->runObjTab[i].regTypeObj &  ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0)
179                 IUnknown_Release(This->runObjTab[i].pObj);
180
181             IMoniker_Release(This->runObjTab[i].pmkObj);
182         }
183        /*  RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
184         *  when RunningObjectTableImpl_UnInitialize function is called
185         */
186
187         /* there's no more elements in the table */
188         This->runObjTabRegister=0;
189         This->runObjTabLastIndx=0;
190
191         return 0;
192     }
193
194     return This->ref;
195 }
196
197 /***********************************************************************
198  *        RunningObjectTable_Initialize
199  */
200 HRESULT WINAPI RunningObjectTableImpl_Initialize()
201 {
202     TRACE("()\n");
203
204     /* create the unique instance of the RunningObjectTableImpl structure */
205     runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));
206
207     if (runningObjectTableInstance == 0)
208         return E_OUTOFMEMORY;
209
210     /* initialize the virtual table function */
211     runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl;
212
213     /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */
214     /* the ROT referred many times not in the same time (all the objects in the ROT will  */
215     /* be removed every time the ROT is removed ) */
216     runningObjectTableInstance->ref = 1;
217
218     /* allocate space memory for the table which contains all the running objects */
219     runningObjectTableInstance->runObjTab = HeapAlloc(GetProcessHeap(), 0, sizeof(RunObject[BLOCK_TAB_SIZE]));
220
221     if (runningObjectTableInstance->runObjTab == NULL)
222         return E_OUTOFMEMORY;
223
224     runningObjectTableInstance->runObjTabSize=BLOCK_TAB_SIZE;
225     runningObjectTableInstance->runObjTabRegister=1;
226     runningObjectTableInstance->runObjTabLastIndx=0;
227
228     return S_OK;
229 }
230
231 /***********************************************************************
232  *        RunningObjectTable_UnInitialize
233  */
234 HRESULT WINAPI RunningObjectTableImpl_UnInitialize()
235 {
236     TRACE("()\n");
237
238     if (runningObjectTableInstance==NULL)
239         return E_POINTER;
240
241     RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance);
242
243     RunningObjectTableImpl_Destroy();
244
245     return S_OK;
246 }
247
248 /***********************************************************************
249  *        RunningObjectTable_Register
250  */
251 HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface,
252                                                DWORD grfFlags,           /* Registration options */
253                                                IUnknown *punkObject,     /* Pointer to the object being registered */
254                                                IMoniker *pmkObjectName,  /* Pointer to the moniker of the object being registered */
255                                                DWORD *pdwRegister)       /* Pointer to the value identifying the  registration */
256 {
257     HRESULT res=S_OK;
258     ICOM_THIS(RunningObjectTableImpl,iface);
259
260     TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
261
262     /* there's only two types of register : strong and or weak registration (only one must be passed on parameter) */
263     if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
264          (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ||  (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
265          (grfFlags) )
266         return E_INVALIDARG;
267
268     if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
269         return E_INVALIDARG;
270
271     /* verify if the object to be registered was registered before */
272     if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL)==S_OK)
273         res = MK_S_MONIKERALREADYREGISTERED;
274
275     /* put the new registered object in the first free element in the table */
276     This->runObjTab[This->runObjTabLastIndx].pObj = punkObject;
277     This->runObjTab[This->runObjTabLastIndx].pmkObj = pmkObjectName;
278     This->runObjTab[This->runObjTabLastIndx].regTypeObj = grfFlags;
279     This->runObjTab[This->runObjTabLastIndx].identRegObj = This->runObjTabRegister;
280     CoFileTimeNow(&(This->runObjTab[This->runObjTabLastIndx].lastModifObj));
281
282     /* gives a registration identifier to the registered object*/
283     (*pdwRegister)= This->runObjTabRegister;
284
285     if (This->runObjTabRegister == 0xFFFFFFFF){
286
287         FIXME("runObjTabRegister: %ld is out of data limite \n",This->runObjTabRegister);
288         return E_FAIL;
289     }
290     This->runObjTabRegister++;
291     This->runObjTabLastIndx++;
292
293     if (This->runObjTabLastIndx == This->runObjTabSize){ /* table is full ! so it must be resized */
294
295         This->runObjTabSize+=BLOCK_TAB_SIZE; /* newsize table */
296         This->runObjTab=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->runObjTab,
297                         This->runObjTabSize * sizeof(RunObject));
298         if (!This->runObjTab)
299             return E_OUTOFMEMORY;
300     }
301     /* add a reference to the object in the strong registration case */
302     if ((grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) !=0 )
303         IUnknown_AddRef(punkObject);
304
305     IMoniker_AddRef(pmkObjectName);
306
307     return res;
308 }
309
310 /***********************************************************************
311  *        RunningObjectTable_Revoke
312  */
313 HRESULT WINAPI RunningObjectTableImpl_Revoke(  IRunningObjectTable* iface,
314                                                DWORD dwRegister)  /* Value identifying registration to be revoked*/
315 {
316
317     DWORD index,j;
318     ICOM_THIS(RunningObjectTableImpl,iface);
319
320     TRACE("(%p,%ld)\n",This,dwRegister);
321
322     /* verify if the object to be revoked was registered before or not */
323     if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
324
325         return E_INVALIDARG;
326
327     /* release the object if it was registered with a strong registrantion option */
328     if ((This->runObjTab[index].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE)!=0)
329         IUnknown_Release(This->runObjTab[index].pObj);
330
331     IMoniker_Release(This->runObjTab[index].pmkObj);
332
333     /* remove the object from the table */
334     for(j=index; j<This->runObjTabLastIndx-1; j++)
335         This->runObjTab[j]= This->runObjTab[j+1];
336
337     This->runObjTabLastIndx--;
338
339     return S_OK;
340 }
341
342 /***********************************************************************
343  *        RunningObjectTable_IsRunning
344  */
345 HRESULT WINAPI RunningObjectTableImpl_IsRunning(  IRunningObjectTable* iface,
346                                                   IMoniker *pmkObjectName)  /* Pointer to the moniker of the object whose status is desired */
347 {
348     ICOM_THIS(RunningObjectTableImpl,iface);
349
350     TRACE("(%p,%p)\n",This,pmkObjectName);
351
352     return RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL);
353 }
354
355 /***********************************************************************
356  *        RunningObjectTable_GetObject
357  */
358 HRESULT WINAPI RunningObjectTableImpl_GetObject(  IRunningObjectTable* iface,
359                                                   IMoniker *pmkObjectName,/* Pointer to the moniker on the object */
360                                                   IUnknown **ppunkObject) /* Address of output variable that receives the IUnknown interface pointer */
361 {
362     DWORD index;
363     ICOM_THIS(RunningObjectTableImpl,iface);
364
365     TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
366
367     if (ppunkObject==NULL)
368         return E_POINTER;
369
370     *ppunkObject=0;
371
372     /* verify if the object was registered before or not */
373     if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE)
374         return MK_E_UNAVAILABLE;
375
376     /* add a reference to the object then set output object argument */
377     IUnknown_AddRef(This->runObjTab[index].pObj);
378     *ppunkObject=This->runObjTab[index].pObj;
379
380     return S_OK;
381 }
382
383 /***********************************************************************
384  *        RunningObjectTable_NoteChangeTime
385  */
386 HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
387                                                      DWORD dwRegister,  /* Value identifying registration being updated */
388                                                      FILETIME *pfiletime) /* Pointer to structure containing object's last change time */
389 {
390     DWORD index=-1;
391     ICOM_THIS(RunningObjectTableImpl,iface);
392
393     TRACE("(%p,%ld,%p)\n",This,dwRegister,pfiletime);
394
395     /* verify if the object to be changed was registered before or not */
396     if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
397         return E_INVALIDARG;
398
399     /* set the new value of the last time change */
400     This->runObjTab[index].lastModifObj= (*pfiletime);
401
402     return S_OK;
403 }
404
405 /***********************************************************************
406  *        RunningObjectTable_GetTimeOfLastChange
407  */
408 HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
409                                                           IMoniker *pmkObjectName,  /* Pointer to moniker on the object whose status is desired */
410                                                           FILETIME *pfiletime)       /* Pointer to structure that receives object's last change time */
411 {
412     DWORD index=-1;
413     ICOM_THIS(RunningObjectTableImpl,iface);
414
415     TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
416
417     if (pmkObjectName==NULL || pfiletime==NULL)
418         return E_INVALIDARG;
419
420     /* verify if the object was registered before or not */
421     if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE)
422         return MK_E_UNAVAILABLE;
423
424     (*pfiletime)= This->runObjTab[index].lastModifObj;
425
426     return S_OK;
427 }
428
429 /***********************************************************************
430  *        RunningObjectTable_EnumRunning
431  */
432 HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
433                                                   IEnumMoniker **ppenumMoniker) /* Address of output variable that receives the IEnumMoniker interface pointer */
434 {
435     FIXME("(%p,%p) needs the IEnumMoniker implementation  \n",iface,ppenumMoniker);
436     return E_NOTIMPL;
437 }
438
439 /***********************************************************************
440  *        GetObjectIndex
441  */
442 HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,
443                                                      DWORD identReg,
444                                                      IMoniker* pmk,
445                                                      DWORD *indx)
446 {
447
448     DWORD i;
449
450     TRACE("(%p,%ld,%p,%p)\n",This,identReg,pmk,indx);
451
452     if (pmk!=NULL)
453         /* search object identified by a moniker */
454         for(i=0 ; (i < This->runObjTabLastIndx) &&(!IMoniker_IsEqual(This->runObjTab[i].pmkObj,pmk)==S_OK);i++);
455     else
456         /* search object identified by a register identifier */
457         for(i=0;((i<This->runObjTabLastIndx)&&(This->runObjTab[i].identRegObj!=identReg));i++);
458
459     if (i==This->runObjTabLastIndx)  return S_FALSE;
460
461     if (indx != NULL)  *indx=i;
462
463     return S_OK;
464 }
465
466 /******************************************************************************
467  *              GetRunningObjectTable   [OLE2.30]
468  */
469 HRESULT WINAPI GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
470 {
471         FIXME("(%ld,%p),stub!\n",reserved,pprot);
472     return E_NOTIMPL;
473 }
474
475 /***********************************************************************
476  *           GetRunningObjectTable (OLE32.73)
477  */
478 HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
479 {
480     IID riid=IID_IRunningObjectTable;
481     HRESULT res;
482
483     TRACE("()\n");
484
485     if (reserved!=0)
486         return E_UNEXPECTED;
487
488     if(runningObjectTableInstance==NULL)
489         return CO_E_NOTINITIALIZED;
490
491     res = RunningObjectTableImpl_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot);
492
493     return res;
494 }
495
496 /******************************************************************************
497  *              OleRun        [OLE32.123]
498  */
499 HRESULT WINAPI OleRun(LPUNKNOWN pUnknown)
500 {
501   IRunnableObject       *runable;
502   ICOM_THIS(IRunnableObject,pUnknown);
503   LRESULT               ret;
504
505   ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable);
506   if (ret)
507         return 0; /* Appears to return no error. */
508   ret  = IRunnableObject_Run(runable,NULL);
509   IRunnableObject_Release(runable);
510   return ret;
511 }
512
513 /******************************************************************************
514  *              MkParseDisplayName        [OLE32.81]
515  */
516 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
517                                 LPDWORD pchEaten, LPMONIKER *ppmk)
518 {
519     FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk);
520     if (!(IsValidInterface((LPUNKNOWN) pbc)))
521         return E_INVALIDARG;
522
523     return MK_E_SYNTAX;
524 }