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