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