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.

721 lines
15 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. DataChannelMgr.cpp
  5. Abstract:
  6. This module contains an implementation of the ISAFRemoteDesktopDataChannel
  7. and ISAFRemoteDesktopChannelMgr interfaces. These interfaces are designed
  8. to abstract out-of-band data channel access for the Salem project.
  9. The classes implemented in this module achieve this objective by
  10. multiplexing multiple data channels into a single data channel that is
  11. implemented by the remote control-specific Salem layer.
  12. Author:
  13. Tad Brockway 02/00
  14. Revision History:
  15. --*/
  16. #ifdef TRC_FILE
  17. #undef TRC_FILE
  18. #endif
  19. #define TRC_FILE "_dcmpl"
  20. #include "DataChannelMgr.h"
  21. #include <RemoteDesktop.h>
  22. #include <RemoteDesktopDBG.h>
  23. ///////////////////////////////////////////////////////
  24. //
  25. // Local Defines
  26. //
  27. #define OUTBUFRESIZEDELTA 100
  28. ///////////////////////////////////////////////////////
  29. //
  30. // CRemoteDesktopChannelMgr Members
  31. //
  32. CRemoteDesktopChannelMgr::CRemoteDesktopChannelMgr()
  33. /*++
  34. Routine Description:
  35. Constructor
  36. Arguments:
  37. Return Value:
  38. None.
  39. --*/
  40. {
  41. DC_BEGIN_FN("CRemoteDesktopChannelMgr::CRemoteDesktopChannelMgr");
  42. #if DBG
  43. m_LockCount = 0;
  44. #endif
  45. m_Initialized = FALSE;
  46. DC_END_FN();
  47. }
  48. HRESULT
  49. CRemoteDesktopChannelMgr::Initialize()
  50. /*++
  51. Routine Description:
  52. Initialize function that must be called after constructor.
  53. Arguments:
  54. Return Value:
  55. S_OK is returned on success. Otherwise, an error code
  56. is returned.
  57. --*/
  58. {
  59. HRESULT hr = S_OK;
  60. DC_BEGIN_FN("CRemoteDesktopChannelMgr::Initialize");
  61. //
  62. // Shouldn't be valid yet.
  63. //
  64. ASSERT(!IsValid());
  65. //
  66. // Initialize the critical section.
  67. //
  68. try {
  69. InitializeCriticalSection(&m_cs);
  70. }
  71. catch(...) {
  72. hr = HRESULT_FROM_WIN32(STATUS_NO_MEMORY);
  73. TRC_ERR((TB, L"Caught exception %08X", hr));
  74. }
  75. SetValid(hr == S_OK);
  76. m_Initialized = (hr == S_OK);
  77. DC_END_FN();
  78. return hr;
  79. }
  80. CRemoteDesktopChannelMgr::~CRemoteDesktopChannelMgr()
  81. /*++
  82. Routine Description:
  83. Destructor
  84. Arguments:
  85. Return Value:
  86. None.
  87. --*/
  88. {
  89. DC_BEGIN_FN("CRemoteDesktopChannelMgr::~CRemoteDesktopChannelMgr");
  90. ThreadLock();
  91. CComBSTR name;
  92. CRemoteDesktopDataChannel *chnl;
  93. HRESULT hr;
  94. //
  95. // Remove each channel.
  96. //
  97. while (!m_ChannelMap.empty()) {
  98. chnl = (*m_ChannelMap.begin()).second->channelObject;
  99. RemoveChannel(chnl->m_ChannelName);
  100. }
  101. //
  102. // Clean up the critical section object.
  103. //
  104. ThreadUnlock();
  105. if (m_Initialized) {
  106. DeleteCriticalSection(&m_cs);
  107. m_Initialized = FALSE;
  108. }
  109. DC_END_FN();
  110. }
  111. HRESULT
  112. CRemoteDesktopChannelMgr::OpenDataChannel_(
  113. BSTR name,
  114. ISAFRemoteDesktopDataChannel **channel
  115. )
  116. /*++
  117. Routine Description:
  118. Open a data channel. Observe that this function doesn't keep
  119. a reference of its own to the returned interface. The channel
  120. notifies us when it goes away so we can remove it from our list.
  121. Arguments:
  122. name - Channel name. Channel names are restricted to
  123. 16 bytes.
  124. channel - Returned channe linterface.
  125. Return Value:
  126. S_OK is returned on success. Otherwise, an error code
  127. is returned.
  128. --*/
  129. {
  130. DC_BEGIN_FN("CRemoteDesktopChannelMgr::OpenDataChannel_");
  131. PCHANNELMAPENTRY newChannel = NULL;
  132. ChannelMap::iterator iter;
  133. HRESULT hr = S_OK;
  134. CComBSTR channelName;
  135. ASSERT(IsValid());
  136. ThreadLock();
  137. //
  138. // Check the parms.
  139. //
  140. if ((name == NULL) || !wcslen(name)) {
  141. TRC_ERR((TB, TEXT("Invalid channel name")));
  142. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  143. goto CLEANUPANDEXIT;
  144. }
  145. if (channel == NULL) {
  146. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  147. goto CLEANUPANDEXIT;
  148. }
  149. channelName = name;
  150. //
  151. // AddRef an existing interface if the channel is already open.
  152. //
  153. iter = m_ChannelMap.find(channelName);
  154. if (iter != m_ChannelMap.end()) {
  155. TRC_NRM((TB, TEXT("Channel %s exists."), name));
  156. CRemoteDesktopDataChannel *chnl = (*iter).second->channelObject;
  157. hr = chnl->GetISAFRemoteDesktopDataChannel(channel);
  158. if (hr != S_OK) {
  159. TRC_ERR((TB, TEXT("GetISAFRemoteDesktopDataChannel failed: %08X"), hr));
  160. }
  161. goto CLEANUPANDEXIT;
  162. }
  163. //
  164. // Create the new channel with some help from the subclass.
  165. //
  166. newChannel = new CHANNELMAPENTRY;
  167. if (newChannel == NULL) {
  168. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  169. goto CLEANUPANDEXIT;
  170. }
  171. newChannel->channelObject = OpenPlatformSpecificDataChannel(
  172. name,
  173. channel
  174. );
  175. if (newChannel->channelObject == NULL) {
  176. TRC_ERR((TB, TEXT("Failed to allocate data channel.")));
  177. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  178. goto CLEANUPANDEXIT;
  179. }
  180. #if DBG
  181. newChannel->bytesSent = 0;
  182. newChannel->bytesRead = 0;
  183. #endif
  184. if (hr != S_OK) {
  185. TRC_ERR((TB, TEXT("QI failed for ISAFRemoteDesktopDataChannel")));
  186. goto CLEANUPANDEXIT;
  187. }
  188. //
  189. // Add the channel to the channel map.
  190. //
  191. try {
  192. m_ChannelMap.insert(ChannelMap::value_type(channelName, newChannel));
  193. }
  194. catch(CRemoteDesktopException x) {
  195. hr = HRESULT_FROM_WIN32(x.m_ErrorCode);
  196. }
  197. CLEANUPANDEXIT:
  198. if (hr != S_OK) {
  199. if (newChannel != NULL) {
  200. (*channel)->Release();
  201. delete newChannel;
  202. }
  203. }
  204. ThreadUnlock();
  205. DC_END_FN();
  206. return hr;
  207. }
  208. HRESULT
  209. CRemoteDesktopChannelMgr::RemoveChannel(
  210. BSTR channel
  211. )
  212. /*++
  213. Routine Description:
  214. Remove an existing data channel. This function is called from the
  215. channel object when its ref count goes to 0.
  216. Arguments:
  217. channel - Name of channel to remove.
  218. Return Value:
  219. None.
  220. --*/
  221. {
  222. HRESULT hr = S_OK;
  223. DC_BEGIN_FN("CRemoteDesktopChannelMgr::RemoveChannel");
  224. ASSERT(IsValid());
  225. ChannelMap::iterator iter;
  226. PCHANNELMAPENTRY pChannel;
  227. ThreadLock();
  228. //
  229. // Find the channel.
  230. //
  231. iter = m_ChannelMap.find(channel);
  232. if (iter == m_ChannelMap.end()) {
  233. hr = HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
  234. ASSERT(FALSE);
  235. TRC_ERR((TB, TEXT("Channel %s does not exist."), channel));
  236. goto CLEANUPANDEXIT;
  237. }
  238. //
  239. // Release the input buffer queue and its contents.
  240. //
  241. pChannel = (*iter).second;
  242. while (!pChannel->inputBufferQueue.empty()) {
  243. QUEUEDCHANNELBUFFER channelBuf = pChannel->inputBufferQueue.front();
  244. SysFreeString(channelBuf.buf);
  245. pChannel->inputBufferQueue.pop_front();
  246. }
  247. //
  248. // Erase the channel.
  249. //
  250. m_ChannelMap.erase(iter);
  251. delete pChannel;
  252. CLEANUPANDEXIT:
  253. ThreadUnlock();
  254. DC_END_FN();
  255. return hr;
  256. }
  257. HRESULT
  258. CRemoteDesktopChannelMgr::SendChannelData(
  259. BSTR channel,
  260. BSTR outputBuf
  261. )
  262. /*++
  263. Routine Description:
  264. Send a buffer on the data channel.
  265. Arguments:
  266. channel - Relevant channel.
  267. outputBuf - Associated output data.
  268. Return Value:
  269. ERROR_SUCCESS is returned on success. Otherwise, an error code
  270. is returned.
  271. --*/
  272. {
  273. DC_BEGIN_FN("CRemoteDesktopChannelMgr::SendChannelData");
  274. ASSERT(IsValid());
  275. HRESULT result = S_OK;
  276. PREMOTEDESKTOP_CHANNELBUFHEADER hdr;
  277. DWORD bytesToSend;
  278. PBYTE data;
  279. BSTR fullOutputBuf;
  280. DWORD bufLen = SysStringByteLen(outputBuf);
  281. DWORD channelNameLen;
  282. PBYTE ptr;
  283. //
  284. // Make sure this is a valid channel.
  285. //
  286. ChannelMap::iterator iter;
  287. //
  288. // ThreadLock
  289. //
  290. ThreadLock();
  291. //
  292. // Make sure the channel exists.
  293. //
  294. iter = m_ChannelMap.find(channel);
  295. if (iter == m_ChannelMap.end()) {
  296. ASSERT(FALSE);
  297. goto CLEANUPANDEXIT;
  298. }
  299. #if DBG
  300. (*iter).second->bytesSent += SysStringByteLen(outputBuf);
  301. #endif
  302. //
  303. // Allocate the outgoing buffer.
  304. //
  305. channelNameLen = SysStringByteLen(channel);
  306. bytesToSend = sizeof(REMOTEDESKTOP_CHANNELBUFHEADER) + bufLen + channelNameLen;
  307. fullOutputBuf = (BSTR)SysAllocStringByteLen(
  308. NULL,
  309. bytesToSend
  310. );
  311. if (fullOutputBuf == NULL) {
  312. TRC_ERR((TB, TEXT("Can't allocate %ld bytes."),
  313. bytesToSend + OUTBUFRESIZEDELTA));
  314. result = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  315. goto CLEANUPANDEXIT;
  316. }
  317. //
  318. // Initialize the header.
  319. //
  320. hdr = (PREMOTEDESKTOP_CHANNELBUFHEADER)fullOutputBuf;
  321. memset(hdr, 0, sizeof(REMOTEDESKTOP_CHANNELBUFHEADER));
  322. #ifdef USE_MAGICNO
  323. hdr->magicNo = CHANNELBUF_MAGICNO;
  324. #endif
  325. hdr->channelNameLen = channelNameLen;
  326. hdr->dataLen = bufLen;
  327. //
  328. // Copy the channel name.
  329. //
  330. ptr = (PBYTE)(hdr + 1);
  331. memcpy(ptr, channel, hdr->channelNameLen);
  332. //
  333. // Copy the data.
  334. //
  335. ptr += hdr->channelNameLen;
  336. memcpy(ptr, outputBuf, bufLen);
  337. //
  338. // Send the data through the concrete subclass.
  339. //
  340. result = SendData(hdr);
  341. //
  342. // Release the send buffer that we allocated.
  343. //
  344. SysFreeString(fullOutputBuf);
  345. CLEANUPANDEXIT:
  346. ThreadUnlock();
  347. DC_END_FN();
  348. return result;
  349. }
  350. HRESULT
  351. CRemoteDesktopChannelMgr::ReadChannelData(
  352. IN BSTR channel,
  353. OUT BSTR *msg
  354. )
  355. /*++
  356. Routine Description:
  357. Read the next message from a data channel.
  358. Arguments:
  359. channel - Relevant data channel.
  360. msg - The next message. The caller should release the
  361. data buffer using SysFreeString.
  362. Return Value:
  363. S_OK on success. ERROR_NO_MORE_ITEMS is returned if there
  364. are no more messages. An error code otherwise.
  365. --*/
  366. {
  367. DC_BEGIN_FN("CRemoteDesktopChannelMgr::ReadChannelData");
  368. HRESULT result = S_OK;
  369. ChannelMap::iterator channelIterator;
  370. PCHANNELMAPENTRY pChannel;
  371. ASSERT(IsValid());
  372. ThreadLock();
  373. //
  374. // Initialize the output buf to NULL.
  375. //
  376. *msg = NULL;
  377. //
  378. // Find the channel.
  379. //
  380. channelIterator = m_ChannelMap.find(channel);
  381. if (channelIterator != m_ChannelMap.end()) {
  382. pChannel = (*channelIterator).second;
  383. }
  384. else {
  385. ASSERT(FALSE);
  386. result = E_FAIL;
  387. goto CLEANUPANDEXIT;
  388. }
  389. //
  390. // Make sure there is data in the queue.
  391. //
  392. if (pChannel->inputBufferQueue.empty()) {
  393. result = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  394. goto CLEANUPANDEXIT;
  395. }
  396. //
  397. // Return the buffer.
  398. //
  399. *msg = pChannel->inputBufferQueue.front().buf;
  400. ASSERT(*msg != NULL);
  401. //
  402. // Delete it.
  403. //
  404. pChannel->inputBufferQueue.pop_front();
  405. CLEANUPANDEXIT:
  406. ThreadUnlock();
  407. DC_END_FN();
  408. return result;
  409. }
  410. VOID
  411. CRemoteDesktopChannelMgr::DataReady(
  412. BSTR msg
  413. )
  414. /*++
  415. Routine Description:
  416. Invoked by the subclass when the next message is ready. This
  417. function copies the message buffer and returns.
  418. Arguments:
  419. msg - Next message.
  420. Return Value:
  421. None.
  422. --*/
  423. {
  424. DC_BEGIN_FN("CRemoteDesktopChannelMgr::DataReady");
  425. ChannelMap::iterator channel;
  426. QUEUEDCHANNELBUFFER channelBuf;
  427. PREMOTEDESKTOP_CHANNELBUFHEADER hdr = NULL;
  428. DWORD result = ERROR_SUCCESS;
  429. DWORD cbMsgSize = 0;
  430. PVOID data;
  431. PBYTE ptr;
  432. BSTR tmp;
  433. CComBSTR channelName;
  434. ASSERT(IsValid());
  435. ASSERT(msg != NULL);
  436. hdr = (PREMOTEDESKTOP_CHANNELBUFHEADER)msg;
  437. cbMsgSize = SysStringByteLen( msg );
  438. //
  439. // check to make sure that header block is big enough to validate
  440. //
  441. if( cbMsgSize < ( sizeof( REMOTEDESKTOP_CHANNELBUFHEADER ) ) )
  442. {
  443. TRC_ERR((TB, TEXT("RemoteChannel buffer header corruption has taken place!!")));
  444. result = E_FAIL;
  445. goto CLEANUPANDEXIT;
  446. }
  447. //
  448. // now check the entire packet to ensure we have enough space
  449. //
  450. if( cbMsgSize < ( sizeof( REMOTEDESKTOP_CHANNELBUFHEADER ) + hdr->channelNameLen + hdr->dataLen ) )
  451. {
  452. TRC_ERR((TB, TEXT("RemoteChannel packet corruption has taken place!!")));
  453. result = E_FAIL;
  454. goto CLEANUPANDEXIT;
  455. }
  456. #ifdef USE_MAGICNO
  457. ASSERT(hdr->magicNo == CHANNELBUF_MAGICNO);
  458. #endif
  459. //
  460. // Initialize the channel buf.
  461. //
  462. channelBuf.buf = NULL;
  463. //
  464. // Get the channel name.
  465. //
  466. tmp = SysAllocStringByteLen(NULL, hdr->channelNameLen);
  467. if (tmp == NULL) {
  468. TRC_ERR((TB, TEXT("Can't allocate channel name.")));
  469. result = E_OUTOFMEMORY;
  470. goto CLEANUPANDEXIT;
  471. }
  472. ptr = (PBYTE)(hdr + 1);
  473. memcpy(tmp, ptr, hdr->channelNameLen);
  474. channelName.Attach(tmp);
  475. ThreadLock();
  476. //
  477. // Find the corresponding channel.
  478. //
  479. #ifdef USE_MAGICNO
  480. ASSERT(hdr->magicNo == CHANNELBUF_MAGICNO);
  481. #endif
  482. channel = m_ChannelMap.find(channelName);
  483. if (channel == m_ChannelMap.end()) {
  484. TRC_ALT((TB, L"Data received for non-existent channel %s",
  485. channelName.m_str));
  486. result = E_FAIL;
  487. ThreadUnlock();
  488. goto CLEANUPANDEXIT;
  489. }
  490. //
  491. // Copy the incoming data buffer.
  492. //
  493. ptr += hdr->channelNameLen;
  494. channelBuf.len = hdr->dataLen;
  495. channelBuf.buf = SysAllocStringByteLen(NULL, channelBuf.len);
  496. if (channelBuf.buf == NULL) {
  497. TRC_ERR((TB, TEXT("Can't allocate %ld bytes for buf."), channelBuf.len));
  498. result = E_FAIL;
  499. ThreadUnlock();
  500. goto CLEANUPANDEXIT;
  501. }
  502. memcpy(channelBuf.buf, ptr, hdr->dataLen);
  503. //
  504. // Add to the channel's input queue.
  505. //
  506. try {
  507. (*channel).second->inputBufferQueue.push_back(channelBuf);
  508. }
  509. catch(CRemoteDesktopException x) {
  510. result = x.m_ErrorCode;
  511. ASSERT(result != ERROR_SUCCESS);
  512. }
  513. //
  514. // Notify the interface that data is ready.
  515. //
  516. if (result == ERROR_SUCCESS) {
  517. (*channel).second->channelObject->DataReady();
  518. #if DBG
  519. (*channel).second->bytesRead += hdr->dataLen;
  520. #endif
  521. }
  522. ThreadUnlock();
  523. CLEANUPANDEXIT:
  524. if ((result != ERROR_SUCCESS) && (channelBuf.buf != NULL)) {
  525. SysFreeString(channelBuf.buf);
  526. }
  527. DC_END_FN();
  528. }