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