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