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