Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

826 lines
17 KiB

4 years ago
  1. /*++
  2. Microsoft Windows
  3. Copyright (c) 1994 Microsoft Corporation. All rights reserved.
  4. Module Name:
  5. stub.c
  6. Abstract:
  7. Implements the IRpcStubBuffer interface.
  8. Author:
  9. ShannonC 12-Oct-1994
  10. Environment:
  11. Windows NT and Windows 95. We do not support DOS and Win16.
  12. Revision History:
  13. --*/
  14. #if !defined(__RPC_DOS__) && !defined(__RPC_WIN16__)
  15. #define USE_STUBLESS_PROXY
  16. #include <ndrp.h>
  17. #include <ndrole.h>
  18. #include <rpcproxy.h>
  19. #include <stddef.h>
  20. #include "ndrtypes.h"
  21. const IID * RPC_ENTRY
  22. NdrpGetStubIID(
  23. IRpcStubBuffer *This);
  24. #pragma code_seg(".orpc")
  25. HRESULT STDMETHODCALLTYPE
  26. CStdStubBuffer_QueryInterface(
  27. IN IRpcStubBuffer *This,
  28. IN REFIID riid,
  29. OUT void ** ppvObject)
  30. /*++
  31. Routine Description:
  32. Query for an interface on the interface stub. The interface
  33. stub supports the IUnknown and IRpcStubBuffer interfaces.
  34. Arguments:
  35. riid - Supplies the IID of the interface being requested.
  36. ppvObject - Returns a pointer to the requested interface.
  37. Return Value:
  38. S_OK
  39. E_NOINTERFACE
  40. --*/
  41. {
  42. HRESULT hr;
  43. if ((memcmp(riid, &IID_IUnknown, sizeof(IID)) == 0) ||
  44. (memcmp(riid, &IID_IRpcStubBuffer, sizeof(IID)) == 0))
  45. {
  46. This->lpVtbl->AddRef(This);
  47. *ppvObject = This;
  48. hr = S_OK;
  49. }
  50. else
  51. {
  52. *ppvObject = 0;
  53. hr = E_NOINTERFACE;
  54. }
  55. return hr;
  56. }
  57. ULONG STDMETHODCALLTYPE
  58. CStdStubBuffer_AddRef(
  59. IN IRpcStubBuffer *This)
  60. /*++
  61. Routine Description:
  62. Increment reference count.
  63. Arguments:
  64. Return Value:
  65. Reference count.
  66. --*/
  67. {
  68. InterlockedIncrement(&((CStdStubBuffer *)This)->RefCount);
  69. return (ULONG) ((CStdStubBuffer *)This)->RefCount;
  70. }
  71. HRESULT STDMETHODCALLTYPE
  72. Forwarding_QueryInterface(
  73. IN IUnknown * This,
  74. IN REFIID riid,
  75. OUT void ** ppv)
  76. {
  77. *ppv = This;
  78. return S_OK;
  79. }
  80. ULONG STDMETHODCALLTYPE
  81. Forwarding_AddRef(
  82. IN IUnknown *This)
  83. {
  84. return 1;
  85. }
  86. ULONG STDMETHODCALLTYPE
  87. Forwarding_Release(
  88. IN IUnknown *This)
  89. {
  90. return 1;
  91. }
  92. ULONG STDMETHODCALLTYPE
  93. NdrCStdStubBuffer_Release(
  94. IN IRpcStubBuffer * This,
  95. IN IPSFactoryBuffer * pFactory)
  96. /*++
  97. Routine Description:
  98. Decrement reference count.
  99. Arguments:
  100. Return Value:
  101. Reference count.
  102. --*/
  103. {
  104. ULONG count;
  105. NDR_ASSERT(((CStdStubBuffer *)This)->RefCount > 0, "Invalid reference count");
  106. count = (ULONG) ((CStdStubBuffer *)This)->RefCount - 1;
  107. if(InterlockedDecrement(&((CStdStubBuffer *)This)->RefCount) == 0)
  108. {
  109. count = 0;
  110. #if DBG == 1
  111. memset(This, '\0', sizeof(CStdStubBuffer));
  112. #endif
  113. //Free the stub buffer
  114. NdrOleFree(This);
  115. //Decrement the DLL reference count.
  116. ((CStdPSFactoryBuffer*)pFactory)->lpVtbl->Release( pFactory );
  117. }
  118. return count;
  119. }
  120. ULONG STDMETHODCALLTYPE
  121. NdrCStdStubBuffer2_Release(
  122. IN IRpcStubBuffer * This,
  123. IN IPSFactoryBuffer * pFactory)
  124. /*++
  125. Routine Description:
  126. Decrement reference count. This function supports delegation to the stub
  127. for the base interface.
  128. Arguments:
  129. Return Value:
  130. Reference count.
  131. --*/
  132. {
  133. ULONG count;
  134. unsigned char *pTemp;
  135. CStdStubBuffer2 * pStubBuffer;
  136. IRpcStubBuffer *pBaseStubBuffer;
  137. pTemp = (unsigned char *)This;
  138. pTemp -= offsetof(CStdStubBuffer2, lpVtbl);
  139. pStubBuffer = (CStdStubBuffer2 *) pTemp;
  140. NDR_ASSERT(pStubBuffer->RefCount > 0, "Invalid reference count");
  141. count = (ULONG) pStubBuffer->RefCount - 1;
  142. if(InterlockedDecrement(&pStubBuffer->RefCount) == 0)
  143. {
  144. count = 0;
  145. pBaseStubBuffer = pStubBuffer->pBaseStubBuffer;
  146. if(pBaseStubBuffer != 0)
  147. pBaseStubBuffer->lpVtbl->Release(pBaseStubBuffer);
  148. #if DBG == 1
  149. memset(pStubBuffer, '\0', sizeof(CStdStubBuffer2));
  150. #endif
  151. //Free the stub buffer
  152. NdrOleFree(pStubBuffer);
  153. //Decrement the DLL reference count.
  154. ((CStdPSFactoryBuffer*)pFactory)->lpVtbl->Release( pFactory );
  155. }
  156. return count;
  157. }
  158. HRESULT STDMETHODCALLTYPE
  159. CStdStubBuffer_Connect(
  160. IN IRpcStubBuffer *This,
  161. IN IUnknown * pUnkServer)
  162. /*++
  163. Routine Description:
  164. Connect the stub buffer to the server object.
  165. Arguments:
  166. Return Value:
  167. --*/
  168. {
  169. HRESULT hr;
  170. const IID *pIID;
  171. IUnknown *punk = 0;
  172. NDR_ASSERT(pUnkServer != 0, "pUnkServer parameter is invalid.");
  173. pIID = NdrpGetStubIID(This);
  174. hr = pUnkServer->lpVtbl->QueryInterface(pUnkServer, pIID, &punk);
  175. punk = (IUnknown *) InterlockedExchange(
  176. (long *) &((CStdStubBuffer *) This)->pvServerObject, (long) punk);
  177. if(punk != 0)
  178. {
  179. //The stub was already connected. Release the old interface pointer.
  180. punk->lpVtbl->Release(punk);
  181. }
  182. return hr;
  183. }
  184. HRESULT STDMETHODCALLTYPE
  185. CStdStubBuffer2_Connect(
  186. IN IRpcStubBuffer *This,
  187. IN IUnknown * pUnkServer)
  188. /*++
  189. Routine Description:
  190. Connect the stub buffer to the server object.
  191. Arguments:
  192. Return Value:
  193. --*/
  194. {
  195. HRESULT hr;
  196. unsigned char * pTemp;
  197. CStdStubBuffer2 * pStubBuffer;
  198. IRpcStubBuffer * pBaseStubBuffer;
  199. hr = CStdStubBuffer_Connect(This, pUnkServer);
  200. if(SUCCEEDED(hr))
  201. {
  202. //Connect the stub for the base interface.
  203. pTemp = (unsigned char *)This;
  204. pTemp -= offsetof(CStdStubBuffer2, lpVtbl);
  205. pStubBuffer = (CStdStubBuffer2 *) pTemp;
  206. pBaseStubBuffer = pStubBuffer->pBaseStubBuffer;
  207. if(pBaseStubBuffer != 0)
  208. {
  209. hr = pBaseStubBuffer->lpVtbl->Connect(pBaseStubBuffer,
  210. (IUnknown *) &pStubBuffer->lpForwardingVtbl);
  211. }
  212. }
  213. return hr;
  214. }
  215. void STDMETHODCALLTYPE
  216. CStdStubBuffer_Disconnect(
  217. IN IRpcStubBuffer *This)
  218. /*++
  219. Routine Description:
  220. Disconnect the stub from the server object.
  221. Arguments:
  222. Return Value:
  223. None.
  224. --*/
  225. {
  226. IUnknown * punk;
  227. //Set pvServerObject to zero.
  228. punk = (IUnknown *) InterlockedExchange(
  229. (long *) &((CStdStubBuffer *)This)->pvServerObject, 0);
  230. if(punk != 0)
  231. {
  232. //
  233. // Free the old interface pointer.
  234. //
  235. punk->lpVtbl->Release(punk);
  236. }
  237. }
  238. void STDMETHODCALLTYPE
  239. CStdStubBuffer2_Disconnect(
  240. IN IRpcStubBuffer *This)
  241. /*++
  242. Routine Description:
  243. Disconnect the stub buffer from the server object.
  244. Arguments:
  245. Return Value:
  246. None.
  247. --*/
  248. {
  249. IUnknown * punk;
  250. unsigned char *pTemp;
  251. CStdStubBuffer2 * pStubBuffer;
  252. IRpcStubBuffer *pBaseStubBuffer;
  253. pTemp = (unsigned char *)This;
  254. pTemp -= offsetof(CStdStubBuffer2, lpVtbl);
  255. pStubBuffer = (CStdStubBuffer2 *) pTemp;
  256. //Disconnect the stub for the base interface.
  257. pBaseStubBuffer = pStubBuffer->pBaseStubBuffer;
  258. if(pBaseStubBuffer != 0)
  259. pBaseStubBuffer->lpVtbl->Disconnect(pBaseStubBuffer);
  260. //Set pvServerObject to zero.
  261. punk = (IUnknown *) InterlockedExchange(
  262. (long *) &pStubBuffer->pvServerObject, 0);
  263. if(punk != 0)
  264. {
  265. //
  266. // Free the old interface pointer.
  267. //
  268. punk->lpVtbl->Release(punk);
  269. }
  270. }
  271. HRESULT STDMETHODCALLTYPE
  272. CStdStubBuffer_Invoke(
  273. IN IRpcStubBuffer * This,
  274. IN RPCOLEMESSAGE * prpcmsg,
  275. IN IRpcChannelBuffer * pRpcChannelBuffer)
  276. /*++
  277. Routine Description:
  278. Invoke a stub function via the dispatch table.
  279. Arguments:
  280. Return Value:
  281. --*/
  282. {
  283. HRESULT hr = S_OK;
  284. unsigned char ** ppTemp;
  285. unsigned char * pTemp;
  286. CInterfaceStubVtbl *pStubVtbl;
  287. unsigned long dwServerPhase = STUB_UNMARSHAL;
  288. //Get a pointer to the stub vtbl.
  289. ppTemp = (unsigned char **) This;
  290. pTemp = *ppTemp;
  291. pTemp -= sizeof(CInterfaceStubHeader);
  292. pStubVtbl = (CInterfaceStubVtbl *) pTemp;
  293. RpcTryExcept
  294. //
  295. //Check if procnum is valid.
  296. //
  297. if((prpcmsg->iMethod >= pStubVtbl->header.DispatchTableCount) ||
  298. (prpcmsg->iMethod < 3))
  299. {
  300. RpcRaiseException(RPC_S_PROCNUM_OUT_OF_RANGE);
  301. }
  302. // null indicates pure-interpreted
  303. if ( pStubVtbl->header.pDispatchTable != 0)
  304. {
  305. (*pStubVtbl->header.pDispatchTable[prpcmsg->iMethod])(
  306. This,
  307. pRpcChannelBuffer,
  308. (PRPC_MESSAGE) prpcmsg,
  309. &dwServerPhase);
  310. }
  311. else
  312. {
  313. #if defined(_MPPC_)
  314. // No interpreter on Power Mac
  315. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  316. #else
  317. PMIDL_SERVER_INFO pServerInfo;
  318. PMIDL_STUB_DESC pStubDesc;
  319. pServerInfo = (PMIDL_SERVER_INFO) pStubVtbl->header.pServerInfo;
  320. pStubDesc = pServerInfo->pStubDesc;
  321. if ( MIDL_VERSION_3_0_39 <= pServerInfo->pStubDesc->MIDLVersion )
  322. {
  323. // Since MIDL 3.0.39 we have a proc flag that indicates
  324. // which interpeter to call. This is because the NDR version
  325. // may be bigger than 1.1 for other reasons.
  326. PFORMAT_STRING pProcFormat;
  327. unsigned short ProcOffset;
  328. ProcOffset = pServerInfo->FmtStringOffset[ prpcmsg->iMethod ];
  329. pProcFormat = & pServerInfo->ProcString[ ProcOffset ];
  330. if ( pProcFormat[1] & Oi_OBJ_USE_V2_INTERPRETER )
  331. {
  332. NdrStubCall2(
  333. This,
  334. pRpcChannelBuffer,
  335. (PRPC_MESSAGE) prpcmsg,
  336. &dwServerPhase );
  337. }
  338. else
  339. {
  340. NdrStubCall(
  341. This,
  342. pRpcChannelBuffer,
  343. (PRPC_MESSAGE) prpcmsg,
  344. &dwServerPhase );
  345. }
  346. }
  347. else
  348. {
  349. // Prior to that, the NDR version (on per file basis)
  350. // was the only indication of -Oi2.
  351. if ( pStubDesc->Version <= NDR_VERSION_1_1 )
  352. {
  353. NdrStubCall(
  354. This,
  355. pRpcChannelBuffer,
  356. (PRPC_MESSAGE) prpcmsg,
  357. &dwServerPhase );
  358. }
  359. else
  360. {
  361. NdrStubCall2(
  362. This,
  363. pRpcChannelBuffer,
  364. (PRPC_MESSAGE) prpcmsg,
  365. &dwServerPhase );
  366. }
  367. }
  368. #endif
  369. }
  370. RpcExcept(dwServerPhase == STUB_CALL_SERVER ?
  371. EXCEPTION_CONTINUE_SEARCH :
  372. EXCEPTION_EXECUTE_HANDLER)
  373. hr = NdrStubErrorHandler( RpcExceptionCode() );
  374. RpcEndExcept
  375. return hr;
  376. }
  377. IRpcStubBuffer * STDMETHODCALLTYPE
  378. CStdStubBuffer_IsIIDSupported(
  379. IN IRpcStubBuffer *This,
  380. IN REFIID riid)
  381. /*++
  382. Routine Description:
  383. If the stub buffer supports the specified interface,
  384. then return an IRpcStubBuffer *. If the interface is not
  385. supported, then return zero.
  386. Arguments:
  387. Return Value:
  388. --*/
  389. {
  390. CStdStubBuffer * pCThis = (CStdStubBuffer *) This;
  391. const IID * pIID;
  392. IRpcStubBuffer * pInterfaceStub = 0;
  393. pIID = NdrpGetStubIID(This);
  394. if(memcmp(riid, pIID, sizeof(IID)) == 0)
  395. {
  396. if(pCThis->pvServerObject != 0)
  397. {
  398. pInterfaceStub = This;
  399. pInterfaceStub->lpVtbl->AddRef(pInterfaceStub);
  400. }
  401. }
  402. return pInterfaceStub;
  403. }
  404. ULONG STDMETHODCALLTYPE
  405. CStdStubBuffer_CountRefs(
  406. IN IRpcStubBuffer *This)
  407. /*++
  408. Routine Description:
  409. Count the number of references to the server object.
  410. Arguments:
  411. Return Value:
  412. --*/
  413. {
  414. ULONG count = 0;
  415. if(((CStdStubBuffer *)This)->pvServerObject != 0)
  416. count++;
  417. return count;
  418. }
  419. ULONG STDMETHODCALLTYPE
  420. CStdStubBuffer2_CountRefs(
  421. IN IRpcStubBuffer *This)
  422. /*++
  423. Routine Description:
  424. Count the number of references to the server object.
  425. Arguments:
  426. Return Value:
  427. --*/
  428. {
  429. ULONG count;
  430. unsigned char *pTemp;
  431. CStdStubBuffer2 * pStubBuffer;
  432. IRpcStubBuffer *pBaseStubBuffer;
  433. pTemp = (unsigned char *)This;
  434. pTemp -= offsetof(CStdStubBuffer2, lpVtbl);
  435. pStubBuffer = (CStdStubBuffer2 *) pTemp;
  436. count = CStdStubBuffer_CountRefs(This);
  437. pBaseStubBuffer = pStubBuffer->pBaseStubBuffer;
  438. if(pBaseStubBuffer != 0)
  439. count += pBaseStubBuffer->lpVtbl->CountRefs(pBaseStubBuffer);
  440. return count;
  441. }
  442. HRESULT STDMETHODCALLTYPE
  443. CStdStubBuffer_DebugServerQueryInterface(
  444. IN IRpcStubBuffer *This,
  445. OUT void **ppv)
  446. /*++
  447. Routine Description:
  448. Return the interface pointer to the server object.
  449. Arguments:
  450. Return Value:
  451. --*/
  452. {
  453. HRESULT hr;
  454. *ppv = ((CStdStubBuffer *)This)->pvServerObject;
  455. if(*ppv != 0)
  456. hr = S_OK;
  457. else
  458. hr = CO_E_OBJNOTCONNECTED;
  459. return hr;
  460. }
  461. void STDMETHODCALLTYPE
  462. CStdStubBuffer_DebugServerRelease(
  463. IN IRpcStubBuffer *This,
  464. IN void *pv)
  465. /*++
  466. Routine Description:
  467. Release a pointer previously obtained via
  468. DebugServerQueryInterface. This function does nothing.
  469. Arguments:
  470. This
  471. pv
  472. Return Value:
  473. None.
  474. --*/
  475. {
  476. }
  477. const IID * RPC_ENTRY
  478. NdrpGetStubIID(
  479. IN IRpcStubBuffer *This)
  480. /*++
  481. Routine Description:
  482. This function returns a pointer to the IID for the interface stub.
  483. Arguments:
  484. Return Value:
  485. --*/
  486. {
  487. unsigned char ** ppTemp;
  488. unsigned char * pTemp;
  489. CInterfaceStubVtbl *pStubVtbl;
  490. //Get a pointer to the stub vtbl.
  491. ppTemp = (unsigned char **) This;
  492. pTemp = *ppTemp;
  493. pTemp -= sizeof(CInterfaceStubHeader);
  494. pStubVtbl = (CInterfaceStubVtbl *) pTemp;
  495. return pStubVtbl->header.piid;
  496. }
  497. void RPC_ENTRY
  498. NdrStubInitialize(
  499. IN PRPC_MESSAGE pRpcMsg,
  500. IN PMIDL_STUB_MESSAGE pStubMsg,
  501. IN PMIDL_STUB_DESC pStubDescriptor,
  502. IN IRpcChannelBuffer * pRpcChannelBuffer )
  503. /*++
  504. Routine Description:
  505. This routine is called by the server stub before marshalling.
  506. It sets up some stub message fields.
  507. Arguments:
  508. pRpcMsg
  509. pStubMsg
  510. pStubDescriptor
  511. pRpcChannelBuffer
  512. Return Value:
  513. None.
  514. --*/
  515. {
  516. NdrServerInitialize(
  517. pRpcMsg,
  518. pStubMsg,
  519. pStubDescriptor);
  520. pRpcChannelBuffer->lpVtbl->GetDestCtx(
  521. pRpcChannelBuffer,
  522. &pStubMsg->dwDestContext,
  523. &pStubMsg->pvDestContext);
  524. }
  525. void RPC_ENTRY
  526. NdrStubGetBuffer(
  527. IN IRpcStubBuffer * This,
  528. IN IRpcChannelBuffer * pChannel,
  529. IN PMIDL_STUB_MESSAGE pStubMsg)
  530. /*++
  531. Routine Description:
  532. Get a message buffer from the channel
  533. Arguments:
  534. This
  535. pChannel
  536. pStubMsg
  537. Return Value:
  538. None. If an error occurs, this functions raises an exception.
  539. --*/
  540. {
  541. HRESULT hr;
  542. const IID * pIID;
  543. pIID = NdrpGetStubIID(This);
  544. pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength;
  545. pStubMsg->RpcMsg->DataRepresentation = NDR_LOCAL_DATA_REPRESENTATION;
  546. hr = pChannel->lpVtbl->GetBuffer(pChannel, (RPCOLEMESSAGE *) pStubMsg->RpcMsg, pIID);
  547. if(FAILED(hr))
  548. {
  549. RpcRaiseException(hr);
  550. }
  551. pStubMsg->Buffer = (unsigned char *) pStubMsg->RpcMsg->Buffer;
  552. pStubMsg->fBufferValid = TRUE;
  553. }
  554. HRESULT RPC_ENTRY
  555. NdrStubErrorHandler(
  556. IN DWORD dwExceptionCode)
  557. /*++
  558. Routine Description:
  559. Map exceptions into HRESULT failure codes. If we caught an
  560. exception from the server object, then propagate the
  561. exception to the channel.
  562. Arguments:
  563. dwExceptionCode
  564. Return Value:
  565. This function returns an HRESULT failure code.
  566. --*/
  567. {
  568. HRESULT hr;
  569. if(FAILED((HRESULT) dwExceptionCode))
  570. hr = (HRESULT) dwExceptionCode;
  571. else
  572. hr = HRESULT_FROM_WIN32(dwExceptionCode);
  573. return hr;
  574. }
  575. void RPC_ENTRY
  576. NdrStubInitializeMarshall (
  577. IN PRPC_MESSAGE pRpcMsg,
  578. IN PMIDL_STUB_MESSAGE pStubMsg,
  579. IN IRpcChannelBuffer * pRpcChannelBuffer )
  580. /*++
  581. Routine Description:
  582. This routine is called by the server stub before marshalling. It
  583. sets up some stub message fields.
  584. Arguments:
  585. pRpcMsg
  586. pStubMsg
  587. pRpcChannelBuffer
  588. Return Value:
  589. None.
  590. --*/
  591. {
  592. pStubMsg->BufferLength = 0;
  593. pStubMsg->IgnoreEmbeddedPointers = FALSE;
  594. pStubMsg->fDontCallFreeInst = 0;
  595. pStubMsg->StackTop = 0;
  596. pRpcChannelBuffer->lpVtbl->GetDestCtx(
  597. pRpcChannelBuffer,
  598. &pStubMsg->dwDestContext,
  599. &pStubMsg->pvDestContext);
  600. }
  601. void __RPC_STUB NdrStubForwardingFunction(
  602. IN IRpcStubBuffer * This,
  603. IN IRpcChannelBuffer * pChannel,
  604. IN PRPC_MESSAGE pmsg,
  605. OUT DWORD __RPC_FAR * pdwStubPhase)
  606. /*++
  607. Routine Description:
  608. This function forwards a call to the stub for the base interface.
  609. Arguments:
  610. pChannel
  611. pmsg
  612. pdwStubPhase
  613. Return Value:
  614. None.
  615. --*/
  616. {
  617. HRESULT hr;
  618. unsigned char *pTemp;
  619. CStdStubBuffer2 * pStubBuffer;
  620. IRpcStubBuffer *pBaseStubBuffer;
  621. pTemp = (unsigned char *)This;
  622. pTemp -= offsetof(CStdStubBuffer2, lpVtbl);
  623. pStubBuffer = (CStdStubBuffer2 *) pTemp;
  624. pBaseStubBuffer = pStubBuffer->pBaseStubBuffer;
  625. hr = pBaseStubBuffer->lpVtbl->Invoke(pBaseStubBuffer,
  626. (RPCOLEMESSAGE *) pmsg,
  627. pChannel);
  628. if(FAILED(hr))
  629. RpcRaiseException(hr);
  630. }
  631. #endif // !defined(__RPC_DOS__) && !defined(__RPC_WIN16__)