- Better tracing.
[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,%s,%p)\n",This,debugstr_guid(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)\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     HeapFree(GetProcessHeap(),0,This->filePathName);
329
330     This->filePathName=filePathW;
331
332     return res;
333 }
334
335 /******************************************************************************
336  *        FileMoniker_Save
337  ******************************************************************************/
338 HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface,
339                                     IStream* pStm,/* pointer to the stream where the object is to be saved */
340                                     BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
341 {
342     /* this function saves data of this object. In the beginning I thougth
343      * that I have just to write the filePath string on Stream. But, when I
344      * tested this function whith windows programs samples, I noticed that it
345      * was not the case. So I analysed data written by this function on
346      * Windows and what this did function exactly ! But I have no idea about
347      * its logic !
348      * I guessed data which must be written on stream is:
349      * 1) WORD constant:zero
350      * 2) length of the path string ("\0" included)
351      * 3) path string type A
352      * 4) DWORD constant : 0xDEADFFFF
353      * 5) ten WORD constant: zero
354      * 6) DWORD: double-length of the the path string type W ("\0" not
355      *    included)
356      * 7) WORD constant: 0x3
357      * 8) filePath unicode string.
358      *    if the length(filePath) > 8 or length(filePath) == 8 stop at step 5)
359      */
360
361     FileMonikerImpl *This = (FileMonikerImpl *)iface;
362
363     HRESULT res;
364     LPOLESTR filePathW=This->filePathName;
365     CHAR*     filePathA;
366     DWORD  len;
367
368     DWORD  constant1 = 0xDEADFFFF; /* these constants are detected after analysing the data structure written by */
369     WORD   constant2 = 0x3;        /* FileMoniker_Save function in a windows program system */
370
371     WORD   zero=0;
372     DWORD doubleLenHex;
373     DWORD doubleLenDec;
374     int i=0;
375
376     TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
377
378     if (pStm==NULL)
379         return E_POINTER;
380
381     /* write a DWORD set to 0 : constant */
382     res=IStream_Write(pStm,&zero,sizeof(WORD),NULL);
383
384     /* write length of filePath string ( "\0" included )*/
385     len = WideCharToMultiByte( CP_ACP, 0, filePathW, -1, NULL, 0, NULL, NULL );
386     res=IStream_Write(pStm,&len,sizeof(DWORD),NULL);
387
388     /* write filePath string type A */
389     filePathA=HeapAlloc(GetProcessHeap(),0,len);
390     WideCharToMultiByte( CP_ACP, 0, filePathW, -1, filePathA, len, NULL, NULL );
391     res=IStream_Write(pStm,filePathA,len,NULL);
392     HeapFree(GetProcessHeap(),0,filePathA);
393
394     /* write a DWORD set to 0xDEADFFFF: constant */
395     res=IStream_Write(pStm,&constant1,sizeof(DWORD),NULL);
396
397     len--;
398     /* write 10 times a DWORD set to 0 : constants */
399     for(i=0;i<10;i++)
400         res=IStream_Write(pStm,&zero,sizeof(WORD),NULL);
401
402     if (len>8)
403         len=0;
404
405     doubleLenHex=doubleLenDec=2*len;
406     if (len > 5)
407         doubleLenDec+=6;
408
409     /* write double-length of the path string ( "\0" included )*/
410     res=IStream_Write(pStm,&doubleLenDec,sizeof(DWORD),NULL);
411
412     if (len==0)
413         return res;
414
415     /* write double-length (hexa representation) of the path string ( "\0" included ) */
416     res=IStream_Write(pStm,&doubleLenHex,sizeof(DWORD),NULL);
417
418     /* write a WORD set to 0x3: constant */
419     res=IStream_Write(pStm,&constant2,sizeof(WORD),NULL);
420
421     /* write path unicode string */
422     res=IStream_Write(pStm,filePathW,doubleLenHex,NULL);
423
424     return res;
425 }
426
427 /******************************************************************************
428  *        FileMoniker_GetSizeMax
429  ******************************************************************************/
430 HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface,
431                                           ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
432 {
433     FileMonikerImpl *This = (FileMonikerImpl *)iface;
434     DWORD len=lstrlenW(This->filePathName);
435     DWORD sizeMAx;
436
437     TRACE("(%p,%p)\n",iface,pcbSize);
438
439     if (pcbSize!=NULL)
440         return E_POINTER;
441
442     /* for more details see FileMonikerImpl_Save coments */
443
444     sizeMAx =  sizeof(WORD) +           /* first WORD is 0 */
445                sizeof(DWORD)+           /* length of filePath including "\0" in the end of the string */
446                (len+1)+                 /* filePath string */
447                sizeof(DWORD)+           /* constant : 0xDEADFFFF */
448                10*sizeof(WORD)+         /* 10 zero WORD */
449                sizeof(DWORD);           /* size of the unicode filePath: "\0" not included */
450
451     if (len==0 || len > 8)
452         return S_OK;
453
454     sizeMAx += sizeof(DWORD)+           /* size of the unicode filePath: "\0" not included */
455                sizeof(WORD)+            /* constant : 0x3 */
456                len*sizeof(WCHAR);       /* unicde filePath string */
457
458     pcbSize->u.LowPart=sizeMAx;
459     pcbSize->u.HighPart=0;
460
461     return S_OK;
462 }
463
464 /******************************************************************************
465  *         FileMoniker_Construct (local function)
466  *******************************************************************************/
467 HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName)
468 {
469     int nb=0,i;
470     int sizeStr=lstrlenW(lpszPathName);
471     LPOLESTR *tabStr=0;
472     static const WCHAR twoPoint[]={'.','.',0};
473     static const WCHAR bkSlash[]={'\\',0};
474     BYTE addBkSlash;
475
476     TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName));
477
478     /* Initialize the virtual fgunction table. */
479     This->lpvtbl1      = &VT_FileMonikerImpl;
480     This->lpvtbl2      = &VT_ROTDataImpl;
481     This->ref          = 0;
482
483     This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1));
484
485     if (This->filePathName==NULL)
486         return E_OUTOFMEMORY;
487
488     strcpyW(This->filePathName,lpszPathName);
489
490     nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr);
491
492     if (nb > 0 ){
493
494         addBkSlash=1;
495         if (lstrcmpW(tabStr[0],twoPoint)!=0)
496             addBkSlash=0;
497         else
498             for(i=0;i<nb;i++){
499
500                 if ( (lstrcmpW(tabStr[i],twoPoint)!=0) && (lstrcmpW(tabStr[i],bkSlash)!=0) ){
501                     addBkSlash=0;
502                     break;
503                 }
504                 else
505
506                     if (lstrcmpW(tabStr[i],bkSlash)==0 && i<nb-1 && lstrcmpW(tabStr[i+1],bkSlash)==0){
507                         *tabStr[i]=0;
508                         sizeStr--;
509                         addBkSlash=0;
510                         break;
511                     }
512             }
513
514         if (lstrcmpW(tabStr[nb-1],bkSlash)==0)
515             addBkSlash=0;
516
517         This->filePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR));
518
519         *This->filePathName=0;
520
521         for(i=0;tabStr[i]!=NULL;i++)
522             strcatW(This->filePathName,tabStr[i]);
523
524         if (addBkSlash)
525             strcatW(This->filePathName,bkSlash);
526     }
527
528     for(i=0; tabStr[i]!=NULL;i++)
529         CoTaskMemFree(tabStr[i]);
530     CoTaskMemFree(tabStr);
531
532     return S_OK;
533 }
534
535 /******************************************************************************
536  *        FileMoniker_Destroy (local function)
537  *******************************************************************************/
538 HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This)
539 {
540     TRACE("(%p)\n",This);
541
542     HeapFree(GetProcessHeap(),0,This->filePathName);
543     HeapFree(GetProcessHeap(),0,This);
544
545     return S_OK;
546 }
547
548 /******************************************************************************
549  *                  FileMoniker_BindToObject
550  ******************************************************************************/
551 HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,
552                                             IBindCtx* pbc,
553                                             IMoniker* pmkToLeft,
554                                             REFIID riid,
555                                             VOID** ppvResult)
556 {
557     HRESULT   res=E_FAIL;
558     CLSID     clsID;
559     IUnknown* pObj=0;
560     IRunningObjectTable *prot=0;
561     IPersistFile  *ppf=0;
562     IClassFactory *pcf=0;
563     IClassActivator *pca=0;
564
565     FileMonikerImpl *This = (FileMonikerImpl *)iface;
566
567     *ppvResult=0;
568
569     TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
570
571     if(pmkToLeft==NULL){
572
573         res=IBindCtx_GetRunningObjectTable(pbc,&prot);
574
575         if (SUCCEEDED(res)){
576             /* if the requested class was loaded before ! we don't need to reload it */
577             res = IRunningObjectTable_GetObject(prot,iface,&pObj);
578
579             if (res==S_FALSE){
580                 /* first activation of this class */
581                 res=GetClassFile(This->filePathName,&clsID);
582                 if (SUCCEEDED(res)){
583
584                     res=CoCreateInstance(&clsID,NULL,CLSCTX_ALL,&IID_IPersistFile,(void**)&ppf);
585                     if (SUCCEEDED(res)){
586
587                         res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
588                         if (SUCCEEDED(res)){
589
590                             pObj=(IUnknown*)ppf;
591                             IUnknown_AddRef(pObj);
592                         }
593                     }
594                 }
595             }
596         }
597     }
598     else{
599         res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassFactory,(void**)&pcf);
600
601         if (res==E_NOINTERFACE){
602
603             res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassActivator,(void**)&pca);
604
605             if (res==E_NOINTERFACE)
606                 return MK_E_INTERMEDIATEINTERFACENOTSUPPORTED;
607         }
608         if (pcf!=NULL){
609
610             IClassFactory_CreateInstance(pcf,NULL,&IID_IPersistFile,(void**)ppf);
611
612             res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
613
614             if (SUCCEEDED(res)){
615
616                 pObj=(IUnknown*)ppf;
617                 IUnknown_AddRef(pObj);
618             }
619         }
620         if (pca!=NULL){
621
622             FIXME("()\n");
623
624             /*res=GetClassFile(This->filePathName,&clsID);
625
626             if (SUCCEEDED(res)){
627
628                 res=IClassActivator_GetClassObject(pca,&clsID,CLSCTX_ALL,0,&IID_IPersistFile,(void**)&ppf);
629
630                 if (SUCCEEDED(res)){
631
632                     pObj=(IUnknown*)ppf;
633                     IUnknown_AddRef(pObj);
634                 }
635             }*/
636         }
637     }
638
639     if (pObj!=NULL){
640         /* get the requested interface from the loaded class */
641         res= IUnknown_QueryInterface(pObj,riid,ppvResult);
642
643         IBindCtx_RegisterObjectBound(pbc,(IUnknown*)*ppvResult);
644
645         IUnknown_Release(pObj);
646     }
647
648     if (prot!=NULL)
649         IRunningObjectTable_Release(prot);
650
651     if (ppf!=NULL)
652         IPersistFile_Release(ppf);
653
654     if (pca!=NULL)
655         IClassActivator_Release(pca);
656
657     if (pcf!=NULL)
658         IClassFactory_Release(pcf);
659
660     return res;
661 }
662
663 /******************************************************************************
664  *        FileMoniker_BindToStorage
665  ******************************************************************************/
666 HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,
667                                              IBindCtx* pbc,
668                                              IMoniker* pmkToLeft,
669                                              REFIID riid,
670                                              VOID** ppvObject)
671 {
672     LPOLESTR filePath=0;
673     IStorage *pstg=0;
674     HRESULT res;
675
676     TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
677
678     if (pmkToLeft==NULL){
679
680         if (IsEqualIID(&IID_IStorage, riid)){
681
682             /* get the file name */
683             FileMonikerImpl_GetDisplayName(iface,pbc,pmkToLeft,&filePath);
684
685             /* verifie if the file contains a storage object */
686             res=StgIsStorageFile(filePath);
687
688             if(res==S_OK){
689
690                 res=StgOpenStorage(filePath,NULL,STGM_READWRITE|STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
691
692                 if (SUCCEEDED(res)){
693
694                     *ppvObject=pstg;
695
696                     IStorage_AddRef(pstg);
697
698                     return res;
699                 }
700             }
701             CoTaskMemFree(filePath);
702         }
703         else
704             if ( (IsEqualIID(&IID_IStream, riid)) || (IsEqualIID(&IID_ILockBytes, riid)) )
705                 return E_FAIL;
706             else
707                 return E_NOINTERFACE;
708     }
709     else {
710
711         FIXME("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
712
713         return E_NOTIMPL;
714     }
715     return res;
716 }
717
718 /******************************************************************************
719  *        FileMoniker_Reduce
720  ******************************************************************************/
721 HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,
722                                       IBindCtx* pbc,
723                                       DWORD dwReduceHowFar,
724                                       IMoniker** ppmkToLeft,
725                                       IMoniker** ppmkReduced)
726 {
727     TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
728
729     if (ppmkReduced==NULL)
730         return E_POINTER;
731
732     FileMonikerImpl_AddRef(iface);
733
734     *ppmkReduced=iface;
735
736     return MK_S_REDUCED_TO_SELF;
737 }
738 /******************************************************************************
739  *        FileMoniker_ComposeWith
740  ******************************************************************************/
741 HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,
742                                            IMoniker* pmkRight,
743                                            BOOL fOnlyIfNotGeneric,
744                                            IMoniker** ppmkComposite)
745 {
746     HRESULT res;
747     LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0;
748     static const WCHAR twoPoint[]={'.','.',0};
749     static const WCHAR bkSlash[]={'\\',0};
750     IBindCtx *bind=0;
751     int i=0,j=0,lastIdx1=0,lastIdx2=0;
752     DWORD mkSys;
753
754     TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
755
756     if (ppmkComposite==NULL)
757         return E_POINTER;
758
759     if (pmkRight==NULL)
760         return E_INVALIDARG;
761
762     *ppmkComposite=0;
763
764     IMoniker_IsSystemMoniker(pmkRight,&mkSys);
765
766     /* check if we have two filemonikers to compose or not */
767     if(mkSys==MKSYS_FILEMONIKER){
768
769         CreateBindCtx(0,&bind);
770
771         FileMonikerImpl_GetDisplayName(iface,bind,NULL,&str1);
772         IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2);
773
774         /* decompose pathnames of the two monikers : (to prepare the path merge operation ) */
775         lastIdx1=FileMonikerImpl_DecomposePath(str1,&strDec1)-1;
776         lastIdx2=FileMonikerImpl_DecomposePath(str2,&strDec2)-1;
777
778         if ((lastIdx1==-1 && lastIdx2>-1)||(lastIdx1==1 && lstrcmpW(strDec1[0],twoPoint)==0))
779             return MK_E_SYNTAX;
780
781         if(lstrcmpW(strDec1[lastIdx1],bkSlash)==0)
782             lastIdx1--;
783
784         /* for etch "..\" in the left of str2 remove the right element from str1 */
785         for(i=0; ( (lastIdx1>=0) && (strDec2[i]!=NULL) && (lstrcmpW(strDec2[i],twoPoint)==0) ) ;i+=2){
786
787             lastIdx1-=2;
788         }
789
790         /* the length of the composed path string  is raised by the sum of the two paths lengths  */
791         newStr=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(lstrlenW(str1)+lstrlenW(str2)+1));
792
793           if (newStr==NULL)
794                 return E_OUTOFMEMORY;
795
796         /* new path is the concatenation of the rest of str1 and str2 */
797         for(*newStr=0,j=0;j<=lastIdx1;j++)
798             strcatW(newStr,strDec1[j]);
799
800         if ((strDec2[i]==NULL && lastIdx1>-1 && lastIdx2>-1) || lstrcmpW(strDec2[i],bkSlash)!=0)
801             strcatW(newStr,bkSlash);
802
803         for(j=i;j<=lastIdx2;j++)
804             strcatW(newStr,strDec2[j]);
805
806         /* create a new moniker with the new string */
807         res=CreateFileMoniker(newStr,ppmkComposite);
808
809         /* free all strings space memory used by this function */
810         HeapFree(GetProcessHeap(),0,newStr);
811
812         for(i=0; strDec1[i]!=NULL;i++)
813             CoTaskMemFree(strDec1[i]);
814         for(i=0; strDec2[i]!=NULL;i++)
815             CoTaskMemFree(strDec2[i]);
816         CoTaskMemFree(strDec1);
817         CoTaskMemFree(strDec2);
818
819         CoTaskMemFree(str1);
820         CoTaskMemFree(str2);
821
822         return res;
823     }
824     else if(mkSys==MKSYS_ANTIMONIKER){
825
826         *ppmkComposite=NULL;
827         return S_OK;
828     }
829     else if (fOnlyIfNotGeneric){
830
831         *ppmkComposite=NULL;
832         return MK_E_NEEDGENERIC;
833     }
834     else
835
836         return CreateGenericComposite(iface,pmkRight,ppmkComposite);
837 }
838
839 /******************************************************************************
840  *        FileMoniker_Enum
841  ******************************************************************************/
842 HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
843 {
844     TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
845
846     if (ppenumMoniker == NULL)
847         return E_POINTER;
848
849     *ppenumMoniker = NULL;
850
851     return S_OK;
852 }
853
854 /******************************************************************************
855  *        FileMoniker_IsEqual
856  ******************************************************************************/
857 HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
858 {
859     FileMonikerImpl *This = (FileMonikerImpl *)iface;
860     CLSID clsid;
861     LPOLESTR filePath;
862     IBindCtx* bind;
863     HRESULT res;
864
865     TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
866
867     if (pmkOtherMoniker==NULL)
868         return S_FALSE;
869
870     IMoniker_GetClassID(pmkOtherMoniker,&clsid);
871
872     if (!IsEqualCLSID(&clsid,&CLSID_FileMoniker))
873         return S_FALSE;
874
875     res = CreateBindCtx(0,&bind);
876     if (FAILED(res)) return res;
877
878     if (SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&filePath))) {
879         int result = lstrcmpiW(filePath, This->filePathName);
880         CoTaskMemFree(filePath);
881         if ( result == 0 ) return S_OK;
882     }
883     return S_FALSE;
884
885 }
886
887 /******************************************************************************
888  *        FileMoniker_Hash
889  ******************************************************************************/
890 HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
891 {
892     FileMonikerImpl *This = (FileMonikerImpl *)iface;
893
894     int  h = 0,i,skip,len;
895     int  off = 0;
896     LPOLESTR val;
897
898     if (pdwHash==NULL)
899         return E_POINTER;
900
901     val =  This->filePathName;
902     len = lstrlenW(val);
903
904     if (len < 16) {
905         for (i = len ; i > 0; i--) {
906             h = (h * 37) + val[off++];
907         }
908     } else {
909         /* only sample some characters */
910         skip = len / 8;
911         for (i = len ; i > 0; i -= skip, off += skip) {
912             h = (h * 39) + val[off];
913         }
914     }
915
916     *pdwHash=h;
917
918     return S_OK;
919 }
920
921 /******************************************************************************
922  *        FileMoniker_IsRunning
923  ******************************************************************************/
924 HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,
925                                          IBindCtx* pbc,
926                                          IMoniker* pmkToLeft,
927                                          IMoniker* pmkNewlyRunning)
928 {
929     IRunningObjectTable* rot;
930     HRESULT res;
931
932     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
933
934     if ( (pmkNewlyRunning!=NULL) && (IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK) )
935         return S_OK;
936
937     if (pbc==NULL)
938         return E_POINTER;
939
940     res=IBindCtx_GetRunningObjectTable(pbc,&rot);
941
942     if (FAILED(res))
943         return res;
944
945     res = IRunningObjectTable_IsRunning(rot,iface);
946
947     IRunningObjectTable_Release(rot);
948
949     return res;
950 }
951
952 /******************************************************************************
953  *        FileMoniker_GetTimeOfLastChange
954  ******************************************************************************/
955 HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
956                                                    IBindCtx* pbc,
957                                                    IMoniker* pmkToLeft,
958                                                    FILETIME* pFileTime)
959 {
960     FileMonikerImpl *This = (FileMonikerImpl *)iface;
961     IRunningObjectTable* rot;
962     HRESULT res;
963     WIN32_FILE_ATTRIBUTE_DATA info;
964
965     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pFileTime);
966
967     if (pFileTime==NULL)
968         return E_POINTER;
969
970     if (pmkToLeft!=NULL)
971         return E_INVALIDARG;
972
973     res=IBindCtx_GetRunningObjectTable(pbc,&rot);
974
975     if (FAILED(res))
976         return res;
977
978     res= IRunningObjectTable_GetTimeOfLastChange(rot,iface,pFileTime);
979
980     if (FAILED(res)){ /* the moniker is not registered */
981
982         if (!GetFileAttributesExW(This->filePathName,GetFileExInfoStandard,&info))
983             return MK_E_NOOBJECT;
984
985         *pFileTime=info.ftLastWriteTime;
986     }
987
988     return S_OK;
989 }
990
991 /******************************************************************************
992  *        FileMoniker_Inverse
993  ******************************************************************************/
994 HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
995 {
996
997     TRACE("(%p,%p)\n",iface,ppmk);
998
999     return CreateAntiMoniker(ppmk);
1000 }
1001
1002 /******************************************************************************
1003  *        FileMoniker_CommonPrefixWith
1004  ******************************************************************************/
1005 HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1006 {
1007
1008     LPOLESTR pathThis,pathOther,*stringTable1,*stringTable2,commonPath;
1009     IBindCtx *pbind;
1010     DWORD mkSys;
1011     ULONG nb1,nb2,i,sameIdx;
1012     BOOL machimeNameCase=FALSE;
1013
1014     if (ppmkPrefix==NULL)
1015         return E_POINTER;
1016
1017     if (pmkOther==NULL)
1018         return E_INVALIDARG;
1019
1020     *ppmkPrefix=0;
1021
1022     /* check if we have the same type of moniker */
1023     IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1024
1025     if(mkSys==MKSYS_FILEMONIKER){
1026         HRESULT ret;
1027
1028         CreateBindCtx(0,&pbind);
1029
1030         /* create a string based on common part of the two paths */
1031
1032         IMoniker_GetDisplayName(iface,pbind,NULL,&pathThis);
1033         IMoniker_GetDisplayName(pmkOther,pbind,NULL,&pathOther);
1034
1035         nb1=FileMonikerImpl_DecomposePath(pathThis,&stringTable1);
1036         nb2=FileMonikerImpl_DecomposePath(pathOther,&stringTable2);
1037
1038         if (nb1==0 || nb2==0)
1039             return MK_E_NOPREFIX;
1040
1041         commonPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(min(lstrlenW(pathThis),lstrlenW(pathOther))+1));
1042
1043         *commonPath=0;
1044
1045         for(sameIdx=0; ( (stringTable1[sameIdx]!=NULL) &&
1046                          (stringTable2[sameIdx]!=NULL) &&
1047                          (lstrcmpiW(stringTable1[sameIdx],stringTable2[sameIdx])==0)); sameIdx++);
1048
1049         if (sameIdx > 1 && *stringTable1[0]=='\\' && *stringTable2[1]=='\\'){
1050
1051             machimeNameCase=TRUE;
1052
1053             for(i=2;i<sameIdx;i++)
1054
1055                 if( (*stringTable1[i]=='\\') && (i+1 < sameIdx) && (*stringTable1[i+1]=='\\') ){
1056                     machimeNameCase=FALSE;
1057                     break;
1058             }
1059         }
1060
1061         if (machimeNameCase && *stringTable1[sameIdx-1]=='\\')
1062             sameIdx--;
1063
1064         if (machimeNameCase && (sameIdx<=3) && (nb1 > 3 || nb2 > 3) )
1065             ret = MK_E_NOPREFIX;
1066         else
1067         {
1068             for(i=0;i<sameIdx;i++)
1069                 strcatW(commonPath,stringTable1[i]);
1070     
1071             for(i=0;i<nb1;i++)
1072                 CoTaskMemFree(stringTable1[i]);
1073     
1074             CoTaskMemFree(stringTable1);
1075     
1076             for(i=0;i<nb2;i++)
1077                 CoTaskMemFree(stringTable2[i]);
1078     
1079             CoTaskMemFree(stringTable2);
1080     
1081             ret = CreateFileMoniker(commonPath,ppmkPrefix);
1082         }
1083         HeapFree(GetProcessHeap(),0,commonPath);
1084         return ret;
1085     }
1086     else
1087         return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
1088 }
1089
1090 /******************************************************************************
1091  *        DecomposePath (local function)
1092  ******************************************************************************/
1093 int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)
1094 {
1095     static const WCHAR bSlash[] = {'\\',0};
1096     WCHAR word[MAX_PATH];
1097     int i=0,j,tabIndex=0;
1098     LPOLESTR *strgtable ;
1099
1100     int len=lstrlenW(str);
1101
1102     TRACE("%s, %p\n", debugstr_w(str), *stringTable);
1103
1104     strgtable =CoTaskMemAlloc(len*sizeof(LPOLESTR));
1105
1106     if (strgtable==NULL)
1107         return E_OUTOFMEMORY;
1108
1109     while(str[i]!=0){
1110
1111         if(str[i]==bSlash[0]){
1112
1113             strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR));
1114
1115             if (strgtable[tabIndex]==NULL)
1116                 return E_OUTOFMEMORY;
1117
1118             strcpyW(strgtable[tabIndex++],bSlash);
1119
1120             i++;
1121
1122         }
1123         else {
1124
1125             for(j=0; str[i]!=0 && str[i]!=bSlash[0] ; i++,j++)
1126                 word[j]=str[i];
1127
1128             word[j]=0;
1129
1130             strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1));
1131
1132             if (strgtable[tabIndex]==NULL)
1133                 return E_OUTOFMEMORY;
1134
1135             strcpyW(strgtable[tabIndex++],word);
1136         }
1137     }
1138     strgtable[tabIndex]=NULL;
1139
1140     *stringTable=strgtable;
1141
1142     return tabIndex;
1143 }
1144
1145 /******************************************************************************
1146  *        FileMoniker_RelativePathTo
1147  ******************************************************************************/
1148 HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
1149 {
1150     IBindCtx *bind;
1151     HRESULT res;
1152     LPOLESTR str1=0,str2=0,*tabStr1=0,*tabStr2=0,relPath=0;
1153     DWORD len1=0,len2=0,sameIdx=0,j=0;
1154     static const WCHAR back[] ={'.','.','\\',0};
1155
1156     TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
1157
1158     if (ppmkRelPath==NULL)
1159         return E_POINTER;
1160
1161     if (pmOther==NULL)
1162         return E_INVALIDARG;
1163
1164     res=CreateBindCtx(0,&bind);
1165     if (FAILED(res))
1166         return res;
1167
1168     res=IMoniker_GetDisplayName(iface,bind,NULL,&str1);
1169     if (FAILED(res))
1170         return res;
1171     res=IMoniker_GetDisplayName(pmOther,bind,NULL,&str2);
1172     if (FAILED(res))
1173         return res;
1174
1175     len1=FileMonikerImpl_DecomposePath(str1,&tabStr1);
1176     len2=FileMonikerImpl_DecomposePath(str2,&tabStr2);
1177
1178     if (FAILED(len1) || FAILED(len2))
1179         return E_OUTOFMEMORY;
1180
1181     /* count the number of similar items from the begin of the two paths */
1182     for(sameIdx=0; ( (tabStr1[sameIdx]!=NULL) &&
1183                    (tabStr2[sameIdx]!=NULL) &&
1184                (lstrcmpiW(tabStr1[sameIdx],tabStr2[sameIdx])==0)); sameIdx++);
1185
1186     /* begin the construction of relativePath */
1187     /* if the two paths have a consecutive similar item from the begin ! the relativePath will be composed */
1188     /* by "..\\" in the begin */
1189     relPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(1+lstrlenW(str1)+lstrlenW(str2)));
1190
1191     *relPath=0;
1192
1193     if (len2>0 && !(len1==1 && len2==1 && sameIdx==0))
1194         for(j=sameIdx;(tabStr1[j] != NULL); j++)
1195             if (*tabStr1[j]!='\\')
1196                 strcatW(relPath,back);
1197
1198     /* add items of the second path (similar items with the first path are not included) to the relativePath */
1199     for(j=sameIdx;tabStr2[j]!=NULL;j++)
1200         strcatW(relPath,tabStr2[j]);
1201
1202     res=CreateFileMoniker(relPath,ppmkRelPath);
1203
1204     for(j=0; tabStr1[j]!=NULL;j++)
1205         CoTaskMemFree(tabStr1[j]);
1206     for(j=0; tabStr2[j]!=NULL;j++)
1207         CoTaskMemFree(tabStr2[j]);
1208     CoTaskMemFree(tabStr1);
1209     CoTaskMemFree(tabStr2);
1210     CoTaskMemFree(str1);
1211     CoTaskMemFree(str2);
1212     HeapFree(GetProcessHeap(),0,relPath);
1213
1214     if (len1==0 || len2==0 || (len1==1 && len2==1 && sameIdx==0))
1215         return MK_S_HIM;
1216
1217     return res;
1218 }
1219
1220 /******************************************************************************
1221  *        FileMoniker_GetDisplayName
1222  ******************************************************************************/
1223 HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,
1224                                               IBindCtx* pbc,
1225                                               IMoniker* pmkToLeft,
1226                                               LPOLESTR *ppszDisplayName)
1227 {
1228     FileMonikerImpl *This = (FileMonikerImpl *)iface;
1229
1230     int len=lstrlenW(This->filePathName);
1231
1232     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1233
1234     if (ppszDisplayName==NULL)
1235         return E_POINTER;
1236
1237     if (pmkToLeft!=NULL)
1238         return E_INVALIDARG;
1239
1240     *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
1241     if (*ppszDisplayName==NULL)
1242         return E_OUTOFMEMORY;
1243
1244     strcpyW(*ppszDisplayName,This->filePathName);
1245
1246     TRACE("-- %s\n", debugstr_w(*ppszDisplayName));
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,%s,%p)\n",This,debugstr_guid(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 (OLE32.@)
1331  ******************************************************************************/
1332 HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk)
1333 {
1334     FileMonikerImpl* newFileMoniker;
1335     HRESULT  hr;
1336
1337     TRACE("(%s,%p)\n",debugstr_w(lpszPathName),ppmk);
1338
1339     if (!ppmk)
1340         return E_POINTER;
1341
1342     if(!lpszPathName)
1343         return MK_E_SYNTAX;
1344
1345     *ppmk=NULL;
1346
1347     newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
1348
1349     if (!newFileMoniker)
1350         return E_OUTOFMEMORY;
1351
1352     hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName);
1353
1354     if (SUCCEEDED(hr))
1355         hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker,&IID_IMoniker,(void**)ppmk);
1356     else
1357         HeapFree(GetProcessHeap(),0,newFileMoniker);
1358
1359     return hr;
1360 }