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.

1189 lines
55 KiB

  1. /****************************************************************************/
  2. // anmapi.c
  3. //
  4. // Network Manger
  5. //
  6. // Copyright(C) Microsoft Corporation 1997-1999
  7. /****************************************************************************/
  8. #include <precomp.h>
  9. #pragma hdrstop
  10. #define TRC_GROUP TRC_GROUP_NETWORK
  11. #define TRC_FILE "anmapi"
  12. #define pTRCWd (pRealNMHandle->pWDHandle)
  13. #include <adcg.h>
  14. #include <acomapi.h>
  15. #include <anmint.h>
  16. #include <asmapi.h>
  17. #include <nwdwapi.h>
  18. #include <anmapi.h>
  19. #include <nprcount.h>
  20. #include <tschannl.h>
  21. /****************************************************************************/
  22. /* Name: NM_GetDataSize */
  23. /* */
  24. /* Purpose: Returns size of per-instance NM data required */
  25. /* */
  26. /* Returns: size of data required */
  27. /* */
  28. /* Operation: NM stores per-instance data in a piece of memory allocated */
  29. /* by WDW. This function returns the size of the data required. */
  30. /* A pointer to this data (the 'NM Handle') is passed into all */
  31. /* subsequent NM functions. */
  32. /****************************************************************************/
  33. unsigned RDPCALL NM_GetDataSize(void)
  34. {
  35. DC_BEGIN_FN("NM_GetDataSize");
  36. DC_END_FN();
  37. return(sizeof(NM_HANDLE_DATA));
  38. } /* NM_GetDataSize */
  39. /****************************************************************************/
  40. /* Name: NM_Init */
  41. /* */
  42. /* Purpose: Initialize NM */
  43. /* */
  44. /* Returns: TRUE - Registered OK */
  45. /* FALSE - Registration failed */
  46. /* */
  47. /* Params: pNMHandle - NM handle */
  48. /* pSMHandle - SM handle, stored by NM and passed on callbacks */
  49. /* to SM */
  50. /* pWDHandle - WD handle, required for tracing */
  51. /* hDomainKernel - MCS handle stored from MCSInitialize() and */
  52. /* used to attach a user. */
  53. /* */
  54. /* Operation: Initialize NM: */
  55. /* - initialize per-instance data */
  56. /* - open channel for communication with PDMCS */
  57. /****************************************************************************/
  58. BOOL RDPCALL NM_Init(PVOID pNMHandle,
  59. PVOID pSMHandle,
  60. PTSHARE_WD pWDHandle,
  61. DomainHandle hDomainKernel)
  62. {
  63. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  64. DC_BEGIN_FN("NM_Init");
  65. /************************************************************************/
  66. /* WARNING: Don't trace before storing the WD Handle */
  67. /************************************************************************/
  68. pRealNMHandle->pWDHandle = pWDHandle;
  69. pRealNMHandle->pSMHandle = pSMHandle;
  70. pRealNMHandle->pContext = pWDHandle->pContext;
  71. pRealNMHandle->hDomain = hDomainKernel;
  72. DC_END_FN();
  73. return(TRUE);
  74. } /* NM_Init */
  75. /****************************************************************************/
  76. /* Name: NM_Term */
  77. /* */
  78. /* Purpose: Terminate NM */
  79. /* */
  80. /* Params: pNMHandle - NM handle */
  81. /* */
  82. /* Operation: Terminate NM */
  83. /* - close channel opened by NM_Init */
  84. /****************************************************************************/
  85. void RDPCALL NM_Term(PVOID pNMHandle)
  86. {
  87. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  88. unsigned i;
  89. PNM_CHANNEL_DATA pChannelData;
  90. DC_BEGIN_FN("NM_Term");
  91. TRC_NRM((TB, "Terminate NM"));
  92. /************************************************************************/
  93. /* Free any half-received virtual channel data */
  94. /************************************************************************/
  95. for (i = 0, pChannelData = pRealNMHandle->channelData;
  96. i < pRealNMHandle->channelArrayCount;
  97. i++, pChannelData++)
  98. {
  99. if (pChannelData->pData != NULL)
  100. {
  101. TRC_NRM((TB, "Free %p", pChannelData->pData));
  102. COM_Free(pChannelData->pData);
  103. }
  104. }
  105. DC_END_FN();
  106. } /* NM_Term */
  107. /****************************************************************************/
  108. /* Name: NM_Connect */
  109. /* */
  110. /* Purpose: Starts the process of connecting to the Client */
  111. /* */
  112. /* Returns: TRUE - Connect started OK */
  113. /* FALSE - Connect failed to start */
  114. /* */
  115. /* Params: pNMHandle - NM handle */
  116. /* pUserDataIn - user data received from Client */
  117. /* */
  118. /* Operation: Attach the user to the domain. PDMCS knows about only 1 */
  119. /* domain, so that one is assumed. */
  120. /* */
  121. /* When the AttachUser completes, join two channels: */
  122. /* - the dynamically allocated broadcast channel (ID returned on */
  123. /* the SM_OnConnected callback) */
  124. /* - the single-user channel for this user. */
  125. /* */
  126. /* Note that this function completes asynchronously. The caller */
  127. /* must wait for a SM_OnConnected or SM_OnDisconnected */
  128. /* callback to find out whether the Connect succeeded or failed. */
  129. /****************************************************************************/
  130. BOOL RDPCALL NM_Connect(PVOID pNMHandle, PRNS_UD_CS_NET pUserDataIn)
  131. {
  132. BOOL rc = FALSE;
  133. BOOLEAN bCompleted;
  134. MCSError MCSErr;
  135. ChannelHandle hChannel;
  136. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  137. unsigned i, j;
  138. unsigned userDataOutLength;
  139. PRNS_UD_SC_NET pUserDataOut = NULL;
  140. PCHANNEL_DEF pChannel;
  141. UINT16 *pMCSChannel;
  142. ChannelID ChID;
  143. UINT32 DataLenValidate;
  144. // for unalignment use purpose
  145. UserHandle UserHandleTemp;
  146. unsigned MaxSendSizeTemp;
  147. DC_BEGIN_FN("NM_Connect");
  148. /************************************************************************/
  149. /* Clear the connection status */
  150. /************************************************************************/
  151. pRealNMHandle->connectStatus = 0;
  152. /************************************************************************/
  153. /* Save virtual channel data */
  154. /************************************************************************/
  155. if (pUserDataIn != NULL)
  156. {
  157. TRC_DATA_NRM("Net User Data",
  158. pUserDataIn,
  159. pUserDataIn->header.length);
  160. TRC_NRM((TB, "Protocol version %#x (%#x/%#x)",
  161. pRealNMHandle->pWDHandle->version,
  162. _RNS_MAJOR_VERSION(pRealNMHandle->pWDHandle->version),
  163. _RNS_MINOR_VERSION(pRealNMHandle->pWDHandle->version)));
  164. /********************************************************************/
  165. /* Protocol version 0x00080002 used 2-byte channel data lengths. */
  166. /* Protocol version 0x00080003 and higher use 4-byte data lengths. */
  167. /* If this is a 2-byte version, ignore its virtual channels. */
  168. /********************************************************************/
  169. if (_RNS_MINOR_VERSION(pRealNMHandle->pWDHandle->version) >= 3)
  170. {
  171. // Validate channle count
  172. DataLenValidate = pUserDataIn->channelCount * sizeof(CHANNEL_DEF);
  173. DataLenValidate += sizeof(RNS_UD_CS_NET);
  174. if (DataLenValidate > pUserDataIn->header.length)
  175. {
  176. TRC_ERR((TB, "Error: Virtual channel data length %u too short for %u",
  177. pUserDataIn->header.length, DataLenValidate));
  178. pRealNMHandle->channelCount = 0;
  179. pRealNMHandle->channelArrayCount = 0;
  180. WDW_LogAndDisconnect(pRealNMHandle->pWDHandle, TRUE,
  181. Log_RDP_VChannelDataTooShort, (PBYTE)pUserDataIn, pUserDataIn->header.length);
  182. DC_QUIT;
  183. }
  184. // we reserve channel 7 for RDPDD so we can allow only the
  185. // buffer size - 1 channels.
  186. if (pUserDataIn->channelCount > sizeof(pRealNMHandle->channelData)
  187. / sizeof(pRealNMHandle->channelData[0]) - 1) {
  188. TRC_ERR((TB, "Error: Too many virtual channels to join: %u.",
  189. pUserDataIn->channelCount));
  190. pRealNMHandle->channelCount = 0;
  191. pRealNMHandle->channelArrayCount = 0;
  192. WDW_LogAndDisconnect(pRealNMHandle->pWDHandle, TRUE,
  193. Log_RDP_VChannelsTooMany, (PBYTE)pUserDataIn,
  194. pUserDataIn->header.length);
  195. DC_QUIT;
  196. }
  197. pRealNMHandle->channelCount = pUserDataIn->channelCount;
  198. pChannel = (PCHANNEL_DEF)(pUserDataIn + 1);
  199. for (i = 0, j = 0; i < pRealNMHandle->channelCount; i++, j++)
  200. {
  201. /************************************************************/
  202. /* Channel 7 is used by RDPDD, so skip it */
  203. /************************************************************/
  204. if (i == WD_THINWIRE_CHANNEL)
  205. {
  206. j++;
  207. }
  208. /************************************************************/
  209. /* Save channel data */
  210. /************************************************************/
  211. strncpy(pRealNMHandle->channelData[j].name,
  212. pChannel[i].name,
  213. CHANNEL_NAME_LEN);
  214. // make sure that the name is zero-terminated
  215. (pRealNMHandle->channelData[j].name)[CHANNEL_NAME_LEN] = 0;
  216. pRealNMHandle->channelData[j].flags = pChannel[i].options;
  217. TRC_NRM((TB, "Channel %d (was %d): %s",
  218. j, i, pChannel[i].name));
  219. }
  220. pRealNMHandle->channelArrayCount = j;
  221. }
  222. else
  223. {
  224. TRC_ERR((TB,
  225. "Minor version %#x doesn't support 4-byte channel data lengths",
  226. _RNS_MINOR_VERSION(pRealNMHandle->pWDHandle->version)));
  227. pRealNMHandle->channelCount = 0;
  228. pRealNMHandle->channelArrayCount = 0;
  229. }
  230. }
  231. else
  232. {
  233. /********************************************************************/
  234. /* No incoming user data = no virtual channels */
  235. /********************************************************************/
  236. TRC_NRM((TB, "No virtual channels"));
  237. pRealNMHandle->channelCount = 0;
  238. pRealNMHandle->channelArrayCount = 0;
  239. }
  240. /************************************************************************/
  241. /* Allocate space for returned user data */
  242. /************************************************************************/
  243. userDataOutLength = (sizeof(RNS_UD_SC_NET) +
  244. (sizeof(UINT16) * pRealNMHandle->channelCount));
  245. userDataOutLength = (unsigned)(DC_ROUND_UP_4(userDataOutLength));
  246. pUserDataOut = COM_Malloc(userDataOutLength);
  247. if (pUserDataOut != NULL) {
  248. memset(pUserDataOut, 0, userDataOutLength);
  249. }
  250. else {
  251. TRC_ERR((TB, "Failed to alloc %d bytes for user data",
  252. userDataOutLength));
  253. DC_QUIT;
  254. }
  255. /************************************************************************/
  256. /* Make the attach-user request call. */
  257. /************************************************************************/
  258. TRC_NRM((TB, "Attach User"));
  259. UserHandleTemp = pRealNMHandle->hUser;
  260. MaxSendSizeTemp = pRealNMHandle->maxPDUSize;
  261. MCSErr = MCSAttachUserRequest(pRealNMHandle->hDomain,
  262. NM_MCSUserCallback,
  263. SM_MCSSendDataCallback,
  264. pNMHandle,
  265. &UserHandleTemp,
  266. &MaxSendSizeTemp,
  267. (BOOLEAN *)(&bCompleted));
  268. pRealNMHandle->hUser = UserHandleTemp;
  269. pRealNMHandle->maxPDUSize = MaxSendSizeTemp;
  270. if (MCSErr == MCS_NO_ERROR) {
  271. TRC_NRM((TB, "AttachUser OK, hUser %p", pRealNMHandle->hUser));
  272. TRC_ASSERT((bCompleted),
  273. (TB, "MCSAttachUser didn't complete synchronously"));
  274. // Extract extra information.
  275. pRealNMHandle->userID = MCSGetUserIDFromHandle(pRealNMHandle->hUser);
  276. pRealNMHandle->connectStatus |= NM_CONNECT_ATTACH;
  277. TRC_NRM((TB, "Attached as user %x, hUser %p",
  278. pRealNMHandle->userID, pRealNMHandle->hUser));
  279. }
  280. else {
  281. TRC_ERR((TB, "Failed AttachUserRequest, MCSErr %d", MCSErr));
  282. DC_QUIT;
  283. }
  284. /************************************************************************/
  285. /* Join the broadcast channel */
  286. /************************************************************************/
  287. MCSErr = MCSChannelJoinRequest(pRealNMHandle->hUser,
  288. 0,
  289. &hChannel,
  290. &bCompleted);
  291. if (MCSErr == MCS_NO_ERROR) {
  292. TRC_ASSERT((bCompleted),
  293. (TB, "MCSChannelJoin didn't complete synchronously"));
  294. // Extract information.
  295. ChID = MCSGetChannelIDFromHandle(hChannel);
  296. pRealNMHandle->channelID = ChID;
  297. pRealNMHandle->hChannel = hChannel;
  298. pRealNMHandle->connectStatus |= NM_CONNECT_JOIN_BROADCAST;
  299. TRC_NRM((TB, "Joined broadcast channel %x (hChannel %p) OK",
  300. ChID, hChannel));
  301. }
  302. else {
  303. TRC_ERR((TB, "Failed to send ChannelJoinRequest, MCSErr %d", MCSErr));
  304. DC_QUIT;
  305. }
  306. /************************************************************************/
  307. /* Join the user channel */
  308. /************************************************************************/
  309. MCSErr = MCSChannelJoinRequest(pRealNMHandle->hUser,
  310. pRealNMHandle->userID,
  311. &hChannel,
  312. &bCompleted);
  313. if (MCSErr == MCS_NO_ERROR) {
  314. TRC_ASSERT((bCompleted),
  315. (TB, "MCSChannelJoin didn't complete synchronously"));
  316. // Extract information.
  317. pRealNMHandle->connectStatus |= NM_CONNECT_JOIN_USER;
  318. TRC_NRM((TB, "Joined user channel (hChannel %p) OK", hChannel));
  319. }
  320. else {
  321. TRC_ERR((TB, "Failed to send ChannelJoinRequest, MCSErr %d", MCSErr));
  322. DC_QUIT;
  323. }
  324. /************************************************************************/
  325. /* If no virtual channels, we're done. */
  326. /************************************************************************/
  327. if (pRealNMHandle->channelCount == 0)
  328. {
  329. TRC_NRM((TB, "No virtual channels to join"));
  330. rc = TRUE;
  331. DC_QUIT;
  332. }
  333. /************************************************************************/
  334. /* Join virtual channels */
  335. /************************************************************************/
  336. for (i = 0; i < pRealNMHandle->channelArrayCount; i++)
  337. {
  338. if (i == WD_THINWIRE_CHANNEL)
  339. {
  340. TRC_NRM((TB, "Skip channel %d", WD_THINWIRE_CHANNEL));
  341. continue;
  342. }
  343. MCSErr = MCSChannelJoinRequest(pRealNMHandle->hUser,
  344. 0,
  345. &hChannel,
  346. &bCompleted);
  347. if (MCSErr == MCS_NO_ERROR) {
  348. TRC_ASSERT((bCompleted),
  349. (TB, "MCSChannelJoin didn't complete synchronously"));
  350. ChID = MCSGetChannelIDFromHandle(hChannel);
  351. pRealNMHandle->channelData[i].MCSChannelID = (UINT16)ChID;
  352. TRC_NRM((TB, "Joined VC %d: %d (hChannel %p)", i, ChID, hChannel));
  353. }
  354. else {
  355. TRC_ERR((TB, "ChannelJoinRequest failed, MCSErr %d", MCSErr));
  356. DC_QUIT;
  357. }
  358. }
  359. /************************************************************************/
  360. /* Everything completed OK */
  361. /************************************************************************/
  362. rc = TRUE;
  363. DC_EXIT_POINT:
  364. if (rc)
  365. {
  366. /********************************************************************/
  367. /* Everything is OK - Complete the user data */
  368. /********************************************************************/
  369. pUserDataOut->header.type = RNS_UD_SC_NET_ID;
  370. pUserDataOut->header.length = (UINT16)userDataOutLength;
  371. pUserDataOut->MCSChannelID = (UINT16)pRealNMHandle->channelID;
  372. pUserDataOut->channelCount = (UINT16)pRealNMHandle->channelCount;
  373. pMCSChannel = (UINT16 *)(pUserDataOut + 1);
  374. TRC_NRM((TB, "Copy %d channels to user data out",
  375. pRealNMHandle->channelCount));
  376. for (i = 0, j = 0; i < pRealNMHandle->channelCount; i++, j++)
  377. {
  378. if (i == WD_THINWIRE_CHANNEL)
  379. {
  380. TRC_NRM((TB, "Skip channel %d", WD_THINWIRE_CHANNEL));
  381. j++;
  382. }
  383. pMCSChannel[i] = pRealNMHandle->channelData[j].MCSChannelID;
  384. TRC_NRM((TB, "Channel %d (%d) = %#x", i, j, pMCSChannel[i]));
  385. }
  386. /********************************************************************/
  387. /* Tell SM we're connected now */
  388. /********************************************************************/
  389. TRC_NRM((TB, "Tell SM we're connecting"));
  390. SM_OnConnected(pRealNMHandle->pSMHandle, pRealNMHandle->userID,
  391. NM_CB_CONN_OK, pUserDataOut, pRealNMHandle->maxPDUSize);
  392. }
  393. else
  394. {
  395. /********************************************************************/
  396. /* Something failed - abort the connection */
  397. /********************************************************************/
  398. TRC_NRM((TB, "Something failed - abort the connection"));
  399. NMAbortConnect(pRealNMHandle);
  400. }
  401. /************************************************************************/
  402. /* Whether we succeeded or failed, we don't need the user data any */
  403. /* more. */
  404. /************************************************************************/
  405. TRC_NRM((TB, "Free user data"));
  406. if (pUserDataOut != NULL) {
  407. COM_Free(pUserDataOut);
  408. }
  409. DC_END_FN();
  410. return(rc);
  411. } /* NM_Connect */
  412. /****************************************************************************/
  413. /* Name: NM_GetMCSDomainInfo */
  414. /* */
  415. /* Purpose: Return the broadcast channel ID to allow shadowing of this */
  416. /* share. */
  417. /* */
  418. /* Params: pNMHandle - NM handle */
  419. /****************************************************************************/
  420. ChannelID RDPCALL NM_GetMCSDomainInfo(PVOID pNMHandle)
  421. {
  422. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  423. return pRealNMHandle->channelID;
  424. }
  425. /****************************************************************************/
  426. /* Name: NM_Disconnect */
  427. /* */
  428. /* Purpose: Disconnect from a Client */
  429. /* */
  430. /* Returns: TRUE - Disconnect started OK */
  431. /* FALSE - Disconnect failed */
  432. /* */
  433. /* Params: pNMHandle - NM handle */
  434. /* */
  435. /* Operation: Detach the user from the domain. */
  436. /* */
  437. /* Note that this function completes asynchronously. The caller */
  438. /* must wait for a SM_OnDisconnected callback to find whether */
  439. /* the Disconnect succeeded or failed. */
  440. /****************************************************************************/
  441. BOOL RDPCALL NM_Disconnect(PVOID pNMHandle)
  442. {
  443. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  444. BOOL rc = TRUE;
  445. DC_BEGIN_FN("NM_Disconnect");
  446. /************************************************************************/
  447. /* Detach from MCS */
  448. /************************************************************************/
  449. if (pRealNMHandle->connectStatus & NM_CONNECT_ATTACH)
  450. {
  451. TRC_NRM((TB, "User attached, need to detach"));
  452. rc = NMDetachUserReq(pRealNMHandle);
  453. }
  454. DC_END_FN();
  455. return(rc);
  456. } /* NM_Disconnect */
  457. /****************************************************************************/
  458. /* Name: NM_AllocBuffer */
  459. /* */
  460. /* Purpose: Acquire a buffer for transmission */
  461. /* */
  462. /* Returns: TRUE - Buffer acquired OK */
  463. /* FALSE - No buffer available */
  464. /* */
  465. /* Params: pNMHandle - NM handle */
  466. /* ppBuffer - Buffer acquired (returned) */
  467. /* bufferSize - size of buffer required */
  468. /* */
  469. /* Operation: Get a buffer from ICA (via IcaBufferAlloc) */
  470. /* This function is synchronous. */
  471. /****************************************************************************/
  472. NTSTATUS __fastcall NM_AllocBuffer(PVOID pNMHandle,
  473. PPVOID ppBuffer,
  474. UINT32 bufferSize,
  475. BOOLEAN fWait)
  476. {
  477. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  478. NTSTATUS status;
  479. POUTBUF pOutBuf;
  480. int i;
  481. UINT32 realBufferSize;
  482. DC_BEGIN_FN("NM_AllocBuffer");
  483. /************************************************************************/
  484. /* Calculate the actual size of data required. Includes a POUTBUF */
  485. /* prefix to point back to the beginning of the OutBuf so we can send */
  486. /* the right thing to MCS. */
  487. /************************************************************************/
  488. TRC_ASSERT((bufferSize < 16384),
  489. (TB,"Buffer req size %u will cause MCS fragmentation, unsupported",
  490. bufferSize));
  491. realBufferSize = bufferSize + SendDataReqPrefixBytes + sizeof(POUTBUF);
  492. /************************************************************************/
  493. /* Allocate an OutBuf */
  494. /************************************************************************/
  495. status = IcaBufferAlloc(pRealNMHandle->pContext,
  496. fWait, /* wait/not wait for a buffer */
  497. FALSE, /* not a control buffer */
  498. realBufferSize,
  499. NULL, /* no original buffer */
  500. (PVOID *)(&pOutBuf));
  501. if (status == STATUS_SUCCESS) { // NT_SUCCESS() does not fail STATUS_TIMEOUT
  502. /********************************************************************/
  503. /* The OutBuf returned includes a data buffer pointer, which points */
  504. /* to a buffer containing */
  505. /* - a pointer to the beginning of the OutBuf (which we set here) */
  506. /* - SendDataReqPrefixBytes */
  507. /* - user data buffer (size bufferSize) */
  508. /* Set the OutBuf pBuffer pointer to the beginning of the user data.*/
  509. /* MCS requires this. */
  510. /* Return to the user a pointer to the user data buffer. */
  511. /********************************************************************/
  512. *((POUTBUF *)pOutBuf->pBuffer) = pOutBuf;
  513. pOutBuf->pBuffer += SendDataReqPrefixBytes + sizeof(POUTBUF);
  514. *ppBuffer = pOutBuf->pBuffer;
  515. TRC_NRM((TB, "Alloc %d bytes OK", bufferSize));
  516. }
  517. else
  518. {
  519. TRC_ERR((TB, "Failed to alloc %d bytes, status %x",
  520. bufferSize, status));
  521. //
  522. // TODO - consider disconnect client here instead of SM_AllocBuffer(),
  523. // keep it in SM_AllocBuffer() so that we don't introduce any regression.
  524. //
  525. //
  526. // IcaBufferAlloc() returns STATUS_IO_TIMEOUT, STATUS_NO_MEMORY, and
  527. // IcaWaitForSingleObject() which returns KeWaitForSingleObject() or
  528. // STATUS_CTX_CLOSE_PENDING. SM_AllocBuffer() need to disconnect this client only
  529. // when error code is STATUS_IO_TIMEOUT so we keep this return code
  530. }
  531. DC_END_FN();
  532. return status;
  533. } /* NM_AllocBuffer */
  534. /****************************************************************************/
  535. /* Name: NM_FreeBuffer */
  536. /* */
  537. /* Purpose: Free a transmit buffer */
  538. /* */
  539. /* Params: pNMHandle - NM handle */
  540. /* pBuffer - Buffer to free */
  541. /* */
  542. /* Operation: Free a buffer (via IcaBufferFree) */
  543. /* This function assumes the buffer was allocated using */
  544. /* NM_AllocBuffer. */
  545. /* */
  546. /* This function is only for freeing buffers which are not sent. */
  547. /* It should not be called for buffers which are sent - */
  548. /* NM_SendData frees the buffer whether the Send succeeds or */
  549. /* not. */
  550. /* */
  551. /* This function is synchronous. */
  552. /****************************************************************************/
  553. void __fastcall NM_FreeBuffer(PVOID pNMHandle, PVOID pBuffer)
  554. {
  555. POUTBUF pOutBuf;
  556. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  557. DC_BEGIN_FN("NM_FreeBuffer");
  558. /************************************************************************/
  559. /* Get the OutBuf pointer stored in prefix */
  560. /************************************************************************/
  561. pOutBuf = *((POUTBUF *)
  562. ((BYTE *)pBuffer - SendDataReqPrefixBytes - sizeof(POUTBUF)));
  563. /************************************************************************/
  564. /* Free the buffer */
  565. /************************************************************************/
  566. IcaBufferFree(pRealNMHandle->pContext, pOutBuf);
  567. DC_END_FN();
  568. } /* NM_FreeBuffer */
  569. /****************************************************************************/
  570. /* Name: NM_SendData */
  571. /* */
  572. /* Purpose: Send data to the appropriate net or pipe destination. */
  573. /* */
  574. /* Returns: TRUE - data sent OK */
  575. /* FALSE - data not sent */
  576. /* */
  577. /* Params: pNMHandle - NM handle */
  578. /* pData - data to send */
  579. /* dataSize - length of data to send */
  580. /* priority - priority to send the data on */
  581. /* userID - user to send the data to (0 = broadcast data) */
  582. /* FastPathOutputFlags - flags from higher layers. Low bit TRUE */
  583. /* means send as fast-path output, using the rest of the */
  584. /*
  585. /* */
  586. /* Operation: Send the data. */
  587. /* - The buffer holding the data must have been allocated using */
  588. /* NM_AllocBuffer. */
  589. /* - Return code FALSE means that a network error occurred. The */
  590. /* caller need do nothing - an NM_DISCONNECTED callback will */
  591. /* eventually arrive. */
  592. /* - The buffer is ALWAYS freed. */
  593. /* */
  594. /* This function is synchronous. */
  595. /****************************************************************************/
  596. BOOL __fastcall NM_SendData(
  597. PVOID pNMHandle,
  598. PBYTE pData,
  599. UINT32 dataSize,
  600. UINT32 priority,
  601. UINT32 userID,
  602. UINT32 FastPathOutputFlags)
  603. {
  604. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  605. BOOL rc = TRUE;
  606. POUTBUF pOutBuf;
  607. MCSError MCSErr;
  608. DC_BEGIN_FN("NM_SendData");
  609. /************************************************************************/
  610. /* Get the OutBuf pointer stored in prefix */
  611. /************************************************************************/
  612. pOutBuf = *((POUTBUF *)
  613. ((BYTE *)pData - SendDataReqPrefixBytes - sizeof(POUTBUF)));
  614. /************************************************************************/
  615. /* Complete the OutBuf. The pBuffer was already set up when the OutBuf */
  616. /* was allocated. MCS needs the user data size set in the OutBuf. */
  617. /************************************************************************/
  618. pOutBuf->ByteCount = dataSize;
  619. // All but shadow passthru stacks get the data sent to the network.
  620. if (pRealNMHandle->pWDHandle->StackClass != Stack_Passthru) {
  621. if (FastPathOutputFlags & NM_SEND_FASTPATH_OUTPUT) {
  622. NTSTATUS Status;
  623. SD_RAWWRITE SdWrite;
  624. // Fast-path output skips MCS. We rewrite the security header
  625. // into the fast-path format, complete the OutBuf, and send
  626. // directly to the transport. For header format details, see
  627. // at128.h. Note we need to wait for the security header
  628. // to be written in SM before getting here in case this
  629. // is a passthru stack.
  630. // First, the 4-byte RNS_SECURITY_HEADER disappears, if present,
  631. // collapsed into the high bit of the first byte.
  632. // Note that the 8-byte MAC signature in RNS_SECURITY_HEADER1
  633. // remains, if present.
  634. if (!(FastPathOutputFlags & NM_NO_SECURITY_HEADER)) {
  635. dataSize -= sizeof(RNS_SECURITY_HEADER);
  636. pData += sizeof(RNS_SECURITY_HEADER);
  637. }
  638. // Work backwards from where we are: First, the total packet
  639. // length including the header.
  640. if (dataSize <= 125) {
  641. // 1-byte form of length, high bit 0.
  642. dataSize += 2;
  643. pData -= 2;
  644. *(pData + 1) = (BYTE)dataSize;
  645. }
  646. else {
  647. // 2-byte form of length, first byte has high bit 1 and 7
  648. // most significant bits.
  649. dataSize += 3;
  650. pData -= 3;
  651. *(pData + 1) = (BYTE)(0x80 | ((dataSize & 0x7F00) >> 8));
  652. *(pData + 2) = (BYTE)(dataSize & 0xFF);
  653. }
  654. // The header byte. This includes TS_OUTPUT_FASTPATH_ACTION_FASTPATH
  655. // and TS_OUTPUT_FASTPATH_ENCRYPTED, if present in the
  656. // fast-path output flags.
  657. *pData = (BYTE)(TS_OUTPUT_FASTPATH_ACTION_FASTPATH |
  658. (FastPathOutputFlags &
  659. TS_OUTPUT_FASTPATH_ENCRYPTION_MASK));
  660. // Set up the OutBuf with its final contents.
  661. pOutBuf->pBuffer = pData;
  662. pOutBuf->ByteCount = dataSize;
  663. // Send downward.
  664. SdWrite.pBuffer = NULL;
  665. SdWrite.ByteCount = 0;
  666. SdWrite.pOutBuf = pOutBuf;
  667. Status = IcaCallNextDriver(pRealNMHandle->pWDHandle->pContext,
  668. SD$RAWWRITE, &SdWrite);
  669. if (NT_SUCCESS(Status)) {
  670. // Increment protocol counters.
  671. pRealNMHandle->pWDHandle->pProtocolStatus->Output.WdFrames++;
  672. pRealNMHandle->pWDHandle->pProtocolStatus->Output.WdBytes +=
  673. dataSize;
  674. }
  675. else {
  676. TRC_ERR((TB,"Failed IcaRawWrite to network, status=%X",
  677. Status));
  678. rc = FALSE;
  679. // We do not free the OutBuf here, TD is supposed to do it.
  680. }
  681. }
  682. else {
  683. TRC_DBG((TB, "Send data on channel %x", userID));
  684. MCSErr = MCSSendDataRequest(pRealNMHandle->hUser,
  685. userID == 0 ? pRealNMHandle->hChannel : NULL,
  686. NORMAL_SEND_DATA,
  687. (ChannelID)userID,
  688. (MCSPriority)priority,
  689. SEGMENTATION_BEGIN | SEGMENTATION_END,
  690. pOutBuf);
  691. if (MCSErr == MCS_NO_ERROR) {
  692. TRC_DATA_NRM("Send OK", pOutBuf, dataSize);
  693. }
  694. else
  695. {
  696. TRC_ERR((TB, "Failed to send OutBuf %p, buffer %p, MCSErr %x",
  697. pOutBuf, pData, MCSErr));
  698. rc = FALSE;
  699. }
  700. }
  701. #ifdef DC_COUNTERS
  702. if (rc) {
  703. PTSHARE_WD m_pTSWd = pRealNMHandle->pWDHandle;
  704. if (dataSize > CORE_IN_COUNT[IN_MAX_PKT_SIZE])
  705. {
  706. CORE_IN_COUNT[IN_MAX_PKT_SIZE] = dataSize;
  707. }
  708. CORE_IN_COUNT[IN_PKT_TOTAL_SENT]++;
  709. if (dataSize < 201) {
  710. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD1]++;
  711. } else if (dataSize < 401) {
  712. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD2]++;
  713. } else if (dataSize < 601) {
  714. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD3]++;
  715. } else if (dataSize < 801) {
  716. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD4]++;
  717. } else if (dataSize < 1001) {
  718. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD5]++;
  719. } else if (dataSize < 1201 ) {
  720. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD6]++;
  721. } else if (dataSize < 1401) {
  722. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD7]++;
  723. } else if (dataSize < 1601) {
  724. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD8]++;
  725. } else if (dataSize < 2001) {
  726. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD9]++;
  727. } else if (dataSize < 4001) {
  728. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD10]++;
  729. } else if (dataSize < 6001) {
  730. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD11]++;
  731. } else if (dataSize < 8001) {
  732. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD12]++;
  733. } else {
  734. CORE_IN_COUNT[IN_PKT_BYTE_SPREAD13]++;
  735. }
  736. }
  737. #endif
  738. }
  739. // Raw write the potentially encrypted data to the shadow stack
  740. else {
  741. SD_RAWWRITE SdWrite;
  742. NTSTATUS status;
  743. TRC_ASSERT((!(FastPathOutputFlags & NM_SEND_FASTPATH_OUTPUT)),
  744. (TB,"Fast-path output requested across shadow pipe!"));
  745. SdWrite.pOutBuf = pOutBuf;
  746. SdWrite.pBuffer = NULL;
  747. SdWrite.ByteCount = 0;
  748. status = IcaCallNextDriver(pRealNMHandle->pContext, SD$RAWWRITE, &SdWrite);
  749. if (status == STATUS_SUCCESS) {
  750. TRC_DBG((TB, "RawWrite: %ld bytes", dataSize));
  751. }
  752. else {
  753. TRC_ERR((TB, "RawWrite failed: %lx", status));
  754. }
  755. }
  756. DC_END_FN();
  757. return rc;
  758. } /* NM_SendData */
  759. /****************************************************************************/
  760. /* Name: NM_MCSUserCallback */
  761. /* */
  762. /* Purpose: Direct callback from MCS */
  763. /* */
  764. /* Returns: nothing */
  765. /* */
  766. /* Params: hUser - should be our user handle */
  767. /* Message - the callback type */
  768. /* Params - Cast to the right type of parameter depending on */
  769. /* callback */
  770. /* UserDefined - our NM handle */
  771. /* */
  772. /* Operation: Called by MCS for callbacks. */
  773. /* */
  774. /* Processing depends on the callback type */
  775. /* - MCS_DETACH_USER_INDICATION */
  776. /* - call SM_OnDisconnected */
  777. /* - all others are ignored. */
  778. /****************************************************************************/
  779. void __stdcall NM_MCSUserCallback(UserHandle hUser,
  780. unsigned Message,
  781. void *Params,
  782. void *UserDefined)
  783. {
  784. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)UserDefined;
  785. DC_BEGIN_FN("NM_MCSUserCallback");
  786. /************************************************************************/
  787. /* First check that this is our UserHandle */
  788. /************************************************************************/
  789. ASSERT(hUser == pRealNMHandle->hUser);
  790. /************************************************************************/
  791. /* If the Share Core is dead, don't do any of this */
  792. /************************************************************************/
  793. if (pRealNMHandle->dead)
  794. {
  795. TRC_ALT((TB, "Callback %s (%d) ignored because we're dead",
  796. Message == MCS_ATTACH_USER_CONFIRM ? "MCS_ATTACH_USER_CONFIRM" :
  797. Message == MCS_CHANNEL_JOIN_CONFIRM ? "MCS_CHANNEL_JOIN_CONFIRM" :
  798. Message == MCS_DETACH_USER_INDICATION ? "MCS_DETACH_USER_INDICATION" :
  799. Message == MCS_SEND_DATA_INDICATION ? "MCS_SEND_DATA_INDICATION" :
  800. "- Unknown - ",
  801. Message));
  802. DC_QUIT;
  803. }
  804. /************************************************************************/
  805. /* Handle callbacks we care about */
  806. /************************************************************************/
  807. switch (Message)
  808. {
  809. case MCS_DETACH_USER_INDICATION:
  810. {
  811. DetachUserIndication *pDUin;
  812. TRC_NRM((TB, "DetachUserIndication"));
  813. pDUin = (DetachUserIndication *)Params;
  814. NMDetachUserInd(pRealNMHandle,
  815. pDUin->Reason,
  816. pDUin->UserID);
  817. }
  818. break;
  819. default:
  820. {
  821. TRC_ERR((TB, "Unhandled MCS callback type %d", Message ));
  822. }
  823. break;
  824. }
  825. DC_EXIT_POINT:
  826. DC_END_FN();
  827. } /* NM_MCSUserCallback */
  828. /****************************************************************************/
  829. /* Name: NM_Dead */
  830. /****************************************************************************/
  831. void RDPCALL NM_Dead(PVOID pNMHandle, BOOL dead)
  832. {
  833. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  834. DC_BEGIN_FN("NM_Dead");
  835. TRC_NRM((TB, "NM Dead ? %s", pRealNMHandle->dead ? "Y" : "N"));
  836. pRealNMHandle->dead = dead;
  837. DC_END_FN();
  838. } /* NM_Dead */
  839. /****************************************************************************/
  840. /* Name: NM_VirtualQueryBindings */
  841. /* */
  842. /* Purpose: Return virtual channel bindings to WD */
  843. /* */
  844. /* Params: pNMHandle - NM Handle */
  845. /* pVBind - pointer to virtual bindings structure to fill in */
  846. /* vBindLength - size (bytes) of virtual bindings structure */
  847. /* pBytesReturned - size (bytes) of data returned */
  848. /****************************************************************************/
  849. NTSTATUS RDPCALL NM_VirtualQueryBindings(PVOID pNMHandle,
  850. PSD_VCBIND pVBind,
  851. ULONG vBindLength,
  852. PULONG pBytesReturned)
  853. {
  854. NTSTATUS status;
  855. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  856. USHORT virtualClass;
  857. UINT i;
  858. DC_BEGIN_FN("NM_VirtualQueryBindings");
  859. /************************************************************************/
  860. /* First see if we have any bindings to report */
  861. /************************************************************************/
  862. if (pRealNMHandle->channelCount == 0)
  863. {
  864. TRC_ALT((TB, "No Virtual Channels to report"));
  865. *pBytesReturned = 0;
  866. status = STATUS_SUCCESS;
  867. DC_QUIT;
  868. }
  869. /************************************************************************/
  870. /* Check there is enough space to report them */
  871. /************************************************************************/
  872. *pBytesReturned = (pRealNMHandle->channelCount * sizeof(SD_VCBIND));
  873. if (vBindLength < *pBytesReturned)
  874. {
  875. TRC_ERR((TB, "Not enough space for %d VCs: need/got %d/%d",
  876. pRealNMHandle->channelCount, *pBytesReturned, vBindLength));
  877. status = STATUS_BUFFER_TOO_SMALL;
  878. DC_QUIT;
  879. }
  880. /************************************************************************/
  881. /* Copy channel names and assign numbers */
  882. /************************************************************************/
  883. for (i = 0, virtualClass = 0;
  884. i < pRealNMHandle->channelCount;
  885. i++, virtualClass++, pVBind++)
  886. {
  887. /********************************************************************/
  888. /* Can't use channel 7 as it's used by RDPDD */
  889. /********************************************************************/
  890. if (i == WD_THINWIRE_CHANNEL)
  891. {
  892. TRC_NRM((TB, "Skip channel %d", i));
  893. virtualClass++;
  894. }
  895. strcpy(pVBind->VirtualName,
  896. pRealNMHandle->channelData[virtualClass].name);
  897. pVBind->VirtualClass = virtualClass;
  898. pVBind->Flags = 0;
  899. if (pRealNMHandle->channelData[virtualClass].flags & CHANNEL_OPTION_REMOTE_CONTROL_PERSISTENT) {
  900. pVBind->Flags |= SD_CHANNEL_FLAG_SHADOW_PERSISTENT;
  901. }
  902. TRC_NRM((TB, "Assigned channel %d to %s",
  903. pVBind->VirtualClass, pVBind->VirtualName));
  904. }
  905. /************************************************************************/
  906. /* That's all */
  907. /************************************************************************/
  908. status = STATUS_SUCCESS;
  909. DC_EXIT_POINT:
  910. DC_END_FN();
  911. return(status);
  912. } /* NM_VirtualQueryBindings */
  913. /****************************************************************************/
  914. /* Name: NM_MCSChannelToVirtual */
  915. /* */
  916. /* Purpose: Convert an MCS channel ID into a virtual channel ID */
  917. /* */
  918. /* Returns: Virtual Channel ID */
  919. /* */
  920. /* Params: pNMHandle - NM Handle */
  921. /* channelID - MCS Channel ID */
  922. /* ppChannelData - data stored for this channel (returned) */
  923. /****************************************************************************/
  924. VIRTUALCHANNELCLASS RDPCALL NM_MCSChannelToVirtual(
  925. PVOID pNMHandle,
  926. UINT16 channelID,
  927. PPNM_CHANNEL_DATA ppChannelData)
  928. {
  929. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  930. PNM_CHANNEL_DATA pChannelData;
  931. unsigned i;
  932. VIRTUALCHANNELCLASS rc;
  933. DC_BEGIN_FN("NM_MCSChannelToVirtual");
  934. /************************************************************************/
  935. /* Find this MCS Channel */
  936. /************************************************************************/
  937. TRC_DBG((TB, "Find MCS channel %hx", channelID));
  938. for (i = 0, pChannelData = pRealNMHandle->channelData;
  939. i < pRealNMHandle->channelArrayCount;
  940. i++, pChannelData++)
  941. {
  942. TRC_DBG((TB, "Compare entry %d: %hx", i, pChannelData->MCSChannelID));
  943. if (pChannelData->MCSChannelID == channelID)
  944. {
  945. rc = i;
  946. *ppChannelData = pChannelData;
  947. TRC_NRM((TB, "MCS channel %hx is VC %d", channelID, rc));
  948. DC_QUIT;
  949. }
  950. }
  951. /************************************************************************/
  952. /* If we get here, we failed to find a match */
  953. /************************************************************************/
  954. TRC_NRM((TB, "No match for MCS channel ID %hx", channelID));
  955. rc = -1;
  956. *ppChannelData = NULL;
  957. DC_EXIT_POINT:
  958. DC_END_FN();
  959. return(rc);
  960. } /* NM_MCSChannelToVirtual */
  961. /****************************************************************************/
  962. /* Name: NM_VirtualChannelToMCS */
  963. /* */
  964. /* Purpose: Convert a virtual channel ID into an MCS channel ID */
  965. /* */
  966. /* Returns: MCS Channel ID */
  967. /* */
  968. /* Params: pNMHandle - NM Handle */
  969. /* channelID - virtual channel ID */
  970. /* ppChannelData - data stored for this channel (returned) */
  971. /****************************************************************************/
  972. INT16 RDPCALL NM_VirtualChannelToMCS(PVOID pNMHandle,
  973. VIRTUALCHANNELCLASS channelID,
  974. PPNM_CHANNEL_DATA ppChannelData)
  975. {
  976. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  977. INT16 rc;
  978. DC_BEGIN_FN("NM_VirtualChannelToMCS");
  979. /************************************************************************/
  980. /* Check the virtual channel is in range */
  981. /************************************************************************/
  982. if (channelID >= (VIRTUALCHANNELCLASS)(pRealNMHandle->channelArrayCount))
  983. {
  984. TRC_ERR((TB, "Unknown virtual channel %d", channelID));
  985. rc = -1;
  986. DC_QUIT;
  987. }
  988. /************************************************************************/
  989. /* Find this Virtual Channel */
  990. /************************************************************************/
  991. rc = pRealNMHandle->channelData[channelID].MCSChannelID;
  992. *ppChannelData = &(pRealNMHandle->channelData[channelID]);
  993. TRC_NRM((TB, "Virtual channel %d = MCS Channel %hx", channelID, rc));
  994. DC_EXIT_POINT:
  995. DC_END_FN();
  996. return(rc);
  997. } /* NM_VirtualChannelToMCS */
  998. /****************************************************************************/
  999. /* Name: NM_QueryChannels */
  1000. /* */
  1001. /* Purpose: Return virtual channel data */
  1002. /* */
  1003. /* Returns: TRUE/FALSE */
  1004. /* */
  1005. /* Params: pNMHandle - NM Handle */
  1006. /* pOutbuf - buffer to receive output data */
  1007. /* outbufLength - size of outbuf */
  1008. /* pBytesReturned - amount of data returned */
  1009. /****************************************************************************/
  1010. NTSTATUS RDPCALL NM_QueryChannels(PVOID pNMHandle,
  1011. PVOID pOutbuf,
  1012. unsigned outbufLength,
  1013. PULONG pBytesReturned)
  1014. {
  1015. NTSTATUS status;
  1016. PCHANNEL_CONNECT_IN pChannelConnect;
  1017. PCHANNEL_CONNECT_DEF pChannelDef;
  1018. PNM_HANDLE_DATA pRealNMHandle = (PNM_HANDLE_DATA)pNMHandle;
  1019. unsigned bytesNeeded;
  1020. unsigned i;
  1021. DC_BEGIN_FN("NM_QueryChannels");
  1022. /************************************************************************/
  1023. /* Check enough space has been supplied */
  1024. /************************************************************************/
  1025. bytesNeeded = sizeof(CHANNEL_CONNECT_IN) +
  1026. (pRealNMHandle->channelArrayCount * sizeof(CHANNEL_CONNECT_DEF));
  1027. if (outbufLength < bytesNeeded)
  1028. {
  1029. TRC_ERR((TB, "Not enough space: need/got %d/%d",
  1030. bytesNeeded, outbufLength));
  1031. status = STATUS_BUFFER_TOO_SMALL;
  1032. DC_QUIT;
  1033. }
  1034. /************************************************************************/
  1035. /* Complete the returned data */
  1036. /************************************************************************/
  1037. pChannelConnect = (PCHANNEL_CONNECT_IN)pOutbuf;
  1038. pChannelConnect->channelCount = pRealNMHandle->channelArrayCount;
  1039. pChannelDef = (PCHANNEL_CONNECT_DEF)(pChannelConnect + 1);
  1040. for (i = 0; i < pRealNMHandle->channelArrayCount; i++)
  1041. {
  1042. strcpy(pChannelDef[i].name, pRealNMHandle->channelData[i].name);
  1043. pChannelDef[i].ID = i;
  1044. }
  1045. /************************************************************************/
  1046. /* Return status and bytesReturned */
  1047. /************************************************************************/
  1048. *pBytesReturned = bytesNeeded;
  1049. status = STATUS_SUCCESS;
  1050. DC_EXIT_POINT:
  1051. DC_END_FN();
  1052. return(status);
  1053. } /* NM_QueryChannels */
  1054.