1 /* 2 * COM stub (CStdStubBuffer) implementation 3 * 4 * Copyright 2001 Ove Kåven, TransGaming Technologies 5 * Copyright 2009 Alexandre Julliard 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdarg.h> 23 24 #define COBJMACROS 25 26 #include "windef.h" 27 #include "winbase.h" 28 #include "winerror.h" 29 #include "excpt.h" 30 31 #include "objbase.h" 32 #include "rpcproxy.h" 33 34 #include "wine/debug.h" 35 #include "wine/exception.h" 36 37 #include "cpsf.h" 38 39 WINE_DEFAULT_DEBUG_CHANNEL(ole); 40 41 #define STUB_HEADER(This) (((const CInterfaceStubHeader*)((This)->lpVtbl))[-1]) 42 43 static LONG WINAPI stub_filter(EXCEPTION_POINTERS *eptr) 44 { 45 if (eptr->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) 46 return EXCEPTION_CONTINUE_SEARCH; 47 return EXCEPTION_EXECUTE_HANDLER; 48 } 49 50 static inline cstdstubbuffer_delegating_t *impl_from_delegating( IRpcStubBuffer *iface ) 51 { 52 return CONTAINING_RECORD((void *)iface, cstdstubbuffer_delegating_t, stub_buffer); 53 } 54 55 HRESULT CStdStubBuffer_Construct(REFIID riid, 56 LPUNKNOWN pUnkServer, 57 PCInterfaceName name, 58 CInterfaceStubVtbl *vtbl, 59 LPPSFACTORYBUFFER pPSFactory, 60 LPRPCSTUBBUFFER *ppStub) 61 { 62 CStdStubBuffer *This; 63 IUnknown *pvServer; 64 HRESULT r; 65 TRACE("(%p,%p,%p,%p) %s\n", pUnkServer, vtbl, pPSFactory, ppStub, name); 66 TRACE("iid=%s\n", debugstr_guid(vtbl->header.piid)); 67 TRACE("vtbl=%p\n", &vtbl->Vtbl); 68 69 if (!IsEqualGUID(vtbl->header.piid, riid)) { 70 ERR("IID mismatch during stub creation\n"); 71 return RPC_E_UNEXPECTED; 72 } 73 74 r = IUnknown_QueryInterface(pUnkServer, riid, (void**)&pvServer); 75 if(FAILED(r)) 76 return r; 77 78 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CStdStubBuffer)); 79 if (!This) { 80 IUnknown_Release(pvServer); 81 return E_OUTOFMEMORY; 82 } 83 84 This->lpVtbl = &vtbl->Vtbl; 85 This->RefCount = 1; 86 This->pvServerObject = pvServer; 87 This->pPSFactory = pPSFactory; 88 *ppStub = (LPRPCSTUBBUFFER)This; 89 90 IPSFactoryBuffer_AddRef(pPSFactory); 91 return S_OK; 92 } 93 94 static CRITICAL_SECTION delegating_vtbl_section; 95 static CRITICAL_SECTION_DEBUG critsect_debug = 96 { 97 0, 0, &delegating_vtbl_section, 98 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, 99 0, 0, { (DWORD_PTR)(__FILE__ ": delegating_vtbl_section") } 100 }; 101 static CRITICAL_SECTION delegating_vtbl_section = { &critsect_debug, -1, 0, 0, 0, 0 }; 102 103 typedef struct 104 { 105 DWORD ref; 106 DWORD size; 107 IUnknownVtbl vtbl; 108 /* remaining entries in vtbl */ 109 } ref_counted_vtbl; 110 111 static ref_counted_vtbl *current_vtbl; 112 113 114 static HRESULT WINAPI delegating_QueryInterface(IUnknown *pUnk, REFIID iid, void **ppv) 115 { 116 *ppv = pUnk; 117 return S_OK; 118 } 119 120 static ULONG WINAPI delegating_AddRef(IUnknown *pUnk) 121 { 122 return 1; 123 } 124 125 static ULONG WINAPI delegating_Release(IUnknown *pUnk) 126 { 127 return 1; 128 } 129 130 /* The idea here is to replace the first param on the stack 131 ie. This (which will point to cstdstubbuffer_delegating_t) 132 with This->stub_buffer.pvServerObject and then jump to the 133 relevant offset in This->stub_buffer.pvServerObject's vtbl. 134 */ 135 #ifdef __i386__ 136 137 #include "pshpack1.h" 138 typedef struct { 139 BYTE mov1[4]; /* mov 0x4(%esp),%eax 8b 44 24 04 */ 140 BYTE mov2[3]; /* mov 0x10(%eax),%eax 8b 40 10 */ 141 BYTE mov3[4]; /* mov %eax,0x4(%esp) 89 44 24 04 */ 142 BYTE mov4[2]; /* mov (%eax),%eax 8b 00 */ 143 BYTE mov5[2]; /* jmp *offset(%eax) ff a0 offset */ 144 DWORD offset; 145 BYTE pad[1]; /* nop 90 */ 146 } vtbl_method_t; 147 #include "poppack.h" 148 149 static const BYTE opcodes[20] = { 0x8b, 0x44, 0x24, 0x04, 0x8b, 0x40, 0x10, 0x89, 0x44, 0x24, 0x04, 150 0x8b, 0x00, 0xff, 0xa0, 0, 0, 0, 0, 0x90 }; 151 152 #elif defined(__x86_64__) 153 154 #include "pshpack1.h" 155 typedef struct 156 { 157 BYTE mov1[4]; /* movq 0x20(%rcx),%rcx 48 8b 49 20 */ 158 BYTE mov2[3]; /* movq (%rcx),%rax 48 8b 01 */ 159 BYTE jmp[2]; /* jmp *offset(%rax) ff a0 offset */ 160 DWORD offset; 161 BYTE pad[3]; /* lea 0x0(%rsi),%rsi 48 8d 36 */ 162 } vtbl_method_t; 163 #include "poppack.h" 164 165 static const BYTE opcodes[16] = { 0x48, 0x8b, 0x49, 0x20, 0x48, 0x8b, 0x01, 166 0xff, 0xa0, 0, 0, 0, 0, 0x48, 0x8d, 0x36 }; 167 #elif defined(__arm__) 168 169 static const DWORD opcodes[] = 170 { 171 0xe52d4004, /* push {r4} */ 172 0xe5900010, /* ldr r0, [r0, #16] */ 173 0xe5904000, /* ldr r4, [r0] */ 174 0xe59fc008, /* ldr ip, [pc, #8] */ 175 0xe08cc004, /* add ip, ip, r4 */ 176 0xe49d4004, /* pop {r4} */ 177 0xe59cf000 /* ldr pc, [ip] */ 178 }; 179 180 typedef struct 181 { 182 DWORD opcodes[ARRAY_SIZE(opcodes)]; 183 DWORD offset; 184 } vtbl_method_t; 185 186 #elif defined(__aarch64__) 187 188 static const DWORD opcodes[] = 189 { 190 0xf9401000, /* ldr x0, [x0,#32] */ 191 0xf9400010, /* ldr x16, [x0] */ 192 0x18000071, /* ldr w17, offset */ 193 0xf8716a10, /* ldr x16, [x16,x17] */ 194 0xd61f0200 /* br x16 */ 195 }; 196 197 typedef struct 198 { 199 DWORD opcodes[ARRAY_SIZE(opcodes)]; 200 DWORD offset; 201 } vtbl_method_t; 202 203 #else 204 205 #warning You must implement delegated proxies/stubs for your CPU 206 typedef struct 207 { 208 DWORD offset; 209 } vtbl_method_t; 210 static const BYTE opcodes[1]; 211 212 #endif 213 214 #define BLOCK_SIZE 1024 215 #define MAX_BLOCKS 64 /* 64k methods should be enough for anybody */ 216 217 static const vtbl_method_t *method_blocks[MAX_BLOCKS]; 218 219 static const vtbl_method_t *allocate_block( unsigned int num ) 220 { 221 unsigned int i; 222 vtbl_method_t *prev, *block; 223 DWORD oldprot; 224 225 block = VirtualAlloc( NULL, BLOCK_SIZE * sizeof(*block), 226 MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE ); 227 if (!block) return NULL; 228 229 for (i = 0; i < BLOCK_SIZE; i++) 230 { 231 memcpy( &block[i], opcodes, sizeof(opcodes) ); 232 block[i].offset = (BLOCK_SIZE * num + i + 3) * sizeof(void *); 233 } 234 VirtualProtect( block, BLOCK_SIZE * sizeof(*block), PAGE_EXECUTE_READ, &oldprot ); 235 prev = InterlockedCompareExchangePointer( (void **)&method_blocks[num], block, NULL ); 236 if (prev) /* someone beat us to it */ 237 { 238 VirtualFree( block, 0, MEM_RELEASE ); 239 block = prev; 240 } 241 return block; 242 } 243 244 static BOOL fill_delegated_stub_table(IUnknownVtbl *vtbl, DWORD num) 245 { 246 const void **entry = (const void **)(vtbl + 1); 247 DWORD i, j; 248 249 if (num - 3 > BLOCK_SIZE * MAX_BLOCKS) 250 { 251 FIXME( "%u methods not supported\n", num ); 252 return FALSE; 253 } 254 vtbl->QueryInterface = delegating_QueryInterface; 255 vtbl->AddRef = delegating_AddRef; 256 vtbl->Release = delegating_Release; 257 for (i = 0; i < (num - 3 + BLOCK_SIZE - 1) / BLOCK_SIZE; i++) 258 { 259 const vtbl_method_t *block = method_blocks[i]; 260 if (!block && !(block = allocate_block( i ))) return FALSE; 261 for (j = 0; j < BLOCK_SIZE && j < num - 3 - i * BLOCK_SIZE; j++) *entry++ = &block[j]; 262 } 263 return TRUE; 264 } 265 266 BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num) 267 { 268 const void **entry = (const void **)(vtbl + 1); 269 DWORD i, j; 270 271 if (num - 3 > BLOCK_SIZE * MAX_BLOCKS) 272 { 273 FIXME( "%u methods not supported\n", num ); 274 return FALSE; 275 } 276 vtbl->QueryInterface = IUnknown_QueryInterface_Proxy; 277 vtbl->AddRef = IUnknown_AddRef_Proxy; 278 vtbl->Release = IUnknown_Release_Proxy; 279 for (i = 0; i < (num - 3 + BLOCK_SIZE - 1) / BLOCK_SIZE; i++) 280 { 281 const vtbl_method_t *block = method_blocks[i]; 282 if (!block && !(block = allocate_block( i ))) return FALSE; 283 for (j = 0; j < BLOCK_SIZE && j < num - 3 - i * BLOCK_SIZE; j++, entry++) 284 if (!*entry) *entry = &block[j]; 285 } 286 return TRUE; 287 } 288 289 IUnknownVtbl *get_delegating_vtbl(DWORD num_methods) 290 { 291 IUnknownVtbl *ret; 292 293 if (num_methods < 256) num_methods = 256; /* avoid frequent reallocations */ 294 295 EnterCriticalSection(&delegating_vtbl_section); 296 297 if(!current_vtbl || num_methods > current_vtbl->size) 298 { 299 ref_counted_vtbl *table = HeapAlloc(GetProcessHeap(), 0, 300 FIELD_OFFSET(ref_counted_vtbl, vtbl) + num_methods * sizeof(void*)); 301 if (!table) 302 { 303 LeaveCriticalSection(&delegating_vtbl_section); 304 return NULL; 305 } 306 307 table->ref = 0; 308 table->size = num_methods; 309 fill_delegated_stub_table(&table->vtbl, num_methods); 310 311 if (current_vtbl && current_vtbl->ref == 0) 312 { 313 TRACE("freeing old table\n"); 314 HeapFree(GetProcessHeap(), 0, current_vtbl); 315 } 316 current_vtbl = table; 317 } 318 319 current_vtbl->ref++; 320 ret = ¤t_vtbl->vtbl; 321 LeaveCriticalSection(&delegating_vtbl_section); 322 return ret; 323 } 324 325 void release_delegating_vtbl(IUnknownVtbl *vtbl) 326 { 327 ref_counted_vtbl *table = (ref_counted_vtbl*)((DWORD *)vtbl - 1); 328 329 EnterCriticalSection(&delegating_vtbl_section); 330 table->ref--; 331 TRACE("ref now %d\n", table->ref); 332 if(table->ref == 0 && table != current_vtbl) 333 { 334 TRACE("... and we're not current so free'ing\n"); 335 HeapFree(GetProcessHeap(), 0, table); 336 } 337 LeaveCriticalSection(&delegating_vtbl_section); 338 } 339 340 HRESULT CStdStubBuffer_Delegating_Construct(REFIID riid, 341 LPUNKNOWN pUnkServer, 342 PCInterfaceName name, 343 CInterfaceStubVtbl *vtbl, 344 REFIID delegating_iid, 345 LPPSFACTORYBUFFER pPSFactory, 346 LPRPCSTUBBUFFER *ppStub) 347 { 348 cstdstubbuffer_delegating_t *This; 349 IUnknown *pvServer; 350 HRESULT r; 351 352 TRACE("(%p,%p,%p,%p) %s\n", pUnkServer, vtbl, pPSFactory, ppStub, name); 353 TRACE("iid=%s delegating to %s\n", debugstr_guid(vtbl->header.piid), debugstr_guid(delegating_iid)); 354 TRACE("vtbl=%p\n", &vtbl->Vtbl); 355 356 if (!IsEqualGUID(vtbl->header.piid, riid)) 357 { 358 ERR("IID mismatch during stub creation\n"); 359 return RPC_E_UNEXPECTED; 360 } 361 362 r = IUnknown_QueryInterface(pUnkServer, riid, (void**)&pvServer); 363 if(FAILED(r)) return r; 364 365 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This)); 366 if (!This) 367 { 368 IUnknown_Release(pvServer); 369 return E_OUTOFMEMORY; 370 } 371 372 This->base_obj = get_delegating_vtbl( vtbl->header.DispatchTableCount ); 373 r = create_stub(delegating_iid, (IUnknown*)&This->base_obj, &This->base_stub); 374 if(FAILED(r)) 375 { 376 release_delegating_vtbl(This->base_obj); 377 HeapFree(GetProcessHeap(), 0, This); 378 IUnknown_Release(pvServer); 379 return r; 380 } 381 382 This->stub_buffer.lpVtbl = &vtbl->Vtbl; 383 This->stub_buffer.RefCount = 1; 384 This->stub_buffer.pvServerObject = pvServer; 385 This->stub_buffer.pPSFactory = pPSFactory; 386 *ppStub = (LPRPCSTUBBUFFER)&This->stub_buffer; 387 388 IPSFactoryBuffer_AddRef(pPSFactory); 389 return S_OK; 390 } 391 392 HRESULT WINAPI CStdStubBuffer_QueryInterface(LPRPCSTUBBUFFER iface, 393 REFIID riid, 394 LPVOID *obj) 395 { 396 CStdStubBuffer *This = (CStdStubBuffer *)iface; 397 TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj); 398 399 if (IsEqualIID(&IID_IUnknown, riid) || 400 IsEqualIID(&IID_IRpcStubBuffer, riid)) 401 { 402 IRpcStubBuffer_AddRef(iface); 403 *obj = iface; 404 return S_OK; 405 } 406 *obj = NULL; 407 return E_NOINTERFACE; 408 } 409 410 ULONG WINAPI CStdStubBuffer_AddRef(LPRPCSTUBBUFFER iface) 411 { 412 CStdStubBuffer *This = (CStdStubBuffer *)iface; 413 TRACE("(%p)->AddRef()\n",This); 414 return InterlockedIncrement(&This->RefCount); 415 } 416 417 ULONG WINAPI NdrCStdStubBuffer_Release(LPRPCSTUBBUFFER iface, 418 LPPSFACTORYBUFFER pPSF) 419 { 420 CStdStubBuffer *This = (CStdStubBuffer *)iface; 421 ULONG refs; 422 423 TRACE("(%p)->Release()\n",This); 424 425 refs = InterlockedDecrement(&This->RefCount); 426 if (!refs) 427 { 428 /* test_Release shows that native doesn't call Disconnect here. 429 We'll leave it in for the time being. */ 430 IRpcStubBuffer_Disconnect(iface); 431 432 IPSFactoryBuffer_Release(pPSF); 433 HeapFree(GetProcessHeap(),0,This); 434 } 435 return refs; 436 } 437 438 ULONG WINAPI NdrCStdStubBuffer2_Release(LPRPCSTUBBUFFER iface, 439 LPPSFACTORYBUFFER pPSF) 440 { 441 cstdstubbuffer_delegating_t *This = impl_from_delegating( iface ); 442 ULONG refs; 443 444 TRACE("(%p)->Release()\n", This); 445 446 refs = InterlockedDecrement(&This->stub_buffer.RefCount); 447 if (!refs) 448 { 449 /* Just like NdrCStdStubBuffer_Release, we shouldn't call 450 Disconnect here */ 451 IRpcStubBuffer_Disconnect((IRpcStubBuffer *)&This->stub_buffer); 452 453 IRpcStubBuffer_Release(This->base_stub); 454 release_delegating_vtbl(This->base_obj); 455 456 IPSFactoryBuffer_Release(pPSF); 457 HeapFree(GetProcessHeap(), 0, This); 458 } 459 460 return refs; 461 } 462 463 HRESULT WINAPI CStdStubBuffer_Connect(LPRPCSTUBBUFFER iface, 464 LPUNKNOWN lpUnkServer) 465 { 466 CStdStubBuffer *This = (CStdStubBuffer *)iface; 467 HRESULT r; 468 IUnknown *new = NULL; 469 470 TRACE("(%p)->Connect(%p)\n",This,lpUnkServer); 471 472 r = IUnknown_QueryInterface(lpUnkServer, STUB_HEADER(This).piid, (void**)&new); 473 new = InterlockedExchangePointer((void**)&This->pvServerObject, new); 474 if(new) 475 IUnknown_Release(new); 476 return r; 477 } 478 479 void WINAPI CStdStubBuffer_Disconnect(LPRPCSTUBBUFFER iface) 480 { 481 CStdStubBuffer *This = (CStdStubBuffer *)iface; 482 IUnknown *old; 483 TRACE("(%p)->Disconnect()\n",This); 484 485 old = InterlockedExchangePointer((void**)&This->pvServerObject, NULL); 486 487 if(old) 488 IUnknown_Release(old); 489 } 490 491 HRESULT WINAPI CStdStubBuffer_Invoke(LPRPCSTUBBUFFER iface, 492 PRPCOLEMESSAGE pMsg, 493 LPRPCCHANNELBUFFER pChannel) 494 { 495 CStdStubBuffer *This = (CStdStubBuffer *)iface; 496 DWORD dwPhase = STUB_UNMARSHAL; 497 HRESULT hr = S_OK; 498 499 TRACE("(%p)->Invoke(%p,%p)\n",This,pMsg,pChannel); 500 501 __TRY 502 { 503 if (STUB_HEADER(This).pDispatchTable) 504 STUB_HEADER(This).pDispatchTable[pMsg->iMethod](iface, pChannel, (PRPC_MESSAGE)pMsg, &dwPhase); 505 else /* pure interpreted */ 506 NdrStubCall2(iface, pChannel, (PRPC_MESSAGE)pMsg, &dwPhase); 507 } 508 __EXCEPT(stub_filter) 509 { 510 DWORD dwExceptionCode = GetExceptionCode(); 511 WARN("a stub call failed with exception 0x%08x (%d)\n", dwExceptionCode, dwExceptionCode); 512 if (FAILED(dwExceptionCode)) 513 hr = dwExceptionCode; 514 else 515 hr = HRESULT_FROM_WIN32(dwExceptionCode); 516 } 517 __ENDTRY 518 519 return hr; 520 } 521 522 LPRPCSTUBBUFFER WINAPI CStdStubBuffer_IsIIDSupported(LPRPCSTUBBUFFER iface, 523 REFIID riid) 524 { 525 CStdStubBuffer *This = (CStdStubBuffer *)iface; 526 TRACE("(%p)->IsIIDSupported(%s)\n",This,debugstr_guid(riid)); 527 return IsEqualGUID(STUB_HEADER(This).piid, riid) ? iface : NULL; 528 } 529 530 ULONG WINAPI CStdStubBuffer_CountRefs(LPRPCSTUBBUFFER iface) 531 { 532 CStdStubBuffer *This = (CStdStubBuffer *)iface; 533 TRACE("(%p)->CountRefs()\n",This); 534 return This->RefCount; 535 } 536 537 HRESULT WINAPI CStdStubBuffer_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, 538 LPVOID *ppv) 539 { 540 CStdStubBuffer *This = (CStdStubBuffer *)iface; 541 TRACE("(%p)->DebugServerQueryInterface(%p)\n",This,ppv); 542 return S_OK; 543 } 544 545 void WINAPI CStdStubBuffer_DebugServerRelease(LPRPCSTUBBUFFER iface, 546 LPVOID pv) 547 { 548 CStdStubBuffer *This = (CStdStubBuffer *)iface; 549 TRACE("(%p)->DebugServerRelease(%p)\n",This,pv); 550 } 551 552 const IRpcStubBufferVtbl CStdStubBuffer_Vtbl = 553 { 554 CStdStubBuffer_QueryInterface, 555 CStdStubBuffer_AddRef, 556 NULL, 557 CStdStubBuffer_Connect, 558 CStdStubBuffer_Disconnect, 559 CStdStubBuffer_Invoke, 560 CStdStubBuffer_IsIIDSupported, 561 CStdStubBuffer_CountRefs, 562 CStdStubBuffer_DebugServerQueryInterface, 563 CStdStubBuffer_DebugServerRelease 564 }; 565 566 static HRESULT WINAPI CStdStubBuffer_Delegating_Connect(LPRPCSTUBBUFFER iface, 567 LPUNKNOWN lpUnkServer) 568 { 569 cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); 570 HRESULT r; 571 TRACE("(%p)->Connect(%p)\n", This, lpUnkServer); 572 573 r = CStdStubBuffer_Connect(iface, lpUnkServer); 574 if(SUCCEEDED(r)) 575 r = IRpcStubBuffer_Connect(This->base_stub, (IUnknown*)&This->base_obj); 576 577 return r; 578 } 579 580 static void WINAPI CStdStubBuffer_Delegating_Disconnect(LPRPCSTUBBUFFER iface) 581 { 582 cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); 583 TRACE("(%p)->Disconnect()\n", This); 584 585 IRpcStubBuffer_Disconnect(This->base_stub); 586 CStdStubBuffer_Disconnect(iface); 587 } 588 589 static ULONG WINAPI CStdStubBuffer_Delegating_CountRefs(LPRPCSTUBBUFFER iface) 590 { 591 cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); 592 ULONG ret; 593 TRACE("(%p)->CountRefs()\n", This); 594 595 ret = CStdStubBuffer_CountRefs(iface); 596 ret += IRpcStubBuffer_CountRefs(This->base_stub); 597 598 return ret; 599 } 600 601 const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl = 602 { 603 CStdStubBuffer_QueryInterface, 604 CStdStubBuffer_AddRef, 605 NULL, 606 CStdStubBuffer_Delegating_Connect, 607 CStdStubBuffer_Delegating_Disconnect, 608 CStdStubBuffer_Invoke, 609 CStdStubBuffer_IsIIDSupported, 610 CStdStubBuffer_Delegating_CountRefs, 611 CStdStubBuffer_DebugServerQueryInterface, 612 CStdStubBuffer_DebugServerRelease 613 }; 614 615 const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface) 616 { 617 CStdStubBuffer *This = (CStdStubBuffer *)iface; 618 return STUB_HEADER(This).pServerInfo; 619 } 620 621 /************************************************************************ 622 * NdrStubForwardingFunction [RPCRT4.@] 623 */ 624 void __RPC_STUB NdrStubForwardingFunction( IRpcStubBuffer *iface, IRpcChannelBuffer *pChannel, 625 PRPC_MESSAGE pMsg, DWORD *pdwStubPhase ) 626 { 627 /* Note pMsg is passed intact since RPCOLEMESSAGE is basically a RPC_MESSAGE. */ 628 629 cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); 630 HRESULT r = IRpcStubBuffer_Invoke(This->base_stub, (RPCOLEMESSAGE*)pMsg, pChannel); 631 if(FAILED(r)) RpcRaiseException(r); 632 return; 633 } 634 635 /*********************************************************************** 636 * NdrStubInitialize [RPCRT4.@] 637 */ 638 void WINAPI NdrStubInitialize(PRPC_MESSAGE pRpcMsg, 639 PMIDL_STUB_MESSAGE pStubMsg, 640 PMIDL_STUB_DESC pStubDescriptor, 641 LPRPCCHANNELBUFFER pRpcChannelBuffer) 642 { 643 TRACE("(%p,%p,%p,%p)\n", pRpcMsg, pStubMsg, pStubDescriptor, pRpcChannelBuffer); 644 NdrServerInitializeNew(pRpcMsg, pStubMsg, pStubDescriptor); 645 pStubMsg->pRpcChannelBuffer = pRpcChannelBuffer; 646 IRpcChannelBuffer_GetDestCtx(pStubMsg->pRpcChannelBuffer, 647 &pStubMsg->dwDestContext, 648 &pStubMsg->pvDestContext); 649 } 650 651 /*********************************************************************** 652 * NdrStubGetBuffer [RPCRT4.@] 653 */ 654 void WINAPI NdrStubGetBuffer(LPRPCSTUBBUFFER iface, 655 LPRPCCHANNELBUFFER pRpcChannelBuffer, 656 PMIDL_STUB_MESSAGE pStubMsg) 657 { 658 CStdStubBuffer *This = (CStdStubBuffer *)iface; 659 HRESULT hr; 660 661 TRACE("(%p, %p, %p)\n", This, pRpcChannelBuffer, pStubMsg); 662 663 pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength; 664 hr = IRpcChannelBuffer_GetBuffer(pRpcChannelBuffer, 665 (RPCOLEMESSAGE *)pStubMsg->RpcMsg, STUB_HEADER(This).piid); 666 if (FAILED(hr)) 667 { 668 RpcRaiseException(hr); 669 return; 670 } 671 672 pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer; 673 } 674