Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmoniker.c
Go to the documentation of this file.
00001 /* 00002 * Monikers 00003 * 00004 * Copyright 1998 Marcus Meissner 00005 * Copyright 1999 Noomen Hamza 00006 * Copyright 2005 Robert Shearman (for CodeWeavers) 00007 * Copyright 2007 Robert Shearman 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 * This library is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00022 */ 00023 00024 #include "config.h" 00025 #include "wine/port.h" 00026 00027 #include <stdarg.h> 00028 #include <string.h> 00029 00030 #define COBJMACROS 00031 00032 #include "winerror.h" 00033 #include "windef.h" 00034 #include "winbase.h" 00035 #include "winuser.h" 00036 #include "wtypes.h" 00037 #include "ole2.h" 00038 00039 #include "wine/list.h" 00040 #include "wine/debug.h" 00041 #include "wine/unicode.h" 00042 #include "wine/exception.h" 00043 00044 #include "compobj_private.h" 00045 #include "moniker.h" 00046 #include "irot.h" 00047 00048 WINE_DEFAULT_DEBUG_CHANNEL(ole); 00049 00050 /* see MSDN docs for IROTData::GetComparisonData, which states what this 00051 * constant is 00052 */ 00053 #define MAX_COMPARISON_DATA 2048 00054 00055 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr) 00056 { 00057 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode); 00058 } 00059 00060 /* define the structure of the running object table elements */ 00061 struct rot_entry 00062 { 00063 struct list entry; 00064 InterfaceData* object; /* marshaled running object*/ 00065 MonikerComparisonData* moniker_data; /* moniker comparison data that identifies this object */ 00066 DWORD cookie; /* cookie identifying this object */ 00067 FILETIME last_modified; 00068 IrotContextHandle ctxt_handle; 00069 }; 00070 00071 /* define the RunningObjectTableImpl structure */ 00072 typedef struct RunningObjectTableImpl 00073 { 00074 IRunningObjectTable IRunningObjectTable_iface; 00075 LONG ref; 00076 00077 struct list rot; /* list of ROT entries */ 00078 CRITICAL_SECTION lock; 00079 } RunningObjectTableImpl; 00080 00081 static RunningObjectTableImpl* runningObjectTableInstance = NULL; 00082 static IrotHandle irot_handle; 00083 00084 /* define the EnumMonikerImpl structure */ 00085 typedef struct EnumMonikerImpl 00086 { 00087 IEnumMoniker IEnumMoniker_iface; 00088 LONG ref; 00089 00090 InterfaceList *moniker_list; 00091 ULONG pos; 00092 } EnumMonikerImpl; 00093 00094 static inline RunningObjectTableImpl *impl_from_IRunningObjectTable(IRunningObjectTable *iface) 00095 { 00096 return CONTAINING_RECORD(iface, RunningObjectTableImpl, IRunningObjectTable_iface); 00097 } 00098 00099 static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface) 00100 { 00101 return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface); 00102 } 00103 00104 /* IEnumMoniker Local functions*/ 00105 static HRESULT EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list, 00106 ULONG pos, IEnumMoniker **ppenumMoniker); 00107 00108 static IrotHandle get_irot_handle(void) 00109 { 00110 if (!irot_handle) 00111 { 00112 RPC_STATUS status; 00113 RPC_WSTR binding; 00114 IrotHandle new_handle; 00115 unsigned short ncacn_np[] = IROT_PROTSEQ; 00116 unsigned short endpoint[] = IROT_ENDPOINT; 00117 status = RpcStringBindingComposeW(NULL, ncacn_np, NULL, endpoint, NULL, &binding); 00118 if (status == RPC_S_OK) 00119 { 00120 status = RpcBindingFromStringBindingW(binding, &new_handle); 00121 RpcStringFreeW(&binding); 00122 } 00123 if (status != RPC_S_OK) 00124 return NULL; 00125 if (InterlockedCompareExchangePointer(&irot_handle, new_handle, NULL)) 00126 /* another thread beat us to it */ 00127 RpcBindingFree(&new_handle); 00128 } 00129 return irot_handle; 00130 } 00131 00132 static BOOL start_rpcss(void) 00133 { 00134 PROCESS_INFORMATION pi; 00135 STARTUPINFOW si; 00136 WCHAR cmd[MAX_PATH]; 00137 static const WCHAR rpcss[] = {'\\','r','p','c','s','s','.','e','x','e',0}; 00138 BOOL rslt; 00139 void *redir; 00140 00141 TRACE("\n"); 00142 00143 ZeroMemory(&si, sizeof(STARTUPINFOA)); 00144 si.cb = sizeof(STARTUPINFOA); 00145 GetSystemDirectoryW( cmd, MAX_PATH - sizeof(rpcss)/sizeof(WCHAR) ); 00146 strcatW( cmd, rpcss ); 00147 00148 Wow64DisableWow64FsRedirection( &redir ); 00149 rslt = CreateProcessW( cmd, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ); 00150 Wow64RevertWow64FsRedirection( redir ); 00151 00152 if (rslt) 00153 { 00154 CloseHandle(pi.hProcess); 00155 CloseHandle(pi.hThread); 00156 Sleep(100); 00157 } 00158 00159 return rslt; 00160 } 00161 00162 static HRESULT create_stream_on_mip_ro(const InterfaceData *mip, IStream **stream) 00163 { 00164 HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData); 00165 void *pv = GlobalLock(hglobal); 00166 memcpy(pv, mip->abData, mip->ulCntData); 00167 GlobalUnlock(hglobal); 00168 return CreateStreamOnHGlobal(hglobal, TRUE, stream); 00169 } 00170 00171 static void rot_entry_delete(struct rot_entry *rot_entry) 00172 { 00173 if (rot_entry->cookie) 00174 { 00175 InterfaceData *object = NULL; 00176 InterfaceData *moniker = NULL; 00177 __TRY 00178 { 00179 IrotRevoke(get_irot_handle(), rot_entry->cookie, 00180 &rot_entry->ctxt_handle, &object, &moniker); 00181 } 00182 __EXCEPT(rpc_filter) 00183 { 00184 } 00185 __ENDTRY 00186 MIDL_user_free(object); 00187 if (moniker) 00188 { 00189 IStream *stream; 00190 HRESULT hr; 00191 hr = create_stream_on_mip_ro(moniker, &stream); 00192 if (hr == S_OK) 00193 { 00194 CoReleaseMarshalData(stream); 00195 IUnknown_Release(stream); 00196 } 00197 } 00198 MIDL_user_free(moniker); 00199 } 00200 if (rot_entry->object) 00201 { 00202 IStream *stream; 00203 HRESULT hr; 00204 hr = create_stream_on_mip_ro(rot_entry->object, &stream); 00205 if (hr == S_OK) 00206 { 00207 CoReleaseMarshalData(stream); 00208 IUnknown_Release(stream); 00209 } 00210 } 00211 HeapFree(GetProcessHeap(), 0, rot_entry->object); 00212 HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data); 00213 HeapFree(GetProcessHeap(), 0, rot_entry); 00214 } 00215 00216 /* moniker_data must be freed with HeapFree when no longer in use */ 00217 static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MonikerComparisonData **moniker_data) 00218 { 00219 HRESULT hr; 00220 IROTData *pROTData = NULL; 00221 hr = IMoniker_QueryInterface(pMoniker, &IID_IROTData, (void *)&pROTData); 00222 if (SUCCEEDED(hr)) 00223 { 00224 ULONG size = MAX_COMPARISON_DATA; 00225 *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[size])); 00226 if (!*moniker_data) 00227 { 00228 IROTData_Release(pROTData); 00229 return E_OUTOFMEMORY; 00230 } 00231 hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size); 00232 IROTData_Release(pROTData); 00233 if (hr != S_OK) 00234 { 00235 ERR("Failed to copy comparison data into buffer, hr = 0x%08x\n", hr); 00236 HeapFree(GetProcessHeap(), 0, *moniker_data); 00237 return hr; 00238 } 00239 (*moniker_data)->ulCntData = size; 00240 } 00241 else 00242 { 00243 IBindCtx *pbc; 00244 LPOLESTR pszDisplayName; 00245 CLSID clsid; 00246 int len; 00247 00248 TRACE("generating comparison data from display name\n"); 00249 00250 hr = CreateBindCtx(0, &pbc); 00251 if (FAILED(hr)) 00252 return hr; 00253 hr = IMoniker_GetDisplayName(pMoniker, pbc, NULL, &pszDisplayName); 00254 IBindCtx_Release(pbc); 00255 if (FAILED(hr)) 00256 return hr; 00257 hr = IMoniker_GetClassID(pMoniker, &clsid); 00258 if (FAILED(hr)) 00259 { 00260 CoTaskMemFree(pszDisplayName); 00261 return hr; 00262 } 00263 00264 len = strlenW(pszDisplayName); 00265 *moniker_data = HeapAlloc(GetProcessHeap(), 0, 00266 FIELD_OFFSET(MonikerComparisonData, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)])); 00267 if (!*moniker_data) 00268 { 00269 CoTaskMemFree(pszDisplayName); 00270 return E_OUTOFMEMORY; 00271 } 00272 (*moniker_data)->ulCntData = sizeof(CLSID) + (len+1)*sizeof(WCHAR); 00273 00274 memcpy(&(*moniker_data)->abData[0], &clsid, sizeof(clsid)); 00275 memcpy(&(*moniker_data)->abData[sizeof(clsid)], pszDisplayName, (len+1)*sizeof(WCHAR)); 00276 CoTaskMemFree(pszDisplayName); 00277 } 00278 return S_OK; 00279 } 00280 00281 static HRESULT reduce_moniker(IMoniker *pmk, IBindCtx *pbc, IMoniker **pmkReduced) 00282 { 00283 IBindCtx *pbcNew = NULL; 00284 HRESULT hr; 00285 if (!pbc) 00286 { 00287 hr = CreateBindCtx(0, &pbcNew); 00288 if (FAILED(hr)) 00289 return hr; 00290 pbc = pbcNew; 00291 } 00292 hr = IMoniker_Reduce(pmk, pbc, MKRREDUCE_ALL, NULL, pmkReduced); 00293 if (FAILED(hr)) 00294 ERR("reducing moniker failed with error 0x%08x\n", hr); 00295 if (pbcNew) IBindCtx_Release(pbcNew); 00296 return hr; 00297 } 00298 00299 /*********************************************************************** 00300 * RunningObjectTable_QueryInterface 00301 */ 00302 static HRESULT WINAPI 00303 RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface, 00304 REFIID riid,void** ppvObject) 00305 { 00306 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 00307 00308 TRACE("(%p,%p,%p)\n",This,riid,ppvObject); 00309 00310 /* validate arguments */ 00311 00312 if (ppvObject==0) 00313 return E_INVALIDARG; 00314 00315 *ppvObject = 0; 00316 00317 if (IsEqualIID(&IID_IUnknown, riid) || 00318 IsEqualIID(&IID_IRunningObjectTable, riid)) 00319 *ppvObject = This; 00320 00321 if ((*ppvObject)==0) 00322 return E_NOINTERFACE; 00323 00324 IRunningObjectTable_AddRef(iface); 00325 00326 return S_OK; 00327 } 00328 00329 /*********************************************************************** 00330 * RunningObjectTable_AddRef 00331 */ 00332 static ULONG WINAPI 00333 RunningObjectTableImpl_AddRef(IRunningObjectTable* iface) 00334 { 00335 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 00336 00337 TRACE("(%p)\n",This); 00338 00339 return InterlockedIncrement(&This->ref); 00340 } 00341 00342 /*********************************************************************** 00343 * RunningObjectTable_Destroy 00344 */ 00345 static HRESULT 00346 RunningObjectTableImpl_Destroy(void) 00347 { 00348 struct list *cursor, *cursor2; 00349 IrotHandle old_handle; 00350 00351 TRACE("()\n"); 00352 00353 if (runningObjectTableInstance==NULL) 00354 return E_INVALIDARG; 00355 00356 /* free the ROT table memory */ 00357 LIST_FOR_EACH_SAFE(cursor, cursor2, &runningObjectTableInstance->rot) 00358 { 00359 struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry); 00360 list_remove(&rot_entry->entry); 00361 rot_entry_delete(rot_entry); 00362 } 00363 00364 DEBUG_CLEAR_CRITSEC_NAME(&runningObjectTableInstance->lock); 00365 DeleteCriticalSection(&runningObjectTableInstance->lock); 00366 00367 /* free the ROT structure memory */ 00368 HeapFree(GetProcessHeap(),0,runningObjectTableInstance); 00369 runningObjectTableInstance = NULL; 00370 00371 old_handle = irot_handle; 00372 irot_handle = NULL; 00373 if (old_handle) 00374 RpcBindingFree(&old_handle); 00375 00376 return S_OK; 00377 } 00378 00379 /*********************************************************************** 00380 * RunningObjectTable_Release 00381 */ 00382 static ULONG WINAPI 00383 RunningObjectTableImpl_Release(IRunningObjectTable* iface) 00384 { 00385 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 00386 ULONG ref; 00387 00388 TRACE("(%p)\n",This); 00389 00390 ref = InterlockedDecrement(&This->ref); 00391 00392 /* uninitialize ROT structure if there's no more references to it */ 00393 if (ref == 0) 00394 { 00395 struct list *cursor, *cursor2; 00396 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->rot) 00397 { 00398 struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry); 00399 list_remove(&rot_entry->entry); 00400 rot_entry_delete(rot_entry); 00401 } 00402 /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only 00403 * when RunningObjectTableImpl_UnInitialize function is called 00404 */ 00405 } 00406 00407 return ref; 00408 } 00409 00410 /*********************************************************************** 00411 * RunningObjectTable_Register 00412 * 00413 * PARAMS 00414 * grfFlags [in] Registration options 00415 * punkObject [in] the object being registered 00416 * pmkObjectName [in] the moniker of the object being registered 00417 * pdwRegister [out] the value identifying the registration 00418 */ 00419 static HRESULT WINAPI 00420 RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags, 00421 IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister) 00422 { 00423 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 00424 struct rot_entry *rot_entry; 00425 HRESULT hr = S_OK; 00426 IStream *pStream = NULL; 00427 DWORD mshlflags; 00428 IBindCtx *pbc; 00429 InterfaceData *moniker = NULL; 00430 00431 TRACE("(%p,%d,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister); 00432 00433 if (grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT)) 00434 { 00435 ERR("Invalid grfFlags: 0x%08x\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT)); 00436 return E_INVALIDARG; 00437 } 00438 00439 if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL) 00440 return E_INVALIDARG; 00441 00442 rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry)); 00443 if (!rot_entry) 00444 return E_OUTOFMEMORY; 00445 00446 /* marshal object */ 00447 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 00448 if (hr != S_OK) 00449 { 00450 rot_entry_delete(rot_entry); 00451 return hr; 00452 } 00453 mshlflags = (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK; 00454 hr = CoMarshalInterface(pStream, &IID_IUnknown, punkObject, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, mshlflags); 00455 /* FIXME: a cleaner way would be to create an IStream class that writes 00456 * directly to an MInterfacePointer */ 00457 if (hr == S_OK) 00458 { 00459 HGLOBAL hglobal; 00460 hr = GetHGlobalFromStream(pStream, &hglobal); 00461 if (hr == S_OK) 00462 { 00463 SIZE_T size = GlobalSize(hglobal); 00464 const void *pv = GlobalLock(hglobal); 00465 rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); 00466 rot_entry->object->ulCntData = size; 00467 memcpy(rot_entry->object->abData, pv, size); 00468 GlobalUnlock(hglobal); 00469 } 00470 } 00471 IStream_Release(pStream); 00472 if (hr != S_OK) 00473 { 00474 rot_entry_delete(rot_entry); 00475 return hr; 00476 } 00477 00478 hr = CreateBindCtx(0, &pbc); 00479 if (FAILED(hr)) 00480 { 00481 rot_entry_delete(rot_entry); 00482 return hr; 00483 } 00484 00485 hr = reduce_moniker(pmkObjectName, pbc, &pmkObjectName); 00486 if (FAILED(hr)) 00487 { 00488 rot_entry_delete(rot_entry); 00489 IBindCtx_Release(pbc); 00490 return hr; 00491 } 00492 00493 hr = IMoniker_GetTimeOfLastChange(pmkObjectName, pbc, NULL, 00494 &rot_entry->last_modified); 00495 IBindCtx_Release(pbc); 00496 if (FAILED(hr)) 00497 { 00498 CoFileTimeNow(&rot_entry->last_modified); 00499 hr = S_OK; 00500 } 00501 00502 hr = get_moniker_comparison_data(pmkObjectName, 00503 &rot_entry->moniker_data); 00504 if (hr != S_OK) 00505 { 00506 rot_entry_delete(rot_entry); 00507 IMoniker_Release(pmkObjectName); 00508 return hr; 00509 } 00510 00511 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 00512 if (hr != S_OK) 00513 { 00514 rot_entry_delete(rot_entry); 00515 IMoniker_Release(pmkObjectName); 00516 return hr; 00517 } 00518 /* marshal moniker */ 00519 hr = CoMarshalInterface(pStream, &IID_IMoniker, (IUnknown *)pmkObjectName, 00520 MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG); 00521 /* FIXME: a cleaner way would be to create an IStream class that writes 00522 * directly to an MInterfacePointer */ 00523 if (hr == S_OK) 00524 { 00525 HGLOBAL hglobal; 00526 hr = GetHGlobalFromStream(pStream, &hglobal); 00527 if (hr == S_OK) 00528 { 00529 SIZE_T size = GlobalSize(hglobal); 00530 const void *pv = GlobalLock(hglobal); 00531 moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[size])); 00532 moniker->ulCntData = size; 00533 memcpy(moniker->abData, pv, size); 00534 GlobalUnlock(hglobal); 00535 } 00536 } 00537 IStream_Release(pStream); 00538 IMoniker_Release(pmkObjectName); 00539 if (hr != S_OK) 00540 { 00541 HeapFree(GetProcessHeap(), 0, moniker); 00542 rot_entry_delete(rot_entry); 00543 return hr; 00544 } 00545 00546 00547 while (TRUE) 00548 { 00549 __TRY 00550 { 00551 hr = IrotRegister(get_irot_handle(), rot_entry->moniker_data, 00552 rot_entry->object, moniker, 00553 &rot_entry->last_modified, grfFlags, 00554 &rot_entry->cookie, &rot_entry->ctxt_handle); 00555 } 00556 __EXCEPT(rpc_filter) 00557 { 00558 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 00559 } 00560 __ENDTRY 00561 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 00562 { 00563 if (start_rpcss()) 00564 continue; 00565 } 00566 break; 00567 } 00568 HeapFree(GetProcessHeap(), 0, moniker); 00569 if (FAILED(hr)) 00570 { 00571 rot_entry_delete(rot_entry); 00572 return hr; 00573 } 00574 00575 /* gives a registration identifier to the registered object*/ 00576 *pdwRegister = rot_entry->cookie; 00577 00578 EnterCriticalSection(&This->lock); 00579 list_add_tail(&This->rot, &rot_entry->entry); 00580 LeaveCriticalSection(&This->lock); 00581 00582 return hr; 00583 } 00584 00585 /*********************************************************************** 00586 * RunningObjectTable_Revoke 00587 * 00588 * PARAMS 00589 * dwRegister [in] Value identifying registration to be revoked 00590 */ 00591 static HRESULT WINAPI 00592 RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister) 00593 { 00594 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 00595 struct rot_entry *rot_entry; 00596 00597 TRACE("(%p,%d)\n",This,dwRegister); 00598 00599 EnterCriticalSection(&This->lock); 00600 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) 00601 { 00602 if (rot_entry->cookie == dwRegister) 00603 { 00604 list_remove(&rot_entry->entry); 00605 LeaveCriticalSection(&This->lock); 00606 00607 rot_entry_delete(rot_entry); 00608 return S_OK; 00609 } 00610 } 00611 LeaveCriticalSection(&This->lock); 00612 00613 return E_INVALIDARG; 00614 } 00615 00616 /*********************************************************************** 00617 * RunningObjectTable_IsRunning 00618 * 00619 * PARAMS 00620 * pmkObjectName [in] moniker of the object whose status is desired 00621 */ 00622 static HRESULT WINAPI 00623 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName) 00624 { 00625 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 00626 MonikerComparisonData *moniker_data; 00627 HRESULT hr; 00628 const struct rot_entry *rot_entry; 00629 00630 TRACE("(%p,%p)\n",This,pmkObjectName); 00631 00632 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName); 00633 if (FAILED(hr)) 00634 return hr; 00635 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); 00636 IMoniker_Release(pmkObjectName); 00637 if (hr != S_OK) 00638 return hr; 00639 00640 hr = S_FALSE; 00641 EnterCriticalSection(&This->lock); 00642 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry) 00643 { 00644 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && 00645 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData)) 00646 { 00647 hr = S_OK; 00648 break; 00649 } 00650 } 00651 LeaveCriticalSection(&This->lock); 00652 00653 if (hr == S_FALSE) 00654 { 00655 while (TRUE) 00656 { 00657 __TRY 00658 { 00659 hr = IrotIsRunning(get_irot_handle(), moniker_data); 00660 } 00661 __EXCEPT(rpc_filter) 00662 { 00663 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 00664 } 00665 __ENDTRY 00666 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 00667 { 00668 if (start_rpcss()) 00669 continue; 00670 } 00671 break; 00672 } 00673 } 00674 00675 HeapFree(GetProcessHeap(), 0, moniker_data); 00676 00677 return hr; 00678 } 00679 00680 /*********************************************************************** 00681 * RunningObjectTable_GetObject 00682 * 00683 * PARAMS 00684 * pmkObjectName [in] Pointer to the moniker on the object 00685 * ppunkObject [out] variable that receives the IUnknown interface pointer 00686 */ 00687 static HRESULT WINAPI 00688 RunningObjectTableImpl_GetObject( IRunningObjectTable* iface, 00689 IMoniker *pmkObjectName, IUnknown **ppunkObject) 00690 { 00691 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 00692 MonikerComparisonData *moniker_data; 00693 InterfaceData *object = NULL; 00694 IrotCookie cookie; 00695 HRESULT hr; 00696 struct rot_entry *rot_entry; 00697 00698 TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject); 00699 00700 if (ppunkObject == NULL) 00701 return E_POINTER; 00702 00703 *ppunkObject = NULL; 00704 00705 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName); 00706 if (FAILED(hr)) 00707 return hr; 00708 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); 00709 IMoniker_Release(pmkObjectName); 00710 if (hr != S_OK) 00711 return hr; 00712 00713 EnterCriticalSection(&This->lock); 00714 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) 00715 { 00716 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && 00717 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData)) 00718 { 00719 IStream *pStream; 00720 hr = create_stream_on_mip_ro(rot_entry->object, &pStream); 00721 if (hr == S_OK) 00722 { 00723 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject); 00724 IStream_Release(pStream); 00725 } 00726 00727 LeaveCriticalSection(&This->lock); 00728 HeapFree(GetProcessHeap(), 0, moniker_data); 00729 00730 return hr; 00731 } 00732 } 00733 LeaveCriticalSection(&This->lock); 00734 00735 TRACE("moniker unavailable locally, calling SCM\n"); 00736 00737 while (TRUE) 00738 { 00739 __TRY 00740 { 00741 hr = IrotGetObject(get_irot_handle(), moniker_data, &object, &cookie); 00742 } 00743 __EXCEPT(rpc_filter) 00744 { 00745 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 00746 } 00747 __ENDTRY 00748 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 00749 { 00750 if (start_rpcss()) 00751 continue; 00752 } 00753 break; 00754 } 00755 00756 if (SUCCEEDED(hr)) 00757 { 00758 IStream *pStream; 00759 hr = create_stream_on_mip_ro(object, &pStream); 00760 if (hr == S_OK) 00761 { 00762 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject); 00763 IStream_Release(pStream); 00764 } 00765 } 00766 else 00767 WARN("Moniker unavailable, IrotGetObject returned 0x%08x\n", hr); 00768 00769 HeapFree(GetProcessHeap(), 0, moniker_data); 00770 00771 return hr; 00772 } 00773 00774 /*********************************************************************** 00775 * RunningObjectTable_NoteChangeTime 00776 * 00777 * PARAMS 00778 * dwRegister [in] Value identifying registration being updated 00779 * pfiletime [in] Pointer to structure containing object's last change time 00780 */ 00781 static HRESULT WINAPI 00782 RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, 00783 DWORD dwRegister, FILETIME *pfiletime) 00784 { 00785 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 00786 struct rot_entry *rot_entry; 00787 HRESULT hr = E_INVALIDARG; 00788 00789 TRACE("(%p,%d,%p)\n",This,dwRegister,pfiletime); 00790 00791 EnterCriticalSection(&This->lock); 00792 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) 00793 { 00794 if (rot_entry->cookie == dwRegister) 00795 { 00796 rot_entry->last_modified = *pfiletime; 00797 LeaveCriticalSection(&This->lock); 00798 00799 while (TRUE) 00800 { 00801 __TRY 00802 { 00803 hr = IrotNoteChangeTime(get_irot_handle(), dwRegister, pfiletime); 00804 } 00805 __EXCEPT(rpc_filter) 00806 { 00807 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 00808 } 00809 __ENDTRY 00810 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 00811 { 00812 if (start_rpcss()) 00813 continue; 00814 } 00815 break; 00816 } 00817 00818 goto done; 00819 } 00820 } 00821 LeaveCriticalSection(&This->lock); 00822 00823 done: 00824 TRACE("-- 0x08%x\n", hr); 00825 return hr; 00826 } 00827 00828 /*********************************************************************** 00829 * RunningObjectTable_GetTimeOfLastChange 00830 * 00831 * PARAMS 00832 * pmkObjectName [in] moniker of the object whose status is desired 00833 * pfiletime [out] structure that receives object's last change time 00834 */ 00835 static HRESULT WINAPI 00836 RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, 00837 IMoniker *pmkObjectName, FILETIME *pfiletime) 00838 { 00839 HRESULT hr = MK_E_UNAVAILABLE; 00840 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 00841 MonikerComparisonData *moniker_data; 00842 const struct rot_entry *rot_entry; 00843 00844 TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime); 00845 00846 if (pmkObjectName==NULL || pfiletime==NULL) 00847 return E_INVALIDARG; 00848 00849 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName); 00850 if (FAILED(hr)) 00851 return hr; 00852 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); 00853 IMoniker_Release(pmkObjectName); 00854 if (hr != S_OK) 00855 return hr; 00856 00857 hr = MK_E_UNAVAILABLE; 00858 00859 EnterCriticalSection(&This->lock); 00860 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry) 00861 { 00862 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && 00863 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData)) 00864 { 00865 *pfiletime = rot_entry->last_modified; 00866 hr = S_OK; 00867 break; 00868 } 00869 } 00870 LeaveCriticalSection(&This->lock); 00871 00872 if (hr != S_OK) 00873 { 00874 while (TRUE) 00875 { 00876 __TRY 00877 { 00878 hr = IrotGetTimeOfLastChange(get_irot_handle(), moniker_data, pfiletime); 00879 } 00880 __EXCEPT(rpc_filter) 00881 { 00882 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 00883 } 00884 __ENDTRY 00885 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 00886 { 00887 if (start_rpcss()) 00888 continue; 00889 } 00890 break; 00891 } 00892 } 00893 00894 HeapFree(GetProcessHeap(), 0, moniker_data); 00895 00896 TRACE("-- 0x%08x\n", hr); 00897 return hr; 00898 } 00899 00900 /*********************************************************************** 00901 * RunningObjectTable_EnumRunning 00902 * 00903 * PARAMS 00904 * ppenumMoniker [out] receives the IEnumMoniker interface pointer 00905 */ 00906 static HRESULT WINAPI 00907 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, 00908 IEnumMoniker **ppenumMoniker) 00909 { 00910 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 00911 InterfaceList *interface_list = NULL; 00912 HRESULT hr; 00913 00914 TRACE("(%p, %p)\n", This, ppenumMoniker); 00915 00916 *ppenumMoniker = NULL; 00917 00918 while (TRUE) 00919 { 00920 __TRY 00921 { 00922 hr = IrotEnumRunning(get_irot_handle(), &interface_list); 00923 } 00924 __EXCEPT(rpc_filter) 00925 { 00926 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 00927 } 00928 __ENDTRY 00929 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 00930 { 00931 if (start_rpcss()) 00932 continue; 00933 } 00934 break; 00935 } 00936 00937 if (SUCCEEDED(hr)) 00938 hr = EnumMonikerImpl_CreateEnumROTMoniker(interface_list, 00939 0, ppenumMoniker); 00940 00941 return hr; 00942 } 00943 00944 /* Virtual function table for the IRunningObjectTable class. */ 00945 static const IRunningObjectTableVtbl VT_RunningObjectTableImpl = 00946 { 00947 RunningObjectTableImpl_QueryInterface, 00948 RunningObjectTableImpl_AddRef, 00949 RunningObjectTableImpl_Release, 00950 RunningObjectTableImpl_Register, 00951 RunningObjectTableImpl_Revoke, 00952 RunningObjectTableImpl_IsRunning, 00953 RunningObjectTableImpl_GetObject, 00954 RunningObjectTableImpl_NoteChangeTime, 00955 RunningObjectTableImpl_GetTimeOfLastChange, 00956 RunningObjectTableImpl_EnumRunning 00957 }; 00958 00959 /*********************************************************************** 00960 * RunningObjectTable_Initialize 00961 */ 00962 HRESULT WINAPI RunningObjectTableImpl_Initialize(void) 00963 { 00964 TRACE("\n"); 00965 00966 /* create the unique instance of the RunningObjectTableImpl structure */ 00967 runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl)); 00968 00969 if (!runningObjectTableInstance) 00970 return E_OUTOFMEMORY; 00971 00972 /* initialize the virtual table function */ 00973 runningObjectTableInstance->IRunningObjectTable_iface.lpVtbl = &VT_RunningObjectTableImpl; 00974 00975 /* the initial reference is set to "1" so that it isn't destroyed after its 00976 * first use until the process is destroyed, as the running object table is 00977 * a process-wide cache of a global table */ 00978 runningObjectTableInstance->ref = 1; 00979 00980 list_init(&runningObjectTableInstance->rot); 00981 InitializeCriticalSection(&runningObjectTableInstance->lock); 00982 DEBUG_SET_CRITSEC_NAME(&runningObjectTableInstance->lock, "RunningObjectTableImpl.lock"); 00983 00984 return S_OK; 00985 } 00986 00987 /*********************************************************************** 00988 * RunningObjectTable_UnInitialize 00989 */ 00990 HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void) 00991 { 00992 TRACE("\n"); 00993 00994 if (runningObjectTableInstance==NULL) 00995 return E_POINTER; 00996 00997 RunningObjectTableImpl_Release(&runningObjectTableInstance->IRunningObjectTable_iface); 00998 00999 RunningObjectTableImpl_Destroy(); 01000 01001 return S_OK; 01002 } 01003 01004 /*********************************************************************** 01005 * GetRunningObjectTable (OLE32.@) 01006 * 01007 * Retrieves the global running object table. 01008 * 01009 * PARAMS 01010 * reserved [I] Reserved. Set to 0. 01011 * pprot [O] Address that receives the pointer to the running object table. 01012 * 01013 * RETURNS 01014 * Success: S_OK. 01015 * Failure: Any HRESULT code. 01016 */ 01017 HRESULT WINAPI 01018 GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot) 01019 { 01020 IID riid=IID_IRunningObjectTable; 01021 HRESULT res; 01022 01023 TRACE("()\n"); 01024 01025 if (reserved!=0) 01026 return E_UNEXPECTED; 01027 01028 if(runningObjectTableInstance==NULL) 01029 return CO_E_NOTINITIALIZED; 01030 01031 res = IRunningObjectTable_QueryInterface(&runningObjectTableInstance->IRunningObjectTable_iface, 01032 &riid,(void**)pprot); 01033 01034 return res; 01035 } 01036 01037 static HRESULT get_moniker_for_progid_display_name(LPBC pbc, 01038 LPCOLESTR szDisplayName, 01039 LPDWORD pchEaten, 01040 LPMONIKER *ppmk) 01041 { 01042 CLSID clsid; 01043 HRESULT hr; 01044 LPWSTR progid; 01045 LPCWSTR start = szDisplayName; 01046 LPCWSTR end; 01047 int len; 01048 IMoniker *class_moniker; 01049 01050 if (*start == '@') 01051 start++; 01052 01053 /* find end delimiter */ 01054 for (end = start; *end; end++) 01055 if (*end == ':') 01056 break; 01057 01058 len = end - start; 01059 01060 /* must start with '@' or have a ':' somewhere and mustn't be one character 01061 * long (since that looks like an absolute path) */ 01062 if (((start == szDisplayName) && (*end == '\0')) || (len <= 1)) 01063 return MK_E_SYNTAX; 01064 01065 progid = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); 01066 if (progid) 01067 { 01068 memcpy(progid, start, len * sizeof(WCHAR)); 01069 progid[len] = '\0'; 01070 } 01071 hr = CLSIDFromProgID(progid, &clsid); 01072 HeapFree(GetProcessHeap(), 0, progid); 01073 if (FAILED(hr)) 01074 return MK_E_SYNTAX; 01075 01076 hr = CreateClassMoniker(&clsid, &class_moniker); 01077 if (SUCCEEDED(hr)) 01078 { 01079 IParseDisplayName *pdn; 01080 hr = IMoniker_BindToObject(class_moniker, pbc, NULL, 01081 &IID_IParseDisplayName, (void **)&pdn); 01082 /* fallback to using IClassFactory to get IParseDisplayName - 01083 * adsldp.dll depends on this */ 01084 if (FAILED(hr)) 01085 { 01086 IClassFactory *pcf; 01087 hr = IMoniker_BindToObject(class_moniker, pbc, NULL, 01088 &IID_IClassFactory, (void **)&pcf); 01089 if (SUCCEEDED(hr)) 01090 { 01091 hr = IClassFactory_CreateInstance(pcf, NULL, 01092 &IID_IParseDisplayName, 01093 (void **)&pdn); 01094 IClassFactory_Release(pcf); 01095 } 01096 } 01097 IMoniker_Release(class_moniker); 01098 if (SUCCEEDED(hr)) 01099 { 01100 hr = IParseDisplayName_ParseDisplayName(pdn, pbc, 01101 (LPOLESTR)szDisplayName, 01102 pchEaten, ppmk); 01103 IParseDisplayName_Release(pdn); 01104 } 01105 } 01106 return hr; 01107 } 01108 01109 /****************************************************************************** 01110 * MkParseDisplayName [OLE32.@] 01111 */ 01112 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName, 01113 LPDWORD pchEaten, LPMONIKER *ppmk) 01114 { 01115 HRESULT hr = MK_E_SYNTAX; 01116 static const WCHAR wszClsidColon[] = {'c','l','s','i','d',':'}; 01117 IMoniker *moniker; 01118 DWORD chEaten; 01119 01120 TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk); 01121 01122 if (!pbc || !IsValidInterface((LPUNKNOWN) pbc)) 01123 return E_INVALIDARG; 01124 01125 if (!szDisplayName || !*szDisplayName) 01126 return E_INVALIDARG; 01127 01128 if (!pchEaten || !ppmk) 01129 return E_INVALIDARG; 01130 01131 *pchEaten = 0; 01132 *ppmk = NULL; 01133 01134 if (!strncmpiW(szDisplayName, wszClsidColon, sizeof(wszClsidColon)/sizeof(wszClsidColon[0]))) 01135 { 01136 hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker); 01137 if (FAILED(hr) && (hr != MK_E_SYNTAX)) 01138 return hr; 01139 } 01140 else 01141 { 01142 hr = get_moniker_for_progid_display_name(pbc, szDisplayName, &chEaten, &moniker); 01143 if (FAILED(hr) && (hr != MK_E_SYNTAX)) 01144 return hr; 01145 } 01146 01147 if (FAILED(hr)) 01148 { 01149 hr = FileMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker); 01150 if (FAILED(hr) && (hr != MK_E_SYNTAX)) 01151 return hr; 01152 } 01153 01154 if (SUCCEEDED(hr)) 01155 { 01156 while (TRUE) 01157 { 01158 IMoniker *next_moniker; 01159 *pchEaten += chEaten; 01160 szDisplayName += chEaten; 01161 if (!*szDisplayName) 01162 { 01163 *ppmk = moniker; 01164 return S_OK; 01165 } 01166 chEaten = 0; 01167 hr = IMoniker_ParseDisplayName(moniker, pbc, NULL, 01168 (LPOLESTR)szDisplayName, &chEaten, 01169 &next_moniker); 01170 IMoniker_Release(moniker); 01171 if (FAILED(hr)) 01172 { 01173 *pchEaten = 0; 01174 break; 01175 } 01176 moniker = next_moniker; 01177 } 01178 } 01179 01180 return hr; 01181 } 01182 01183 /*********************************************************************** 01184 * GetClassFile (OLE32.@) 01185 * 01186 * Retrieves the class ID associated with the given filename. 01187 * 01188 * PARAMS 01189 * filePathName [I] Filename to retrieve the class ID for. 01190 * pclsid [O] Address that receives the class ID for the file. 01191 * 01192 * RETURNS 01193 * Success: S_OK. 01194 * Failure: Any HRESULT code. 01195 */ 01196 HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid) 01197 { 01198 IStorage *pstg=0; 01199 HRESULT res; 01200 int nbElm, length, i; 01201 LONG sizeProgId; 01202 LPOLESTR *pathDec=0,absFile=0,progId=0; 01203 LPWSTR extension; 01204 static const WCHAR bkslashW[] = {'\\',0}; 01205 static const WCHAR dotW[] = {'.',0}; 01206 01207 TRACE("%s, %p\n", debugstr_w(filePathName), pclsid); 01208 01209 /* if the file contain a storage object the return the CLSID written by IStorage_SetClass method*/ 01210 if((StgIsStorageFile(filePathName))==S_OK){ 01211 01212 res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg); 01213 01214 if (SUCCEEDED(res)) 01215 res=ReadClassStg(pstg,pclsid); 01216 01217 IStorage_Release(pstg); 01218 01219 return res; 01220 } 01221 /* If the file is not a storage object then attempt to match various bits in the file against a 01222 pattern in the registry. This case is not frequently used, so I present only the pseudocode for 01223 this case. 01224 01225 for(i=0;i<nFileTypes;i++) 01226 01227 for(i=0;j<nPatternsForType;j++){ 01228 01229 PATTERN pat; 01230 HANDLE hFile; 01231 01232 pat=ReadPatternFromRegistry(i,j); 01233 hFile=CreateFileW(filePathName,,,,,,hFile); 01234 SetFilePosition(hFile,pat.offset); 01235 ReadFile(hFile,buf,pat.size,&r,NULL); 01236 if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){ 01237 01238 *pclsid=ReadCLSIDFromRegistry(i); 01239 return S_OK; 01240 } 01241 } 01242 */ 01243 01244 /* if the above strategies fail then search for the extension key in the registry */ 01245 01246 /* get the last element (absolute file) in the path name */ 01247 nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec); 01248 absFile=pathDec[nbElm-1]; 01249 01250 /* failed if the path represents a directory and not an absolute file name*/ 01251 if (!lstrcmpW(absFile, bkslashW)) 01252 return MK_E_INVALIDEXTENSION; 01253 01254 /* get the extension of the file */ 01255 extension = NULL; 01256 length=lstrlenW(absFile); 01257 for(i = length-1; (i >= 0) && *(extension = &absFile[i]) != '.'; i--) 01258 /* nothing */; 01259 01260 if (!extension || !lstrcmpW(extension, dotW)) 01261 return MK_E_INVALIDEXTENSION; 01262 01263 res=RegQueryValueW(HKEY_CLASSES_ROOT, extension, NULL, &sizeProgId); 01264 01265 /* get the progId associated to the extension */ 01266 progId = CoTaskMemAlloc(sizeProgId); 01267 res = RegQueryValueW(HKEY_CLASSES_ROOT, extension, progId, &sizeProgId); 01268 01269 if (res==ERROR_SUCCESS) 01270 /* return the clsid associated to the progId */ 01271 res= CLSIDFromProgID(progId,pclsid); 01272 01273 for(i=0; pathDec[i]!=NULL;i++) 01274 CoTaskMemFree(pathDec[i]); 01275 CoTaskMemFree(pathDec); 01276 01277 CoTaskMemFree(progId); 01278 01279 if (res==ERROR_SUCCESS) 01280 return res; 01281 01282 return MK_E_INVALIDEXTENSION; 01283 } 01284 01285 /*********************************************************************** 01286 * EnumMoniker_QueryInterface 01287 */ 01288 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject) 01289 { 01290 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01291 01292 TRACE("(%p,%p,%p)\n",This,riid,ppvObject); 01293 01294 /* validate arguments */ 01295 if (ppvObject == NULL) 01296 return E_INVALIDARG; 01297 01298 *ppvObject = NULL; 01299 01300 if (IsEqualIID(&IID_IUnknown, riid)) 01301 *ppvObject = This; 01302 else 01303 if (IsEqualIID(&IID_IEnumMoniker, riid)) 01304 *ppvObject = This; 01305 01306 if ((*ppvObject)==NULL) 01307 return E_NOINTERFACE; 01308 01309 IEnumMoniker_AddRef(iface); 01310 01311 return S_OK; 01312 } 01313 01314 /*********************************************************************** 01315 * EnumMoniker_AddRef 01316 */ 01317 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface) 01318 { 01319 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01320 01321 TRACE("(%p)\n",This); 01322 01323 return InterlockedIncrement(&This->ref); 01324 } 01325 01326 /*********************************************************************** 01327 * EnumMoniker_release 01328 */ 01329 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface) 01330 { 01331 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01332 ULONG ref; 01333 01334 TRACE("(%p)\n",This); 01335 01336 ref = InterlockedDecrement(&This->ref); 01337 01338 /* uninitialize rot structure if there's no more reference to it*/ 01339 if (ref == 0) 01340 { 01341 ULONG i; 01342 01343 TRACE("(%p) Deleting\n",This); 01344 01345 for (i = 0; i < This->moniker_list->size; i++) 01346 HeapFree(GetProcessHeap(), 0, This->moniker_list->interfaces[i]); 01347 HeapFree(GetProcessHeap(), 0, This->moniker_list); 01348 HeapFree(GetProcessHeap(), 0, This); 01349 } 01350 01351 return ref; 01352 } 01353 /*********************************************************************** 01354 * EnumMoniker_Next 01355 */ 01356 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched) 01357 { 01358 ULONG i; 01359 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01360 HRESULT hr = S_OK; 01361 01362 TRACE("(%p) TabCurrentPos %d Tablastindx %d\n", This, This->pos, This->moniker_list->size); 01363 01364 /* retrieve the requested number of moniker from the current position */ 01365 for(i = 0; (This->pos < This->moniker_list->size) && (i < celt); i++) 01366 { 01367 IStream *stream; 01368 hr = create_stream_on_mip_ro(This->moniker_list->interfaces[This->pos++], &stream); 01369 if (hr != S_OK) break; 01370 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]); 01371 IStream_Release(stream); 01372 if (hr != S_OK) break; 01373 } 01374 01375 if (pceltFetched != NULL) 01376 *pceltFetched= i; 01377 01378 if (hr != S_OK) 01379 return hr; 01380 01381 if (i == celt) 01382 return S_OK; 01383 else 01384 return S_FALSE; 01385 01386 } 01387 01388 /*********************************************************************** 01389 * EnumMoniker_Skip 01390 */ 01391 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt) 01392 { 01393 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01394 01395 TRACE("(%p)\n",This); 01396 01397 if (This->pos + celt >= This->moniker_list->size) 01398 return S_FALSE; 01399 01400 This->pos += celt; 01401 01402 return S_OK; 01403 } 01404 01405 /*********************************************************************** 01406 * EnumMoniker_Reset 01407 */ 01408 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface) 01409 { 01410 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01411 01412 This->pos = 0; /* set back to start of list */ 01413 01414 TRACE("(%p)\n",This); 01415 01416 return S_OK; 01417 } 01418 01419 /*********************************************************************** 01420 * EnumMoniker_Clone 01421 */ 01422 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum) 01423 { 01424 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 01425 InterfaceList *moniker_list; 01426 ULONG i; 01427 01428 TRACE("(%p)\n",This); 01429 01430 *ppenum = NULL; 01431 01432 moniker_list = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceList, interfaces[This->moniker_list->size])); 01433 if (!moniker_list) 01434 return E_OUTOFMEMORY; 01435 01436 moniker_list->size = This->moniker_list->size; 01437 for (i = 0; i < This->moniker_list->size; i++) 01438 { 01439 SIZE_T size = FIELD_OFFSET(InterfaceData, abData[This->moniker_list->interfaces[i]->ulCntData]); 01440 moniker_list->interfaces[i] = HeapAlloc(GetProcessHeap(), 0, size); 01441 if (!moniker_list->interfaces[i]) 01442 { 01443 ULONG end = i; 01444 for (i = 0; i < end; i++) 01445 HeapFree(GetProcessHeap(), 0, moniker_list->interfaces[i]); 01446 HeapFree(GetProcessHeap(), 0, moniker_list); 01447 return E_OUTOFMEMORY; 01448 } 01449 memcpy(moniker_list->interfaces[i], This->moniker_list->interfaces[i], size); 01450 } 01451 01452 /* copy the enum structure */ 01453 return EnumMonikerImpl_CreateEnumROTMoniker(moniker_list, This->pos, ppenum); 01454 } 01455 01456 /* Virtual function table for the IEnumMoniker class. */ 01457 static const IEnumMonikerVtbl VT_EnumMonikerImpl = 01458 { 01459 EnumMonikerImpl_QueryInterface, 01460 EnumMonikerImpl_AddRef, 01461 EnumMonikerImpl_Release, 01462 EnumMonikerImpl_Next, 01463 EnumMonikerImpl_Skip, 01464 EnumMonikerImpl_Reset, 01465 EnumMonikerImpl_Clone 01466 }; 01467 01468 /*********************************************************************** 01469 * EnumMonikerImpl_CreateEnumROTMoniker 01470 * Used by EnumRunning to create the structure and EnumClone 01471 * to copy the structure 01472 */ 01473 static HRESULT EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list, 01474 ULONG current_pos, 01475 IEnumMoniker **ppenumMoniker) 01476 { 01477 EnumMonikerImpl* This = NULL; 01478 01479 if (!ppenumMoniker) 01480 return E_INVALIDARG; 01481 01482 This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl)); 01483 if (!This) return E_OUTOFMEMORY; 01484 01485 TRACE("(%p)\n", This); 01486 01487 /* initialize the virtual table function */ 01488 This->IEnumMoniker_iface.lpVtbl = &VT_EnumMonikerImpl; 01489 01490 /* the initial reference is set to "1" */ 01491 This->ref = 1; /* set the ref count to one */ 01492 This->pos = current_pos; /* Set the list start posn */ 01493 This->moniker_list = moniker_list; 01494 01495 *ppenumMoniker = &This->IEnumMoniker_iface; 01496 01497 return S_OK; 01498 } 01499 01500 01501 /* Shared implementation of moniker marshaler based on saving and loading of 01502 * monikers */ 01503 01504 typedef struct MonikerMarshal 01505 { 01506 IUnknown IUnknown_iface; 01507 IMarshal IMarshal_iface; 01508 01509 LONG ref; 01510 IMoniker *moniker; 01511 } MonikerMarshal; 01512 01513 static inline MonikerMarshal *impl_from_IUnknown(IUnknown *iface) 01514 { 01515 return CONTAINING_RECORD(iface, MonikerMarshal, IUnknown_iface); 01516 } 01517 01518 static inline MonikerMarshal *impl_from_IMarshal( IMarshal *iface ) 01519 { 01520 return CONTAINING_RECORD(iface, MonikerMarshal, IMarshal_iface); 01521 } 01522 01523 static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv) 01524 { 01525 MonikerMarshal *This = impl_from_IUnknown(iface); 01526 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); 01527 *ppv = NULL; 01528 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid)) 01529 { 01530 *ppv = &This->IMarshal_iface; 01531 IUnknown_AddRef((IUnknown *)&This->IMarshal_iface); 01532 return S_OK; 01533 } 01534 FIXME("No interface for %s\n", debugstr_guid(riid)); 01535 return E_NOINTERFACE; 01536 } 01537 01538 static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface) 01539 { 01540 MonikerMarshal *This = impl_from_IUnknown(iface); 01541 return InterlockedIncrement(&This->ref); 01542 } 01543 01544 static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface) 01545 { 01546 MonikerMarshal *This = impl_from_IUnknown(iface); 01547 ULONG ref = InterlockedDecrement(&This->ref); 01548 01549 if (!ref) HeapFree(GetProcessHeap(), 0, This); 01550 return ref; 01551 } 01552 01553 static const IUnknownVtbl VT_MonikerMarshalInner = 01554 { 01555 MonikerMarshalInner_QueryInterface, 01556 MonikerMarshalInner_AddRef, 01557 MonikerMarshalInner_Release 01558 }; 01559 01560 static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv) 01561 { 01562 MonikerMarshal *This = impl_from_IMarshal(iface); 01563 return IMoniker_QueryInterface(This->moniker, riid, ppv); 01564 } 01565 01566 static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface) 01567 { 01568 MonikerMarshal *This = impl_from_IMarshal(iface); 01569 return IMoniker_AddRef(This->moniker); 01570 } 01571 01572 static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface) 01573 { 01574 MonikerMarshal *This = impl_from_IMarshal(iface); 01575 return IMoniker_Release(This->moniker); 01576 } 01577 01578 static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass( 01579 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, 01580 void* pvDestContext, DWORD mshlflags, CLSID* pCid) 01581 { 01582 MonikerMarshal *This = impl_from_IMarshal(iface); 01583 01584 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv, 01585 dwDestContext, pvDestContext, mshlflags, pCid); 01586 01587 return IMoniker_GetClassID(This->moniker, pCid); 01588 } 01589 01590 static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax( 01591 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, 01592 void* pvDestContext, DWORD mshlflags, DWORD* pSize) 01593 { 01594 MonikerMarshal *This = impl_from_IMarshal(iface); 01595 HRESULT hr; 01596 ULARGE_INTEGER size; 01597 01598 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv, 01599 dwDestContext, pvDestContext, mshlflags, pSize); 01600 01601 hr = IMoniker_GetSizeMax(This->moniker, &size); 01602 if (hr == S_OK) 01603 *pSize = (DWORD)size.QuadPart; 01604 return hr; 01605 } 01606 01607 static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm, 01608 REFIID riid, void* pv, DWORD dwDestContext, 01609 void* pvDestContext, DWORD mshlflags) 01610 { 01611 MonikerMarshal *This = impl_from_IMarshal(iface); 01612 01613 TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv, 01614 dwDestContext, pvDestContext, mshlflags); 01615 01616 return IMoniker_Save(This->moniker, pStm, FALSE); 01617 } 01618 01619 static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv) 01620 { 01621 MonikerMarshal *This = impl_from_IMarshal(iface); 01622 HRESULT hr; 01623 01624 TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv); 01625 01626 hr = IMoniker_Load(This->moniker, pStm); 01627 if (hr == S_OK) 01628 hr = IMoniker_QueryInterface(This->moniker, riid, ppv); 01629 return hr; 01630 } 01631 01632 static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) 01633 { 01634 TRACE("()\n"); 01635 /* can't release a state-based marshal as nothing on server side to 01636 * release */ 01637 return S_OK; 01638 } 01639 01640 static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved) 01641 { 01642 TRACE("()\n"); 01643 /* can't disconnect a state-based marshal as nothing on server side to 01644 * disconnect from */ 01645 return S_OK; 01646 } 01647 01648 static const IMarshalVtbl VT_MonikerMarshal = 01649 { 01650 MonikerMarshal_QueryInterface, 01651 MonikerMarshal_AddRef, 01652 MonikerMarshal_Release, 01653 MonikerMarshal_GetUnmarshalClass, 01654 MonikerMarshal_GetMarshalSizeMax, 01655 MonikerMarshal_MarshalInterface, 01656 MonikerMarshal_UnmarshalInterface, 01657 MonikerMarshal_ReleaseMarshalData, 01658 MonikerMarshal_DisconnectObject 01659 }; 01660 01661 HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer) 01662 { 01663 MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 01664 if (!This) return E_OUTOFMEMORY; 01665 01666 This->IUnknown_iface.lpVtbl = &VT_MonikerMarshalInner; 01667 This->IMarshal_iface.lpVtbl = &VT_MonikerMarshal; 01668 This->ref = 1; 01669 This->moniker = inner; 01670 01671 *outer = &This->IUnknown_iface; 01672 return S_OK; 01673 } 01674 01675 void * __RPC_USER MIDL_user_allocate(SIZE_T size) 01676 { 01677 return HeapAlloc(GetProcessHeap(), 0, size); 01678 } 01679 01680 void __RPC_USER MIDL_user_free(void *p) 01681 { 01682 HeapFree(GetProcessHeap(), 0, p); 01683 } Generated on Sun May 27 2012 04:24:15 for ReactOS by
1.7.6.1
|