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