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