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