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