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