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