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