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