Ref count increment/decrement cleanup.
[wine/multimedia.git] / dlls / ole32 / filemoniker.c
blobe01763d50108708f6d2b909a618a09a069933b6d
1 /***************************************************************************************
2 * FileMonikers implementation
4 * Copyright 1999 Noomen Hamza
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.
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.
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 ***************************************************************************************/
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <string.h>
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "winnls.h"
31 #include "wine/unicode.h"
32 #include "wine/debug.h"
33 #include "objbase.h"
34 #include "moniker.h"
36 #include "compobj_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40 const CLSID CLSID_FileMoniker = {
41 0x303, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
44 /* filemoniker data structure */
45 typedef struct FileMonikerImpl{
47 IMonikerVtbl* lpvtbl1; /* VTable relative to the IMoniker interface.*/
49 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
50 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
52 IROTDataVtbl* lpvtbl2; /* VTable relative to the IROTData interface.*/
54 ULONG ref; /* reference counter for this object */
56 LPOLESTR filePathName; /* path string identified by this filemoniker */
58 } FileMonikerImpl;
60 /********************************************************************************/
61 /* FileMoniker prototype functions : */
63 /* IUnknown prototype functions */
64 static HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
65 static ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface);
66 static ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface);
68 /* IPersist prototype functions */
69 static HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
71 /* IPersistStream prototype functions */
72 static HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface);
73 static HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface, IStream* pStm);
74 static HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
75 static HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
77 /* IMoniker prototype functions */
78 static HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
79 static HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
80 static HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
81 static HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
82 static HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
83 static HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
84 static HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
85 static HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
86 static HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pFileTime);
87 static HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
88 static HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
89 static HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
90 static HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
91 static HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
92 static HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
94 /********************************************************************************/
95 /* IROTData prototype functions */
97 /* IUnknown prototype functions */
98 static HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
99 static ULONG WINAPI FileMonikerROTDataImpl_AddRef(IROTData* iface);
100 static ULONG WINAPI FileMonikerROTDataImpl_Release(IROTData* iface);
102 /* IROTData prototype function */
103 static HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
105 /* Local function used by filemoniker implementation */
106 HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName);
107 HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* iface);
108 int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** tabStr);
111 /********************************************************************************/
112 /* Virtual function table for the FileMonikerImpl class which include IPersist,*/
113 /* IPersistStream and IMoniker functions. */
114 static IMonikerVtbl VT_FileMonikerImpl =
116 FileMonikerImpl_QueryInterface,
117 FileMonikerImpl_AddRef,
118 FileMonikerImpl_Release,
119 FileMonikerImpl_GetClassID,
120 FileMonikerImpl_IsDirty,
121 FileMonikerImpl_Load,
122 FileMonikerImpl_Save,
123 FileMonikerImpl_GetSizeMax,
124 FileMonikerImpl_BindToObject,
125 FileMonikerImpl_BindToStorage,
126 FileMonikerImpl_Reduce,
127 FileMonikerImpl_ComposeWith,
128 FileMonikerImpl_Enum,
129 FileMonikerImpl_IsEqual,
130 FileMonikerImpl_Hash,
131 FileMonikerImpl_IsRunning,
132 FileMonikerImpl_GetTimeOfLastChange,
133 FileMonikerImpl_Inverse,
134 FileMonikerImpl_CommonPrefixWith,
135 FileMonikerImpl_RelativePathTo,
136 FileMonikerImpl_GetDisplayName,
137 FileMonikerImpl_ParseDisplayName,
138 FileMonikerImpl_IsSystemMoniker
141 /********************************************************************************/
142 /* Virtual function table for the IROTData class. */
143 static IROTDataVtbl VT_ROTDataImpl =
145 FileMonikerROTDataImpl_QueryInterface,
146 FileMonikerROTDataImpl_AddRef,
147 FileMonikerROTDataImpl_Release,
148 FileMonikerROTDataImpl_GetComparaisonData
151 /*******************************************************************************
152 * FileMoniker_QueryInterface
153 *******************************************************************************/
154 HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
156 FileMonikerImpl *This = (FileMonikerImpl *)iface;
158 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
160 /* Perform a sanity check on the parameters.*/
161 if ( (This==0) || (ppvObject==0) )
162 return E_INVALIDARG;
164 /* Initialize the return parameter */
165 *ppvObject = 0;
167 /* Compare the riid with the interface IDs implemented by this object.*/
168 if (IsEqualIID(&IID_IUnknown, riid) ||
169 IsEqualIID(&IID_IPersist, riid) ||
170 IsEqualIID(&IID_IPersistStream,riid) ||
171 IsEqualIID(&IID_IMoniker, riid)
173 *ppvObject = iface;
175 else if (IsEqualIID(&IID_IROTData, riid))
176 *ppvObject = (IROTData*)&(This->lpvtbl2);
178 /* Check that we obtained an interface.*/
179 if ((*ppvObject)==0)
180 return E_NOINTERFACE;
182 /* Query Interface always increases the reference count by one when it is successful */
183 FileMonikerImpl_AddRef(iface);
185 return S_OK;
188 /******************************************************************************
189 * FileMoniker_AddRef
190 ******************************************************************************/
191 ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface)
193 FileMonikerImpl *This = (FileMonikerImpl *)iface;
195 TRACE("(%p)\n",iface);
197 return InterlockedIncrement(&This->ref);
200 /******************************************************************************
201 * FileMoniker_Release
202 ******************************************************************************/
203 ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface)
205 FileMonikerImpl *This = (FileMonikerImpl *)iface;
206 ULONG ref;
208 TRACE("(%p)\n",iface);
210 ref = InterlockedDecrement(&This->ref);
212 /* destroy the object if there's no more reference on it */
213 if (ref == 0) FileMonikerImpl_Destroy(This);
215 return ref;
218 /******************************************************************************
219 * FileMoniker_GetClassID
220 ******************************************************************************/
221 HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface,
222 CLSID *pClassID)/* Pointer to CLSID of object */
224 TRACE("(%p,%p),stub!\n",iface,pClassID);
226 if (pClassID==NULL)
227 return E_POINTER;
229 *pClassID = CLSID_FileMoniker;
231 return S_OK;
234 /******************************************************************************
235 * FileMoniker_IsDirty
236 ******************************************************************************/
237 HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface)
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. */
243 TRACE("(%p)\n",iface);
245 return S_FALSE;
248 /******************************************************************************
249 * FileMoniker_Load
250 ******************************************************************************/
251 HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm)
253 HRESULT res;
254 CHAR* filePathA;
255 WCHAR* filePathW;
256 ULONG bread;
257 WORD wbuffer;
258 DWORD dwbuffer,length,i,doubleLenHex,doubleLenDec;
260 FileMonikerImpl *This = (FileMonikerImpl *)iface;
262 TRACE("(%p,%p)\n",iface,pStm);
264 /* this function locates and reads from the stream the filePath string written by FileMonikerImpl_Save */
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;
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;
276 /* read filePath string */
277 filePathA=HeapAlloc(GetProcessHeap(),0,length);
278 res=IStream_Read(pStm,filePathA,length,&bread);
279 HeapFree(GetProcessHeap(),0,filePathA);
280 if (bread != length)
281 return E_FAIL;
283 /* read the first constant */
284 IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
285 if (bread != sizeof(DWORD) || dwbuffer != 0xDEADFFFF)
286 return E_FAIL;
288 length--;
290 for(i=0;i<10;i++){
291 res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
292 if (bread!=sizeof(WORD) || wbuffer!=0)
293 return E_FAIL;
296 if (length>8)
297 length=0;
299 doubleLenHex=doubleLenDec=2*length;
300 if (length > 5)
301 doubleLenDec+=6;
303 res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
304 if (bread!=sizeof(DWORD) || dwbuffer!=doubleLenDec)
305 return E_FAIL;
307 if (length==0)
308 return res;
310 res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
311 if (bread!=sizeof(DWORD) || dwbuffer!=doubleLenHex)
312 return E_FAIL;
314 res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
315 if (bread!=sizeof(WORD) || wbuffer!=0x3)
316 return E_FAIL;
318 filePathW=HeapAlloc(GetProcessHeap(),0,(length+1)*sizeof(WCHAR));
319 filePathW[length]=0;
320 res=IStream_Read(pStm,filePathW,doubleLenHex,&bread);
321 if (bread!=doubleLenHex) {
322 HeapFree(GetProcessHeap(), 0, filePathW);
323 return E_FAIL;
326 if (This->filePathName!=NULL)
327 HeapFree(GetProcessHeap(),0,This->filePathName);
329 This->filePathName=filePathW;
331 return res;
334 /******************************************************************************
335 * FileMoniker_Save
336 ******************************************************************************/
337 HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface,
338 IStream* pStm,/* pointer to the stream where the object is to be saved */
339 BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
341 /* this function saves data of this object. In the beginning I thougth
342 * that I have just to write the filePath string on Stream. But, when I
343 * tested this function whith windows programs samples, I noticed that it
344 * was not the case. So I analysed data written by this function on
345 * Windows and what this did function exactly ! But I have no idea about
346 * its logic !
347 * I guessed data which must be written on stream is:
348 * 1) WORD constant:zero
349 * 2) length of the path string ("\0" included)
350 * 3) path string type A
351 * 4) DWORD constant : 0xDEADFFFF
352 * 5) ten WORD constant: zero
353 * 6) DWORD: double-length of the the path string type W ("\0" not
354 * included)
355 * 7) WORD constant: 0x3
356 * 8) filePath unicode string.
357 * if the length(filePath) > 8 or length(filePath) == 8 stop at step 5)
360 FileMonikerImpl *This = (FileMonikerImpl *)iface;
362 HRESULT res;
363 LPOLESTR filePathW=This->filePathName;
364 CHAR* filePathA;
365 DWORD len;
367 DWORD constant1 = 0xDEADFFFF; /* these constants are detected after analysing the data structure written by */
368 WORD constant2 = 0x3; /* FileMoniker_Save function in a windows program system */
370 WORD zero=0;
371 DWORD doubleLenHex;
372 DWORD doubleLenDec;
373 int i=0;
375 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
377 if (pStm==NULL)
378 return E_POINTER;
380 /* write a DWORD set to 0 : constant */
381 res=IStream_Write(pStm,&zero,sizeof(WORD),NULL);
383 /* write length of filePath string ( "\0" included )*/
384 len = WideCharToMultiByte( CP_ACP, 0, filePathW, -1, NULL, 0, NULL, NULL );
385 res=IStream_Write(pStm,&len,sizeof(DWORD),NULL);
387 /* write filePath string type A */
388 filePathA=HeapAlloc(GetProcessHeap(),0,len);
389 WideCharToMultiByte( CP_ACP, 0, filePathW, -1, filePathA, len, NULL, NULL );
390 res=IStream_Write(pStm,filePathA,len,NULL);
391 HeapFree(GetProcessHeap(),0,filePathA);
393 /* write a DWORD set to 0xDEADFFFF: constant */
394 res=IStream_Write(pStm,&constant1,sizeof(DWORD),NULL);
396 len--;
397 /* write 10 times a DWORD set to 0 : constants */
398 for(i=0;i<10;i++)
399 res=IStream_Write(pStm,&zero,sizeof(WORD),NULL);
401 if (len>8)
402 len=0;
404 doubleLenHex=doubleLenDec=2*len;
405 if (len > 5)
406 doubleLenDec+=6;
408 /* write double-length of the path string ( "\0" included )*/
409 res=IStream_Write(pStm,&doubleLenDec,sizeof(DWORD),NULL);
411 if (len==0)
412 return res;
414 /* write double-length (hexa representation) of the path string ( "\0" included ) */
415 res=IStream_Write(pStm,&doubleLenHex,sizeof(DWORD),NULL);
417 /* write a WORD set to 0x3: constant */
418 res=IStream_Write(pStm,&constant2,sizeof(WORD),NULL);
420 /* write path unicode string */
421 res=IStream_Write(pStm,filePathW,doubleLenHex,NULL);
423 return res;
426 /******************************************************************************
427 * FileMoniker_GetSizeMax
428 ******************************************************************************/
429 HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface,
430 ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
432 FileMonikerImpl *This = (FileMonikerImpl *)iface;
433 DWORD len=lstrlenW(This->filePathName);
434 DWORD sizeMAx;
436 TRACE("(%p,%p)\n",iface,pcbSize);
438 if (pcbSize!=NULL)
439 return E_POINTER;
441 /* for more details see FileMonikerImpl_Save coments */
443 sizeMAx = sizeof(WORD) + /* first WORD is 0 */
444 sizeof(DWORD)+ /* length of filePath including "\0" in the end of the string */
445 (len+1)+ /* filePath string */
446 sizeof(DWORD)+ /* constant : 0xDEADFFFF */
447 10*sizeof(WORD)+ /* 10 zero WORD */
448 sizeof(DWORD); /* size of the unicode filePath: "\0" not included */
450 if (len==0 || len > 8)
451 return S_OK;
453 sizeMAx += sizeof(DWORD)+ /* size of the unicode filePath: "\0" not included */
454 sizeof(WORD)+ /* constant : 0x3 */
455 len*sizeof(WCHAR); /* unicde filePath string */
457 pcbSize->u.LowPart=sizeMAx;
458 pcbSize->u.HighPart=0;
460 return S_OK;
463 /******************************************************************************
464 * FileMoniker_Construct (local function)
465 *******************************************************************************/
466 HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName)
468 int nb=0,i;
469 int sizeStr=lstrlenW(lpszPathName);
470 LPOLESTR *tabStr=0;
471 static const WCHAR twoPoint[]={'.','.',0};
472 static const WCHAR bkSlash[]={'\\',0};
473 BYTE addBkSlash;
475 TRACE("(%p,%p)\n",This,lpszPathName);
477 /* Initialize the virtual fgunction table. */
478 This->lpvtbl1 = &VT_FileMonikerImpl;
479 This->lpvtbl2 = &VT_ROTDataImpl;
480 This->ref = 0;
482 This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1));
484 if (This->filePathName==NULL)
485 return E_OUTOFMEMORY;
487 strcpyW(This->filePathName,lpszPathName);
489 nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr);
491 if (nb > 0 ){
493 addBkSlash=1;
494 if (lstrcmpW(tabStr[0],twoPoint)!=0)
495 addBkSlash=0;
496 else
497 for(i=0;i<nb;i++){
499 if ( (lstrcmpW(tabStr[i],twoPoint)!=0) && (lstrcmpW(tabStr[i],bkSlash)!=0) ){
500 addBkSlash=0;
501 break;
503 else
505 if (lstrcmpW(tabStr[i],bkSlash)==0 && i<nb-1 && lstrcmpW(tabStr[i+1],bkSlash)==0){
506 *tabStr[i]=0;
507 sizeStr--;
508 addBkSlash=0;
509 break;
513 if (lstrcmpW(tabStr[nb-1],bkSlash)==0)
514 addBkSlash=0;
516 This->filePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR));
518 *This->filePathName=0;
520 for(i=0;tabStr[i]!=NULL;i++)
521 strcatW(This->filePathName,tabStr[i]);
523 if (addBkSlash)
524 strcatW(This->filePathName,bkSlash);
527 for(i=0; tabStr[i]!=NULL;i++)
528 CoTaskMemFree(tabStr[i]);
529 CoTaskMemFree(tabStr);
531 return S_OK;
534 /******************************************************************************
535 * FileMoniker_Destroy (local function)
536 *******************************************************************************/
537 HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This)
539 TRACE("(%p)\n",This);
541 if (This->filePathName!=NULL)
542 HeapFree(GetProcessHeap(),0,This->filePathName);
544 HeapFree(GetProcessHeap(),0,This);
546 return S_OK;
549 /******************************************************************************
550 * FileMoniker_BindToObject
551 ******************************************************************************/
552 HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,
553 IBindCtx* pbc,
554 IMoniker* pmkToLeft,
555 REFIID riid,
556 VOID** ppvResult)
558 HRESULT res=E_FAIL;
559 CLSID clsID;
560 IUnknown* pObj=0;
561 IRunningObjectTable *prot=0;
562 IPersistFile *ppf=0;
563 IClassFactory *pcf=0;
564 IClassActivator *pca=0;
566 FileMonikerImpl *This = (FileMonikerImpl *)iface;
568 *ppvResult=0;
570 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
572 if(pmkToLeft==NULL){
574 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
576 if (SUCCEEDED(res)){
577 /* if the requested class was loaded before ! we don't need to reload it */
578 res = IRunningObjectTable_GetObject(prot,iface,&pObj);
580 if (res==S_FALSE){
581 /* first activation of this class */
582 res=GetClassFile(This->filePathName,&clsID);
583 if (SUCCEEDED(res)){
585 res=CoCreateInstance(&clsID,NULL,CLSCTX_ALL,&IID_IPersistFile,(void**)&ppf);
586 if (SUCCEEDED(res)){
588 res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
589 if (SUCCEEDED(res)){
591 pObj=(IUnknown*)ppf;
592 IUnknown_AddRef(pObj);
599 else{
600 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassFactory,(void**)&pcf);
602 if (res==E_NOINTERFACE){
604 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassActivator,(void**)&pca);
606 if (res==E_NOINTERFACE)
607 return MK_E_INTERMEDIATEINTERFACENOTSUPPORTED;
609 if (pcf!=NULL){
611 IClassFactory_CreateInstance(pcf,NULL,&IID_IPersistFile,(void**)ppf);
613 res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
615 if (SUCCEEDED(res)){
617 pObj=(IUnknown*)ppf;
618 IUnknown_AddRef(pObj);
621 if (pca!=NULL){
623 FIXME("()\n");
625 /*res=GetClassFile(This->filePathName,&clsID);
627 if (SUCCEEDED(res)){
629 res=IClassActivator_GetClassObject(pca,&clsID,CLSCTX_ALL,0,&IID_IPersistFile,(void**)&ppf);
631 if (SUCCEEDED(res)){
633 pObj=(IUnknown*)ppf;
634 IUnknown_AddRef(pObj);
640 if (pObj!=NULL){
641 /* get the requested interface from the loaded class */
642 res= IUnknown_QueryInterface(pObj,riid,ppvResult);
644 IBindCtx_RegisterObjectBound(pbc,(IUnknown*)*ppvResult);
646 IUnknown_Release(pObj);
649 if (prot!=NULL)
650 IRunningObjectTable_Release(prot);
652 if (ppf!=NULL)
653 IPersistFile_Release(ppf);
655 if (pca!=NULL)
656 IClassActivator_Release(pca);
658 if (pcf!=NULL)
659 IClassFactory_Release(pcf);
661 return res;
664 /******************************************************************************
665 * FileMoniker_BindToStorage
666 ******************************************************************************/
667 HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,
668 IBindCtx* pbc,
669 IMoniker* pmkToLeft,
670 REFIID riid,
671 VOID** ppvObject)
673 LPOLESTR filePath=0;
674 IStorage *pstg=0;
675 HRESULT res;
677 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject);
679 if (pmkToLeft==NULL){
681 if (IsEqualIID(&IID_IStorage, riid)){
683 /* get the file name */
684 FileMonikerImpl_GetDisplayName(iface,pbc,pmkToLeft,&filePath);
686 /* verifie if the file contains a storage object */
687 res=StgIsStorageFile(filePath);
689 if(res==S_OK){
691 res=StgOpenStorage(filePath,NULL,STGM_READWRITE|STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
693 if (SUCCEEDED(res)){
695 *ppvObject=pstg;
697 IStorage_AddRef(pstg);
699 return res;
702 CoTaskMemFree(filePath);
704 else
705 if ( (IsEqualIID(&IID_IStream, riid)) || (IsEqualIID(&IID_ILockBytes, riid)) )
706 return E_FAIL;
707 else
708 return E_NOINTERFACE;
710 else {
712 FIXME("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject);
714 return E_NOTIMPL;
716 return res;
719 /******************************************************************************
720 * FileMoniker_Reduce
721 ******************************************************************************/
722 HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,
723 IBindCtx* pbc,
724 DWORD dwReduceHowFar,
725 IMoniker** ppmkToLeft,
726 IMoniker** ppmkReduced)
728 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
730 if (ppmkReduced==NULL)
731 return E_POINTER;
733 FileMonikerImpl_AddRef(iface);
735 *ppmkReduced=iface;
737 return MK_S_REDUCED_TO_SELF;
739 /******************************************************************************
740 * FileMoniker_ComposeWith
741 ******************************************************************************/
742 HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,
743 IMoniker* pmkRight,
744 BOOL fOnlyIfNotGeneric,
745 IMoniker** ppmkComposite)
747 HRESULT res;
748 LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0;
749 static const WCHAR twoPoint[]={'.','.',0};
750 static const WCHAR bkSlash[]={'\\',0};
751 IBindCtx *bind=0;
752 int i=0,j=0,lastIdx1=0,lastIdx2=0;
753 DWORD mkSys;
755 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
757 if (ppmkComposite==NULL)
758 return E_POINTER;
760 if (pmkRight==NULL)
761 return E_INVALIDARG;
763 *ppmkComposite=0;
765 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
767 /* check if we have two filemonikers to compose or not */
768 if(mkSys==MKSYS_FILEMONIKER){
770 CreateBindCtx(0,&bind);
772 FileMonikerImpl_GetDisplayName(iface,bind,NULL,&str1);
773 IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2);
775 /* decompose pathnames of the two monikers : (to prepare the path merge operation ) */
776 lastIdx1=FileMonikerImpl_DecomposePath(str1,&strDec1)-1;
777 lastIdx2=FileMonikerImpl_DecomposePath(str2,&strDec2)-1;
779 if ((lastIdx1==-1 && lastIdx2>-1)||(lastIdx1==1 && lstrcmpW(strDec1[0],twoPoint)==0))
780 return MK_E_SYNTAX;
782 if(lstrcmpW(strDec1[lastIdx1],bkSlash)==0)
783 lastIdx1--;
785 /* for etch "..\" in the left of str2 remove the right element from str1 */
786 for(i=0; ( (lastIdx1>=0) && (strDec2[i]!=NULL) && (lstrcmpW(strDec2[i],twoPoint)==0) ) ;i+=2){
788 lastIdx1-=2;
791 /* the length of the composed path string is raised by the sum of the two paths lengths */
792 newStr=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(lstrlenW(str1)+lstrlenW(str2)+1));
794 if (newStr==NULL)
795 return E_OUTOFMEMORY;
797 /* new path is the concatenation of the rest of str1 and str2 */
798 for(*newStr=0,j=0;j<=lastIdx1;j++)
799 strcatW(newStr,strDec1[j]);
801 if ((strDec2[i]==NULL && lastIdx1>-1 && lastIdx2>-1) || lstrcmpW(strDec2[i],bkSlash)!=0)
802 strcatW(newStr,bkSlash);
804 for(j=i;j<=lastIdx2;j++)
805 strcatW(newStr,strDec2[j]);
807 /* create a new moniker with the new string */
808 res=CreateFileMoniker(newStr,ppmkComposite);
810 /* free all strings space memory used by this function */
811 HeapFree(GetProcessHeap(),0,newStr);
813 for(i=0; strDec1[i]!=NULL;i++)
814 CoTaskMemFree(strDec1[i]);
815 for(i=0; strDec2[i]!=NULL;i++)
816 CoTaskMemFree(strDec2[i]);
817 CoTaskMemFree(strDec1);
818 CoTaskMemFree(strDec2);
820 CoTaskMemFree(str1);
821 CoTaskMemFree(str2);
823 return res;
825 else if(mkSys==MKSYS_ANTIMONIKER){
827 *ppmkComposite=NULL;
828 return S_OK;
830 else if (fOnlyIfNotGeneric){
832 *ppmkComposite=NULL;
833 return MK_E_NEEDGENERIC;
835 else
837 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
840 /******************************************************************************
841 * FileMoniker_Enum
842 ******************************************************************************/
843 HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
845 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
847 if (ppenumMoniker == NULL)
848 return E_POINTER;
850 *ppenumMoniker = NULL;
852 return S_OK;
855 /******************************************************************************
856 * FileMoniker_IsEqual
857 ******************************************************************************/
858 HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
860 FileMonikerImpl *This = (FileMonikerImpl *)iface;
861 CLSID clsid;
862 LPOLESTR filePath;
863 IBindCtx* bind;
864 HRESULT res;
866 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
868 if (pmkOtherMoniker==NULL)
869 return S_FALSE;
871 IMoniker_GetClassID(pmkOtherMoniker,&clsid);
873 if (!IsEqualCLSID(&clsid,&CLSID_FileMoniker))
874 return S_FALSE;
876 res = CreateBindCtx(0,&bind);
877 if (FAILED(res)) return res;
879 if (SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&filePath))) {
880 int result = lstrcmpiW(filePath, This->filePathName);
881 CoTaskMemFree(filePath);
882 if ( result == 0 ) return S_OK;
884 return S_FALSE;
888 /******************************************************************************
889 * FileMoniker_Hash
890 ******************************************************************************/
891 HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
893 FileMonikerImpl *This = (FileMonikerImpl *)iface;
895 int h = 0,i,skip,len;
896 int off = 0;
897 LPOLESTR val;
899 if (pdwHash==NULL)
900 return E_POINTER;
902 val = This->filePathName;
903 len = lstrlenW(val);
905 if (len < 16) {
906 for (i = len ; i > 0; i--) {
907 h = (h * 37) + val[off++];
909 } else {
910 /* only sample some characters */
911 skip = len / 8;
912 for (i = len ; i > 0; i -= skip, off += skip) {
913 h = (h * 39) + val[off];
917 *pdwHash=h;
919 return S_OK;
922 /******************************************************************************
923 * FileMoniker_IsRunning
924 ******************************************************************************/
925 HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,
926 IBindCtx* pbc,
927 IMoniker* pmkToLeft,
928 IMoniker* pmkNewlyRunning)
930 IRunningObjectTable* rot;
931 HRESULT res;
933 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
935 if ( (pmkNewlyRunning!=NULL) && (IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK) )
936 return S_OK;
938 if (pbc==NULL)
939 return E_POINTER;
941 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
943 if (FAILED(res))
944 return res;
946 res = IRunningObjectTable_IsRunning(rot,iface);
948 IRunningObjectTable_Release(rot);
950 return res;
953 /******************************************************************************
954 * FileMoniker_GetTimeOfLastChange
955 ******************************************************************************/
956 HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
957 IBindCtx* pbc,
958 IMoniker* pmkToLeft,
959 FILETIME* pFileTime)
961 FileMonikerImpl *This = (FileMonikerImpl *)iface;
962 IRunningObjectTable* rot;
963 HRESULT res;
964 WIN32_FILE_ATTRIBUTE_DATA info;
966 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pFileTime);
968 if (pFileTime==NULL)
969 return E_POINTER;
971 if (pmkToLeft!=NULL)
972 return E_INVALIDARG;
974 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
976 if (FAILED(res))
977 return res;
979 res= IRunningObjectTable_GetTimeOfLastChange(rot,iface,pFileTime);
981 if (FAILED(res)){ /* the moniker is not registered */
983 if (!GetFileAttributesExW(This->filePathName,GetFileExInfoStandard,&info))
984 return MK_E_NOOBJECT;
986 *pFileTime=info.ftLastWriteTime;
989 return S_OK;
992 /******************************************************************************
993 * FileMoniker_Inverse
994 ******************************************************************************/
995 HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
998 TRACE("(%p,%p)\n",iface,ppmk);
1000 return CreateAntiMoniker(ppmk);
1003 /******************************************************************************
1004 * FileMoniker_CommonPrefixWith
1005 ******************************************************************************/
1006 HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1009 LPOLESTR pathThis,pathOther,*stringTable1,*stringTable2,commonPath;
1010 IBindCtx *pbind;
1011 DWORD mkSys;
1012 ULONG nb1,nb2,i,sameIdx;
1013 BOOL machimeNameCase=FALSE;
1015 if (ppmkPrefix==NULL)
1016 return E_POINTER;
1018 if (pmkOther==NULL)
1019 return E_INVALIDARG;
1021 *ppmkPrefix=0;
1023 /* check if we have the same type of moniker */
1024 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1026 if(mkSys==MKSYS_FILEMONIKER){
1027 HRESULT ret;
1029 CreateBindCtx(0,&pbind);
1031 /* create a string based on common part of the two paths */
1033 IMoniker_GetDisplayName(iface,pbind,NULL,&pathThis);
1034 IMoniker_GetDisplayName(pmkOther,pbind,NULL,&pathOther);
1036 nb1=FileMonikerImpl_DecomposePath(pathThis,&stringTable1);
1037 nb2=FileMonikerImpl_DecomposePath(pathOther,&stringTable2);
1039 if (nb1==0 || nb2==0)
1040 return MK_E_NOPREFIX;
1042 commonPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(min(lstrlenW(pathThis),lstrlenW(pathOther))+1));
1044 *commonPath=0;
1046 for(sameIdx=0; ( (stringTable1[sameIdx]!=NULL) &&
1047 (stringTable2[sameIdx]!=NULL) &&
1048 (lstrcmpiW(stringTable1[sameIdx],stringTable2[sameIdx])==0)); sameIdx++);
1050 if (sameIdx > 1 && *stringTable1[0]=='\\' && *stringTable2[1]=='\\'){
1052 machimeNameCase=TRUE;
1054 for(i=2;i<sameIdx;i++)
1056 if( (*stringTable1[i]=='\\') && (i+1 < sameIdx) && (*stringTable1[i+1]=='\\') ){
1057 machimeNameCase=FALSE;
1058 break;
1062 if (machimeNameCase && *stringTable1[sameIdx-1]=='\\')
1063 sameIdx--;
1065 if (machimeNameCase && (sameIdx<=3) && (nb1 > 3 || nb2 > 3) )
1066 ret = MK_E_NOPREFIX;
1067 else
1069 for(i=0;i<sameIdx;i++)
1070 strcatW(commonPath,stringTable1[i]);
1072 for(i=0;i<nb1;i++)
1073 CoTaskMemFree(stringTable1[i]);
1075 CoTaskMemFree(stringTable1);
1077 for(i=0;i<nb2;i++)
1078 CoTaskMemFree(stringTable2[i]);
1080 CoTaskMemFree(stringTable2);
1082 ret = CreateFileMoniker(commonPath,ppmkPrefix);
1084 HeapFree(GetProcessHeap(),0,commonPath);
1085 return ret;
1087 else
1088 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
1091 /******************************************************************************
1092 * DecomposePath (local function)
1093 ******************************************************************************/
1094 int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)
1096 static const WCHAR bSlash[] = {'\\',0};
1097 WCHAR word[MAX_PATH];
1098 int i=0,j,tabIndex=0;
1099 LPOLESTR *strgtable ;
1101 int len=lstrlenW(str);
1103 TRACE("%s, %p\n", debugstr_w(str), *stringTable);
1105 strgtable =CoTaskMemAlloc(len*sizeof(LPOLESTR));
1107 if (strgtable==NULL)
1108 return E_OUTOFMEMORY;
1110 while(str[i]!=0){
1112 if(str[i]==bSlash[0]){
1114 strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR));
1116 if (strgtable[tabIndex]==NULL)
1117 return E_OUTOFMEMORY;
1119 strcpyW(strgtable[tabIndex++],bSlash);
1121 i++;
1124 else {
1126 for(j=0; str[i]!=0 && str[i]!=bSlash[0] ; i++,j++)
1127 word[j]=str[i];
1129 word[j]=0;
1131 strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1));
1133 if (strgtable[tabIndex]==NULL)
1134 return E_OUTOFMEMORY;
1136 strcpyW(strgtable[tabIndex++],word);
1139 strgtable[tabIndex]=NULL;
1141 *stringTable=strgtable;
1143 return tabIndex;
1146 /******************************************************************************
1147 * FileMoniker_RelativePathTo
1148 ******************************************************************************/
1149 HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
1151 IBindCtx *bind;
1152 HRESULT res;
1153 LPOLESTR str1=0,str2=0,*tabStr1=0,*tabStr2=0,relPath=0;
1154 DWORD len1=0,len2=0,sameIdx=0,j=0;
1155 static const WCHAR back[] ={'.','.','\\',0};
1157 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
1159 if (ppmkRelPath==NULL)
1160 return E_POINTER;
1162 if (pmOther==NULL)
1163 return E_INVALIDARG;
1165 res=CreateBindCtx(0,&bind);
1166 if (FAILED(res))
1167 return res;
1169 res=IMoniker_GetDisplayName(iface,bind,NULL,&str1);
1170 if (FAILED(res))
1171 return res;
1172 res=IMoniker_GetDisplayName(pmOther,bind,NULL,&str2);
1173 if (FAILED(res))
1174 return res;
1176 len1=FileMonikerImpl_DecomposePath(str1,&tabStr1);
1177 len2=FileMonikerImpl_DecomposePath(str2,&tabStr2);
1179 if (FAILED(len1) || FAILED(len2))
1180 return E_OUTOFMEMORY;
1182 /* count the number of similar items from the begin of the two paths */
1183 for(sameIdx=0; ( (tabStr1[sameIdx]!=NULL) &&
1184 (tabStr2[sameIdx]!=NULL) &&
1185 (lstrcmpiW(tabStr1[sameIdx],tabStr2[sameIdx])==0)); sameIdx++);
1187 /* begin the construction of relativePath */
1188 /* if the two paths have a consecutive similar item from the begin ! the relativePath will be composed */
1189 /* by "..\\" in the begin */
1190 relPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(1+lstrlenW(str1)+lstrlenW(str2)));
1192 *relPath=0;
1194 if (len2>0 && !(len1==1 && len2==1 && sameIdx==0))
1195 for(j=sameIdx;(tabStr1[j] != NULL); j++)
1196 if (*tabStr1[j]!='\\')
1197 strcatW(relPath,back);
1199 /* add items of the second path (similar items with the first path are not included) to the relativePath */
1200 for(j=sameIdx;tabStr2[j]!=NULL;j++)
1201 strcatW(relPath,tabStr2[j]);
1203 res=CreateFileMoniker(relPath,ppmkRelPath);
1205 for(j=0; tabStr1[j]!=NULL;j++)
1206 CoTaskMemFree(tabStr1[j]);
1207 for(j=0; tabStr2[j]!=NULL;j++)
1208 CoTaskMemFree(tabStr2[j]);
1209 CoTaskMemFree(tabStr1);
1210 CoTaskMemFree(tabStr2);
1211 CoTaskMemFree(str1);
1212 CoTaskMemFree(str2);
1213 HeapFree(GetProcessHeap(),0,relPath);
1215 if (len1==0 || len2==0 || (len1==1 && len2==1 && sameIdx==0))
1216 return MK_S_HIM;
1218 return res;
1221 /******************************************************************************
1222 * FileMoniker_GetDisplayName
1223 ******************************************************************************/
1224 HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,
1225 IBindCtx* pbc,
1226 IMoniker* pmkToLeft,
1227 LPOLESTR *ppszDisplayName)
1229 FileMonikerImpl *This = (FileMonikerImpl *)iface;
1231 int len=lstrlenW(This->filePathName);
1233 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1235 if (ppszDisplayName==NULL)
1236 return E_POINTER;
1238 if (pmkToLeft!=NULL)
1239 return E_INVALIDARG;
1241 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
1242 if (*ppszDisplayName==NULL)
1243 return E_OUTOFMEMORY;
1245 strcpyW(*ppszDisplayName,This->filePathName);
1247 return S_OK;
1250 /******************************************************************************
1251 * FileMoniker_ParseDisplayName
1252 ******************************************************************************/
1253 HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,
1254 IBindCtx* pbc,
1255 IMoniker* pmkToLeft,
1256 LPOLESTR pszDisplayName,
1257 ULONG* pchEaten,
1258 IMoniker** ppmkOut)
1260 FIXME("(%p,%p,%p,%p,%p,%p),stub!\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
1261 return E_NOTIMPL;
1264 /******************************************************************************
1265 * FileMoniker_IsSystemMoniker
1266 ******************************************************************************/
1267 HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1269 TRACE("(%p,%p)\n",iface,pwdMksys);
1271 if (!pwdMksys)
1272 return E_POINTER;
1274 (*pwdMksys)=MKSYS_FILEMONIKER;
1276 return S_OK;
1279 /*******************************************************************************
1280 * FileMonikerIROTData_QueryInterface
1281 *******************************************************************************/
1282 HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1285 ICOM_THIS_From_IROTData(IMoniker, iface);
1287 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1289 return FileMonikerImpl_QueryInterface(This, riid, ppvObject);
1292 /***********************************************************************
1293 * FileMonikerIROTData_AddRef
1295 ULONG WINAPI FileMonikerROTDataImpl_AddRef(IROTData *iface)
1297 ICOM_THIS_From_IROTData(IMoniker, iface);
1299 TRACE("(%p)\n",This);
1301 return FileMonikerImpl_AddRef(This);
1304 /***********************************************************************
1305 * FileMonikerIROTData_Release
1307 ULONG WINAPI FileMonikerROTDataImpl_Release(IROTData* iface)
1309 ICOM_THIS_From_IROTData(IMoniker, iface);
1311 TRACE("(%p)\n",This);
1313 return FileMonikerImpl_Release(This);
1316 /******************************************************************************
1317 * FileMonikerIROTData_GetComparaisonData
1318 ******************************************************************************/
1319 HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1320 BYTE* pbData,
1321 ULONG cbMax,
1322 ULONG* pcbData)
1324 FIXME("(),stub!\n");
1325 return E_NOTIMPL;
1328 /******************************************************************************
1329 * CreateFileMoniker (OLE32.@)
1330 ******************************************************************************/
1331 HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk)
1333 FileMonikerImpl* newFileMoniker = 0;
1334 HRESULT hr = E_FAIL;
1335 IID riid=IID_IMoniker;
1337 TRACE("(%p,%p)\n",lpszPathName,ppmk);
1339 if (ppmk==NULL)
1340 return E_POINTER;
1342 if(lpszPathName==NULL)
1343 return MK_E_SYNTAX;
1345 *ppmk=0;
1347 newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
1349 if (newFileMoniker == 0)
1350 return E_OUTOFMEMORY;
1352 hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName);
1354 if (SUCCEEDED(hr))
1355 hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker,&riid,(void**)ppmk);
1356 else
1357 HeapFree(GetProcessHeap(),0,newFileMoniker);
1359 return hr;