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