Source code of Windows XP (NT5)
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.

1685 lines
46 KiB

  1. //--------------------------------------------------------------
  2. //
  3. // File: async.cxx
  4. //
  5. // Contents: Test proxy and stub for async
  6. //
  7. //---------------------------------------------------------------
  8. #include <windows.h>
  9. #include <stdio.h>
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <errno.h>
  13. #include <io.h>
  14. #include <malloc.h>
  15. #include <ole2.h>
  16. #include <coguid.h>
  17. #include "async.h"
  18. typedef struct SAsyncData
  19. {
  20. BOOL bLate;
  21. BOOL bSleep;
  22. BOOL bFail;
  23. };
  24. class CProxy;
  25. class CProxyComplete;
  26. class CStubComplete;
  27. class CPCInnerUnknown : public IUnknown
  28. {
  29. public:
  30. // IUnknown methods
  31. STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
  32. STDMETHOD_(ULONG,AddRef) ( void );
  33. STDMETHOD_(ULONG,Release) ( void );
  34. // Constructor
  35. CPCInnerUnknown( CProxyComplete *pParent );
  36. DWORD _iRef;
  37. CProxyComplete *_pParent;
  38. };
  39. class CProxyComplete : public IAsyncManager, public ICancelMethodCalls
  40. {
  41. public:
  42. STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
  43. STDMETHOD_(ULONG,AddRef) ( void );
  44. STDMETHOD_(ULONG,Release) ( void );
  45. STDMETHOD (Cancel) ( void );
  46. STDMETHOD (TestCancel) ( void );
  47. STDMETHOD (CompleteCall) ( HRESULT result );
  48. STDMETHOD (GetCallContext) ( REFIID riid, void **pInterface );
  49. STDMETHOD (GetState) ( DWORD *pState );
  50. STDMETHOD (SetCancelTimeout) ( ULONG lSec ) { return E_NOTIMPL; }
  51. CProxyComplete( IUnknown *pControl, BOOL fAutoComplete, HRESULT *hr );
  52. ~CProxyComplete();
  53. CPCInnerUnknown _Inner;
  54. IUnknown *_pSyncInner;
  55. IUnknown *_pControl;
  56. RPCOLEMESSAGE _Message;
  57. BOOL _fAutoComplete;
  58. IRpcChannelBuffer3 *_pChannel;
  59. };
  60. class CSCInnerUnknown : public IUnknown
  61. {
  62. public:
  63. // IUnknown methods
  64. STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
  65. STDMETHOD_(ULONG,AddRef) ( void );
  66. STDMETHOD_(ULONG,Release) ( void );
  67. // Constructor
  68. CSCInnerUnknown( CStubComplete *pParent );
  69. DWORD _iRef;
  70. CStubComplete *_pParent;
  71. };
  72. class CStubComplete : public IAsyncManager, public IAsyncSetup,
  73. public ICancelMethodCalls
  74. {
  75. public:
  76. STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
  77. STDMETHOD_(ULONG,AddRef) ( void );
  78. STDMETHOD_(ULONG,Release) ( void );
  79. STDMETHOD (Cancel) ( void );
  80. STDMETHOD (CompleteCall) ( HRESULT result );
  81. STDMETHOD (GetCallContext) ( REFIID riid, void **pInterface );
  82. STDMETHOD (GetState) ( DWORD *pState );
  83. STDMETHOD (SetCancelTimeout) ( ULONG lSec ) { return E_NOTIMPL; }
  84. STDMETHOD (TestCancel) ( void );
  85. STDMETHOD (GetAsyncManager) ( REFIID riid,
  86. IUnknown *pOuter,
  87. DWORD dwFlags,
  88. IUnknown **pInner,
  89. IAsyncManager **pComplete );
  90. CStubComplete( IUnknown *pControl, IRpcChannelBuffer3 *, RPCOLEMESSAGE *,
  91. HRESULT *hr );
  92. ~CStubComplete();
  93. CSCInnerUnknown _Inner;
  94. IUnknown *_pSyncInner;
  95. IUnknown *_pControl;
  96. RPCOLEMESSAGE _Message;
  97. IRpcChannelBuffer3 *_pChannel;
  98. };
  99. class CAsync : public IAsync
  100. {
  101. public:
  102. STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
  103. STDMETHOD_(ULONG,AddRef) ( void );
  104. STDMETHOD_(ULONG,Release) ( void );
  105. STDMETHOD (Async) ( IAsyncManager **pCall, BOOL, BOOL, BOOL );
  106. STDMETHOD (RecurseAsync) ( IAsyncManager **pCall, IAsync *, DWORD );
  107. CAsync( IUnknown *pControl, CProxy *pProxy );
  108. ~CAsync();
  109. private:
  110. IUnknown *_pControl;
  111. CProxy *_pProxy;
  112. };
  113. class CProxy: public IRpcProxyBuffer, IAsyncSetup
  114. {
  115. public:
  116. STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
  117. STDMETHOD_(ULONG,AddRef) ( void );
  118. STDMETHOD_(ULONG,Release) ( void );
  119. STDMETHOD (Connect) ( IRpcChannelBuffer *pRpcChannelBuffer );
  120. STDMETHOD_(void,Disconnect)( void );
  121. STDMETHOD (GetAsyncManager)( REFIID riid,
  122. IUnknown *pOuter,
  123. DWORD dwFlags,
  124. IUnknown **pInner,
  125. IAsyncManager **pComplete );
  126. CProxy( IUnknown *pControl );
  127. CAsync _Async;
  128. DWORD _iRef;
  129. IRpcChannelBuffer3 *_pChannel;
  130. };
  131. class CStub : public IRpcStubBuffer
  132. {
  133. public:
  134. STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
  135. STDMETHOD_(ULONG,AddRef) ( void );
  136. STDMETHOD_(ULONG,Release) ( void );
  137. STDMETHOD (Connect) ( IUnknown *pServer );
  138. STDMETHOD_(void, Disconnect) ( void );
  139. STDMETHOD (Invoke) ( RPCOLEMESSAGE *pMessage,
  140. IRpcChannelBuffer *pChannel );
  141. STDMETHOD_(IRpcStubBuffer *,IsIIDSupported)( REFIID riid );
  142. STDMETHOD_(ULONG,CountRefs) ( void );
  143. STDMETHOD (DebugServerQueryInterface) ( void **ppv );
  144. STDMETHOD_(void,DebugServerRelease) ( void *ppv );
  145. CStub( IAsync *pServer );
  146. private:
  147. DWORD _iRef;
  148. IAsync *_pAsync;
  149. };
  150. class CPSFactory : public IPSFactoryBuffer
  151. {
  152. public:
  153. STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
  154. STDMETHOD_(ULONG,AddRef) ( void );
  155. STDMETHOD_(ULONG,Release) ( void );
  156. STDMETHOD (CreateProxy) ( IUnknown *pUnkOuter,
  157. REFIID riid,
  158. IRpcProxyBuffer **ppProxy,
  159. void **ppv );
  160. STDMETHOD (CreateStub) ( REFIID riid,
  161. IUnknown *pUnkServer,
  162. IRpcStubBuffer **ppStub );
  163. CPSFactory();
  164. private:
  165. DWORD _iRef;
  166. };
  167. const IID IID_IAsync = {0x70000000,0x76d7,0x11Cf,{0x9a,0xf1,0x00,0x20,0xaf,0x6e,0x72,0xf4}};
  168. //+-------------------------------------------------------------------------
  169. //
  170. // Function: DllCanUnloadNow
  171. //
  172. // Synopsis: Dll entry point
  173. //
  174. //--------------------------------------------------------------------------
  175. STDAPI DllCanUnloadNow()
  176. {
  177. return S_FALSE;
  178. }
  179. //+-------------------------------------------------------------------------
  180. //
  181. // Function: DllGetClassObject
  182. //
  183. // Synopsis: Dll entry point
  184. //
  185. //--------------------------------------------------------------------------
  186. STDAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv)
  187. {
  188. CPSFactory *pFactory;
  189. // Check for IPSFactoryBuffer
  190. if (clsid == IID_IAsync && iid == IID_IPSFactoryBuffer)
  191. {
  192. pFactory = new CPSFactory();
  193. *ppv = pFactory;
  194. if (pFactory == NULL)
  195. return E_OUTOFMEMORY;
  196. else
  197. return S_OK;
  198. }
  199. return E_NOTIMPL;
  200. }
  201. //+-------------------------------------------------------------------
  202. //
  203. // Member: CPSFactory::AddRef, public
  204. //
  205. // Synopsis: Adds a reference to an interface
  206. //
  207. //--------------------------------------------------------------------
  208. STDMETHODIMP_(ULONG) CPSFactory::AddRef()
  209. {
  210. InterlockedIncrement( (long *) &_iRef );
  211. return _iRef;
  212. }
  213. //+-------------------------------------------------------------------
  214. //
  215. // Member: CPSFactory::CPSFactory
  216. //
  217. // Synopsis: Constructor
  218. //
  219. //--------------------------------------------------------------------
  220. CPSFactory::CPSFactory()
  221. {
  222. _iRef = 1;
  223. }
  224. //+-------------------------------------------------------------------
  225. //
  226. // Member: CPSFactory::CreateProxy, public
  227. //
  228. // Synopsis: Create an instance of the requested proxy
  229. //
  230. //--------------------------------------------------------------------
  231. STDMETHODIMP CPSFactory::CreateProxy( IUnknown *pUnkOuter, REFIID riid,
  232. IRpcProxyBuffer **ppProxy, void **ppv )
  233. {
  234. CProxy *pProxy;
  235. // Validate the parameters.
  236. if (ppv == NULL || riid != IID_IAsync || pUnkOuter == NULL)
  237. return E_INVALIDARG;
  238. *ppv = NULL;
  239. // Create a proxy.
  240. pProxy = new CProxy( pUnkOuter );
  241. if (pProxy == NULL)
  242. return E_OUTOFMEMORY;
  243. *ppProxy = pProxy;
  244. *ppv = &pProxy->_Async;
  245. return S_OK;
  246. }
  247. //+-------------------------------------------------------------------
  248. //
  249. // Member: CPSFactory::CreateStub, public
  250. //
  251. // Synopsis: Create an instance of the requested stub
  252. //
  253. //--------------------------------------------------------------------
  254. STDMETHODIMP CPSFactory::CreateStub( REFIID riid, IUnknown *pUnkServer,
  255. IRpcStubBuffer **ppStub )
  256. {
  257. IAsync *pAsync;
  258. CStub *pStub;
  259. HRESULT hr;
  260. // Validate the parameters.
  261. if (riid != IID_IAsync)
  262. return E_INVALIDARG;
  263. // Get the IAsync interface.
  264. hr = pUnkServer->QueryInterface( IID_IAsync, (void **) &pAsync );
  265. if (FAILED(hr))
  266. return hr;
  267. // Create a stub.
  268. pStub = new CStub( pAsync );
  269. pAsync->Release();
  270. if (pStub == NULL)
  271. return E_OUTOFMEMORY;
  272. *ppStub = pStub;
  273. return S_OK;
  274. }
  275. //+-------------------------------------------------------------------
  276. //
  277. // Member: CPSFactory::QueryInterface, public
  278. //
  279. // Synopsis: Returns a pointer to the requested interface.
  280. //
  281. //--------------------------------------------------------------------
  282. STDMETHODIMP CPSFactory::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
  283. {
  284. if (IsEqualIID(riid, IID_IUnknown) ||
  285. IsEqualIID(riid, IID_IPSFactoryBuffer))
  286. *ppvObj = (IPSFactoryBuffer *) this;
  287. else
  288. {
  289. *ppvObj = NULL;
  290. return E_NOINTERFACE;
  291. }
  292. AddRef();
  293. return S_OK;
  294. }
  295. //+-------------------------------------------------------------------
  296. //
  297. // Member: CPSFactory::Release, public
  298. //
  299. // Synopsis: Releases an interface
  300. //
  301. //--------------------------------------------------------------------
  302. STDMETHODIMP_(ULONG) CPSFactory::Release()
  303. {
  304. ULONG lRef = _iRef - 1;
  305. if (InterlockedDecrement( (long*) &_iRef ) == 0)
  306. {
  307. delete this;
  308. return 0;
  309. }
  310. else
  311. return lRef;
  312. }
  313. //+-------------------------------------------------------------------
  314. //
  315. // Member: CProxy::AddRef, public
  316. //
  317. // Synopsis: Adds a reference to an interface
  318. //
  319. //--------------------------------------------------------------------
  320. STDMETHODIMP_(ULONG) CProxy::AddRef()
  321. {
  322. InterlockedIncrement( (long *) &_iRef );
  323. return _iRef;
  324. }
  325. //+-------------------------------------------------------------------
  326. //
  327. // Member: CProxy::Connect, public
  328. //
  329. // Synopsis: Connects the proxy to a channel
  330. //
  331. //--------------------------------------------------------------------
  332. STDMETHODIMP CProxy::Connect( IRpcChannelBuffer *pChannel )
  333. {
  334. HRESULT hr;
  335. // Get the other channel buffer interface.
  336. hr = pChannel->QueryInterface( IID_IRpcChannelBuffer3, (void **) &_pChannel );
  337. return hr;
  338. }
  339. //+-------------------------------------------------------------------
  340. //
  341. // Member: CProxy::Disconnect, public
  342. //
  343. // Synopsis: Disconnects the proxy from a channel
  344. //
  345. //--------------------------------------------------------------------
  346. STDMETHODIMP_(void) CProxy::Disconnect()
  347. {
  348. if (_pChannel != NULL)
  349. {
  350. _pChannel->Release();
  351. _pChannel = NULL;
  352. }
  353. }
  354. //+-------------------------------------------------------------------
  355. //
  356. // Member: CProxy::CProxy, public
  357. //
  358. // Synopsis: Constructor
  359. //
  360. //--------------------------------------------------------------------
  361. CProxy::CProxy( IUnknown *pControl ) :
  362. _Async( pControl, this )
  363. {
  364. _iRef = 1;
  365. _pChannel = NULL;
  366. }
  367. //+-------------------------------------------------------------------
  368. //
  369. // Member: CProxy::GetAsyncManager, public
  370. //
  371. // Synopsis: Creates a proxy completion object
  372. //
  373. //--------------------------------------------------------------------
  374. STDMETHODIMP CProxy::GetAsyncManager( REFIID riid,
  375. IUnknown *pOuter,
  376. DWORD dwFlags,
  377. IUnknown **ppInner,
  378. IAsyncManager **ppComplete )
  379. {
  380. HRESULT hr;
  381. CProxyComplete *pComplete;
  382. // Create a new proxy completion object.
  383. pComplete = new CProxyComplete( pOuter, FALSE, &hr );
  384. if (pComplete == NULL)
  385. return E_OUTOFMEMORY;
  386. else if (FAILED(hr))
  387. {
  388. delete pComplete;
  389. return hr;
  390. }
  391. // Get IAsyncManager.
  392. *ppComplete = (IAsyncManager *) pComplete;
  393. *ppInner = (IUnknown *) &pComplete->_Inner;
  394. pComplete->AddRef();
  395. return S_OK;
  396. }
  397. //+-------------------------------------------------------------------
  398. //
  399. // Member: CProxy::QueryInterface, public
  400. //
  401. // Synopsis: Returns a pointer to the requested interface.
  402. //
  403. //--------------------------------------------------------------------
  404. STDMETHODIMP CProxy::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
  405. {
  406. if (IsEqualIID(riid, IID_IUnknown) ||
  407. IsEqualIID(riid, IID_IRpcProxyBuffer))
  408. *ppvObj = (IRpcProxyBuffer *) this;
  409. else if (IsEqualIID(riid, IID_IAsyncSetup))
  410. *ppvObj = (IAsyncSetup *) this;
  411. else
  412. {
  413. *ppvObj = NULL;
  414. return E_NOINTERFACE;
  415. }
  416. AddRef();
  417. return S_OK;
  418. }
  419. //+-------------------------------------------------------------------
  420. //
  421. // Member: CProxy::Release, public
  422. //
  423. // Synopsis: Releases an interface
  424. //
  425. //--------------------------------------------------------------------
  426. STDMETHODIMP_(ULONG) CProxy::Release()
  427. {
  428. ULONG lRef = _iRef - 1;
  429. if (InterlockedDecrement( (long*) &_iRef ) == 0)
  430. {
  431. delete this;
  432. return 0;
  433. }
  434. else
  435. return lRef;
  436. }
  437. //+-------------------------------------------------------------------
  438. //
  439. // Member: CAsync::AddRef, public
  440. //
  441. // Synopsis: Adds a reference to an interface
  442. //
  443. //--------------------------------------------------------------------
  444. STDMETHODIMP_(ULONG) CAsync::AddRef()
  445. {
  446. return _pControl->AddRef();
  447. }
  448. //+-------------------------------------------------------------------
  449. //
  450. // Member: CAsync::Async, public
  451. //
  452. // Synopsis: Marshal parameters for an async call.
  453. //
  454. //--------------------------------------------------------------------
  455. STDMETHODIMP CAsync::Async( IAsyncManager **ppCall, BOOL bLate,
  456. BOOL bSleep, BOOL bFail )
  457. {
  458. HRESULT hr;
  459. CProxyComplete *pComplete;
  460. BOOL fFreeComplete = FALSE;
  461. DWORD lIgnore;
  462. SAsyncData *pData;
  463. DWORD fFlags = RPC_BUFFER_ASYNC;
  464. // If there is no async complete, create one. Aggregate in the
  465. // correct ISignal.
  466. if (ppCall == NULL || *ppCall == NULL)
  467. {
  468. // Initialize the out parameters.
  469. if (ppCall != NULL)
  470. *ppCall = NULL;
  471. else
  472. fFlags |= RPCFLG_AUTO_COMPLETE;
  473. // Create a new proxy complete object.
  474. pComplete = new CProxyComplete( NULL, ppCall == NULL, &hr );
  475. if (pComplete == NULL)
  476. return E_OUTOFMEMORY;
  477. if (FAILED(hr))
  478. {
  479. delete pComplete;
  480. return hr;
  481. }
  482. fFreeComplete = TRUE;
  483. if (ppCall != NULL)
  484. *ppCall = pComplete;
  485. }
  486. // Otherwise the passed in completion object should be one of ours.
  487. else
  488. {
  489. pComplete = (CProxyComplete *) *ppCall;
  490. if (pComplete->_pChannel != NULL)
  491. return E_FAIL;
  492. }
  493. // Get a buffer.
  494. memset( &pComplete->_Message, 0, sizeof(pComplete->_Message) );
  495. pComplete->_Message.cbBuffer = sizeof( SAsyncData );
  496. pComplete->_Message.dataRepresentation = 0x10;
  497. pComplete->_Message.iMethod = 3;
  498. pComplete->_Message.rpcFlags = fFlags;
  499. hr = _pProxy->_pChannel->GetBuffer( &pComplete->_Message, IID_IAsync );
  500. if (FAILED(hr)) goto Done;
  501. // Register async.
  502. hr = _pProxy->_pChannel->RegisterAsync( &pComplete->_Message,
  503. (IAsyncManager *) pComplete );
  504. if (FAILED(hr))
  505. {
  506. // Register async shouldn't fail.
  507. DebugBreak();
  508. }
  509. // Fill in the buffer.
  510. pData = (SAsyncData *) pComplete->_Message.Buffer;
  511. pData->bLate = bLate;
  512. pData->bSleep = bSleep;
  513. pData->bFail = bFail;
  514. // Send the buffer.
  515. pComplete->_pChannel = _pProxy->_pChannel;
  516. _pProxy->_pChannel->AddRef();
  517. hr = _pProxy->_pChannel->Send( &pComplete->_Message, &lIgnore );
  518. Done:
  519. if (FAILED(hr))
  520. {
  521. if (pComplete->_pChannel != NULL)
  522. {
  523. pComplete->_pChannel = NULL;
  524. _pProxy->_pChannel->Release();
  525. }
  526. if (fFreeComplete)
  527. {
  528. delete pComplete;
  529. if (ppCall != NULL)
  530. *ppCall = NULL;
  531. }
  532. }
  533. return hr;
  534. }
  535. //+-------------------------------------------------------------------
  536. //
  537. // Member: CAsync::CAsync, public
  538. //
  539. // Synopsis: Constructor
  540. //
  541. //--------------------------------------------------------------------
  542. CAsync::CAsync( IUnknown *pControl, CProxy *pProxy )
  543. {
  544. _pControl = pControl;
  545. _pProxy = pProxy;
  546. _pControl->AddRef();
  547. }
  548. //+-------------------------------------------------------------------
  549. //
  550. // Member: CAsync::~CAsync, public
  551. //
  552. // Synopsis: Destructor
  553. //
  554. //--------------------------------------------------------------------
  555. CAsync::~CAsync()
  556. {
  557. _pControl->Release();
  558. }
  559. //+-------------------------------------------------------------------
  560. //
  561. // Member: CAsync::QueryInterface, public
  562. //
  563. // Synopsis: Returns a pointer to the requested interface.
  564. //
  565. //--------------------------------------------------------------------
  566. STDMETHODIMP CAsync::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
  567. {
  568. return _pControl->QueryInterface( riid, ppvObj );
  569. }
  570. //+-------------------------------------------------------------------
  571. //
  572. // Member: CAsync::RecurseAsync, public
  573. //
  574. // Synopsis: Marshal parameters for a RecurseAsync call.
  575. //
  576. //--------------------------------------------------------------------
  577. STDMETHODIMP CAsync::RecurseAsync( IAsyncManager **ppCall, IAsync *pCallback,
  578. DWORD depth )
  579. {
  580. HRESULT hr;
  581. CProxyComplete *pComplete;
  582. BOOL fFreeComplete = FALSE;
  583. DWORD lIgnore;
  584. HANDLE memory = NULL;
  585. ULONG size;
  586. IStream *pStream = NULL;
  587. LARGE_INTEGER pos;
  588. DWORD *pBuffer;
  589. DWORD dwDestCtx;
  590. VOID *pvDestCtx = NULL;
  591. BOOL fFlags = RPC_BUFFER_ASYNC;
  592. // If there is no async complete, create one. Aggregate in the
  593. // correct ISignal.
  594. if (ppCall == NULL || *ppCall == NULL)
  595. {
  596. // Initialize the out parameters.
  597. if (ppCall != NULL)
  598. *ppCall = NULL;
  599. else
  600. fFlags |= RPCFLG_AUTO_COMPLETE;
  601. // Create a new proxy complete object.
  602. pComplete = new CProxyComplete( NULL, ppCall == NULL, &hr );
  603. if (pComplete == NULL)
  604. return E_OUTOFMEMORY;
  605. if (FAILED(hr))
  606. {
  607. delete pComplete;
  608. return hr;
  609. }
  610. fFreeComplete = TRUE;
  611. if (ppCall != NULL)
  612. *ppCall = pComplete;
  613. }
  614. // Otherwise the passed in completion object should be one of ours.
  615. else
  616. {
  617. pComplete = (CProxyComplete *) *ppCall;
  618. if (pComplete->_pChannel != NULL)
  619. return E_FAIL;
  620. }
  621. // Get the destination context.
  622. hr = _pProxy->_pChannel->GetDestCtx( &dwDestCtx, &pvDestCtx );
  623. // Find out how much memory to allocate.
  624. hr = CoGetMarshalSizeMax( &size, IID_IAsync, pCallback, dwDestCtx,
  625. pvDestCtx, MSHLFLAGS_NORMAL );
  626. if (FAILED(hr))
  627. goto Done;
  628. // Allocate memory.
  629. memory = GlobalAlloc( GMEM_FIXED, size );
  630. if (memory == NULL)
  631. {
  632. hr = E_OUTOFMEMORY;
  633. goto Done;
  634. }
  635. // Create a stream.
  636. hr = CreateStreamOnHGlobal( memory, TRUE, &pStream );
  637. if (FAILED(hr))
  638. goto Done;
  639. memory = NULL;
  640. // Marshal the object.
  641. hr = CoMarshalInterface( pStream, IID_IAsync, pCallback, dwDestCtx,
  642. pvDestCtx, MSHLFLAGS_NORMAL );
  643. if (FAILED(hr))
  644. goto Done;
  645. // Seek back to the start of the stream.
  646. pos.QuadPart = 0;
  647. hr = pStream->Seek( pos, STREAM_SEEK_SET, NULL );
  648. if (FAILED(hr))
  649. goto Done;
  650. // Get a buffer.
  651. memset( &pComplete->_Message, 0, sizeof(pComplete->_Message) );
  652. pComplete->_Message.cbBuffer = sizeof(depth) + size;
  653. pComplete->_Message.dataRepresentation = 0x10;
  654. pComplete->_Message.iMethod = 4;
  655. pComplete->_Message.rpcFlags = fFlags;
  656. hr = _pProxy->_pChannel->GetBuffer( &pComplete->_Message, IID_IAsync );
  657. if (FAILED(hr)) goto Done;
  658. // Register async.
  659. hr = _pProxy->_pChannel->RegisterAsync( &pComplete->_Message,
  660. (IAsyncManager *) pComplete );
  661. if (FAILED(hr))
  662. {
  663. // Register async shouldn't fail.
  664. DebugBreak();
  665. }
  666. // Fill in the buffer.
  667. pBuffer = (DWORD *) pComplete->_Message.Buffer;
  668. *pBuffer = depth;
  669. pBuffer += 1;
  670. hr = pStream->Read( (void *) pBuffer, size, NULL );
  671. if (FAILED(hr))
  672. goto Done;
  673. // Send the buffer.
  674. pComplete->_pChannel = _pProxy->_pChannel;
  675. _pProxy->_pChannel->AddRef();
  676. hr = _pProxy->_pChannel->Send( &pComplete->_Message, &lIgnore );
  677. Done:
  678. if (pStream != NULL)
  679. pStream->Release();
  680. if (memory != NULL)
  681. GlobalFree( memory );
  682. if (FAILED(hr))
  683. {
  684. if (pComplete->_pChannel != NULL)
  685. {
  686. pComplete->_pChannel = NULL;
  687. _pProxy->_pChannel->Release();
  688. }
  689. if (fFreeComplete)
  690. {
  691. delete pComplete;
  692. if (ppCall != NULL)
  693. *ppCall = NULL;
  694. }
  695. }
  696. return hr;
  697. }
  698. //+-------------------------------------------------------------------
  699. //
  700. // Member: CAsync::Release, public
  701. //
  702. // Synopsis: Releases an interface
  703. //
  704. //--------------------------------------------------------------------
  705. STDMETHODIMP_(ULONG) CAsync::Release()
  706. {
  707. return _pControl->Release();
  708. }
  709. //+-------------------------------------------------------------------
  710. //
  711. // Member: CPCInnerUnknown::AddRef, public
  712. //
  713. // Synopsis: Adds a reference to an interface
  714. //
  715. //--------------------------------------------------------------------
  716. STDMETHODIMP_(ULONG) CPCInnerUnknown::AddRef()
  717. {
  718. InterlockedIncrement( (long *) &_iRef );
  719. return _iRef;
  720. }
  721. //+-------------------------------------------------------------------
  722. //
  723. // Member: CPCInnerUnknown::CPCInnerUnknown
  724. //
  725. // Synopsis: Constructor
  726. //
  727. //--------------------------------------------------------------------
  728. CPCInnerUnknown::CPCInnerUnknown( CProxyComplete *pParent )
  729. {
  730. _iRef = 1;
  731. _pParent = pParent;
  732. }
  733. //+-------------------------------------------------------------------
  734. //
  735. // Member: CPCInnerUnknown::QueryInterface, public
  736. //
  737. // Synopsis: Returns a pointer to the requested interface.
  738. //
  739. //--------------------------------------------------------------------
  740. STDMETHODIMP CPCInnerUnknown::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
  741. {
  742. IUnknown *pUnk;
  743. if (IsEqualIID(riid, IID_IUnknown))
  744. pUnk = (IUnknown *) this;
  745. else if (IsEqualIID(riid, IID_IAsyncManager))
  746. pUnk = (IAsyncManager *) _pParent;
  747. else if (IsEqualIID(riid, IID_ICancelMethodCalls))
  748. pUnk = (ICancelMethodCalls *) _pParent;
  749. else if (_pParent->_pSyncInner != NULL)
  750. return _pParent->_pSyncInner->QueryInterface( riid, ppvObj );
  751. pUnk->AddRef();
  752. *ppvObj = pUnk;
  753. return S_OK;
  754. }
  755. //+-------------------------------------------------------------------
  756. //
  757. // Member: CPCInnerUnknown::Release, public
  758. //
  759. // Synopsis: Releases an interface
  760. //
  761. //--------------------------------------------------------------------
  762. STDMETHODIMP_(ULONG) CPCInnerUnknown::Release()
  763. {
  764. ULONG lRef = _iRef - 1;
  765. if (InterlockedDecrement( (long*) &_iRef ) == 0)
  766. {
  767. delete _pParent;
  768. return 0;
  769. }
  770. else
  771. return lRef;
  772. }
  773. //+-------------------------------------------------------------------
  774. //
  775. // Member: CProxyComplete::AddRef, public
  776. //
  777. // Synopsis: Adds a reference to an interface
  778. //
  779. //--------------------------------------------------------------------
  780. STDMETHODIMP_(ULONG) CProxyComplete::AddRef()
  781. {
  782. return _pControl->AddRef();
  783. }
  784. //+-------------------------------------------------------------------
  785. //
  786. // Member: CProxyComplete::Cancel, public
  787. //
  788. // Synopsis: Forward cancel to the channel
  789. //
  790. //--------------------------------------------------------------------
  791. STDMETHODIMP CProxyComplete::Cancel()
  792. {
  793. HRESULT hr;
  794. if (_pChannel == NULL)
  795. return RPC_E_CALL_COMPLETE;
  796. hr = _pChannel->Cancel( &_Message );
  797. return hr;
  798. }
  799. //+-------------------------------------------------------------------
  800. //
  801. // Member: CProxyComplete::CompleteCall, public
  802. //
  803. // Synopsis: Receive the reply and parse the out parameters
  804. //
  805. //--------------------------------------------------------------------
  806. STDMETHODIMP CProxyComplete::CompleteCall( HRESULT result )
  807. {
  808. HRESULT hr;
  809. HRESULT temp;
  810. DWORD lIgnore;
  811. // Fail if there is no call.
  812. if (_pChannel == NULL)
  813. return RPC_E_CALL_COMPLETE;
  814. // Call receive.
  815. hr = _pChannel->Receive( &_Message, 0, &lIgnore );
  816. if (hr == RPC_S_CALLPENDING || hr == 0x15)
  817. return hr;
  818. if (FAILED(hr))
  819. goto Done;
  820. // Unmarshal the results.
  821. if (_Message.cbBuffer < sizeof(HRESULT))
  822. {
  823. hr = RPC_E_INVALID_DATAPACKET;
  824. goto Done;
  825. }
  826. temp = *((HRESULT *) _Message.Buffer);
  827. // Free the buffer.
  828. hr = _pChannel->FreeBuffer( &_Message );
  829. if (SUCCEEDED(hr))
  830. hr = temp;
  831. // If auto complete, self release.
  832. Done:
  833. _pChannel->Release();
  834. _pChannel = NULL;
  835. if (_fAutoComplete)
  836. _Inner.Release();
  837. return hr;
  838. }
  839. //+-------------------------------------------------------------------
  840. //
  841. // Member: CProxyComplete::CProxyComplete
  842. //
  843. // Synopsis: Constructor
  844. //
  845. //--------------------------------------------------------------------
  846. CProxyComplete::CProxyComplete( IUnknown *pControl, BOOL fAutoComplete,
  847. HRESULT *hr) :
  848. _Inner( this )
  849. {
  850. // Save the easy fields
  851. _pSyncInner = NULL;
  852. _fAutoComplete = fAutoComplete;
  853. _pChannel = NULL;
  854. if (pControl == NULL)
  855. _pControl = &_Inner;
  856. else
  857. {
  858. _pControl = pControl;
  859. _pControl->AddRef();
  860. }
  861. // Aggregate in an ISynchronize.
  862. if (fAutoComplete)
  863. *hr = CoCreateInstance( CLSID_Synchronize_AutoComplete,
  864. &_Inner,
  865. CLSCTX_INPROC_SERVER, IID_IUnknown,
  866. (void **) &_pSyncInner );
  867. else
  868. *hr = CoCreateInstance( CLSID_Synchronize_ManualResetEvent,
  869. &_Inner,
  870. CLSCTX_INPROC_SERVER, IID_IUnknown,
  871. (void **) &_pSyncInner );
  872. if (SUCCEEDED(*hr))
  873. {
  874. // Aggregation requires some weird reference counting.
  875. Release();
  876. }
  877. }
  878. //+-------------------------------------------------------------------
  879. //
  880. // Member: CProxyComplete::~CProxyComplete
  881. //
  882. // Synopsis: Destructor
  883. //
  884. //--------------------------------------------------------------------
  885. CProxyComplete::~CProxyComplete()
  886. {
  887. // Make sure we don't get deleted twice.
  888. _Inner._iRef = 0xdead;
  889. if (_pSyncInner != NULL)
  890. _pSyncInner->Release();
  891. if (_pChannel != NULL)
  892. _pChannel->Release();
  893. if (_pControl != &_Inner)
  894. _pControl->Release();
  895. }
  896. //+-------------------------------------------------------------------
  897. //
  898. // Member: CProxyComplete::GetCallContext, public
  899. //
  900. // Synopsis: Calls GetCallContext on the channel
  901. //
  902. //--------------------------------------------------------------------
  903. STDMETHODIMP CProxyComplete::GetCallContext( REFIID riid, void **pInterface )
  904. {
  905. if (_pChannel == NULL)
  906. return RPC_E_CALL_COMPLETE;
  907. return _pChannel->GetCallContext( &_Message, riid, pInterface );
  908. }
  909. //+-------------------------------------------------------------------
  910. //
  911. // Member: CProxyComplete::GetState, public
  912. //
  913. // Synopsis: Returns a pointer to the requested interface.
  914. //
  915. //--------------------------------------------------------------------
  916. STDMETHODIMP CProxyComplete::GetState( DWORD *pState )
  917. {
  918. if (_pChannel == NULL)
  919. return RPC_E_CALL_COMPLETE;
  920. return _pChannel->GetState( &_Message, pState );
  921. }
  922. //+-------------------------------------------------------------------
  923. //
  924. // Member: CProxyComplete::QueryInterface, public
  925. //
  926. // Synopsis: Returns a pointer to the requested interface.
  927. //
  928. //--------------------------------------------------------------------
  929. STDMETHODIMP CProxyComplete::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
  930. {
  931. return _pControl->QueryInterface( riid, ppvObj );
  932. }
  933. //+-------------------------------------------------------------------
  934. //
  935. // Member: CProxyComplete::Release, public
  936. //
  937. // Synopsis: Releases an interface
  938. //
  939. //--------------------------------------------------------------------
  940. STDMETHODIMP_(ULONG) CProxyComplete::Release()
  941. {
  942. return _pControl->Release();
  943. }
  944. //+-------------------------------------------------------------------
  945. //
  946. // Member: CProxyComplete::TestCancel, public
  947. //
  948. // Synopsis: Is call canceled?
  949. //
  950. //--------------------------------------------------------------------
  951. STDMETHODIMP CProxyComplete::TestCancel()
  952. {
  953. HRESULT hr;
  954. DWORD state;
  955. // The call is complete is already cleaned up.
  956. if (_pChannel == NULL)
  957. return RPC_E_CALL_COMPLETE;
  958. // Ask the channel about the state of the call.
  959. hr = _pChannel->GetState( &_Message, &state );
  960. if (FAILED(hr))
  961. return hr;
  962. // Convert the flags to error codes.
  963. if (state & DCOM_CALL_CANCELED)
  964. return RPC_E_CALL_CANCELED;
  965. else if (state & DCOM_CALL_COMPLETE)
  966. return RPC_E_CALL_COMPLETE;
  967. else
  968. return RPC_S_CALLPENDING;
  969. }
  970. //+-------------------------------------------------------------------
  971. //
  972. // Member: CStub::AddRef, public
  973. //
  974. // Synopsis: Adds a reference to an interface
  975. //
  976. //--------------------------------------------------------------------
  977. STDMETHODIMP_(ULONG) CStub::AddRef()
  978. {
  979. InterlockedIncrement( (long *) &_iRef );
  980. return _iRef;
  981. }
  982. //+-------------------------------------------------------------------
  983. //
  984. // Member: CStub::Connect
  985. //
  986. // Synopsis: Connect the stub to the server
  987. //
  988. //--------------------------------------------------------------------
  989. STDMETHODIMP CStub::Connect( IUnknown *pServer )
  990. {
  991. // Get the IAsync interface.
  992. return pServer->QueryInterface( IID_IAsync, (void **) &_pAsync );
  993. }
  994. //+-------------------------------------------------------------------
  995. //
  996. // Member: CStub::CountRefs
  997. //
  998. // Synopsis: Unused
  999. //
  1000. //--------------------------------------------------------------------
  1001. STDMETHODIMP_(ULONG) CStub::CountRefs()
  1002. {
  1003. return 0;
  1004. }
  1005. //+-------------------------------------------------------------------
  1006. //
  1007. // Member: CStub::CStub
  1008. //
  1009. // Synopsis: Constructor
  1010. //
  1011. //--------------------------------------------------------------------
  1012. CStub::CStub( IAsync *pAsync )
  1013. {
  1014. _iRef = 1;
  1015. _pAsync = pAsync;
  1016. pAsync->AddRef();
  1017. }
  1018. //+-------------------------------------------------------------------
  1019. //
  1020. // Member: CStub::DebugServerQueryInterface
  1021. //
  1022. // Synopsis: Returns a pointer to the server without AddRefing.
  1023. //
  1024. //--------------------------------------------------------------------
  1025. STDMETHODIMP CStub::DebugServerQueryInterface( void **ppv )
  1026. {
  1027. *ppv = _pAsync;
  1028. return S_OK;
  1029. }
  1030. //+-------------------------------------------------------------------
  1031. //
  1032. // Member: CStub::DebugServerRelease
  1033. //
  1034. // Synopsis: Paired with DebugServerQueryInterface. Does nothing.
  1035. //
  1036. //--------------------------------------------------------------------
  1037. STDMETHODIMP_(void) CStub::DebugServerRelease( void *ppv )
  1038. {
  1039. }
  1040. //+-------------------------------------------------------------------
  1041. //
  1042. // Member: CStub::Disconnect
  1043. //
  1044. // Synopsis: Releases the server.
  1045. //
  1046. //--------------------------------------------------------------------
  1047. STDMETHODIMP_(void) CStub::Disconnect()
  1048. {
  1049. if (_pAsync != NULL)
  1050. {
  1051. _pAsync->Release();
  1052. _pAsync = NULL;
  1053. }
  1054. }
  1055. //+-------------------------------------------------------------------
  1056. //
  1057. // Member: CStub::Invoke
  1058. //
  1059. // Synopsis: Unmarshals the parameters for IAsync and calls it.
  1060. // Creates a completion stub.
  1061. //
  1062. //--------------------------------------------------------------------
  1063. STDMETHODIMP CStub::Invoke( RPCOLEMESSAGE *pMessage,
  1064. IRpcChannelBuffer *pChannel )
  1065. {
  1066. IRpcChannelBuffer3 *pChannel2 = NULL;
  1067. CStubComplete *pComplete;
  1068. HRESULT hr = S_OK;
  1069. SAsyncData *pData;
  1070. IAsync *pCallback = NULL;
  1071. DWORD depth;
  1072. DWORD *pBuffer;
  1073. HANDLE memory = NULL;
  1074. IStream *pStream = NULL;
  1075. LARGE_INTEGER pos;
  1076. // Get channel buffer 2.
  1077. hr = pChannel->QueryInterface( IID_IRpcChannelBuffer3, (void **)
  1078. &pChannel2 );
  1079. if (FAILED(hr))
  1080. return hr;
  1081. // Create completion stub.
  1082. pComplete = new CStubComplete( NULL, pChannel2, pMessage, &hr );
  1083. if (pComplete == NULL)
  1084. {
  1085. pChannel2->Release();
  1086. return E_OUTOFMEMORY;
  1087. }
  1088. if (FAILED(hr))
  1089. {
  1090. delete pComplete;
  1091. pChannel2->Release();
  1092. return hr;
  1093. }
  1094. // Register async.
  1095. hr = pComplete->_pChannel->RegisterAsync( &pComplete->_Message,
  1096. (IAsyncManager *) pComplete );
  1097. if (FAILED(hr))
  1098. DebugBreak();
  1099. // Unmarshal data for a call to Async.
  1100. if (pMessage->iMethod == 3)
  1101. {
  1102. if (pMessage->cbBuffer < sizeof(SAsyncData))
  1103. {
  1104. hr = RPC_E_INVALID_DATAPACKET;
  1105. goto Done;
  1106. }
  1107. pData = (SAsyncData *) pMessage->Buffer;
  1108. }
  1109. // Unmarshal data for a call to RecurseAsync.
  1110. else if (pMessage->iMethod == 4)
  1111. {
  1112. /*
  1113. if (un pitic)
  1114. {
  1115. mic mic mic;
  1116. }
  1117. */
  1118. // Get the depth.
  1119. if (pMessage->cbBuffer < sizeof(DWORD))
  1120. {
  1121. hr = RPC_E_INVALID_DATAPACKET;
  1122. goto Done;
  1123. }
  1124. pBuffer = (DWORD *) pMessage->Buffer;
  1125. depth = *pBuffer;
  1126. pBuffer += 1;
  1127. // Allocate memory.
  1128. memory = GlobalAlloc( GMEM_FIXED, pMessage->cbBuffer - sizeof(DWORD) );
  1129. if (memory == NULL)
  1130. goto Done;
  1131. // Create a stream.
  1132. hr = CreateStreamOnHGlobal( memory, TRUE, &pStream );
  1133. if (FAILED(hr))
  1134. goto Done;
  1135. memory = NULL;
  1136. // Copy the data into the stream.
  1137. hr = pStream->Write( (void *) pBuffer,
  1138. pMessage->cbBuffer - sizeof(DWORD), NULL );
  1139. if (FAILED(hr))
  1140. goto Done;
  1141. // Seek back to the start of the stream.
  1142. pos.QuadPart = 0;
  1143. hr = pStream->Seek( pos, STREAM_SEEK_SET, NULL );
  1144. if (FAILED(hr))
  1145. goto Done;
  1146. // Unmarshal the object.
  1147. hr = CoUnmarshalInterface( pStream, IID_IAsync,
  1148. (void **) &pCallback );
  1149. if (FAILED(hr))
  1150. goto Done;
  1151. }
  1152. // Bad packet.
  1153. else
  1154. {
  1155. hr = RPC_E_INVALID_DATAPACKET;
  1156. goto Done;
  1157. }
  1158. // Call server.
  1159. if (pMessage->iMethod == 3)
  1160. _pAsync->Async( (IAsyncManager **) &pComplete, pData->bLate,
  1161. pData->bSleep, pData->bFail );
  1162. else
  1163. _pAsync->RecurseAsync( (IAsyncManager **) &pComplete, pCallback,
  1164. depth );
  1165. pComplete->Release();
  1166. // Cleanup
  1167. Done:
  1168. if (pStream != NULL)
  1169. pStream->Release();
  1170. if (memory != NULL)
  1171. GlobalFree( memory );
  1172. if (pCallback != NULL)
  1173. pCallback->Release();
  1174. if (FAILED(hr))
  1175. pChannel2->Cancel( &pComplete->_Message );
  1176. pChannel2->Release();
  1177. return hr;
  1178. }
  1179. //+-------------------------------------------------------------------
  1180. //
  1181. // Member: CStub::IsIIDSupported
  1182. //
  1183. // Synopsis: Indicates which IIDs this stub can unmarshal.
  1184. //
  1185. //--------------------------------------------------------------------
  1186. STDMETHODIMP_(IRpcStubBuffer *) CStub::IsIIDSupported( REFIID riid )
  1187. {
  1188. return NULL;
  1189. }
  1190. //+-------------------------------------------------------------------
  1191. //
  1192. // Member: CStub::QueryInterface, public
  1193. //
  1194. // Synopsis: Returns a pointer to the requested interface.
  1195. //
  1196. //--------------------------------------------------------------------
  1197. STDMETHODIMP CStub::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
  1198. {
  1199. if (IsEqualIID(riid, IID_IUnknown) ||
  1200. IsEqualIID(riid, IID_IRpcStubBuffer))
  1201. *ppvObj = (IRpcStubBuffer *) this;
  1202. else
  1203. {
  1204. *ppvObj = NULL;
  1205. return E_NOINTERFACE;
  1206. }
  1207. AddRef();
  1208. return S_OK;
  1209. }
  1210. //+-------------------------------------------------------------------
  1211. //
  1212. // Member: CStub::Release, public
  1213. //
  1214. // Synopsis: Releases an interface
  1215. //
  1216. //--------------------------------------------------------------------
  1217. STDMETHODIMP_(ULONG) CStub::Release()
  1218. {
  1219. ULONG lRef = _iRef - 1;
  1220. if (InterlockedDecrement( (long*) &_iRef ) == 0)
  1221. {
  1222. delete this;
  1223. return 0;
  1224. }
  1225. else
  1226. return lRef;
  1227. }
  1228. //+-------------------------------------------------------------------
  1229. //
  1230. // Member: CSCInnerUnknown::AddRef, public
  1231. //
  1232. // Synopsis: Adds a reference to an interface
  1233. //
  1234. //--------------------------------------------------------------------
  1235. STDMETHODIMP_(ULONG) CSCInnerUnknown::AddRef()
  1236. {
  1237. InterlockedIncrement( (long *) &_iRef );
  1238. return _iRef;
  1239. }
  1240. //+-------------------------------------------------------------------
  1241. //
  1242. // Member: CSCInnerUnknown::CSCInnerUnknown
  1243. //
  1244. // Synopsis: Constructor
  1245. //
  1246. //--------------------------------------------------------------------
  1247. CSCInnerUnknown::CSCInnerUnknown( CStubComplete *pParent )
  1248. {
  1249. _iRef = 1;
  1250. _pParent = pParent;
  1251. }
  1252. //+-------------------------------------------------------------------
  1253. //
  1254. // Member: CSCInnerUnknown::QueryInterface, public
  1255. //
  1256. // Synopsis: Returns a pointer to the requested interface.
  1257. //
  1258. //--------------------------------------------------------------------
  1259. STDMETHODIMP CSCInnerUnknown::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
  1260. {
  1261. IUnknown *pUnk;
  1262. if (IsEqualIID(riid, IID_IUnknown))
  1263. pUnk = (IUnknown *) this;
  1264. else if (IsEqualIID(riid, IID_IAsyncManager))
  1265. pUnk = (IAsyncManager *) _pParent;
  1266. else if (IsEqualIID(riid, IID_ICancelMethodCalls))
  1267. pUnk = (ICancelMethodCalls *) _pParent;
  1268. else if (IsEqualIID(riid, IID_IAsyncSetup))
  1269. pUnk = (IAsyncSetup *) _pParent;
  1270. else if (_pParent->_pSyncInner != NULL)
  1271. return _pParent->_pSyncInner->QueryInterface( riid, ppvObj );
  1272. pUnk->AddRef();
  1273. *ppvObj = pUnk;
  1274. return S_OK;
  1275. }
  1276. //+-------------------------------------------------------------------
  1277. //
  1278. // Member: CSCInnerUnknown::Release, public
  1279. //
  1280. // Synopsis: Releases an interface
  1281. //
  1282. //--------------------------------------------------------------------
  1283. STDMETHODIMP_(ULONG) CSCInnerUnknown::Release()
  1284. {
  1285. ULONG lRef = _iRef - 1;
  1286. if (InterlockedDecrement( (long*) &_iRef ) == 0)
  1287. {
  1288. delete _pParent;
  1289. return 0;
  1290. }
  1291. else
  1292. return lRef;
  1293. }
  1294. //+-------------------------------------------------------------------
  1295. //
  1296. // Member: CStubComplete::AddRef, public
  1297. //
  1298. // Synopsis: Adds a reference to an interface
  1299. //
  1300. //--------------------------------------------------------------------
  1301. STDMETHODIMP_(ULONG) CStubComplete::AddRef()
  1302. {
  1303. return _pControl->AddRef();
  1304. }
  1305. //+-------------------------------------------------------------------
  1306. //
  1307. // Member: CStubComplete::Cancel, public
  1308. //
  1309. // Synopsis: Forward cancel to the channel
  1310. //
  1311. //--------------------------------------------------------------------
  1312. STDMETHODIMP CStubComplete::Cancel()
  1313. {
  1314. HRESULT hr;
  1315. if (_pChannel == NULL)
  1316. return RPC_E_CALL_COMPLETE;
  1317. hr = _pChannel->Cancel( &_Message );
  1318. _pChannel->Release();
  1319. _pChannel = NULL;
  1320. return hr;
  1321. }
  1322. //+-------------------------------------------------------------------
  1323. //
  1324. // Member: CStubComplete::CompleteCall, public
  1325. //
  1326. // Synopsis: Get a buffer and send the reply.
  1327. //
  1328. //--------------------------------------------------------------------
  1329. STDMETHODIMP CStubComplete::CompleteCall( HRESULT result )
  1330. {
  1331. HRESULT hr;
  1332. DWORD lIgnore;
  1333. // Fail if there is no call.
  1334. if (_pChannel == NULL)
  1335. return RPC_E_CALL_COMPLETE;
  1336. // Get a buffer.
  1337. _Message.cbBuffer = 4;
  1338. hr = _pChannel->GetBuffer( &_Message, IID_IAsync );
  1339. if (FAILED(hr))
  1340. goto Done;
  1341. // Marshal the result.
  1342. *((HRESULT *) _Message.Buffer) = result;
  1343. // Send the reply.
  1344. hr = _pChannel->Send( &_Message, &lIgnore );
  1345. Done:
  1346. _pChannel->Release();
  1347. _pChannel = NULL;
  1348. return hr;
  1349. }
  1350. //+-------------------------------------------------------------------
  1351. //
  1352. // Member: CStubComplete::CStubComplete
  1353. //
  1354. // Synopsis: Constructor
  1355. //
  1356. //--------------------------------------------------------------------
  1357. CStubComplete::CStubComplete( IUnknown *pControl,
  1358. IRpcChannelBuffer3 *pChannel,
  1359. RPCOLEMESSAGE *pMessage,
  1360. HRESULT *hr ) :
  1361. _Inner( this )
  1362. {
  1363. _Message = *pMessage;
  1364. _pSyncInner = NULL;
  1365. _pChannel = pChannel;
  1366. pChannel->AddRef();
  1367. if (pControl == NULL)
  1368. _pControl = &_Inner;
  1369. else
  1370. {
  1371. _pControl = pControl;
  1372. _pControl->AddRef();
  1373. }
  1374. // Aggregate in an ISynchronize.
  1375. *hr = CoCreateInstance( CLSID_Synchronize_ManualResetEvent,
  1376. &_Inner,
  1377. CLSCTX_INPROC_SERVER, IID_IUnknown,
  1378. (void **) &_pSyncInner );
  1379. if (SUCCEEDED(*hr))
  1380. {
  1381. // Aggregation requires some weird reference counting.
  1382. Release();
  1383. }
  1384. }
  1385. //+-------------------------------------------------------------------
  1386. //
  1387. // Member: CStubComplete::~CStubComplete
  1388. //
  1389. // Synopsis: Destructor
  1390. //
  1391. //--------------------------------------------------------------------
  1392. CStubComplete::~CStubComplete()
  1393. {
  1394. // Make sure we don't get deleted twice.
  1395. _Inner._iRef = 0xdead;
  1396. if (_pSyncInner != NULL)
  1397. _pSyncInner->Release();
  1398. if (_pChannel != NULL)
  1399. _pChannel->Release();
  1400. if (_pControl != &_Inner)
  1401. _pControl->Release();
  1402. }
  1403. //+-------------------------------------------------------------------
  1404. //
  1405. // Member: CStubComplete::GetAsyncManager, public
  1406. //
  1407. // Synopsis: Creates a stub completion object and reregisters it
  1408. // in place of this one.
  1409. //
  1410. //--------------------------------------------------------------------
  1411. STDMETHODIMP CStubComplete::GetAsyncManager( REFIID riid,
  1412. IUnknown *pOuter,
  1413. DWORD dwFlags,
  1414. IUnknown **ppInner,
  1415. IAsyncManager **ppComplete )
  1416. {
  1417. CStubComplete *pComplete;
  1418. HRESULT hr;
  1419. // Fail if there is no call.
  1420. if (_pChannel == NULL)
  1421. return RPC_E_CALL_COMPLETE;
  1422. // Create a new stub completion object.
  1423. pComplete = new CStubComplete( pOuter, _pChannel, &_Message, &hr );
  1424. if (pComplete == NULL)
  1425. return E_OUTOFMEMORY;
  1426. if (FAILED(hr))
  1427. {
  1428. delete pComplete;
  1429. return hr;
  1430. }
  1431. // Register the new stub completion object.
  1432. hr = _pChannel->RegisterAsync( &pComplete->_Message, pComplete );
  1433. if (FAILED(hr))
  1434. DebugBreak();
  1435. // Disconnect this stub completion object.
  1436. _pChannel->Release();
  1437. _pChannel = NULL;
  1438. *ppComplete = pComplete;
  1439. *ppInner = &pComplete->_Inner;
  1440. return S_OK;
  1441. }
  1442. //+-------------------------------------------------------------------
  1443. //
  1444. // Member: CStubComplete::GetCallContext, public
  1445. //
  1446. // Synopsis: Calls GetCallContext on the channel
  1447. //
  1448. //--------------------------------------------------------------------
  1449. STDMETHODIMP CStubComplete::GetCallContext( REFIID riid, void **pInterface )
  1450. {
  1451. if (_pChannel == NULL)
  1452. return RPC_E_CALL_COMPLETE;
  1453. return _pChannel->GetCallContext( &_Message, riid, pInterface );
  1454. }
  1455. //+-------------------------------------------------------------------
  1456. //
  1457. // Member: CStubComplete::GetState, public
  1458. //
  1459. // Synopsis: Returns a pointer to the requested interface.
  1460. //
  1461. //--------------------------------------------------------------------
  1462. STDMETHODIMP CStubComplete::GetState( DWORD *pState )
  1463. {
  1464. if (_pChannel == NULL)
  1465. return RPC_E_CALL_COMPLETE;
  1466. return _pChannel->GetState( &_Message, pState );
  1467. }
  1468. //+-------------------------------------------------------------------
  1469. //
  1470. // Member: CStubComplete::QueryInterface, public
  1471. //
  1472. // Synopsis: Returns a pointer to the requested interface.
  1473. //
  1474. //--------------------------------------------------------------------
  1475. STDMETHODIMP CStubComplete::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
  1476. {
  1477. return _pControl->QueryInterface( riid, ppvObj );
  1478. }
  1479. //+-------------------------------------------------------------------
  1480. //
  1481. // Member: CStubComplete::Release, public
  1482. //
  1483. // Synopsis: Releases an interface
  1484. //
  1485. //--------------------------------------------------------------------
  1486. STDMETHODIMP_(ULONG) CStubComplete::Release()
  1487. {
  1488. return _pControl->Release();
  1489. }
  1490. //+-------------------------------------------------------------------
  1491. //
  1492. // Member: CStubComplete::TestCancel, public
  1493. //
  1494. // Synopsis: Is call canceled?
  1495. //
  1496. //--------------------------------------------------------------------
  1497. STDMETHODIMP CStubComplete::TestCancel()
  1498. {
  1499. HRESULT hr;
  1500. DWORD state;
  1501. // The call is complete is already cleaned up.
  1502. if (_pChannel == NULL)
  1503. return RPC_E_CALL_COMPLETE;
  1504. // Ask the channel about the state of the call.
  1505. hr = _pChannel->GetState( &_Message, &state );
  1506. if (FAILED(hr))
  1507. return hr;
  1508. // Convert the flags to error codes.
  1509. if (state & DCOM_CALL_CANCELED)
  1510. return RPC_E_CALL_CANCELED;
  1511. else if (state & DCOM_CALL_COMPLETE)
  1512. return RPC_E_CALL_COMPLETE;
  1513. else
  1514. return RPC_S_CALLPENDING;
  1515. }