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