Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfilemoniker.c
Go to the documentation of this file.
00001 /* 00002 * FileMonikers implementation 00003 * 00004 * Copyright 1999 Noomen Hamza 00005 * Copyright 2007 Robert Shearman 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include <assert.h> 00023 #include <stdarg.h> 00024 #include <string.h> 00025 00026 #define COBJMACROS 00027 #define NONAMELESSUNION 00028 #define NONAMELESSSTRUCT 00029 00030 #include "windef.h" 00031 #include "winbase.h" 00032 #include "winerror.h" 00033 #include "winnls.h" 00034 #include "wine/unicode.h" 00035 #include "wine/debug.h" 00036 #include "objbase.h" 00037 #include "moniker.h" 00038 00039 #include "compobj_private.h" 00040 00041 WINE_DEFAULT_DEBUG_CHANNEL(ole); 00042 00043 /* filemoniker data structure */ 00044 typedef struct FileMonikerImpl{ 00045 IMoniker IMoniker_iface; 00046 IROTData IROTData_iface; 00047 LONG ref; 00048 LPOLESTR filePathName; /* path string identified by this filemoniker */ 00049 IUnknown *pMarshal; /* custom marshaler */ 00050 } FileMonikerImpl; 00051 00052 static inline FileMonikerImpl *impl_from_IMoniker(IMoniker *iface) 00053 { 00054 return CONTAINING_RECORD(iface, FileMonikerImpl, IMoniker_iface); 00055 } 00056 00057 static inline FileMonikerImpl *impl_from_IROTData(IROTData *iface) 00058 { 00059 return CONTAINING_RECORD(iface, FileMonikerImpl, IROTData_iface); 00060 } 00061 00062 /* Local function used by filemoniker implementation */ 00063 static HRESULT FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName); 00064 static HRESULT FileMonikerImpl_Destroy(FileMonikerImpl* iface); 00065 00066 /******************************************************************************* 00067 * FileMoniker_QueryInterface 00068 */ 00069 static HRESULT WINAPI 00070 FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) 00071 { 00072 FileMonikerImpl *This = impl_from_IMoniker(iface); 00073 00074 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); 00075 00076 /* Perform a sanity check on the parameters.*/ 00077 if ( ppvObject==0 ) 00078 return E_INVALIDARG; 00079 00080 /* Initialize the return parameter */ 00081 *ppvObject = 0; 00082 00083 /* Compare the riid with the interface IDs implemented by this object.*/ 00084 if (IsEqualIID(&IID_IUnknown, riid) || 00085 IsEqualIID(&IID_IPersist, riid) || 00086 IsEqualIID(&IID_IPersistStream,riid) || 00087 IsEqualIID(&IID_IMoniker, riid) 00088 ) 00089 *ppvObject = iface; 00090 00091 else if (IsEqualIID(&IID_IROTData, riid)) 00092 *ppvObject = &This->IROTData_iface; 00093 else if (IsEqualIID(&IID_IMarshal, riid)) 00094 { 00095 HRESULT hr = S_OK; 00096 if (!This->pMarshal) 00097 hr = MonikerMarshal_Create(iface, &This->pMarshal); 00098 if (hr != S_OK) 00099 return hr; 00100 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject); 00101 } 00102 00103 /* Check that we obtained an interface.*/ 00104 if ((*ppvObject)==0) 00105 return E_NOINTERFACE; 00106 00107 /* Query Interface always increases the reference count by one when it is successful */ 00108 IMoniker_AddRef(iface); 00109 00110 return S_OK; 00111 } 00112 00113 /****************************************************************************** 00114 * FileMoniker_AddRef 00115 */ 00116 static ULONG WINAPI 00117 FileMonikerImpl_AddRef(IMoniker* iface) 00118 { 00119 FileMonikerImpl *This = impl_from_IMoniker(iface); 00120 00121 TRACE("(%p)\n",iface); 00122 00123 return InterlockedIncrement(&This->ref); 00124 } 00125 00126 /****************************************************************************** 00127 * FileMoniker_Release 00128 */ 00129 static ULONG WINAPI 00130 FileMonikerImpl_Release(IMoniker* iface) 00131 { 00132 FileMonikerImpl *This = impl_from_IMoniker(iface); 00133 ULONG ref; 00134 00135 TRACE("(%p)\n",iface); 00136 00137 ref = InterlockedDecrement(&This->ref); 00138 00139 /* destroy the object if there's no more reference on it */ 00140 if (ref == 0) FileMonikerImpl_Destroy(This); 00141 00142 return ref; 00143 } 00144 00145 /****************************************************************************** 00146 * FileMoniker_GetClassID 00147 */ 00148 static HRESULT WINAPI 00149 FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID) 00150 { 00151 TRACE("(%p,%p)\n",iface,pClassID); 00152 00153 if (pClassID==NULL) 00154 return E_POINTER; 00155 00156 *pClassID = CLSID_FileMoniker; 00157 00158 return S_OK; 00159 } 00160 00161 /****************************************************************************** 00162 * FileMoniker_IsDirty 00163 * 00164 * Note that the OLE-provided implementations of the IPersistStream::IsDirty 00165 * method in the OLE-provided moniker interfaces always return S_FALSE because 00166 * their internal state never changes. 00167 */ 00168 static HRESULT WINAPI 00169 FileMonikerImpl_IsDirty(IMoniker* iface) 00170 { 00171 00172 TRACE("(%p)\n",iface); 00173 00174 return S_FALSE; 00175 } 00176 00177 /****************************************************************************** 00178 * FileMoniker_Load 00179 * 00180 * this function locates and reads from the stream the filePath string 00181 * written by FileMonikerImpl_Save 00182 */ 00183 static HRESULT WINAPI 00184 FileMonikerImpl_Load(IMoniker* iface, IStream* pStm) 00185 { 00186 FileMonikerImpl *This = impl_from_IMoniker(iface); 00187 HRESULT res; 00188 CHAR* filePathA = NULL; 00189 WCHAR* filePathW = NULL; 00190 ULONG bread; 00191 WORD wbuffer; 00192 DWORD dwbuffer, bytesA, bytesW, len; 00193 int i; 00194 00195 00196 TRACE("(%p,%p)\n",iface,pStm); 00197 00198 /* first WORD */ 00199 res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread); 00200 if (bread!=sizeof(WORD)) 00201 { 00202 WARN("Couldn't read 0 word\n"); 00203 goto fail; 00204 } 00205 00206 /* read filePath string length (plus one) */ 00207 res=IStream_Read(pStm,&bytesA,sizeof(DWORD),&bread); 00208 if (bread != sizeof(DWORD)) 00209 { 00210 WARN("Couldn't read file string length\n"); 00211 goto fail; 00212 } 00213 00214 /* read filePath string */ 00215 filePathA=HeapAlloc(GetProcessHeap(),0,bytesA); 00216 if (!filePathA) 00217 { 00218 res = E_OUTOFMEMORY; 00219 goto fail; 00220 } 00221 00222 res=IStream_Read(pStm,filePathA,bytesA,&bread); 00223 if (bread != bytesA) 00224 { 00225 WARN("Couldn't read file path string\n"); 00226 goto fail; 00227 } 00228 00229 /* read the unknown value */ 00230 IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread); 00231 if (bread != sizeof(WORD)) 00232 { 00233 WARN("Couldn't read unknown value\n"); 00234 goto fail; 00235 } 00236 00237 /* read the DEAD constant */ 00238 IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread); 00239 if (bread != sizeof(WORD)) 00240 { 00241 WARN("Couldn't read DEAD constant\n"); 00242 goto fail; 00243 } 00244 00245 for(i=0;i<5;i++) 00246 { 00247 res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread); 00248 if (bread!=sizeof(DWORD)) 00249 { 00250 WARN("Couldn't read 0 padding\n"); 00251 goto fail; 00252 } 00253 } 00254 00255 res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread); 00256 if (bread!=sizeof(DWORD)) 00257 goto fail; 00258 00259 if (!dwbuffer) /* No W-string */ 00260 { 00261 bytesA--; 00262 len=MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, filePathA, bytesA, NULL, 0); 00263 if (!len) 00264 goto fail; 00265 00266 filePathW=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR)); 00267 if (!filePathW) 00268 { 00269 res = E_OUTOFMEMORY; 00270 goto fail; 00271 } 00272 MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, filePathA, -1, filePathW, len+1); 00273 goto succeed; 00274 } 00275 00276 if (dwbuffer < 6) 00277 goto fail; 00278 00279 bytesW=dwbuffer - 6; 00280 00281 res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread); 00282 if (bread!=sizeof(DWORD) || dwbuffer!=bytesW) 00283 goto fail; 00284 00285 res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread); 00286 if (bread!=sizeof(WORD) || wbuffer!=0x3) 00287 goto fail; 00288 00289 len=bytesW/sizeof(WCHAR); 00290 filePathW=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR)); 00291 if(!filePathW) 00292 { 00293 res = E_OUTOFMEMORY; 00294 goto fail; 00295 } 00296 res=IStream_Read(pStm,filePathW,bytesW,&bread); 00297 if (bread!=bytesW) 00298 goto fail; 00299 00300 filePathW[len]=0; 00301 00302 succeed: 00303 HeapFree(GetProcessHeap(),0,filePathA); 00304 HeapFree(GetProcessHeap(),0,This->filePathName); 00305 This->filePathName=filePathW; 00306 00307 return S_OK; 00308 00309 fail: 00310 HeapFree(GetProcessHeap(), 0, filePathA); 00311 HeapFree(GetProcessHeap(), 0, filePathW); 00312 00313 if (SUCCEEDED(res)) 00314 res = E_FAIL; 00315 return res; 00316 } 00317 00318 /****************************************************************************** 00319 * FileMoniker_Save 00320 * 00321 * This function saves data of this object. In the beginning I thought 00322 * that I have just to write the filePath string on Stream. But, when I 00323 * tested this function with windows program samples, I noticed that it 00324 * was not the case. This implementation is based on XP SP2. Other versions 00325 * of Windows have minor variations. 00326 * 00327 * Data which must be written on stream is: 00328 * 1) WORD constant: zero (not validated by Windows) 00329 * 2) length of the path string ("\0" included) 00330 * 3) path string type A 00331 * 4) Unknown WORD value: Frequently 0xFFFF, but not always. If set very large, 00332 * Windows returns E_OUTOFMEMORY 00333 * 5) WORD Constant: 0xDEAD (not validated by Windows) 00334 * 6) five DWORD constant: zero (not validated by Windows) 00335 * 7) If we're only writing the multibyte version, 00336 * write a zero DWORD and finish. 00337 * 00338 * 8) DWORD: double-length of the path string type W ("\0" not 00339 * included) 00340 * 9) WORD constant: 0x3 00341 * 10) filePath unicode string. 00342 * 00343 */ 00344 static HRESULT WINAPI 00345 FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty) 00346 { 00347 FileMonikerImpl *This = impl_from_IMoniker(iface); 00348 HRESULT res; 00349 LPOLESTR filePathW=This->filePathName; 00350 CHAR* filePathA; 00351 DWORD bytesA, bytesW, len; 00352 00353 static const WORD FFFF = 0xFFFF; /* Constants */ 00354 static const WORD DEAD = 0xDEAD; 00355 static const DWORD ZERO = 0; 00356 static const WORD THREE = 0x3; 00357 00358 int i; 00359 BOOL bUsedDefault, bWriteWide; 00360 00361 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty); 00362 00363 if (pStm==NULL) 00364 return E_POINTER; 00365 00366 /* write a 0 WORD */ 00367 res=IStream_Write(pStm,&ZERO,sizeof(WORD),NULL); 00368 if (FAILED(res)) return res; 00369 00370 /* write length of filePath string ( 0 included )*/ 00371 bytesA = WideCharToMultiByte( CP_ACP, 0, filePathW, -1, NULL, 0, NULL, NULL ); 00372 res=IStream_Write(pStm,&bytesA,sizeof(DWORD),NULL); 00373 if (FAILED(res)) return res; 00374 00375 /* write A string (with '\0') */ 00376 filePathA=HeapAlloc(GetProcessHeap(),0,bytesA); 00377 if (!filePathA) 00378 return E_OUTOFMEMORY; 00379 WideCharToMultiByte( CP_ACP, 0, filePathW, -1, filePathA, bytesA, NULL, &bUsedDefault); 00380 res=IStream_Write(pStm,filePathA,bytesA,NULL); 00381 HeapFree(GetProcessHeap(),0,filePathA); 00382 if (FAILED(res)) return res; 00383 00384 /* write a WORD 0xFFFF */ 00385 res=IStream_Write(pStm,&FFFF,sizeof(WORD),NULL); 00386 if (FAILED(res)) return res; 00387 00388 /* write a WORD 0xDEAD */ 00389 res=IStream_Write(pStm,&DEAD,sizeof(WORD),NULL); 00390 if (FAILED(res)) return res; 00391 00392 /* write 5 zero DWORDs */ 00393 for(i=0;i<5;i++) 00394 { 00395 res=IStream_Write(pStm,&ZERO,sizeof(DWORD),NULL); 00396 if (FAILED(res)) return res; 00397 } 00398 00399 /* Write the wide version if: 00400 * + couldn't convert to CP_ACP, 00401 * or + it's a directory, 00402 * or + there's a character > 0xFF 00403 */ 00404 len = lstrlenW(filePathW); 00405 bWriteWide = (bUsedDefault || (len > 0 && filePathW[len-1]=='\\' )); 00406 if (!bWriteWide) 00407 { 00408 WCHAR* pch; 00409 for(pch=filePathW;*pch;++pch) 00410 { 00411 if (*pch > 0xFF) 00412 { 00413 bWriteWide = TRUE; 00414 break; 00415 } 00416 } 00417 } 00418 00419 if (!bWriteWide) 00420 return IStream_Write(pStm,&ZERO,sizeof(DWORD),NULL); 00421 00422 /* write bytes needed for the filepathW (without 0) + 6 */ 00423 bytesW = len*sizeof(WCHAR) + 6; 00424 res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL); 00425 if (FAILED(res)) return res; 00426 00427 /* try again, without the extra 6 */ 00428 bytesW -= 6; 00429 res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL); 00430 if (FAILED(res)) return res; 00431 00432 /* write a WORD 3 */ 00433 res=IStream_Write(pStm,&THREE,sizeof(WORD),NULL); 00434 if (FAILED(res)) return res; 00435 00436 /* write W string (no 0) */ 00437 return IStream_Write(pStm,filePathW,bytesW,NULL); 00438 } 00439 00440 /****************************************************************************** 00441 * FileMoniker_GetSizeMax 00442 */ 00443 static HRESULT WINAPI 00444 FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize) 00445 { 00446 FileMonikerImpl *This = impl_from_IMoniker(iface); 00447 00448 TRACE("(%p,%p)\n",iface,pcbSize); 00449 00450 if (!pcbSize) 00451 return E_POINTER; 00452 00453 /* We could calculate exactly (see ...::Save()) but instead 00454 * we'll make a quick over-estimate, like Windows (NT4, XP) does. 00455 */ 00456 pcbSize->u.LowPart = 0x38 + 4 * lstrlenW(This->filePathName); 00457 pcbSize->u.HighPart = 0; 00458 00459 return S_OK; 00460 } 00461 00462 /****************************************************************************** 00463 * FileMoniker_Destroy (local function) 00464 *******************************************************************************/ 00465 HRESULT FileMonikerImpl_Destroy(FileMonikerImpl* This) 00466 { 00467 TRACE("(%p)\n",This); 00468 00469 if (This->pMarshal) IUnknown_Release(This->pMarshal); 00470 HeapFree(GetProcessHeap(),0,This->filePathName); 00471 HeapFree(GetProcessHeap(),0,This); 00472 00473 return S_OK; 00474 } 00475 00476 /****************************************************************************** 00477 * FileMoniker_BindToObject 00478 */ 00479 static HRESULT WINAPI 00480 FileMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, 00481 REFIID riid, VOID** ppvResult) 00482 { 00483 FileMonikerImpl *This = impl_from_IMoniker(iface); 00484 HRESULT res=E_FAIL; 00485 CLSID clsID; 00486 IUnknown* pObj=0; 00487 IRunningObjectTable *prot=0; 00488 IPersistFile *ppf=0; 00489 IClassFactory *pcf=0; 00490 IClassActivator *pca=0; 00491 00492 *ppvResult=0; 00493 00494 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); 00495 00496 if(pmkToLeft==NULL){ 00497 00498 res=IBindCtx_GetRunningObjectTable(pbc,&prot); 00499 00500 if (SUCCEEDED(res)){ 00501 /* if the requested class was loaded before ! we don't need to reload it */ 00502 res = IRunningObjectTable_GetObject(prot,iface,&pObj); 00503 00504 if (res==S_FALSE){ 00505 /* first activation of this class */ 00506 res=GetClassFile(This->filePathName,&clsID); 00507 if (SUCCEEDED(res)){ 00508 00509 res=CoCreateInstance(&clsID,NULL,CLSCTX_ALL,&IID_IPersistFile,(void**)&ppf); 00510 if (SUCCEEDED(res)){ 00511 00512 res=IPersistFile_Load(ppf,This->filePathName,STGM_READ); 00513 if (SUCCEEDED(res)){ 00514 00515 pObj=(IUnknown*)ppf; 00516 IUnknown_AddRef(pObj); 00517 } 00518 } 00519 } 00520 } 00521 } 00522 } 00523 else{ 00524 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassFactory,(void**)&pcf); 00525 00526 if (res==E_NOINTERFACE){ 00527 00528 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassActivator,(void**)&pca); 00529 00530 if (res==E_NOINTERFACE) 00531 return MK_E_INTERMEDIATEINTERFACENOTSUPPORTED; 00532 } 00533 if (pcf!=NULL){ 00534 00535 IClassFactory_CreateInstance(pcf,NULL,&IID_IPersistFile,(void**)&ppf); 00536 00537 res=IPersistFile_Load(ppf,This->filePathName,STGM_READ); 00538 00539 if (SUCCEEDED(res)){ 00540 00541 pObj=(IUnknown*)ppf; 00542 IUnknown_AddRef(pObj); 00543 } 00544 } 00545 if (pca!=NULL){ 00546 00547 FIXME("()\n"); 00548 00549 /*res=GetClassFile(This->filePathName,&clsID); 00550 00551 if (SUCCEEDED(res)){ 00552 00553 res=IClassActivator_GetClassObject(pca,&clsID,CLSCTX_ALL,0,&IID_IPersistFile,(void**)&ppf); 00554 00555 if (SUCCEEDED(res)){ 00556 00557 pObj=(IUnknown*)ppf; 00558 IUnknown_AddRef(pObj); 00559 } 00560 }*/ 00561 } 00562 } 00563 00564 if (pObj!=NULL){ 00565 /* get the requested interface from the loaded class */ 00566 res= IUnknown_QueryInterface(pObj,riid,ppvResult); 00567 00568 IBindCtx_RegisterObjectBound(pbc,*ppvResult); 00569 00570 IUnknown_Release(pObj); 00571 } 00572 00573 if (prot!=NULL) 00574 IRunningObjectTable_Release(prot); 00575 00576 if (ppf!=NULL) 00577 IPersistFile_Release(ppf); 00578 00579 if (pca!=NULL) 00580 IClassActivator_Release(pca); 00581 00582 if (pcf!=NULL) 00583 IClassFactory_Release(pcf); 00584 00585 return res; 00586 } 00587 00588 /****************************************************************************** 00589 * FileMoniker_BindToStorage 00590 */ 00591 static HRESULT WINAPI 00592 FileMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, 00593 REFIID riid, VOID** ppvObject) 00594 { 00595 LPOLESTR filePath=0; 00596 IStorage *pstg=0; 00597 HRESULT res; 00598 00599 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject); 00600 00601 if (pmkToLeft==NULL){ 00602 00603 if (IsEqualIID(&IID_IStorage, riid)){ 00604 00605 /* get the file name */ 00606 IMoniker_GetDisplayName(iface,pbc,pmkToLeft,&filePath); 00607 00608 /* verify if the file contains a storage object */ 00609 res=StgIsStorageFile(filePath); 00610 00611 if(res==S_OK){ 00612 00613 res=StgOpenStorage(filePath,NULL,STGM_READWRITE|STGM_SHARE_DENY_WRITE,NULL,0,&pstg); 00614 00615 if (SUCCEEDED(res)){ 00616 00617 *ppvObject=pstg; 00618 00619 IStorage_AddRef(pstg); 00620 00621 return res; 00622 } 00623 } 00624 CoTaskMemFree(filePath); 00625 } 00626 else 00627 if ( (IsEqualIID(&IID_IStream, riid)) || (IsEqualIID(&IID_ILockBytes, riid)) ) 00628 return E_FAIL; 00629 else 00630 return E_NOINTERFACE; 00631 } 00632 else { 00633 00634 FIXME("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject); 00635 00636 return E_NOTIMPL; 00637 } 00638 return res; 00639 } 00640 00641 /****************************************************************************** 00642 * FileMoniker_Reduce 00643 ******************************************************************************/ 00644 static HRESULT WINAPI 00645 FileMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar, 00646 IMoniker** ppmkToLeft, IMoniker** ppmkReduced) 00647 { 00648 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced); 00649 00650 if (ppmkReduced==NULL) 00651 return E_POINTER; 00652 00653 IMoniker_AddRef(iface); 00654 00655 *ppmkReduced=iface; 00656 00657 return MK_S_REDUCED_TO_SELF; 00658 } 00659 00660 /****************************************************************************** 00661 * FileMoniker_ComposeWith 00662 */ 00663 static HRESULT WINAPI 00664 FileMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight, 00665 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite) 00666 { 00667 HRESULT res; 00668 LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0; 00669 static const WCHAR twoPoint[]={'.','.',0}; 00670 static const WCHAR bkSlash[]={'\\',0}; 00671 IBindCtx *bind=0; 00672 int i=0,j=0,lastIdx1=0,lastIdx2=0; 00673 DWORD mkSys; 00674 00675 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite); 00676 00677 if (ppmkComposite==NULL) 00678 return E_POINTER; 00679 00680 if (pmkRight==NULL) 00681 return E_INVALIDARG; 00682 00683 *ppmkComposite=0; 00684 00685 IMoniker_IsSystemMoniker(pmkRight,&mkSys); 00686 00687 /* check if we have two FileMonikers to compose or not */ 00688 if(mkSys==MKSYS_FILEMONIKER){ 00689 00690 CreateBindCtx(0,&bind); 00691 00692 IMoniker_GetDisplayName(iface,bind,NULL,&str1); 00693 IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2); 00694 00695 /* decompose pathnames of the two monikers : (to prepare the path merge operation ) */ 00696 lastIdx1=FileMonikerImpl_DecomposePath(str1,&strDec1)-1; 00697 lastIdx2=FileMonikerImpl_DecomposePath(str2,&strDec2)-1; 00698 00699 if ((lastIdx1==-1 && lastIdx2>-1)||(lastIdx1==1 && lstrcmpW(strDec1[0],twoPoint)==0)) 00700 return MK_E_SYNTAX; 00701 00702 if(lstrcmpW(strDec1[lastIdx1],bkSlash)==0) 00703 lastIdx1--; 00704 00705 /* for etch "..\" in the left of str2 remove the right element from str1 */ 00706 for(i=0; ( (lastIdx1>=0) && (strDec2[i]!=NULL) && (lstrcmpW(strDec2[i],twoPoint)==0) ) ;i+=2){ 00707 00708 lastIdx1-=2; 00709 } 00710 00711 /* the length of the composed path string is raised by the sum of the two paths lengths */ 00712 newStr=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(lstrlenW(str1)+lstrlenW(str2)+1)); 00713 00714 if (newStr==NULL) 00715 return E_OUTOFMEMORY; 00716 00717 /* new path is the concatenation of the rest of str1 and str2 */ 00718 for(*newStr=0,j=0;j<=lastIdx1;j++) 00719 strcatW(newStr,strDec1[j]); 00720 00721 if ((strDec2[i]==NULL && lastIdx1>-1 && lastIdx2>-1) || lstrcmpW(strDec2[i],bkSlash)!=0) 00722 strcatW(newStr,bkSlash); 00723 00724 for(j=i;j<=lastIdx2;j++) 00725 strcatW(newStr,strDec2[j]); 00726 00727 /* create a new moniker with the new string */ 00728 res=CreateFileMoniker(newStr,ppmkComposite); 00729 00730 /* free all strings space memory used by this function */ 00731 HeapFree(GetProcessHeap(),0,newStr); 00732 00733 for(i=0; strDec1[i]!=NULL;i++) 00734 CoTaskMemFree(strDec1[i]); 00735 for(i=0; strDec2[i]!=NULL;i++) 00736 CoTaskMemFree(strDec2[i]); 00737 CoTaskMemFree(strDec1); 00738 CoTaskMemFree(strDec2); 00739 00740 CoTaskMemFree(str1); 00741 CoTaskMemFree(str2); 00742 00743 return res; 00744 } 00745 else if(mkSys==MKSYS_ANTIMONIKER){ 00746 00747 *ppmkComposite=NULL; 00748 return S_OK; 00749 } 00750 else if (fOnlyIfNotGeneric){ 00751 00752 *ppmkComposite=NULL; 00753 return MK_E_NEEDGENERIC; 00754 } 00755 else 00756 00757 return CreateGenericComposite(iface,pmkRight,ppmkComposite); 00758 } 00759 00760 /****************************************************************************** 00761 * FileMoniker_Enum 00762 */ 00763 static HRESULT WINAPI 00764 FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) 00765 { 00766 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker); 00767 00768 if (ppenumMoniker == NULL) 00769 return E_POINTER; 00770 00771 *ppenumMoniker = NULL; 00772 00773 return S_OK; 00774 } 00775 00776 /****************************************************************************** 00777 * FileMoniker_IsEqual 00778 */ 00779 static HRESULT WINAPI 00780 FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) 00781 { 00782 FileMonikerImpl *This = impl_from_IMoniker(iface); 00783 CLSID clsid; 00784 LPOLESTR filePath; 00785 IBindCtx* bind; 00786 HRESULT res; 00787 00788 TRACE("(%p,%p)\n",iface,pmkOtherMoniker); 00789 00790 if (pmkOtherMoniker==NULL) 00791 return S_FALSE; 00792 00793 IMoniker_GetClassID(pmkOtherMoniker,&clsid); 00794 00795 if (!IsEqualCLSID(&clsid,&CLSID_FileMoniker)) 00796 return S_FALSE; 00797 00798 res = CreateBindCtx(0,&bind); 00799 if (FAILED(res)) return res; 00800 00801 res = S_FALSE; 00802 if (SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&filePath))) { 00803 if (!lstrcmpiW(filePath, This->filePathName)) 00804 res = S_OK; 00805 CoTaskMemFree(filePath); 00806 } 00807 00808 IBindCtx_Release(bind); 00809 return res; 00810 } 00811 00812 /****************************************************************************** 00813 * FileMoniker_Hash 00814 */ 00815 static HRESULT WINAPI 00816 FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) 00817 { 00818 FileMonikerImpl *This = impl_from_IMoniker(iface); 00819 int h = 0,i,skip,len; 00820 int off = 0; 00821 LPOLESTR val; 00822 00823 if (pdwHash==NULL) 00824 return E_POINTER; 00825 00826 val = This->filePathName; 00827 len = lstrlenW(val); 00828 00829 if (len < 16) { 00830 for (i = len ; i > 0; i--) { 00831 h = (h * 37) + val[off++]; 00832 } 00833 } else { 00834 /* only sample some characters */ 00835 skip = len / 8; 00836 for (i = len ; i > 0; i -= skip, off += skip) { 00837 h = (h * 39) + val[off]; 00838 } 00839 } 00840 00841 *pdwHash=h; 00842 00843 return S_OK; 00844 } 00845 00846 /****************************************************************************** 00847 * FileMoniker_IsRunning 00848 */ 00849 static HRESULT WINAPI 00850 FileMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, 00851 IMoniker* pmkNewlyRunning) 00852 { 00853 IRunningObjectTable* rot; 00854 HRESULT res; 00855 00856 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning); 00857 00858 if ( (pmkNewlyRunning!=NULL) && (IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK) ) 00859 return S_OK; 00860 00861 if (pbc==NULL) 00862 return E_POINTER; 00863 00864 res=IBindCtx_GetRunningObjectTable(pbc,&rot); 00865 00866 if (FAILED(res)) 00867 return res; 00868 00869 res = IRunningObjectTable_IsRunning(rot,iface); 00870 00871 IRunningObjectTable_Release(rot); 00872 00873 return res; 00874 } 00875 00876 /****************************************************************************** 00877 * FileMoniker_GetTimeOfLastChange 00878 ******************************************************************************/ 00879 static HRESULT WINAPI 00880 FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, 00881 IMoniker* pmkToLeft, FILETIME* pFileTime) 00882 { 00883 FileMonikerImpl *This = impl_from_IMoniker(iface); 00884 IRunningObjectTable* rot; 00885 HRESULT res; 00886 WIN32_FILE_ATTRIBUTE_DATA info; 00887 00888 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pFileTime); 00889 00890 if (pFileTime==NULL) 00891 return E_POINTER; 00892 00893 if (pmkToLeft!=NULL) 00894 return E_INVALIDARG; 00895 00896 res=IBindCtx_GetRunningObjectTable(pbc,&rot); 00897 00898 if (FAILED(res)) 00899 return res; 00900 00901 res= IRunningObjectTable_GetTimeOfLastChange(rot,iface,pFileTime); 00902 00903 if (FAILED(res)){ /* the moniker is not registered */ 00904 00905 if (!GetFileAttributesExW(This->filePathName,GetFileExInfoStandard,&info)) 00906 return MK_E_NOOBJECT; 00907 00908 *pFileTime=info.ftLastWriteTime; 00909 } 00910 00911 return S_OK; 00912 } 00913 00914 /****************************************************************************** 00915 * FileMoniker_Inverse 00916 */ 00917 static HRESULT WINAPI 00918 FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) 00919 { 00920 TRACE("(%p,%p)\n",iface,ppmk); 00921 00922 return CreateAntiMoniker(ppmk); 00923 } 00924 00925 /****************************************************************************** 00926 * FileMoniker_CommonPrefixWith 00927 */ 00928 static HRESULT WINAPI 00929 FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) 00930 { 00931 00932 LPOLESTR pathThis,pathOther,*stringTable1,*stringTable2,commonPath; 00933 IBindCtx *pbind; 00934 DWORD mkSys; 00935 ULONG nb1,nb2,i,sameIdx; 00936 BOOL machimeNameCase=FALSE; 00937 00938 if (ppmkPrefix==NULL) 00939 return E_POINTER; 00940 00941 if (pmkOther==NULL) 00942 return E_INVALIDARG; 00943 00944 *ppmkPrefix=0; 00945 00946 /* check if we have the same type of moniker */ 00947 IMoniker_IsSystemMoniker(pmkOther,&mkSys); 00948 00949 if(mkSys==MKSYS_FILEMONIKER){ 00950 HRESULT ret; 00951 00952 ret = CreateBindCtx(0,&pbind); 00953 if (FAILED(ret)) 00954 return ret; 00955 00956 /* create a string based on common part of the two paths */ 00957 00958 ret = IMoniker_GetDisplayName(iface,pbind,NULL,&pathThis); 00959 if (FAILED(ret)) 00960 return ret; 00961 ret = IMoniker_GetDisplayName(pmkOther,pbind,NULL,&pathOther); 00962 if (FAILED(ret)) 00963 return ret; 00964 00965 nb1=FileMonikerImpl_DecomposePath(pathThis,&stringTable1); 00966 if (FAILED(nb1)) 00967 return nb1; 00968 nb2=FileMonikerImpl_DecomposePath(pathOther,&stringTable2); 00969 if (FAILED(nb2)) 00970 return nb2; 00971 00972 if (nb1==0 || nb2==0) 00973 return MK_E_NOPREFIX; 00974 00975 commonPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(min(lstrlenW(pathThis),lstrlenW(pathOther))+1)); 00976 if (!commonPath) 00977 return E_OUTOFMEMORY; 00978 00979 *commonPath=0; 00980 00981 for(sameIdx=0; ( (stringTable1[sameIdx]!=NULL) && 00982 (stringTable2[sameIdx]!=NULL) && 00983 (lstrcmpiW(stringTable1[sameIdx],stringTable2[sameIdx])==0)); sameIdx++); 00984 00985 if (sameIdx > 1 && *stringTable1[0]=='\\' && *stringTable2[1]=='\\'){ 00986 00987 machimeNameCase=TRUE; 00988 00989 for(i=2;i<sameIdx;i++) 00990 00991 if( (*stringTable1[i]=='\\') && (i+1 < sameIdx) && (*stringTable1[i+1]=='\\') ){ 00992 machimeNameCase=FALSE; 00993 break; 00994 } 00995 } 00996 00997 if (machimeNameCase && *stringTable1[sameIdx-1]=='\\') 00998 sameIdx--; 00999 01000 if (machimeNameCase && (sameIdx<=3) && (nb1 > 3 || nb2 > 3) ) 01001 ret = MK_E_NOPREFIX; 01002 else 01003 { 01004 for(i=0;i<sameIdx;i++) 01005 strcatW(commonPath,stringTable1[i]); 01006 01007 for(i=0;i<nb1;i++) 01008 CoTaskMemFree(stringTable1[i]); 01009 01010 CoTaskMemFree(stringTable1); 01011 01012 for(i=0;i<nb2;i++) 01013 CoTaskMemFree(stringTable2[i]); 01014 01015 CoTaskMemFree(stringTable2); 01016 01017 ret = CreateFileMoniker(commonPath,ppmkPrefix); 01018 } 01019 HeapFree(GetProcessHeap(),0,commonPath); 01020 return ret; 01021 } 01022 else 01023 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix); 01024 } 01025 01026 /****************************************************************************** 01027 * DecomposePath (local function) 01028 */ 01029 int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable) 01030 { 01031 static const WCHAR bSlash[] = {'\\',0}; 01032 LPOLESTR word; 01033 int i=0,j,tabIndex=0, ret=0; 01034 LPOLESTR *strgtable ; 01035 01036 int len=lstrlenW(str); 01037 01038 TRACE("%s, %p\n", debugstr_w(str), *stringTable); 01039 01040 strgtable = CoTaskMemAlloc((len + 1)*sizeof(*strgtable)); 01041 01042 if (strgtable==NULL) 01043 return E_OUTOFMEMORY; 01044 01045 word = CoTaskMemAlloc((len + 1)*sizeof(WCHAR)); 01046 01047 if (word==NULL) 01048 { 01049 ret = E_OUTOFMEMORY; 01050 goto lend; 01051 } 01052 01053 while(str[i]!=0){ 01054 01055 if(str[i]==bSlash[0]){ 01056 01057 strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR)); 01058 01059 if (strgtable[tabIndex]==NULL) 01060 { 01061 ret = E_OUTOFMEMORY; 01062 goto lend; 01063 } 01064 01065 strcpyW(strgtable[tabIndex++],bSlash); 01066 01067 i++; 01068 01069 } 01070 else { 01071 01072 for(j=0; str[i]!=0 && str[i]!=bSlash[0] ; i++,j++) 01073 word[j]=str[i]; 01074 01075 word[j]=0; 01076 01077 strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1)); 01078 01079 if (strgtable[tabIndex]==NULL) 01080 { 01081 ret = E_OUTOFMEMORY; 01082 goto lend; 01083 } 01084 01085 strcpyW(strgtable[tabIndex++],word); 01086 } 01087 } 01088 strgtable[tabIndex]=NULL; 01089 01090 *stringTable=strgtable; 01091 01092 ret = tabIndex; 01093 01094 lend: 01095 if (ret < 0) 01096 { 01097 for (i = 0; i < tabIndex; i++) 01098 CoTaskMemFree(strgtable[i]); 01099 01100 CoTaskMemFree(strgtable); 01101 } 01102 01103 if (word) 01104 CoTaskMemFree(word); 01105 01106 return ret; 01107 } 01108 01109 /****************************************************************************** 01110 * FileMoniker_RelativePathTo 01111 */ 01112 static HRESULT WINAPI 01113 FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) 01114 { 01115 IBindCtx *bind; 01116 HRESULT res; 01117 LPOLESTR str1=0,str2=0,*tabStr1=0,*tabStr2=0,relPath=0; 01118 DWORD len1=0,len2=0,sameIdx=0,j=0; 01119 static const WCHAR back[] ={'.','.','\\',0}; 01120 01121 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath); 01122 01123 if (ppmkRelPath==NULL) 01124 return E_POINTER; 01125 01126 if (pmOther==NULL) 01127 return E_INVALIDARG; 01128 01129 res=CreateBindCtx(0,&bind); 01130 if (FAILED(res)) 01131 return res; 01132 01133 res=IMoniker_GetDisplayName(iface,bind,NULL,&str1); 01134 if (FAILED(res)) 01135 return res; 01136 res=IMoniker_GetDisplayName(pmOther,bind,NULL,&str2); 01137 if (FAILED(res)) 01138 return res; 01139 01140 len1=FileMonikerImpl_DecomposePath(str1,&tabStr1); 01141 len2=FileMonikerImpl_DecomposePath(str2,&tabStr2); 01142 01143 if (FAILED(len1) || FAILED(len2)) 01144 return E_OUTOFMEMORY; 01145 01146 /* count the number of similar items from the begin of the two paths */ 01147 for(sameIdx=0; ( (tabStr1[sameIdx]!=NULL) && 01148 (tabStr2[sameIdx]!=NULL) && 01149 (lstrcmpiW(tabStr1[sameIdx],tabStr2[sameIdx])==0)); sameIdx++); 01150 01151 /* begin the construction of relativePath */ 01152 /* if the two paths have a consecutive similar item from the begin ! the relativePath will be composed */ 01153 /* by "..\\" in the begin */ 01154 relPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(1+lstrlenW(str1)+lstrlenW(str2))); 01155 01156 *relPath=0; 01157 01158 if (len2>0 && !(len1==1 && len2==1 && sameIdx==0)) 01159 for(j=sameIdx;(tabStr1[j] != NULL); j++) 01160 if (*tabStr1[j]!='\\') 01161 strcatW(relPath,back); 01162 01163 /* add items of the second path (similar items with the first path are not included) to the relativePath */ 01164 for(j=sameIdx;tabStr2[j]!=NULL;j++) 01165 strcatW(relPath,tabStr2[j]); 01166 01167 res=CreateFileMoniker(relPath,ppmkRelPath); 01168 01169 for(j=0; tabStr1[j]!=NULL;j++) 01170 CoTaskMemFree(tabStr1[j]); 01171 for(j=0; tabStr2[j]!=NULL;j++) 01172 CoTaskMemFree(tabStr2[j]); 01173 CoTaskMemFree(tabStr1); 01174 CoTaskMemFree(tabStr2); 01175 CoTaskMemFree(str1); 01176 CoTaskMemFree(str2); 01177 HeapFree(GetProcessHeap(),0,relPath); 01178 01179 if (len1==0 || len2==0 || (len1==1 && len2==1 && sameIdx==0)) 01180 return MK_S_HIM; 01181 01182 return res; 01183 } 01184 01185 /****************************************************************************** 01186 * FileMoniker_GetDisplayName 01187 */ 01188 static HRESULT WINAPI 01189 FileMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc, 01190 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName) 01191 { 01192 FileMonikerImpl *This = impl_from_IMoniker(iface); 01193 int len=lstrlenW(This->filePathName); 01194 01195 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName); 01196 01197 if (ppszDisplayName==NULL) 01198 return E_POINTER; 01199 01200 if (pmkToLeft!=NULL) 01201 return E_INVALIDARG; 01202 01203 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(len+1)); 01204 if (*ppszDisplayName==NULL) 01205 return E_OUTOFMEMORY; 01206 01207 strcpyW(*ppszDisplayName,This->filePathName); 01208 01209 TRACE("-- %s\n", debugstr_w(*ppszDisplayName)); 01210 01211 return S_OK; 01212 } 01213 01214 /****************************************************************************** 01215 * FileMoniker_ParseDisplayName 01216 */ 01217 static HRESULT WINAPI 01218 FileMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, 01219 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut) 01220 { 01221 FIXME("(%p,%p,%p,%p,%p,%p),stub!\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut); 01222 return E_NOTIMPL; 01223 } 01224 01225 /****************************************************************************** 01226 * FileMoniker_IsSystemMoniker 01227 */ 01228 static HRESULT WINAPI 01229 FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) 01230 { 01231 TRACE("(%p,%p)\n",iface,pwdMksys); 01232 01233 if (!pwdMksys) 01234 return E_POINTER; 01235 01236 (*pwdMksys)=MKSYS_FILEMONIKER; 01237 01238 return S_OK; 01239 } 01240 01241 /******************************************************************************* 01242 * FileMonikerIROTData_QueryInterface 01243 */ 01244 static HRESULT WINAPI 01245 FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject) 01246 { 01247 01248 FileMonikerImpl *This = impl_from_IROTData(iface); 01249 01250 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); 01251 01252 return FileMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject); 01253 } 01254 01255 /*********************************************************************** 01256 * FileMonikerIROTData_AddRef 01257 */ 01258 static ULONG WINAPI 01259 FileMonikerROTDataImpl_AddRef(IROTData *iface) 01260 { 01261 FileMonikerImpl *This = impl_from_IROTData(iface); 01262 01263 TRACE("(%p)\n",This); 01264 01265 return IMoniker_AddRef(&This->IMoniker_iface); 01266 } 01267 01268 /*********************************************************************** 01269 * FileMonikerIROTData_Release 01270 */ 01271 static ULONG WINAPI 01272 FileMonikerROTDataImpl_Release(IROTData* iface) 01273 { 01274 FileMonikerImpl *This = impl_from_IROTData(iface); 01275 01276 TRACE("(%p)\n",This); 01277 01278 return FileMonikerImpl_Release(&This->IMoniker_iface); 01279 } 01280 01281 /****************************************************************************** 01282 * FileMonikerIROTData_GetComparisonData 01283 */ 01284 static HRESULT WINAPI 01285 FileMonikerROTDataImpl_GetComparisonData(IROTData* iface, BYTE* pbData, 01286 ULONG cbMax, ULONG* pcbData) 01287 { 01288 FileMonikerImpl *This = impl_from_IROTData(iface); 01289 int len = strlenW(This->filePathName)+1; 01290 int i; 01291 LPWSTR pszFileName; 01292 01293 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData); 01294 01295 *pcbData = sizeof(CLSID) + len * sizeof(WCHAR); 01296 if (cbMax < *pcbData) 01297 return E_OUTOFMEMORY; 01298 01299 memcpy(pbData, &CLSID_FileMoniker, sizeof(CLSID)); 01300 pszFileName = (LPWSTR)(pbData+sizeof(CLSID)); 01301 for (i = 0; i < len; i++) 01302 pszFileName[i] = toupperW(This->filePathName[i]); 01303 01304 return S_OK; 01305 } 01306 01307 /* 01308 * Virtual function table for the FileMonikerImpl class which include IPersist, 01309 * IPersistStream and IMoniker functions. 01310 */ 01311 static const IMonikerVtbl VT_FileMonikerImpl = 01312 { 01313 FileMonikerImpl_QueryInterface, 01314 FileMonikerImpl_AddRef, 01315 FileMonikerImpl_Release, 01316 FileMonikerImpl_GetClassID, 01317 FileMonikerImpl_IsDirty, 01318 FileMonikerImpl_Load, 01319 FileMonikerImpl_Save, 01320 FileMonikerImpl_GetSizeMax, 01321 FileMonikerImpl_BindToObject, 01322 FileMonikerImpl_BindToStorage, 01323 FileMonikerImpl_Reduce, 01324 FileMonikerImpl_ComposeWith, 01325 FileMonikerImpl_Enum, 01326 FileMonikerImpl_IsEqual, 01327 FileMonikerImpl_Hash, 01328 FileMonikerImpl_IsRunning, 01329 FileMonikerImpl_GetTimeOfLastChange, 01330 FileMonikerImpl_Inverse, 01331 FileMonikerImpl_CommonPrefixWith, 01332 FileMonikerImpl_RelativePathTo, 01333 FileMonikerImpl_GetDisplayName, 01334 FileMonikerImpl_ParseDisplayName, 01335 FileMonikerImpl_IsSystemMoniker 01336 }; 01337 01338 /* Virtual function table for the IROTData class. */ 01339 static const IROTDataVtbl VT_ROTDataImpl = 01340 { 01341 FileMonikerROTDataImpl_QueryInterface, 01342 FileMonikerROTDataImpl_AddRef, 01343 FileMonikerROTDataImpl_Release, 01344 FileMonikerROTDataImpl_GetComparisonData 01345 }; 01346 01347 /****************************************************************************** 01348 * FileMoniker_Construct (local function) 01349 */ 01350 static HRESULT FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName) 01351 { 01352 int nb=0,i; 01353 int sizeStr=lstrlenW(lpszPathName); 01354 LPOLESTR *tabStr=0; 01355 static const WCHAR twoPoint[]={'.','.',0}; 01356 static const WCHAR bkSlash[]={'\\',0}; 01357 BYTE addBkSlash; 01358 01359 TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName)); 01360 01361 /* Initialize the virtual function table. */ 01362 This->IMoniker_iface.lpVtbl = &VT_FileMonikerImpl; 01363 This->IROTData_iface.lpVtbl = &VT_ROTDataImpl; 01364 This->ref = 0; 01365 This->pMarshal = NULL; 01366 01367 This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1)); 01368 01369 if (This->filePathName==NULL) 01370 return E_OUTOFMEMORY; 01371 01372 strcpyW(This->filePathName,lpszPathName); 01373 01374 nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr); 01375 01376 if (nb > 0 ){ 01377 01378 addBkSlash=1; 01379 if (lstrcmpW(tabStr[0],twoPoint)!=0) 01380 addBkSlash=0; 01381 else 01382 for(i=0;i<nb;i++){ 01383 01384 if ( (lstrcmpW(tabStr[i],twoPoint)!=0) && (lstrcmpW(tabStr[i],bkSlash)!=0) ){ 01385 addBkSlash=0; 01386 break; 01387 } 01388 else 01389 01390 if (lstrcmpW(tabStr[i],bkSlash)==0 && i<nb-1 && lstrcmpW(tabStr[i+1],bkSlash)==0){ 01391 *tabStr[i]=0; 01392 sizeStr--; 01393 addBkSlash=0; 01394 break; 01395 } 01396 } 01397 01398 if (lstrcmpW(tabStr[nb-1],bkSlash)==0) 01399 addBkSlash=0; 01400 01401 This->filePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR)); 01402 01403 *This->filePathName=0; 01404 01405 for(i=0;tabStr[i]!=NULL;i++) 01406 strcatW(This->filePathName,tabStr[i]); 01407 01408 if (addBkSlash) 01409 strcatW(This->filePathName,bkSlash); 01410 } 01411 01412 for(i=0; tabStr[i]!=NULL;i++) 01413 CoTaskMemFree(tabStr[i]); 01414 CoTaskMemFree(tabStr); 01415 01416 return S_OK; 01417 } 01418 01419 /****************************************************************************** 01420 * CreateFileMoniker (OLE32.@) 01421 ******************************************************************************/ 01422 HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, IMoniker **ppmk) 01423 { 01424 FileMonikerImpl* newFileMoniker; 01425 HRESULT hr; 01426 01427 TRACE("(%s,%p)\n",debugstr_w(lpszPathName),ppmk); 01428 01429 if (!ppmk) 01430 return E_POINTER; 01431 01432 if(!lpszPathName) 01433 return MK_E_SYNTAX; 01434 01435 *ppmk=NULL; 01436 01437 newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl)); 01438 01439 if (!newFileMoniker) 01440 return E_OUTOFMEMORY; 01441 01442 hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName); 01443 01444 if (SUCCEEDED(hr)) 01445 hr = IMoniker_QueryInterface(&newFileMoniker->IMoniker_iface,&IID_IMoniker,(void**)ppmk); 01446 else 01447 HeapFree(GetProcessHeap(),0,newFileMoniker); 01448 01449 return hr; 01450 } 01451 01452 /* find a character from a set in reverse without the string having to be null-terminated */ 01453 static inline WCHAR *memrpbrkW(const WCHAR *ptr, size_t n, const WCHAR *accept) 01454 { 01455 const WCHAR *end, *ret = NULL; 01456 for (end = ptr + n; ptr < end; ptr++) if (strchrW(accept, *ptr)) ret = ptr; 01457 return (WCHAR *)ret; 01458 } 01459 01460 HRESULT FileMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName, 01461 LPDWORD pchEaten, IMoniker **ppmk) 01462 { 01463 LPCWSTR end; 01464 static const WCHAR wszSeparators[] = {':','\\','/','!',0}; 01465 01466 for (end = szDisplayName + strlenW(szDisplayName); 01467 end && (end != szDisplayName); 01468 end = memrpbrkW(szDisplayName, end - szDisplayName, wszSeparators)) 01469 { 01470 HRESULT hr; 01471 IRunningObjectTable *rot; 01472 IMoniker *file_moniker; 01473 LPWSTR file_display_name; 01474 LPWSTR full_path_name; 01475 DWORD full_path_name_len; 01476 int len = end - szDisplayName; 01477 01478 file_display_name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); 01479 if (!file_display_name) return E_OUTOFMEMORY; 01480 memcpy(file_display_name, szDisplayName, len * sizeof(WCHAR)); 01481 file_display_name[len] = '\0'; 01482 01483 hr = CreateFileMoniker(file_display_name, &file_moniker); 01484 if (FAILED(hr)) 01485 { 01486 HeapFree(GetProcessHeap(), 0, file_display_name); 01487 return hr; 01488 } 01489 01490 hr = IBindCtx_GetRunningObjectTable(pbc, &rot); 01491 if (FAILED(hr)) 01492 { 01493 HeapFree(GetProcessHeap(), 0, file_display_name); 01494 IMoniker_Release(file_moniker); 01495 return hr; 01496 } 01497 01498 hr = IRunningObjectTable_IsRunning(rot, file_moniker); 01499 IRunningObjectTable_Release(rot); 01500 if (FAILED(hr)) 01501 { 01502 HeapFree(GetProcessHeap(), 0, file_display_name); 01503 IMoniker_Release(file_moniker); 01504 return hr; 01505 } 01506 if (hr == S_OK) 01507 { 01508 TRACE("found running file moniker for %s\n", debugstr_w(file_display_name)); 01509 *pchEaten = len; 01510 *ppmk = file_moniker; 01511 HeapFree(GetProcessHeap(), 0, file_display_name); 01512 return S_OK; 01513 } 01514 01515 full_path_name_len = GetFullPathNameW(file_display_name, 0, NULL, NULL); 01516 if (!full_path_name_len) 01517 { 01518 HeapFree(GetProcessHeap(), 0, file_display_name); 01519 IMoniker_Release(file_moniker); 01520 return MK_E_SYNTAX; 01521 } 01522 full_path_name = HeapAlloc(GetProcessHeap(), 0, full_path_name_len * sizeof(WCHAR)); 01523 if (!full_path_name) 01524 { 01525 HeapFree(GetProcessHeap(), 0, file_display_name); 01526 IMoniker_Release(file_moniker); 01527 return E_OUTOFMEMORY; 01528 } 01529 GetFullPathNameW(file_display_name, full_path_name_len, full_path_name, NULL); 01530 01531 if (GetFileAttributesW(full_path_name) == INVALID_FILE_ATTRIBUTES) 01532 TRACE("couldn't open file %s\n", debugstr_w(full_path_name)); 01533 else 01534 { 01535 TRACE("got file moniker for %s\n", debugstr_w(szDisplayName)); 01536 *pchEaten = len; 01537 *ppmk = file_moniker; 01538 HeapFree(GetProcessHeap(), 0, file_display_name); 01539 HeapFree(GetProcessHeap(), 0, full_path_name); 01540 return S_OK; 01541 } 01542 HeapFree(GetProcessHeap(), 0, file_display_name); 01543 HeapFree(GetProcessHeap(), 0, full_path_name); 01544 IMoniker_Release(file_moniker); 01545 } 01546 01547 return MK_E_CANTOPENFILE; 01548 } 01549 01550 01551 static HRESULT WINAPI FileMonikerCF_QueryInterface(LPCLASSFACTORY iface, 01552 REFIID riid, LPVOID *ppv) 01553 { 01554 *ppv = NULL; 01555 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) 01556 { 01557 *ppv = iface; 01558 IUnknown_AddRef(iface); 01559 return S_OK; 01560 } 01561 return E_NOINTERFACE; 01562 } 01563 01564 static ULONG WINAPI FileMonikerCF_AddRef(LPCLASSFACTORY iface) 01565 { 01566 return 2; /* non-heap based object */ 01567 } 01568 01569 static ULONG WINAPI FileMonikerCF_Release(LPCLASSFACTORY iface) 01570 { 01571 return 1; /* non-heap based object */ 01572 } 01573 01574 static HRESULT WINAPI FileMonikerCF_CreateInstance(LPCLASSFACTORY iface, 01575 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) 01576 { 01577 FileMonikerImpl* newFileMoniker; 01578 HRESULT hr; 01579 static const WCHAR wszEmpty[] = { 0 }; 01580 01581 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv); 01582 01583 *ppv = NULL; 01584 01585 if (pUnk) 01586 return CLASS_E_NOAGGREGATION; 01587 01588 newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl)); 01589 if (!newFileMoniker) 01590 return E_OUTOFMEMORY; 01591 01592 hr = FileMonikerImpl_Construct(newFileMoniker, wszEmpty); 01593 01594 if (SUCCEEDED(hr)) 01595 hr = IMoniker_QueryInterface(&newFileMoniker->IMoniker_iface, riid, ppv); 01596 if (FAILED(hr)) 01597 HeapFree(GetProcessHeap(),0,newFileMoniker); 01598 01599 return hr; 01600 } 01601 01602 static HRESULT WINAPI FileMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) 01603 { 01604 FIXME("(%d), stub!\n",fLock); 01605 return S_OK; 01606 } 01607 01608 static const IClassFactoryVtbl FileMonikerCFVtbl = 01609 { 01610 FileMonikerCF_QueryInterface, 01611 FileMonikerCF_AddRef, 01612 FileMonikerCF_Release, 01613 FileMonikerCF_CreateInstance, 01614 FileMonikerCF_LockServer 01615 }; 01616 static const IClassFactoryVtbl *FileMonikerCF = &FileMonikerCFVtbl; 01617 01618 HRESULT FileMonikerCF_Create(REFIID riid, LPVOID *ppv) 01619 { 01620 return IClassFactory_QueryInterface((IClassFactory *)&FileMonikerCF, riid, ppv); 01621 } Generated on Sat May 26 2012 04:24:09 for ReactOS by
1.7.6.1
|