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.

1758 lines
40 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. CTSRDPServerChannelMgr.cpp
  5. Abstract:
  6. This module contains the TSRDP server-side subclass of
  7. CRemoteDesktopChannelMgr. Classes in this hierarchy are used to multiplex
  8. a single data channel into multiple client channels.
  9. CRemoteDesktopChannelMgr handles most of the details of multiplexing
  10. the data. Subclasses are responsible for implementing the details of
  11. interfacing with the transport for the underlying single data channel.
  12. The CTSRDPServerChannelMgr creates a named pipe that
  13. can be connected to by the TSRDP Assistant SessionVC Add-In. The TSRDP
  14. Assistant Session VC Add-In acts as a proxy for virtual channel data
  15. from the client-side Remote Desktop Host ActiveX Control. A background
  16. thread in this class handles the movement of data between an instance
  17. of this class and the proxy.
  18. Author:
  19. Tad Brockway 02/00
  20. Revision History:
  21. --*/
  22. #include "stdafx.h"
  23. #ifdef TRC_FILE
  24. #undef TRC_FILE
  25. #endif
  26. #define TRC_FILE "_tsrdpscm"
  27. #include "TSRDPServerDataChannelMgr.h"
  28. #include <TSRDPRemoteDesktop.h>
  29. #include "TSRDPRemoteDesktopSession.h"
  30. #include <RemoteDesktopUtils.h>
  31. #define INCOMINGBUFFER_RESIZEDELTA 1024
  32. ///////////////////////////////////////////////////////
  33. //
  34. // CTSRDPServerDataChannel Members
  35. //
  36. CTSRDPServerDataChannel::CTSRDPServerDataChannel()
  37. /*++
  38. Routine Description:
  39. Constructor
  40. Arguments:
  41. Return Value:
  42. None.
  43. --*/
  44. {
  45. DC_BEGIN_FN("CTSRDPServerDataChannel::CTSRDPServerDataChannel");
  46. TRC_NRM((TB, L"***Ref count is: %ld", m_dwRef));
  47. DC_END_FN();
  48. }
  49. CTSRDPServerDataChannel::~CTSRDPServerDataChannel()
  50. /*++
  51. Routine Description:
  52. Destructor
  53. Arguments:
  54. 7
  55. Return Value:
  56. None.
  57. --*/
  58. {
  59. DC_BEGIN_FN("CTSRDPServerDataChannel::~CTSRDPServerDataChannel");
  60. //
  61. // Notify the channel manager that we have gone away.
  62. //
  63. m_ChannelMgr->RemoveChannel(m_ChannelName);
  64. DC_END_FN();
  65. }
  66. STDMETHODIMP
  67. CTSRDPServerDataChannel::ReceiveChannelData(
  68. BSTR *data
  69. )
  70. /*++
  71. Routine Description:
  72. Receive the next complete data packet on this channel.
  73. Arguments:
  74. data - The next data packet. Should be released by the
  75. caller.
  76. Return Value:
  77. S_OK on success. Otherwise, an error result is returned.
  78. --*/
  79. {
  80. HRESULT result;
  81. DC_BEGIN_FN("CTSRDPServerDataChannel::ReceiveChannelData");
  82. result = m_ChannelMgr->ReadChannelData(m_ChannelName, data);
  83. DC_END_FN();
  84. return result;
  85. }
  86. STDMETHODIMP
  87. CTSRDPServerDataChannel::SendChannelData(
  88. BSTR data
  89. )
  90. /*++
  91. Routine Description:
  92. Send data on this channel.
  93. Arguments:
  94. data - Data to send.
  95. Return Value:
  96. S_OK on success. Otherwise, an error result is returned.
  97. --*/
  98. {
  99. HRESULT hr;
  100. DC_BEGIN_FN("CTSRDPServerDataChannel::SendChannelData");
  101. hr = m_ChannelMgr->SendChannelData(m_ChannelName, data);
  102. DC_END_FN();
  103. return hr;
  104. }
  105. STDMETHODIMP
  106. CTSRDPServerDataChannel::put_OnChannelDataReady(
  107. IDispatch * newVal
  108. )
  109. /*++
  110. Routine Description:
  111. SAFRemoteDesktopDataChannel Scriptable Event Object Registration
  112. Properties
  113. Arguments:
  114. Return Value:
  115. S_OK on success. Otherwise, an error status is returned.
  116. --*/
  117. {
  118. DC_BEGIN_FN("CTSRDPServerDataChannel::put_OnChannelDataReady");
  119. m_OnChannelDataReady = newVal;
  120. DC_END_FN();
  121. return S_OK;
  122. }
  123. STDMETHODIMP
  124. CTSRDPServerDataChannel::get_ChannelName(
  125. BSTR *pVal
  126. )
  127. /*++
  128. Routine Description:
  129. Return the channel name.
  130. Arguments:
  131. pVal - Returned channel name.
  132. Return Value:
  133. S_OK on success. Otherwise, an error status is returned.
  134. --*/
  135. {
  136. DC_BEGIN_FN("CTSRDPServerDataChannel::get_ChannelName");
  137. CComBSTR str;
  138. str = m_ChannelName;
  139. *pVal = str.Detach();
  140. DC_END_FN();
  141. return S_OK;
  142. }
  143. /*++
  144. Routine Description:
  145. Called when data is ready on our channel.
  146. Arguments:
  147. pVal - Returned channel name.
  148. Return Value:
  149. S_OK on success. Otherwise, an error status is returned.
  150. --*/
  151. VOID
  152. CTSRDPServerDataChannel::DataReady()
  153. {
  154. DC_BEGIN_FN("CTSRDPServerDataChannel::DataReady");
  155. //
  156. // Fire our data ready event.
  157. //
  158. Fire_ChannelDataReady(m_ChannelName, m_OnChannelDataReady);
  159. DC_END_FN();
  160. }
  161. ///////////////////////////////////////////////////////
  162. //
  163. // CTSRDPServerChannelMgr Methods
  164. //
  165. CTSRDPServerChannelMgr::CTSRDPServerChannelMgr()
  166. /*++
  167. Routine Description:
  168. Constructor
  169. Arguments:
  170. Return Value:
  171. --*/
  172. {
  173. DC_BEGIN_FN("CTSRDPServerChannelMgr::CTSRDPServerChannelMgr");
  174. m_IOThreadBridge = NULL;
  175. m_IOThreadBridgeThreadID = 0;
  176. m_IOThreadBridgeStream = NULL;
  177. m_VCAddInPipe = INVALID_HANDLE_VALUE;
  178. m_Connected = FALSE;
  179. m_ReadIOCompleteEvent = NULL;
  180. m_WriteIOCompleteEvent = NULL;
  181. m_PipeCreateEvent = NULL;
  182. m_IncomingBufferSize = 0;
  183. m_IncomingBuffer = NULL;
  184. TRC_NRM((TB, L"***Ref count is: %ld", m_dwRef));
  185. #if DBG
  186. m_LockCount = 0;
  187. #endif
  188. m_IOThreadHndl = NULL;
  189. //
  190. // Initialize the critical section.
  191. //
  192. InitializeCriticalSection(&m_cs);
  193. //
  194. // Not valid, until initialized.
  195. //
  196. SetValid(FALSE);
  197. DC_END_FN();
  198. }
  199. CTSRDPServerChannelMgr::~CTSRDPServerChannelMgr()
  200. /*++
  201. Routine Description:
  202. Destructor
  203. Arguments:
  204. Return Value:
  205. --*/
  206. {
  207. DC_BEGIN_FN("CTSRDPServerChannelMgr::~CTSRDPServerChannelMgr");
  208. //
  209. // Make sure we are no longer listening for data.
  210. //
  211. StopListening();
  212. //
  213. // Close the read IO processing event.
  214. //
  215. if (m_ReadIOCompleteEvent != NULL) {
  216. CloseHandle(m_ReadIOCompleteEvent);
  217. m_ReadIOCompleteEvent = NULL;
  218. }
  219. //
  220. // Close the write IO processing event.
  221. //
  222. if (m_WriteIOCompleteEvent != NULL) {
  223. CloseHandle(m_WriteIOCompleteEvent);
  224. m_WriteIOCompleteEvent = NULL;
  225. }
  226. //
  227. // Release the incoming buffer.
  228. //
  229. if (m_IncomingBuffer != NULL) {
  230. SysFreeString(m_IncomingBuffer);
  231. m_IncomingBuffer = NULL;
  232. }
  233. if (m_PipeCreateEvent != NULL) {
  234. CloseHandle(m_PipeCreateEvent);
  235. m_PipeCreateEvent = NULL;
  236. }
  237. if( NULL != m_IOThreadHndl ) {
  238. CloseHandle( m_IOThreadHndl );
  239. m_IOThreadHndl = NULL;
  240. }
  241. //
  242. // This should have been cleaned up in the background thread.
  243. //
  244. ASSERT(m_IOThreadBridge == NULL);
  245. ASSERT(m_IOThreadBridgeStream == NULL);
  246. DeleteCriticalSection(&m_cs);
  247. DC_END_FN();
  248. }
  249. HRESULT
  250. CTSRDPServerChannelMgr::Initialize(
  251. CTSRDPRemoteDesktopSession *sessionObject,
  252. BSTR helpSessionID
  253. )
  254. /*++
  255. Routine Description:
  256. Initialize an instance of this class.
  257. Arguments:
  258. sessionObject - Back pointer to the containing
  259. session object.
  260. Return Value:
  261. S_OK is returned on success. Otherwise, an error code
  262. is returned.
  263. --*/
  264. {
  265. DC_BEGIN_FN("CTSRDPServerChannelMgr::Initialize");
  266. HRESULT result = ERROR_SUCCESS;
  267. TRC_NRM((TB, L"***Ref count is: %ld", m_dwRef));
  268. //
  269. // Record help session id.
  270. //
  271. m_HelpSessionID = helpSessionID;
  272. //
  273. // Record the containing session object.
  274. //
  275. m_RDPSessionObject = sessionObject;
  276. //
  277. // Set the initial buffer size and buffer to be at least the
  278. // size of a channel buffer header.
  279. //
  280. ASSERT(m_IncomingBuffer == NULL);
  281. m_IncomingBuffer = SysAllocStringByteLen(
  282. NULL,
  283. INCOMINGBUFFER_RESIZEDELTA
  284. );
  285. if (m_IncomingBuffer == NULL) {
  286. result = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  287. goto CLEANUPANDEXIT;
  288. }
  289. m_IncomingBufferSize = INCOMINGBUFFER_RESIZEDELTA;
  290. //
  291. // Create the read IO processing event.
  292. //
  293. ASSERT(m_ReadIOCompleteEvent == NULL);
  294. m_ReadIOCompleteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  295. if (m_ReadIOCompleteEvent == NULL) {
  296. result = HRESULT_FROM_WIN32(GetLastError());
  297. TRC_ERR((TB, L"CreateEvent: %08X", result));
  298. goto CLEANUPANDEXIT;
  299. }
  300. //
  301. // Create the write IO processing event.
  302. //
  303. ASSERT(m_WriteIOCompleteEvent == NULL);
  304. m_WriteIOCompleteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  305. if (m_WriteIOCompleteEvent == NULL) {
  306. result = HRESULT_FROM_WIN32(GetLastError());
  307. TRC_ERR((TB, L"CreateEvent: %08X", result));
  308. goto CLEANUPANDEXIT;
  309. }
  310. //
  311. // Create the named pipe create event
  312. //
  313. ASSERT(m_PipeCreateEvent == NULL);
  314. m_PipeCreateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  315. if (m_PipeCreateEvent == NULL) {
  316. result = HRESULT_FROM_WIN32(GetLastError());
  317. TRC_ERR((TB, L"CreateEvent: %08X", result));
  318. goto CLEANUPANDEXIT;
  319. }
  320. //
  321. // Initialize the parent class.
  322. //
  323. result = CRemoteDesktopChannelMgr::Initialize();
  324. if (result != S_OK) {
  325. goto CLEANUPANDEXIT;
  326. }
  327. //
  328. // We are valid, if we made it here.
  329. //
  330. SetValid(TRUE);
  331. TRC_NRM((TB, L"***Ref count is: %ld", m_dwRef));
  332. CLEANUPANDEXIT:
  333. DC_END_FN();
  334. return result;
  335. }
  336. VOID
  337. CTSRDPServerChannelMgr::ClosePipe()
  338. /*++
  339. Routine Description:
  340. Close the named pipe.
  341. Arguments:
  342. Return Value:
  343. --*/
  344. {
  345. DC_BEGIN_FN("CTSRDPServerChannelMgr::ClosePipe");
  346. ASSERT(m_VCAddInPipe != INVALID_HANDLE_VALUE);
  347. FlushFileBuffers(m_VCAddInPipe);
  348. //
  349. // reset the pipe creation event so that the foreground
  350. // thread can wait for the next help session
  351. //
  352. ResetEvent(m_PipeCreateEvent);
  353. DisconnectNamedPipe(m_VCAddInPipe);
  354. CloseHandle(m_VCAddInPipe);
  355. m_VCAddInPipe = INVALID_HANDLE_VALUE;
  356. m_Connected = FALSE;
  357. DC_END_FN();
  358. }
  359. HRESULT
  360. CTSRDPServerChannelMgr::StartListening(
  361. BSTR assistAccount
  362. )
  363. /*++
  364. Routine Description:
  365. Start listening for data channel data.
  366. Arguments:
  367. assistAccount - Name of machine assistant account.
  368. Return Value:
  369. S_OK is returned on success. Otherwise, an error code
  370. is returned.
  371. --*/
  372. {
  373. DC_BEGIN_FN("CTSRDPServerChannelMgr::StartListening");
  374. HRESULT hr = S_OK;
  375. if (!IsValid()) {
  376. ASSERT(FALSE);
  377. hr = E_FAIL;
  378. goto CLEANUPANDEXIT;
  379. }
  380. //
  381. // If the background thread is still active, then fail. This
  382. // means that it is still trying to shut down.
  383. //
  384. if (m_IOThreadHndl != NULL) {
  385. if (WaitForSingleObject(m_IOThreadHndl, 0) == WAIT_OBJECT_0) {
  386. CloseHandle( m_IOThreadHndl );
  387. m_IOThreadHndl = NULL;
  388. }
  389. else {
  390. TRC_ERR((TB, L"Background thread not shut down, yet: %08X.",
  391. GetLastError()));
  392. hr = HRESULT_FROM_WIN32(ERROR_ACTIVE_CONNECTIONS);
  393. goto CLEANUPANDEXIT;
  394. }
  395. }
  396. //
  397. // Make the thread bridge interface available to the background thread.
  398. //
  399. hr = CoMarshalInterThreadInterfaceInStream(
  400. IID_IRDSThreadBridge,
  401. (ISAFRemoteDesktopChannelMgr*)this,
  402. &m_IOThreadBridgeStream
  403. );
  404. if (!SUCCEEDED(hr)) {
  405. TRC_ERR((TB, TEXT("CoMarshalInterThreadInterfaceInStream: %08X"), hr));
  406. goto CLEANUPANDEXIT;
  407. }
  408. //
  409. // Reset the connected flag.
  410. //
  411. m_Connected = FALSE;
  412. //
  413. // Record the machine assistant account name.
  414. //
  415. ASSERT(assistAccount != NULL);
  416. m_AssistAccount = assistAccount;
  417. //
  418. // Reset the read IO processing event.
  419. //
  420. ASSERT(m_ReadIOCompleteEvent != NULL);
  421. ResetEvent(m_ReadIOCompleteEvent);
  422. //
  423. // Reset the write IO processing event.
  424. //
  425. ASSERT(m_WriteIOCompleteEvent != NULL);
  426. ResetEvent(m_WriteIOCompleteEvent);
  427. //
  428. //reset the named pipe creation event
  429. ASSERT(m_PipeCreateEvent != NULL);
  430. ResetEvent(m_PipeCreateEvent);
  431. //
  432. // Create the background thread that receives data from the
  433. // named pipe.
  434. //
  435. ASSERT(m_IOThreadHndl == NULL);
  436. m_IOThreadHndl = CreateThread(
  437. NULL, 0,
  438. (LPTHREAD_START_ROUTINE)_IOThread,
  439. this,
  440. 0,&m_IOThreadID
  441. );
  442. if (m_IOThreadHndl == NULL) {
  443. hr = HRESULT_FROM_WIN32(GetLastError());
  444. TRC_ERR((TB, TEXT("CreateThread: %08X"), hr));
  445. goto CLEANUPANDEXIT;
  446. }
  447. //
  448. //wait for the named pipe creation event to be signaled
  449. //and check for the result. If failed, bail
  450. //
  451. WaitForSingleObject(m_PipeCreateEvent, INFINITE);
  452. //
  453. //set the error to pipe_busy because we assume that someone else
  454. //has already created it and that is the reason the CreateNamedPipe call failed.
  455. //
  456. if (m_VCAddInPipe == INVALID_HANDLE_VALUE) {
  457. hr = HRESULT_FROM_WIN32(ERROR_PIPE_BUSY);
  458. TRC_ERR((TB, L"CreateNamedPipe returned fail"));
  459. goto CLEANUPANDEXIT;
  460. }
  461. CLEANUPANDEXIT:
  462. DC_END_FN();
  463. return hr;
  464. }
  465. HRESULT
  466. CTSRDPServerChannelMgr::StopListening()
  467. /*++
  468. Routine Description:
  469. Stop listening for data channel data.
  470. Arguments:
  471. Return Value:
  472. S_OK is returned on success. Otherwise, an error code
  473. is returned.
  474. --*/
  475. {
  476. DC_BEGIN_FN("CTSRDPServerChannelMgr::StopListening");
  477. DWORD waitResult;
  478. //
  479. // Close the named pipe.
  480. //
  481. ThreadLock();
  482. if (m_VCAddInPipe != INVALID_HANDLE_VALUE) {
  483. ClosePipe();
  484. }
  485. ThreadUnlock();
  486. TRC_NRM((TB, L"***Ref count is: %ld", m_dwRef));
  487. DC_END_FN();
  488. return S_OK;
  489. }
  490. HRESULT
  491. CTSRDPServerChannelMgr::SendData(
  492. PREMOTEDESKTOP_CHANNELBUFHEADER msg
  493. )
  494. /*++
  495. Routine Description:
  496. Send Function Invoked by Parent Class
  497. Arguments:
  498. msg - Message data. Note that the underlying representation
  499. for this data structure is a BSTR so that it is compatible
  500. with COM methods.
  501. Return Value:
  502. S_OK is returned on success. Otherwise, an error code
  503. is returned.
  504. --*/
  505. {
  506. DC_BEGIN_FN("CTSRDPServerChannelMgr::SendData");
  507. HRESULT result = S_OK;
  508. DWORD bytesWritten;
  509. OVERLAPPED ol;
  510. DWORD msgLen;
  511. if (!IsValid()) {
  512. ASSERT(FALSE);
  513. result = E_FAIL;
  514. goto CLEANUPANDEXIT;
  515. }
  516. if (m_Connected) {
  517. //
  518. // Write the header.
  519. //
  520. memset(&ol, 0, sizeof(ol));
  521. ol.hEvent = m_WriteIOCompleteEvent;
  522. ResetEvent(ol.hEvent);
  523. BOOL ret = WriteFile(
  524. m_VCAddInPipe,
  525. msg,
  526. sizeof(REMOTEDESKTOP_CHANNELBUFHEADER),
  527. NULL,
  528. &ol
  529. );
  530. if (ret || (!ret && (GetLastError() == ERROR_IO_PENDING))) {
  531. ret = GetOverlappedResult(
  532. m_VCAddInPipe,
  533. &ol,
  534. &bytesWritten,
  535. TRUE
  536. );
  537. }
  538. if (!ret) {
  539. result = HRESULT_FROM_WIN32(GetLastError());
  540. TRC_ALT((TB, TEXT("Header write failed: %08X"), result));
  541. goto CLEANUPANDEXIT;
  542. }
  543. ASSERT(bytesWritten == sizeof(REMOTEDESKTOP_CHANNELBUFHEADER));
  544. //
  545. // Write the rest of the message.
  546. //
  547. msgLen = msg->dataLen + msg->channelNameLen;
  548. memset(&ol, 0, sizeof(ol));
  549. ol.hEvent = m_WriteIOCompleteEvent;
  550. ResetEvent(ol.hEvent);
  551. ret = WriteFile(
  552. m_VCAddInPipe,
  553. (PBYTE)(msg+1),
  554. msgLen,
  555. NULL,
  556. &ol
  557. );
  558. if (ret || (!ret && (GetLastError() == ERROR_IO_PENDING))) {
  559. ret = GetOverlappedResult(
  560. m_VCAddInPipe,
  561. &ol,
  562. &bytesWritten,
  563. TRUE
  564. );
  565. }
  566. if (!ret) {
  567. result = HRESULT_FROM_WIN32(GetLastError());
  568. TRC_ALT((TB, TEXT("Message write failed: %08X"), result));
  569. goto CLEANUPANDEXIT;
  570. }
  571. ASSERT(bytesWritten == msgLen);
  572. }
  573. else {
  574. result = HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE);
  575. }
  576. CLEANUPANDEXIT:
  577. //
  578. // If there was an error, we should close the pipe so it
  579. // can be reopened in the background thread.
  580. //
  581. if (result != S_OK) {
  582. ThreadLock();
  583. if (m_VCAddInPipe != INVALID_HANDLE_VALUE) {
  584. ClosePipe();
  585. }
  586. ThreadUnlock();
  587. }
  588. DC_END_FN();
  589. return result;
  590. }
  591. DWORD
  592. CTSRDPServerChannelMgr::IOThread()
  593. /*++
  594. Routine Description:
  595. Background Thread Managing Named Pipe Connection to the
  596. TSRDP Assistant SessionVC Add-In.
  597. Arguments:
  598. Return Value:
  599. Returns 0
  600. --*/
  601. {
  602. DC_BEGIN_FN("CTSRDPServerChannelMgr::IOThread");
  603. DWORD result;
  604. DWORD lastError;
  605. WCHAR pipePath[MAX_PATH+1];
  606. OVERLAPPED ol;
  607. DWORD waitResult;
  608. WCHAR pipeName[MAX_PATH];
  609. PSECURITY_ATTRIBUTES pipeAttribs = NULL;
  610. //
  611. // Notify the parent class that the IO thread is being initialized.
  612. //
  613. result = IOThreadInit();
  614. if (result != ERROR_SUCCESS) {
  615. goto CLEANUPANDEXIT;
  616. }
  617. //
  618. // Get the security descriptor for the named pipe.
  619. //
  620. pipeAttribs = GetPipeSecurityAttribs(m_AssistAccount);
  621. if (pipeAttribs == NULL) {
  622. result = GetLastError();
  623. goto CLEANUPANDEXIT;
  624. }
  625. lastError = ERROR_SUCCESS;
  626. ASSERT(!m_Connected);
  627. //
  628. // Handle connections by the TSRDP Assistant SessionVC Add-In
  629. // until we are supposed to shut down.
  630. //
  631. ASSERT(m_VCAddInPipe == INVALID_HANDLE_VALUE);
  632. ASSERT(!m_Connected);
  633. wsprintf(pipeName, L"%s-%s", TSRDPREMOTEDESKTOP_PIPENAME, m_HelpSessionID);
  634. wsprintf(pipePath, L"\\\\.\\pipe\\%s", pipeName);
  635. m_VCAddInPipe = CreateNamedPipe(
  636. pipePath,
  637. PIPE_ACCESS_DUPLEX |
  638. FILE_FLAG_OVERLAPPED,
  639. PIPE_TYPE_MESSAGE |
  640. PIPE_READMODE_MESSAGE |
  641. PIPE_WAIT,
  642. 1,
  643. TSRDPREMOTEDESKTOP_PIPEBUFSIZE,
  644. TSRDPREMOTEDESKTOP_PIPEBUFSIZE,
  645. TSRDPREMOTEDESKTOP_PIPETIMEOUT,
  646. pipeAttribs
  647. );
  648. //
  649. //signal the foreground thread about the pipe creation result
  650. //
  651. SetEvent(m_PipeCreateEvent);
  652. if (m_VCAddInPipe == INVALID_HANDLE_VALUE) {
  653. lastError = GetLastError();
  654. TRC_ERR((TB, TEXT("CreatePipe: %08X. Shutting down background thread."),
  655. lastError));
  656. goto CLEANUPANDEXIT;
  657. }
  658. //
  659. // Wait for the TSRDP Assistant SesionVC Add-In to connect.
  660. // If it succeeds, the function returns a nonzero value. If the
  661. // function returns zero, GetLastError returns ERROR_PIPE_CONNECTED.
  662. //
  663. memset(&ol, 0, sizeof(ol));
  664. ol.hEvent = m_ReadIOCompleteEvent;
  665. ResetEvent(ol.hEvent);
  666. if (!ConnectNamedPipe(m_VCAddInPipe, &ol) && (GetLastError() == ERROR_IO_PENDING)) {
  667. TRC_NRM((TB, L"Waiting for connect."));
  668. //
  669. // Wait for the connect event to fire.
  670. //
  671. waitResult = WaitForSingleObject(m_ReadIOCompleteEvent, INFINITE);
  672. if (waitResult != WAIT_OBJECT_0)
  673. {
  674. m_Connected = FALSE;
  675. }
  676. //
  677. // Otherwise, if the io complete event fired.
  678. //
  679. else
  680. {
  681. //
  682. // If the io complete event fired.
  683. //
  684. TRC_NRM((TB, L"Connect event signaled."));
  685. DWORD ignored;
  686. m_Connected = GetOverlappedResult(m_VCAddInPipe, &ol, &ignored, TRUE);
  687. if (!m_Connected) {
  688. lastError = GetLastError();
  689. TRC_ERR((TB, L"GetOverlappedResult: %08X", lastError));
  690. }
  691. else {
  692. TRC_NRM((TB, L"Connection established."));
  693. }
  694. }
  695. } //!ConnectNamedPipe
  696. else if (GetLastError() == ERROR_PIPE_CONNECTED) {
  697. TRC_NRM((TB, L"Connected without pending."));
  698. m_Connected = TRUE;
  699. }
  700. else {
  701. lastError = GetLastError();
  702. TRC_ERR((TB, L"ConnectNamedPipe: %08X", lastError));
  703. }
  704. //
  705. // If we got a valid connection, process reads until the pipe is
  706. // disconnected, after notifying the parent class that we have
  707. // a valid connection.
  708. //
  709. if (m_Connected) {
  710. //
  711. // Notify the foreground thread that the client connected.
  712. //
  713. m_IOThreadBridge->ClientConnectedNotify();
  714. ProcessPipeMessagesUntilDisconnect();
  715. //
  716. // Notify the foreground thread that the the client has disconnected.
  717. //
  718. m_IOThreadBridge->ClientDisconnectedNotify();
  719. }
  720. CLEANUPANDEXIT:
  721. //
  722. // Close the pipe if it is still open.
  723. //
  724. ThreadLock();
  725. if (m_VCAddInPipe != INVALID_HANDLE_VALUE) {
  726. ClosePipe();
  727. }
  728. ThreadUnlock();
  729. //
  730. // Clean up the named pipe security attribs.
  731. //
  732. if (pipeAttribs != NULL) {
  733. FreePipeSecurityAttribs(pipeAttribs);
  734. }
  735. //
  736. // Notify the parent class that the IO thread is shutting down.
  737. // The parent class will signal this event when the class is completely
  738. // shut down.
  739. //
  740. result = IOThreadShutdown(NULL);
  741. DC_END_FN();
  742. return result;
  743. }
  744. DWORD CTSRDPServerChannelMgr::_IOThread(
  745. CTSRDPServerChannelMgr *instance
  746. )
  747. {
  748. return instance->IOThread();
  749. }
  750. VOID
  751. CTSRDPServerChannelMgr::ProcessPipeMessagesUntilDisconnect()
  752. /*++
  753. Routine Description:
  754. Process messages on the named pipe until it disconnects or
  755. until the shutdown flag is set.
  756. Arguments:
  757. Return Value:
  758. --*/
  759. {
  760. DC_BEGIN_FN("CTSRDPServerChannelMgr::ProcessPipeMessagesUntilDisconnect");
  761. DWORD bytesRead;
  762. DWORD result;
  763. PREMOTEDESKTOP_CHANNELBUFHEADER hdr;
  764. DWORD msgLen;
  765. //
  766. // Loop until the connection is terminated or we are to shut down.
  767. //
  768. while (m_Connected) {
  769. //
  770. // Read the next buffer header.
  771. //
  772. ASSERT(m_IncomingBufferSize >= sizeof(REMOTEDESKTOP_CHANNELBUFHEADER));
  773. result = ReadNextPipeMessage(
  774. sizeof(REMOTEDESKTOP_CHANNELBUFHEADER),
  775. &bytesRead,
  776. (PBYTE)m_IncomingBuffer
  777. );
  778. if ((result != ERROR_SUCCESS) && (result != ERROR_MORE_DATA)) {
  779. break;
  780. }
  781. ASSERT(bytesRead == sizeof(REMOTEDESKTOP_CHANNELBUFHEADER));
  782. hdr = (PREMOTEDESKTOP_CHANNELBUFHEADER)m_IncomingBuffer;
  783. #ifdef USE_MAGICNO
  784. ASSERT(hdr->magicNo == CHANNELBUF_MAGICNO);
  785. #endif
  786. //
  787. // Size the incoming buffer.
  788. //
  789. msgLen = hdr->dataLen + hdr->channelNameLen;
  790. if (m_IncomingBufferSize < msgLen) {
  791. DWORD sz = msgLen + sizeof(REMOTEDESKTOP_CHANNELBUFHEADER);
  792. m_IncomingBuffer = (BSTR)ReallocBSTR(
  793. m_IncomingBuffer, sz
  794. );
  795. if (m_IncomingBuffer != NULL) {
  796. hdr = (PREMOTEDESKTOP_CHANNELBUFHEADER)m_IncomingBuffer;
  797. m_IncomingBufferSize = sz;
  798. }
  799. else {
  800. TRC_ERR((TB, L"Can't resize %ld bytes for incoming buffer.",
  801. m_IncomingBufferSize + INCOMINGBUFFER_RESIZEDELTA));
  802. m_IncomingBufferSize = 0;
  803. break;
  804. }
  805. }
  806. //
  807. // Read the buffer data.
  808. //
  809. result = ReadNextPipeMessage(
  810. msgLen,
  811. &bytesRead,
  812. ((PBYTE)m_IncomingBuffer) + sizeof(REMOTEDESKTOP_CHANNELBUFHEADER)
  813. );
  814. if (result != ERROR_SUCCESS) {
  815. break;
  816. }
  817. ASSERT(bytesRead == msgLen);
  818. //
  819. // Process the complete buffer in the foreground thread.
  820. //
  821. m_IOThreadBridge->DataReadyNotify(m_IncomingBuffer);
  822. }
  823. //
  824. // We are here because something went wrong and we should disconnect.
  825. //
  826. ThreadLock();
  827. if (m_VCAddInPipe != INVALID_HANDLE_VALUE) {
  828. ClosePipe();
  829. }
  830. ThreadUnlock();
  831. DC_END_FN();
  832. }
  833. DWORD
  834. CTSRDPServerChannelMgr::ReadNextPipeMessage(
  835. IN DWORD bytesToRead,
  836. OUT DWORD *bytesRead,
  837. IN PBYTE buf
  838. )
  839. /*++
  840. Abstract:
  841. Read the next message from the pipe.
  842. Parameter:
  843. bytesToRead - Number of bytes to read.
  844. bytesRead - Number of bytes read.
  845. buf - Buffer for data read.
  846. Returns:
  847. ERROR_SUCCESS on success. Otherwise, a windows error code is
  848. returned.
  849. --*/
  850. {
  851. DC_BEGIN_FN("CTSRDPServerChannelMgr::ReadNextPipeMessage");
  852. OVERLAPPED ol;
  853. BOOL result;
  854. DWORD lastError;
  855. DWORD waitResult;
  856. memset(&ol, 0, sizeof(ol));
  857. ol.hEvent = m_ReadIOCompleteEvent;
  858. ResetEvent(ol.hEvent);
  859. lastError = ERROR_SUCCESS;
  860. result = ReadFile(m_VCAddInPipe, buf, bytesToRead, bytesRead, &ol);
  861. if (!result) {
  862. //
  863. // If IO is pending.
  864. //
  865. lastError = GetLastError();
  866. if (lastError == ERROR_IO_PENDING) {
  867. //
  868. // Wait for the read to finish and for the shutdown event to fire.
  869. //
  870. waitResult = WaitForSingleObject(m_ReadIOCompleteEvent, INFINITE);
  871. if (waitResult == WAIT_OBJECT_0)
  872. {
  873. if (GetOverlappedResult(m_VCAddInPipe, &ol, bytesRead, TRUE)) {
  874. lastError = ERROR_SUCCESS;
  875. }
  876. else {
  877. lastError = GetLastError();
  878. TRC_ALT((TB, L"GetOverlappedResult: %08X", lastError));
  879. }
  880. }
  881. else {
  882. lastError = GetLastError();
  883. TRC_NRM((TB, L"WaitForSingleObject failed : %08x", lastError));
  884. }
  885. }
  886. }
  887. else {
  888. lastError = ERROR_SUCCESS;
  889. }
  890. DC_END_FN();
  891. return lastError;
  892. }
  893. PSECURITY_ATTRIBUTES
  894. CTSRDPServerChannelMgr::GetPipeSecurityAttribs(
  895. IN LPTSTR assistantUserName
  896. )
  897. /*++
  898. Abstract:
  899. Returns the security attribs for the named pipe.
  900. Parameter:
  901. assistantUserName - Machine assistant user account.
  902. Returns:
  903. NULL on error. Otherwise, the security attribs are returned
  904. and should be freed via call to FREEMEM. On error, GetLastError()
  905. can be used to get extended error information.
  906. --*/
  907. {
  908. PACL pAcl=NULL;
  909. DWORD sidSz;
  910. DWORD domainSz;
  911. PSID pCurrentUserSid = NULL;
  912. PSID pHelpAssistantSid = NULL;
  913. DWORD result = ERROR_SUCCESS;
  914. PSECURITY_ATTRIBUTES attribs = NULL;
  915. SID_NAME_USE sidNameUse;
  916. DWORD aclSz;
  917. HANDLE userToken = NULL;
  918. WCHAR *domainName = NULL;
  919. DC_BEGIN_FN("CTSRDPServerChannelMgr::GetPipeSecurityAttribs");
  920. //
  921. // Allocate the security attributes.
  922. //
  923. attribs = (PSECURITY_ATTRIBUTES)ALLOCMEM(sizeof(SECURITY_ATTRIBUTES));
  924. if (attribs == NULL) {
  925. TRC_ERR((TB, L"Can't allocate security attribs."));
  926. result = ERROR_NOT_ENOUGH_MEMORY;
  927. goto CLEANUPANDEXIT;
  928. }
  929. memset(attribs, 0, sizeof(SECURITY_ATTRIBUTES));
  930. //
  931. // Allocate the security descriptor.
  932. //
  933. attribs->lpSecurityDescriptor = ALLOCMEM(sizeof(SECURITY_DESCRIPTOR));
  934. if (attribs->lpSecurityDescriptor == NULL) {
  935. TRC_ERR((TB, L"Can't allocate SD"));
  936. result = ERROR_NOT_ENOUGH_MEMORY;
  937. goto CLEANUPANDEXIT;
  938. }
  939. //
  940. // Initialize the security descriptor.
  941. //
  942. if (!InitializeSecurityDescriptor(
  943. attribs->lpSecurityDescriptor,
  944. SECURITY_DESCRIPTOR_REVISION
  945. )) {
  946. result = GetLastError();
  947. TRC_ERR((TB, L"InitializeSecurityDescriptor: %08X", result));
  948. goto CLEANUPANDEXIT;
  949. }
  950. //
  951. // Get the token for the current process.
  952. //
  953. if (!OpenProcessToken(
  954. GetCurrentProcess(),
  955. TOKEN_QUERY,
  956. &userToken
  957. )) {
  958. result = GetLastError();
  959. TRC_ERR((TB, L"OpenProcessToken: %08X", result));
  960. goto CLEANUPANDEXIT;
  961. }
  962. //
  963. // Get the SID for the current user.
  964. //
  965. pCurrentUserSid = GetUserSid(userToken);
  966. if (pCurrentUserSid == NULL) {
  967. result = GetLastError();
  968. goto CLEANUPANDEXIT;
  969. }
  970. //
  971. // Get the size for the assistant account user SID.
  972. //
  973. domainSz = 0; sidSz = 0;
  974. if (!LookupAccountName(NULL, assistantUserName, NULL,
  975. &sidSz, NULL, &domainSz, &sidNameUse
  976. ) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
  977. result = GetLastError();
  978. TRC_ERR((TB, L"LookupAccountName: %08X", result));
  979. goto CLEANUPANDEXIT;
  980. }
  981. //
  982. // Allocate the SID.
  983. //
  984. pHelpAssistantSid = (PSID)ALLOCMEM(sidSz);
  985. if (pHelpAssistantSid == NULL) {
  986. TRC_ERR((TB, L"Can't allocate help asistant SID."));
  987. result = ERROR_NOT_ENOUGH_MEMORY;
  988. goto CLEANUPANDEXIT;
  989. }
  990. //
  991. // Allocate the domain name.
  992. //
  993. domainName = (WCHAR *)ALLOCMEM(domainSz * sizeof(WCHAR));
  994. if (domainName == NULL) {
  995. TRC_ERR((TB, L"Can't allocate domain"));
  996. result = ERROR_NOT_ENOUGH_MEMORY;
  997. goto CLEANUPANDEXIT;
  998. }
  999. //
  1000. // Get the assistant account SID.
  1001. //
  1002. if (!LookupAccountName(NULL, assistantUserName, pHelpAssistantSid,
  1003. &sidSz, domainName, &domainSz, &sidNameUse
  1004. )) {
  1005. result = GetLastError();
  1006. TRC_ERR((TB, L"LookupAccountName: %08X", result));
  1007. goto CLEANUPANDEXIT;
  1008. }
  1009. //
  1010. // Allocate space for the ACL.
  1011. //
  1012. aclSz = GetLengthSid(pCurrentUserSid) +
  1013. GetLengthSid(pHelpAssistantSid) +
  1014. sizeof(ACL) +
  1015. (2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  1016. pAcl = (PACL)ALLOCMEM(aclSz);
  1017. if(pAcl == NULL) {
  1018. TRC_ERR((TB, L"Can't allocate ACL"));
  1019. result = ERROR_NOT_ENOUGH_MEMORY;
  1020. goto CLEANUPANDEXIT;
  1021. }
  1022. //
  1023. // Initialize the ACL.
  1024. //
  1025. if (!InitializeAcl(pAcl, aclSz, ACL_REVISION)) {
  1026. result = GetLastError();
  1027. TRC_ERR((TB, L"InitializeACL: %08X", result));
  1028. goto CLEANUPANDEXIT;
  1029. }
  1030. //
  1031. // Add the current user ace.
  1032. //
  1033. if (!AddAccessAllowedAce(pAcl,
  1034. ACL_REVISION,
  1035. GENERIC_READ | GENERIC_WRITE | GENERIC_ALL,
  1036. pCurrentUserSid
  1037. )) {
  1038. result = GetLastError();
  1039. TRC_ERR((TB, L"AddAccessAllowedAce: %08X", result));
  1040. goto CLEANUPANDEXIT;
  1041. }
  1042. //
  1043. // Add the help assistant ace.
  1044. //
  1045. if (!AddAccessAllowedAce(pAcl,
  1046. ACL_REVISION,
  1047. GENERIC_READ | GENERIC_WRITE | GENERIC_ALL,
  1048. pHelpAssistantSid
  1049. )) {
  1050. result = GetLastError();
  1051. TRC_ERR((TB, L"AddAccessAllowedAce: %08X", result));
  1052. goto CLEANUPANDEXIT;
  1053. }
  1054. //
  1055. // Set the secrity descriptor discretionary ACL.
  1056. //
  1057. if (!SetSecurityDescriptorDacl(attribs->lpSecurityDescriptor,
  1058. TRUE, pAcl, FALSE)) {
  1059. result = GetLastError();
  1060. TRC_ERR((TB, L"SetSecurityDescriptorDacl: %08X", result));
  1061. goto CLEANUPANDEXIT;
  1062. }
  1063. CLEANUPANDEXIT:
  1064. if (pCurrentUserSid != NULL) {
  1065. FREEMEM(pCurrentUserSid);
  1066. }
  1067. if (pHelpAssistantSid != NULL) {
  1068. FREEMEM(pHelpAssistantSid);
  1069. }
  1070. if (domainName != NULL) {
  1071. FREEMEM(domainName);
  1072. }
  1073. if( userToken != NULL ) {
  1074. CloseHandle( userToken );
  1075. }
  1076. //
  1077. // Clean up on error.
  1078. //
  1079. if (result != ERROR_SUCCESS) {
  1080. if (attribs != NULL) {
  1081. FreePipeSecurityAttribs(attribs);
  1082. attribs = NULL;
  1083. }
  1084. }
  1085. SetLastError(result);
  1086. DC_END_FN();
  1087. return attribs;
  1088. }
  1089. VOID
  1090. CTSRDPServerChannelMgr::FreePipeSecurityAttribs(
  1091. PSECURITY_ATTRIBUTES attribs
  1092. )
  1093. /*++
  1094. Abstract:
  1095. Release security attribs allocated via a call to GetPipeSecurityAttribs
  1096. Parameter:
  1097. attribs - Attribs returned by GetPipeSecurityAttribs.
  1098. Returns:
  1099. --*/
  1100. {
  1101. BOOL daclPresent;
  1102. PACL pDacl = NULL;
  1103. BOOL daclDefaulted;
  1104. DC_BEGIN_FN("CTSRDPServerChannelMgr::FreePipeSecurityAttribs");
  1105. ASSERT(attribs != NULL);
  1106. if (attribs->lpSecurityDescriptor) {
  1107. if (GetSecurityDescriptorDacl(
  1108. attribs->lpSecurityDescriptor,
  1109. &daclPresent,
  1110. &pDacl,
  1111. &daclDefaulted
  1112. )) {
  1113. ASSERT(!daclDefaulted);
  1114. if (pDacl != NULL) {
  1115. FREEMEM(pDacl);
  1116. }
  1117. }
  1118. FREEMEM(attribs->lpSecurityDescriptor);
  1119. }
  1120. FREEMEM(attribs);
  1121. DC_END_FN();
  1122. }
  1123. PSID
  1124. CTSRDPServerChannelMgr::GetUserSid(
  1125. IN HANDLE userToken
  1126. )
  1127. /*++
  1128. Routine Description:
  1129. Get the SID for a particular user.
  1130. Arguments:
  1131. Access Token for the User
  1132. Return Value:
  1133. The PSID if successful. Otherwise, NULL is returned and
  1134. GetLastError can be used to retrieve the windows error code.
  1135. --*/
  1136. {
  1137. DC_BEGIN_FN("CTSRDPServerChannelMgr::GetUserSid");
  1138. TOKEN_USER * ptu = NULL;
  1139. BOOL bResult;
  1140. PSID psid = NULL;
  1141. DWORD defaultSize = sizeof(TOKEN_USER);
  1142. DWORD size;
  1143. DWORD result = ERROR_SUCCESS;
  1144. ptu = (TOKEN_USER *)ALLOCMEM(defaultSize);
  1145. if (ptu == NULL) {
  1146. goto CLEANUPANDEXIT;
  1147. }
  1148. //
  1149. // Get information about the user token.
  1150. //
  1151. bResult = GetTokenInformation(
  1152. userToken,
  1153. TokenUser,
  1154. ptu,
  1155. defaultSize,
  1156. &size
  1157. );
  1158. if (bResult == FALSE) {
  1159. result = GetLastError();
  1160. if (result == ERROR_INSUFFICIENT_BUFFER) {
  1161. //
  1162. // sAllocate required memory
  1163. //
  1164. FREEMEM(ptu);
  1165. ptu = (TOKEN_USER *)ALLOCMEM(size);
  1166. if (ptu == NULL) {
  1167. TRC_ERR((TB, L"Can't allocate user token."));
  1168. result = ERROR_NOT_ENOUGH_MEMORY;
  1169. goto CLEANUPANDEXIT;
  1170. }
  1171. else {
  1172. defaultSize = size;
  1173. bResult = GetTokenInformation(
  1174. userToken,
  1175. TokenUser,
  1176. ptu,
  1177. defaultSize,
  1178. &size
  1179. );
  1180. if (bResult == FALSE) {
  1181. result = GetLastError();
  1182. TRC_ERR((TB, L"GetTokenInformation: %08X", result));
  1183. goto CLEANUPANDEXIT;
  1184. }
  1185. }
  1186. }
  1187. else {
  1188. TRC_ERR((TB, L"GetTokenInformation: %08X", result));
  1189. goto CLEANUPANDEXIT;
  1190. }
  1191. }
  1192. //
  1193. // Get the length of the SID.
  1194. //
  1195. size = GetLengthSid(ptu->User.Sid);
  1196. //
  1197. // Allocate memory. This will be freed by the caller.
  1198. //
  1199. psid = (PSID)ALLOCMEM(size);
  1200. if (psid != NULL) {
  1201. CopySid(size, psid, ptu->User.Sid);
  1202. }
  1203. else {
  1204. TRC_ERR((TB, L"Can't allocate SID"));
  1205. result = ERROR_NOT_ENOUGH_MEMORY;
  1206. goto CLEANUPANDEXIT;
  1207. }
  1208. CLEANUPANDEXIT:
  1209. if (ptu != NULL) {
  1210. FREEMEM(ptu);
  1211. }
  1212. SetLastError(result);
  1213. DC_END_FN();
  1214. return psid;
  1215. }
  1216. DWORD
  1217. CTSRDPServerChannelMgr::IOThreadInit()
  1218. /*++
  1219. Routine Description:
  1220. Called on Init of Background Thread
  1221. Arguments:
  1222. Return Value:
  1223. Returns ERROR_SUCCESS on success. Otherwise, an error code
  1224. is returned.
  1225. --*/
  1226. {
  1227. DC_BEGIN_FN("CTSRDPServerChannelMgr::IOThreadInit");
  1228. HRESULT hr;
  1229. DWORD result = ERROR_SUCCESS;
  1230. if (!IsValid()) {
  1231. ASSERT(FALSE);
  1232. return E_FAIL;
  1233. }
  1234. //
  1235. // We only allow one IO thread.
  1236. //
  1237. ASSERT(m_IOThreadBridgeThreadID == 0);
  1238. m_IOThreadBridgeThreadID = GetCurrentThreadId();
  1239. //
  1240. // Need to define the apartment for this thread as STA.
  1241. //
  1242. hr = CoInitialize(NULL);
  1243. if (!SUCCEEDED(hr)) {
  1244. TRC_ERR((TB, TEXT("CoInitializeEx: %08X"), hr));
  1245. result = E_FAIL;
  1246. goto CLEANUPANDEXIT;
  1247. }
  1248. //
  1249. // Grab the thread bridge
  1250. //
  1251. hr = CoGetInterfaceAndReleaseStream(
  1252. m_IOThreadBridgeStream,
  1253. IID_IRDSThreadBridge,
  1254. (PVOID*)&m_IOThreadBridge
  1255. );
  1256. if (SUCCEEDED(hr)) {
  1257. m_IOThreadBridgeStream = NULL;
  1258. }
  1259. else {
  1260. TRC_ERR((TB, TEXT("CoGetInterfaceAndReleaseStream: %08X"), hr));
  1261. result = E_FAIL;
  1262. goto CLEANUPANDEXIT;
  1263. }
  1264. CLEANUPANDEXIT:
  1265. if (!SUCCEEDED(hr)) {
  1266. m_IOThreadBridgeThreadID = 0;
  1267. }
  1268. DC_END_FN();
  1269. return result;
  1270. }
  1271. DWORD
  1272. CTSRDPServerChannelMgr::IOThreadShutdown(
  1273. HANDLE shutDownEvent
  1274. )
  1275. /*++
  1276. Routine Description:
  1277. Called on Shutdown of Background Thread
  1278. Arguments:
  1279. shutDownEvent - We need to signal this when we are completely
  1280. done shutting down.
  1281. Return Value:
  1282. --*/
  1283. {
  1284. DC_BEGIN_FN("CTSRDPServerChannelMgr::IOThreadShutdown");
  1285. IRDSThreadBridge *tmp;
  1286. //
  1287. // Make sure the init CB was called and succeded.
  1288. //
  1289. ASSERT(m_IOThreadBridgeThreadID != 0);
  1290. m_IOThreadBridgeThreadID = 0;
  1291. //
  1292. // Get a reference to the thread interface bridge so the foreground
  1293. // thread doesn't try to whack it when we signal the event, indicating
  1294. // that the background thread has completely shut down.
  1295. //
  1296. tmp = m_IOThreadBridge;
  1297. m_IOThreadBridge = NULL;
  1298. //
  1299. // Signal that the thread is shut down, completely.
  1300. //
  1301. if (shutDownEvent != NULL) {
  1302. SetEvent(shutDownEvent);
  1303. }
  1304. //
  1305. // Decrement the ref count on the IO thread bridge. This may cause the
  1306. // COM object that contains us to go away, so we need to do this,
  1307. // carefully, as the last thing before shutting down COM for this thread.
  1308. //
  1309. if (tmp != NULL) {
  1310. tmp->Release();
  1311. }
  1312. CoUninitialize();
  1313. DC_END_FN();
  1314. return ERROR_SUCCESS;
  1315. }
  1316. STDMETHODIMP
  1317. CTSRDPServerChannelMgr::ClientConnectedNotify()
  1318. /*++
  1319. Routine Description:
  1320. This function is implemented for the IRDSThreadBridge interface and
  1321. is called by the background thread when a client connects. This
  1322. function, in turn, notifies the containing Remote Desktop Session class.
  1323. Arguments:
  1324. Return Value:
  1325. --*/
  1326. {
  1327. DC_BEGIN_FN("CTSRDPServerChannelMgr::ClientConnectedNotify");
  1328. m_RDPSessionObject->ClientConnected();
  1329. DC_END_FN();
  1330. return S_OK;
  1331. }
  1332. STDMETHODIMP
  1333. CTSRDPServerChannelMgr::ClientDisconnectedNotify()
  1334. /*++
  1335. Routine Description:
  1336. This function is implemented for the IRDSThreadBridge interface and
  1337. is called by the background thread when a client disconnects. This
  1338. function, in turn, notifies the containing Remote Desktop Session class.
  1339. Arguments:
  1340. Return Value:
  1341. --*/
  1342. {
  1343. DC_BEGIN_FN("CTSRDPServerChannelMgr::ClientDisconnectedNotify");
  1344. m_RDPSessionObject->ClientDisconnected();
  1345. DC_END_FN();
  1346. return S_OK;
  1347. }
  1348. STDMETHODIMP
  1349. CTSRDPServerChannelMgr::DataReadyNotify(
  1350. BSTR data
  1351. )
  1352. /*++
  1353. Routine Description:
  1354. This function is implemented for the IRDSThreadBridge interface and
  1355. is called by the background thread when new data is received. This
  1356. function, in turn, notifies the parent class.
  1357. Arguments:
  1358. data - New data.
  1359. Return Value:
  1360. --*/
  1361. {
  1362. DC_BEGIN_FN("CTSRDPServerChannelMgr::ClientDisconnectedNotify");
  1363. CRemoteDesktopChannelMgr::DataReady(data);
  1364. DC_END_FN();
  1365. return S_OK;
  1366. }