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