Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencompositemoniker.c
Go to the documentation of this file.
00001 /* 00002 * CompositeMonikers implementation 00003 * 00004 * Copyright 1999 Noomen Hamza 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <assert.h> 00022 #include <stdarg.h> 00023 #include <string.h> 00024 00025 #define COBJMACROS 00026 #define NONAMELESSUNION 00027 #define NONAMELESSSTRUCT 00028 00029 #include "windef.h" 00030 #include "winbase.h" 00031 #include "winuser.h" 00032 #include "winerror.h" 00033 #include "wine/debug.h" 00034 #include "wine/unicode.h" 00035 #include "ole2.h" 00036 #include "moniker.h" 00037 00038 WINE_DEFAULT_DEBUG_CHANNEL(ole); 00039 00040 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */ 00041 00042 /* CompositeMoniker data structure */ 00043 typedef struct CompositeMonikerImpl{ 00044 IMoniker IMoniker_iface; 00045 IROTData IROTData_iface; 00046 IMarshal IMarshal_iface; 00047 LONG ref; 00048 IMoniker** tabMoniker; /* dynamic table containing all components (monikers) of this composite moniker */ 00049 ULONG tabSize; /* size of tabMoniker */ 00050 ULONG tabLastIndex; /* first free index in tabMoniker */ 00051 } CompositeMonikerImpl; 00052 00053 static inline CompositeMonikerImpl *impl_from_IMoniker(IMoniker *iface) 00054 { 00055 return CONTAINING_RECORD(iface, CompositeMonikerImpl, IMoniker_iface); 00056 } 00057 00058 static inline CompositeMonikerImpl *impl_from_IROTData(IROTData *iface) 00059 { 00060 return CONTAINING_RECORD(iface, CompositeMonikerImpl, IROTData_iface); 00061 } 00062 00063 static inline CompositeMonikerImpl *impl_from_IMarshal(IMarshal *iface) 00064 { 00065 return CONTAINING_RECORD(iface, CompositeMonikerImpl, IMarshal_iface); 00066 } 00067 00068 /* EnumMoniker data structure */ 00069 typedef struct EnumMonikerImpl{ 00070 IEnumMoniker IEnumMoniker_iface; 00071 LONG ref; 00072 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */ 00073 ULONG tabSize; /* size of tabMoniker */ 00074 ULONG currentPos; /* index pointer on the current moniker */ 00075 } EnumMonikerImpl; 00076 00077 static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface) 00078 { 00079 return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface); 00080 } 00081 00082 static HRESULT EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk); 00083 00084 /******************************************************************************* 00085 * CompositeMoniker_QueryInterface 00086 *******************************************************************************/ 00087 static HRESULT WINAPI 00088 CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) 00089 { 00090 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 00091 00092 TRACE("(%p,%p,%p)\n",This,riid,ppvObject); 00093 00094 /* Perform a sanity check on the parameters.*/ 00095 if ( ppvObject==0 ) 00096 return E_INVALIDARG; 00097 00098 /* Initialize the return parameter */ 00099 *ppvObject = 0; 00100 00101 /* Compare the riid with the interface IDs implemented by this object.*/ 00102 if (IsEqualIID(&IID_IUnknown, riid) || 00103 IsEqualIID(&IID_IPersist, riid) || 00104 IsEqualIID(&IID_IPersistStream, riid) || 00105 IsEqualIID(&IID_IMoniker, riid) 00106 ) 00107 *ppvObject = iface; 00108 else if (IsEqualIID(&IID_IROTData, riid)) 00109 *ppvObject = &This->IROTData_iface; 00110 else if (IsEqualIID(&IID_IMarshal, riid)) 00111 *ppvObject = &This->IMarshal_iface; 00112 00113 /* Check that we obtained an interface.*/ 00114 if ((*ppvObject)==0) 00115 return E_NOINTERFACE; 00116 00117 /* Query Interface always increases the reference count by one when it is successful */ 00118 IMoniker_AddRef(iface); 00119 00120 return S_OK; 00121 } 00122 00123 /****************************************************************************** 00124 * CompositeMoniker_AddRef 00125 ******************************************************************************/ 00126 static ULONG WINAPI 00127 CompositeMonikerImpl_AddRef(IMoniker* iface) 00128 { 00129 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 00130 00131 TRACE("(%p)\n",This); 00132 00133 return InterlockedIncrement(&This->ref); 00134 } 00135 00136 static void CompositeMonikerImpl_ReleaseMonikersInTable(CompositeMonikerImpl *This) 00137 { 00138 ULONG i; 00139 00140 for (i = 0; i < This->tabLastIndex; i++) 00141 IMoniker_Release(This->tabMoniker[i]); 00142 00143 This->tabLastIndex = 0; 00144 } 00145 00146 /****************************************************************************** 00147 * CompositeMoniker_Release 00148 ******************************************************************************/ 00149 static ULONG WINAPI 00150 CompositeMonikerImpl_Release(IMoniker* iface) 00151 { 00152 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 00153 ULONG ref; 00154 00155 TRACE("(%p)\n",This); 00156 00157 ref = InterlockedDecrement(&This->ref); 00158 00159 /* destroy the object if there's no more reference on it */ 00160 if (ref == 0){ 00161 00162 /* release all the components before destroying this object */ 00163 CompositeMonikerImpl_ReleaseMonikersInTable(This); 00164 00165 HeapFree(GetProcessHeap(),0,This->tabMoniker); 00166 HeapFree(GetProcessHeap(),0,This); 00167 } 00168 return ref; 00169 } 00170 00171 /****************************************************************************** 00172 * CompositeMoniker_GetClassID 00173 ******************************************************************************/ 00174 static HRESULT WINAPI 00175 CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID) 00176 { 00177 TRACE("(%p,%p)\n",iface,pClassID); 00178 00179 if (pClassID==NULL) 00180 return E_POINTER; 00181 00182 *pClassID = CLSID_CompositeMoniker; 00183 00184 return S_OK; 00185 } 00186 00187 /****************************************************************************** 00188 * CompositeMoniker_IsDirty 00189 ******************************************************************************/ 00190 static HRESULT WINAPI 00191 CompositeMonikerImpl_IsDirty(IMoniker* iface) 00192 { 00193 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty 00194 method in the OLE-provided moniker interfaces always return S_FALSE because 00195 their internal state never changes. */ 00196 00197 TRACE("(%p)\n",iface); 00198 00199 return S_FALSE; 00200 } 00201 00202 /****************************************************************************** 00203 * CompositeMoniker_Load 00204 ******************************************************************************/ 00205 static HRESULT WINAPI 00206 CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm) 00207 { 00208 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 00209 HRESULT res; 00210 DWORD moniker_count; 00211 DWORD i; 00212 00213 TRACE("(%p,%p)\n",iface,pStm); 00214 00215 /* this function call OleLoadFromStream function for each moniker within this object */ 00216 00217 res=IStream_Read(pStm,&moniker_count,sizeof(DWORD),NULL); 00218 if (res != S_OK) 00219 { 00220 ERR("couldn't reading moniker count from stream\n"); 00221 return E_FAIL; 00222 } 00223 00224 CompositeMonikerImpl_ReleaseMonikersInTable(This); 00225 00226 for (i = 0; i < moniker_count; i++) 00227 { 00228 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]); 00229 if (FAILED(res)) 00230 { 00231 ERR("couldn't load moniker from stream, res = 0x%08x\n", res); 00232 break; 00233 } 00234 00235 /* resize the table if needed */ 00236 if (++This->tabLastIndex==This->tabSize){ 00237 00238 This->tabSize+=BLOCK_TAB_SIZE; 00239 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker)); 00240 00241 if (This->tabMoniker==NULL) 00242 return E_OUTOFMEMORY; 00243 } 00244 } 00245 00246 return res; 00247 } 00248 00249 /****************************************************************************** 00250 * CompositeMoniker_Save 00251 ******************************************************************************/ 00252 static HRESULT WINAPI 00253 CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty) 00254 { 00255 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 00256 HRESULT res; 00257 IEnumMoniker *enumMk; 00258 IMoniker *pmk; 00259 DWORD moniker_count = This->tabLastIndex; 00260 00261 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty); 00262 00263 /* This function calls OleSaveToStream function for each moniker within 00264 * this object. 00265 * When I tested this function in windows, I usually found this constant 00266 * at the beginning of the stream. I don't known why (there's no 00267 * indication in the specification) ! 00268 */ 00269 res=IStream_Write(pStm,&moniker_count,sizeof(moniker_count),NULL); 00270 if (FAILED(res)) return res; 00271 00272 IMoniker_Enum(iface,TRUE,&enumMk); 00273 00274 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){ 00275 00276 res=OleSaveToStream((IPersistStream*)pmk,pStm); 00277 00278 IMoniker_Release(pmk); 00279 00280 if (FAILED(res)){ 00281 00282 IEnumMoniker_Release(enumMk); 00283 return res; 00284 } 00285 } 00286 00287 IEnumMoniker_Release(enumMk); 00288 00289 return S_OK; 00290 } 00291 00292 /****************************************************************************** 00293 * CompositeMoniker_GetSizeMax 00294 ******************************************************************************/ 00295 static HRESULT WINAPI 00296 CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize) 00297 { 00298 IEnumMoniker *enumMk; 00299 IMoniker *pmk; 00300 ULARGE_INTEGER ptmpSize; 00301 00302 /* The sizeMax of this object is calculated by calling GetSizeMax on 00303 * each moniker within this object then summing all returned values 00304 */ 00305 00306 TRACE("(%p,%p)\n",iface,pcbSize); 00307 00308 if (!pcbSize) 00309 return E_POINTER; 00310 00311 pcbSize->QuadPart = sizeof(DWORD); 00312 00313 IMoniker_Enum(iface,TRUE,&enumMk); 00314 00315 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){ 00316 00317 IMoniker_GetSizeMax(pmk,&ptmpSize); 00318 00319 IMoniker_Release(pmk); 00320 00321 pcbSize->QuadPart = ptmpSize.QuadPart + sizeof(CLSID); 00322 } 00323 00324 IEnumMoniker_Release(enumMk); 00325 00326 return S_OK; 00327 } 00328 00329 /****************************************************************************** 00330 * CompositeMoniker_BindToObject 00331 ******************************************************************************/ 00332 static HRESULT WINAPI 00333 CompositeMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, 00334 IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult) 00335 { 00336 HRESULT res; 00337 IRunningObjectTable *prot; 00338 IMoniker *tempMk,*antiMk,*mostRigthMk; 00339 IEnumMoniker *enumMoniker; 00340 00341 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult); 00342 00343 if (ppvResult==NULL) 00344 return E_POINTER; 00345 00346 *ppvResult=0; 00347 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */ 00348 /* object for the requested interface pointer. */ 00349 if(pmkToLeft==NULL){ 00350 00351 res=IBindCtx_GetRunningObjectTable(pbc,&prot); 00352 00353 if (SUCCEEDED(res)){ 00354 00355 /* if the requested class was loaded before ! we don't need to reload it */ 00356 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult); 00357 00358 if (res==S_OK) 00359 return res; 00360 } 00361 } 00362 else{ 00363 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */ 00364 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */ 00365 00366 IMoniker_Enum(iface,FALSE,&enumMoniker); 00367 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); 00368 IEnumMoniker_Release(enumMoniker); 00369 00370 res=CreateAntiMoniker(&antiMk); 00371 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); 00372 IMoniker_Release(antiMk); 00373 00374 res=IMoniker_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult); 00375 00376 IMoniker_Release(tempMk); 00377 IMoniker_Release(mostRigthMk); 00378 } 00379 00380 return res; 00381 } 00382 00383 /****************************************************************************** 00384 * CompositeMoniker_BindToStorage 00385 ******************************************************************************/ 00386 static HRESULT WINAPI 00387 CompositeMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, 00388 IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult) 00389 { 00390 HRESULT res; 00391 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftMk; 00392 IEnumMoniker *enumMoniker; 00393 00394 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult); 00395 00396 *ppvResult=0; 00397 00398 /* This method recursively calls BindToStorage on the rightmost component of the composite, */ 00399 /* passing the rest of the composite as the pmkToLeft parameter for that call. */ 00400 00401 if (pmkToLeft) 00402 { 00403 res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk); 00404 if (FAILED(res)) return res; 00405 } 00406 else 00407 leftMk = iface; 00408 00409 IMoniker_Enum(iface, FALSE, &enumMoniker); 00410 IEnumMoniker_Next(enumMoniker, 1, &mostRigthMk, NULL); 00411 IEnumMoniker_Release(enumMoniker); 00412 00413 res = CreateAntiMoniker(&antiMk); 00414 if (FAILED(res)) return res; 00415 res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk); 00416 if (FAILED(res)) return res; 00417 IMoniker_Release(antiMk); 00418 00419 res = IMoniker_BindToStorage(mostRigthMk, pbc, tempMk, riid, ppvResult); 00420 00421 IMoniker_Release(tempMk); 00422 00423 IMoniker_Release(mostRigthMk); 00424 00425 if (pmkToLeft) 00426 IMoniker_Release(leftMk); 00427 00428 return res; 00429 } 00430 00431 /****************************************************************************** 00432 * CompositeMoniker_Reduce 00433 ******************************************************************************/ 00434 static HRESULT WINAPI 00435 CompositeMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar, 00436 IMoniker** ppmkToLeft, IMoniker** ppmkReduced) 00437 { 00438 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk; 00439 IEnumMoniker *enumMoniker; 00440 00441 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced); 00442 00443 if (ppmkReduced==NULL) 00444 return E_POINTER; 00445 00446 /* This method recursively calls Reduce for each of its component monikers. */ 00447 00448 if (ppmkToLeft==NULL){ 00449 00450 IMoniker_Enum(iface,FALSE,&enumMoniker); 00451 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); 00452 IEnumMoniker_Release(enumMoniker); 00453 00454 CreateAntiMoniker(&antiMk); 00455 IMoniker_ComposeWith(iface,antiMk,0,&tempMk); 00456 IMoniker_Release(antiMk); 00457 00458 return IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced); 00459 } 00460 else if (*ppmkToLeft==NULL) 00461 00462 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced); 00463 00464 else{ 00465 00466 /* separate the composite moniker in to left and right moniker */ 00467 IMoniker_Enum(iface,FALSE,&enumMoniker); 00468 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); 00469 IEnumMoniker_Release(enumMoniker); 00470 00471 CreateAntiMoniker(&antiMk); 00472 IMoniker_ComposeWith(iface,antiMk,0,&tempMk); 00473 IMoniker_Release(antiMk); 00474 00475 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */ 00476 /* of the reduced components */ 00477 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) && 00478 IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk) 00479 ) 00480 00481 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced); 00482 00483 else{ 00484 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/ 00485 00486 IMoniker_AddRef(iface); 00487 00488 *ppmkReduced=iface; 00489 00490 return MK_S_REDUCED_TO_SELF; 00491 } 00492 } 00493 } 00494 00495 /****************************************************************************** 00496 * CompositeMoniker_ComposeWith 00497 ******************************************************************************/ 00498 static HRESULT WINAPI 00499 CompositeMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight, 00500 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite) 00501 { 00502 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite); 00503 00504 if ((ppmkComposite==NULL)||(pmkRight==NULL)) 00505 return E_POINTER; 00506 00507 *ppmkComposite=0; 00508 00509 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */ 00510 /* otherwise, the method returns the result of combining the two monikers by calling the */ 00511 /* CreateGenericComposite function */ 00512 00513 if (fOnlyIfNotGeneric) 00514 return MK_E_NEEDGENERIC; 00515 00516 return CreateGenericComposite(iface,pmkRight,ppmkComposite); 00517 } 00518 00519 /****************************************************************************** 00520 * CompositeMoniker_Enum 00521 ******************************************************************************/ 00522 static HRESULT WINAPI 00523 CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) 00524 { 00525 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 00526 00527 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker); 00528 00529 if (ppenumMoniker == NULL) 00530 return E_POINTER; 00531 00532 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker); 00533 } 00534 00535 /****************************************************************************** 00536 * CompositeMoniker_IsEqual 00537 ******************************************************************************/ 00538 static HRESULT WINAPI 00539 CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) 00540 { 00541 IEnumMoniker *enumMoniker1,*enumMoniker2; 00542 IMoniker *tempMk1,*tempMk2; 00543 HRESULT res1,res2,res; 00544 BOOL done; 00545 00546 TRACE("(%p,%p)\n",iface,pmkOtherMoniker); 00547 00548 if (pmkOtherMoniker==NULL) 00549 return S_FALSE; 00550 00551 /* This method returns S_OK if the components of both monikers are equal when compared in the */ 00552 /* left-to-right order.*/ 00553 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1); 00554 00555 if (enumMoniker1==NULL) 00556 return S_FALSE; 00557 00558 IMoniker_Enum(iface,TRUE,&enumMoniker2); 00559 00560 do { 00561 00562 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 00563 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL); 00564 00565 if((res1==S_OK)&&(res2==S_OK)){ 00566 done = (res = IMoniker_IsEqual(tempMk1,tempMk2)) == S_FALSE; 00567 } 00568 else 00569 { 00570 res = (res1==S_FALSE) && (res2==S_FALSE); 00571 done = TRUE; 00572 } 00573 00574 if (res1==S_OK) 00575 IMoniker_Release(tempMk1); 00576 00577 if (res2==S_OK) 00578 IMoniker_Release(tempMk2); 00579 } while (!done); 00580 00581 IEnumMoniker_Release(enumMoniker1); 00582 IEnumMoniker_Release(enumMoniker2); 00583 00584 return res; 00585 } 00586 /****************************************************************************** 00587 * CompositeMoniker_Hash 00588 ******************************************************************************/ 00589 static HRESULT WINAPI 00590 CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) 00591 { 00592 IEnumMoniker *enumMoniker; 00593 IMoniker *tempMk; 00594 HRESULT res; 00595 DWORD tempHash; 00596 00597 TRACE("(%p,%p)\n",iface,pdwHash); 00598 00599 if (pdwHash==NULL) 00600 return E_POINTER; 00601 00602 res = IMoniker_Enum(iface,TRUE,&enumMoniker); 00603 if(FAILED(res)) 00604 return res; 00605 00606 *pdwHash = 0; 00607 00608 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){ 00609 res = IMoniker_Hash(tempMk, &tempHash); 00610 if(FAILED(res)) 00611 break; 00612 *pdwHash = *pdwHash ^ tempHash; 00613 00614 IMoniker_Release(tempMk); 00615 } 00616 00617 IEnumMoniker_Release(enumMoniker); 00618 00619 return res; 00620 } 00621 00622 /****************************************************************************** 00623 * CompositeMoniker_IsRunning 00624 ******************************************************************************/ 00625 static HRESULT WINAPI 00626 CompositeMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, 00627 IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning) 00628 { 00629 IRunningObjectTable* rot; 00630 HRESULT res; 00631 IMoniker *tempMk,*antiMk,*mostRigthMk; 00632 IEnumMoniker *enumMoniker; 00633 00634 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning); 00635 00636 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/ 00637 if (pmkToLeft!=NULL){ 00638 00639 CreateGenericComposite(pmkToLeft,iface,&tempMk); 00640 00641 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning); 00642 00643 IMoniker_Release(tempMk); 00644 00645 return res; 00646 } 00647 else 00648 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */ 00649 /* to this moniker */ 00650 00651 if (pmkNewlyRunning!=NULL) 00652 00653 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK) 00654 return S_OK; 00655 00656 else 00657 return S_FALSE; 00658 00659 else{ 00660 00661 if (pbc==NULL) 00662 return E_INVALIDARG; 00663 00664 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */ 00665 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */ 00666 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */ 00667 /* the composite as the pmkToLeft parameter for that call. */ 00668 00669 res=IBindCtx_GetRunningObjectTable(pbc,&rot); 00670 00671 if (FAILED(res)) 00672 return res; 00673 00674 res = IRunningObjectTable_IsRunning(rot,iface); 00675 IRunningObjectTable_Release(rot); 00676 00677 if(res==S_OK) 00678 return S_OK; 00679 00680 else{ 00681 00682 IMoniker_Enum(iface,FALSE,&enumMoniker); 00683 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); 00684 IEnumMoniker_Release(enumMoniker); 00685 00686 res=CreateAntiMoniker(&antiMk); 00687 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); 00688 IMoniker_Release(antiMk); 00689 00690 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning); 00691 00692 IMoniker_Release(tempMk); 00693 IMoniker_Release(mostRigthMk); 00694 00695 return res; 00696 } 00697 } 00698 } 00699 00700 /****************************************************************************** 00701 * CompositeMoniker_GetTimeOfLastChange 00702 ******************************************************************************/ 00703 static HRESULT WINAPI 00704 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, 00705 IMoniker* pmkToLeft, FILETIME* pCompositeTime) 00706 { 00707 HRESULT res; 00708 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftMk; 00709 IEnumMoniker *enumMoniker; 00710 00711 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime); 00712 00713 if (pCompositeTime==NULL) 00714 return E_INVALIDARG; 00715 00716 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */ 00717 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */ 00718 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */ 00719 /* of the composite as the pmkToLeft parameter for that call. */ 00720 if (pmkToLeft) 00721 { 00722 IRunningObjectTable* rot; 00723 00724 res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk); 00725 00726 res = IBindCtx_GetRunningObjectTable(pbc,&rot); 00727 if (FAILED(res)) 00728 { 00729 IMoniker_Release(leftMk); 00730 return res; 00731 } 00732 00733 if (IRunningObjectTable_GetTimeOfLastChange(rot,leftMk,pCompositeTime)==S_OK) 00734 { 00735 IMoniker_Release(leftMk); 00736 return res; 00737 } 00738 } 00739 else 00740 leftMk = iface; 00741 00742 IMoniker_Enum(iface, FALSE, &enumMoniker); 00743 IEnumMoniker_Next(enumMoniker, 1, &mostRigthMk, NULL); 00744 IEnumMoniker_Release(enumMoniker); 00745 00746 res = CreateAntiMoniker(&antiMk); 00747 res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk); 00748 IMoniker_Release(antiMk); 00749 00750 res = IMoniker_GetTimeOfLastChange(mostRigthMk, pbc, tempMk, pCompositeTime); 00751 00752 IMoniker_Release(tempMk); 00753 IMoniker_Release(mostRigthMk); 00754 00755 if (pmkToLeft) 00756 IMoniker_Release(leftMk); 00757 00758 return res; 00759 } 00760 00761 /****************************************************************************** 00762 * CompositeMoniker_Inverse 00763 ******************************************************************************/ 00764 static HRESULT WINAPI 00765 CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) 00766 { 00767 HRESULT res; 00768 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk; 00769 IEnumMoniker *enumMoniker; 00770 00771 TRACE("(%p,%p)\n",iface,ppmk); 00772 00773 if (ppmk==NULL) 00774 return E_POINTER; 00775 00776 /* This method returns a composite moniker that consists of the inverses of each of the components */ 00777 /* of the original composite, stored in reverse order */ 00778 00779 res=CreateAntiMoniker(&antiMk); 00780 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); 00781 IMoniker_Release(antiMk); 00782 00783 if (tempMk==NULL) 00784 00785 return IMoniker_Inverse(iface,ppmk); 00786 00787 else{ 00788 00789 IMoniker_Enum(iface,FALSE,&enumMoniker); 00790 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); 00791 IEnumMoniker_Release(enumMoniker); 00792 00793 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk); 00794 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk); 00795 00796 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk); 00797 00798 IMoniker_Release(tempMk); 00799 IMoniker_Release(mostRigthMk); 00800 IMoniker_Release(tempInvMk); 00801 IMoniker_Release(mostRigthInvMk); 00802 00803 return res; 00804 } 00805 } 00806 00807 /****************************************************************************** 00808 * CompositeMoniker_CommonPrefixWith 00809 ******************************************************************************/ 00810 static HRESULT WINAPI 00811 CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface, IMoniker* pmkOther, 00812 IMoniker** ppmkPrefix) 00813 { 00814 DWORD mkSys; 00815 HRESULT res1,res2; 00816 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2; 00817 IEnumMoniker *enumMoniker1,*enumMoniker2; 00818 ULONG i,nbCommonMk=0; 00819 00820 /* If the other moniker is a composite, this method compares the components of each composite from left */ 00821 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */ 00822 /* of the leftmost components were common to both monikers. */ 00823 00824 if (ppmkPrefix==NULL) 00825 return E_POINTER; 00826 00827 *ppmkPrefix=0; 00828 00829 if (pmkOther==NULL) 00830 return MK_E_NOPREFIX; 00831 00832 IMoniker_IsSystemMoniker(pmkOther,&mkSys); 00833 00834 if(mkSys==MKSYS_GENERICCOMPOSITE){ 00835 00836 IMoniker_Enum(iface,TRUE,&enumMoniker1); 00837 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2); 00838 00839 while(1){ 00840 00841 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL); 00842 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL); 00843 00844 if ((res1==S_FALSE) && (res2==S_FALSE)){ 00845 00846 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/ 00847 *ppmkPrefix=iface; 00848 IMoniker_AddRef(iface); 00849 return MK_S_US; 00850 } 00851 else if ((res1==S_OK) && (res2==S_OK)){ 00852 00853 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK) 00854 00855 nbCommonMk++; 00856 00857 else 00858 break; 00859 00860 } 00861 else if (res1==S_OK){ 00862 00863 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */ 00864 /* ppmkPrefix to the other moniker. */ 00865 *ppmkPrefix=pmkOther; 00866 return MK_S_HIM; 00867 } 00868 else{ 00869 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */ 00870 /* to this moniker. */ 00871 *ppmkPrefix=iface; 00872 return MK_S_ME; 00873 } 00874 } 00875 00876 IEnumMoniker_Release(enumMoniker1); 00877 IEnumMoniker_Release(enumMoniker2); 00878 00879 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */ 00880 if (nbCommonMk==0) 00881 return MK_E_NOPREFIX; 00882 00883 IEnumMoniker_Reset(enumMoniker1); 00884 00885 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 00886 00887 /* if we have more than one common moniker the result will be a composite moniker */ 00888 if (nbCommonMk>1){ 00889 00890 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/ 00891 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL); 00892 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix); 00893 IMoniker_Release(tempMk1); 00894 IMoniker_Release(tempMk2); 00895 00896 /* compose all common monikers in a composite moniker */ 00897 for(i=0;i<nbCommonMk;i++){ 00898 00899 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 00900 00901 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2); 00902 00903 IMoniker_Release(*ppmkPrefix); 00904 00905 IMoniker_Release(tempMk1); 00906 00907 *ppmkPrefix=tempMk2; 00908 } 00909 return S_OK; 00910 } 00911 else{ 00912 /* if we have only one common moniker the result will be a simple moniker which is the most-left one*/ 00913 *ppmkPrefix=tempMk1; 00914 00915 return S_OK; 00916 } 00917 } 00918 else{ 00919 /* If the other moniker is not a composite, the method simply compares it to the leftmost component 00920 of this moniker.*/ 00921 00922 IMoniker_Enum(iface,TRUE,&enumMoniker1); 00923 00924 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL); 00925 00926 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){ 00927 00928 *ppmkPrefix=pmkOther; 00929 00930 return MK_S_HIM; 00931 } 00932 else 00933 return MK_E_NOPREFIX; 00934 } 00935 } 00936 00937 /*************************************************************************************************** 00938 * GetAfterCommonPrefix (local function) 00939 * This function returns a moniker that consist of the remainder when the common prefix is removed 00940 ***************************************************************************************************/ 00941 static VOID GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk) 00942 { 00943 IMoniker *tempMk,*tempMk1,*tempMk2; 00944 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3; 00945 ULONG nbRestMk=0; 00946 DWORD mkSys; 00947 HRESULT res1,res2; 00948 00949 *restMk=0; 00950 00951 /* to create an enumerator for pGenMk with current position pointed on the first element after common */ 00952 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */ 00953 /* on the first difference. */ 00954 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1); 00955 00956 IMoniker_IsSystemMoniker(commonMk,&mkSys); 00957 00958 if (mkSys==MKSYS_GENERICCOMPOSITE){ 00959 00960 IMoniker_Enum(commonMk,TRUE,&enumMoniker2); 00961 while(1){ 00962 00963 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 00964 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL); 00965 00966 if ((res1==S_FALSE)||(res2==S_FALSE)){ 00967 00968 if (res1==S_OK) 00969 00970 nbRestMk++; 00971 00972 IMoniker_Release(tempMk1); 00973 IMoniker_Release(tempMk2); 00974 00975 break; 00976 } 00977 IMoniker_Release(tempMk1); 00978 IMoniker_Release(tempMk2); 00979 } 00980 } 00981 else{ 00982 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 00983 IMoniker_Release(tempMk1); 00984 } 00985 00986 /* count the number of elements in the enumerator after the common prefix */ 00987 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3); 00988 00989 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++) 00990 00991 IMoniker_Release(tempMk); 00992 00993 if (nbRestMk==0) 00994 return; 00995 00996 /* create a generic composite moniker with monikers located after the common prefix */ 00997 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 00998 00999 if (nbRestMk==1){ 01000 01001 *restMk= tempMk1; 01002 return; 01003 } 01004 else { 01005 01006 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL); 01007 01008 CreateGenericComposite(tempMk1,tempMk2,restMk); 01009 01010 IMoniker_Release(tempMk1); 01011 01012 IMoniker_Release(tempMk2); 01013 01014 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){ 01015 01016 CreateGenericComposite(*restMk,tempMk1,&tempMk2); 01017 01018 IMoniker_Release(tempMk1); 01019 01020 IMoniker_Release(*restMk); 01021 01022 *restMk=tempMk2; 01023 } 01024 } 01025 } 01026 01027 /****************************************************************************** 01028 * CompositeMoniker_RelativePathTo 01029 ******************************************************************************/ 01030 static HRESULT WINAPI 01031 CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, 01032 IMoniker** ppmkRelPath) 01033 { 01034 HRESULT res; 01035 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0; 01036 01037 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath); 01038 01039 if (ppmkRelPath==NULL) 01040 return E_POINTER; 01041 01042 *ppmkRelPath=0; 01043 01044 /* This method finds the common prefix of the two monikers and creates two monikers that consist */ 01045 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */ 01046 /* of this moniker and composes the remainder of the other moniker on the right of it. */ 01047 01048 /* finds the common prefix of the two monikers */ 01049 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk); 01050 01051 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */ 01052 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){ 01053 01054 *ppmkRelPath=pmkOther; 01055 IMoniker_AddRef(pmkOther); 01056 return MK_S_HIM; 01057 } 01058 01059 GetAfterCommonPrefix(iface,commonMk,&restThisMk); 01060 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk); 01061 01062 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */ 01063 /* moniker when the common prefix is removed */ 01064 if (res==MK_S_HIM){ 01065 01066 IMoniker_Inverse(restThisMk,ppmkRelPath); 01067 IMoniker_Release(restThisMk); 01068 } 01069 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */ 01070 /* when the common prefix is removed */ 01071 else if (res==MK_S_ME){ 01072 01073 *ppmkRelPath=restOtherMk; 01074 IMoniker_AddRef(restOtherMk); 01075 } 01076 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */ 01077 /* moniker on the right of it. */ 01078 else if (res==S_OK){ 01079 01080 IMoniker_Inverse(restThisMk,&invRestThisMk); 01081 IMoniker_Release(restThisMk); 01082 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath); 01083 IMoniker_Release(invRestThisMk); 01084 IMoniker_Release(restOtherMk); 01085 } 01086 return S_OK; 01087 } 01088 01089 /****************************************************************************** 01090 * CompositeMoniker_GetDisplayName 01091 ******************************************************************************/ 01092 static HRESULT WINAPI 01093 CompositeMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc, 01094 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName) 01095 { 01096 ULONG lengthStr=1; 01097 IEnumMoniker *enumMoniker; 01098 IMoniker* tempMk; 01099 LPOLESTR tempStr; 01100 01101 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName); 01102 01103 if (ppszDisplayName==NULL) 01104 return E_POINTER; 01105 01106 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)); 01107 01108 if (*ppszDisplayName==NULL) 01109 return E_OUTOFMEMORY; 01110 01111 /* This method returns the concatenation of the display names returned by each component moniker of */ 01112 /* the composite */ 01113 01114 **ppszDisplayName=0; 01115 01116 IMoniker_Enum(iface,TRUE,&enumMoniker); 01117 01118 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){ 01119 01120 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr); 01121 01122 lengthStr+=lstrlenW(tempStr); 01123 01124 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR)); 01125 01126 if (*ppszDisplayName==NULL) 01127 return E_OUTOFMEMORY; 01128 01129 strcatW(*ppszDisplayName,tempStr); 01130 01131 CoTaskMemFree(tempStr); 01132 IMoniker_Release(tempMk); 01133 } 01134 01135 IEnumMoniker_Release(enumMoniker); 01136 01137 return S_OK; 01138 } 01139 01140 /****************************************************************************** 01141 * CompositeMoniker_ParseDisplayName 01142 ******************************************************************************/ 01143 static HRESULT WINAPI 01144 CompositeMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, 01145 IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, 01146 IMoniker** ppmkOut) 01147 { 01148 IEnumMoniker *enumMoniker; 01149 IMoniker *tempMk,*mostRigthMk,*antiMk; 01150 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/ 01151 /* passing everything else as the pmkToLeft parameter for that call. */ 01152 01153 /* get the most right moniker */ 01154 IMoniker_Enum(iface,FALSE,&enumMoniker); 01155 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); 01156 IEnumMoniker_Release(enumMoniker); 01157 01158 /* get the left moniker */ 01159 CreateAntiMoniker(&antiMk); 01160 IMoniker_ComposeWith(iface,antiMk,0,&tempMk); 01161 IMoniker_Release(antiMk); 01162 01163 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut); 01164 } 01165 01166 /****************************************************************************** 01167 * CompositeMoniker_IsSystemMoniker 01168 ******************************************************************************/ 01169 static HRESULT WINAPI 01170 CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) 01171 { 01172 TRACE("(%p,%p)\n",iface,pwdMksys); 01173 01174 if (!pwdMksys) 01175 return E_POINTER; 01176 01177 (*pwdMksys)=MKSYS_GENERICCOMPOSITE; 01178 01179 return S_OK; 01180 } 01181 01182 /******************************************************************************* 01183 * CompositeMonikerIROTData_QueryInterface 01184 *******************************************************************************/ 01185 static HRESULT WINAPI 01186 CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid, 01187 VOID** ppvObject) 01188 { 01189 CompositeMonikerImpl *This = impl_from_IROTData(iface); 01190 01191 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject); 01192 01193 return CompositeMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject); 01194 } 01195 01196 /*********************************************************************** 01197 * CompositeMonikerIROTData_AddRef 01198 */ 01199 static ULONG WINAPI 01200 CompositeMonikerROTDataImpl_AddRef(IROTData *iface) 01201 { 01202 CompositeMonikerImpl *This = impl_from_IROTData(iface); 01203 01204 TRACE("(%p)\n",iface); 01205 01206 return IMoniker_AddRef(&This->IMoniker_iface); 01207 } 01208 01209 /*********************************************************************** 01210 * CompositeMonikerIROTData_Release 01211 */ 01212 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface) 01213 { 01214 CompositeMonikerImpl *This = impl_from_IROTData(iface); 01215 01216 TRACE("(%p)\n",iface); 01217 01218 return IMoniker_Release(&This->IMoniker_iface); 01219 } 01220 01221 /****************************************************************************** 01222 * CompositeMonikerIROTData_GetComparisonData 01223 ******************************************************************************/ 01224 static HRESULT WINAPI 01225 CompositeMonikerROTDataImpl_GetComparisonData(IROTData* iface, 01226 BYTE* pbData, ULONG cbMax, ULONG* pcbData) 01227 { 01228 CompositeMonikerImpl *This = impl_from_IROTData(iface); 01229 IEnumMoniker *pEnumMk; 01230 IMoniker *pmk; 01231 HRESULT hr; 01232 01233 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData); 01234 01235 *pcbData = sizeof(CLSID); 01236 01237 hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk); 01238 if (FAILED(hr)) return hr; 01239 01240 while(IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK) 01241 { 01242 IROTData *pROTData; 01243 hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData); 01244 if (FAILED(hr)) 01245 ERR("moniker doesn't support IROTData interface\n"); 01246 01247 if (SUCCEEDED(hr)) 01248 { 01249 ULONG cbData; 01250 hr = IROTData_GetComparisonData(pROTData, NULL, 0, &cbData); 01251 IROTData_Release(pROTData); 01252 if (SUCCEEDED(hr) || (hr == E_OUTOFMEMORY)) 01253 { 01254 *pcbData += cbData; 01255 hr = S_OK; 01256 } 01257 else 01258 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr); 01259 } 01260 01261 IMoniker_Release(pmk); 01262 01263 if (FAILED(hr)) 01264 { 01265 IEnumMoniker_Release(pEnumMk); 01266 return hr; 01267 } 01268 } 01269 if (cbMax < *pcbData) 01270 return E_OUTOFMEMORY; 01271 01272 IEnumMoniker_Reset(pEnumMk); 01273 01274 memcpy(pbData, &CLSID_CompositeMoniker, sizeof(CLSID)); 01275 pbData += sizeof(CLSID); 01276 cbMax -= sizeof(CLSID); 01277 01278 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK) 01279 { 01280 IROTData *pROTData; 01281 hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData); 01282 if (FAILED(hr)) 01283 ERR("moniker doesn't support IROTData interface\n"); 01284 01285 if (SUCCEEDED(hr)) 01286 { 01287 ULONG cbData; 01288 hr = IROTData_GetComparisonData(pROTData, pbData, cbMax, &cbData); 01289 IROTData_Release(pROTData); 01290 if (SUCCEEDED(hr)) 01291 { 01292 pbData += cbData; 01293 cbMax -= cbData; 01294 } 01295 else 01296 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr); 01297 } 01298 01299 IMoniker_Release(pmk); 01300 01301 if (FAILED(hr)) 01302 { 01303 IEnumMoniker_Release(pEnumMk); 01304 return hr; 01305 } 01306 } 01307 01308 IEnumMoniker_Release(pEnumMk); 01309 01310 return S_OK; 01311 } 01312 01313 static HRESULT WINAPI CompositeMonikerMarshalImpl_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv) 01314 { 01315 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 01316 01317 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppv); 01318 01319 return CompositeMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppv); 01320 } 01321 01322 static ULONG WINAPI CompositeMonikerMarshalImpl_AddRef(IMarshal *iface) 01323 { 01324 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 01325 01326 TRACE("(%p)\n",iface); 01327 01328 return CompositeMonikerImpl_AddRef(&This->IMoniker_iface); 01329 } 01330 01331 static ULONG WINAPI CompositeMonikerMarshalImpl_Release(IMarshal *iface) 01332 { 01333 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 01334 01335 TRACE("(%p)\n",iface); 01336 01337 return CompositeMonikerImpl_Release(&This->IMoniker_iface); 01338 } 01339 01340 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetUnmarshalClass( 01341 IMarshal *iface, REFIID riid, void *pv, DWORD dwDestContext, 01342 void* pvDestContext, DWORD mshlflags, CLSID* pCid) 01343 { 01344 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 01345 01346 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv, 01347 dwDestContext, pvDestContext, mshlflags, pCid); 01348 01349 return IMoniker_GetClassID(&This->IMoniker_iface, pCid); 01350 } 01351 01352 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetMarshalSizeMax( 01353 IMarshal *iface, REFIID riid, void *pv, DWORD dwDestContext, 01354 void* pvDestContext, DWORD mshlflags, DWORD* pSize) 01355 { 01356 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 01357 IEnumMoniker *pEnumMk; 01358 IMoniker *pmk; 01359 HRESULT hr; 01360 ULARGE_INTEGER size; 01361 01362 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv, 01363 dwDestContext, pvDestContext, mshlflags, pSize); 01364 01365 *pSize = 0x10; /* to match native */ 01366 01367 hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk); 01368 if (FAILED(hr)) return hr; 01369 01370 hr = IMoniker_GetSizeMax(&This->IMoniker_iface, &size); 01371 01372 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK) 01373 { 01374 ULONG size; 01375 01376 hr = CoGetMarshalSizeMax(&size, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags); 01377 if (SUCCEEDED(hr)) 01378 *pSize += size; 01379 01380 IMoniker_Release(pmk); 01381 01382 if (FAILED(hr)) 01383 { 01384 IEnumMoniker_Release(pEnumMk); 01385 return hr; 01386 } 01387 } 01388 01389 IEnumMoniker_Release(pEnumMk); 01390 01391 return S_OK; 01392 } 01393 01394 static HRESULT WINAPI CompositeMonikerMarshalImpl_MarshalInterface(IMarshal *iface, IStream *pStm, 01395 REFIID riid, void* pv, DWORD dwDestContext, 01396 void* pvDestContext, DWORD mshlflags) 01397 { 01398 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 01399 IEnumMoniker *pEnumMk; 01400 IMoniker *pmk; 01401 HRESULT hr; 01402 ULONG i = 0; 01403 01404 TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv, 01405 dwDestContext, pvDestContext, mshlflags); 01406 01407 hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk); 01408 if (FAILED(hr)) return hr; 01409 01410 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK) 01411 { 01412 hr = CoMarshalInterface(pStm, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags); 01413 01414 IMoniker_Release(pmk); 01415 01416 if (FAILED(hr)) 01417 { 01418 IEnumMoniker_Release(pEnumMk); 01419 return hr; 01420 } 01421 i++; 01422 } 01423 01424 if (i != 2) 01425 FIXME("moniker count of %d not supported\n", i); 01426 01427 IEnumMoniker_Release(pEnumMk); 01428 01429 return S_OK; 01430 } 01431 01432 static HRESULT WINAPI CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, 01433 REFIID riid, void **ppv) 01434 { 01435 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 01436 HRESULT hr; 01437 01438 TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv); 01439 01440 CompositeMonikerImpl_ReleaseMonikersInTable(This); 01441 01442 /* resize the table if needed */ 01443 if (This->tabLastIndex + 2 > This->tabSize) 01444 { 01445 This->tabSize += max(BLOCK_TAB_SIZE, 2); 01446 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker)); 01447 01448 if (This->tabMoniker==NULL) 01449 return E_OUTOFMEMORY; 01450 } 01451 01452 hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]); 01453 if (FAILED(hr)) 01454 { 01455 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr); 01456 return hr; 01457 } 01458 This->tabLastIndex++; 01459 hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]); 01460 if (FAILED(hr)) 01461 { 01462 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr); 01463 return hr; 01464 } 01465 This->tabLastIndex++; 01466 01467 return IMoniker_QueryInterface(&This->IMoniker_iface, riid, ppv); 01468 } 01469 01470 static HRESULT WINAPI CompositeMonikerMarshalImpl_ReleaseMarshalData(IMarshal *iface, IStream *pStm) 01471 { 01472 TRACE("(%p)\n", pStm); 01473 /* can't release a state-based marshal as nothing on server side to 01474 * release */ 01475 return S_OK; 01476 } 01477 01478 static HRESULT WINAPI CompositeMonikerMarshalImpl_DisconnectObject(IMarshal *iface, 01479 DWORD dwReserved) 01480 { 01481 TRACE("(0x%x)\n", dwReserved); 01482 /* can't disconnect a state-based marshal as nothing on server side to 01483 * disconnect from */ 01484 return S_OK; 01485 } 01486 01487 /****************************************************************************** 01488 * EnumMonikerImpl_QueryInterface 01489 ******************************************************************************/ 01490 static HRESULT WINAPI 01491 EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject) 01492 { 01493 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01494 01495 TRACE("(%p,%p,%p)\n",This,riid,ppvObject); 01496 01497 /* Perform a sanity check on the parameters.*/ 01498 if ( ppvObject==0 ) 01499 return E_INVALIDARG; 01500 01501 /* Initialize the return parameter */ 01502 *ppvObject = 0; 01503 01504 /* Compare the riid with the interface IDs implemented by this object.*/ 01505 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid)) 01506 *ppvObject = iface; 01507 01508 /* Check that we obtained an interface.*/ 01509 if ((*ppvObject)==0) 01510 return E_NOINTERFACE; 01511 01512 /* Query Interface always increases the reference count by one when it is successful */ 01513 IEnumMoniker_AddRef(iface); 01514 01515 return S_OK; 01516 } 01517 01518 /****************************************************************************** 01519 * EnumMonikerImpl_AddRef 01520 ******************************************************************************/ 01521 static ULONG WINAPI 01522 EnumMonikerImpl_AddRef(IEnumMoniker* iface) 01523 { 01524 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01525 01526 TRACE("(%p)\n",This); 01527 01528 return InterlockedIncrement(&This->ref); 01529 01530 } 01531 01532 /****************************************************************************** 01533 * EnumMonikerImpl_Release 01534 ******************************************************************************/ 01535 static ULONG WINAPI 01536 EnumMonikerImpl_Release(IEnumMoniker* iface) 01537 { 01538 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01539 ULONG i; 01540 ULONG ref; 01541 TRACE("(%p)\n",This); 01542 01543 ref = InterlockedDecrement(&This->ref); 01544 01545 /* destroy the object if there's no more reference on it */ 01546 if (ref == 0) { 01547 01548 for(i=0;i<This->tabSize;i++) 01549 IMoniker_Release(This->tabMoniker[i]); 01550 01551 HeapFree(GetProcessHeap(),0,This->tabMoniker); 01552 HeapFree(GetProcessHeap(),0,This); 01553 } 01554 return ref; 01555 } 01556 01557 /****************************************************************************** 01558 * EnumMonikerImpl_Next 01559 ******************************************************************************/ 01560 static HRESULT WINAPI 01561 EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, 01562 ULONG* pceltFethed) 01563 { 01564 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01565 ULONG i; 01566 01567 /* retrieve the requested number of moniker from the current position */ 01568 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++) 01569 { 01570 rgelt[i]=This->tabMoniker[This->currentPos++]; 01571 IMoniker_AddRef(rgelt[i]); 01572 } 01573 01574 if (pceltFethed!=NULL) 01575 *pceltFethed= i; 01576 01577 if (i==celt) 01578 return S_OK; 01579 else 01580 return S_FALSE; 01581 } 01582 01583 /****************************************************************************** 01584 * EnumMonikerImpl_Skip 01585 ******************************************************************************/ 01586 static HRESULT WINAPI 01587 EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt) 01588 { 01589 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01590 01591 if ((This->currentPos+celt) >= This->tabSize) 01592 return S_FALSE; 01593 01594 This->currentPos+=celt; 01595 01596 return S_OK; 01597 } 01598 01599 /****************************************************************************** 01600 * EnumMonikerImpl_Reset 01601 ******************************************************************************/ 01602 static HRESULT WINAPI 01603 EnumMonikerImpl_Reset(IEnumMoniker* iface) 01604 { 01605 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01606 01607 This->currentPos=0; 01608 01609 return S_OK; 01610 } 01611 01612 /****************************************************************************** 01613 * EnumMonikerImpl_Clone 01614 ******************************************************************************/ 01615 static HRESULT WINAPI 01616 EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum) 01617 { 01618 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01619 01620 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum); 01621 } 01622 01623 /********************************************************************************/ 01624 /* Virtual function table for the IROTData class */ 01625 static const IEnumMonikerVtbl VT_EnumMonikerImpl = 01626 { 01627 EnumMonikerImpl_QueryInterface, 01628 EnumMonikerImpl_AddRef, 01629 EnumMonikerImpl_Release, 01630 EnumMonikerImpl_Next, 01631 EnumMonikerImpl_Skip, 01632 EnumMonikerImpl_Reset, 01633 EnumMonikerImpl_Clone 01634 }; 01635 01636 /****************************************************************************** 01637 * EnumMonikerImpl_CreateEnumMoniker 01638 ******************************************************************************/ 01639 static HRESULT 01640 EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, ULONG tabSize, 01641 ULONG currentPos, BOOL leftToRigth, IEnumMoniker ** ppmk) 01642 { 01643 EnumMonikerImpl* newEnumMoniker; 01644 int i; 01645 01646 if (currentPos > tabSize) 01647 return E_INVALIDARG; 01648 01649 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl)); 01650 01651 if (newEnumMoniker == 0) 01652 return STG_E_INSUFFICIENTMEMORY; 01653 01654 /* Initialize the virtual function table. */ 01655 newEnumMoniker->IEnumMoniker_iface.lpVtbl = &VT_EnumMonikerImpl; 01656 newEnumMoniker->ref = 1; 01657 01658 newEnumMoniker->tabSize=tabSize; 01659 newEnumMoniker->currentPos=currentPos; 01660 01661 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker)); 01662 01663 if (newEnumMoniker->tabMoniker==NULL) { 01664 HeapFree(GetProcessHeap(), 0, newEnumMoniker); 01665 return E_OUTOFMEMORY; 01666 } 01667 01668 if (leftToRigth) 01669 for (i=0;i<tabSize;i++){ 01670 01671 newEnumMoniker->tabMoniker[i]=tabMoniker[i]; 01672 IMoniker_AddRef(tabMoniker[i]); 01673 } 01674 else 01675 for (i=tabSize-1;i>=0;i--){ 01676 01677 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i]; 01678 IMoniker_AddRef(tabMoniker[i]); 01679 } 01680 01681 *ppmk=&newEnumMoniker->IEnumMoniker_iface; 01682 01683 return S_OK; 01684 } 01685 01686 /********************************************************************************/ 01687 /* Virtual function table for the CompositeMonikerImpl class which includes */ 01688 /* IPersist, IPersistStream and IMoniker functions. */ 01689 01690 static const IMonikerVtbl VT_CompositeMonikerImpl = 01691 { 01692 CompositeMonikerImpl_QueryInterface, 01693 CompositeMonikerImpl_AddRef, 01694 CompositeMonikerImpl_Release, 01695 CompositeMonikerImpl_GetClassID, 01696 CompositeMonikerImpl_IsDirty, 01697 CompositeMonikerImpl_Load, 01698 CompositeMonikerImpl_Save, 01699 CompositeMonikerImpl_GetSizeMax, 01700 CompositeMonikerImpl_BindToObject, 01701 CompositeMonikerImpl_BindToStorage, 01702 CompositeMonikerImpl_Reduce, 01703 CompositeMonikerImpl_ComposeWith, 01704 CompositeMonikerImpl_Enum, 01705 CompositeMonikerImpl_IsEqual, 01706 CompositeMonikerImpl_Hash, 01707 CompositeMonikerImpl_IsRunning, 01708 CompositeMonikerImpl_GetTimeOfLastChange, 01709 CompositeMonikerImpl_Inverse, 01710 CompositeMonikerImpl_CommonPrefixWith, 01711 CompositeMonikerImpl_RelativePathTo, 01712 CompositeMonikerImpl_GetDisplayName, 01713 CompositeMonikerImpl_ParseDisplayName, 01714 CompositeMonikerImpl_IsSystemMoniker 01715 }; 01716 01717 /********************************************************************************/ 01718 /* Virtual function table for the IROTData class. */ 01719 static const IROTDataVtbl VT_ROTDataImpl = 01720 { 01721 CompositeMonikerROTDataImpl_QueryInterface, 01722 CompositeMonikerROTDataImpl_AddRef, 01723 CompositeMonikerROTDataImpl_Release, 01724 CompositeMonikerROTDataImpl_GetComparisonData 01725 }; 01726 01727 static const IMarshalVtbl VT_MarshalImpl = 01728 { 01729 CompositeMonikerMarshalImpl_QueryInterface, 01730 CompositeMonikerMarshalImpl_AddRef, 01731 CompositeMonikerMarshalImpl_Release, 01732 CompositeMonikerMarshalImpl_GetUnmarshalClass, 01733 CompositeMonikerMarshalImpl_GetMarshalSizeMax, 01734 CompositeMonikerMarshalImpl_MarshalInterface, 01735 CompositeMonikerMarshalImpl_UnmarshalInterface, 01736 CompositeMonikerMarshalImpl_ReleaseMarshalData, 01737 CompositeMonikerMarshalImpl_DisconnectObject 01738 }; 01739 01740 /****************************************************************************** 01741 * Composite-Moniker_Construct (local function) 01742 *******************************************************************************/ 01743 static HRESULT 01744 CompositeMonikerImpl_Construct(IMoniker **ppMoniker, IMoniker *pmkFirst, IMoniker *pmkRest) 01745 { 01746 DWORD mkSys; 01747 IEnumMoniker *enumMoniker; 01748 IMoniker *tempMk; 01749 HRESULT res; 01750 CompositeMonikerImpl *This; 01751 01752 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 01753 01754 if (!This) 01755 return E_OUTOFMEMORY; 01756 01757 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest); 01758 01759 /* Initialize the virtual function table. */ 01760 This->IMoniker_iface.lpVtbl = &VT_CompositeMonikerImpl; 01761 This->IROTData_iface.lpVtbl = &VT_ROTDataImpl; 01762 This->IMarshal_iface.lpVtbl = &VT_MarshalImpl; 01763 This->ref = 1; 01764 01765 This->tabSize=BLOCK_TAB_SIZE; 01766 This->tabLastIndex=0; 01767 01768 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker)); 01769 if (This->tabMoniker==NULL) { 01770 HeapFree(GetProcessHeap(), 0, This); 01771 return E_OUTOFMEMORY; 01772 } 01773 01774 if (!pmkFirst && !pmkRest) 01775 { 01776 *ppMoniker = &This->IMoniker_iface; 01777 return S_OK; 01778 } 01779 01780 IMoniker_IsSystemMoniker(pmkFirst,&mkSys); 01781 01782 /* put the first moniker contents in the beginning of the table */ 01783 if (mkSys!=MKSYS_GENERICCOMPOSITE){ 01784 01785 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst; 01786 IMoniker_AddRef(pmkFirst); 01787 } 01788 else{ 01789 01790 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker); 01791 01792 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){ 01793 01794 01795 if (++This->tabLastIndex==This->tabSize){ 01796 LPVOID tab_moniker = This->tabMoniker; 01797 01798 This->tabSize+=BLOCK_TAB_SIZE; 01799 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker)); 01800 01801 if (This->tabMoniker==NULL){ 01802 HeapFree(GetProcessHeap(), 0, tab_moniker); 01803 HeapFree(GetProcessHeap(), 0, This); 01804 return E_OUTOFMEMORY; 01805 } 01806 } 01807 } 01808 01809 IEnumMoniker_Release(enumMoniker); 01810 } 01811 01812 /* put the rest moniker contents after the first one and make simplification if needed */ 01813 01814 IMoniker_IsSystemMoniker(pmkRest,&mkSys); 01815 01816 if (mkSys!=MKSYS_GENERICCOMPOSITE){ 01817 01818 /* add a simple moniker to the moniker table */ 01819 01820 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk); 01821 01822 if (res==MK_E_NEEDGENERIC){ 01823 01824 /* there's no simplification in this case */ 01825 This->tabMoniker[This->tabLastIndex]=pmkRest; 01826 01827 This->tabLastIndex++; 01828 01829 IMoniker_AddRef(pmkRest); 01830 } 01831 else if (tempMk==NULL){ 01832 01833 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */ 01834 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); 01835 01836 This->tabLastIndex--; 01837 } 01838 else if (SUCCEEDED(res)){ 01839 01840 /* the non-generic composition was successful so we can make a simplification in this case */ 01841 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); 01842 01843 This->tabMoniker[This->tabLastIndex-1]=tempMk; 01844 } else 01845 return res; 01846 01847 /* resize tabMoniker if needed */ 01848 if (This->tabLastIndex==This->tabSize){ 01849 LPVOID tab_moniker = This->tabMoniker; 01850 01851 This->tabSize+=BLOCK_TAB_SIZE; 01852 01853 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker)); 01854 01855 if (This->tabMoniker==NULL){ 01856 HeapFree(GetProcessHeap(), 0, tab_moniker); 01857 HeapFree(GetProcessHeap(), 0, This); 01858 return E_OUTOFMEMORY; 01859 } 01860 } 01861 } 01862 else{ 01863 01864 /* add a composite moniker to the moniker table (do the same thing 01865 * for each moniker within the composite moniker as a simple moniker 01866 * (see above for how to add a simple moniker case) ) 01867 */ 01868 IMoniker_Enum(pmkRest,TRUE,&enumMoniker); 01869 01870 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){ 01871 01872 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk); 01873 01874 if (res==MK_E_NEEDGENERIC){ 01875 01876 This->tabLastIndex++; 01877 } 01878 else if (tempMk==NULL){ 01879 01880 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); 01881 IMoniker_Release(This->tabMoniker[This->tabLastIndex]); 01882 This->tabLastIndex--; 01883 } 01884 else{ 01885 01886 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); 01887 01888 This->tabMoniker[This->tabLastIndex-1]=tempMk; 01889 } 01890 01891 if (This->tabLastIndex==This->tabSize){ 01892 LPVOID tab_moniker = This->tabMoniker; 01893 01894 This->tabSize+=BLOCK_TAB_SIZE; 01895 01896 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker)); 01897 01898 if (This->tabMoniker==NULL){ 01899 HeapFree(GetProcessHeap(), 0, tab_moniker); 01900 HeapFree(GetProcessHeap(), 0, This); 01901 return E_OUTOFMEMORY; 01902 } 01903 } 01904 } 01905 01906 IEnumMoniker_Release(enumMoniker); 01907 } 01908 01909 /* only one moniker, then just return it */ 01910 if (This->tabLastIndex == 1) 01911 { 01912 *ppMoniker = This->tabMoniker[0]; 01913 IMoniker_AddRef(*ppMoniker); 01914 IMoniker_Release(&This->IMoniker_iface); 01915 } 01916 else 01917 *ppMoniker = &This->IMoniker_iface; 01918 01919 return S_OK; 01920 } 01921 01922 /****************************************************************************** 01923 * CreateGenericComposite [OLE32.@] 01924 ******************************************************************************/ 01925 HRESULT WINAPI 01926 CreateGenericComposite(IMoniker *pmkFirst, IMoniker *pmkRest, IMoniker **ppmkComposite) 01927 { 01928 IMoniker* moniker = 0; 01929 HRESULT hr = S_OK; 01930 01931 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite); 01932 01933 if (ppmkComposite==NULL) 01934 return E_POINTER; 01935 01936 *ppmkComposite=0; 01937 01938 if (pmkFirst==NULL && pmkRest!=NULL){ 01939 01940 *ppmkComposite=pmkRest; 01941 return S_OK; 01942 } 01943 else if (pmkFirst!=NULL && pmkRest==NULL){ 01944 *ppmkComposite=pmkFirst; 01945 return S_OK; 01946 } 01947 else if (pmkFirst==NULL && pmkRest==NULL) 01948 return S_OK; 01949 01950 hr = CompositeMonikerImpl_Construct(&moniker,pmkFirst,pmkRest); 01951 01952 if (FAILED(hr)) 01953 return hr; 01954 01955 hr = IMoniker_QueryInterface(moniker,&IID_IMoniker,(void**)ppmkComposite); 01956 IMoniker_Release(moniker); 01957 01958 return hr; 01959 } 01960 01961 /****************************************************************************** 01962 * MonikerCommonPrefixWith [OLE32.@] 01963 ******************************************************************************/ 01964 HRESULT WINAPI 01965 MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon) 01966 { 01967 FIXME("(),stub!\n"); 01968 return E_NOTIMPL; 01969 } 01970 01971 static HRESULT WINAPI CompositeMonikerCF_QueryInterface(LPCLASSFACTORY iface, 01972 REFIID riid, LPVOID *ppv) 01973 { 01974 *ppv = NULL; 01975 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) 01976 { 01977 *ppv = iface; 01978 IUnknown_AddRef(iface); 01979 return S_OK; 01980 } 01981 return E_NOINTERFACE; 01982 } 01983 01984 static ULONG WINAPI CompositeMonikerCF_AddRef(LPCLASSFACTORY iface) 01985 { 01986 return 2; /* non-heap based object */ 01987 } 01988 01989 static ULONG WINAPI CompositeMonikerCF_Release(LPCLASSFACTORY iface) 01990 { 01991 return 1; /* non-heap based object */ 01992 } 01993 01994 static HRESULT WINAPI CompositeMonikerCF_CreateInstance(LPCLASSFACTORY iface, 01995 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) 01996 { 01997 IMoniker* pMoniker; 01998 HRESULT hr; 01999 02000 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv); 02001 02002 *ppv = NULL; 02003 02004 if (pUnk) 02005 return CLASS_E_NOAGGREGATION; 02006 02007 hr = CompositeMonikerImpl_Construct(&pMoniker, NULL, NULL); 02008 02009 if (SUCCEEDED(hr)) 02010 { 02011 hr = IMoniker_QueryInterface(pMoniker, riid, ppv); 02012 IMoniker_Release(pMoniker); 02013 } 02014 02015 return hr; 02016 } 02017 02018 static HRESULT WINAPI CompositeMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) 02019 { 02020 FIXME("(%d), stub!\n",fLock); 02021 return S_OK; 02022 } 02023 02024 static const IClassFactoryVtbl CompositeMonikerCFVtbl = 02025 { 02026 CompositeMonikerCF_QueryInterface, 02027 CompositeMonikerCF_AddRef, 02028 CompositeMonikerCF_Release, 02029 CompositeMonikerCF_CreateInstance, 02030 CompositeMonikerCF_LockServer 02031 }; 02032 static const IClassFactoryVtbl *CompositeMonikerCF = &CompositeMonikerCFVtbl; 02033 02034 HRESULT CompositeMonikerCF_Create(REFIID riid, LPVOID *ppv) 02035 { 02036 return IClassFactory_QueryInterface((IClassFactory *)&CompositeMonikerCF, riid, ppv); 02037 } Generated on Sun May 27 2012 04:25:35 for ReactOS by
1.7.6.1
|