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