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.

1022 lines
28 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // File: remunkps.cxx
  4. //
  5. // Contents: IRemoteUnnknown custom proxy/stub implementation
  6. //
  7. // Classes: CRemUnknownFactory
  8. // CRemUnknownSyncP
  9. // CRemUnknownAsyncP
  10. //
  11. // History: 15-Dec-97 MattSmit Created
  12. //
  13. //--------------------------------------------------------------------
  14. #include <ole2int.h>
  15. #include "remunkps.hxx"
  16. #include "..\..\com\dcomrem\sync.hxx"
  17. // out internal psclass factory implementation
  18. EXTERN_C HRESULT ProxyDllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv);
  19. //+--------------------------------------------------------------------
  20. //
  21. // Function: RemUnkGetClassObject
  22. //
  23. // Synopsis: Creates a factory object for our custom IRemUnknown proxy.
  24. //
  25. //---------------------------------------------------------------------
  26. HRESULT RemUnkPSGetClassObject(REFIID riid, LPVOID *ppv)
  27. {
  28. ComDebOut((DEB_CHANNEL, "RemUnkPSGetClassObject IN riid:%I, ppv:0x%x\n", &riid, ppv));
  29. HRESULT hr = E_OUTOFMEMORY;
  30. CRemUnknownFactory *pObj = new CRemUnknownFactory();
  31. if (pObj)
  32. {
  33. hr = pObj->QueryInterface(riid, ppv);
  34. }
  35. ComDebOut((DEB_CHANNEL, "RemUnkPSGetClassObject OUT hr:0x%x\n", hr));
  36. return hr;
  37. }
  38. //+-------------------------------------------------------------------
  39. //
  40. // Class: CRemUnknownFactory
  41. //
  42. // Synopsis: Custom factory for the proxy/stub for IRemUnknown.
  43. //
  44. //--------------------------------------------------------------------
  45. //+-------------------------------------------------------------------
  46. //
  47. // Interface: IUnKnown
  48. //
  49. // Synopsis: Simple IUnknown implementation. QI will support
  50. // IPSFactoryBuffer
  51. //
  52. //--------------------------------------------------------------------
  53. STDMETHODIMP CRemUnknownFactory::QueryInterface(REFIID riid, PVOID *pv)
  54. {
  55. ComDebOut((DEB_CHANNEL, "CRemUnknownFactory::QueryInterface IN riid:%I, pv:0x%x\n", &riid, pv));
  56. if ((riid == IID_IUnknown) || (riid == IID_IPSFactoryBuffer))
  57. {
  58. *pv = this;
  59. AddRef();
  60. return S_OK;
  61. }
  62. else
  63. {
  64. return E_NOINTERFACE;
  65. }
  66. }
  67. STDMETHODIMP_(ULONG) CRemUnknownFactory::AddRef()
  68. {
  69. return InterlockedIncrement((PLONG) &_cRefs);
  70. }
  71. STDMETHODIMP_(ULONG) CRemUnknownFactory::Release()
  72. {
  73. ULONG ret = InterlockedDecrement((PLONG) &_cRefs);
  74. if (ret == 0)
  75. {
  76. delete this;
  77. }
  78. return ret;
  79. }
  80. //+-------------------------------------------------------------------
  81. //
  82. // Interface: IPSFactoryBuffer
  83. //
  84. //--------------------------------------------------------------------
  85. //+-------------------------------------------------------------------
  86. //
  87. // Method: CreateProxy
  88. //
  89. // Synopsis: Creates a custom synchronous proxy object so we can
  90. // implement ICallFactory on the proxy.
  91. //
  92. //--------------------------------------------------------------------
  93. STDMETHODIMP CRemUnknownFactory::CreateProxy(IUnknown *pUnkOuter,
  94. REFIID riid,
  95. IRpcProxyBuffer **ppProxy,
  96. void **ppv)
  97. {
  98. ComDebOut((DEB_CHANNEL, "CRemUnknownFactory::CreateProxy IN pUnkOuter:0x%x, riid:%I,"
  99. " ppProxy:0x%x, ppv:0x%x\n", pUnkOuter, &riid, ppProxy, ppv));
  100. HRESULT hr;
  101. Win4Assert((riid == IID_IRemUnknown) ||
  102. (riid == IID_IRemUnknown2) ||
  103. (riid == IID_IRemUnknownN) ||
  104. (riid == IID_IRundown)) ;
  105. hr = E_OUTOFMEMORY;
  106. CRemUnknownSyncP *pObj = new CRemUnknownSyncP();
  107. if (pObj)
  108. {
  109. hr = pObj->Init(pUnkOuter, riid, ppProxy, ppv);
  110. pObj->_IntUnk.Release();
  111. }
  112. // Clean up out parameters on error.
  113. if (FAILED(hr))
  114. {
  115. *ppProxy = NULL;
  116. *ppv = NULL;
  117. }
  118. ComDebOut((DEB_CHANNEL, "CRemUnknownFactory::CreateProxy OUT hr:0x%x\n", hr));
  119. return hr;
  120. }
  121. //+-------------------------------------------------------------------
  122. //
  123. // Method: CreateStub
  124. //
  125. // Synopsis: Create the MIDL generated stub and give it back
  126. // because we do not need to get involved on the server
  127. // side.
  128. //
  129. //--------------------------------------------------------------------
  130. STDMETHODIMP CRemUnknownFactory::CreateStub(REFIID riid,
  131. IUnknown *pUnkServer,
  132. IRpcStubBuffer **ppStub)
  133. {
  134. ComDebOut((DEB_CHANNEL, "CRemUnknownFactory::CreateStub IN riid:%I, pUnkServer:0x%x, ppStub:0x%x\n",
  135. &riid, pUnkServer, ppStub));
  136. HRESULT hr;
  137. IPSFactoryBuffer *pFac;
  138. if (SUCCEEDED(hr = ProxyDllGetClassObject(CLSID_PSOlePrx32, IID_IPSFactoryBuffer, (void **) &pFac)))
  139. {
  140. hr = pFac->CreateStub(riid, pUnkServer, ppStub);
  141. pFac->Release();
  142. }
  143. ComDebOut((DEB_CHANNEL, "CRemUnknownFactory::CreateStub OUT hr:0x%x\n", hr));
  144. return hr;
  145. }
  146. //+-------------------------------------------------------------------
  147. //
  148. // Class: CRemUnknownSyncP::CRpcProxyBuffer
  149. //
  150. // Synopsis: Internal Unknown and IRpcProxyBuffer implementation
  151. // for CRemUnknownSyncP
  152. //
  153. //--------------------------------------------------------------------
  154. //+-------------------------------------------------------------------
  155. //
  156. // Interface: IUnKnown
  157. //
  158. // Synopsis: Simple IUnknown implementation. QI will support
  159. // IRpcProxyBuffer, ICallFactory and delegate the
  160. // rest to the MIDL implementation
  161. //
  162. //--------------------------------------------------------------------
  163. STDMETHODIMP CRemUnknownSyncP::CRpcProxyBuffer::QueryInterface(REFIID riid, PVOID *pv)
  164. {
  165. ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::CRpcProxyBuffer::QueryInterface"
  166. " riid:%I, pv:0x%x\n", &riid, pv));
  167. CRemUnknownSyncP *This = (CRemUnknownSyncP *) (((BYTE *) this) - offsetof(CRemUnknownSyncP, _IntUnk));
  168. if ((riid == IID_IUnknown) || (riid == IID_IRpcProxyBuffer))
  169. {
  170. *pv = this;
  171. AddRef();
  172. return S_OK;
  173. }
  174. else if (riid == IID_ICallFactory)
  175. {
  176. *pv = (ICallFactory * ) This;
  177. This->AddRef();
  178. return S_OK;
  179. }
  180. else
  181. {
  182. return This->_pPrx->QueryInterface(riid, pv);
  183. }
  184. }
  185. STDMETHODIMP_(ULONG) CRemUnknownSyncP::CRpcProxyBuffer::AddRef()
  186. {
  187. return InterlockedIncrement((PLONG) &_cRefs);
  188. }
  189. STDMETHODIMP_(ULONG) CRemUnknownSyncP::CRpcProxyBuffer::Release()
  190. {
  191. ULONG ret = InterlockedDecrement((PLONG) &_cRefs);
  192. if (ret == 0)
  193. {
  194. CRemUnknownSyncP *This = (CRemUnknownSyncP *) (((BYTE *) this) - offsetof(CRemUnknownSyncP, _IntUnk));
  195. delete This;
  196. }
  197. return ret;
  198. }
  199. //+-------------------------------------------------------------------
  200. //
  201. // Interface: IRpcProxyBuffer
  202. //
  203. // Synopsis: Delegates IrpcProxyBuffer calls to the MIDL generated
  204. //
  205. //
  206. //--------------------------------------------------------------------
  207. STDMETHODIMP CRemUnknownSyncP::CRpcProxyBuffer::Connect(IRpcChannelBuffer *pRpcChannelBuffer)
  208. {
  209. ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::CRpcProxyBuffer::Connect pRpcChannelBuffer:0x%x\n", pRpcChannelBuffer));
  210. CRemUnknownSyncP *This = (CRemUnknownSyncP *) (((BYTE *) this) - offsetof(CRemUnknownSyncP, _IntUnk));
  211. return This->_pPrx->Connect(pRpcChannelBuffer);
  212. }
  213. STDMETHODIMP_(void) CRemUnknownSyncP::CRpcProxyBuffer::Disconnect()
  214. {
  215. ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::CRpcProxyBuffer::Disconnect\n" ));
  216. CRemUnknownSyncP *This = (CRemUnknownSyncP *) (((BYTE *) this) - offsetof(CRemUnknownSyncP, _IntUnk));
  217. This->_pPrx->Disconnect();
  218. }
  219. //+-------------------------------------------------------------------
  220. //
  221. // Class: CRemUnknownSyncP
  222. //
  223. // Synopsis: Synchronous proxy for IRemUknown
  224. //
  225. //--------------------------------------------------------------------
  226. //+-------------------------------------------------------------------
  227. //
  228. // Method: Init
  229. //
  230. // Synopsis: Initializes the proxy wrapper by creating the MIDL
  231. // generated proxy and saving the outer unknown.
  232. //
  233. //--------------------------------------------------------------------
  234. HRESULT CRemUnknownSyncP::Init(IUnknown *pUnkOuter,
  235. REFIID riid,
  236. IRpcProxyBuffer **ppProxy,
  237. void **ppv)
  238. {
  239. ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::Init IN pUnkOuter:0x%x,"
  240. " riid:%I, ppProxy:0x%x, ppv:0x%x\n", pUnkOuter, &riid, ppProxy, ppv));
  241. HRESULT hr;
  242. _pCtrlUnk = pUnkOuter;
  243. IPSFactoryBuffer *pFac;
  244. if (SUCCEEDED(hr = ProxyDllGetClassObject(CLSID_PSOlePrx32, IID_IPSFactoryBuffer, (void **) &pFac)))
  245. {
  246. IRpcProxyBuffer *pPrx = 0;
  247. if (SUCCEEDED(hr = pFac->CreateProxy(pUnkOuter, riid, &pPrx, ppv)))
  248. {
  249. _pPrx = pPrx;
  250. *ppProxy = &_IntUnk;
  251. (*ppProxy)->AddRef();
  252. }
  253. pFac->Release();
  254. }
  255. ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::Init OUT hr:0x%x\n", hr));
  256. return hr;
  257. }
  258. //+-------------------------------------------------------------------
  259. //
  260. // Method: Destructor
  261. //
  262. // Synopsis: Release the MIDL generated proxy if we aquired it.
  263. //
  264. //--------------------------------------------------------------------
  265. CRemUnknownSyncP::~CRemUnknownSyncP()
  266. {
  267. ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP~CRemUnknownSyncP \n" ));
  268. if (_pPrx)
  269. {
  270. _pPrx->Release();
  271. _pPrx = NULL;
  272. }
  273. }
  274. //+-------------------------------------------------------------------
  275. //
  276. // Interface: IUnKnown
  277. //
  278. // Synopsis: Simple IUnknown implementation. Delegates to outer.
  279. //
  280. //--------------------------------------------------------------------
  281. STDMETHODIMP CRemUnknownSyncP::QueryInterface(REFIID riid, PVOID *pv)
  282. {
  283. return _pCtrlUnk->QueryInterface(riid, pv);
  284. }
  285. STDMETHODIMP_(ULONG) CRemUnknownSyncP::AddRef()
  286. {
  287. return _pCtrlUnk->AddRef();
  288. }
  289. STDMETHODIMP_(ULONG) CRemUnknownSyncP::Release()
  290. {
  291. return _pCtrlUnk->Release();
  292. }
  293. //+-------------------------------------------------------------------
  294. //
  295. // Interface: ICallFactory
  296. //
  297. // Synopsis: Interface for creating asynchronous call objects
  298. //
  299. //--------------------------------------------------------------------
  300. //+-------------------------------------------------------------------
  301. //
  302. // Method: CreateCall
  303. //
  304. // Synopsis: create and initialize an async call object
  305. //
  306. //--------------------------------------------------------------------
  307. STDMETHODIMP CRemUnknownSyncP::CreateCall(REFIID riid,
  308. IUnknown *pCtrlUnk,
  309. REFIID riid2,
  310. IUnknown **ppUnk)
  311. {
  312. ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::CreateCall IN "
  313. "riid:%I, pCtrlUnk:0x%x, riid2:%I, ppUnk:0x%x\n",
  314. &riid, pCtrlUnk, &riid2, ppUnk));
  315. HRESULT hr = E_OUTOFMEMORY;
  316. Win4Assert((riid == IID_AsyncIRemUnknown) || (riid == IID_AsyncIRemUnknown2));
  317. CRemUnknownAsyncCallP *pObj = new CRemUnknownAsyncCallP(pCtrlUnk);
  318. if (pObj)
  319. {
  320. hr = pObj->_IntUnk.QueryInterface(riid2, (void **) ppUnk);
  321. pObj->_IntUnk.Release();
  322. }
  323. ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::CreateCall OUT hr:0x%x\n", hr));
  324. return hr;
  325. }
  326. //+-------------------------------------------------------------------
  327. //
  328. // Class: CRemUnknownAsyncCallP::CRpcProxyBuffer
  329. //
  330. // Synopsis: Inner unknown and proxy buffer interface
  331. //
  332. //--------------------------------------------------------------------
  333. //+-------------------------------------------------------------------
  334. //
  335. // Interface: IUnKnown
  336. //
  337. // Synopsis: Simple IUnknown implementation. QI will support
  338. // IRpcProxyBuffer and AsyncIRemUnknown
  339. //
  340. //--------------------------------------------------------------------
  341. STDMETHODIMP CRemUnknownAsyncCallP::CRpcProxyBuffer::QueryInterface(REFIID riid, PVOID *pv)
  342. {
  343. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::CRpcProxyBuffer::QueryInterface "
  344. " riid:%I, pv:0x%x\n", &riid, pv));
  345. CRemUnknownAsyncCallP *This = (CRemUnknownAsyncCallP *) (((BYTE *) this) - offsetof(CRemUnknownAsyncCallP, _IntUnk));
  346. if ((riid == IID_IUnknown) || (riid == IID_IRpcProxyBuffer))
  347. {
  348. *pv = this;
  349. AddRef();
  350. return S_OK;
  351. }
  352. else if ((riid == IID_AsyncIRemUnknown) || (riid == IID_AsyncIRemUnknown2) )
  353. {
  354. *pv = (AsyncIRemUnknown2 * ) This;
  355. This->AddRef();
  356. return S_OK;
  357. }
  358. return E_NOINTERFACE;
  359. }
  360. STDMETHODIMP_(ULONG) CRemUnknownAsyncCallP::CRpcProxyBuffer::AddRef()
  361. {
  362. return InterlockedIncrement((PLONG) &_cRefs);
  363. }
  364. STDMETHODIMP_(ULONG) CRemUnknownAsyncCallP::CRpcProxyBuffer::Release()
  365. {
  366. ULONG ret = InterlockedDecrement((PLONG) &_cRefs);
  367. if (ret == 0)
  368. {
  369. CRemUnknownAsyncCallP *This = (CRemUnknownAsyncCallP *) (((BYTE *) this) - offsetof(CRemUnknownAsyncCallP, _IntUnk));
  370. delete This;
  371. }
  372. return ret;
  373. }
  374. //+-------------------------------------------------------------------
  375. //
  376. // Interface: IRpcProxyBuffer
  377. //
  378. // Synopsis: handles logistics of connecting and disconnecting
  379. // the proxy call object
  380. //
  381. //--------------------------------------------------------------------
  382. STDMETHODIMP CRemUnknownAsyncCallP::CRpcProxyBuffer::Connect(IRpcChannelBuffer *pRpcChannelBuffer)
  383. {
  384. CRemUnknownAsyncCallP *This = (CRemUnknownAsyncCallP *) (((BYTE *) this) - offsetof(CRemUnknownAsyncCallP, _IntUnk));
  385. Win4Assert(!This->_pChnl);
  386. return pRpcChannelBuffer->QueryInterface(IID_IAsyncRpcChannelBuffer, (void **) &(This->_pChnl));
  387. }
  388. STDMETHODIMP_(void) CRemUnknownAsyncCallP::CRpcProxyBuffer::Disconnect(void)
  389. {
  390. CRemUnknownAsyncCallP *This = (CRemUnknownAsyncCallP *) (((BYTE *) this) - offsetof(CRemUnknownAsyncCallP, _IntUnk));
  391. if (This->_pChnl)
  392. {
  393. This->_pChnl->Release();
  394. This->_pChnl = NULL;
  395. }
  396. }
  397. //+-------------------------------------------------------------------
  398. //
  399. // Class: CRemUnknownAsyncCallP
  400. //
  401. // Synopsis: Asynchronous proxy call object for IRemUknown
  402. //
  403. //--------------------------------------------------------------------
  404. //+-------------------------------------------------------------------
  405. //
  406. // Interface: IUnKnown
  407. //
  408. // Synopsis: Simple IUnknown implementation. Delegates to outer.
  409. //
  410. //--------------------------------------------------------------------
  411. STDMETHODIMP CRemUnknownAsyncCallP::QueryInterface(REFIID riid, PVOID *pv)
  412. {
  413. return _pCtrlUnk->QueryInterface(riid, pv);
  414. }
  415. STDMETHODIMP_(ULONG) CRemUnknownAsyncCallP::AddRef()
  416. {
  417. return _pCtrlUnk->AddRef();
  418. }
  419. STDMETHODIMP_(ULONG) CRemUnknownAsyncCallP::Release()
  420. {
  421. return _pCtrlUnk->Release();
  422. }
  423. //+-------------------------------------------------------------------
  424. //
  425. // Interface: AsyncIRemUnknown
  426. //
  427. // Synopsis: This is the actual async interface which will marshal
  428. // the parameters.
  429. //
  430. //--------------------------------------------------------------------
  431. //+----------------------------------------------------------------------------
  432. //
  433. // Member: CRemUnknownAsyncCallP::Begin_RemQueryInterface
  434. //
  435. // Synopsis: Marshal paramenters and save cIids
  436. //
  437. // History: 23-Jan-98 MattSmit Created
  438. //
  439. //-----------------------------------------------------------------------------
  440. STDMETHODIMP CRemUnknownAsyncCallP::Begin_RemQueryInterface(
  441. REFIPID ripid,
  442. unsigned long cRefs,
  443. unsigned short cIids,
  444. IID *iids
  445. )
  446. {
  447. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface IN"
  448. " ripid:%I, crefs:0x%d, cIids:0x%d, iids:%I\n",
  449. &ripid, cRefs, cIids, iids));
  450. _hr = S_OK;
  451. HRESULT hr;
  452. // Get the synchronize interface
  453. ISynchronize *pSync;
  454. if (FAILED(hr = _pCtrlUnk->QueryInterface(IID_ISynchronize, (void **) &pSync) ))
  455. {
  456. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface"
  457. " FAILED QI for ISyncronize\n"));
  458. return hr;
  459. }
  460. // set up message
  461. memset(&_msg, 0, sizeof(RPCOLEMESSAGE));
  462. _msg.cbBuffer = sizeof(IPID) + // ripid
  463. sizeof(unsigned long) + // cRefs
  464. sizeof(unsigned short) + 2 + // cIids + padding
  465. sizeof(unsigned long) + (cIids * sizeof(IID)); // iids
  466. _msg.rpcFlags = RPC_BUFFER_ASYNC;
  467. _msg.iMethod = 3;
  468. // get buffer
  469. if (SUCCEEDED(hr = _pChnl->GetBuffer(&_msg, IID_IRemUnknown)))
  470. {
  471. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface "
  472. "buffer obtained _msg.cbBuffer:%d, _msg.Buffer:0x%x \n",
  473. _msg.cbBuffer, _msg.Buffer));
  474. BYTE * p = (BYTE *)_msg.Buffer;
  475. memset(p, 0, _msg.cbBuffer);
  476. // marshal the parameters
  477. memcpy(p, &ripid, sizeof(IPID));
  478. p += sizeof(IPID);
  479. memcpy(p, &cRefs, sizeof(cRefs));
  480. p += sizeof (cRefs);
  481. memcpy(p, &cIids, sizeof(unsigned short));
  482. p += sizeof (unsigned short) + 2;
  483. memcpy(p, &cIids, sizeof(unsigned short));
  484. p += sizeof (unsigned long);
  485. unsigned short i;
  486. for (i=0; i<cIids; i++)
  487. {
  488. memcpy(p, iids+i, sizeof(IID));
  489. p += sizeof (IID);
  490. }
  491. // save this for later
  492. _cIids = cIids;
  493. // send
  494. ULONG status;
  495. hr = _pChnl->Send(&_msg, pSync, &status);
  496. }
  497. if (FAILED(hr))
  498. {
  499. pSync->Signal();
  500. _hr = hr;
  501. }
  502. pSync->Release();
  503. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface OUT hr:0x%x\n", hr));
  504. return hr;
  505. }
  506. //+----------------------------------------------------------------------------
  507. //
  508. // Member: CRemUnknownAsyncCallP::Finish_RemQueryInterface
  509. //
  510. // Synopsis: Unmarshal QI parameters
  511. //
  512. // History: 23-Jan-98 MattSmit Created
  513. //
  514. //-----------------------------------------------------------------------------
  515. STDMETHODIMP CRemUnknownAsyncCallP::Finish_RemQueryInterface(REMQIRESULT **ppQIResults)
  516. {
  517. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface IN ppQIResults:0x%x\n", ppQIResults));
  518. HRESULT hr;
  519. // check state
  520. if (FAILED(_hr) )
  521. {
  522. return _hr;
  523. }
  524. // ensure call has completed
  525. ISynchronize *pSync;
  526. if (SUCCEEDED(_pCtrlUnk->QueryInterface(IID_ISynchronize, (void **) &pSync) ))
  527. {
  528. hr = pSync->Wait(0, INFINITE);
  529. pSync->Release();
  530. if (FAILED(hr))
  531. {
  532. return hr;
  533. }
  534. }
  535. // receive
  536. ULONG status;
  537. if (SUCCEEDED(hr = _pChnl->Receive(&_msg, &status)))
  538. {
  539. hr = E_OUTOFMEMORY;
  540. // unmarshal parameters
  541. REMQIRESULT *p = (REMQIRESULT *)CoTaskMemAlloc(_cIids * sizeof(REMQIRESULT));
  542. if (p)
  543. {
  544. ComDebOut((DEB_CHANNEL, "_cIids = 0x%x, _msg.cbBuffer = 0x%x, _msg.Buffer=0x%x\n",
  545. _cIids, _msg.cbBuffer, _msg.Buffer));
  546. ComDebOut((DEB_CHANNEL, "sizeof(REMQIRESULT)=0x%x, offsetof(REMQIRESULT, std)=0x%x\n",
  547. sizeof(REMQIRESULT),offsetof(REMQIRESULT, std)));
  548. // Win4Assert(_cIids == ((unsigned long *) _msg.Buffer)[1]);
  549. BYTE * pBuffer = (BYTE *)_msg.Buffer;
  550. pBuffer += sizeof(DWORD)*2;
  551. memcpy(p, pBuffer, sizeof(REMQIRESULT) *_cIids);
  552. *ppQIResults = p;
  553. hr = S_OK;
  554. }
  555. // free the buffer
  556. _pChnl->FreeBuffer(&_msg);
  557. }
  558. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface OUT hr:0x%x\n", hr));
  559. return hr;
  560. }
  561. //+----------------------------------------------------------------------------
  562. //
  563. // Member: CRemUnknownAsyncCallP::Begin_RemAddRef
  564. //
  565. // Synopsis: Not implemented. Never used
  566. //
  567. // History: 23-Jan-98 MattSmit Created
  568. //
  569. //-----------------------------------------------------------------------------
  570. STDMETHODIMP CRemUnknownAsyncCallP::Begin_RemAddRef(unsigned short cInterfaceRefs,
  571. REMINTERFACEREF InterfaceRefs[])
  572. {
  573. return E_NOTIMPL;
  574. }
  575. //+----------------------------------------------------------------------------
  576. //
  577. // Member: CRemUnknownAsyncCallP::Finish_RemAddRef
  578. //
  579. // Synopsis: Not implemented. Never used
  580. //
  581. // History: 23-Jan-98 MattSmit Created
  582. //
  583. //-----------------------------------------------------------------------------
  584. STDMETHODIMP CRemUnknownAsyncCallP::Finish_RemAddRef(HRESULT *pResults)
  585. {
  586. return E_NOTIMPL;
  587. }
  588. //+----------------------------------------------------------------------------
  589. //
  590. // Member: CRemUnknownAsyncCallP::Begin_RemRelease
  591. //
  592. // Synopsis: Marshal parameters.
  593. //
  594. // History: 23-Jan-98 MattSmit Created
  595. //
  596. //-----------------------------------------------------------------------------
  597. STDMETHODIMP CRemUnknownAsyncCallP::Begin_RemRelease(unsigned short cInterfaceRefs,
  598. REMINTERFACEREF InterfaceRefs[])
  599. {
  600. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemRelease IN cInterfaceRefs:0x%d, ",
  601. "InterfaceRefs:0x%x\n", cInterfaceRefs, InterfaceRefs));
  602. _hr = S_OK;
  603. HRESULT hr;
  604. // Get the synchronize interface
  605. ISynchronize *pSync;
  606. if (FAILED(hr = _pCtrlUnk->QueryInterface(IID_ISynchronize, (void **) &pSync) ))
  607. {
  608. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemRelease FAILED QI for ISyncronize\n"));
  609. return hr;
  610. }
  611. // set up message
  612. memset(&_msg, 0, sizeof(RPCOLEMESSAGE));
  613. _msg.cbBuffer = sizeof(unsigned short) + 2 + // cInterfaceRefs
  614. sizeof(unsigned long) + (sizeof(REMINTERFACEREF) * cInterfaceRefs); // InterfaceRefs[]
  615. _msg.rpcFlags = RPC_BUFFER_ASYNC;
  616. _msg.iMethod = 5;
  617. // get buffer
  618. if (SUCCEEDED(hr = _pChnl->GetBuffer(&_msg, IID_IRemUnknown)))
  619. {
  620. BYTE * p = (BYTE *)_msg.Buffer;
  621. memset(p, 0, _msg.cbBuffer);
  622. // marshal the parameters
  623. memcpy(p, &cInterfaceRefs, sizeof(unsigned short));
  624. p += sizeof (unsigned short) + 2;
  625. memcpy(p, &cInterfaceRefs, sizeof(unsigned short));
  626. p += sizeof (unsigned long);
  627. unsigned short i;
  628. for (i=0; i<cInterfaceRefs; i++)
  629. {
  630. memcpy(p, InterfaceRefs+i, sizeof(REMINTERFACEREF));
  631. p += sizeof (REMINTERFACEREF);
  632. }
  633. // send
  634. ULONG status;
  635. hr = _pChnl->Send(&_msg, pSync, &status);
  636. }
  637. else
  638. {
  639. pSync->Signal();
  640. }
  641. if (FAILED(hr))
  642. {
  643. _hr = hr;
  644. }
  645. pSync->Release();
  646. return hr;
  647. }
  648. //+----------------------------------------------------------------------------
  649. //
  650. // Member: CRemUnknownAsyncCallP::Finish_RemRelease
  651. //
  652. // Synopsis: Check state and return.
  653. //
  654. // History: 23-Jan-98 MattSmit Created
  655. //
  656. //-----------------------------------------------------------------------------
  657. STDMETHODIMP CRemUnknownAsyncCallP::Finish_RemRelease()
  658. {
  659. HRESULT hr;
  660. // check state
  661. if (FAILED(_hr) )
  662. {
  663. return _hr;
  664. }
  665. // ensure call has completed
  666. ISynchronize *pSync;
  667. if (SUCCEEDED(_pCtrlUnk->QueryInterface(IID_ISynchronize, (void **) &pSync) ))
  668. {
  669. hr = pSync->Wait(0, INFINITE);
  670. pSync->Release();
  671. if (FAILED(hr))
  672. {
  673. return hr;
  674. }
  675. }
  676. // receive
  677. ULONG status;
  678. if (SUCCEEDED(hr = _pChnl->Receive(&_msg, &status)))
  679. {
  680. // free the buffer
  681. _pChnl->FreeBuffer(&_msg);
  682. }
  683. return hr;
  684. }
  685. //+----------------------------------------------------------------------------
  686. //
  687. // Member: CRemUnknownAsyncCallP::Begin_RemQueryInterface2
  688. //
  689. // Synopsis: Marshal parameters, save count for Finish.
  690. //
  691. // History: 23-Jan-98 MattSmit Created
  692. //
  693. //-----------------------------------------------------------------------------
  694. STDMETHODIMP CRemUnknownAsyncCallP::Begin_RemQueryInterface2 (
  695. REFIPID ripid,
  696. unsigned short cIids,
  697. IID *iids
  698. )
  699. {
  700. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface2 IN "
  701. "ripid:%I, cIids:0x%d, iids:0x%x\n", &ripid, cIids, iids));
  702. _hr = S_OK;
  703. HRESULT hr;
  704. // Get the synchronize interface
  705. ISynchronize *pSync;
  706. if (FAILED(hr = _pCtrlUnk->QueryInterface(IID_ISynchronize, (void **) &pSync) ))
  707. {
  708. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface2 FAILED QI for ISynchronize\n"));
  709. return hr;
  710. }
  711. // set up message
  712. memset(&_msg, 0, sizeof(RPCOLEMESSAGE));
  713. _msg.cbBuffer = sizeof(IPID) + // ripid
  714. sizeof(unsigned short) + 2 + // cIids + padding
  715. sizeof(unsigned long) + (cIids * sizeof(IID)); // iids
  716. _msg.rpcFlags = RPC_BUFFER_ASYNC;
  717. _msg.iMethod = 6;
  718. // get buffer
  719. if (SUCCEEDED(hr = _pChnl->GetBuffer(&_msg, IID_IRemUnknown)))
  720. {
  721. BYTE * p = (BYTE *)_msg.Buffer;
  722. memset(p, 0, _msg.cbBuffer);
  723. // marshal the parameters
  724. memcpy(p, &ripid, sizeof(IPID));
  725. p += sizeof(IPID);
  726. memcpy(p, &cIids, sizeof(unsigned short));
  727. p += sizeof (unsigned short) + 2;
  728. memcpy(p, &cIids, sizeof(unsigned short));
  729. p += sizeof (unsigned long);
  730. memcpy(p, iids, sizeof(IID) * cIids);
  731. ComDebOut((DEB_CHANNEL, "RemQueryInterface2: _msg.Buffer:%x\n", _msg.Buffer));
  732. // save this for later
  733. _cIids = cIids;
  734. // send
  735. ULONG status;
  736. hr = _pChnl->Send(&_msg, pSync, &status);
  737. }
  738. if (FAILED(hr))
  739. {
  740. pSync->Signal();
  741. _hr = hr;
  742. }
  743. pSync->Release();
  744. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface2 OUT hr:0x%x\n", hr));
  745. return hr;
  746. }
  747. //+----------------------------------------------------------------------------
  748. //
  749. // Member: CRemUnknownAsyncCallP::Finish_RemQueryInterface2
  750. //
  751. // Synopsis: Unmarshal out parameters.
  752. //
  753. // History: 23-Jan-98 MattSmit Created
  754. //
  755. //-----------------------------------------------------------------------------
  756. STDMETHODIMP CRemUnknownAsyncCallP::Finish_RemQueryInterface2(
  757. HRESULT *phr,
  758. MInterfacePointer **ppMIF
  759. )
  760. {
  761. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface2 IN "
  762. "phr:0x%x, ppMIF:0x%x\n", phr, ppMIF));
  763. HRESULT hr;
  764. // check state
  765. if (FAILED(_hr) )
  766. {
  767. return _hr;
  768. }
  769. // ensure call has completed
  770. hr = WaitObject(_pCtrlUnk, 0, INFINITE);
  771. if (FAILED(hr))
  772. {
  773. return hr;
  774. }
  775. // receive
  776. ULONG status;
  777. if (SUCCEEDED(hr = _pChnl->Receive(&_msg, &status)))
  778. {
  779. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface2 \n",
  780. "_cIids = 0x%x, _msg.cbBuffer = 0x%x, _msg.Buffer=0x%x\n",
  781. _cIids, _msg.cbBuffer, _msg.Buffer));
  782. BYTE * pBuffer = (BYTE *)_msg.Buffer;
  783. pBuffer += sizeof(ULONG); // skip the count
  784. memcpy(phr, pBuffer, sizeof(HRESULT) *_cIids); // copy the hresults
  785. pBuffer += sizeof(HRESULT) *_cIids; // advance past hresults
  786. pBuffer += sizeof(ULONG); // skip count
  787. pBuffer += sizeof(ULONG) * _cIids; // not sure what this is, but its there.
  788. for(int i = 0; i < _cIids; i++)
  789. {
  790. // allocate memory and transfer to out parameters.
  791. ULONG *pulCntData = (PULONG) pBuffer;
  792. ULONG cb = sizeof(MInterfacePointer) + *pulCntData;
  793. MInterfacePointer *pMIF = (MInterfacePointer *) CoTaskMemAlloc(cb);
  794. if (pMIF)
  795. {
  796. pMIF->ulCntData = *pulCntData;
  797. pBuffer += sizeof(ULONG);
  798. pBuffer += sizeof(ULONG); // skip count
  799. memcpy(pMIF->abData, pBuffer, pMIF->ulCntData);
  800. ppMIF[i] = pMIF;
  801. pBuffer += pMIF->ulCntData;
  802. }
  803. else
  804. {
  805. // no memory, so free up what we have left
  806. // an return an error
  807. hr = E_OUTOFMEMORY;
  808. for (int j = 0; j<i; j++)
  809. {
  810. CoTaskMemFree(ppMIF[j]);
  811. ppMIF[j] = NULL;
  812. }
  813. break;
  814. }
  815. }
  816. // free the buffer
  817. _pChnl->FreeBuffer(&_msg);
  818. }
  819. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface2 "
  820. "phr:%x, ppMIF:%x\n", phr, ppMIF));
  821. ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface2 OUT hr:0x%x\n", hr));
  822. return hr;
  823. }