1 /* 2 * Monikers 3 * 4 * Copyright 1998 Marcus Meissner 5 * Copyright 1999 Noomen Hamza 6 * Copyright 2005 Robert Shearman (for CodeWeavers) 7 * Copyright 2007 Robert Shearman 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 22 */ 23 24 #include <stdarg.h> 25 #include <string.h> 26 27 #define COBJMACROS 28 29 #include "winerror.h" 30 #include "windef.h" 31 #include "winbase.h" 32 #include "winuser.h" 33 #include "winsvc.h" 34 #include "wtypes.h" 35 #include "ole2.h" 36 37 #include "wine/list.h" 38 #include "wine/debug.h" 39 #include "wine/exception.h" 40 41 #include "compobj_private.h" 42 #include "moniker.h" 43 #include "irot.h" 44 45 WINE_DEFAULT_DEBUG_CHANNEL(ole); 46 47 /* see MSDN docs for IROTData::GetComparisonData, which states what this 48 * constant is 49 */ 50 #define MAX_COMPARISON_DATA 2048 51 52 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr) 53 { 54 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode); 55 } 56 57 /* define the structure of the running object table elements */ 58 struct rot_entry 59 { 60 struct list entry; 61 InterfaceData* object; /* marshaled running object*/ 62 MonikerComparisonData* moniker_data; /* moniker comparison data that identifies this object */ 63 DWORD cookie; /* cookie identifying this object */ 64 FILETIME last_modified; 65 IrotContextHandle ctxt_handle; 66 }; 67 68 /* define the RunningObjectTableImpl structure */ 69 typedef struct RunningObjectTableImpl 70 { 71 IRunningObjectTable IRunningObjectTable_iface; 72 LONG ref; 73 74 struct list rot; /* list of ROT entries */ 75 CRITICAL_SECTION lock; 76 } RunningObjectTableImpl; 77 78 static RunningObjectTableImpl* runningObjectTableInstance = NULL; 79 static IrotHandle irot_handle; 80 81 /* define the EnumMonikerImpl structure */ 82 typedef struct EnumMonikerImpl 83 { 84 IEnumMoniker IEnumMoniker_iface; 85 LONG ref; 86 87 InterfaceList *moniker_list; 88 ULONG pos; 89 } EnumMonikerImpl; 90 91 static inline RunningObjectTableImpl *impl_from_IRunningObjectTable(IRunningObjectTable *iface) 92 { 93 return CONTAINING_RECORD(iface, RunningObjectTableImpl, IRunningObjectTable_iface); 94 } 95 96 static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface) 97 { 98 return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface); 99 } 100 101 /* IEnumMoniker Local functions*/ 102 static HRESULT EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list, 103 ULONG pos, IEnumMoniker **ppenumMoniker); 104 105 static IrotHandle get_irot_handle(void) 106 { 107 if (!irot_handle) 108 { 109 RPC_STATUS status; 110 RPC_WSTR binding; 111 IrotHandle new_handle; 112 unsigned short ncacn_np[] = IROT_PROTSEQ; 113 unsigned short endpoint[] = IROT_ENDPOINT; 114 status = RpcStringBindingComposeW(NULL, ncacn_np, NULL, endpoint, NULL, &binding); 115 if (status == RPC_S_OK) 116 { 117 status = RpcBindingFromStringBindingW(binding, &new_handle); 118 RpcStringFreeW(&binding); 119 } 120 if (status != RPC_S_OK) 121 return NULL; 122 if (InterlockedCompareExchangePointer(&irot_handle, new_handle, NULL)) 123 /* another thread beat us to it */ 124 RpcBindingFree(&new_handle); 125 } 126 return irot_handle; 127 } 128 129 static BOOL start_rpcss(void) 130 { 131 static const WCHAR rpcssW[] = {'R','p','c','S','s',0}; 132 SC_HANDLE scm, service; 133 SERVICE_STATUS_PROCESS status; 134 BOOL ret = FALSE; 135 136 TRACE("\n"); 137 138 if (!(scm = OpenSCManagerW( NULL, NULL, 0 ))) 139 { 140 ERR( "failed to open service manager\n" ); 141 return FALSE; 142 } 143 if (!(service = OpenServiceW( scm, rpcssW, SERVICE_START | SERVICE_QUERY_STATUS ))) 144 { 145 ERR( "failed to open RpcSs service\n" ); 146 CloseServiceHandle( scm ); 147 return FALSE; 148 } 149 if (StartServiceW( service, 0, NULL ) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) 150 { 151 ULONGLONG start_time = GetTickCount64(); 152 do 153 { 154 DWORD dummy; 155 156 if (!QueryServiceStatusEx( service, SC_STATUS_PROCESS_INFO, 157 (BYTE *)&status, sizeof(status), &dummy )) 158 break; 159 if (status.dwCurrentState == SERVICE_RUNNING) 160 { 161 ret = TRUE; 162 break; 163 } 164 if (GetTickCount64() - start_time > 30000) break; 165 Sleep( 100 ); 166 167 } while (status.dwCurrentState == SERVICE_START_PENDING); 168 169 if (status.dwCurrentState != SERVICE_RUNNING) 170 WARN( "RpcSs failed to start %u\n", status.dwCurrentState ); 171 } 172 else ERR( "failed to start RpcSs service\n" ); 173 174 CloseServiceHandle( service ); 175 CloseServiceHandle( scm ); 176 return ret; 177 } 178 179 static HRESULT create_stream_on_mip_ro(const InterfaceData *mip, IStream **stream) 180 { 181 HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData); 182 void *pv = GlobalLock(hglobal); 183 memcpy(pv, mip->abData, mip->ulCntData); 184 GlobalUnlock(hglobal); 185 return CreateStreamOnHGlobal(hglobal, TRUE, stream); 186 } 187 188 static void rot_entry_delete(struct rot_entry *rot_entry) 189 { 190 if (rot_entry->cookie) 191 { 192 InterfaceData *object = NULL; 193 InterfaceData *moniker = NULL; 194 __TRY 195 { 196 IrotRevoke(get_irot_handle(), rot_entry->cookie, 197 &rot_entry->ctxt_handle, &object, &moniker); 198 } 199 __EXCEPT(rpc_filter) 200 { 201 } 202 __ENDTRY 203 MIDL_user_free(object); 204 if (moniker) 205 { 206 IStream *stream; 207 HRESULT hr; 208 hr = create_stream_on_mip_ro(moniker, &stream); 209 if (hr == S_OK) 210 { 211 CoReleaseMarshalData(stream); 212 IStream_Release(stream); 213 } 214 } 215 MIDL_user_free(moniker); 216 } 217 if (rot_entry->object) 218 { 219 IStream *stream; 220 HRESULT hr; 221 hr = create_stream_on_mip_ro(rot_entry->object, &stream); 222 if (hr == S_OK) 223 { 224 CoReleaseMarshalData(stream); 225 IStream_Release(stream); 226 } 227 } 228 HeapFree(GetProcessHeap(), 0, rot_entry->object); 229 HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data); 230 HeapFree(GetProcessHeap(), 0, rot_entry); 231 } 232 233 /* moniker_data must be freed with HeapFree when no longer in use */ 234 static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MonikerComparisonData **moniker_data) 235 { 236 HRESULT hr; 237 IROTData *pROTData = NULL; 238 hr = IMoniker_QueryInterface(pMoniker, &IID_IROTData, (void *)&pROTData); 239 if (SUCCEEDED(hr)) 240 { 241 ULONG size = MAX_COMPARISON_DATA; 242 *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[size])); 243 if (!*moniker_data) 244 { 245 IROTData_Release(pROTData); 246 return E_OUTOFMEMORY; 247 } 248 hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size); 249 IROTData_Release(pROTData); 250 if (hr != S_OK) 251 { 252 ERR("Failed to copy comparison data into buffer, hr = 0x%08x\n", hr); 253 HeapFree(GetProcessHeap(), 0, *moniker_data); 254 return hr; 255 } 256 (*moniker_data)->ulCntData = size; 257 } 258 else 259 { 260 IBindCtx *pbc; 261 LPOLESTR pszDisplayName; 262 CLSID clsid; 263 int len; 264 265 TRACE("generating comparison data from display name\n"); 266 267 hr = CreateBindCtx(0, &pbc); 268 if (FAILED(hr)) 269 return hr; 270 hr = IMoniker_GetDisplayName(pMoniker, pbc, NULL, &pszDisplayName); 271 IBindCtx_Release(pbc); 272 if (FAILED(hr)) 273 return hr; 274 hr = IMoniker_GetClassID(pMoniker, &clsid); 275 if (FAILED(hr)) 276 { 277 CoTaskMemFree(pszDisplayName); 278 return hr; 279 } 280 281 len = lstrlenW(pszDisplayName); 282 *moniker_data = HeapAlloc(GetProcessHeap(), 0, 283 FIELD_OFFSET(MonikerComparisonData, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)])); 284 if (!*moniker_data) 285 { 286 CoTaskMemFree(pszDisplayName); 287 return E_OUTOFMEMORY; 288 } 289 (*moniker_data)->ulCntData = sizeof(CLSID) + (len+1)*sizeof(WCHAR); 290 291 memcpy(&(*moniker_data)->abData[0], &clsid, sizeof(clsid)); 292 memcpy(&(*moniker_data)->abData[sizeof(clsid)], pszDisplayName, (len+1)*sizeof(WCHAR)); 293 CoTaskMemFree(pszDisplayName); 294 } 295 return S_OK; 296 } 297 298 static HRESULT reduce_moniker(IMoniker *pmk, IBindCtx *pbc, IMoniker **pmkReduced) 299 { 300 IBindCtx *pbcNew = NULL; 301 HRESULT hr; 302 if (!pbc) 303 { 304 hr = CreateBindCtx(0, &pbcNew); 305 if (FAILED(hr)) 306 return hr; 307 pbc = pbcNew; 308 } 309 hr = IMoniker_Reduce(pmk, pbc, MKRREDUCE_ALL, NULL, pmkReduced); 310 if (FAILED(hr)) 311 ERR("reducing moniker failed with error 0x%08x\n", hr); 312 if (pbcNew) IBindCtx_Release(pbcNew); 313 return hr; 314 } 315 316 /*********************************************************************** 317 * RunningObjectTable_QueryInterface 318 */ 319 static HRESULT WINAPI 320 RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface, 321 REFIID riid,void** ppvObject) 322 { 323 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 324 325 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); 326 327 /* validate arguments */ 328 329 if (ppvObject==0) 330 return E_INVALIDARG; 331 332 *ppvObject = 0; 333 334 if (IsEqualIID(&IID_IUnknown, riid) || 335 IsEqualIID(&IID_IRunningObjectTable, riid)) 336 *ppvObject = &This->IRunningObjectTable_iface; 337 338 if ((*ppvObject)==0) 339 return E_NOINTERFACE; 340 341 IRunningObjectTable_AddRef(iface); 342 343 return S_OK; 344 } 345 346 /*********************************************************************** 347 * RunningObjectTable_AddRef 348 */ 349 static ULONG WINAPI 350 RunningObjectTableImpl_AddRef(IRunningObjectTable* iface) 351 { 352 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 353 354 TRACE("(%p)\n",This); 355 356 return InterlockedIncrement(&This->ref); 357 } 358 359 /*********************************************************************** 360 * RunningObjectTable_Destroy 361 */ 362 static HRESULT 363 RunningObjectTableImpl_Destroy(void) 364 { 365 struct list *cursor, *cursor2; 366 IrotHandle old_handle; 367 368 TRACE("()\n"); 369 370 if (runningObjectTableInstance==NULL) 371 return E_INVALIDARG; 372 373 /* free the ROT table memory */ 374 LIST_FOR_EACH_SAFE(cursor, cursor2, &runningObjectTableInstance->rot) 375 { 376 struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry); 377 list_remove(&rot_entry->entry); 378 rot_entry_delete(rot_entry); 379 } 380 381 DEBUG_CLEAR_CRITSEC_NAME(&runningObjectTableInstance->lock); 382 DeleteCriticalSection(&runningObjectTableInstance->lock); 383 384 /* free the ROT structure memory */ 385 HeapFree(GetProcessHeap(),0,runningObjectTableInstance); 386 runningObjectTableInstance = NULL; 387 388 old_handle = irot_handle; 389 irot_handle = NULL; 390 if (old_handle) 391 RpcBindingFree(&old_handle); 392 393 return S_OK; 394 } 395 396 /*********************************************************************** 397 * RunningObjectTable_Release 398 */ 399 static ULONG WINAPI 400 RunningObjectTableImpl_Release(IRunningObjectTable* iface) 401 { 402 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 403 ULONG ref; 404 405 TRACE("(%p)\n",This); 406 407 ref = InterlockedDecrement(&This->ref); 408 409 /* uninitialize ROT structure if there are no more references to it */ 410 if (ref == 0) 411 { 412 struct list *cursor, *cursor2; 413 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->rot) 414 { 415 struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry); 416 list_remove(&rot_entry->entry); 417 rot_entry_delete(rot_entry); 418 } 419 /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only 420 * when RunningObjectTableImpl_UnInitialize function is called 421 */ 422 } 423 424 return ref; 425 } 426 427 /*********************************************************************** 428 * RunningObjectTable_Register 429 * 430 * PARAMS 431 * grfFlags [in] Registration options 432 * punkObject [in] the object being registered 433 * pmkObjectName [in] the moniker of the object being registered 434 * pdwRegister [out] the value identifying the registration 435 */ 436 static HRESULT WINAPI 437 RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags, 438 IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister) 439 { 440 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 441 struct rot_entry *rot_entry; 442 HRESULT hr = S_OK; 443 IStream *pStream = NULL; 444 DWORD mshlflags; 445 IBindCtx *pbc; 446 InterfaceData *moniker = NULL; 447 448 TRACE("(%p,%d,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister); 449 450 if (grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT)) 451 { 452 ERR("Invalid grfFlags: 0x%08x\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT)); 453 return E_INVALIDARG; 454 } 455 456 if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL) 457 return E_INVALIDARG; 458 459 rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry)); 460 if (!rot_entry) 461 return E_OUTOFMEMORY; 462 463 /* marshal object */ 464 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 465 if (hr != S_OK) 466 { 467 rot_entry_delete(rot_entry); 468 return hr; 469 } 470 mshlflags = (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK; 471 hr = CoMarshalInterface(pStream, &IID_IUnknown, punkObject, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, mshlflags); 472 /* FIXME: a cleaner way would be to create an IStream class that writes 473 * directly to an MInterfacePointer */ 474 if (hr == S_OK) 475 { 476 HGLOBAL hglobal; 477 hr = GetHGlobalFromStream(pStream, &hglobal); 478 if (hr == S_OK) 479 { 480 SIZE_T size = GlobalSize(hglobal); 481 const void *pv = GlobalLock(hglobal); 482 rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); 483 rot_entry->object->ulCntData = size; 484 memcpy(rot_entry->object->abData, pv, size); 485 GlobalUnlock(hglobal); 486 } 487 } 488 IStream_Release(pStream); 489 if (hr != S_OK) 490 { 491 rot_entry_delete(rot_entry); 492 return hr; 493 } 494 495 hr = CreateBindCtx(0, &pbc); 496 if (FAILED(hr)) 497 { 498 rot_entry_delete(rot_entry); 499 return hr; 500 } 501 502 hr = reduce_moniker(pmkObjectName, pbc, &pmkObjectName); 503 if (FAILED(hr)) 504 { 505 rot_entry_delete(rot_entry); 506 IBindCtx_Release(pbc); 507 return hr; 508 } 509 510 hr = IMoniker_GetTimeOfLastChange(pmkObjectName, pbc, NULL, 511 &rot_entry->last_modified); 512 IBindCtx_Release(pbc); 513 if (FAILED(hr)) 514 { 515 CoFileTimeNow(&rot_entry->last_modified); 516 hr = S_OK; 517 } 518 519 hr = get_moniker_comparison_data(pmkObjectName, 520 &rot_entry->moniker_data); 521 if (hr != S_OK) 522 { 523 rot_entry_delete(rot_entry); 524 IMoniker_Release(pmkObjectName); 525 return hr; 526 } 527 528 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 529 if (hr != S_OK) 530 { 531 rot_entry_delete(rot_entry); 532 IMoniker_Release(pmkObjectName); 533 return hr; 534 } 535 /* marshal moniker */ 536 hr = CoMarshalInterface(pStream, &IID_IMoniker, (IUnknown *)pmkObjectName, 537 MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG); 538 /* FIXME: a cleaner way would be to create an IStream class that writes 539 * directly to an MInterfacePointer */ 540 if (hr == S_OK) 541 { 542 HGLOBAL hglobal; 543 hr = GetHGlobalFromStream(pStream, &hglobal); 544 if (hr == S_OK) 545 { 546 SIZE_T size = GlobalSize(hglobal); 547 const void *pv = GlobalLock(hglobal); 548 moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[size])); 549 moniker->ulCntData = size; 550 memcpy(moniker->abData, pv, size); 551 GlobalUnlock(hglobal); 552 } 553 } 554 IStream_Release(pStream); 555 IMoniker_Release(pmkObjectName); 556 if (hr != S_OK) 557 { 558 HeapFree(GetProcessHeap(), 0, moniker); 559 rot_entry_delete(rot_entry); 560 return hr; 561 } 562 563 564 while (TRUE) 565 { 566 __TRY 567 { 568 hr = IrotRegister(get_irot_handle(), rot_entry->moniker_data, 569 rot_entry->object, moniker, 570 &rot_entry->last_modified, grfFlags, 571 &rot_entry->cookie, &rot_entry->ctxt_handle); 572 } 573 __EXCEPT(rpc_filter) 574 { 575 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 576 } 577 __ENDTRY 578 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 579 { 580 if (start_rpcss()) 581 continue; 582 } 583 break; 584 } 585 HeapFree(GetProcessHeap(), 0, moniker); 586 if (FAILED(hr)) 587 { 588 rot_entry_delete(rot_entry); 589 return hr; 590 } 591 592 /* gives a registration identifier to the registered object*/ 593 *pdwRegister = rot_entry->cookie; 594 595 EnterCriticalSection(&This->lock); 596 list_add_tail(&This->rot, &rot_entry->entry); 597 LeaveCriticalSection(&This->lock); 598 599 return hr; 600 } 601 602 /*********************************************************************** 603 * RunningObjectTable_Revoke 604 * 605 * PARAMS 606 * dwRegister [in] Value identifying registration to be revoked 607 */ 608 static HRESULT WINAPI 609 RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister) 610 { 611 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 612 struct rot_entry *rot_entry; 613 614 TRACE("(%p,%d)\n",This,dwRegister); 615 616 EnterCriticalSection(&This->lock); 617 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) 618 { 619 if (rot_entry->cookie == dwRegister) 620 { 621 list_remove(&rot_entry->entry); 622 LeaveCriticalSection(&This->lock); 623 624 rot_entry_delete(rot_entry); 625 return S_OK; 626 } 627 } 628 LeaveCriticalSection(&This->lock); 629 630 return E_INVALIDARG; 631 } 632 633 /*********************************************************************** 634 * RunningObjectTable_IsRunning 635 * 636 * PARAMS 637 * pmkObjectName [in] moniker of the object whose status is desired 638 */ 639 static HRESULT WINAPI 640 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName) 641 { 642 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 643 MonikerComparisonData *moniker_data; 644 HRESULT hr; 645 const struct rot_entry *rot_entry; 646 647 TRACE("(%p,%p)\n",This,pmkObjectName); 648 649 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName); 650 if (FAILED(hr)) 651 return hr; 652 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); 653 IMoniker_Release(pmkObjectName); 654 if (hr != S_OK) 655 return hr; 656 657 hr = S_FALSE; 658 EnterCriticalSection(&This->lock); 659 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry) 660 { 661 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && 662 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData)) 663 { 664 hr = S_OK; 665 break; 666 } 667 } 668 LeaveCriticalSection(&This->lock); 669 670 if (hr == S_FALSE) 671 { 672 while (TRUE) 673 { 674 __TRY 675 { 676 hr = IrotIsRunning(get_irot_handle(), moniker_data); 677 } 678 __EXCEPT(rpc_filter) 679 { 680 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 681 } 682 __ENDTRY 683 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 684 { 685 if (start_rpcss()) 686 continue; 687 } 688 break; 689 } 690 } 691 692 HeapFree(GetProcessHeap(), 0, moniker_data); 693 694 return hr; 695 } 696 697 /*********************************************************************** 698 * RunningObjectTable_GetObject 699 * 700 * PARAMS 701 * pmkObjectName [in] Pointer to the moniker on the object 702 * ppunkObject [out] variable that receives the IUnknown interface pointer 703 */ 704 static HRESULT WINAPI 705 RunningObjectTableImpl_GetObject( IRunningObjectTable* iface, 706 IMoniker *pmkObjectName, IUnknown **ppunkObject) 707 { 708 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 709 MonikerComparisonData *moniker_data; 710 InterfaceData *object = NULL; 711 IrotCookie cookie; 712 HRESULT hr; 713 struct rot_entry *rot_entry; 714 715 TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject); 716 717 if (ppunkObject == NULL) 718 return E_POINTER; 719 720 *ppunkObject = NULL; 721 722 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName); 723 if (FAILED(hr)) 724 return hr; 725 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); 726 IMoniker_Release(pmkObjectName); 727 if (hr != S_OK) 728 return hr; 729 730 EnterCriticalSection(&This->lock); 731 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) 732 { 733 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && 734 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData)) 735 { 736 IStream *pStream; 737 hr = create_stream_on_mip_ro(rot_entry->object, &pStream); 738 if (hr == S_OK) 739 { 740 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject); 741 IStream_Release(pStream); 742 } 743 744 LeaveCriticalSection(&This->lock); 745 HeapFree(GetProcessHeap(), 0, moniker_data); 746 747 return hr; 748 } 749 } 750 LeaveCriticalSection(&This->lock); 751 752 TRACE("moniker unavailable locally, calling SCM\n"); 753 754 while (TRUE) 755 { 756 __TRY 757 { 758 hr = IrotGetObject(get_irot_handle(), moniker_data, &object, &cookie); 759 } 760 __EXCEPT(rpc_filter) 761 { 762 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 763 } 764 __ENDTRY 765 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 766 { 767 if (start_rpcss()) 768 continue; 769 } 770 break; 771 } 772 773 if (SUCCEEDED(hr)) 774 { 775 IStream *pStream; 776 hr = create_stream_on_mip_ro(object, &pStream); 777 if (hr == S_OK) 778 { 779 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject); 780 IStream_Release(pStream); 781 } 782 } 783 else 784 WARN("Moniker unavailable, IrotGetObject returned 0x%08x\n", hr); 785 786 HeapFree(GetProcessHeap(), 0, moniker_data); 787 788 return hr; 789 } 790 791 /*********************************************************************** 792 * RunningObjectTable_NoteChangeTime 793 * 794 * PARAMS 795 * dwRegister [in] Value identifying registration being updated 796 * pfiletime [in] Pointer to structure containing object's last change time 797 */ 798 static HRESULT WINAPI 799 RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, 800 DWORD dwRegister, FILETIME *pfiletime) 801 { 802 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 803 struct rot_entry *rot_entry; 804 HRESULT hr = E_INVALIDARG; 805 806 TRACE("(%p,%d,%p)\n",This,dwRegister,pfiletime); 807 808 EnterCriticalSection(&This->lock); 809 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) 810 { 811 if (rot_entry->cookie == dwRegister) 812 { 813 rot_entry->last_modified = *pfiletime; 814 LeaveCriticalSection(&This->lock); 815 816 while (TRUE) 817 { 818 __TRY 819 { 820 hr = IrotNoteChangeTime(get_irot_handle(), dwRegister, pfiletime); 821 } 822 __EXCEPT(rpc_filter) 823 { 824 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 825 } 826 __ENDTRY 827 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 828 { 829 if (start_rpcss()) 830 continue; 831 } 832 break; 833 } 834 835 goto done; 836 } 837 } 838 LeaveCriticalSection(&This->lock); 839 840 done: 841 TRACE("-- 0x08%x\n", hr); 842 return hr; 843 } 844 845 /*********************************************************************** 846 * RunningObjectTable_GetTimeOfLastChange 847 * 848 * PARAMS 849 * pmkObjectName [in] moniker of the object whose status is desired 850 * pfiletime [out] structure that receives object's last change time 851 */ 852 static HRESULT WINAPI 853 RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, 854 IMoniker *pmkObjectName, FILETIME *pfiletime) 855 { 856 HRESULT hr = MK_E_UNAVAILABLE; 857 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 858 MonikerComparisonData *moniker_data; 859 const struct rot_entry *rot_entry; 860 861 TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime); 862 863 if (pmkObjectName==NULL || pfiletime==NULL) 864 return E_INVALIDARG; 865 866 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName); 867 if (FAILED(hr)) 868 return hr; 869 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); 870 IMoniker_Release(pmkObjectName); 871 if (hr != S_OK) 872 return hr; 873 874 hr = MK_E_UNAVAILABLE; 875 876 EnterCriticalSection(&This->lock); 877 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry) 878 { 879 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && 880 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData)) 881 { 882 *pfiletime = rot_entry->last_modified; 883 hr = S_OK; 884 break; 885 } 886 } 887 LeaveCriticalSection(&This->lock); 888 889 if (hr != S_OK) 890 { 891 while (TRUE) 892 { 893 __TRY 894 { 895 hr = IrotGetTimeOfLastChange(get_irot_handle(), moniker_data, pfiletime); 896 } 897 __EXCEPT(rpc_filter) 898 { 899 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 900 } 901 __ENDTRY 902 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 903 { 904 if (start_rpcss()) 905 continue; 906 } 907 break; 908 } 909 } 910 911 HeapFree(GetProcessHeap(), 0, moniker_data); 912 913 TRACE("-- 0x%08x\n", hr); 914 return hr; 915 } 916 917 /*********************************************************************** 918 * RunningObjectTable_EnumRunning 919 * 920 * PARAMS 921 * ppenumMoniker [out] receives the IEnumMoniker interface pointer 922 */ 923 static HRESULT WINAPI 924 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, 925 IEnumMoniker **ppenumMoniker) 926 { 927 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface); 928 InterfaceList *interface_list = NULL; 929 HRESULT hr; 930 931 TRACE("(%p, %p)\n", This, ppenumMoniker); 932 933 *ppenumMoniker = NULL; 934 935 while (TRUE) 936 { 937 __TRY 938 { 939 hr = IrotEnumRunning(get_irot_handle(), &interface_list); 940 } 941 __EXCEPT(rpc_filter) 942 { 943 hr = HRESULT_FROM_WIN32(GetExceptionCode()); 944 } 945 __ENDTRY 946 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) 947 { 948 if (start_rpcss()) 949 continue; 950 } 951 break; 952 } 953 954 if (SUCCEEDED(hr)) 955 hr = EnumMonikerImpl_CreateEnumROTMoniker(interface_list, 956 0, ppenumMoniker); 957 958 return hr; 959 } 960 961 /* Virtual function table for the IRunningObjectTable class. */ 962 static const IRunningObjectTableVtbl VT_RunningObjectTableImpl = 963 { 964 RunningObjectTableImpl_QueryInterface, 965 RunningObjectTableImpl_AddRef, 966 RunningObjectTableImpl_Release, 967 RunningObjectTableImpl_Register, 968 RunningObjectTableImpl_Revoke, 969 RunningObjectTableImpl_IsRunning, 970 RunningObjectTableImpl_GetObject, 971 RunningObjectTableImpl_NoteChangeTime, 972 RunningObjectTableImpl_GetTimeOfLastChange, 973 RunningObjectTableImpl_EnumRunning 974 }; 975 976 /*********************************************************************** 977 * RunningObjectTable_Initialize 978 */ 979 HRESULT WINAPI RunningObjectTableImpl_Initialize(void) 980 { 981 TRACE("\n"); 982 983 /* create the unique instance of the RunningObjectTableImpl structure */ 984 runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl)); 985 986 if (!runningObjectTableInstance) 987 return E_OUTOFMEMORY; 988 989 /* initialize the virtual table function */ 990 runningObjectTableInstance->IRunningObjectTable_iface.lpVtbl = &VT_RunningObjectTableImpl; 991 992 /* the initial reference is set to "1" so that it isn't destroyed after its 993 * first use until the process is destroyed, as the running object table is 994 * a process-wide cache of a global table */ 995 runningObjectTableInstance->ref = 1; 996 997 list_init(&runningObjectTableInstance->rot); 998 InitializeCriticalSection(&runningObjectTableInstance->lock); 999 DEBUG_SET_CRITSEC_NAME(&runningObjectTableInstance->lock, "RunningObjectTableImpl.lock"); 1000 1001 return S_OK; 1002 } 1003 1004 /*********************************************************************** 1005 * RunningObjectTable_UnInitialize 1006 */ 1007 HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void) 1008 { 1009 TRACE("\n"); 1010 1011 if (runningObjectTableInstance==NULL) 1012 return E_POINTER; 1013 1014 RunningObjectTableImpl_Release(&runningObjectTableInstance->IRunningObjectTable_iface); 1015 1016 RunningObjectTableImpl_Destroy(); 1017 1018 return S_OK; 1019 } 1020 1021 /*********************************************************************** 1022 * GetRunningObjectTable (OLE32.@) 1023 * 1024 * Retrieves the global running object table. 1025 * 1026 * PARAMS 1027 * reserved [I] Reserved. Set to 0. 1028 * pprot [O] Address that receives the pointer to the running object table. 1029 * 1030 * RETURNS 1031 * Success: S_OK. 1032 * Failure: Any HRESULT code. 1033 */ 1034 HRESULT WINAPI 1035 GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot) 1036 { 1037 IID riid=IID_IRunningObjectTable; 1038 HRESULT res; 1039 1040 TRACE("()\n"); 1041 1042 if (reserved!=0) 1043 return E_UNEXPECTED; 1044 1045 if(runningObjectTableInstance==NULL) 1046 return CO_E_NOTINITIALIZED; 1047 1048 res = IRunningObjectTable_QueryInterface(&runningObjectTableInstance->IRunningObjectTable_iface, 1049 &riid,(void**)pprot); 1050 1051 return res; 1052 } 1053 1054 static HRESULT get_moniker_for_progid_display_name(LPBC pbc, 1055 LPCOLESTR szDisplayName, 1056 LPDWORD pchEaten, 1057 LPMONIKER *ppmk) 1058 { 1059 CLSID clsid; 1060 HRESULT hr; 1061 LPWSTR progid; 1062 LPCWSTR start = szDisplayName; 1063 LPCWSTR end; 1064 int len; 1065 IMoniker *class_moniker; 1066 1067 if (*start == '@') 1068 start++; 1069 1070 /* find end delimiter */ 1071 for (end = start; *end; end++) 1072 if (*end == ':') 1073 break; 1074 1075 len = end - start; 1076 1077 /* must start with '@' or have a ':' somewhere and mustn't be one character 1078 * long (since that looks like an absolute path) */ 1079 if (((start == szDisplayName) && (*end == '\0')) || (len <= 1)) 1080 return MK_E_SYNTAX; 1081 1082 progid = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); 1083 if (progid) 1084 { 1085 memcpy(progid, start, len * sizeof(WCHAR)); 1086 progid[len] = '\0'; 1087 } 1088 hr = CLSIDFromProgID(progid, &clsid); 1089 HeapFree(GetProcessHeap(), 0, progid); 1090 if (FAILED(hr)) 1091 return MK_E_SYNTAX; 1092 1093 hr = CreateClassMoniker(&clsid, &class_moniker); 1094 if (SUCCEEDED(hr)) 1095 { 1096 IParseDisplayName *pdn; 1097 hr = IMoniker_BindToObject(class_moniker, pbc, NULL, 1098 &IID_IParseDisplayName, (void **)&pdn); 1099 /* fallback to using IClassFactory to get IParseDisplayName - 1100 * adsldp.dll depends on this */ 1101 if (FAILED(hr)) 1102 { 1103 IClassFactory *pcf; 1104 hr = IMoniker_BindToObject(class_moniker, pbc, NULL, 1105 &IID_IClassFactory, (void **)&pcf); 1106 if (SUCCEEDED(hr)) 1107 { 1108 hr = IClassFactory_CreateInstance(pcf, NULL, 1109 &IID_IParseDisplayName, 1110 (void **)&pdn); 1111 IClassFactory_Release(pcf); 1112 } 1113 } 1114 IMoniker_Release(class_moniker); 1115 if (SUCCEEDED(hr)) 1116 { 1117 hr = IParseDisplayName_ParseDisplayName(pdn, pbc, 1118 (LPOLESTR)szDisplayName, 1119 pchEaten, ppmk); 1120 IParseDisplayName_Release(pdn); 1121 } 1122 } 1123 return hr; 1124 } 1125 1126 /****************************************************************************** 1127 * MkParseDisplayName [OLE32.@] 1128 */ 1129 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName, 1130 LPDWORD pchEaten, LPMONIKER *ppmk) 1131 { 1132 HRESULT hr = MK_E_SYNTAX; 1133 static const WCHAR wszClsidColon[] = {'c','l','s','i','d',':'}; 1134 IMoniker *moniker; 1135 DWORD chEaten; 1136 1137 TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk); 1138 1139 if (!pbc || !IsValidInterface((LPUNKNOWN) pbc)) 1140 return E_INVALIDARG; 1141 1142 if (!szDisplayName || !*szDisplayName) 1143 return E_INVALIDARG; 1144 1145 if (!pchEaten || !ppmk) 1146 return E_INVALIDARG; 1147 1148 *pchEaten = 0; 1149 *ppmk = NULL; 1150 1151 if (!_wcsnicmp(szDisplayName, wszClsidColon, ARRAY_SIZE(wszClsidColon))) 1152 { 1153 hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker); 1154 if (FAILED(hr) && (hr != MK_E_SYNTAX)) 1155 return hr; 1156 } 1157 else 1158 { 1159 hr = get_moniker_for_progid_display_name(pbc, szDisplayName, &chEaten, &moniker); 1160 if (FAILED(hr) && (hr != MK_E_SYNTAX)) 1161 return hr; 1162 } 1163 1164 if (FAILED(hr)) 1165 { 1166 hr = FileMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker); 1167 if (FAILED(hr) && (hr != MK_E_SYNTAX)) 1168 return hr; 1169 } 1170 1171 if (SUCCEEDED(hr)) 1172 { 1173 while (TRUE) 1174 { 1175 IMoniker *next_moniker; 1176 *pchEaten += chEaten; 1177 szDisplayName += chEaten; 1178 if (!*szDisplayName) 1179 { 1180 *ppmk = moniker; 1181 return S_OK; 1182 } 1183 chEaten = 0; 1184 hr = IMoniker_ParseDisplayName(moniker, pbc, NULL, 1185 (LPOLESTR)szDisplayName, &chEaten, 1186 &next_moniker); 1187 IMoniker_Release(moniker); 1188 if (FAILED(hr)) 1189 { 1190 *pchEaten = 0; 1191 break; 1192 } 1193 moniker = next_moniker; 1194 } 1195 } 1196 1197 return hr; 1198 } 1199 1200 /*********************************************************************** 1201 * GetClassFile (OLE32.@) 1202 * 1203 * Retrieves the class ID associated with the given filename. 1204 * 1205 * PARAMS 1206 * filePathName [I] Filename to retrieve the class ID for. 1207 * pclsid [O] Address that receives the class ID for the file. 1208 * 1209 * RETURNS 1210 * Success: S_OK. 1211 * Failure: Any HRESULT code. 1212 */ 1213 HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid) 1214 { 1215 IStorage *pstg=0; 1216 HRESULT res; 1217 int nbElm, length, i; 1218 LONG sizeProgId, ret; 1219 LPOLESTR *pathDec=0,absFile=0,progId=0; 1220 LPWSTR extension; 1221 static const WCHAR bkslashW[] = {'\\',0}; 1222 static const WCHAR dotW[] = {'.',0}; 1223 1224 TRACE("%s, %p\n", debugstr_w(filePathName), pclsid); 1225 1226 /* if the file contain a storage object the return the CLSID written by IStorage_SetClass method*/ 1227 if((StgIsStorageFile(filePathName))==S_OK){ 1228 1229 res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg); 1230 1231 if (SUCCEEDED(res)) { 1232 res=ReadClassStg(pstg,pclsid); 1233 IStorage_Release(pstg); 1234 } 1235 1236 return res; 1237 } 1238 /* If the file is not a storage object then attempt to match various bits in the file against a 1239 pattern in the registry. This case is not frequently used, so I present only the pseudocode for 1240 this case. 1241 1242 for(i=0;i<nFileTypes;i++) 1243 1244 for(i=0;j<nPatternsForType;j++){ 1245 1246 PATTERN pat; 1247 HANDLE hFile; 1248 1249 pat=ReadPatternFromRegistry(i,j); 1250 hFile=CreateFileW(filePathName,,,,,,hFile); 1251 SetFilePosition(hFile,pat.offset); 1252 ReadFile(hFile,buf,pat.size,&r,NULL); 1253 if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){ 1254 1255 *pclsid=ReadCLSIDFromRegistry(i); 1256 return S_OK; 1257 } 1258 } 1259 */ 1260 1261 /* if the above strategies fail then search for the extension key in the registry */ 1262 1263 /* get the last element (absolute file) in the path name */ 1264 nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec); 1265 absFile=pathDec[nbElm-1]; 1266 1267 /* failed if the path represents a directory and not an absolute file name*/ 1268 if (!wcscmp(absFile, bkslashW)) { 1269 CoTaskMemFree(pathDec); 1270 return MK_E_INVALIDEXTENSION; 1271 } 1272 1273 /* get the extension of the file */ 1274 extension = NULL; 1275 length=lstrlenW(absFile); 1276 for(i = length-1; (i >= 0) && *(extension = &absFile[i]) != '.'; i--) 1277 /* nothing */; 1278 1279 if (!extension || !wcscmp(extension, dotW)) { 1280 CoTaskMemFree(pathDec); 1281 return MK_E_INVALIDEXTENSION; 1282 } 1283 1284 ret = RegQueryValueW(HKEY_CLASSES_ROOT, extension, NULL, &sizeProgId); 1285 if (!ret) { 1286 /* get the progId associated to the extension */ 1287 progId = CoTaskMemAlloc(sizeProgId); 1288 ret = RegQueryValueW(HKEY_CLASSES_ROOT, extension, progId, &sizeProgId); 1289 if (!ret) 1290 /* return the clsid associated to the progId */ 1291 res = CLSIDFromProgID(progId, pclsid); 1292 else 1293 res = HRESULT_FROM_WIN32(ret); 1294 CoTaskMemFree(progId); 1295 } 1296 else 1297 res = HRESULT_FROM_WIN32(ret); 1298 1299 for(i=0; pathDec[i]!=NULL;i++) 1300 CoTaskMemFree(pathDec[i]); 1301 CoTaskMemFree(pathDec); 1302 1303 return res != S_OK ? MK_E_INVALIDEXTENSION : res; 1304 } 1305 1306 /*********************************************************************** 1307 * EnumMoniker_QueryInterface 1308 */ 1309 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject) 1310 { 1311 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1312 1313 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); 1314 1315 /* validate arguments */ 1316 if (ppvObject == NULL) 1317 return E_INVALIDARG; 1318 1319 *ppvObject = NULL; 1320 1321 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid)) 1322 *ppvObject = &This->IEnumMoniker_iface; 1323 else 1324 return E_NOINTERFACE; 1325 1326 IEnumMoniker_AddRef(iface); 1327 return S_OK; 1328 } 1329 1330 /*********************************************************************** 1331 * EnumMoniker_AddRef 1332 */ 1333 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface) 1334 { 1335 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1336 1337 TRACE("(%p)\n",This); 1338 1339 return InterlockedIncrement(&This->ref); 1340 } 1341 1342 /*********************************************************************** 1343 * EnumMoniker_release 1344 */ 1345 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface) 1346 { 1347 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1348 ULONG ref; 1349 1350 TRACE("(%p)\n",This); 1351 1352 ref = InterlockedDecrement(&This->ref); 1353 1354 /* uninitialize ROT structure if there are no more references to it */ 1355 if (ref == 0) 1356 { 1357 ULONG i; 1358 1359 TRACE("(%p) Deleting\n",This); 1360 1361 for (i = 0; i < This->moniker_list->size; i++) 1362 HeapFree(GetProcessHeap(), 0, This->moniker_list->interfaces[i]); 1363 HeapFree(GetProcessHeap(), 0, This->moniker_list); 1364 HeapFree(GetProcessHeap(), 0, This); 1365 } 1366 1367 return ref; 1368 } 1369 /*********************************************************************** 1370 * EnumMoniker_Next 1371 */ 1372 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched) 1373 { 1374 ULONG i; 1375 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1376 HRESULT hr = S_OK; 1377 1378 TRACE("(%p) TabCurrentPos %d Tablastindx %d\n", This, This->pos, This->moniker_list->size); 1379 1380 /* retrieve the requested number of moniker from the current position */ 1381 for(i = 0; (This->pos < This->moniker_list->size) && (i < celt); i++) 1382 { 1383 IStream *stream; 1384 hr = create_stream_on_mip_ro(This->moniker_list->interfaces[This->pos++], &stream); 1385 if (hr != S_OK) break; 1386 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]); 1387 IStream_Release(stream); 1388 if (hr != S_OK) break; 1389 } 1390 1391 if (pceltFetched != NULL) 1392 *pceltFetched= i; 1393 1394 if (hr != S_OK) 1395 return hr; 1396 1397 if (i == celt) 1398 return S_OK; 1399 else 1400 return S_FALSE; 1401 1402 } 1403 1404 /*********************************************************************** 1405 * EnumMoniker_Skip 1406 */ 1407 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt) 1408 { 1409 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1410 1411 TRACE("(%p)\n",This); 1412 1413 if (This->pos + celt >= This->moniker_list->size) 1414 return S_FALSE; 1415 1416 This->pos += celt; 1417 1418 return S_OK; 1419 } 1420 1421 /*********************************************************************** 1422 * EnumMoniker_Reset 1423 */ 1424 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface) 1425 { 1426 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1427 1428 This->pos = 0; /* set back to start of list */ 1429 1430 TRACE("(%p)\n",This); 1431 1432 return S_OK; 1433 } 1434 1435 /*********************************************************************** 1436 * EnumMoniker_Clone 1437 */ 1438 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum) 1439 { 1440 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1441 InterfaceList *moniker_list; 1442 ULONG i; 1443 1444 TRACE("(%p)\n",This); 1445 1446 *ppenum = NULL; 1447 1448 moniker_list = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceList, interfaces[This->moniker_list->size])); 1449 if (!moniker_list) 1450 return E_OUTOFMEMORY; 1451 1452 moniker_list->size = This->moniker_list->size; 1453 for (i = 0; i < This->moniker_list->size; i++) 1454 { 1455 SIZE_T size = FIELD_OFFSET(InterfaceData, abData[This->moniker_list->interfaces[i]->ulCntData]); 1456 moniker_list->interfaces[i] = HeapAlloc(GetProcessHeap(), 0, size); 1457 if (!moniker_list->interfaces[i]) 1458 { 1459 ULONG end = i; 1460 for (i = 0; i < end; i++) 1461 HeapFree(GetProcessHeap(), 0, moniker_list->interfaces[i]); 1462 HeapFree(GetProcessHeap(), 0, moniker_list); 1463 return E_OUTOFMEMORY; 1464 } 1465 memcpy(moniker_list->interfaces[i], This->moniker_list->interfaces[i], size); 1466 } 1467 1468 /* copy the enum structure */ 1469 return EnumMonikerImpl_CreateEnumROTMoniker(moniker_list, This->pos, ppenum); 1470 } 1471 1472 /* Virtual function table for the IEnumMoniker class. */ 1473 static const IEnumMonikerVtbl VT_EnumMonikerImpl = 1474 { 1475 EnumMonikerImpl_QueryInterface, 1476 EnumMonikerImpl_AddRef, 1477 EnumMonikerImpl_Release, 1478 EnumMonikerImpl_Next, 1479 EnumMonikerImpl_Skip, 1480 EnumMonikerImpl_Reset, 1481 EnumMonikerImpl_Clone 1482 }; 1483 1484 /*********************************************************************** 1485 * EnumMonikerImpl_CreateEnumROTMoniker 1486 * Used by EnumRunning to create the structure and EnumClone 1487 * to copy the structure 1488 */ 1489 static HRESULT EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list, 1490 ULONG current_pos, 1491 IEnumMoniker **ppenumMoniker) 1492 { 1493 EnumMonikerImpl* This = NULL; 1494 1495 if (!ppenumMoniker) 1496 return E_INVALIDARG; 1497 1498 This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl)); 1499 if (!This) return E_OUTOFMEMORY; 1500 1501 TRACE("(%p)\n", This); 1502 1503 /* initialize the virtual table function */ 1504 This->IEnumMoniker_iface.lpVtbl = &VT_EnumMonikerImpl; 1505 1506 /* the initial reference is set to "1" */ 1507 This->ref = 1; /* set the ref count to one */ 1508 This->pos = current_pos; /* Set the list start posn */ 1509 This->moniker_list = moniker_list; 1510 1511 *ppenumMoniker = &This->IEnumMoniker_iface; 1512 1513 return S_OK; 1514 } 1515 1516 1517 /* Shared implementation of moniker marshaler based on saving and loading of 1518 * monikers */ 1519 1520 typedef struct MonikerMarshal 1521 { 1522 IUnknown IUnknown_iface; 1523 IMarshal IMarshal_iface; 1524 1525 LONG ref; 1526 IMoniker *moniker; 1527 } MonikerMarshal; 1528 1529 static inline MonikerMarshal *impl_from_IUnknown(IUnknown *iface) 1530 { 1531 return CONTAINING_RECORD(iface, MonikerMarshal, IUnknown_iface); 1532 } 1533 1534 static inline MonikerMarshal *impl_from_IMarshal( IMarshal *iface ) 1535 { 1536 return CONTAINING_RECORD(iface, MonikerMarshal, IMarshal_iface); 1537 } 1538 1539 static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv) 1540 { 1541 MonikerMarshal *This = impl_from_IUnknown(iface); 1542 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); 1543 *ppv = NULL; 1544 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid)) 1545 { 1546 *ppv = &This->IMarshal_iface; 1547 IMarshal_AddRef(&This->IMarshal_iface); 1548 return S_OK; 1549 } 1550 FIXME("No interface for %s\n", debugstr_guid(riid)); 1551 return E_NOINTERFACE; 1552 } 1553 1554 static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface) 1555 { 1556 MonikerMarshal *This = impl_from_IUnknown(iface); 1557 return InterlockedIncrement(&This->ref); 1558 } 1559 1560 static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface) 1561 { 1562 MonikerMarshal *This = impl_from_IUnknown(iface); 1563 ULONG ref = InterlockedDecrement(&This->ref); 1564 1565 if (!ref) HeapFree(GetProcessHeap(), 0, This); 1566 return ref; 1567 } 1568 1569 static const IUnknownVtbl VT_MonikerMarshalInner = 1570 { 1571 MonikerMarshalInner_QueryInterface, 1572 MonikerMarshalInner_AddRef, 1573 MonikerMarshalInner_Release 1574 }; 1575 1576 static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv) 1577 { 1578 MonikerMarshal *This = impl_from_IMarshal(iface); 1579 return IMoniker_QueryInterface(This->moniker, riid, ppv); 1580 } 1581 1582 static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface) 1583 { 1584 MonikerMarshal *This = impl_from_IMarshal(iface); 1585 return IMoniker_AddRef(This->moniker); 1586 } 1587 1588 static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface) 1589 { 1590 MonikerMarshal *This = impl_from_IMarshal(iface); 1591 return IMoniker_Release(This->moniker); 1592 } 1593 1594 static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass( 1595 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, 1596 void* pvDestContext, DWORD mshlflags, CLSID* pCid) 1597 { 1598 MonikerMarshal *This = impl_from_IMarshal(iface); 1599 1600 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv, 1601 dwDestContext, pvDestContext, mshlflags, pCid); 1602 1603 return IMoniker_GetClassID(This->moniker, pCid); 1604 } 1605 1606 static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax( 1607 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, 1608 void* pvDestContext, DWORD mshlflags, DWORD* pSize) 1609 { 1610 MonikerMarshal *This = impl_from_IMarshal(iface); 1611 HRESULT hr; 1612 ULARGE_INTEGER size; 1613 1614 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv, 1615 dwDestContext, pvDestContext, mshlflags, pSize); 1616 1617 hr = IMoniker_GetSizeMax(This->moniker, &size); 1618 if (hr == S_OK) 1619 *pSize = (DWORD)size.QuadPart; 1620 return hr; 1621 } 1622 1623 static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm, 1624 REFIID riid, void* pv, DWORD dwDestContext, 1625 void* pvDestContext, DWORD mshlflags) 1626 { 1627 MonikerMarshal *This = impl_from_IMarshal(iface); 1628 1629 TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv, 1630 dwDestContext, pvDestContext, mshlflags); 1631 1632 return IMoniker_Save(This->moniker, pStm, FALSE); 1633 } 1634 1635 static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv) 1636 { 1637 MonikerMarshal *This = impl_from_IMarshal(iface); 1638 HRESULT hr; 1639 1640 TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv); 1641 1642 hr = IMoniker_Load(This->moniker, pStm); 1643 if (hr == S_OK) 1644 hr = IMoniker_QueryInterface(This->moniker, riid, ppv); 1645 return hr; 1646 } 1647 1648 static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) 1649 { 1650 TRACE("()\n"); 1651 /* can't release a state-based marshal as nothing on server side to 1652 * release */ 1653 return S_OK; 1654 } 1655 1656 static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved) 1657 { 1658 TRACE("()\n"); 1659 /* can't disconnect a state-based marshal as nothing on server side to 1660 * disconnect from */ 1661 return S_OK; 1662 } 1663 1664 static const IMarshalVtbl VT_MonikerMarshal = 1665 { 1666 MonikerMarshal_QueryInterface, 1667 MonikerMarshal_AddRef, 1668 MonikerMarshal_Release, 1669 MonikerMarshal_GetUnmarshalClass, 1670 MonikerMarshal_GetMarshalSizeMax, 1671 MonikerMarshal_MarshalInterface, 1672 MonikerMarshal_UnmarshalInterface, 1673 MonikerMarshal_ReleaseMarshalData, 1674 MonikerMarshal_DisconnectObject 1675 }; 1676 1677 HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer) 1678 { 1679 MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 1680 if (!This) return E_OUTOFMEMORY; 1681 1682 This->IUnknown_iface.lpVtbl = &VT_MonikerMarshalInner; 1683 This->IMarshal_iface.lpVtbl = &VT_MonikerMarshal; 1684 This->ref = 1; 1685 This->moniker = inner; 1686 1687 *outer = &This->IUnknown_iface; 1688 return S_OK; 1689 } 1690 1691 void * __RPC_USER MIDL_user_allocate(SIZE_T size) 1692 { 1693 return HeapAlloc(GetProcessHeap(), 0, size); 1694 } 1695 1696 void __RPC_USER MIDL_user_free(void *p) 1697 { 1698 HeapFree(GetProcessHeap(), 0, p); 1699 } 1700