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