Leaked source code of windows server 2003
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.

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