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