Implement A->W call for GetNamedSecurityInfo.
[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 #include "winerror.h"
35 #include "windef.h"
36 #include "winbase.h"
37 #include "winuser.h"
38 #include "wtypes.h"
39 #include "wine/debug.h"
40 #include "ole2.h"
41
42 #include "compobj_private.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(ole);
45
46 #define  BLOCK_TAB_SIZE 20 /* represent the first size table and it's increment block size */
47
48 /* define the structure of the running object table elements */
49 typedef struct RunObject{
50
51     IUnknown*  pObj; /* points on a running object*/
52     IMoniker*  pmkObj; /* points on a moniker who identifies this object */
53     FILETIME   lastModifObj;
54     DWORD      identRegObj; /* registration key relative to this object */
55     DWORD      regTypeObj; /* registration type : strong or weak */
56 }RunObject;
57
58 /* define the RunningObjectTableImpl structure */
59 typedef struct RunningObjectTableImpl{
60
61     ICOM_VFIELD(IRunningObjectTable);
62     ULONG      ref;
63
64     RunObject* runObjTab;            /* pointer to the first object in the table       */
65     DWORD      runObjTabSize;       /* current table size                            */
66     DWORD      runObjTabLastIndx;  /* first free index element in the table.        */
67     DWORD      runObjTabRegister; /* registration key of the next registered object */
68
69 } RunningObjectTableImpl;
70
71 RunningObjectTableImpl* runningObjectTableInstance=0;
72
73 /* IRunningObjectTable prototype functions : */
74 /* IUnknown functions*/
75 static HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject);
76 static ULONG   WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface);
77 static ULONG   WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface);
78 /* IRunningObjectTable functions */
79 static HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,IUnknown* punkObject,IMoniker* pmkObjectName,DWORD* pdwRegister);
80 static HRESULT WINAPI RunningObjectTableImpl_Revoke(IRunningObjectTable* iface, DWORD dwRegister);
81 static HRESULT WINAPI RunningObjectTableImpl_IsRunning(IRunningObjectTable* iface, IMoniker* pmkObjectName);
82 static HRESULT WINAPI RunningObjectTableImpl_GetObject(IRunningObjectTable* iface, IMoniker* pmkObjectName,IUnknown** ppunkObject);
83 static HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, DWORD dwRegister,FILETIME* pfiletime);
84 static HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, IMoniker* pmkObjectName,FILETIME* pfiletime);
85 static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker** ppenumMoniker);
86 /* Local functions*/
87 HRESULT WINAPI RunningObjectTableImpl_Initialize();
88 HRESULT WINAPI RunningObjectTableImpl_UnInitialize();
89 HRESULT WINAPI RunningObjectTableImpl_Destroy();
90 HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,DWORD identReg,IMoniker* pmk,DWORD *indx);
91
92 /* Virtual function table for the IRunningObjectTable class. */
93 static ICOM_VTABLE(IRunningObjectTable) VT_RunningObjectTableImpl =
94 {
95     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
96     RunningObjectTableImpl_QueryInterface,
97     RunningObjectTableImpl_AddRef,
98     RunningObjectTableImpl_Release,
99     RunningObjectTableImpl_Register,
100     RunningObjectTableImpl_Revoke,
101     RunningObjectTableImpl_IsRunning,
102     RunningObjectTableImpl_GetObject,
103     RunningObjectTableImpl_NoteChangeTime,
104     RunningObjectTableImpl_GetTimeOfLastChange,
105     RunningObjectTableImpl_EnumRunning
106 };
107
108 /***********************************************************************
109  *        RunningObjectTable_QueryInterface
110  */
111 HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject)
112 {
113     ICOM_THIS(RunningObjectTableImpl,iface);
114
115     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
116
117     /* validate arguments */
118     if (This==0)
119         return CO_E_NOTINITIALIZED;
120
121     if (ppvObject==0)
122         return E_INVALIDARG;
123
124     *ppvObject = 0;
125
126     if (IsEqualIID(&IID_IUnknown, riid))
127         *ppvObject = (IRunningObjectTable*)This;
128     else
129         if (IsEqualIID(&IID_IRunningObjectTable, riid))
130             *ppvObject = (IRunningObjectTable*)This;
131
132     if ((*ppvObject)==0)
133         return E_NOINTERFACE;
134
135     RunningObjectTableImpl_AddRef(iface);
136
137     return S_OK;
138 }
139
140 /***********************************************************************
141  *        RunningObjectTable_AddRef
142  */
143 ULONG   WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
144 {
145     ICOM_THIS(RunningObjectTableImpl,iface);
146
147     TRACE("(%p)\n",This);
148
149     return ++(This->ref);
150 }
151
152 /***********************************************************************
153  *        RunningObjectTable_Initialize
154  */
155 HRESULT WINAPI RunningObjectTableImpl_Destroy()
156 {
157     TRACE("()\n");
158
159     if (runningObjectTableInstance==NULL)
160         return E_INVALIDARG;
161
162     /* free the ROT table memory */
163     HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab);
164
165     /* free the ROT structure memory */
166     HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
167
168     return S_OK;
169 }
170
171 /***********************************************************************
172  *        RunningObjectTable_Release
173  */
174 ULONG   WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface)
175 {
176     DWORD i;
177     ICOM_THIS(RunningObjectTableImpl,iface);
178
179     TRACE("(%p)\n",This);
180
181     This->ref--;
182
183     /* unitialize ROT structure if there's no more reference to it*/
184     if (This->ref==0){
185
186         /* release all registered objects */
187         for(i=0;i<This->runObjTabLastIndx;i++)
188         {
189             if (( This->runObjTab[i].regTypeObj &  ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0)
190                 IUnknown_Release(This->runObjTab[i].pObj);
191
192             IMoniker_Release(This->runObjTab[i].pmkObj);
193         }
194        /*  RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
195         *  when RunningObjectTableImpl_UnInitialize function is called
196         */
197
198         /* there's no more elements in the table */
199         This->runObjTabRegister=0;
200         This->runObjTabLastIndx=0;
201
202         return 0;
203     }
204
205     return This->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     ICOM_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     ICOM_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     ICOM_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     ICOM_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     ICOM_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     ICOM_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   ICOM_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  }