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