ReactOS  0.4.14-dev-614-gbfd8a84
filemoniker.c
Go to the documentation of this file.
1 /*
2  * FileMonikers implementation
3  *
4  * Copyright 1999 Noomen Hamza
5  * Copyright 2007 Robert Shearman
6  *
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.
11  *
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.
16  *
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
20  */
21 
22 #include <assert.h>
23 #include <stdarg.h>
24 #include <string.h>
25 
26 #define COBJMACROS
27 #define NONAMELESSUNION
28 
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"
36 
37 #include "compobj_private.h"
38 
40 
41 /* filemoniker data structure */
42 typedef struct FileMonikerImpl{
46  LPOLESTR filePathName; /* path string identified by this filemoniker */
47  IUnknown *pMarshal; /* custom marshaler */
49 
51 {
52  return CONTAINING_RECORD(iface, FileMonikerImpl, IMoniker_iface);
53 }
54 
56 {
57  return CONTAINING_RECORD(iface, FileMonikerImpl, IROTData_iface);
58 }
59 
60 /* Local function used by filemoniker implementation */
61 static HRESULT FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName);
63 
64 /*******************************************************************************
65  * FileMoniker_QueryInterface
66  */
67 static HRESULT WINAPI
69 {
71 
72  TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
73 
74  /* Perform a sanity check on the parameters.*/
75  if ( ppvObject==0 )
76  return E_INVALIDARG;
77 
78  /* Initialize the return parameter */
79  *ppvObject = 0;
80 
81  /* Compare the riid with the interface IDs implemented by this object.*/
82  if (IsEqualIID(&IID_IUnknown, riid) ||
85  IsEqualIID(&IID_IMoniker, riid)
86  )
87  *ppvObject = iface;
88 
89  else if (IsEqualIID(&IID_IROTData, riid))
90  *ppvObject = &This->IROTData_iface;
91  else if (IsEqualIID(&IID_IMarshal, riid))
92  {
93  HRESULT hr = S_OK;
94  if (!This->pMarshal)
95  hr = MonikerMarshal_Create(iface, &This->pMarshal);
96  if (hr != S_OK)
97  return hr;
98  return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
99  }
100 
101  /* Check that we obtained an interface.*/
102  if ((*ppvObject)==0)
103  return E_NOINTERFACE;
104 
105  /* Query Interface always increases the reference count by one when it is successful */
106  IMoniker_AddRef(iface);
107 
108  return S_OK;
109 }
110 
111 /******************************************************************************
112  * FileMoniker_AddRef
113  */
114 static ULONG WINAPI
116 {
118 
119  TRACE("(%p)\n",iface);
120 
121  return InterlockedIncrement(&This->ref);
122 }
123 
124 /******************************************************************************
125  * FileMoniker_Release
126  */
127 static ULONG WINAPI
129 {
131  ULONG ref;
132 
133  TRACE("(%p)\n",iface);
134 
135  ref = InterlockedDecrement(&This->ref);
136 
137  /* destroy the object if there are no more references to it */
138  if (ref == 0) FileMonikerImpl_Destroy(This);
139 
140  return ref;
141 }
142 
143 /******************************************************************************
144  * FileMoniker_GetClassID
145  */
146 static HRESULT WINAPI
148 {
149  TRACE("(%p,%p)\n",iface,pClassID);
150 
151  if (pClassID==NULL)
152  return E_POINTER;
153 
154  *pClassID = CLSID_FileMoniker;
155 
156  return S_OK;
157 }
158 
159 /******************************************************************************
160  * FileMoniker_IsDirty
161  *
162  * Note that the OLE-provided implementations of the IPersistStream::IsDirty
163  * method in the OLE-provided moniker interfaces always return S_FALSE because
164  * their internal state never changes.
165  */
166 static HRESULT WINAPI
168 {
169 
170  TRACE("(%p)\n",iface);
171 
172  return S_FALSE;
173 }
174 
175 /******************************************************************************
176  * FileMoniker_Load
177  *
178  * this function locates and reads from the stream the filePath string
179  * written by FileMonikerImpl_Save
180  */
181 static HRESULT WINAPI
183 {
185  HRESULT res;
186  CHAR* filePathA = NULL;
187  WCHAR* filePathW = NULL;
188  ULONG bread;
189  WORD wbuffer;
190  DWORD dwbuffer, bytesA, bytesW, len;
191  int i;
192 
193 
194  TRACE("(%p,%p)\n",iface,pStm);
195 
196  /* first WORD */
197  res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
198  if (bread!=sizeof(WORD))
199  {
200  WARN("Couldn't read 0 word\n");
201  goto fail;
202  }
203 
204  /* read filePath string length (plus one) */
205  res=IStream_Read(pStm,&bytesA,sizeof(DWORD),&bread);
206  if (bread != sizeof(DWORD))
207  {
208  WARN("Couldn't read file string length\n");
209  goto fail;
210  }
211 
212  /* read filePath string */
213  filePathA=HeapAlloc(GetProcessHeap(),0,bytesA);
214  if (!filePathA)
215  {
216  res = E_OUTOFMEMORY;
217  goto fail;
218  }
219 
220  res=IStream_Read(pStm,filePathA,bytesA,&bread);
221  if (bread != bytesA)
222  {
223  WARN("Couldn't read file path string\n");
224  goto fail;
225  }
226 
227  /* read the unknown value */
228  IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
229  if (bread != sizeof(WORD))
230  {
231  WARN("Couldn't read unknown value\n");
232  goto fail;
233  }
234 
235  /* read the DEAD constant */
236  IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
237  if (bread != sizeof(WORD))
238  {
239  WARN("Couldn't read DEAD constant\n");
240  goto fail;
241  }
242 
243  for(i=0;i<5;i++)
244  {
245  res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
246  if (bread!=sizeof(DWORD))
247  {
248  WARN("Couldn't read 0 padding\n");
249  goto fail;
250  }
251  }
252 
253  res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
254  if (bread!=sizeof(DWORD))
255  goto fail;
256 
257  if (!dwbuffer) /* No W-string */
258  {
259  bytesA--;
260  len=MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, filePathA, bytesA, NULL, 0);
261  if (!len)
262  goto fail;
263 
264  filePathW=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
265  if (!filePathW)
266  {
267  res = E_OUTOFMEMORY;
268  goto fail;
269  }
270  MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, filePathA, -1, filePathW, len+1);
271  goto succeed;
272  }
273 
274  if (dwbuffer < 6)
275  goto fail;
276 
277  bytesW=dwbuffer - 6;
278 
279  res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
280  if (bread!=sizeof(DWORD) || dwbuffer!=bytesW)
281  goto fail;
282 
283  res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
284  if (bread!=sizeof(WORD) || wbuffer!=0x3)
285  goto fail;
286 
287  len=bytesW/sizeof(WCHAR);
288  filePathW=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
289  if(!filePathW)
290  {
291  res = E_OUTOFMEMORY;
292  goto fail;
293  }
294  res=IStream_Read(pStm,filePathW,bytesW,&bread);
295  if (bread!=bytesW)
296  goto fail;
297 
298  filePathW[len]=0;
299 
300  succeed:
301  HeapFree(GetProcessHeap(),0,filePathA);
302  HeapFree(GetProcessHeap(),0,This->filePathName);
303  This->filePathName=filePathW;
304 
305  return S_OK;
306 
307  fail:
308  HeapFree(GetProcessHeap(), 0, filePathA);
309  HeapFree(GetProcessHeap(), 0, filePathW);
310 
311  if (SUCCEEDED(res))
312  res = E_FAIL;
313  return res;
314 }
315 
316 /******************************************************************************
317  * FileMoniker_Save
318  *
319  * This function saves data of this object. In the beginning I thought
320  * that I have just to write the filePath string on Stream. But, when I
321  * tested this function with windows program samples, I noticed that it
322  * was not the case. This implementation is based on XP SP2. Other versions
323  * of Windows have minor variations.
324  *
325  * Data which must be written on stream is:
326  * 1) WORD constant: zero (not validated by Windows)
327  * 2) length of the path string ("\0" included)
328  * 3) path string type A
329  * 4) Unknown WORD value: Frequently 0xFFFF, but not always. If set very large,
330  * Windows returns E_OUTOFMEMORY
331  * 5) WORD Constant: 0xDEAD (not validated by Windows)
332  * 6) five DWORD constant: zero (not validated by Windows)
333  * 7) If we're only writing the multibyte version,
334  * write a zero DWORD and finish.
335  *
336  * 8) DWORD: double-length of the path string type W ("\0" not
337  * included)
338  * 9) WORD constant: 0x3
339  * 10) filePath unicode string.
340  *
341  */
342 static HRESULT WINAPI
343 FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
344 {
346  HRESULT res;
347  LPOLESTR filePathW=This->filePathName;
348  CHAR* filePathA;
349  DWORD bytesA, bytesW, len;
350 
351  static const WORD FFFF = 0xFFFF; /* Constants */
352  static const WORD DEAD = 0xDEAD;
353  static const DWORD ZERO = 0;
354  static const WORD THREE = 0x3;
355 
356  int i;
357  BOOL bUsedDefault, bWriteWide;
358 
359  TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
360 
361  if (pStm==NULL)
362  return E_POINTER;
363 
364  /* write a 0 WORD */
365  res=IStream_Write(pStm,&ZERO,sizeof(WORD),NULL);
366  if (FAILED(res)) return res;
367 
368  /* write length of filePath string ( 0 included )*/
369  bytesA = WideCharToMultiByte( CP_ACP, 0, filePathW, -1, NULL, 0, NULL, NULL );
370  res=IStream_Write(pStm,&bytesA,sizeof(DWORD),NULL);
371  if (FAILED(res)) return res;
372 
373  /* write A string (with '\0') */
374  filePathA=HeapAlloc(GetProcessHeap(),0,bytesA);
375  if (!filePathA)
376  return E_OUTOFMEMORY;
377  WideCharToMultiByte( CP_ACP, 0, filePathW, -1, filePathA, bytesA, NULL, &bUsedDefault);
378  res=IStream_Write(pStm,filePathA,bytesA,NULL);
379  HeapFree(GetProcessHeap(),0,filePathA);
380  if (FAILED(res)) return res;
381 
382  /* write a WORD 0xFFFF */
383  res=IStream_Write(pStm,&FFFF,sizeof(WORD),NULL);
384  if (FAILED(res)) return res;
385 
386  /* write a WORD 0xDEAD */
387  res=IStream_Write(pStm,&DEAD,sizeof(WORD),NULL);
388  if (FAILED(res)) return res;
389 
390  /* write 5 zero DWORDs */
391  for(i=0;i<5;i++)
392  {
393  res=IStream_Write(pStm,&ZERO,sizeof(DWORD),NULL);
394  if (FAILED(res)) return res;
395  }
396 
397  /* Write the wide version if:
398  * + couldn't convert to CP_ACP,
399  * or + it's a directory,
400  * or + there's a character > 0xFF
401  */
402  len = lstrlenW(filePathW);
403  bWriteWide = (bUsedDefault || (len > 0 && filePathW[len-1]=='\\' ));
404  if (!bWriteWide)
405  {
406  WCHAR* pch;
407  for(pch=filePathW;*pch;++pch)
408  {
409  if (*pch > 0xFF)
410  {
411  bWriteWide = TRUE;
412  break;
413  }
414  }
415  }
416 
417  if (!bWriteWide)
418  return IStream_Write(pStm,&ZERO,sizeof(DWORD),NULL);
419 
420  /* write bytes needed for the filepathW (without 0) + 6 */
421  bytesW = len*sizeof(WCHAR) + 6;
422  res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL);
423  if (FAILED(res)) return res;
424 
425  /* try again, without the extra 6 */
426  bytesW -= 6;
427  res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL);
428  if (FAILED(res)) return res;
429 
430  /* write a WORD 3 */
431  res=IStream_Write(pStm,&THREE,sizeof(WORD),NULL);
432  if (FAILED(res)) return res;
433 
434  /* write W string (no 0) */
435  return IStream_Write(pStm,filePathW,bytesW,NULL);
436 }
437 
438 /******************************************************************************
439  * FileMoniker_GetSizeMax
440  */
441 static HRESULT WINAPI
443 {
445 
446  TRACE("(%p,%p)\n",iface,pcbSize);
447 
448  if (!pcbSize)
449  return E_POINTER;
450 
451  /* We could calculate exactly (see ...::Save()) but instead
452  * we'll make a quick over-estimate, like Windows (NT4, XP) does.
453  */
454  pcbSize->u.LowPart = 0x38 + 4 * lstrlenW(This->filePathName);
455  pcbSize->u.HighPart = 0;
456 
457  return S_OK;
458 }
459 
460 /******************************************************************************
461  * FileMoniker_Destroy (local function)
462  *******************************************************************************/
464 {
465  TRACE("(%p)\n",This);
466 
467  if (This->pMarshal) IUnknown_Release(This->pMarshal);
468  HeapFree(GetProcessHeap(),0,This->filePathName);
470 
471  return S_OK;
472 }
473 
474 /******************************************************************************
475  * FileMoniker_BindToObject
476  */
477 static HRESULT WINAPI
479  REFIID riid, VOID** ppvResult)
480 {
483  CLSID clsID;
484  IUnknown* pObj=0;
485  IRunningObjectTable *prot=0;
486  IPersistFile *ppf=0;
487  IClassFactory *pcf=0;
488  IClassActivator *pca=0;
489 
490  *ppvResult=0;
491 
492  TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
493 
494  if(pmkToLeft==NULL){
495 
496  res=IBindCtx_GetRunningObjectTable(pbc,&prot);
497 
498  if (SUCCEEDED(res)){
499  /* if the requested class was loaded before ! we don't need to reload it */
500  res = IRunningObjectTable_GetObject(prot,iface,&pObj);
501 
502  if (res != S_OK){
503  /* first activation of this class */
504  res=GetClassFile(This->filePathName,&clsID);
505  if (SUCCEEDED(res)){
506 
507  res=CoCreateInstance(&clsID,NULL,CLSCTX_SERVER,&IID_IPersistFile,(void**)&ppf);
508  if (SUCCEEDED(res)){
509 
510  res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
511  if (SUCCEEDED(res)){
512 
513  pObj=(IUnknown*)ppf;
514  IUnknown_AddRef(pObj);
515  }
516  }
517  }
518  }
519  }
520  }
521  else{
522  res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassFactory,(void**)&pcf);
523 
524  if (res==E_NOINTERFACE){
525 
526  res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassActivator,(void**)&pca);
527 
528  if (res==E_NOINTERFACE)
530  }
531  if (pcf!=NULL){
532 
533  IClassFactory_CreateInstance(pcf,NULL,&IID_IPersistFile,(void**)&ppf);
534 
535  res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
536 
537  if (SUCCEEDED(res)){
538 
539  pObj=(IUnknown*)ppf;
540  IUnknown_AddRef(pObj);
541  }
542  }
543  if (pca!=NULL){
544 
545  FIXME("()\n");
546 
547  /*res=GetClassFile(This->filePathName,&clsID);
548 
549  if (SUCCEEDED(res)){
550 
551  res=IClassActivator_GetClassObject(pca,&clsID,CLSCTX_ALL,0,&IID_IPersistFile,(void**)&ppf);
552 
553  if (SUCCEEDED(res)){
554 
555  pObj=(IUnknown*)ppf;
556  IUnknown_AddRef(pObj);
557  }
558  }*/
559  }
560  }
561 
562  if (pObj!=NULL){
563  /* get the requested interface from the loaded class */
564  res= IUnknown_QueryInterface(pObj,riid,ppvResult);
565 
566  IBindCtx_RegisterObjectBound(pbc,*ppvResult);
567 
568  IUnknown_Release(pObj);
569  }
570 
571  if (prot!=NULL)
572  IRunningObjectTable_Release(prot);
573 
574  if (ppf!=NULL)
575  IPersistFile_Release(ppf);
576 
577  if (pca!=NULL)
578  IClassActivator_Release(pca);
579 
580  if (pcf!=NULL)
581  IClassFactory_Release(pcf);
582 
583  return res;
584 }
585 
586 /******************************************************************************
587  * FileMoniker_BindToStorage
588  */
589 static HRESULT WINAPI
592 {
593  LPOLESTR filePath=0;
594  IStorage *pstg=0;
595  HRESULT res;
596 
597  TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
598 
599  if (pmkToLeft==NULL){
600 
601  if (IsEqualIID(&IID_IStorage, riid)){
602 
603  /* get the file name */
604  IMoniker_GetDisplayName(iface,pbc,pmkToLeft,&filePath);
605 
607 
608  if (SUCCEEDED(res))
609  *ppvObject=pstg;
610 
611  CoTaskMemFree(filePath);
612  }
613  else
614  if ( (IsEqualIID(&IID_IStream, riid)) || (IsEqualIID(&IID_ILockBytes, riid)) )
615  return E_FAIL;
616  else
617  return E_NOINTERFACE;
618  }
619  else {
620 
621  FIXME("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
622 
623  return E_NOTIMPL;
624  }
625  return res;
626 }
627 
628 /******************************************************************************
629  * FileMoniker_Reduce
630  ******************************************************************************/
631 static HRESULT WINAPI
632 FileMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
633  IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
634 {
635  TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
636 
637  if (ppmkReduced==NULL)
638  return E_POINTER;
639 
640  IMoniker_AddRef(iface);
641 
642  *ppmkReduced=iface;
643 
644  return MK_S_REDUCED_TO_SELF;
645 }
646 
647 static void free_stringtable(LPOLESTR *stringTable)
648 {
649  int i;
650 
651  for (i=0; stringTable[i]!=NULL; i++)
652  CoTaskMemFree(stringTable[i]);
653  CoTaskMemFree(stringTable);
654 }
655 
656 /******************************************************************************
657  * FileMoniker_ComposeWith
658  */
659 static HRESULT WINAPI
661  BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
662 {
663  HRESULT res;
664  LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0;
665  static const WCHAR twoPoint[]={'.','.',0};
666  static const WCHAR bkSlash[]={'\\',0};
667  IBindCtx *bind=0;
668  int i=0,j=0,lastIdx1=0,lastIdx2=0;
669  DWORD mkSys;
670 
671  TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
672 
673  if (ppmkComposite==NULL)
674  return E_POINTER;
675 
676  if (pmkRight==NULL)
677  return E_INVALIDARG;
678 
679  *ppmkComposite=0;
680 
681  IMoniker_IsSystemMoniker(pmkRight,&mkSys);
682 
683  /* check if we have two FileMonikers to compose or not */
684  if(mkSys==MKSYS_FILEMONIKER){
685 
686  CreateBindCtx(0,&bind);
687 
688  IMoniker_GetDisplayName(iface,bind,NULL,&str1);
689  IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2);
690 
691  /* decompose pathnames of the two monikers : (to prepare the path merge operation ) */
692  lastIdx1=FileMonikerImpl_DecomposePath(str1,&strDec1)-1;
693  lastIdx2=FileMonikerImpl_DecomposePath(str2,&strDec2)-1;
694 
695  if ((lastIdx1==-1 && lastIdx2>-1)||(lastIdx1==1 && wcscmp(strDec1[0],twoPoint)==0))
696  res = MK_E_SYNTAX;
697  else{
698  if(wcscmp(strDec1[lastIdx1],bkSlash)==0)
699  lastIdx1--;
700 
701  /* for each "..\" in the left of str2 remove the right element from str1 */
702  for(i=0; ( (lastIdx1>=0) && (strDec2[i]!=NULL) && (wcscmp(strDec2[i],twoPoint)==0) ); i+=2){
703 
704  lastIdx1-=2;
705  }
706 
707  /* the length of the composed path string is increased by the sum of the two paths' lengths */
708  newStr=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(lstrlenW(str1)+lstrlenW(str2)+1));
709 
710  if (newStr){
711  /* new path is the concatenation of the rest of str1 and str2 */
712  for(*newStr=0,j=0;j<=lastIdx1;j++)
713  lstrcatW(newStr,strDec1[j]);
714 
715  if ((strDec2[i]==NULL && lastIdx1>-1 && lastIdx2>-1) || wcscmp(strDec2[i],bkSlash)!=0)
716  lstrcatW(newStr,bkSlash);
717 
718  for(j=i;j<=lastIdx2;j++)
719  lstrcatW(newStr,strDec2[j]);
720 
721  /* create a new moniker with the new string */
722  res=CreateFileMoniker(newStr,ppmkComposite);
723 
724  /* free string memory used by this function */
725  HeapFree(GetProcessHeap(),0,newStr);
726  }
727  else res = E_OUTOFMEMORY;
728  }
729 
730  free_stringtable(strDec1);
731  free_stringtable(strDec2);
732 
733  CoTaskMemFree(str1);
734  CoTaskMemFree(str2);
735 
736  return res;
737  }
738  else if(mkSys==MKSYS_ANTIMONIKER){
739 
740  *ppmkComposite=NULL;
741  return S_OK;
742  }
743  else if (fOnlyIfNotGeneric){
744 
745  *ppmkComposite=NULL;
746  return MK_E_NEEDGENERIC;
747  }
748  else
749 
750  return CreateGenericComposite(iface,pmkRight,ppmkComposite);
751 }
752 
753 /******************************************************************************
754  * FileMoniker_Enum
755  */
756 static HRESULT WINAPI
757 FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
758 {
759  TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
760 
761  if (ppenumMoniker == NULL)
762  return E_POINTER;
763 
764  *ppenumMoniker = NULL;
765 
766  return S_OK;
767 }
768 
769 /******************************************************************************
770  * FileMoniker_IsEqual
771  */
772 static HRESULT WINAPI
773 FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
774 {
776  CLSID clsid;
777  LPOLESTR filePath;
778  IBindCtx* bind;
779  HRESULT res;
780 
781  TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
782 
783  if (pmkOtherMoniker==NULL)
784  return S_FALSE;
785 
786  IMoniker_GetClassID(pmkOtherMoniker,&clsid);
787 
788  if (!IsEqualCLSID(&clsid,&CLSID_FileMoniker))
789  return S_FALSE;
790 
791  res = CreateBindCtx(0,&bind);
792  if (FAILED(res)) return res;
793 
794  res = S_FALSE;
795  if (SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&filePath))) {
796  if (!lstrcmpiW(filePath, This->filePathName))
797  res = S_OK;
798  CoTaskMemFree(filePath);
799  }
800 
801  IBindCtx_Release(bind);
802  return res;
803 }
804 
805 /******************************************************************************
806  * FileMoniker_Hash
807  */
808 static HRESULT WINAPI
810 {
812  int h = 0,i,skip,len;
813  int off = 0;
814  LPOLESTR val;
815 
816  if (pdwHash==NULL)
817  return E_POINTER;
818 
819  val = This->filePathName;
820  len = lstrlenW(val);
821 
822  if (len < 16) {
823  for (i = len ; i > 0; i--) {
824  h = (h * 37) + val[off++];
825  }
826  } else {
827  /* only sample some characters */
828  skip = len / 8;
829  for (i = len ; i > 0; i -= skip, off += skip) {
830  h = (h * 39) + val[off];
831  }
832  }
833 
834  *pdwHash=h;
835 
836  return S_OK;
837 }
838 
839 /******************************************************************************
840  * FileMoniker_IsRunning
841  */
842 static HRESULT WINAPI
844  IMoniker* pmkNewlyRunning)
845 {
847  HRESULT res;
848 
849  TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
850 
851  if ( (pmkNewlyRunning!=NULL) && (IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK) )
852  return S_OK;
853 
854  if (pbc==NULL)
855  return E_POINTER;
856 
857  res=IBindCtx_GetRunningObjectTable(pbc,&rot);
858 
859  if (FAILED(res))
860  return res;
861 
862  res = IRunningObjectTable_IsRunning(rot,iface);
863 
864  IRunningObjectTable_Release(rot);
865 
866  return res;
867 }
868 
869 /******************************************************************************
870  * FileMoniker_GetTimeOfLastChange
871  ******************************************************************************/
872 static HRESULT WINAPI
874  IMoniker* pmkToLeft, FILETIME* pFileTime)
875 {
878  HRESULT res;
880 
881  TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pFileTime);
882 
883  if (pFileTime==NULL)
884  return E_POINTER;
885 
886  if (pmkToLeft!=NULL)
887  return E_INVALIDARG;
888 
889  res=IBindCtx_GetRunningObjectTable(pbc,&rot);
890 
891  if (FAILED(res))
892  return res;
893 
894  res= IRunningObjectTable_GetTimeOfLastChange(rot,iface,pFileTime);
895 
896  if (FAILED(res)){ /* the moniker is not registered */
897 
899  return MK_E_NOOBJECT;
900 
901  *pFileTime=info.ftLastWriteTime;
902  }
903 
904  return S_OK;
905 }
906 
907 /******************************************************************************
908  * FileMoniker_Inverse
909  */
910 static HRESULT WINAPI
912 {
913  TRACE("(%p,%p)\n",iface,ppmk);
914 
915  return CreateAntiMoniker(ppmk);
916 }
917 
918 /******************************************************************************
919  * FileMoniker_CommonPrefixWith
920  */
921 static HRESULT WINAPI
923 {
924 
925  LPOLESTR pathThis = NULL, pathOther = NULL, *stringTable1 = NULL;
926  LPOLESTR *stringTable2 = NULL, commonPath = NULL;
927  IBindCtx *bindctx;
928  DWORD mkSys;
929  ULONG nb1,nb2,i,sameIdx;
930  BOOL machineNameCase = FALSE;
931  HRESULT ret;
932 
933  if (ppmkPrefix==NULL)
934  return E_POINTER;
935 
936  if (pmkOther==NULL)
937  return E_INVALIDARG;
938 
939  *ppmkPrefix=0;
940 
941  /* check if we have the same type of moniker */
942  IMoniker_IsSystemMoniker(pmkOther,&mkSys);
943  if (mkSys != MKSYS_FILEMONIKER)
944  return MonikerCommonPrefixWith(iface, pmkOther, ppmkPrefix);
945 
946  ret = CreateBindCtx(0, &bindctx);
947  if (FAILED(ret))
948  return ret;
949 
950  /* create a string based on common part of the two paths */
951  ret = IMoniker_GetDisplayName(iface, bindctx, NULL, &pathThis);
952  if (FAILED(ret))
953  goto failed;
954 
955  ret = IMoniker_GetDisplayName(pmkOther, bindctx, NULL, &pathOther);
956  if (FAILED(ret))
957  goto failed;
958 
959  nb1 = FileMonikerImpl_DecomposePath(pathThis, &stringTable1);
960  if (FAILED(nb1)) {
961  ret = nb1;
962  goto failed;
963  }
964 
965  nb2 = FileMonikerImpl_DecomposePath(pathOther, &stringTable2);
966  if (FAILED(nb2)) {
967  ret = nb2;
968  goto failed;
969  }
970 
971  if (nb1 == 0 || nb2 == 0) {
972  ret = MK_E_NOPREFIX;
973  goto failed;
974  }
975 
976  commonPath = CoTaskMemAlloc(sizeof(WCHAR)*(min(lstrlenW(pathThis),lstrlenW(pathOther))+1));
977  if (!commonPath) {
978  ret = E_OUTOFMEMORY;
979  goto failed;
980  }
981 
982  *commonPath = 0;
983  for(sameIdx=0; ( (stringTable1[sameIdx]!=NULL) &&
984  (stringTable2[sameIdx]!=NULL) &&
985  (lstrcmpiW(stringTable1[sameIdx],stringTable2[sameIdx])==0)); sameIdx++);
986 
987  if (sameIdx > 1 && *stringTable1[0]=='\\' && *stringTable2[1]=='\\'){
988  machineNameCase = TRUE;
989 
990  for(i=2;i<sameIdx;i++)
991  if( (*stringTable1[i]=='\\') && (i+1 < sameIdx) && (*stringTable1[i+1]=='\\') ){
992  machineNameCase = FALSE;
993  break;
994  }
995  }
996 
997  if (machineNameCase && *stringTable1[sameIdx-1]=='\\')
998  sameIdx--;
999 
1000  if (machineNameCase && (sameIdx<=3) && (nb1 > 3 || nb2 > 3) )
1001  ret = MK_E_NOPREFIX;
1002  else
1003  {
1004  for (i = 0; i < sameIdx; i++)
1005  lstrcatW(commonPath,stringTable1[i]);
1006  ret = CreateFileMoniker(commonPath, ppmkPrefix);
1007  }
1008 
1009 failed:
1010  IBindCtx_Release(bindctx);
1011  CoTaskMemFree(pathThis);
1012  CoTaskMemFree(pathOther);
1013  CoTaskMemFree(commonPath);
1014  if (stringTable1) free_stringtable(stringTable1);
1015  if (stringTable2) free_stringtable(stringTable2);
1016 
1017  return ret;
1018 }
1019 
1020 /******************************************************************************
1021  * DecomposePath (local function)
1022  */
1023 int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)
1024 {
1025  static const WCHAR bSlash[] = {'\\',0};
1026  LPOLESTR word;
1027  int i=0,j,tabIndex=0, ret=0;
1028  LPOLESTR *strgtable ;
1029 
1030  int len=lstrlenW(str);
1031 
1032  TRACE("%s, %p\n", debugstr_w(str), *stringTable);
1033 
1034  strgtable = CoTaskMemAlloc((len + 1)*sizeof(*strgtable));
1035 
1036  if (strgtable==NULL)
1037  return E_OUTOFMEMORY;
1038 
1039  word = CoTaskMemAlloc((len + 1)*sizeof(WCHAR));
1040 
1041  if (word==NULL)
1042  {
1043  ret = E_OUTOFMEMORY;
1044  goto lend;
1045  }
1046 
1047  while(str[i]!=0){
1048 
1049  if(str[i]==bSlash[0]){
1050 
1051  strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR));
1052 
1053  if (strgtable[tabIndex]==NULL)
1054  {
1055  ret = E_OUTOFMEMORY;
1056  goto lend;
1057  }
1058 
1059  lstrcpyW(strgtable[tabIndex++],bSlash);
1060 
1061  i++;
1062 
1063  }
1064  else {
1065 
1066  for(j=0; str[i]!=0 && str[i]!=bSlash[0] ; i++,j++)
1067  word[j]=str[i];
1068 
1069  word[j]=0;
1070 
1071  strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1));
1072 
1073  if (strgtable[tabIndex]==NULL)
1074  {
1075  ret = E_OUTOFMEMORY;
1076  goto lend;
1077  }
1078 
1079  lstrcpyW(strgtable[tabIndex++],word);
1080  }
1081  }
1082  strgtable[tabIndex]=NULL;
1083 
1084  *stringTable=strgtable;
1085 
1086  ret = tabIndex;
1087 
1088 lend:
1089  if (ret < 0)
1090  {
1091  for (i = 0; i < tabIndex; i++)
1092  CoTaskMemFree(strgtable[i]);
1093 
1094  CoTaskMemFree(strgtable);
1095  }
1096 
1098 
1099  return ret;
1100 }
1101 
1102 /******************************************************************************
1103  * FileMoniker_RelativePathTo
1104  */
1105 static HRESULT WINAPI
1107 {
1108  IBindCtx *bind;
1109  HRESULT res;
1110  LPOLESTR str1=0,str2=0,*tabStr1=0,*tabStr2=0,relPath=0;
1111  DWORD len1=0,len2=0,sameIdx=0,j=0;
1112  static const WCHAR back[] ={'.','.','\\',0};
1113 
1114  TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
1115 
1116  if (ppmkRelPath==NULL)
1117  return E_POINTER;
1118 
1119  if (pmOther==NULL)
1120  return E_INVALIDARG;
1121 
1122  res=CreateBindCtx(0,&bind);
1123  if (FAILED(res))
1124  return res;
1125 
1126  res=IMoniker_GetDisplayName(iface,bind,NULL,&str1);
1127  if (FAILED(res))
1128  return res;
1129  res=IMoniker_GetDisplayName(pmOther,bind,NULL,&str2);
1130  if (FAILED(res))
1131  return res;
1132 
1133  len1=FileMonikerImpl_DecomposePath(str1,&tabStr1);
1134  if (FAILED(len1))
1135  return E_OUTOFMEMORY;
1136  len2=FileMonikerImpl_DecomposePath(str2,&tabStr2);
1137 
1138  if (FAILED(len2))
1139  {
1140  free_stringtable(tabStr1);
1141  return E_OUTOFMEMORY;
1142  }
1143 
1144  /* count the number of similar items from the begin of the two paths */
1145  for(sameIdx=0; ( (tabStr1[sameIdx]!=NULL) &&
1146  (tabStr2[sameIdx]!=NULL) &&
1147  (lstrcmpiW(tabStr1[sameIdx],tabStr2[sameIdx])==0)); sameIdx++);
1148 
1149  /* begin the construction of relativePath */
1150  /* if the two paths have a consecutive similar item from the begin ! the relativePath will be composed */
1151  /* by "..\\" in the begin */
1152  relPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(1+lstrlenW(str1)+lstrlenW(str2)));
1153 
1154  *relPath=0;
1155 
1156  if (len2>0 && !(len1==1 && len2==1 && sameIdx==0))
1157  for(j=sameIdx;(tabStr1[j] != NULL); j++)
1158  if (*tabStr1[j]!='\\')
1159  lstrcatW(relPath,back);
1160 
1161  /* add items of the second path (similar items with the first path are not included) to the relativePath */
1162  for(j=sameIdx;tabStr2[j]!=NULL;j++)
1163  lstrcatW(relPath,tabStr2[j]);
1164 
1165  res=CreateFileMoniker(relPath,ppmkRelPath);
1166 
1167  free_stringtable(tabStr1);
1168  free_stringtable(tabStr2);
1169  CoTaskMemFree(str1);
1170  CoTaskMemFree(str2);
1171  HeapFree(GetProcessHeap(),0,relPath);
1172 
1173  if (len1==0 || len2==0 || (len1==1 && len2==1 && sameIdx==0))
1174  return MK_S_HIM;
1175 
1176  return res;
1177 }
1178 
1179 /******************************************************************************
1180  * FileMoniker_GetDisplayName
1181  */
1182 static HRESULT WINAPI
1184  IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
1185 {
1187  int len=lstrlenW(This->filePathName);
1188 
1189  TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1190 
1191  if (ppszDisplayName==NULL)
1192  return E_POINTER;
1193 
1194  if (pmkToLeft!=NULL)
1195  return E_INVALIDARG;
1196 
1197  *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
1198  if (*ppszDisplayName==NULL)
1199  return E_OUTOFMEMORY;
1200 
1201  lstrcpyW(*ppszDisplayName,This->filePathName);
1202 
1203  TRACE("-- %s\n", debugstr_w(*ppszDisplayName));
1204 
1205  return S_OK;
1206 }
1207 
1208 /******************************************************************************
1209  * FileMoniker_ParseDisplayName
1210  */
1211 static HRESULT WINAPI
1213  LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
1214 {
1215  FIXME("(%p,%p,%p,%p,%p,%p),stub!\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
1216  return E_NOTIMPL;
1217 }
1218 
1219 /******************************************************************************
1220  * FileMoniker_IsSystemMoniker
1221  */
1222 static HRESULT WINAPI
1224 {
1225  TRACE("(%p,%p)\n",iface,pwdMksys);
1226 
1227  if (!pwdMksys)
1228  return E_POINTER;
1229 
1230  (*pwdMksys)=MKSYS_FILEMONIKER;
1231 
1232  return S_OK;
1233 }
1234 
1235 /*******************************************************************************
1236  * FileMonikerIROTData_QueryInterface
1237  */
1238 static HRESULT WINAPI
1240 {
1241 
1243 
1244  TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
1245 
1246  return FileMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
1247 }
1248 
1249 /***********************************************************************
1250  * FileMonikerIROTData_AddRef
1251  */
1252 static ULONG WINAPI
1254 {
1256 
1257  TRACE("(%p)\n",This);
1258 
1259  return IMoniker_AddRef(&This->IMoniker_iface);
1260 }
1261 
1262 /***********************************************************************
1263  * FileMonikerIROTData_Release
1264  */
1265 static ULONG WINAPI
1267 {
1269 
1270  TRACE("(%p)\n",This);
1271 
1272  return FileMonikerImpl_Release(&This->IMoniker_iface);
1273 }
1274 
1275 /******************************************************************************
1276  * FileMonikerIROTData_GetComparisonData
1277  */
1278 static HRESULT WINAPI
1280  ULONG cbMax, ULONG* pcbData)
1281 {
1283  int len = lstrlenW(This->filePathName)+1;
1284  int i;
1286 
1287  TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
1288 
1289  *pcbData = sizeof(CLSID) + len * sizeof(WCHAR);
1290  if (cbMax < *pcbData)
1291  return E_OUTOFMEMORY;
1292 
1293  memcpy(pbData, &CLSID_FileMoniker, sizeof(CLSID));
1294  pszFileName = (LPWSTR)(pbData+sizeof(CLSID));
1295  for (i = 0; i < len; i++)
1296  pszFileName[i] = towupper(This->filePathName[i]);
1297 
1298  return S_OK;
1299 }
1300 
1301 /*
1302  * Virtual function table for the FileMonikerImpl class which include IPersist,
1303  * IPersistStream and IMoniker functions.
1304  */
1305 static const IMonikerVtbl VT_FileMonikerImpl =
1306 {
1330 };
1331 
1332 /* Virtual function table for the IROTData class. */
1333 static const IROTDataVtbl VT_ROTDataImpl =
1334 {
1339 };
1340 
1341 /******************************************************************************
1342  * FileMoniker_Construct (local function)
1343  */
1344 static HRESULT FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName)
1345 {
1346  int nb=0,i;
1347  int sizeStr=lstrlenW(lpszPathName);
1348  LPOLESTR *tabStr=0;
1349  static const WCHAR twoPoint[]={'.','.',0};
1350  static const WCHAR bkSlash[]={'\\',0};
1351  BOOL addBkSlash;
1352 
1353  TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName));
1354 
1355  /* Initialize the virtual function table. */
1356  This->IMoniker_iface.lpVtbl = &VT_FileMonikerImpl;
1357  This->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
1358  This->ref = 0;
1359  This->pMarshal = NULL;
1360 
1361  This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1));
1362 
1363  if (This->filePathName==NULL)
1364  return E_OUTOFMEMORY;
1365 
1366  lstrcpyW(This->filePathName,lpszPathName);
1367 
1368  nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr);
1369 
1370  if (nb > 0 ){
1371 
1372  addBkSlash = TRUE;
1373  if (wcscmp(tabStr[0],twoPoint)!=0)
1374  addBkSlash = FALSE;
1375  else
1376  for(i=0;i<nb;i++){
1377 
1378  if ( (wcscmp(tabStr[i],twoPoint)!=0) && (wcscmp(tabStr[i],bkSlash)!=0) ){
1379  addBkSlash = FALSE;
1380  break;
1381  }
1382  else
1383 
1384  if (wcscmp(tabStr[i],bkSlash)==0 && i<nb-1 && wcscmp(tabStr[i+1],bkSlash)==0){
1385  *tabStr[i]=0;
1386  sizeStr--;
1387  addBkSlash = FALSE;
1388  break;
1389  }
1390  }
1391 
1392  if (wcscmp(tabStr[nb-1],bkSlash)==0)
1393  addBkSlash = FALSE;
1394 
1395  This->filePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR));
1396 
1397  *This->filePathName=0;
1398 
1399  for(i=0;tabStr[i]!=NULL;i++)
1400  lstrcatW(This->filePathName,tabStr[i]);
1401 
1402  if (addBkSlash)
1403  lstrcatW(This->filePathName,bkSlash);
1404  }
1405 
1406  free_stringtable(tabStr);
1407 
1408  return S_OK;
1409 }
1410 
1411 /******************************************************************************
1412  * CreateFileMoniker (OLE32.@)
1413  ******************************************************************************/
1414 HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, IMoniker **ppmk)
1415 {
1416  FileMonikerImpl* newFileMoniker;
1417  HRESULT hr;
1418 
1419  TRACE("(%s,%p)\n",debugstr_w(lpszPathName),ppmk);
1420 
1421  if (!ppmk)
1422  return E_POINTER;
1423 
1424  if(!lpszPathName)
1425  return MK_E_SYNTAX;
1426 
1427  *ppmk=NULL;
1428 
1429  newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
1430 
1431  if (!newFileMoniker)
1432  return E_OUTOFMEMORY;
1433 
1434  hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName);
1435 
1436  if (SUCCEEDED(hr))
1437  hr = IMoniker_QueryInterface(&newFileMoniker->IMoniker_iface,&IID_IMoniker,(void**)ppmk);
1438  else
1439  HeapFree(GetProcessHeap(),0,newFileMoniker);
1440 
1441  return hr;
1442 }
1443 
1444 /* find a character from a set in reverse without the string having to be null-terminated */
1445 static inline WCHAR *memrpbrkW(const WCHAR *ptr, size_t n, const WCHAR *accept)
1446 {
1447  const WCHAR *end, *ret = NULL;
1448  for (end = ptr + n; ptr < end; ptr++) if (wcschr(accept, *ptr)) ret = ptr;
1449  return (WCHAR *)ret;
1450 }
1451 
1452 HRESULT FileMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
1453  LPDWORD pchEaten, IMoniker **ppmk)
1454 {
1455  LPCWSTR end;
1456  static const WCHAR wszSeparators[] = {':','\\','/','!',0};
1457 
1458  for (end = szDisplayName + lstrlenW(szDisplayName);
1459  end && (end != szDisplayName);
1460  end = memrpbrkW(szDisplayName, end - szDisplayName, wszSeparators))
1461  {
1462  HRESULT hr;
1464  IMoniker *file_moniker;
1465  LPWSTR file_display_name;
1466  LPWSTR full_path_name;
1467  DWORD full_path_name_len;
1468  int len = end - szDisplayName;
1469 
1470  file_display_name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
1471  if (!file_display_name) return E_OUTOFMEMORY;
1472  memcpy(file_display_name, szDisplayName, len * sizeof(WCHAR));
1473  file_display_name[len] = '\0';
1474 
1475  hr = CreateFileMoniker(file_display_name, &file_moniker);
1476  if (FAILED(hr))
1477  {
1478  HeapFree(GetProcessHeap(), 0, file_display_name);
1479  return hr;
1480  }
1481 
1482  hr = IBindCtx_GetRunningObjectTable(pbc, &rot);
1483  if (FAILED(hr))
1484  {
1485  HeapFree(GetProcessHeap(), 0, file_display_name);
1486  IMoniker_Release(file_moniker);
1487  return hr;
1488  }
1489 
1490  hr = IRunningObjectTable_IsRunning(rot, file_moniker);
1491  IRunningObjectTable_Release(rot);
1492  if (FAILED(hr))
1493  {
1494  HeapFree(GetProcessHeap(), 0, file_display_name);
1495  IMoniker_Release(file_moniker);
1496  return hr;
1497  }
1498  if (hr == S_OK)
1499  {
1500  TRACE("found running file moniker for %s\n", debugstr_w(file_display_name));
1501  *pchEaten = len;
1502  *ppmk = file_moniker;
1503  HeapFree(GetProcessHeap(), 0, file_display_name);
1504  return S_OK;
1505  }
1506 
1507  full_path_name_len = GetFullPathNameW(file_display_name, 0, NULL, NULL);
1508  if (!full_path_name_len)
1509  {
1510  HeapFree(GetProcessHeap(), 0, file_display_name);
1511  IMoniker_Release(file_moniker);
1512  return MK_E_SYNTAX;
1513  }
1514  full_path_name = HeapAlloc(GetProcessHeap(), 0, full_path_name_len * sizeof(WCHAR));
1515  if (!full_path_name)
1516  {
1517  HeapFree(GetProcessHeap(), 0, file_display_name);
1518  IMoniker_Release(file_moniker);
1519  return E_OUTOFMEMORY;
1520  }
1521  GetFullPathNameW(file_display_name, full_path_name_len, full_path_name, NULL);
1522 
1523  if (GetFileAttributesW(full_path_name) == INVALID_FILE_ATTRIBUTES)
1524  TRACE("couldn't open file %s\n", debugstr_w(full_path_name));
1525  else
1526  {
1527  TRACE("got file moniker for %s\n", debugstr_w(szDisplayName));
1528  *pchEaten = len;
1529  *ppmk = file_moniker;
1530  HeapFree(GetProcessHeap(), 0, file_display_name);
1531  HeapFree(GetProcessHeap(), 0, full_path_name);
1532  return S_OK;
1533  }
1534  HeapFree(GetProcessHeap(), 0, file_display_name);
1535  HeapFree(GetProcessHeap(), 0, full_path_name);
1536  IMoniker_Release(file_moniker);
1537  }
1538 
1539  return MK_E_CANTOPENFILE;
1540 }
1541 
1542 
1544 {
1545  FileMonikerImpl* newFileMoniker;
1546  HRESULT hr;
1547  static const WCHAR wszEmpty[] = { 0 };
1548 
1549  TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
1550 
1551  *ppv = NULL;
1552 
1553  if (pUnk)
1554  return CLASS_E_NOAGGREGATION;
1555 
1556  newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
1557  if (!newFileMoniker)
1558  return E_OUTOFMEMORY;
1559 
1560  hr = FileMonikerImpl_Construct(newFileMoniker, wszEmpty);
1561 
1562  if (SUCCEEDED(hr))
1563  hr = IMoniker_QueryInterface(&newFileMoniker->IMoniker_iface, riid, ppv);
1564  if (FAILED(hr))
1565  HeapFree(GetProcessHeap(),0,newFileMoniker);
1566 
1567  return hr;
1568 }
WINE_DEFAULT_DEBUG_CHANNEL(ole)
struct FileMonikerImpl FileMonikerImpl
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
#define MK_S_REDUCED_TO_SELF
Definition: winerror.h:2773
#define MB_ERR_INVALID_CHARS
Definition: unicode.h:41
#define E_NOINTERFACE
Definition: winerror.h:2364
HRESULT WINAPI MonikerCommonPrefixWith(IMoniker *pmkThis, IMoniker *pmkOther, IMoniker **ppmkCommon)
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:420
#define WideCharToMultiByte
Definition: compat.h:101
HRESULT hr
Definition: shlfolder.c:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
HRESULT WINAPI GetClassFile(LPCOLESTR filePathName, CLSID *pclsid)
Definition: moniker.c:1213
interface IBindCtx * LPBC
Definition: objfwd.h:18
#define MK_E_INTERMEDIATEINTERFACENOTSUPPORTED
Definition: winerror.h:2788
INT WSAAPI bind(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: socklife.c:36
REFIID riid
Definition: precomp.h:44
#define CP_ACP
Definition: compat.h:99
static FileMonikerImpl * impl_from_IMoniker(IMoniker *iface)
Definition: filemoniker.c:50
static FileMonikerImpl * impl_from_IROTData(IROTData *iface)
Definition: filemoniker.c:55
const GUID IID_IPersist
Definition: proxy.cpp:14
static HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker *iface, DWORD *pwdMksys)
Definition: filemoniker.c:1223
char CHAR
Definition: xmlstorage.h:175
#define WARN(fmt,...)
Definition: debug.h:111
REFIID LPVOID * ppv
Definition: atlbase.h:39
GLdouble n
Definition: glext.h:7729
static HRESULT FileMonikerImpl_Destroy(FileMonikerImpl *iface)
Definition: filemoniker.c:463
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1105
static const IROTDataVtbl VT_ROTDataImpl
Definition: filemoniker.c:1333
static HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid, VOID **ppvResult)
Definition: filemoniker.c:478
static HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
Definition: filemoniker.c:773
GLuint GLuint end
Definition: gl.h:1545
static ULONG WINAPI FileMonikerImpl_Release(IMoniker *iface)
Definition: filemoniker.c:128
static LPOLESTR
Definition: stg_prop.c:27
#define lstrlenW
Definition: compat.h:415
#define E_FAIL
Definition: ddrawi.h:102
Definition: send.c:47
#define pch(ap)
Definition: match.c:418
static HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, FILETIME *pFileTime)
Definition: filemoniker.c:873
static HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, IMoniker *pmkNewlyRunning)
Definition: filemoniker.c:843
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
struct _test_info info[]
Definition: SetCursorPos.c:19
static HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSize)
Definition: filemoniker.c:442
static HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker *iface)
Definition: filemoniker.c:167
static ULONG WINAPI FileMonikerROTDataImpl_AddRef(IROTData *iface)
Definition: filemoniker.c:1253
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
static HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker *iface, IMoniker *pmOther, IMoniker **ppmkRelPath)
Definition: filemoniker.c:1106
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static HRESULT WINAPI FileMonikerImpl_Load(IMoniker *iface, IStream *pStm)
Definition: filemoniker.c:182
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:802
#define debugstr_w
Definition: kernel32.h:32
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:110
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:41
static PVOID ptr
Definition: dispmode.c:27
GLfloat rot
Definition: 3dtext.c:36
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
static HRESULT WINAPI FileMonikerImpl_Hash(IMoniker *iface, DWORD *pdwHash)
Definition: filemoniker.c:809
#define DEAD
Definition: PathResolve.cpp:76
static WCHAR * memrpbrkW(const WCHAR *ptr, size_t n, const WCHAR *accept)
Definition: filemoniker.c:1445
#define MK_E_NEEDGENERIC
Definition: winerror.h:2783
static const WCHAR wszEmpty[]
Definition: misc.c:327
#define debugstr_guid
Definition: kernel32.h:35
static HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar, IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
Definition: filemoniker.c:632
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
GLuint GLfloat * val
Definition: glext.h:7180
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define STGM_READ
Definition: objbase.h:916
#define MK_E_CANTOPENFILE
Definition: winerror.h:2791
#define TRACE(s)
Definition: solgame.cpp:4
#define GetProcessHeap()
Definition: compat.h:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC *ppbc)
Definition: bindctx.c:556
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
static HRESULT WINAPI FileMonikerROTDataImpl_GetComparisonData(IROTData *iface, BYTE *pbData, ULONG cbMax, ULONG *pcbData)
Definition: filemoniker.c:1279
HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, IMoniker **ppmk)
Definition: filemoniker.c:1414
const GUID IID_IUnknown
HRESULT WINAPI StgOpenStorage(const OLECHAR *pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstgOpen)
Definition: storage32.c:8755
#define WINAPI
Definition: msvc.h:6
unsigned short WORD
Definition: ntddk_ex.h:93
static HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker *iface, REFIID riid, void **ppvObject)
Definition: filemoniker.c:68
unsigned long DWORD
Definition: ntddk_ex.h:95
IROTData IROTData_iface
Definition: filemoniker.c:44
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR **stringTable)
Definition: filemoniker.c:1023
Definition: texture.c:1662
static HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther, IMoniker **ppmkPrefix)
Definition: filemoniker.c:922
static HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData *iface, REFIID riid, VOID **ppvObject)
Definition: filemoniker.c:1239
const GUID IID_IPersistStream
Definition: proxy.cpp:13
int ret
HRESULT WINAPI CreateAntiMoniker(IMoniker **ppmk)
Definition: antimoniker.c:608
REFCLSID clsid
Definition: msctf.c:82
#define InterlockedDecrement
Definition: armddk.h:52
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
static HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker *iface, IMoniker **ppmk)
Definition: filemoniker.c:911
REFIID LPVOID * ppvObject
Definition: precomp.h:44
#define CLASS_E_NOAGGREGATION
Definition: winerror.h:2662
SOCKET WSAAPI accept(IN SOCKET s, OUT LPSOCKADDR addr, OUT INT FAR *addrlen)
Definition: socklife.c:23
#define STGM_READWRITE
Definition: objbase.h:918
#define MK_E_NOPREFIX
Definition: winerror.h:2795
static const IMonikerVtbl VT_FileMonikerImpl
Definition: filemoniker.c:1305
_Inout_ SURFOBJ _In_opt_ SURFOBJ _In_ CLIPOBJ _In_opt_ XLATEOBJ _In_opt_ COLORADJUSTMENT * pca
Definition: winddi.h:3775
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define S_OK
Definition: intsafe.h:59
IMoniker IMoniker_iface
Definition: filemoniker.c:43
HRESULT WINAPI FileMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv)
Definition: filemoniker.c:1543
#define InterlockedIncrement
Definition: armddk.h:53
static HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker *iface, IMoniker *pmkRight, BOOL fOnlyIfNotGeneric, IMoniker **ppmkComposite)
Definition: filemoniker.c:660
#define lstrcpyW
Definition: compat.h:414
static HRESULT WINAPI FileMonikerImpl_Save(IMoniker *iface, IStream *pStm, BOOL fClearDirty)
Definition: filemoniker.c:343
#define HeapReAlloc
Definition: compat.h:401
#define E_NOTIMPL
Definition: ddrawi.h:99
HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer)
Definition: moniker.c:1677
#define min(a, b)
Definition: monoChain.cc:55
const WCHAR * word
Definition: lex.c:36
#define MultiByteToWideChar
Definition: compat.h:100
#define skip(...)
Definition: atltest.h:64
const GUID IID_IPersistFile
HRESULT FileMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName, LPDWORD pchEaten, IMoniker **ppmk)
Definition: filemoniker.c:1452
GLuint res
Definition: glext.h:9613
uint32_t * LPDWORD
Definition: typedefs.h:57
unsigned int ULONG
Definition: retypes.h:1
static void free_stringtable(LPOLESTR *stringTable)
Definition: filemoniker.c:647
BOOL WINAPI GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation)
Definition: fileinfo.c:702
static HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker *iface, CLSID *pClassID)
Definition: filemoniker.c:147
static ULONG WINAPI FileMonikerROTDataImpl_Release(IROTData *iface)
Definition: filemoniker.c:1266
#define MK_E_SYNTAX
Definition: winerror.h:2785
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
#define towupper(c)
Definition: wctype.h:99
HRESULT WINAPI CreateGenericComposite(IMoniker *pmkFirst, IMoniker *pmkRest, IMoniker **ppmkComposite)
static HRESULT FileMonikerImpl_Construct(FileMonikerImpl *iface, LPCOLESTR lpszPathName)
Definition: filemoniker.c:1344
#define STGM_SHARE_DENY_WRITE
Definition: objbase.h:921
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define E_POINTER
Definition: winerror.h:2365
const GUID IID_IClassFactory
static ULONG WINAPI FileMonikerImpl_AddRef(IMoniker *iface)
Definition: filemoniker.c:115
static HRESULT WINAPI FileMonikerImpl_Enum(IMoniker *iface, BOOL fForward, IEnumMoniker **ppenumMoniker)
Definition: filemoniker.c:757
#define IsEqualCLSID(rclsid1, rclsid2)
Definition: guiddef.h:96
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
IUnknown * pMarshal
Definition: filemoniker.c:47
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:404
struct _ULARGE_INTEGER::@3769 u
#define HeapFree(x, y, z)
Definition: compat.h:402
static HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
Definition: filemoniker.c:1183
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
static HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
Definition: filemoniker.c:1212
#define MK_E_NOOBJECT
Definition: winerror.h:2786
#define SUCCEEDED(hr)
Definition: intsafe.h:57
_In_ DWORD _Out_writes_bytes_to_opt_ pcbData void _Inout_ DWORD * pcbData
Definition: wincrypt.h:4953
LPOLESTR filePathName
Definition: filemoniker.c:46
off
Definition: i386-dis.c:3909
_In_ HCRYPTHASH _In_ BOOL _In_ DWORD _Inout_updates_bytes_to_ pdwDataLen BYTE * pbData
Definition: wincrypt.h:4201
#define MK_S_HIM
Definition: winerror.h:2775
static HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid, VOID **ppvObject)
Definition: filemoniker.c:590