Fixed typo.
[wine] / ole / filemoniker.c
1 /***************************************************************************************
2  *                            FileMonikers implementation
3  *
4  *               Copyright 1999  Noomen Hamza
5  ***************************************************************************************/
6
7 #include <assert.h>
8 #include "winerror.h"
9 #include "debugtools.h"
10 #include "heap.h"
11 #include "winuser.h"
12 #include "file.h"
13 #include "winreg.h"
14 #include "objbase.h"
15 #include "wine/obj_storage.h"
16 #include "wine/obj_base.h"
17
18 DEFAULT_DEBUG_CHANNEL(ole)
19
20 /* filemoniker data structure */
21 typedef struct FileMonikerImpl{
22
23     ICOM_VTABLE(IMoniker)*  lpvtbl1;  /* VTable relative to the IMoniker interface.*/
24
25     /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether 
26      * two monikers are equal. That's whay IROTData interface is implemented by monikers.
27      */
28     ICOM_VTABLE(IROTData)*  lpvtbl2;  /* VTable relative to the IROTData interface.*/
29
30     ULONG ref; /* reference counter for this object */
31
32     LPOLESTR filePathName; /* path string identified by this filemoniker */
33
34 } FileMonikerImpl;
35
36 /********************************************************************************/
37 /* FileMoniker prototype functions :                                            */
38
39 /* IUnknown prototype functions */
40 static HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
41 static ULONG   WINAPI FileMonikerImpl_AddRef(IMoniker* iface);
42 static ULONG   WINAPI FileMonikerImpl_Release(IMoniker* iface);
43
44 /* IPersist prototype functions */
45 static HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
46
47 /* IPersistStream prototype functions */
48 static HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface);
49 static HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface, IStream* pStm);
50 static HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
51 static HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
52
53 /* IMoniker prototype functions */
54 static HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
55 static HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
56 static HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
57 static HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
58 static HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
59 static HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
60 static HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
61 static HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
62 static HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pFileTime);
63 static HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
64 static HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
65 static HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
66 static HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
67 static HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
68 static HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
69
70 /********************************************************************************/
71 /* IROTData prototype functions                                                 */
72
73 /* IUnknown prototype functions */
74 static HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
75 static ULONG   WINAPI FileMonikerROTDataImpl_AddRef(IROTData* iface);
76 static ULONG   WINAPI FileMonikerROTDataImpl_Release(IROTData* iface);
77
78 /* IROTData prototype function */
79 static HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
80
81 /* Local function used by filemoniker implementation */
82 HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName);
83 HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* iface);
84 int     WINAPI FileMonikerImpl_DecomposePath(LPOLESTR str, LPOLESTR** tabStr);
85
86
87 /********************************************************************************/
88 /* Virtual function table for the FileMonikerImpl class witch  include Ipersist,*/
89 /* IPersistStream and IMoniker functions.                                       */
90 static ICOM_VTABLE(IMoniker) VT_FileMonikerImpl =
91 {
92     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
93     FileMonikerImpl_QueryInterface,
94     FileMonikerImpl_AddRef,
95     FileMonikerImpl_Release,
96     FileMonikerImpl_GetClassID,
97     FileMonikerImpl_IsDirty,
98     FileMonikerImpl_Load,
99     FileMonikerImpl_Save,
100     FileMonikerImpl_GetSizeMax,
101     FileMonikerImpl_BindToObject,
102     FileMonikerImpl_BindToStorage,
103     FileMonikerImpl_Reduce,
104     FileMonikerImpl_ComposeWith,
105     FileMonikerImpl_Enum,
106     FileMonikerImpl_IsEqual,
107     FileMonikerImpl_Hash,
108     FileMonikerImpl_IsRunning,
109     FileMonikerImpl_GetTimeOfLastChange,
110     FileMonikerImpl_Inverse,
111     FileMonikerImpl_CommonPrefixWith,
112     FileMonikerImpl_RelativePathTo,
113     FileMonikerImpl_GetDisplayName,
114     FileMonikerImpl_ParseDisplayName,
115     FileMonikerImpl_IsSystemMoniker
116 };
117
118 /********************************************************************************/
119 /* Virtual function table for the IROTData class.                               */
120 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
121 {
122     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
123     FileMonikerROTDataImpl_QueryInterface,
124     FileMonikerROTDataImpl_AddRef,
125     FileMonikerROTDataImpl_Release,
126     FileMonikerROTDataImpl_GetComparaisonData
127 };
128
129 /*******************************************************************************
130  *        FileMoniker_QueryInterface
131  *******************************************************************************/
132 HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
133 {
134     ICOM_THIS(FileMonikerImpl,iface);
135   
136   TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
137
138     /* Perform a sanity check on the parameters.*/
139     if ( (This==0) || (ppvObject==0) )
140         return E_INVALIDARG;
141   
142     /* Initialize the return parameter */
143   *ppvObject = 0;
144
145     /* Compare the riid with the interface IDs implemented by this object.*/
146     if (IsEqualIID(&IID_IUnknown, riid)      ||
147         IsEqualIID(&IID_IPersist, riid)      ||
148         IsEqualIID(&IID_IPersistStream,riid) ||
149         IsEqualIID(&IID_IMoniker, riid)
150        )
151         *ppvObject = iface;
152     
153     else if (IsEqualIID(&IID_IROTData, riid))
154         *ppvObject = (IROTData*)&(This->lpvtbl2);
155
156     /* Check that we obtained an interface.*/
157     if ((*ppvObject)==0)
158         return E_NOINTERFACE;
159   
160     /* Query Interface always increases the reference count by one when it is successful */
161   FileMonikerImpl_AddRef(iface);
162
163     return S_OK;
164 }
165
166 /******************************************************************************
167  *        FileMoniker_AddRef
168  ******************************************************************************/
169 ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface)
170 {
171     ICOM_THIS(FileMonikerImpl,iface);
172
173     TRACE("(%p)\n",iface);
174
175     return ++(This->ref);
176 }
177
178 /******************************************************************************
179  *        FileMoniker_Release
180  ******************************************************************************/
181 ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface)
182 {
183     ICOM_THIS(FileMonikerImpl,iface);
184
185     TRACE("(%p)\n",iface);
186
187     This->ref--;
188
189     /* destroy the object if there's no more reference on it */
190     if (This->ref==0){
191
192         FileMonikerImpl_Destroy(This);
193
194         return 0;
195     }
196     return This->ref;;
197 }
198
199 /******************************************************************************
200  *        FileMoniker_GetClassID
201  ******************************************************************************/
202 HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface,
203                                           CLSID *pClassID)/* Pointer to CLSID of object */
204 {
205     TRACE("(%p,%p),stub!\n",iface,pClassID);
206
207     if (pClassID==NULL)
208         return E_POINTER;
209
210     *pClassID = CLSID_FileMoniker;
211         
212     return S_OK;
213 }
214
215 /******************************************************************************
216  *        FileMoniker_IsDirty
217  ******************************************************************************/
218 HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface)
219 {
220     /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
221        method in the OLE-provided moniker interfaces always return S_FALSE because
222        their internal state never changes. */
223
224     TRACE("(%p)\n",iface);
225
226     return S_FALSE;
227 }
228
229 /******************************************************************************
230  *        FileMoniker_Load
231  ******************************************************************************/
232 HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm)
233 {
234     HRESULT res;
235     CHAR* filePathA;
236     WCHAR* filePathW;
237     ULONG bread;
238     WORD  wbuffer;
239     DWORD dwbuffer,length,i,doubleLenHex,doubleLenDec;
240
241     ICOM_THIS(FileMonikerImpl,iface);
242
243     TRACE("(%p,%p)\n",iface,pStm);
244
245     /* this function locate and read from the stream the filePath string writen by FileMonikerImpl_Save */
246
247     /* first WORD is non significative */
248     res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
249     if (bread!=sizeof(WORD) || wbuffer!=0)
250         return E_FAIL;
251     
252     /* read filePath string length (plus one) */
253     res=IStream_Read(pStm,&length,sizeof(DWORD),&bread);
254     if (bread != sizeof(DWORD))
255         return E_FAIL;
256
257     /* read filePath string */
258     filePathA=HeapAlloc(GetProcessHeap(),0,length);
259     res=IStream_Read(pStm,filePathA,length,&bread);
260     if (bread != length)
261         return E_FAIL;
262
263     /* read the first constant */
264     IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
265     if (bread != sizeof(DWORD) || dwbuffer != 0xDEADFFFF)
266         return E_FAIL;
267         
268     length--;
269         
270     for(i=0;i<10;i++){
271         res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
272         if (bread!=sizeof(WORD) || wbuffer!=0)
273             return E_FAIL;
274     }
275     
276     if (length>8)
277         length=0;
278         
279     doubleLenHex=doubleLenDec=2*length;
280     if (length > 5)
281         doubleLenDec+=6;
282
283     res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
284     if (bread!=sizeof(DWORD) || dwbuffer!=doubleLenDec)
285         return E_FAIL;
286
287     if (length==0)
288         return res;
289         
290     res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
291     if (bread!=sizeof(DWORD) || dwbuffer!=doubleLenHex)
292         return E_FAIL;
293
294     res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
295     if (bread!=sizeof(WORD) || wbuffer!=0x3)
296         return E_FAIL;
297
298     filePathW=HeapAlloc(GetProcessHeap(),0,(length+1)*sizeof(WCHAR));
299     filePathW[length]=0;
300     res=IStream_Read(pStm,filePathW,doubleLenHex,&bread);
301     if (bread!=doubleLenHex)
302         return E_FAIL;
303
304     if (This->filePathName!=NULL)
305         HeapFree(GetProcessHeap(),0,This->filePathName);
306
307     This->filePathName=filePathW;
308
309     HeapFree(GetProcessHeap(),0,filePathA);
310     
311     return res;
312 }
313
314 /******************************************************************************
315  *        FileMoniker_Save
316  ******************************************************************************/
317 HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface,
318                                     IStream* pStm,/* poniter to the stream where the object is to be saved */
319                                     BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
320 {
321     /* this function saves data of this object. In the begining I thougth that I have just to write
322      * the filePath string on Stream. But, when I tested this function whith windows programs samples !
323      * I noted that it was not the case. So I analysed data writen by this function on Windows system and 
324      * what did this function do exactly ! but I have no idear a bout its logic !
325      * I guessed data who must be writen on stream wich is:
326      * 1) WORD constant:zero 2) length of the path string ("\0" included) 3) path string type A
327      * 4) DWORD constant : 0xDEADFFFF 5) ten WORD constant: zero  6) DWORD: double-length of the the path
328      * string type W ("\0" not included) 7) WORD constant: 0x3 8) filePath unicode string.
329      *  if the length(filePath) > 8 or.length(filePath) == 8 stop at step 5)
330      */
331
332     ICOM_THIS(FileMonikerImpl,iface);        
333
334     HRESULT res;
335     LPOLESTR filePathW=This->filePathName;
336     CHAR*     filePathA;
337     DWORD  len=1+lstrlenW(filePathW);
338
339     DWORD  constant1 = 0xDEADFFFF; /* these constants are detected after analysing the data structure writen by */
340     WORD   constant2 = 0x3;        /* FileMoniker_Save function in a windows program system */
341
342     WORD   zero=0;
343     DWORD doubleLenHex;
344     DWORD doubleLenDec;
345     int i=0;
346
347     TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
348
349     if (pStm==NULL)
350         return E_POINTER;
351
352     /* write a DWORD seted to 0 : constant */
353     res=IStream_Write(pStm,&zero,sizeof(WORD),NULL);
354
355     /* write length of filePath string ( "\0" included )*/
356     res=IStream_Write(pStm,&len,sizeof(DWORD),NULL);
357
358     /* write filePath string type A */
359     filePathA=HeapAlloc(GetProcessHeap(),0,len);
360     lstrcpyWtoA(filePathA,filePathW);
361     res=IStream_Write(pStm,filePathA,len,NULL);
362     HeapFree(GetProcessHeap(),0,filePathA);
363
364     /* write a DWORD seted to 0xDEADFFFF: constant */
365     res=IStream_Write(pStm,&constant1,sizeof(DWORD),NULL);
366         
367     len--;
368     /* write 10 times a DWORD seted to 0 : constants */
369     for(i=0;i<10;i++)
370         res=IStream_Write(pStm,&zero,sizeof(WORD),NULL);
371         
372     if (len>8)
373         len=0;
374         
375     doubleLenHex=doubleLenDec=2*len;
376     if (len > 5)
377         doubleLenDec+=6;
378
379     /* write double-length of the path string ( "\0" included )*/
380     res=IStream_Write(pStm,&doubleLenDec,sizeof(DWORD),NULL);
381
382     if (len==0)
383         return res;
384
385     /* write double-length (hexa representation) of the path string ( "\0" included ) */
386     res=IStream_Write(pStm,&doubleLenHex,sizeof(DWORD),NULL);
387
388     /* write a WORD seted to 0x3: constant */
389     res=IStream_Write(pStm,&constant2,sizeof(WORD),NULL);
390
391     /* write path unicode string */
392     res=IStream_Write(pStm,filePathW,doubleLenHex,NULL);
393
394     return res;
395 }
396
397 /******************************************************************************
398  *        FileMoniker_GetSizeMax
399  ******************************************************************************/
400 HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface,
401                                           ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
402 {
403     ICOM_THIS(FileMonikerImpl,iface);
404     DWORD len=lstrlenW(This->filePathName);
405     DWORD sizeMAx;
406
407     TRACE("(%p,%p)\n",iface,pcbSize);
408
409     if (pcbSize!=NULL)
410         return E_POINTER;
411
412     /* for more details see FileMonikerImpl_Save coments */
413     
414     sizeMAx =  sizeof(WORD) +           /* first WORD is 0 */
415                sizeof(DWORD)+           /* length of filePath including "\0" in the end of the string */
416                (len+1)+                 /* filePath string */
417                sizeof(DWORD)+           /* constant : 0xDEADFFFF */
418                10*sizeof(WORD)+         /* 10 zero WORD */
419                sizeof(DWORD);           /* size of the unicode filePath: "\0" not included */
420
421     if (len==0 || len > 8)
422         return S_OK;
423     
424     sizeMAx += sizeof(DWORD)+           /* size of the unicode filePath: "\0" not included */
425                sizeof(WORD)+            /* constant : 0x3 */
426                len*sizeof(WCHAR);       /* unicde filePath string */
427     
428     pcbSize->LowPart=sizeMAx;
429     pcbSize->HighPart=0;
430
431     return S_OK;
432 }
433
434 /******************************************************************************
435  *         FileMoniker_Construct (local function)
436  *******************************************************************************/
437 HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName)
438 {
439     int nb=0,i;
440     int sizeStr=lstrlenW(lpszPathName);
441     LPOLESTR *tabStr=0;
442     WCHAR twoPoint[]={'.','.',0};
443     WCHAR bkSlash[]={'\\',0};
444     BYTE addBkSlash;
445     
446     TRACE("(%p,%p)\n",This,lpszPathName);
447
448     /* Initialize the virtual fgunction table. */
449     This->lpvtbl1      = &VT_FileMonikerImpl;
450     This->lpvtbl2      = &VT_ROTDataImpl;
451     This->ref          = 0;
452
453     This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1));
454
455     if (This->filePathName==NULL)
456         return E_OUTOFMEMORY;
457
458     lstrcpyW(This->filePathName,lpszPathName);
459
460     nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr);
461
462     if (nb > 0 ){
463
464         addBkSlash=1;
465         if (lstrcmpW(tabStr[0],twoPoint)!=0)
466             addBkSlash=0;
467         else
468             for(i=0;i<nb;i++){
469
470                 if ( (lstrcmpW(tabStr[i],twoPoint)!=0) && (lstrcmpW(tabStr[i],bkSlash)!=0) ){
471                     addBkSlash=0;
472                     break;
473                 }
474                 else
475
476                     if (lstrcmpW(tabStr[i],bkSlash)==0 && i<nb-1 && lstrcmpW(tabStr[i+1],bkSlash)==0){
477                         *tabStr[i]=0;
478                         sizeStr--;
479                         addBkSlash=0;
480                         break;
481                     }
482             }
483
484         if (lstrcmpW(tabStr[nb-1],bkSlash)==0)
485             addBkSlash=0;
486
487         This->filePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR));
488
489         *This->filePathName=0;
490     
491         for(i=0;tabStr[i]!=NULL;i++)
492             lstrcatW(This->filePathName,tabStr[i]);
493     
494         if (addBkSlash)
495             lstrcatW(This->filePathName,bkSlash);
496     }
497
498     for(i=0; tabStr[i]!=NULL;i++)
499         CoTaskMemFree(tabStr[i]);
500     CoTaskMemFree(tabStr);
501
502     return S_OK;
503 }
504
505 /******************************************************************************
506  *        FileMoniker_Destroy (local function)
507  *******************************************************************************/
508 HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This)
509 {
510     TRACE("(%p)\n",This);
511
512     if (This->filePathName!=NULL)
513             HeapFree(GetProcessHeap(),0,This->filePathName);
514
515     HeapFree(GetProcessHeap(),0,This);
516
517     return S_OK;
518 }
519
520 /******************************************************************************
521  *                  FileMoniker_BindToObject
522  ******************************************************************************/
523 HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,
524                                             IBindCtx* pbc,
525                                             IMoniker* pmkToLeft,
526                                             REFIID riid,
527                                             VOID** ppvResult)
528 {
529     HRESULT   res=E_FAIL;
530     CLSID     clsID;
531     IUnknown* pObj=0;
532     IRunningObjectTable *prot=0;
533     IPersistFile  *ppf=0;
534     IClassFactory *pcf=0;
535     IClassActivator *pca=0;
536     
537     ICOM_THIS(FileMonikerImpl,iface);    
538
539     *ppvResult=0;
540
541     TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
542
543     if(pmkToLeft==NULL){
544         
545         res=IBindCtx_GetRunningObjectTable(pbc,&prot);
546
547         if (SUCCEEDED(res)){
548             /* if the requested class was loaded befor ! we dont need to reload it */
549             res = IRunningObjectTable_GetObject(prot,iface,&pObj);
550
551             if (res==S_FALSE){
552                 /* first activation of this class */
553                 res=GetClassFile(This->filePathName,&clsID);
554                 if (SUCCEEDED(res)){
555
556                     res=CoCreateInstance(&clsID,NULL,CLSCTX_ALL,&IID_IPersistFile,(void**)&ppf);
557                     if (SUCCEEDED(res)){
558
559                         res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
560                         if (SUCCEEDED(res)){
561
562                             pObj=(IUnknown*)ppf;
563                             IUnknown_AddRef(pObj);
564                         }
565                     }
566                 }
567             }
568         }
569     }
570     else{
571         res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassFactory,(void**)&pcf);
572
573         if (res==E_NOINTERFACE){
574
575             res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassActivator,(void**)&pca);
576         
577             if (res==E_NOINTERFACE)
578                 return MK_E_INTERMEDIATEINTERFACENOTSUPPORTED;
579         }
580         if (pcf!=NULL){
581
582             IClassFactory_CreateInstance(pcf,NULL,&IID_IPersistFile,(void**)ppf);
583
584             res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
585
586             if (SUCCEEDED(res)){
587
588                 pObj=(IUnknown*)ppf;
589                 IUnknown_AddRef(pObj);
590             }
591         }
592         if (pca!=NULL){
593
594             FIXME("()");
595             
596             /*res=GetClassFile(This->filePathName,&clsID);
597
598             if (SUCCEEDED(res)){
599
600                 res=IClassActivator_GetClassObject(pca,&clsID,CLSCTX_ALL,0,&IID_IPersistFile,(void**)&ppf);
601
602                 if (SUCCEEDED(res)){
603
604                     pObj=(IUnknown*)ppf;
605                     IUnknown_AddRef(pObj);
606                 }
607             }*/
608         }
609 }
610
611     if (pObj!=NULL){
612         /* get the requested interface from the loaded class */
613         res= IUnknown_QueryInterface(pObj,riid,ppvResult);
614
615         IBindCtx_RegisterObjectBound(pbc,(IUnknown*)*ppvResult);
616
617         IUnknown_Release(pObj);
618     }
619
620     if (prot!=NULL)
621         IRunningObjectTable_Release(prot);
622
623     if (ppf!=NULL)
624         IPersistFile_Release(ppf);
625
626     if (pca!=NULL)
627         IClassActivator_Release(pca);
628
629     if (pcf!=NULL)
630         IClassFactory_Release(pcf);
631     
632     return res;
633 }
634
635 /******************************************************************************
636  *        FileMoniker_BindToStorage
637  ******************************************************************************/
638 HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,
639                                              IBindCtx* pbc,
640                                              IMoniker* pmkToLeft,
641                                              REFIID riid,
642                                              VOID** ppvObject)
643 {
644     LPOLESTR filePath=0;
645     IStorage *pstg=0;
646     HRESULT res;
647
648     TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject);
649
650     if (pmkToLeft==NULL){
651
652         if (IsEqualIID(&IID_IStorage, riid)){
653
654             /* get the file name */
655             FileMonikerImpl_GetDisplayName(iface,pbc,pmkToLeft,&filePath);
656
657             /* verifie if the file contains a storage object */
658             res=StgIsStorageFile(filePath);
659
660             if(res==S_OK){
661
662                 res=StgOpenStorage(filePath,NULL,STGM_READWRITE|STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
663
664                 if (SUCCEEDED(res)){
665
666                     *ppvObject=pstg;
667
668                     IStorage_AddRef(pstg);
669
670                     return res;
671                 }
672             }
673             CoTaskMemFree(filePath);
674         }
675         else
676             if ( (IsEqualIID(&IID_IStream, riid)) || (IsEqualIID(&IID_ILockBytes, riid)) )
677
678                 return E_UNSPEC;
679             else
680
681                 return E_NOINTERFACE;
682     }
683     else {
684
685         FIXME("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject);
686
687     return E_NOTIMPL;
688 }
689     return res;
690 }
691
692 /******************************************************************************
693  *        FileMoniker_Reduce
694  ******************************************************************************/
695 HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,
696                                       IBindCtx* pbc,
697                                       DWORD dwReduceHowFar,
698                                       IMoniker** ppmkToLeft,
699                                       IMoniker** ppmkReduced)
700 {
701     TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
702
703     if (ppmkReduced==NULL)
704         return E_POINTER;
705
706     FileMonikerImpl_AddRef(iface);
707
708     *ppmkReduced=iface;
709
710     return MK_S_REDUCED_TO_SELF;
711 }
712 /******************************************************************************
713  *        FileMoniker_ComposeWith
714  ******************************************************************************/
715 HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,
716                                            IMoniker* pmkRight,
717                                            BOOL fOnlyIfNotGeneric,
718                                            IMoniker** ppmkComposite)
719 {
720     HRESULT res;
721     LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0;
722     WCHAR twoPoint[]={'.','.',0};
723     WCHAR bkSlash[]={'\\',0};
724     IBindCtx *bind=0;
725     int i=0,j=0,lastIdx1=0,lastIdx2=0;
726     DWORD mkSys;
727
728     TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
729
730     if (ppmkComposite==NULL)
731         return E_POINTER;
732
733     if (pmkRight==NULL)
734         return E_INVALIDARG;
735
736     *ppmkComposite=0;
737     
738     IMoniker_IsSystemMoniker(pmkRight,&mkSys);
739
740     /* check if we have two filemonikers to compose or not */
741     if(mkSys==MKSYS_FILEMONIKER){
742
743         CreateBindCtx(0,&bind);
744
745         FileMonikerImpl_GetDisplayName(iface,bind,NULL,&str1);
746         IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2);
747
748         /* decompose pathnames of the two monikers : (to prepare the path merge operation ) */
749         lastIdx1=FileMonikerImpl_DecomposePath(str1,&strDec1)-1;
750         lastIdx2=FileMonikerImpl_DecomposePath(str2,&strDec2)-1;
751
752         if ((lastIdx1==-1 && lastIdx2>-1)||(lastIdx1==1 && lstrcmpW(strDec1[0],twoPoint)==0))
753             return MK_E_SYNTAX;
754
755         if(lstrcmpW(strDec1[lastIdx1],bkSlash)==0)
756             lastIdx1--;
757
758         /* for etch "..\" in the left of str2 remove the right element from str1 */
759         for(i=0; ( (lastIdx1>=0) && (strDec2[i]!=NULL) && (lstrcmpW(strDec2[i],twoPoint)==0) ) ;i+=2){
760
761             lastIdx1-=2;
762         }
763
764         /* the length of the composed path string  is raised by the sum of the two paths lengths  */
765         newStr=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(lstrlenW(str1)+lstrlenW(str2)+1));
766         
767           if (newStr==NULL)
768                 return E_OUTOFMEMORY;
769
770         /* new path is the concatenation of the rest of str1 and str2 */
771         for(*newStr=0,j=0;j<=lastIdx1;j++)
772             lstrcatW(newStr,strDec1[j]);
773
774         if ((strDec2[i]==NULL && lastIdx1>-1 && lastIdx2>-1) || lstrcmpW(strDec2[i],bkSlash)!=0)
775             lstrcatW(newStr,bkSlash);
776             
777         for(j=i;j<=lastIdx2;j++)
778             lstrcatW(newStr,strDec2[j]);
779         
780         /* create a new moniker with the new string */
781         res=CreateFileMoniker(newStr,ppmkComposite);
782
783         /* free all strings space memory used by this function */
784         HeapFree(GetProcessHeap(),0,newStr);
785
786         for(i=0; strDec1[i]!=NULL;i++)
787             CoTaskMemFree(strDec1[i]);
788         for(i=0; strDec2[i]!=NULL;i++)
789             CoTaskMemFree(strDec2[i]);
790         CoTaskMemFree(strDec1);
791         CoTaskMemFree(strDec2);
792
793         CoTaskMemFree(str1);
794         CoTaskMemFree(str2);
795
796         return res;
797     }
798     else if(mkSys==MKSYS_ANTIMONIKER){
799
800         *ppmkComposite=NULL;
801         return S_OK;
802     }
803     else if (fOnlyIfNotGeneric){
804
805         *ppmkComposite=NULL;
806         return MK_E_NEEDGENERIC;
807     }
808     else
809
810         return CreateGenericComposite(iface,pmkRight,ppmkComposite);
811 }
812
813 /******************************************************************************
814  *        FileMoniker_Enum
815  ******************************************************************************/
816 HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
817 {
818     TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
819
820     if (ppenumMoniker == NULL)
821         return E_POINTER;
822
823     *ppenumMoniker = NULL;
824
825     return S_OK;
826 }
827
828 /******************************************************************************
829  *        FileMoniker_IsEqual
830  ******************************************************************************/
831 HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
832 {
833     ICOM_THIS(FileMonikerImpl,iface);
834     CLSID clsid;
835     LPOLESTR filePath;
836     IBindCtx* bind;
837     HRESULT res;
838
839     TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
840
841     if (pmkOtherMoniker==NULL)
842         return S_FALSE;
843
844     IMoniker_GetClassID(pmkOtherMoniker,&clsid);
845
846     if (!IsEqualCLSID(&clsid,&CLSID_FileMoniker))
847
848         return S_FALSE;
849
850     res=CreateBindCtx(0,&bind);
851     if (FAILED(res))
852         return res;
853
854     IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&filePath);
855     
856     if (lstrcmpiW(filePath,
857                   This->filePathName)!=0)
858
859         return S_FALSE;
860     
861     return S_OK;
862 }
863
864 /******************************************************************************
865  *        FileMoniker_Hash
866  ******************************************************************************/
867 HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
868 {
869     ICOM_THIS(FileMonikerImpl,iface);
870
871     int  h = 0,i,skip,len;
872     int  off = 0;
873     LPOLESTR val;
874
875     if (pdwHash==NULL)
876         return E_POINTER;
877     
878     val =  This->filePathName;
879     len = lstrlenW(val);
880
881     if (len < 16) {
882         for (i = len ; i > 0; i--) {
883             h = (h * 37) + val[off++];
884         }
885     } else {
886         /* only sample some characters */
887         skip = len / 8;
888         for (i = len ; i > 0; i -= skip, off += skip) {
889             h = (h * 39) + val[off];
890         }
891 }
892
893     *pdwHash=h;
894
895     return S_OK;
896 }
897
898 /******************************************************************************
899  *        FileMoniker_IsRunning
900  ******************************************************************************/
901 HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,
902                                          IBindCtx* pbc,
903                                          IMoniker* pmkToLeft,
904                                          IMoniker* pmkNewlyRunning)
905 {
906     IRunningObjectTable* rot;
907     HRESULT res;
908
909     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
910
911     if ( (pmkNewlyRunning!=NULL) && (IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK) )
912         return S_OK;
913
914     if (pbc==NULL)
915         return E_POINTER;
916
917     res=IBindCtx_GetRunningObjectTable(pbc,&rot);
918
919     if (FAILED(res))
920         return res;
921
922     res = IRunningObjectTable_IsRunning(rot,iface);
923
924     IRunningObjectTable_Release(rot);
925
926     return res;
927 }
928
929 /******************************************************************************
930  *        FileMoniker_GetTimeOfLastChange
931  ******************************************************************************/
932 HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
933                                                    IBindCtx* pbc,
934                                                    IMoniker* pmkToLeft,
935                                                    FILETIME* pFileTime)
936 {
937     ICOM_THIS(FileMonikerImpl,iface);
938     IRunningObjectTable* rot;
939     HRESULT res;
940     WIN32_FILE_ATTRIBUTE_DATA info;
941
942     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pFileTime);
943
944     if (pFileTime==NULL)
945         return E_POINTER;
946
947     if (pmkToLeft!=NULL)
948         return E_INVALIDARG;
949
950     res=IBindCtx_GetRunningObjectTable(pbc,&rot);
951
952     if (FAILED(res))
953         return res;
954
955     res= IRunningObjectTable_GetTimeOfLastChange(rot,iface,pFileTime);
956
957     if (FAILED(res)){ /* the moniker is not registred */
958
959         if (!GetFileAttributesExW(This->filePathName,GetFileExInfoStandard,&info))
960             return MK_E_NOOBJECT;
961         
962         *pFileTime=info.ftLastWriteTime;
963 }
964
965     return S_OK;
966 }
967
968 /******************************************************************************
969  *        FileMoniker_Inverse
970  ******************************************************************************/
971 HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
972 {
973
974     TRACE("(%p,%p)\n",iface,ppmk);
975
976     return CreateAntiMoniker(ppmk);
977 }
978
979 /******************************************************************************
980  *        FileMoniker_CommonPrefixWith
981  ******************************************************************************/
982 HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
983 {
984
985     LPOLESTR pathThis,pathOther,*stringTable1,*stringTable2,commonPath;
986     IBindCtx *pbind;
987     DWORD mkSys;
988     ULONG nb1,nb2,i,sameIdx;
989     BOOL machimeNameCase=FALSE;
990
991     if (ppmkPrefix==NULL)
992         return E_POINTER;
993
994     if (pmkOther==NULL)
995         return E_INVALIDARG;
996     
997     *ppmkPrefix=0;
998     
999     /* check if we have the same type of moniker */
1000     IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1001
1002     if(mkSys==MKSYS_FILEMONIKER){
1003
1004         CreateBindCtx(0,&pbind);
1005
1006         /* create a string based on common part of the two paths */
1007
1008         IMoniker_GetDisplayName(iface,pbind,NULL,&pathThis);
1009         IMoniker_GetDisplayName(pmkOther,pbind,NULL,&pathOther);
1010
1011         nb1=FileMonikerImpl_DecomposePath(pathThis,&stringTable1);
1012         nb2=FileMonikerImpl_DecomposePath(pathOther,&stringTable2);
1013
1014         if (nb1==0 || nb2==0)
1015             return MK_E_NOPREFIX;
1016
1017         commonPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(min(lstrlenW(pathThis),lstrlenW(pathOther))+1));
1018
1019         *commonPath=0;
1020         
1021         for(sameIdx=0; ( (stringTable1[sameIdx]!=NULL) &&
1022                          (stringTable2[sameIdx]!=NULL) &&
1023                          (lstrcmpiW(stringTable1[sameIdx],stringTable2[sameIdx])==0)); sameIdx++);
1024
1025         if (sameIdx > 1 && *stringTable1[0]=='\\' && *stringTable2[1]=='\\'){
1026
1027             machimeNameCase=TRUE;
1028
1029             for(i=2;i<sameIdx;i++)
1030
1031                 if( (*stringTable1[i]=='\\') && (i+1 < sameIdx) && (*stringTable1[i+1]=='\\') ){
1032                     machimeNameCase=FALSE;
1033                     break;
1034 }
1035         }
1036
1037         if (machimeNameCase && *stringTable1[sameIdx-1]=='\\')
1038             sameIdx--;
1039         
1040         if (machimeNameCase && (sameIdx<=3) && (nb1 > 3 || nb2 > 3) )
1041             return MK_E_NOPREFIX;
1042
1043         for(i=0;i<sameIdx;i++)
1044             lstrcatW(commonPath,stringTable1[i]);
1045         
1046         for(i=0;i<nb1;i++)
1047             CoTaskMemFree(stringTable1[i]);
1048
1049         CoTaskMemFree(stringTable1);
1050
1051         for(i=0;i<nb2;i++)
1052             CoTaskMemFree(stringTable2[i]);
1053
1054         CoTaskMemFree(stringTable2);
1055
1056         HeapFree(GetProcessHeap(),0,commonPath);
1057         
1058         return CreateFileMoniker(commonPath,ppmkPrefix);
1059     }
1060     else
1061         return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
1062 }
1063
1064 /******************************************************************************
1065  *        DecomposePath (local function)
1066  ******************************************************************************/
1067 int WINAPI FileMonikerImpl_DecomposePath(LPOLESTR str, LPOLESTR** stringTable)
1068 {
1069     WCHAR bSlash[] = {'\\',0};
1070     WCHAR word[100];
1071     int i=0,j,tabIndex=0;
1072     LPOLESTR *strgtable ;
1073
1074     int len=lstrlenW(str);
1075
1076     strgtable =CoTaskMemAlloc(len*sizeof(LPOLESTR));
1077     
1078     if (strgtable==NULL)
1079         return E_OUTOFMEMORY;
1080     
1081     while(str[i]!=0){
1082
1083         if(str[i]==bSlash[0]){
1084
1085             strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR));
1086
1087             if (strgtable[tabIndex]==NULL)
1088                 return E_OUTOFMEMORY;
1089
1090             lstrcpyW(strgtable[tabIndex++],bSlash);
1091
1092             i++;
1093
1094         }
1095         else {
1096
1097             for(j=0; str[i]!=0 && str[i]!=bSlash[0] ; i++,j++)
1098                 word[j]=str[i];
1099
1100             word[j]=0;
1101
1102             strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1));
1103
1104             if (strgtable[tabIndex]==NULL)
1105                 return E_OUTOFMEMORY;
1106
1107             lstrcpyW(strgtable[tabIndex++],word);
1108         }
1109     }
1110     strgtable[tabIndex]=NULL;
1111     
1112     *stringTable=strgtable;
1113     
1114     return tabIndex;
1115 }
1116
1117 /******************************************************************************
1118  *        FileMoniker_RelativePathTo
1119  ******************************************************************************/
1120 HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
1121 {
1122     IBindCtx *bind;
1123     HRESULT res;
1124     LPOLESTR str1=0,str2=0,*tabStr1=0,*tabStr2=0,relPath=0;
1125     DWORD len1=0,len2=0,sameIdx=0,j=0;
1126     WCHAR back[] ={'.','.','\\',0};
1127     
1128     TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
1129
1130     if (ppmkRelPath==NULL)
1131         return E_POINTER;
1132
1133     if (pmOther==NULL)
1134         return E_INVALIDARG;
1135     
1136     res=CreateBindCtx(0,&bind);
1137     if (FAILED(res))
1138         return res;
1139
1140     res=IMoniker_GetDisplayName(iface,bind,NULL,&str1);
1141     if (FAILED(res))
1142         return res;
1143     res=IMoniker_GetDisplayName(pmOther,bind,NULL,&str2);
1144     if (FAILED(res))
1145         return res;
1146
1147     len1=FileMonikerImpl_DecomposePath(str1,&tabStr1);
1148     len2=FileMonikerImpl_DecomposePath(str2,&tabStr2);
1149
1150     if (FAILED(len1) || FAILED(len2))
1151         return E_OUTOFMEMORY;
1152         
1153     /* count the number of similar items from the begin of the two paths */
1154     for(sameIdx=0; ( (tabStr1[sameIdx]!=NULL) &&
1155                    (tabStr2[sameIdx]!=NULL) &&
1156                (lstrcmpiW(tabStr1[sameIdx],tabStr2[sameIdx])==0)); sameIdx++);
1157
1158     /* begin the construction of relativePath */
1159     /* if the two paths have a consecutive similar item from the begin ! the relativePath will be composed */
1160     /* by "..\\" in the begin */
1161     relPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(1+lstrlenW(str1)+lstrlenW(str2)));
1162
1163     *relPath=0;
1164
1165     if (len2>0 && !(len1==1 && len2==1 && sameIdx==0))
1166         for(j=sameIdx;(tabStr1[j] != NULL); j++)
1167             if (*tabStr1[j]!='\\')
1168                 lstrcatW(relPath,back);
1169
1170     /* add items of the second path (similar items with the first path are not included) to the relativePath */
1171     for(j=sameIdx;tabStr2[j]!=NULL;j++)
1172         lstrcatW(relPath,tabStr2[j]);
1173     
1174     res=CreateFileMoniker(relPath,ppmkRelPath);
1175     
1176     for(j=0; tabStr1[j]!=NULL;j++)
1177         CoTaskMemFree(tabStr1[j]);
1178     for(j=0; tabStr2[j]!=NULL;j++)
1179         CoTaskMemFree(tabStr2[j]);
1180     CoTaskMemFree(tabStr1);
1181     CoTaskMemFree(tabStr2);
1182     CoTaskMemFree(str1);
1183     CoTaskMemFree(str2);
1184     HeapFree(GetProcessHeap(),0,relPath);
1185
1186     if (len1==0 || len2==0 || (len1==1 && len2==1 && sameIdx==0))
1187         return MK_S_HIM;
1188
1189     return res;
1190 }
1191
1192 /******************************************************************************
1193  *        FileMoniker_GetDisplayName
1194  ******************************************************************************/
1195 HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,
1196                                               IBindCtx* pbc,
1197                                               IMoniker* pmkToLeft,
1198                                               LPOLESTR *ppszDisplayName)
1199 {
1200     ICOM_THIS(FileMonikerImpl,iface);
1201
1202     int len=lstrlenW(This->filePathName);
1203
1204     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1205
1206     if (ppszDisplayName==NULL)
1207         return E_POINTER;
1208
1209     if (pmkToLeft!=NULL)
1210         return E_INVALIDARG;
1211
1212     *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
1213     if (*ppszDisplayName==NULL)
1214         return E_OUTOFMEMORY;
1215
1216     lstrcpyW(*ppszDisplayName,This->filePathName);
1217     
1218     return S_OK;
1219 }
1220
1221 /******************************************************************************
1222  *        FileMoniker_ParseDisplayName
1223  ******************************************************************************/
1224 HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,
1225                                                 IBindCtx* pbc,
1226                                                 IMoniker* pmkToLeft,
1227                                                 LPOLESTR pszDisplayName,
1228                                                 ULONG* pchEaten,
1229                                                 IMoniker** ppmkOut)
1230 {
1231     FIXME("(%p,%p,%p,%p,%p,%p),stub!\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
1232     return E_NOTIMPL;
1233 }
1234
1235 /******************************************************************************
1236  *        FileMoniker_IsSystemMonker
1237  ******************************************************************************/
1238 HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1239 {
1240     TRACE("(%p,%p)\n",iface,pwdMksys);
1241
1242     if (!pwdMksys)
1243         return E_POINTER;
1244     
1245     (*pwdMksys)=MKSYS_FILEMONIKER;
1246
1247     return S_OK;
1248 }
1249
1250 /*******************************************************************************
1251  *        FileMonikerIROTData_QueryInterface
1252  *******************************************************************************/
1253 HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1254 {
1255
1256     ICOM_THIS_From_IROTData(IMoniker, iface);
1257
1258     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1259
1260     return FileMonikerImpl_QueryInterface(This, riid, ppvObject);
1261 }
1262
1263 /***********************************************************************
1264  *        FileMonikerIROTData_AddRef
1265  */
1266 ULONG   WINAPI FileMonikerROTDataImpl_AddRef(IROTData *iface)
1267 {
1268     ICOM_THIS_From_IROTData(IMoniker, iface);
1269
1270     TRACE("(%p)\n",This);
1271
1272     return FileMonikerImpl_AddRef(This);
1273 }
1274
1275 /***********************************************************************
1276  *        FileMonikerIROTData_Release
1277  */
1278 ULONG   WINAPI FileMonikerROTDataImpl_Release(IROTData* iface)
1279 {
1280     ICOM_THIS_From_IROTData(IMoniker, iface);
1281     
1282     TRACE("(%p)\n",This);
1283
1284     return FileMonikerImpl_Release(This);
1285 }
1286
1287 /******************************************************************************
1288  *        FileMonikerIROTData_GetComparaisonData
1289  ******************************************************************************/
1290 HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1291                                                          BYTE* pbData,
1292                                                          ULONG cbMax,
1293                                                          ULONG* pcbData)
1294 {
1295     FIXME("(),stub!\n");
1296     return E_NOTIMPL;
1297 }
1298
1299 /******************************************************************************
1300  *        CreateFileMoniker16
1301  ******************************************************************************/
1302 HRESULT WINAPI CreateFileMoniker16(LPCOLESTR16 lpszPathName,LPMONIKER* ppmk)
1303 {
1304
1305     FIXME("(%s,%p),stub!\n",lpszPathName,ppmk);
1306     return E_NOTIMPL;
1307 }
1308
1309 /******************************************************************************
1310  *        CreateFileMoniker
1311  ******************************************************************************/
1312 HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk)
1313 {
1314     FileMonikerImpl* newFileMoniker = 0;
1315     HRESULT  hr = E_FAIL;
1316     IID riid=IID_IMoniker;
1317
1318     TRACE("(%p,%p)\n",lpszPathName,ppmk);
1319
1320     if (ppmk==NULL)
1321         return E_POINTER;
1322
1323     if(lpszPathName==NULL)
1324         return MK_E_SYNTAX;
1325             
1326     *ppmk=0;
1327         
1328     newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
1329
1330     if (newFileMoniker == 0)
1331         return E_OUTOFMEMORY;
1332
1333     hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName);
1334
1335     if (SUCCEEDED(hr))
1336         hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker,&riid,(void**)ppmk);
1337     else
1338         HeapFree(GetProcessHeap(),0,newFileMoniker);
1339
1340     return hr;
1341 }