Include stdio.h for MinGW.
[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 <stdarg.h>
23 #include <string.h>
24
25 #define COBJMACROS
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "winnls.h"
33 #include "wine/unicode.h"
34 #include "wine/debug.h"
35 #include "objbase.h"
36 #include "moniker.h"
37
38 #include "compobj_private.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(ole);
41
42 const CLSID CLSID_FileMoniker = {
43   0x303, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
44 };
45
46 /* filemoniker data structure */
47 typedef struct FileMonikerImpl{
48
49     IMonikerVtbl*  lpvtbl1;  /* VTable relative to the IMoniker interface.*/
50
51     /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
52      * two monikers are equal. That's whay IROTData interface is implemented by monikers.
53      */
54     IROTDataVtbl*  lpvtbl2;  /* VTable relative to the IROTData interface.*/
55
56     ULONG ref; /* reference counter for this object */
57
58     LPOLESTR filePathName; /* path string identified by this filemoniker */
59
60 } FileMonikerImpl;
61
62 /********************************************************************************/
63 /* FileMoniker prototype functions :                                            */
64
65 /* IUnknown prototype functions */
66 static HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
67 static ULONG   WINAPI FileMonikerImpl_AddRef(IMoniker* iface);
68 static ULONG   WINAPI FileMonikerImpl_Release(IMoniker* iface);
69
70 /* IPersist prototype functions */
71 static HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
72
73 /* IPersistStream prototype functions */
74 static HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface);
75 static HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface, IStream* pStm);
76 static HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
77 static HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
78
79 /* IMoniker prototype functions */
80 static HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
81 static HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
82 static HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
83 static HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
84 static HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
85 static HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
86 static HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
87 static HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
88 static HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pFileTime);
89 static HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
90 static HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
91 static HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
92 static HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
93 static HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
94 static HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
95
96 /********************************************************************************/
97 /* IROTData prototype functions                                                 */
98
99 /* IUnknown prototype functions */
100 static HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
101 static ULONG   WINAPI FileMonikerROTDataImpl_AddRef(IROTData* iface);
102 static ULONG   WINAPI FileMonikerROTDataImpl_Release(IROTData* iface);
103
104 /* IROTData prototype function */
105 static HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
106
107 /* Local function used by filemoniker implementation */
108 HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName);
109 HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* iface);
110 int     WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** tabStr);
111
112
113 /********************************************************************************/
114 /* Virtual function table for the FileMonikerImpl class which  include IPersist,*/
115 /* IPersistStream and IMoniker functions.                                       */
116 static IMonikerVtbl VT_FileMonikerImpl =
117 {
118     FileMonikerImpl_QueryInterface,
119     FileMonikerImpl_AddRef,
120     FileMonikerImpl_Release,
121     FileMonikerImpl_GetClassID,
122     FileMonikerImpl_IsDirty,
123     FileMonikerImpl_Load,
124     FileMonikerImpl_Save,
125     FileMonikerImpl_GetSizeMax,
126     FileMonikerImpl_BindToObject,
127     FileMonikerImpl_BindToStorage,
128     FileMonikerImpl_Reduce,
129     FileMonikerImpl_ComposeWith,
130     FileMonikerImpl_Enum,
131     FileMonikerImpl_IsEqual,
132     FileMonikerImpl_Hash,
133     FileMonikerImpl_IsRunning,
134     FileMonikerImpl_GetTimeOfLastChange,
135     FileMonikerImpl_Inverse,
136     FileMonikerImpl_CommonPrefixWith,
137     FileMonikerImpl_RelativePathTo,
138     FileMonikerImpl_GetDisplayName,
139     FileMonikerImpl_ParseDisplayName,
140     FileMonikerImpl_IsSystemMoniker
141 };
142
143 /********************************************************************************/
144 /* Virtual function table for the IROTData class.                               */
145 static IROTDataVtbl VT_ROTDataImpl =
146 {
147     FileMonikerROTDataImpl_QueryInterface,
148     FileMonikerROTDataImpl_AddRef,
149     FileMonikerROTDataImpl_Release,
150     FileMonikerROTDataImpl_GetComparaisonData
151 };
152
153 /*******************************************************************************
154  *        FileMoniker_QueryInterface
155  *******************************************************************************/
156 HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
157 {
158     FileMonikerImpl *This = (FileMonikerImpl *)iface;
159
160   TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
161
162     /* Perform a sanity check on the parameters.*/
163     if ( (This==0) || (ppvObject==0) )
164         return E_INVALIDARG;
165
166     /* Initialize the return parameter */
167   *ppvObject = 0;
168
169     /* Compare the riid with the interface IDs implemented by this object.*/
170     if (IsEqualIID(&IID_IUnknown, riid)      ||
171         IsEqualIID(&IID_IPersist, riid)      ||
172         IsEqualIID(&IID_IPersistStream,riid) ||
173         IsEqualIID(&IID_IMoniker, riid)
174        )
175         *ppvObject = iface;
176
177     else if (IsEqualIID(&IID_IROTData, riid))
178         *ppvObject = (IROTData*)&(This->lpvtbl2);
179
180     /* Check that we obtained an interface.*/
181     if ((*ppvObject)==0)
182         return E_NOINTERFACE;
183
184     /* Query Interface always increases the reference count by one when it is successful */
185   FileMonikerImpl_AddRef(iface);
186
187     return S_OK;
188 }
189
190 /******************************************************************************
191  *        FileMoniker_AddRef
192  ******************************************************************************/
193 ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface)
194 {
195     FileMonikerImpl *This = (FileMonikerImpl *)iface;
196
197     TRACE("(%p)\n",iface);
198
199     return InterlockedIncrement(&This->ref);
200 }
201
202 /******************************************************************************
203  *        FileMoniker_Release
204  ******************************************************************************/
205 ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface)
206 {
207     FileMonikerImpl *This = (FileMonikerImpl *)iface;
208     ULONG ref;
209
210     TRACE("(%p)\n",iface);
211
212     ref = InterlockedDecrement(&This->ref);
213
214     /* destroy the object if there's no more reference on it */
215     if (ref == 0) FileMonikerImpl_Destroy(This);
216
217     return ref;
218 }
219
220 /******************************************************************************
221  *        FileMoniker_GetClassID
222  ******************************************************************************/
223 HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface,
224                                           CLSID *pClassID)/* Pointer to CLSID of object */
225 {
226     TRACE("(%p,%p),stub!\n",iface,pClassID);
227
228     if (pClassID==NULL)
229         return E_POINTER;
230
231     *pClassID = CLSID_FileMoniker;
232
233     return S_OK;
234 }
235
236 /******************************************************************************
237  *        FileMoniker_IsDirty
238  ******************************************************************************/
239 HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface)
240 {
241     /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
242        method in the OLE-provided moniker interfaces always return S_FALSE because
243        their internal state never changes. */
244
245     TRACE("(%p)\n",iface);
246
247     return S_FALSE;
248 }
249
250 /******************************************************************************
251  *        FileMoniker_Load
252  ******************************************************************************/
253 HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm)
254 {
255     HRESULT res;
256     CHAR* filePathA;
257     WCHAR* filePathW;
258     ULONG bread;
259     WORD  wbuffer;
260     DWORD dwbuffer,length,i,doubleLenHex,doubleLenDec;
261
262     FileMonikerImpl *This = (FileMonikerImpl *)iface;
263
264     TRACE("(%p,%p)\n",iface,pStm);
265
266     /* this function locates and reads from the stream the filePath string written by FileMonikerImpl_Save */
267
268     /* first WORD is non significative */
269     res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
270     if (bread!=sizeof(WORD) || wbuffer!=0)
271         return E_FAIL;
272
273     /* read filePath string length (plus one) */
274     res=IStream_Read(pStm,&length,sizeof(DWORD),&bread);
275     if (bread != sizeof(DWORD))
276         return E_FAIL;
277
278     /* read filePath string */
279     filePathA=HeapAlloc(GetProcessHeap(),0,length);
280     res=IStream_Read(pStm,filePathA,length,&bread);
281     HeapFree(GetProcessHeap(),0,filePathA);
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         HeapFree(GetProcessHeap(), 0, filePathW);
325         return E_FAIL;
326     }
327
328     if (This->filePathName!=NULL)
329         HeapFree(GetProcessHeap(),0,This->filePathName);
330
331     This->filePathName=filePathW;
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     FileMonikerImpl *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     FileMonikerImpl *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->u.LowPart=sizeMAx;
460     pcbSize->u.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     static const WCHAR twoPoint[]={'.','.',0};
474     static const 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     FileMonikerImpl *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 before ! we don't 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                 return E_FAIL;
709             else
710                 return E_NOINTERFACE;
711     }
712     else {
713
714         FIXME("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject);
715
716         return E_NOTIMPL;
717     }
718     return res;
719 }
720
721 /******************************************************************************
722  *        FileMoniker_Reduce
723  ******************************************************************************/
724 HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,
725                                       IBindCtx* pbc,
726                                       DWORD dwReduceHowFar,
727                                       IMoniker** ppmkToLeft,
728                                       IMoniker** ppmkReduced)
729 {
730     TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
731
732     if (ppmkReduced==NULL)
733         return E_POINTER;
734
735     FileMonikerImpl_AddRef(iface);
736
737     *ppmkReduced=iface;
738
739     return MK_S_REDUCED_TO_SELF;
740 }
741 /******************************************************************************
742  *        FileMoniker_ComposeWith
743  ******************************************************************************/
744 HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,
745                                            IMoniker* pmkRight,
746                                            BOOL fOnlyIfNotGeneric,
747                                            IMoniker** ppmkComposite)
748 {
749     HRESULT res;
750     LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0;
751     static const WCHAR twoPoint[]={'.','.',0};
752     static const WCHAR bkSlash[]={'\\',0};
753     IBindCtx *bind=0;
754     int i=0,j=0,lastIdx1=0,lastIdx2=0;
755     DWORD mkSys;
756
757     TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
758
759     if (ppmkComposite==NULL)
760         return E_POINTER;
761
762     if (pmkRight==NULL)
763         return E_INVALIDARG;
764
765     *ppmkComposite=0;
766
767     IMoniker_IsSystemMoniker(pmkRight,&mkSys);
768
769     /* check if we have two filemonikers to compose or not */
770     if(mkSys==MKSYS_FILEMONIKER){
771
772         CreateBindCtx(0,&bind);
773
774         FileMonikerImpl_GetDisplayName(iface,bind,NULL,&str1);
775         IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2);
776
777         /* decompose pathnames of the two monikers : (to prepare the path merge operation ) */
778         lastIdx1=FileMonikerImpl_DecomposePath(str1,&strDec1)-1;
779         lastIdx2=FileMonikerImpl_DecomposePath(str2,&strDec2)-1;
780
781         if ((lastIdx1==-1 && lastIdx2>-1)||(lastIdx1==1 && lstrcmpW(strDec1[0],twoPoint)==0))
782             return MK_E_SYNTAX;
783
784         if(lstrcmpW(strDec1[lastIdx1],bkSlash)==0)
785             lastIdx1--;
786
787         /* for etch "..\" in the left of str2 remove the right element from str1 */
788         for(i=0; ( (lastIdx1>=0) && (strDec2[i]!=NULL) && (lstrcmpW(strDec2[i],twoPoint)==0) ) ;i+=2){
789
790             lastIdx1-=2;
791         }
792
793         /* the length of the composed path string  is raised by the sum of the two paths lengths  */
794         newStr=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(lstrlenW(str1)+lstrlenW(str2)+1));
795
796           if (newStr==NULL)
797                 return E_OUTOFMEMORY;
798
799         /* new path is the concatenation of the rest of str1 and str2 */
800         for(*newStr=0,j=0;j<=lastIdx1;j++)
801             strcatW(newStr,strDec1[j]);
802
803         if ((strDec2[i]==NULL && lastIdx1>-1 && lastIdx2>-1) || lstrcmpW(strDec2[i],bkSlash)!=0)
804             strcatW(newStr,bkSlash);
805
806         for(j=i;j<=lastIdx2;j++)
807             strcatW(newStr,strDec2[j]);
808
809         /* create a new moniker with the new string */
810         res=CreateFileMoniker(newStr,ppmkComposite);
811
812         /* free all strings space memory used by this function */
813         HeapFree(GetProcessHeap(),0,newStr);
814
815         for(i=0; strDec1[i]!=NULL;i++)
816             CoTaskMemFree(strDec1[i]);
817         for(i=0; strDec2[i]!=NULL;i++)
818             CoTaskMemFree(strDec2[i]);
819         CoTaskMemFree(strDec1);
820         CoTaskMemFree(strDec2);
821
822         CoTaskMemFree(str1);
823         CoTaskMemFree(str2);
824
825         return res;
826     }
827     else if(mkSys==MKSYS_ANTIMONIKER){
828
829         *ppmkComposite=NULL;
830         return S_OK;
831     }
832     else if (fOnlyIfNotGeneric){
833
834         *ppmkComposite=NULL;
835         return MK_E_NEEDGENERIC;
836     }
837     else
838
839         return CreateGenericComposite(iface,pmkRight,ppmkComposite);
840 }
841
842 /******************************************************************************
843  *        FileMoniker_Enum
844  ******************************************************************************/
845 HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
846 {
847     TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
848
849     if (ppenumMoniker == NULL)
850         return E_POINTER;
851
852     *ppenumMoniker = NULL;
853
854     return S_OK;
855 }
856
857 /******************************************************************************
858  *        FileMoniker_IsEqual
859  ******************************************************************************/
860 HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
861 {
862     FileMonikerImpl *This = (FileMonikerImpl *)iface;
863     CLSID clsid;
864     LPOLESTR filePath;
865     IBindCtx* bind;
866     HRESULT res;
867
868     TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
869
870     if (pmkOtherMoniker==NULL)
871         return S_FALSE;
872
873     IMoniker_GetClassID(pmkOtherMoniker,&clsid);
874
875     if (!IsEqualCLSID(&clsid,&CLSID_FileMoniker))
876         return S_FALSE;
877
878     res = CreateBindCtx(0,&bind);
879     if (FAILED(res)) return res;
880
881     if (SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&filePath))) {
882         int result = lstrcmpiW(filePath, This->filePathName);
883         CoTaskMemFree(filePath);
884         if ( result == 0 ) return S_OK;
885     }
886     return S_FALSE;
887
888 }
889
890 /******************************************************************************
891  *        FileMoniker_Hash
892  ******************************************************************************/
893 HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
894 {
895     FileMonikerImpl *This = (FileMonikerImpl *)iface;
896
897     int  h = 0,i,skip,len;
898     int  off = 0;
899     LPOLESTR val;
900
901     if (pdwHash==NULL)
902         return E_POINTER;
903
904     val =  This->filePathName;
905     len = lstrlenW(val);
906
907     if (len < 16) {
908         for (i = len ; i > 0; i--) {
909             h = (h * 37) + val[off++];
910         }
911     } else {
912         /* only sample some characters */
913         skip = len / 8;
914         for (i = len ; i > 0; i -= skip, off += skip) {
915             h = (h * 39) + val[off];
916         }
917     }
918
919     *pdwHash=h;
920
921     return S_OK;
922 }
923
924 /******************************************************************************
925  *        FileMoniker_IsRunning
926  ******************************************************************************/
927 HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,
928                                          IBindCtx* pbc,
929                                          IMoniker* pmkToLeft,
930                                          IMoniker* pmkNewlyRunning)
931 {
932     IRunningObjectTable* rot;
933     HRESULT res;
934
935     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
936
937     if ( (pmkNewlyRunning!=NULL) && (IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK) )
938         return S_OK;
939
940     if (pbc==NULL)
941         return E_POINTER;
942
943     res=IBindCtx_GetRunningObjectTable(pbc,&rot);
944
945     if (FAILED(res))
946         return res;
947
948     res = IRunningObjectTable_IsRunning(rot,iface);
949
950     IRunningObjectTable_Release(rot);
951
952     return res;
953 }
954
955 /******************************************************************************
956  *        FileMoniker_GetTimeOfLastChange
957  ******************************************************************************/
958 HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
959                                                    IBindCtx* pbc,
960                                                    IMoniker* pmkToLeft,
961                                                    FILETIME* pFileTime)
962 {
963     FileMonikerImpl *This = (FileMonikerImpl *)iface;
964     IRunningObjectTable* rot;
965     HRESULT res;
966     WIN32_FILE_ATTRIBUTE_DATA info;
967
968     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pFileTime);
969
970     if (pFileTime==NULL)
971         return E_POINTER;
972
973     if (pmkToLeft!=NULL)
974         return E_INVALIDARG;
975
976     res=IBindCtx_GetRunningObjectTable(pbc,&rot);
977
978     if (FAILED(res))
979         return res;
980
981     res= IRunningObjectTable_GetTimeOfLastChange(rot,iface,pFileTime);
982
983     if (FAILED(res)){ /* the moniker is not registered */
984
985         if (!GetFileAttributesExW(This->filePathName,GetFileExInfoStandard,&info))
986             return MK_E_NOOBJECT;
987
988         *pFileTime=info.ftLastWriteTime;
989     }
990
991     return S_OK;
992 }
993
994 /******************************************************************************
995  *        FileMoniker_Inverse
996  ******************************************************************************/
997 HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
998 {
999
1000     TRACE("(%p,%p)\n",iface,ppmk);
1001
1002     return CreateAntiMoniker(ppmk);
1003 }
1004
1005 /******************************************************************************
1006  *        FileMoniker_CommonPrefixWith
1007  ******************************************************************************/
1008 HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1009 {
1010
1011     LPOLESTR pathThis,pathOther,*stringTable1,*stringTable2,commonPath;
1012     IBindCtx *pbind;
1013     DWORD mkSys;
1014     ULONG nb1,nb2,i,sameIdx;
1015     BOOL machimeNameCase=FALSE;
1016
1017     if (ppmkPrefix==NULL)
1018         return E_POINTER;
1019
1020     if (pmkOther==NULL)
1021         return E_INVALIDARG;
1022
1023     *ppmkPrefix=0;
1024
1025     /* check if we have the same type of moniker */
1026     IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1027
1028     if(mkSys==MKSYS_FILEMONIKER){
1029         HRESULT ret;
1030
1031         CreateBindCtx(0,&pbind);
1032
1033         /* create a string based on common part of the two paths */
1034
1035         IMoniker_GetDisplayName(iface,pbind,NULL,&pathThis);
1036         IMoniker_GetDisplayName(pmkOther,pbind,NULL,&pathOther);
1037
1038         nb1=FileMonikerImpl_DecomposePath(pathThis,&stringTable1);
1039         nb2=FileMonikerImpl_DecomposePath(pathOther,&stringTable2);
1040
1041         if (nb1==0 || nb2==0)
1042             return MK_E_NOPREFIX;
1043
1044         commonPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(min(lstrlenW(pathThis),lstrlenW(pathOther))+1));
1045
1046         *commonPath=0;
1047
1048         for(sameIdx=0; ( (stringTable1[sameIdx]!=NULL) &&
1049                          (stringTable2[sameIdx]!=NULL) &&
1050                          (lstrcmpiW(stringTable1[sameIdx],stringTable2[sameIdx])==0)); sameIdx++);
1051
1052         if (sameIdx > 1 && *stringTable1[0]=='\\' && *stringTable2[1]=='\\'){
1053
1054             machimeNameCase=TRUE;
1055
1056             for(i=2;i<sameIdx;i++)
1057
1058                 if( (*stringTable1[i]=='\\') && (i+1 < sameIdx) && (*stringTable1[i+1]=='\\') ){
1059                     machimeNameCase=FALSE;
1060                     break;
1061             }
1062         }
1063
1064         if (machimeNameCase && *stringTable1[sameIdx-1]=='\\')
1065             sameIdx--;
1066
1067         if (machimeNameCase && (sameIdx<=3) && (nb1 > 3 || nb2 > 3) )
1068             ret = MK_E_NOPREFIX;
1069         else
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             ret = CreateFileMoniker(commonPath,ppmkPrefix);
1085         }
1086         HeapFree(GetProcessHeap(),0,commonPath);
1087         return ret;
1088     }
1089     else
1090         return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
1091 }
1092
1093 /******************************************************************************
1094  *        DecomposePath (local function)
1095  ******************************************************************************/
1096 int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)
1097 {
1098     static const WCHAR bSlash[] = {'\\',0};
1099     WCHAR word[MAX_PATH];
1100     int i=0,j,tabIndex=0;
1101     LPOLESTR *strgtable ;
1102
1103     int len=lstrlenW(str);
1104
1105     TRACE("%s, %p\n", debugstr_w(str), *stringTable);
1106
1107     strgtable =CoTaskMemAlloc(len*sizeof(LPOLESTR));
1108
1109     if (strgtable==NULL)
1110         return E_OUTOFMEMORY;
1111
1112     while(str[i]!=0){
1113
1114         if(str[i]==bSlash[0]){
1115
1116             strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR));
1117
1118             if (strgtable[tabIndex]==NULL)
1119                 return E_OUTOFMEMORY;
1120
1121             strcpyW(strgtable[tabIndex++],bSlash);
1122
1123             i++;
1124
1125         }
1126         else {
1127
1128             for(j=0; str[i]!=0 && str[i]!=bSlash[0] ; i++,j++)
1129                 word[j]=str[i];
1130
1131             word[j]=0;
1132
1133             strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1));
1134
1135             if (strgtable[tabIndex]==NULL)
1136                 return E_OUTOFMEMORY;
1137
1138             strcpyW(strgtable[tabIndex++],word);
1139         }
1140     }
1141     strgtable[tabIndex]=NULL;
1142
1143     *stringTable=strgtable;
1144
1145     return tabIndex;
1146 }
1147
1148 /******************************************************************************
1149  *        FileMoniker_RelativePathTo
1150  ******************************************************************************/
1151 HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
1152 {
1153     IBindCtx *bind;
1154     HRESULT res;
1155     LPOLESTR str1=0,str2=0,*tabStr1=0,*tabStr2=0,relPath=0;
1156     DWORD len1=0,len2=0,sameIdx=0,j=0;
1157     static const WCHAR back[] ={'.','.','\\',0};
1158
1159     TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
1160
1161     if (ppmkRelPath==NULL)
1162         return E_POINTER;
1163
1164     if (pmOther==NULL)
1165         return E_INVALIDARG;
1166
1167     res=CreateBindCtx(0,&bind);
1168     if (FAILED(res))
1169         return res;
1170
1171     res=IMoniker_GetDisplayName(iface,bind,NULL,&str1);
1172     if (FAILED(res))
1173         return res;
1174     res=IMoniker_GetDisplayName(pmOther,bind,NULL,&str2);
1175     if (FAILED(res))
1176         return res;
1177
1178     len1=FileMonikerImpl_DecomposePath(str1,&tabStr1);
1179     len2=FileMonikerImpl_DecomposePath(str2,&tabStr2);
1180
1181     if (FAILED(len1) || FAILED(len2))
1182         return E_OUTOFMEMORY;
1183
1184     /* count the number of similar items from the begin of the two paths */
1185     for(sameIdx=0; ( (tabStr1[sameIdx]!=NULL) &&
1186                    (tabStr2[sameIdx]!=NULL) &&
1187                (lstrcmpiW(tabStr1[sameIdx],tabStr2[sameIdx])==0)); sameIdx++);
1188
1189     /* begin the construction of relativePath */
1190     /* if the two paths have a consecutive similar item from the begin ! the relativePath will be composed */
1191     /* by "..\\" in the begin */
1192     relPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(1+lstrlenW(str1)+lstrlenW(str2)));
1193
1194     *relPath=0;
1195
1196     if (len2>0 && !(len1==1 && len2==1 && sameIdx==0))
1197         for(j=sameIdx;(tabStr1[j] != NULL); j++)
1198             if (*tabStr1[j]!='\\')
1199                 strcatW(relPath,back);
1200
1201     /* add items of the second path (similar items with the first path are not included) to the relativePath */
1202     for(j=sameIdx;tabStr2[j]!=NULL;j++)
1203         strcatW(relPath,tabStr2[j]);
1204
1205     res=CreateFileMoniker(relPath,ppmkRelPath);
1206
1207     for(j=0; tabStr1[j]!=NULL;j++)
1208         CoTaskMemFree(tabStr1[j]);
1209     for(j=0; tabStr2[j]!=NULL;j++)
1210         CoTaskMemFree(tabStr2[j]);
1211     CoTaskMemFree(tabStr1);
1212     CoTaskMemFree(tabStr2);
1213     CoTaskMemFree(str1);
1214     CoTaskMemFree(str2);
1215     HeapFree(GetProcessHeap(),0,relPath);
1216
1217     if (len1==0 || len2==0 || (len1==1 && len2==1 && sameIdx==0))
1218         return MK_S_HIM;
1219
1220     return res;
1221 }
1222
1223 /******************************************************************************
1224  *        FileMoniker_GetDisplayName
1225  ******************************************************************************/
1226 HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,
1227                                               IBindCtx* pbc,
1228                                               IMoniker* pmkToLeft,
1229                                               LPOLESTR *ppszDisplayName)
1230 {
1231     FileMonikerImpl *This = (FileMonikerImpl *)iface;
1232
1233     int len=lstrlenW(This->filePathName);
1234
1235     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1236
1237     if (ppszDisplayName==NULL)
1238         return E_POINTER;
1239
1240     if (pmkToLeft!=NULL)
1241         return E_INVALIDARG;
1242
1243     *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
1244     if (*ppszDisplayName==NULL)
1245         return E_OUTOFMEMORY;
1246
1247     strcpyW(*ppszDisplayName,This->filePathName);
1248
1249     return S_OK;
1250 }
1251
1252 /******************************************************************************
1253  *        FileMoniker_ParseDisplayName
1254  ******************************************************************************/
1255 HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,
1256                                                 IBindCtx* pbc,
1257                                                 IMoniker* pmkToLeft,
1258                                                 LPOLESTR pszDisplayName,
1259                                                 ULONG* pchEaten,
1260                                                 IMoniker** ppmkOut)
1261 {
1262     FIXME("(%p,%p,%p,%p,%p,%p),stub!\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
1263     return E_NOTIMPL;
1264 }
1265
1266 /******************************************************************************
1267  *        FileMoniker_IsSystemMoniker
1268  ******************************************************************************/
1269 HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1270 {
1271     TRACE("(%p,%p)\n",iface,pwdMksys);
1272
1273     if (!pwdMksys)
1274         return E_POINTER;
1275
1276     (*pwdMksys)=MKSYS_FILEMONIKER;
1277
1278     return S_OK;
1279 }
1280
1281 /*******************************************************************************
1282  *        FileMonikerIROTData_QueryInterface
1283  *******************************************************************************/
1284 HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1285 {
1286
1287     ICOM_THIS_From_IROTData(IMoniker, iface);
1288
1289     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1290
1291     return FileMonikerImpl_QueryInterface(This, riid, ppvObject);
1292 }
1293
1294 /***********************************************************************
1295  *        FileMonikerIROTData_AddRef
1296  */
1297 ULONG   WINAPI FileMonikerROTDataImpl_AddRef(IROTData *iface)
1298 {
1299     ICOM_THIS_From_IROTData(IMoniker, iface);
1300
1301     TRACE("(%p)\n",This);
1302
1303     return FileMonikerImpl_AddRef(This);
1304 }
1305
1306 /***********************************************************************
1307  *        FileMonikerIROTData_Release
1308  */
1309 ULONG   WINAPI FileMonikerROTDataImpl_Release(IROTData* iface)
1310 {
1311     ICOM_THIS_From_IROTData(IMoniker, iface);
1312
1313     TRACE("(%p)\n",This);
1314
1315     return FileMonikerImpl_Release(This);
1316 }
1317
1318 /******************************************************************************
1319  *        FileMonikerIROTData_GetComparaisonData
1320  ******************************************************************************/
1321 HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1322                                                          BYTE* pbData,
1323                                                          ULONG cbMax,
1324                                                          ULONG* pcbData)
1325 {
1326     FIXME("(),stub!\n");
1327     return E_NOTIMPL;
1328 }
1329
1330 /******************************************************************************
1331  *        CreateFileMoniker (OLE32.@)
1332  ******************************************************************************/
1333 HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk)
1334 {
1335     FileMonikerImpl* newFileMoniker = 0;
1336     HRESULT  hr = E_FAIL;
1337     IID riid=IID_IMoniker;
1338
1339     TRACE("(%p,%p)\n",lpszPathName,ppmk);
1340
1341     if (ppmk==NULL)
1342         return E_POINTER;
1343
1344     if(lpszPathName==NULL)
1345         return MK_E_SYNTAX;
1346
1347     *ppmk=0;
1348
1349     newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
1350
1351     if (newFileMoniker == 0)
1352         return E_OUTOFMEMORY;
1353
1354     hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName);
1355
1356     if (SUCCEEDED(hr))
1357         hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker,&riid,(void**)ppmk);
1358     else
1359         HeapFree(GetProcessHeap(),0,newFileMoniker);
1360
1361     return hr;
1362 }