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