mfplat: Remove duplicated GUID entry from attribute tracing.
[wine/zf.git] / dlls / ole32 / filemoniker.c
blobd8c401c89785e75ef746a5e5b6b429c9fbfad386
1 /*
2 * FileMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 * Copyright 2007 Robert Shearman
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <assert.h>
23 #include <stdarg.h>
24 #include <string.h>
26 #define COBJMACROS
27 #define NONAMELESSUNION
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "winnls.h"
33 #include "wine/debug.h"
34 #include "objbase.h"
35 #include "moniker.h"
37 #include "compobj_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
41 /* filemoniker data structure */
42 typedef struct FileMonikerImpl{
43 IMoniker IMoniker_iface;
44 IROTData IROTData_iface;
45 LONG ref;
46 LPOLESTR filePathName; /* path string identified by this filemoniker */
47 IUnknown *pMarshal; /* custom marshaler */
48 } FileMonikerImpl;
50 static inline FileMonikerImpl *impl_from_IMoniker(IMoniker *iface)
52 return CONTAINING_RECORD(iface, FileMonikerImpl, IMoniker_iface);
55 static inline FileMonikerImpl *impl_from_IROTData(IROTData *iface)
57 return CONTAINING_RECORD(iface, FileMonikerImpl, IROTData_iface);
60 /* Local function used by filemoniker implementation */
61 static HRESULT FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName);
62 static HRESULT FileMonikerImpl_Destroy(FileMonikerImpl* iface);
64 /*******************************************************************************
65 * FileMoniker_QueryInterface
67 static HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker *iface, REFIID riid, void **ppvObject)
69 FileMonikerImpl *This = impl_from_IMoniker(iface);
71 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), ppvObject);
73 if (!ppvObject)
74 return E_INVALIDARG;
76 *ppvObject = 0;
78 if (IsEqualIID(&IID_IUnknown, riid) ||
79 IsEqualIID(&IID_IPersist, riid) ||
80 IsEqualIID(&IID_IPersistStream,riid) ||
81 IsEqualIID(&IID_IMoniker, riid) ||
82 IsEqualGUID(&CLSID_FileMoniker, riid))
84 *ppvObject = iface;
86 else if (IsEqualIID(&IID_IROTData, riid))
87 *ppvObject = &This->IROTData_iface;
88 else if (IsEqualIID(&IID_IMarshal, riid))
90 HRESULT hr = S_OK;
91 if (!This->pMarshal)
92 hr = MonikerMarshal_Create(iface, &This->pMarshal);
93 if (hr != S_OK)
94 return hr;
95 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
98 if (!*ppvObject)
99 return E_NOINTERFACE;
101 IMoniker_AddRef(iface);
103 return S_OK;
106 /******************************************************************************
107 * FileMoniker_AddRef
109 static ULONG WINAPI
110 FileMonikerImpl_AddRef(IMoniker* iface)
112 FileMonikerImpl *This = impl_from_IMoniker(iface);
114 TRACE("(%p)\n",iface);
116 return InterlockedIncrement(&This->ref);
119 /******************************************************************************
120 * FileMoniker_Release
122 static ULONG WINAPI
123 FileMonikerImpl_Release(IMoniker* iface)
125 FileMonikerImpl *This = impl_from_IMoniker(iface);
126 ULONG ref;
128 TRACE("(%p)\n",iface);
130 ref = InterlockedDecrement(&This->ref);
132 /* destroy the object if there are no more references to it */
133 if (ref == 0) FileMonikerImpl_Destroy(This);
135 return ref;
138 /******************************************************************************
139 * FileMoniker_GetClassID
141 static HRESULT WINAPI
142 FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID)
144 TRACE("(%p,%p)\n",iface,pClassID);
146 if (pClassID==NULL)
147 return E_POINTER;
149 *pClassID = CLSID_FileMoniker;
151 return S_OK;
154 /******************************************************************************
155 * FileMoniker_IsDirty
157 * Note that the OLE-provided implementations of the IPersistStream::IsDirty
158 * method in the OLE-provided moniker interfaces always return S_FALSE because
159 * their internal state never changes.
161 static HRESULT WINAPI
162 FileMonikerImpl_IsDirty(IMoniker* iface)
165 TRACE("(%p)\n",iface);
167 return S_FALSE;
170 /******************************************************************************
171 * FileMoniker_Load
173 * this function locates and reads from the stream the filePath string
174 * written by FileMonikerImpl_Save
176 static HRESULT WINAPI
177 FileMonikerImpl_Load(IMoniker* iface, IStream* pStm)
179 FileMonikerImpl *This = impl_from_IMoniker(iface);
180 HRESULT res;
181 CHAR* filePathA = NULL;
182 WCHAR* filePathW = NULL;
183 ULONG bread;
184 WORD wbuffer;
185 DWORD dwbuffer, bytesA, bytesW, len;
186 int i;
189 TRACE("(%p,%p)\n",iface,pStm);
191 /* first WORD */
192 res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
193 if (bread!=sizeof(WORD))
195 WARN("Couldn't read 0 word\n");
196 goto fail;
199 /* read filePath string length (plus one) */
200 res=IStream_Read(pStm,&bytesA,sizeof(DWORD),&bread);
201 if (bread != sizeof(DWORD))
203 WARN("Couldn't read file string length\n");
204 goto fail;
207 /* read filePath string */
208 filePathA=HeapAlloc(GetProcessHeap(),0,bytesA);
209 if (!filePathA)
211 res = E_OUTOFMEMORY;
212 goto fail;
215 res=IStream_Read(pStm,filePathA,bytesA,&bread);
216 if (bread != bytesA)
218 WARN("Couldn't read file path string\n");
219 goto fail;
222 /* read the unknown value */
223 IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
224 if (bread != sizeof(WORD))
226 WARN("Couldn't read unknown value\n");
227 goto fail;
230 /* read the DEAD constant */
231 IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
232 if (bread != sizeof(WORD))
234 WARN("Couldn't read DEAD constant\n");
235 goto fail;
238 for(i=0;i<5;i++)
240 res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
241 if (bread!=sizeof(DWORD))
243 WARN("Couldn't read 0 padding\n");
244 goto fail;
248 res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
249 if (bread!=sizeof(DWORD))
250 goto fail;
252 if (!dwbuffer) /* No W-string */
254 bytesA--;
255 len=MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, filePathA, bytesA, NULL, 0);
256 if (!len)
257 goto fail;
259 filePathW=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
260 if (!filePathW)
262 res = E_OUTOFMEMORY;
263 goto fail;
265 MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, filePathA, -1, filePathW, len+1);
266 goto succeed;
269 if (dwbuffer < 6)
270 goto fail;
272 bytesW=dwbuffer - 6;
274 res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
275 if (bread!=sizeof(DWORD) || dwbuffer!=bytesW)
276 goto fail;
278 res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
279 if (bread!=sizeof(WORD) || wbuffer!=0x3)
280 goto fail;
282 len=bytesW/sizeof(WCHAR);
283 filePathW=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
284 if(!filePathW)
286 res = E_OUTOFMEMORY;
287 goto fail;
289 res=IStream_Read(pStm,filePathW,bytesW,&bread);
290 if (bread!=bytesW)
291 goto fail;
293 filePathW[len]=0;
295 succeed:
296 HeapFree(GetProcessHeap(),0,filePathA);
297 HeapFree(GetProcessHeap(),0,This->filePathName);
298 This->filePathName=filePathW;
300 return S_OK;
302 fail:
303 HeapFree(GetProcessHeap(), 0, filePathA);
304 HeapFree(GetProcessHeap(), 0, filePathW);
306 if (SUCCEEDED(res))
307 res = E_FAIL;
308 return res;
311 /******************************************************************************
312 * FileMoniker_Save
314 * This function saves data of this object. In the beginning I thought
315 * that I have just to write the filePath string on Stream. But, when I
316 * tested this function with windows program samples, I noticed that it
317 * was not the case. This implementation is based on XP SP2. Other versions
318 * of Windows have minor variations.
320 * Data which must be written on stream is:
321 * 1) WORD constant: zero (not validated by Windows)
322 * 2) length of the path string ("\0" included)
323 * 3) path string type A
324 * 4) Unknown WORD value: Frequently 0xFFFF, but not always. If set very large,
325 * Windows returns E_OUTOFMEMORY
326 * 5) WORD Constant: 0xDEAD (not validated by Windows)
327 * 6) five DWORD constant: zero (not validated by Windows)
328 * 7) If we're only writing the multibyte version,
329 * write a zero DWORD and finish.
331 * 8) DWORD: double-length of the path string type W ("\0" not
332 * included)
333 * 9) WORD constant: 0x3
334 * 10) filePath unicode string.
337 static HRESULT WINAPI
338 FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
340 FileMonikerImpl *This = impl_from_IMoniker(iface);
341 HRESULT res;
342 LPOLESTR filePathW=This->filePathName;
343 CHAR* filePathA;
344 DWORD bytesA, bytesW, len;
346 static const WORD FFFF = 0xFFFF; /* Constants */
347 static const WORD DEAD = 0xDEAD;
348 static const DWORD ZERO = 0;
349 static const WORD THREE = 0x3;
351 int i;
352 BOOL bUsedDefault, bWriteWide;
354 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
356 if (pStm==NULL)
357 return E_POINTER;
359 /* write a 0 WORD */
360 res=IStream_Write(pStm,&ZERO,sizeof(WORD),NULL);
361 if (FAILED(res)) return res;
363 /* write length of filePath string ( 0 included )*/
364 bytesA = WideCharToMultiByte( CP_ACP, 0, filePathW, -1, NULL, 0, NULL, NULL );
365 res=IStream_Write(pStm,&bytesA,sizeof(DWORD),NULL);
366 if (FAILED(res)) return res;
368 /* write A string (with '\0') */
369 filePathA=HeapAlloc(GetProcessHeap(),0,bytesA);
370 if (!filePathA)
371 return E_OUTOFMEMORY;
372 WideCharToMultiByte( CP_ACP, 0, filePathW, -1, filePathA, bytesA, NULL, &bUsedDefault);
373 res=IStream_Write(pStm,filePathA,bytesA,NULL);
374 HeapFree(GetProcessHeap(),0,filePathA);
375 if (FAILED(res)) return res;
377 /* write a WORD 0xFFFF */
378 res=IStream_Write(pStm,&FFFF,sizeof(WORD),NULL);
379 if (FAILED(res)) return res;
381 /* write a WORD 0xDEAD */
382 res=IStream_Write(pStm,&DEAD,sizeof(WORD),NULL);
383 if (FAILED(res)) return res;
385 /* write 5 zero DWORDs */
386 for(i=0;i<5;i++)
388 res=IStream_Write(pStm,&ZERO,sizeof(DWORD),NULL);
389 if (FAILED(res)) return res;
392 /* Write the wide version if:
393 * + couldn't convert to CP_ACP,
394 * or + it's a directory,
395 * or + there's a character > 0xFF
397 len = lstrlenW(filePathW);
398 bWriteWide = (bUsedDefault || (len > 0 && filePathW[len-1]=='\\' ));
399 if (!bWriteWide)
401 WCHAR* pch;
402 for(pch=filePathW;*pch;++pch)
404 if (*pch > 0xFF)
406 bWriteWide = TRUE;
407 break;
412 if (!bWriteWide)
413 return IStream_Write(pStm,&ZERO,sizeof(DWORD),NULL);
415 /* write bytes needed for the filepathW (without 0) + 6 */
416 bytesW = len*sizeof(WCHAR) + 6;
417 res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL);
418 if (FAILED(res)) return res;
420 /* try again, without the extra 6 */
421 bytesW -= 6;
422 res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL);
423 if (FAILED(res)) return res;
425 /* write a WORD 3 */
426 res=IStream_Write(pStm,&THREE,sizeof(WORD),NULL);
427 if (FAILED(res)) return res;
429 /* write W string (no 0) */
430 return IStream_Write(pStm,filePathW,bytesW,NULL);
433 /******************************************************************************
434 * FileMoniker_GetSizeMax
436 static HRESULT WINAPI
437 FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
439 FileMonikerImpl *This = impl_from_IMoniker(iface);
441 TRACE("(%p,%p)\n",iface,pcbSize);
443 if (!pcbSize)
444 return E_POINTER;
446 /* We could calculate exactly (see ...::Save()) but instead
447 * we'll make a quick over-estimate, like Windows (NT4, XP) does.
449 pcbSize->u.LowPart = 0x38 + 4 * lstrlenW(This->filePathName);
450 pcbSize->u.HighPart = 0;
452 return S_OK;
455 /******************************************************************************
456 * FileMoniker_Destroy (local function)
457 *******************************************************************************/
458 HRESULT FileMonikerImpl_Destroy(FileMonikerImpl* This)
460 TRACE("(%p)\n",This);
462 if (This->pMarshal) IUnknown_Release(This->pMarshal);
463 HeapFree(GetProcessHeap(),0,This->filePathName);
464 HeapFree(GetProcessHeap(),0,This);
466 return S_OK;
469 /******************************************************************************
470 * FileMoniker_BindToObject
472 static HRESULT WINAPI
473 FileMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
474 REFIID riid, VOID** ppvResult)
476 FileMonikerImpl *This = impl_from_IMoniker(iface);
477 HRESULT res=E_FAIL;
478 CLSID clsID;
479 IUnknown* pObj=0;
480 IRunningObjectTable *prot=0;
481 IPersistFile *ppf=0;
482 IClassFactory *pcf=0;
483 IClassActivator *pca=0;
485 *ppvResult=0;
487 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
489 if(pmkToLeft==NULL){
491 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
493 if (SUCCEEDED(res)){
494 /* if the requested class was loaded before ! we don't need to reload it */
495 res = IRunningObjectTable_GetObject(prot,iface,&pObj);
497 if (res != S_OK){
498 /* first activation of this class */
499 res=GetClassFile(This->filePathName,&clsID);
500 if (SUCCEEDED(res)){
502 res=CoCreateInstance(&clsID,NULL,CLSCTX_SERVER,&IID_IPersistFile,(void**)&ppf);
503 if (SUCCEEDED(res)){
505 res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
506 if (SUCCEEDED(res)){
508 pObj=(IUnknown*)ppf;
509 IUnknown_AddRef(pObj);
516 else{
517 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassFactory,(void**)&pcf);
519 if (res==E_NOINTERFACE){
521 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassActivator,(void**)&pca);
523 if (res==E_NOINTERFACE)
524 return MK_E_INTERMEDIATEINTERFACENOTSUPPORTED;
526 if (pcf!=NULL){
528 IClassFactory_CreateInstance(pcf,NULL,&IID_IPersistFile,(void**)&ppf);
530 res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
532 if (SUCCEEDED(res)){
534 pObj=(IUnknown*)ppf;
535 IUnknown_AddRef(pObj);
538 if (pca!=NULL){
540 FIXME("()\n");
542 /*res=GetClassFile(This->filePathName,&clsID);
544 if (SUCCEEDED(res)){
546 res=IClassActivator_GetClassObject(pca,&clsID,CLSCTX_ALL,0,&IID_IPersistFile,(void**)&ppf);
548 if (SUCCEEDED(res)){
550 pObj=(IUnknown*)ppf;
551 IUnknown_AddRef(pObj);
557 if (pObj!=NULL){
558 /* get the requested interface from the loaded class */
559 res= IUnknown_QueryInterface(pObj,riid,ppvResult);
561 IBindCtx_RegisterObjectBound(pbc,*ppvResult);
563 IUnknown_Release(pObj);
566 if (prot!=NULL)
567 IRunningObjectTable_Release(prot);
569 if (ppf!=NULL)
570 IPersistFile_Release(ppf);
572 if (pca!=NULL)
573 IClassActivator_Release(pca);
575 if (pcf!=NULL)
576 IClassFactory_Release(pcf);
578 return res;
581 /******************************************************************************
582 * FileMoniker_BindToStorage
584 static HRESULT WINAPI
585 FileMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
586 REFIID riid, VOID** ppvObject)
588 LPOLESTR filePath=0;
589 IStorage *pstg=0;
590 HRESULT res;
592 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
594 if (pmkToLeft==NULL){
596 if (IsEqualIID(&IID_IStorage, riid)){
598 /* get the file name */
599 IMoniker_GetDisplayName(iface,pbc,pmkToLeft,&filePath);
601 res=StgOpenStorage(filePath,NULL,STGM_READWRITE|STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
603 if (SUCCEEDED(res))
604 *ppvObject=pstg;
606 CoTaskMemFree(filePath);
608 else
609 if ( (IsEqualIID(&IID_IStream, riid)) || (IsEqualIID(&IID_ILockBytes, riid)) )
610 return E_FAIL;
611 else
612 return E_NOINTERFACE;
614 else {
616 FIXME("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
618 return E_NOTIMPL;
620 return res;
623 /******************************************************************************
624 * FileMoniker_Reduce
625 ******************************************************************************/
626 static HRESULT WINAPI
627 FileMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
628 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
630 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
632 if (ppmkReduced==NULL)
633 return E_POINTER;
635 IMoniker_AddRef(iface);
637 *ppmkReduced=iface;
639 return MK_S_REDUCED_TO_SELF;
642 static void free_stringtable(LPOLESTR *stringTable)
644 int i;
646 for (i=0; stringTable[i]!=NULL; i++)
647 CoTaskMemFree(stringTable[i]);
648 CoTaskMemFree(stringTable);
651 /******************************************************************************
652 * FileMoniker_ComposeWith
654 static HRESULT WINAPI
655 FileMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
656 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
658 HRESULT res;
659 LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0;
660 IBindCtx *bind=0;
661 int i=0,j=0,lastIdx1=0,lastIdx2=0;
662 DWORD mkSys, order;
664 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
666 if (ppmkComposite==NULL)
667 return E_POINTER;
669 if (pmkRight==NULL)
670 return E_INVALIDARG;
672 *ppmkComposite=0;
674 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
676 /* check if we have two FileMonikers to compose or not */
677 if(mkSys==MKSYS_FILEMONIKER){
679 CreateBindCtx(0,&bind);
681 IMoniker_GetDisplayName(iface,bind,NULL,&str1);
682 IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2);
684 /* decompose pathnames of the two monikers : (to prepare the path merge operation ) */
685 lastIdx1=FileMonikerImpl_DecomposePath(str1,&strDec1)-1;
686 lastIdx2=FileMonikerImpl_DecomposePath(str2,&strDec2)-1;
688 if ((lastIdx1 == -1 && lastIdx2 > -1) || (lastIdx1 == 1 && !wcscmp(strDec1[0], L"..")))
689 res = MK_E_SYNTAX;
690 else{
691 if (!wcscmp(strDec1[lastIdx1], L"\\"))
692 lastIdx1--;
694 /* for each "..\" in the left of str2 remove the right element from str1 */
695 for (i = 0; lastIdx1 >= 0 && strDec2[i] && !wcscmp(strDec2[i], L".."); i += 2)
696 lastIdx1-=2;
698 /* the length of the composed path string is increased by the sum of the two paths' lengths */
699 newStr=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(lstrlenW(str1)+lstrlenW(str2)+1));
701 if (newStr){
702 /* new path is the concatenation of the rest of str1 and str2 */
703 for(*newStr=0,j=0;j<=lastIdx1;j++)
704 lstrcatW(newStr,strDec1[j]);
706 if ((!strDec2[i] && lastIdx1 > -1 && lastIdx2 > -1) || wcscmp(strDec2[i], L"\\"))
707 lstrcatW(newStr, L"\\");
709 for(j=i;j<=lastIdx2;j++)
710 lstrcatW(newStr,strDec2[j]);
712 /* create a new moniker with the new string */
713 res=CreateFileMoniker(newStr,ppmkComposite);
715 /* free string memory used by this function */
716 HeapFree(GetProcessHeap(),0,newStr);
718 else res = E_OUTOFMEMORY;
721 free_stringtable(strDec1);
722 free_stringtable(strDec2);
724 CoTaskMemFree(str1);
725 CoTaskMemFree(str2);
727 return res;
729 else if (is_anti_moniker(pmkRight, &order))
731 return order > 1 ? create_anti_moniker(order - 1, ppmkComposite) : S_OK;
733 else if (fOnlyIfNotGeneric){
735 *ppmkComposite=NULL;
736 return MK_E_NEEDGENERIC;
738 else
740 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
743 /******************************************************************************
744 * FileMoniker_Enum
746 static HRESULT WINAPI
747 FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
749 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
751 if (ppenumMoniker == NULL)
752 return E_POINTER;
754 *ppenumMoniker = NULL;
756 return S_OK;
759 /******************************************************************************
760 * FileMoniker_IsEqual
762 static HRESULT WINAPI
763 FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
765 FileMonikerImpl *This = impl_from_IMoniker(iface);
766 CLSID clsid;
767 LPOLESTR filePath;
768 IBindCtx* bind;
769 HRESULT res;
771 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
773 if (pmkOtherMoniker==NULL)
774 return S_FALSE;
776 IMoniker_GetClassID(pmkOtherMoniker,&clsid);
778 if (!IsEqualCLSID(&clsid,&CLSID_FileMoniker))
779 return S_FALSE;
781 res = CreateBindCtx(0,&bind);
782 if (FAILED(res)) return res;
784 res = S_FALSE;
785 if (SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&filePath))) {
786 if (!lstrcmpiW(filePath, This->filePathName))
787 res = S_OK;
788 CoTaskMemFree(filePath);
791 IBindCtx_Release(bind);
792 return res;
795 /******************************************************************************
796 * FileMoniker_Hash
798 static HRESULT WINAPI
799 FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
801 FileMonikerImpl *This = impl_from_IMoniker(iface);
802 int h = 0,i,skip,len;
803 int off = 0;
804 LPOLESTR val;
806 if (pdwHash==NULL)
807 return E_POINTER;
809 val = This->filePathName;
810 len = lstrlenW(val);
812 if (len < 16) {
813 for (i = len ; i > 0; i--) {
814 h = (h * 37) + val[off++];
816 } else {
817 /* only sample some characters */
818 skip = len / 8;
819 for (i = len ; i > 0; i -= skip, off += skip) {
820 h = (h * 39) + val[off];
824 *pdwHash=h;
826 return S_OK;
829 /******************************************************************************
830 * FileMoniker_IsRunning
832 static HRESULT WINAPI
833 FileMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
834 IMoniker* pmkNewlyRunning)
836 IRunningObjectTable* rot;
837 HRESULT res;
839 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
841 if ( (pmkNewlyRunning!=NULL) && (IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK) )
842 return S_OK;
844 if (pbc==NULL)
845 return E_POINTER;
847 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
849 if (FAILED(res))
850 return res;
852 res = IRunningObjectTable_IsRunning(rot,iface);
854 IRunningObjectTable_Release(rot);
856 return res;
859 /******************************************************************************
860 * FileMoniker_GetTimeOfLastChange
861 ******************************************************************************/
862 static HRESULT WINAPI
863 FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
864 IMoniker* pmkToLeft, FILETIME* pFileTime)
866 FileMonikerImpl *This = impl_from_IMoniker(iface);
867 IRunningObjectTable* rot;
868 HRESULT res;
869 WIN32_FILE_ATTRIBUTE_DATA info;
871 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pFileTime);
873 if (pFileTime==NULL)
874 return E_POINTER;
876 if (pmkToLeft!=NULL)
877 return E_INVALIDARG;
879 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
881 if (FAILED(res))
882 return res;
884 res= IRunningObjectTable_GetTimeOfLastChange(rot,iface,pFileTime);
886 if (FAILED(res)){ /* the moniker is not registered */
888 if (!GetFileAttributesExW(This->filePathName,GetFileExInfoStandard,&info))
889 return MK_E_NOOBJECT;
891 *pFileTime=info.ftLastWriteTime;
894 return S_OK;
897 /******************************************************************************
898 * FileMoniker_Inverse
900 static HRESULT WINAPI
901 FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
903 TRACE("(%p,%p)\n",iface,ppmk);
905 return CreateAntiMoniker(ppmk);
908 /******************************************************************************
909 * FileMoniker_CommonPrefixWith
911 static HRESULT WINAPI
912 FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
915 LPOLESTR pathThis = NULL, pathOther = NULL, *stringTable1 = NULL;
916 LPOLESTR *stringTable2 = NULL, commonPath = NULL;
917 IBindCtx *bindctx;
918 DWORD mkSys;
919 ULONG nb1,nb2,i,sameIdx;
920 BOOL machineNameCase = FALSE;
921 HRESULT ret;
923 if (ppmkPrefix==NULL)
924 return E_POINTER;
926 if (pmkOther==NULL)
927 return E_INVALIDARG;
929 *ppmkPrefix=0;
931 /* check if we have the same type of moniker */
932 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
933 if (mkSys != MKSYS_FILEMONIKER)
934 return MonikerCommonPrefixWith(iface, pmkOther, ppmkPrefix);
936 ret = CreateBindCtx(0, &bindctx);
937 if (FAILED(ret))
938 return ret;
940 /* create a string based on common part of the two paths */
941 ret = IMoniker_GetDisplayName(iface, bindctx, NULL, &pathThis);
942 if (FAILED(ret))
943 goto failed;
945 ret = IMoniker_GetDisplayName(pmkOther, bindctx, NULL, &pathOther);
946 if (FAILED(ret))
947 goto failed;
949 nb1 = FileMonikerImpl_DecomposePath(pathThis, &stringTable1);
950 if (FAILED(nb1)) {
951 ret = nb1;
952 goto failed;
955 nb2 = FileMonikerImpl_DecomposePath(pathOther, &stringTable2);
956 if (FAILED(nb2)) {
957 ret = nb2;
958 goto failed;
961 if (nb1 == 0 || nb2 == 0) {
962 ret = MK_E_NOPREFIX;
963 goto failed;
966 commonPath = CoTaskMemAlloc(sizeof(WCHAR)*(min(lstrlenW(pathThis),lstrlenW(pathOther))+1));
967 if (!commonPath) {
968 ret = E_OUTOFMEMORY;
969 goto failed;
972 *commonPath = 0;
973 for(sameIdx=0; ( (stringTable1[sameIdx]!=NULL) &&
974 (stringTable2[sameIdx]!=NULL) &&
975 (lstrcmpiW(stringTable1[sameIdx],stringTable2[sameIdx])==0)); sameIdx++);
977 if (sameIdx > 1 && *stringTable1[0]=='\\' && *stringTable2[1]=='\\'){
978 machineNameCase = TRUE;
980 for(i=2;i<sameIdx;i++)
981 if( (*stringTable1[i]=='\\') && (i+1 < sameIdx) && (*stringTable1[i+1]=='\\') ){
982 machineNameCase = FALSE;
983 break;
987 if (machineNameCase && *stringTable1[sameIdx-1]=='\\')
988 sameIdx--;
990 if (machineNameCase && (sameIdx<=3) && (nb1 > 3 || nb2 > 3) )
991 ret = MK_E_NOPREFIX;
992 else
994 for (i = 0; i < sameIdx; i++)
995 lstrcatW(commonPath,stringTable1[i]);
996 ret = CreateFileMoniker(commonPath, ppmkPrefix);
999 failed:
1000 IBindCtx_Release(bindctx);
1001 CoTaskMemFree(pathThis);
1002 CoTaskMemFree(pathOther);
1003 CoTaskMemFree(commonPath);
1004 if (stringTable1) free_stringtable(stringTable1);
1005 if (stringTable2) free_stringtable(stringTable2);
1007 return ret;
1010 /******************************************************************************
1011 * DecomposePath (local function)
1013 int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)
1015 LPOLESTR word;
1016 int i=0,j,tabIndex=0, ret=0;
1017 LPOLESTR *strgtable ;
1019 int len=lstrlenW(str);
1021 TRACE("%s, %p\n", debugstr_w(str), *stringTable);
1023 strgtable = CoTaskMemAlloc((len + 1)*sizeof(*strgtable));
1025 if (strgtable==NULL)
1026 return E_OUTOFMEMORY;
1028 word = CoTaskMemAlloc((len + 1)*sizeof(WCHAR));
1030 if (word==NULL)
1032 ret = E_OUTOFMEMORY;
1033 goto lend;
1036 while(str[i]!=0){
1038 if (str[i] == L'\\')
1041 strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR));
1043 if (strgtable[tabIndex]==NULL)
1045 ret = E_OUTOFMEMORY;
1046 goto lend;
1049 lstrcpyW(strgtable[tabIndex++], L"\\");
1051 i++;
1054 else {
1056 for (j = 0; str[i] && str[i] != L'\\'; i++, j++)
1057 word[j]=str[i];
1059 word[j]=0;
1061 strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1));
1063 if (strgtable[tabIndex]==NULL)
1065 ret = E_OUTOFMEMORY;
1066 goto lend;
1069 lstrcpyW(strgtable[tabIndex++],word);
1072 strgtable[tabIndex]=NULL;
1074 *stringTable=strgtable;
1076 ret = tabIndex;
1078 lend:
1079 if (ret < 0)
1081 for (i = 0; i < tabIndex; i++)
1082 CoTaskMemFree(strgtable[i]);
1084 CoTaskMemFree(strgtable);
1087 CoTaskMemFree(word);
1089 return ret;
1092 /******************************************************************************
1093 * FileMoniker_RelativePathTo
1095 static HRESULT WINAPI
1096 FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
1098 IBindCtx *bind;
1099 HRESULT res;
1100 LPOLESTR str1=0,str2=0,*tabStr1=0,*tabStr2=0,relPath=0;
1101 DWORD len1=0,len2=0,sameIdx=0,j=0;
1103 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
1105 if (ppmkRelPath==NULL)
1106 return E_POINTER;
1108 if (pmOther==NULL)
1109 return E_INVALIDARG;
1111 res=CreateBindCtx(0,&bind);
1112 if (FAILED(res))
1113 return res;
1115 res=IMoniker_GetDisplayName(iface,bind,NULL,&str1);
1116 if (FAILED(res))
1117 return res;
1118 res=IMoniker_GetDisplayName(pmOther,bind,NULL,&str2);
1119 if (FAILED(res))
1120 return res;
1122 len1=FileMonikerImpl_DecomposePath(str1,&tabStr1);
1123 if (FAILED(len1))
1124 return E_OUTOFMEMORY;
1125 len2=FileMonikerImpl_DecomposePath(str2,&tabStr2);
1127 if (FAILED(len2))
1129 free_stringtable(tabStr1);
1130 return E_OUTOFMEMORY;
1133 /* count the number of similar items from the begin of the two paths */
1134 for(sameIdx=0; ( (tabStr1[sameIdx]!=NULL) &&
1135 (tabStr2[sameIdx]!=NULL) &&
1136 (lstrcmpiW(tabStr1[sameIdx],tabStr2[sameIdx])==0)); sameIdx++);
1138 /* begin the construction of relativePath */
1139 /* if the two paths have a consecutive similar item from the begin ! the relativePath will be composed */
1140 /* by "..\\" in the begin */
1141 relPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(1+lstrlenW(str1)+lstrlenW(str2)));
1143 *relPath=0;
1145 if (len2>0 && !(len1==1 && len2==1 && sameIdx==0))
1146 for(j=sameIdx;(tabStr1[j] != NULL); j++)
1147 if (*tabStr1[j]!='\\')
1148 lstrcatW(relPath, L"..\\");
1150 /* add items of the second path (similar items with the first path are not included) to the relativePath */
1151 for(j=sameIdx;tabStr2[j]!=NULL;j++)
1152 lstrcatW(relPath,tabStr2[j]);
1154 res=CreateFileMoniker(relPath,ppmkRelPath);
1156 free_stringtable(tabStr1);
1157 free_stringtable(tabStr2);
1158 CoTaskMemFree(str1);
1159 CoTaskMemFree(str2);
1160 HeapFree(GetProcessHeap(),0,relPath);
1162 if (len1==0 || len2==0 || (len1==1 && len2==1 && sameIdx==0))
1163 return MK_S_HIM;
1165 return res;
1168 /******************************************************************************
1169 * FileMoniker_GetDisplayName
1171 static HRESULT WINAPI
1172 FileMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
1173 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
1175 FileMonikerImpl *This = impl_from_IMoniker(iface);
1176 int len=lstrlenW(This->filePathName);
1178 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1180 if (ppszDisplayName==NULL)
1181 return E_POINTER;
1183 if (pmkToLeft!=NULL)
1184 return E_INVALIDARG;
1186 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
1187 if (*ppszDisplayName==NULL)
1188 return E_OUTOFMEMORY;
1190 lstrcpyW(*ppszDisplayName,This->filePathName);
1192 TRACE("-- %s\n", debugstr_w(*ppszDisplayName));
1194 return S_OK;
1197 /******************************************************************************
1198 * FileMoniker_ParseDisplayName
1200 static HRESULT WINAPI
1201 FileMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
1202 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
1204 FIXME("(%p,%p,%p,%p,%p,%p),stub!\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
1205 return E_NOTIMPL;
1208 /******************************************************************************
1209 * FileMoniker_IsSystemMoniker
1211 static HRESULT WINAPI
1212 FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1214 TRACE("(%p,%p)\n",iface,pwdMksys);
1216 if (!pwdMksys)
1217 return E_POINTER;
1219 (*pwdMksys)=MKSYS_FILEMONIKER;
1221 return S_OK;
1224 /*******************************************************************************
1225 * FileMonikerIROTData_QueryInterface
1227 static HRESULT WINAPI
1228 FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1231 FileMonikerImpl *This = impl_from_IROTData(iface);
1233 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1235 return FileMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
1238 /***********************************************************************
1239 * FileMonikerIROTData_AddRef
1241 static ULONG WINAPI
1242 FileMonikerROTDataImpl_AddRef(IROTData *iface)
1244 FileMonikerImpl *This = impl_from_IROTData(iface);
1246 TRACE("(%p)\n",This);
1248 return IMoniker_AddRef(&This->IMoniker_iface);
1251 /***********************************************************************
1252 * FileMonikerIROTData_Release
1254 static ULONG WINAPI
1255 FileMonikerROTDataImpl_Release(IROTData* iface)
1257 FileMonikerImpl *This = impl_from_IROTData(iface);
1259 TRACE("(%p)\n",This);
1261 return FileMonikerImpl_Release(&This->IMoniker_iface);
1264 /******************************************************************************
1265 * FileMonikerIROTData_GetComparisonData
1267 static HRESULT WINAPI
1268 FileMonikerROTDataImpl_GetComparisonData(IROTData* iface, BYTE* pbData,
1269 ULONG cbMax, ULONG* pcbData)
1271 FileMonikerImpl *This = impl_from_IROTData(iface);
1272 int len = lstrlenW(This->filePathName)+1;
1273 int i;
1274 LPWSTR pszFileName;
1276 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
1278 *pcbData = sizeof(CLSID) + len * sizeof(WCHAR);
1279 if (cbMax < *pcbData)
1280 return E_OUTOFMEMORY;
1282 memcpy(pbData, &CLSID_FileMoniker, sizeof(CLSID));
1283 pszFileName = (LPWSTR)(pbData+sizeof(CLSID));
1284 for (i = 0; i < len; i++)
1285 pszFileName[i] = towupper(This->filePathName[i]);
1287 return S_OK;
1291 * Virtual function table for the FileMonikerImpl class which include IPersist,
1292 * IPersistStream and IMoniker functions.
1294 static const IMonikerVtbl VT_FileMonikerImpl =
1296 FileMonikerImpl_QueryInterface,
1297 FileMonikerImpl_AddRef,
1298 FileMonikerImpl_Release,
1299 FileMonikerImpl_GetClassID,
1300 FileMonikerImpl_IsDirty,
1301 FileMonikerImpl_Load,
1302 FileMonikerImpl_Save,
1303 FileMonikerImpl_GetSizeMax,
1304 FileMonikerImpl_BindToObject,
1305 FileMonikerImpl_BindToStorage,
1306 FileMonikerImpl_Reduce,
1307 FileMonikerImpl_ComposeWith,
1308 FileMonikerImpl_Enum,
1309 FileMonikerImpl_IsEqual,
1310 FileMonikerImpl_Hash,
1311 FileMonikerImpl_IsRunning,
1312 FileMonikerImpl_GetTimeOfLastChange,
1313 FileMonikerImpl_Inverse,
1314 FileMonikerImpl_CommonPrefixWith,
1315 FileMonikerImpl_RelativePathTo,
1316 FileMonikerImpl_GetDisplayName,
1317 FileMonikerImpl_ParseDisplayName,
1318 FileMonikerImpl_IsSystemMoniker
1321 /* Virtual function table for the IROTData class. */
1322 static const IROTDataVtbl VT_ROTDataImpl =
1324 FileMonikerROTDataImpl_QueryInterface,
1325 FileMonikerROTDataImpl_AddRef,
1326 FileMonikerROTDataImpl_Release,
1327 FileMonikerROTDataImpl_GetComparisonData
1330 /******************************************************************************
1331 * FileMoniker_Construct (local function)
1333 static HRESULT FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName)
1335 int nb=0,i;
1336 int sizeStr=lstrlenW(lpszPathName);
1337 LPOLESTR *tabStr=0;
1338 BOOL addBkSlash;
1340 TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName));
1342 /* Initialize the virtual function table. */
1343 This->IMoniker_iface.lpVtbl = &VT_FileMonikerImpl;
1344 This->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
1345 This->ref = 0;
1346 This->pMarshal = NULL;
1348 This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1));
1350 if (This->filePathName==NULL)
1351 return E_OUTOFMEMORY;
1353 lstrcpyW(This->filePathName,lpszPathName);
1355 nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr);
1357 if (nb > 0 ){
1359 addBkSlash = TRUE;
1360 if (wcscmp(tabStr[0], L".."))
1361 addBkSlash = FALSE;
1362 else
1363 for(i=0;i<nb;i++){
1365 if (wcscmp(tabStr[i], L"..") && wcscmp(tabStr[i], L"\\"))
1367 addBkSlash = FALSE;
1368 break;
1370 else
1372 if (!wcscmp(tabStr[i], L"\\") && i < nb - 1 && !wcscmp(tabStr[i+1], L"\\"))
1374 *tabStr[i]=0;
1375 sizeStr--;
1376 addBkSlash = FALSE;
1377 break;
1381 if (!wcscmp(tabStr[nb-1], L"\\"))
1382 addBkSlash = FALSE;
1384 This->filePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR));
1386 *This->filePathName=0;
1388 for(i=0;tabStr[i]!=NULL;i++)
1389 lstrcatW(This->filePathName,tabStr[i]);
1391 if (addBkSlash)
1392 lstrcatW(This->filePathName, L"\\");
1395 free_stringtable(tabStr);
1397 return S_OK;
1400 /******************************************************************************
1401 * CreateFileMoniker (OLE32.@)
1402 ******************************************************************************/
1403 HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, IMoniker **ppmk)
1405 FileMonikerImpl* newFileMoniker;
1406 HRESULT hr;
1408 TRACE("(%s,%p)\n",debugstr_w(lpszPathName),ppmk);
1410 if (!ppmk)
1411 return E_POINTER;
1413 if(!lpszPathName)
1414 return MK_E_SYNTAX;
1416 *ppmk=NULL;
1418 newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
1420 if (!newFileMoniker)
1421 return E_OUTOFMEMORY;
1423 hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName);
1425 if (SUCCEEDED(hr))
1426 hr = IMoniker_QueryInterface(&newFileMoniker->IMoniker_iface,&IID_IMoniker,(void**)ppmk);
1427 else
1428 HeapFree(GetProcessHeap(),0,newFileMoniker);
1430 return hr;
1433 /* find a character from a set in reverse without the string having to be null-terminated */
1434 static inline WCHAR *memrpbrkW(const WCHAR *ptr, size_t n, const WCHAR *accept)
1436 const WCHAR *end, *ret = NULL;
1437 for (end = ptr + n; ptr < end; ptr++) if (wcschr(accept, *ptr)) ret = ptr;
1438 return (WCHAR *)ret;
1441 HRESULT FileMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
1442 LPDWORD pchEaten, IMoniker **ppmk)
1444 LPCWSTR end;
1446 for (end = szDisplayName + lstrlenW(szDisplayName);
1447 end && (end != szDisplayName);
1448 end = memrpbrkW(szDisplayName, end - szDisplayName, L":\\/!"))
1450 HRESULT hr;
1451 IRunningObjectTable *rot;
1452 IMoniker *file_moniker;
1453 LPWSTR file_display_name;
1454 LPWSTR full_path_name;
1455 DWORD full_path_name_len;
1456 int len = end - szDisplayName;
1458 file_display_name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
1459 if (!file_display_name) return E_OUTOFMEMORY;
1460 memcpy(file_display_name, szDisplayName, len * sizeof(WCHAR));
1461 file_display_name[len] = '\0';
1463 hr = CreateFileMoniker(file_display_name, &file_moniker);
1464 if (FAILED(hr))
1466 HeapFree(GetProcessHeap(), 0, file_display_name);
1467 return hr;
1470 hr = IBindCtx_GetRunningObjectTable(pbc, &rot);
1471 if (FAILED(hr))
1473 HeapFree(GetProcessHeap(), 0, file_display_name);
1474 IMoniker_Release(file_moniker);
1475 return hr;
1478 hr = IRunningObjectTable_IsRunning(rot, file_moniker);
1479 IRunningObjectTable_Release(rot);
1480 if (FAILED(hr))
1482 HeapFree(GetProcessHeap(), 0, file_display_name);
1483 IMoniker_Release(file_moniker);
1484 return hr;
1486 if (hr == S_OK)
1488 TRACE("found running file moniker for %s\n", debugstr_w(file_display_name));
1489 *pchEaten = len;
1490 *ppmk = file_moniker;
1491 HeapFree(GetProcessHeap(), 0, file_display_name);
1492 return S_OK;
1495 full_path_name_len = GetFullPathNameW(file_display_name, 0, NULL, NULL);
1496 if (!full_path_name_len)
1498 HeapFree(GetProcessHeap(), 0, file_display_name);
1499 IMoniker_Release(file_moniker);
1500 return MK_E_SYNTAX;
1502 full_path_name = HeapAlloc(GetProcessHeap(), 0, full_path_name_len * sizeof(WCHAR));
1503 if (!full_path_name)
1505 HeapFree(GetProcessHeap(), 0, file_display_name);
1506 IMoniker_Release(file_moniker);
1507 return E_OUTOFMEMORY;
1509 GetFullPathNameW(file_display_name, full_path_name_len, full_path_name, NULL);
1511 if (GetFileAttributesW(full_path_name) == INVALID_FILE_ATTRIBUTES)
1512 TRACE("couldn't open file %s\n", debugstr_w(full_path_name));
1513 else
1515 TRACE("got file moniker for %s\n", debugstr_w(szDisplayName));
1516 *pchEaten = len;
1517 *ppmk = file_moniker;
1518 HeapFree(GetProcessHeap(), 0, file_display_name);
1519 HeapFree(GetProcessHeap(), 0, full_path_name);
1520 return S_OK;
1522 HeapFree(GetProcessHeap(), 0, file_display_name);
1523 HeapFree(GetProcessHeap(), 0, full_path_name);
1524 IMoniker_Release(file_moniker);
1527 return MK_E_CANTOPENFILE;
1531 HRESULT WINAPI FileMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv)
1533 FileMonikerImpl* newFileMoniker;
1534 HRESULT hr;
1536 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
1538 *ppv = NULL;
1540 if (pUnk)
1541 return CLASS_E_NOAGGREGATION;
1543 newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
1544 if (!newFileMoniker)
1545 return E_OUTOFMEMORY;
1547 hr = FileMonikerImpl_Construct(newFileMoniker, L"");
1549 if (SUCCEEDED(hr))
1550 hr = IMoniker_QueryInterface(&newFileMoniker->IMoniker_iface, riid, ppv);
1551 if (FAILED(hr))
1552 HeapFree(GetProcessHeap(),0,newFileMoniker);
1554 return hr;