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