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.

1089 lines
48 KiB

  1. /****************************************************************************/
  2. /* ascint.c */
  3. /* */
  4. /* Share Controller Internal functions. */
  5. /* */
  6. /* Copyright(c) Microsoft, PictureTel 1992-1997 */
  7. /* Copyright(c) Microsoft 1997-2000 */
  8. /****************************************************************************/
  9. #include <precomp.h>
  10. #pragma hdrstop
  11. #define TRC_FILE "ascint"
  12. #include <as_conf.hpp>
  13. #include <string.h>
  14. #include <stdio.h>
  15. extern "C"
  16. {
  17. #include <asmapi.h>
  18. }
  19. /****************************************************************************/
  20. /* FUNCTION: SCPartyJoiningShare */
  21. /* */
  22. /* Called when a new party is joining the share. This is an internal */
  23. /* function because it is the SC which calls all these functions. The */
  24. /* processing done here relies on the capabilities - so it is in here as */
  25. /* this is called after CPC_PartyJoiningShare. */
  26. /* */
  27. /* PARAMETERS: */
  28. /* locPersonID - local person ID of remote person joining the share. */
  29. /* oldShareSize - the number of the parties which were in the share (ie */
  30. /* excludes the joining party). */
  31. /* */
  32. /* RETURNS: */
  33. /* TRUE if the party can join the share. */
  34. /* FALSE if the party can NOT join the share. */
  35. /****************************************************************************/
  36. BOOL RDPCALL SHCLASS SCPartyJoiningShare(LOCALPERSONID locPersonID,
  37. unsigned oldShareSize)
  38. {
  39. DC_BEGIN_FN("SCPartyJoiningShare");
  40. DC_IGNORE_PARAMETER(locPersonID);
  41. if (oldShareSize != 0) {
  42. SCParseGeneralCaps();
  43. // Initialize Flow Control.
  44. SCFlowInit();
  45. }
  46. DC_END_FN();
  47. return TRUE;
  48. }
  49. /****************************************************************************/
  50. /* FUNCTION: SCPartyLeftShare() */
  51. /* */
  52. /* Called when a party has left the share. */
  53. /* */
  54. /* PARAMETERS: */
  55. /* locPersonID - local person ID of remote person leaving the */
  56. /* share. */
  57. /* newShareSize - the number of the parties now in the share (ie excludes */
  58. /* the leaving party). */
  59. /****************************************************************************/
  60. void RDPCALL SHCLASS SCPartyLeftShare(LOCALPERSONID locPersonID,
  61. unsigned newShareSize)
  62. {
  63. DC_BEGIN_FN("SCPartyLeftShare");
  64. DC_IGNORE_PARAMETER(locPersonID);
  65. if (newShareSize != 0)
  66. SCParseGeneralCaps();
  67. DC_END_FN();
  68. }
  69. /****************************************************************************/
  70. // SCParseGeneralCaps
  71. //
  72. // Enumerates the general capabilities and sets up needed variables.
  73. /****************************************************************************/
  74. void RDPCALL SHCLASS SCParseGeneralCaps()
  75. {
  76. DC_BEGIN_FN("SCParseGeneralCaps");
  77. // Set default local support for fast-path output. It must be shut down
  78. // during a shadow to guarantee the non-fast-path format is used
  79. // in the cross-server shadow pipe, even though that means a performance
  80. // hit on the wire to each client. Note that checking for shadowState
  81. // == SHADOW_NONE is not a sufficient check, there is a timing window
  82. // where it is likely not be be set yet, so we also force it off in
  83. // SC_AddPartyToShare().
  84. if (m_pTSWd->shadowState == SHADOW_NONE) {
  85. scUseFastPathOutput = TRUE;
  86. }
  87. else {
  88. scUseFastPathOutput = FALSE;
  89. TRC_ALT((TB,"Forcing fast-path output to off in shadow"));
  90. }
  91. CPC_EnumerateCapabilities(TS_CAPSETTYPE_GENERAL, NULL,
  92. SCEnumGeneralCaps);
  93. // Set the package header reservation size based on the final results of
  94. // the fast-path output support.
  95. if (scUseFastPathOutput) {
  96. if (m_pTSWd->bCompress) {
  97. TRC_ALT((TB,"Fast-path output enabled with compression"));
  98. scUpdatePDUHeaderSpace = 4;
  99. scCompressionUsedValue = TS_OUTPUT_FASTPATH_COMPRESSION_USED;
  100. }
  101. else {
  102. TRC_ALT((TB,"Fast-path output enabled without compression"));
  103. scUpdatePDUHeaderSpace = 3;
  104. scCompressionUsedValue = 0;
  105. }
  106. }
  107. else {
  108. TRC_ALT((TB,"Fast-path output disabled"));
  109. scUpdatePDUHeaderSpace = sizeof(TS_SHAREDATAHEADER);
  110. }
  111. SCUpdateVCCaps();
  112. DC_END_FN();
  113. }
  114. /****************************************************************************/
  115. /* FUNCTION: SCEnumGeneralCaps */
  116. /* */
  117. /* Used to determine the lowest version in the share. */
  118. /* */
  119. /* PARAMETERS: standard CPC callback parameters */
  120. /****************************************************************************/
  121. void RDPCALL SHCLASS SCEnumGeneralCaps(
  122. LOCALPERSONID locPersonID,
  123. UINT_PTR UserData,
  124. PTS_CAPABILITYHEADER pCapabilities )
  125. {
  126. PTS_GENERAL_CAPABILITYSET pGeneralCaps =
  127. (PTS_GENERAL_CAPABILITYSET)pCapabilities;
  128. DC_BEGIN_FN("SCEnumGeneralCaps");
  129. DC_IGNORE_PARAMETER(locPersonID);
  130. DC_IGNORE_PARAMETER(UserData);
  131. // Determine if we should support No BC header or not depending on the
  132. // client support level and the current support level
  133. scNoBitmapCompressionHdr = min(scNoBitmapCompressionHdr,
  134. pGeneralCaps->extraFlags & TS_EXTRA_NO_BITMAP_COMPRESSION_HDR);
  135. // Disable fast-path output if any client does not support it.
  136. if (!(pGeneralCaps->extraFlags & TS_FASTPATH_OUTPUT_SUPPORTED))
  137. scUseFastPathOutput = FALSE;
  138. // Enable sending Long Credentials back to the client if it supports it
  139. if (pGeneralCaps->extraFlags & TS_LONG_CREDENTIALS_SUPPORTED) {
  140. scUseLongCredentials = TRUE;
  141. } else {
  142. scUseLongCredentials = FALSE;
  143. }
  144. // Determine if we should enable the arc cookie
  145. if ((pGeneralCaps->extraFlags & TS_AUTORECONNECT_COOKIE_SUPPORTED) &&
  146. (FALSE == m_pTSWd->fPolicyDisablesArc)) {
  147. scUseAutoReconnect = TRUE;
  148. }
  149. else {
  150. scUseAutoReconnect = FALSE;
  151. }
  152. // Determine if we support the more secure checksum style
  153. if ((pGeneralCaps->extraFlags & TS_ENC_SECURE_CHECKSUM)) {
  154. SM_SetSafeChecksumMethod(scPSMHandle, TRUE);
  155. }
  156. else {
  157. SM_SetSafeChecksumMethod(scPSMHandle, FALSE);
  158. }
  159. DC_END_FN();
  160. }
  161. /****************************************************************************/
  162. /* FUNCTION: SCCallPartyJoiningShare */
  163. /* */
  164. /* Calls other components' XX_PartyJoiningShare() functions. Should be */
  165. /* called with scNumberInShare set to the old call size. */
  166. /* */
  167. /* PARAMETERS: */
  168. /* locPersonID - of party joining the call. */
  169. /* sizeOfCaps - sizeof the capabilities parameter pCaps. */
  170. /* pCaps - pointer to capabilities for the party. */
  171. /* pAccepted - pointer to array of BOOLs which is filled in with the */
  172. /* result of the respective components function. */
  173. /* oldShareSize - the number to pass to the PJS functions. */
  174. /* */
  175. /* RETURNS: */
  176. /* TRUE - all components accepted the party; pAccepted will be filled with */
  177. /* TRUE. */
  178. /* FALSE - a component rejected the party. Any components which accepted */
  179. /* the party will have their pAccepted entry set to TRUE; all other */
  180. /* entries will be FALSE. */
  181. /****************************************************************************/
  182. BOOL RDPCALL SHCLASS SCCallPartyJoiningShare(
  183. LOCALPERSONID locPersonID,
  184. unsigned sizeOfCaps,
  185. PVOID pCaps,
  186. PBOOL pAccepted,
  187. unsigned oldShareSize)
  188. {
  189. DC_BEGIN_FN("SCCallPartyJoiningShare");
  190. /************************************************************************/
  191. /* Set all of pAccepted to FALSE. */
  192. /************************************************************************/
  193. memset(pAccepted, 0, sizeof(BOOL) * SC_NUM_PARTY_JOINING_FCTS);
  194. /************************************************************************/
  195. /* Call the functions in the correct order, giving up if any reject the */
  196. /* party. */
  197. /************************************************************************/
  198. #define CALL_PJS(NUM, CALL) \
  199. TRC_NRM((TB, "Call PJS # %d", NUM)); \
  200. if (0 == (pAccepted[NUM] = CALL)) \
  201. { \
  202. TRC_NRM((TB, "%d PartyJoining failed", (unsigned)NUM)); \
  203. return FALSE; \
  204. }
  205. TRC_NRM((TB, "{%d}Call PJS functions", locPersonID));
  206. /************************************************************************/
  207. // Notes on the order of PartyJoiningShare calls:
  208. // 1. CPC must be called before everyone else (as everyone else needs
  209. // capabilites for the new party).
  210. // 2. UP must be called after SC because UP relies on the caps
  211. // negotiation in SC.
  212. /************************************************************************/
  213. CALL_PJS(SC_CPC, CPC_PartyJoiningShare(locPersonID, oldShareSize,
  214. sizeOfCaps, pCaps))
  215. CALL_PJS(SC_SC, SCPartyJoiningShare(locPersonID, oldShareSize))
  216. CALL_PJS(SC_IM, IM_PartyJoiningShare (locPersonID, oldShareSize))
  217. CALL_PJS(SC_CA, CA_PartyJoiningShare (locPersonID, oldShareSize))
  218. CALL_PJS(SC_CM, CM_PartyJoiningShare (locPersonID, oldShareSize))
  219. CALL_PJS(SC_OE, OE_PartyJoiningShare (locPersonID, oldShareSize))
  220. CALL_PJS(SC_SSI, SSI_PartyJoiningShare(locPersonID, oldShareSize))
  221. CALL_PJS(SC_USR, USR_PartyJoiningShare(locPersonID, oldShareSize))
  222. CALL_PJS(SC_UP, UP_PartyJoiningShare(locPersonID, oldShareSize))
  223. CALL_PJS(SC_SBC, SBC_PartyJoiningShare(locPersonID, oldShareSize))
  224. TRC_DATA_NRM("PJS status",
  225. pAccepted,
  226. sizeof(BOOL) * SC_NUM_PARTY_JOINING_FCTS);
  227. DC_END_FN();
  228. return TRUE;
  229. }
  230. /****************************************************************************/
  231. /* FUNCTION: SCCallPartyLeftShare */
  232. /* */
  233. /* Calls other components' XX_PartyLeftShare() functions. should be called */
  234. /* with scNumberInShare set to the new call size. */
  235. /* */
  236. /* PARAMETERS: */
  237. /* locPersonID - of party who has left the call. */
  238. /* pAccepted - pointer to array of BOOLs which is used to decide which */
  239. /* components' functions to call. Any component with an entry set to */
  240. /* TRUE will be called. */
  241. /* newShareSize - the number to pass to the various PLS functions. */
  242. /****************************************************************************/
  243. void RDPCALL SHCLASS SCCallPartyLeftShare(LOCALPERSONID locPersonID,
  244. PBOOL pAccepted,
  245. unsigned newShareSize )
  246. {
  247. DC_BEGIN_FN("SCCallPartyLeftShare");
  248. /************************************************************************/
  249. /* Call any components which have their pAccepted entry to TRUE. */
  250. /************************************************************************/
  251. #define CALL_PLS(A, B) \
  252. { \
  253. if (pAccepted[A]) \
  254. { \
  255. TRC_NRM((TB, "Call PLS # %d", A)); \
  256. B(locPersonID, newShareSize); \
  257. } \
  258. }
  259. TRC_NRM((TB, "Call PLS functions"));
  260. /************************************************************************/
  261. /* Notes on order of PartyLeftShare calls */
  262. /* */
  263. /* 1. CPC must be called first (so everyone else gets capabilities */
  264. /* which exclude the party which has left). */
  265. /************************************************************************/
  266. CALL_PLS(SC_CPC, CPC_PartyLeftShare)
  267. CALL_PLS(SC_SC, SCPartyLeftShare)
  268. CALL_PLS(SC_CA, CA_PartyLeftShare )
  269. CALL_PLS(SC_IM, IM_PartyLeftShare )
  270. CALL_PLS(SC_OE, OE_PartyLeftShare )
  271. CALL_PLS(SC_SBC, SBC_PartyLeftShare)
  272. CALL_PLS(SC_SSI, SSI_PartyLeftShare)
  273. CALL_PLS(SC_USR, USR_PartyLeftShare)
  274. CALL_PLS(SC_UP, UP_PartyLeftShare)
  275. TRC_NRM((TB, "Done PLS functions"));
  276. DC_END_FN();
  277. }
  278. /****************************************************************************/
  279. /* Name: SCInitiateSync */
  280. /* */
  281. /* Purpose: Initiate synchronization */
  282. /* */
  283. /* Params: bShadowSync - set to true of this sync is being requested for */
  284. /* a shadowing session. */
  285. /* */
  286. /* Operation: Broadcast a sync packet on all priorities */
  287. /* Call other components to synchronize, unless this is a shadow */
  288. /* sync in which case the DD will already have synchronized */
  289. /* itself prior to initiating this action. */
  290. /****************************************************************************/
  291. void RDPCALL SHCLASS SCInitiateSync(BOOLEAN bShadowSync)
  292. {
  293. PTS_SYNCHRONIZE_PDU pPkt;
  294. NTSTATUS status;
  295. BOOL rc;
  296. DC_BEGIN_FN("SCInitiateSync");
  297. SC_CHECK_STATE(SCE_INITIATESYNC);
  298. /************************************************************************/
  299. // Allocate a Sync PDU
  300. // fWait is TRUE means that we will always wait for a buffer to be avail
  301. /************************************************************************/
  302. status = SM_AllocBuffer(scPSMHandle,
  303. (PPVOID)(&pPkt),
  304. sizeof(TS_SYNCHRONIZE_PDU),
  305. TRUE,
  306. FALSE);
  307. if ( STATUS_SUCCESS == status ) {
  308. /********************************************************************/
  309. // Build the Sync PDU
  310. /********************************************************************/
  311. pPkt->shareDataHeader.shareControlHeader.totalLength =
  312. sizeof(TS_SYNCHRONIZE_PDU);
  313. pPkt->shareDataHeader.pduType2 = TS_PDUTYPE2_SYNCHRONIZE;
  314. pPkt->messageType = TS_SYNCMSGTYPE_SYNC;
  315. /********************************************************************/
  316. // Send the Sync PDU (Broadcast, all parties, all priorities)
  317. /********************************************************************/
  318. rc = SC_SendData((PTS_SHAREDATAHEADER)pPkt,
  319. sizeof(TS_SYNCHRONIZE_PDU),
  320. sizeof(TS_SYNCHRONIZE_PDU),
  321. 0, 0);
  322. if (rc) {
  323. TRC_NRM((TB, "Sent Sync OK"));
  324. /****************************************************************/
  325. // Call all the XX_SyncNow() functions.
  326. /****************************************************************/
  327. CA_SyncNow();
  328. PM_SyncNow(); // added for shadowing
  329. UP_SyncNow(bShadowSync);
  330. }
  331. else {
  332. TRC_ERR((TB, "Failed to send Sync PDU"));
  333. }
  334. }
  335. else {
  336. TRC_ERR((TB, "Failed to alloc syncPDU"));
  337. }
  338. DC_EXIT_POINT:
  339. DC_END_FN();
  340. } /* SCInitiateSync */
  341. /****************************************************************************/
  342. /* Name: SCConfirmActive */
  343. /* */
  344. /* Purpose: Handle incoming ConfirmActivePDU */
  345. /* */
  346. /* Params: netPersonID - ID of sender of ConfirmActivePDU */
  347. /* pPkt - ConfirmActivePDU */
  348. /****************************************************************************/
  349. void RDPCALL SHCLASS SCConfirmActive(
  350. PTS_CONFIRM_ACTIVE_PDU pPkt,
  351. unsigned DataLength,
  352. NETPERSONID netPersonID)
  353. {
  354. LOCALPERSONID localPersonID = 0;
  355. unsigned localCapsSize;
  356. PTS_COMBINED_CAPABILITIES pLocalCaps;
  357. BOOL acceptedArray[SC_NUM_PARTY_JOINING_FCTS];
  358. BOOL rc = FALSE;
  359. BOOL callingPJS = FALSE;
  360. BOOL kickWDW = FALSE;
  361. unsigned errDetailCode = 0;
  362. WCHAR detailData[25];
  363. unsigned len, detailDataLen;
  364. DC_BEGIN_FN("SCConfirmActive");
  365. SC_CHECK_STATE(SCE_CONFIRM_ACTIVE);
  366. // First check we have enogh data for this packet.
  367. if (DataLength >= (sizeof(TS_CONFIRM_ACTIVE_PDU) - 1)) {
  368. if (DataLength >= (sizeof(TS_CONFIRM_ACTIVE_PDU) - 1 +
  369. pPkt->lengthSourceDescriptor +
  370. pPkt->lengthCombinedCapabilities)) {
  371. // Do some meaningful work here to predict the branches correctly.
  372. goto PDUOK;
  373. }
  374. else {
  375. TRC_ERR((TB,"Total PDU len %u too short for header and data len %u",
  376. DataLength, pPkt->lengthSourceDescriptor +
  377. pPkt->lengthCombinedCapabilities));
  378. goto ShortPDU;
  379. }
  380. }
  381. else {
  382. TRC_ERR((TB,"Data length %u too short for ConfirmActivePDU header",
  383. DataLength));
  384. goto ShortPDU;
  385. }
  386. PDUOK:
  387. kickWDW = FALSE;
  388. /************************************************************************/
  389. /* Check it's the right ConfirmActivePDU */
  390. /************************************************************************/
  391. if (pPkt->shareID != scShareID)
  392. {
  393. TRC_ERR((TB, "Wrong Share ID, expect %x, got %x",
  394. scShareID, pPkt->shareID));
  395. errDetailCode = Log_RDP_ConfirmActiveWrongShareID;
  396. len = swprintf(detailData, L"%x %x", scShareID, pPkt->shareID);
  397. detailDataLen = sizeof(*detailData) * len;
  398. DC_QUIT;
  399. }
  400. if (pPkt->originatorID != scUserID)
  401. {
  402. TRC_ERR((TB, "Wrong originator ID, expect %d, got %hd",
  403. scUserID, pPkt->originatorID));
  404. errDetailCode = Log_RDP_ConfirmActiveWrongOriginator;
  405. len = swprintf(detailData, L"%x %hx", scUserID, pPkt->originatorID);
  406. detailDataLen = sizeof(*detailData) * len;
  407. DC_QUIT;
  408. }
  409. /************************************************************************/
  410. /* We will receive a ConfirmActivePDU on all priorities. If we get */
  411. /* here and we're already in a Share, this must be a second or */
  412. /* subsequent one. Simply ignore it. Set rc = TRUE so that we don't */
  413. /* send a DeactivateOtherPDU below. */
  414. /************************************************************************/
  415. if (scState == SCS_IN_SHARE)
  416. {
  417. TRC_ALT((TB, "Superfluous ConfirmActivePDU received"));
  418. rc = TRUE;
  419. DC_QUIT;
  420. }
  421. /************************************************************************/
  422. /* If we get here, this is the first ConfirmActivePDU, and it's from */
  423. /* the right Client. Set a flag which will cause us to kick WDW back */
  424. /* into life at the end of this function */
  425. /************************************************************************/
  426. kickWDW = TRUE;
  427. /************************************************************************/
  428. /* Reject this party if it will exceed the maximum number of parties */
  429. /* allowed in a share. (Not required for RNS V1.0, but left in as it */
  430. /* doesn't do any harm). */
  431. /************************************************************************/
  432. if (scNumberInShare == SC_DEF_MAX_PARTIES)
  433. {
  434. TRC_ERR((TB, "Reached max parties in share %d",
  435. SC_DEF_MAX_PARTIES));
  436. DC_QUIT;
  437. }
  438. /************************************************************************/
  439. /* If this is the first remote party in the share, call the */
  440. /* XX_PartyJoiningShare() functions for the local party first. */
  441. /************************************************************************/
  442. callingPJS = TRUE;
  443. if (scNumberInShare == 0)
  444. {
  445. CPC_GetCombinedCapabilities(SC_LOCAL_PERSON_ID,
  446. &localCapsSize,
  447. &pLocalCaps);
  448. if (!SCCallPartyJoiningShare(SC_LOCAL_PERSON_ID,
  449. localCapsSize,
  450. pLocalCaps,
  451. acceptedArray,
  452. 0))
  453. {
  454. /****************************************************************/
  455. /* Some component rejected the local party */
  456. /****************************************************************/
  457. TRC_ERR((TB, "The local party should never be rejected"));
  458. DC_QUIT;
  459. }
  460. /********************************************************************/
  461. /* There is now one party in the share (the local one). */
  462. /********************************************************************/
  463. scNumberInShare = 1;
  464. TRC_NRM((TB, "Added local person"));
  465. }
  466. /************************************************************************/
  467. /* Calculate a localPersonID for the remote party and store their */
  468. /* details in the party array. */
  469. /************************************************************************/
  470. for ( localPersonID = 1;
  471. localPersonID < SC_DEF_MAX_PARTIES;
  472. localPersonID++ )
  473. {
  474. if (scPartyArray[localPersonID].netPersonID == 0)
  475. {
  476. /****************************************************************/
  477. /* Found an empty slot. */
  478. /****************************************************************/
  479. TRC_NRM((TB, "Allocated local person ID %d", localPersonID));
  480. break;
  481. }
  482. }
  483. /************************************************************************/
  484. /* Even though scNumberInShare is checked against SC_DEF_MAX_PARTIES */
  485. /* above, the loop above might still not find an empty slot. */
  486. /************************************************************************/
  487. if (SC_DEF_MAX_PARTIES <= localPersonID)
  488. {
  489. TRC_ABORT((TB, "Couldn't find room to store local person"));
  490. DC_QUIT;
  491. }
  492. /************************************************************************/
  493. /* Store the new person's details */
  494. /************************************************************************/
  495. scPartyArray[localPersonID].netPersonID = netPersonID;
  496. // we know that we have at least lengthSourceDescriptor bytes in the buffer
  497. // we should copy not more than lengthSourceDescriptor or the destination
  498. // buffer size.
  499. strncpy(scPartyArray[localPersonID].name,
  500. (char *)(&(pPkt->data[0])),
  501. min(sizeof(scPartyArray[0].name)-sizeof(scPartyArray[0].name[0]),
  502. pPkt->lengthSourceDescriptor));
  503. // zero terminate to make sure we don't overflow on subsequent processing.
  504. scPartyArray[localPersonID].name[sizeof(scPartyArray[0].name)/
  505. sizeof(scPartyArray[0].name[0]) - 1] = 0;
  506. memset(scPartyArray[localPersonID].sync,
  507. 0,
  508. sizeof(scPartyArray[localPersonID].sync));
  509. TRC_NRM((TB, "{%d} person name %s",
  510. (unsigned)localPersonID, scPartyArray[localPersonID].name));
  511. /************************************************************************/
  512. /* Call the XX_PartyJoiningShare() functions for the remote party. */
  513. /************************************************************************/
  514. if (!SCCallPartyJoiningShare(localPersonID,
  515. pPkt->lengthCombinedCapabilities,
  516. (PVOID)(&(pPkt->data[pPkt->lengthSourceDescriptor])),
  517. acceptedArray,
  518. scNumberInShare))
  519. {
  520. /********************************************************************/
  521. // Some component rejected the remote party. Force a disconnect
  522. // and log an event.
  523. /********************************************************************/
  524. TRC_ERR((TB, "Remote party rejected"));
  525. errDetailCode = Log_RDP_BadCapabilities;
  526. detailDataLen = 0;
  527. DC_QUIT;
  528. }
  529. /************************************************************************/
  530. /* The remote party is now in the share. */
  531. /************************************************************************/
  532. callingPJS = FALSE;
  533. rc = TRUE;
  534. scNumberInShare++;
  535. TRC_NRM((TB, "Number in share %d", (unsigned)scNumberInShare));
  536. /************************************************************************/
  537. /* Move onto the next state. */
  538. /************************************************************************/
  539. SC_SET_STATE(SCS_IN_SHARE);
  540. /************************************************************************/
  541. /* Synchronise only for primary stacks. Shadow stacks will be sync'd */
  542. /* by the DD right before output starts. */
  543. /************************************************************************/
  544. SCInitiateSync(m_pTSWd->StackClass == Stack_Shadow);
  545. DC_EXIT_POINT:
  546. if (!rc)
  547. {
  548. /********************************************************************/
  549. /* Something went wrong. Tidy up */
  550. /********************************************************************/
  551. TRC_NRM((TB, "Something went wrong - %d people in Share",
  552. scNumberInShare));
  553. /********************************************************************/
  554. /* If we fail, tell WDW now, so it can clean up. If we succeed, FH */
  555. /* tells WDW when font negotiation is complete. */
  556. /********************************************************************/
  557. if (kickWDW)
  558. {
  559. TRC_NRM((TB, "Kick WDW"));
  560. WDW_ShareCreated(m_pTSWd, FALSE);
  561. }
  562. if (callingPJS)
  563. {
  564. TRC_NRM((TB, "Failed in PJS functions"));
  565. /****************************************************************/
  566. /* Notify components that remote party has left Share. Note */
  567. /* that scNumberInShare is not updated if PJS functions fail. */
  568. /****************************************************************/
  569. if (scNumberInShare > 0)
  570. {
  571. /************************************************************/
  572. /* We failed to add a remote party */
  573. /************************************************************/
  574. TRC_NRM((TB, "Failed to add remote party"));
  575. SCCallPartyLeftShare(localPersonID,
  576. acceptedArray,
  577. scNumberInShare );
  578. /************************************************************/
  579. /* Set acceptedArray ready to call PJS for local person */
  580. /************************************************************/
  581. memset(acceptedArray,
  582. TRUE,
  583. sizeof(BOOL) * SC_NUM_PARTY_JOINING_FCTS );
  584. }
  585. if (scNumberInShare <= 1)
  586. {
  587. /************************************************************/
  588. /* We failed to add one of */
  589. /* - the local person (scNumberInShare == 0) */
  590. /* - the first remote person (scNumberInShare == 1) */
  591. /* Either way, we now need to remove the local person. */
  592. /************************************************************/
  593. TRC_NRM((TB, "Clean up local person"));
  594. SCCallPartyLeftShare(SC_LOCAL_PERSON_ID,
  595. acceptedArray, 0);
  596. scNumberInShare = 0;
  597. }
  598. }
  599. /********************************************************************/
  600. /* Now we need to terminate the Client, via one of two means: */
  601. /* - if it's a protocol error, simply disconnect the Client */
  602. /* - if it's a resource error, try to end the Share. */
  603. /********************************************************************/
  604. if (errDetailCode != 0)
  605. {
  606. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  607. errDetailCode,
  608. (BYTE *)detailData,
  609. detailDataLen);
  610. }
  611. TRC_NRM((TB, "Reject the new person"));
  612. SCDeactivateOther(netPersonID);
  613. /********************************************************************/
  614. /* Finally, free the local person ID, if one was allocated */
  615. /********************************************************************/
  616. if ((localPersonID != 0) && (localPersonID != SC_DEF_MAX_PARTIES))
  617. {
  618. TRC_NRM((TB, "Free local person ID"));
  619. scPartyArray[localPersonID].netPersonID = 0;
  620. }
  621. }
  622. DC_END_FN();
  623. return;
  624. // Error handling
  625. ShortPDU:
  626. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_ConfirmActivePDUTooShort,
  627. (BYTE *)pPkt, DataLength);
  628. DC_END_FN();
  629. } /* SC_ConfirmActivePDU */
  630. /****************************************************************************/
  631. /* Name: SCDeactivateOther */
  632. /* */
  633. /* Purpose: Deactivate another person */
  634. /* */
  635. /* Params: netPersonID - ID of person to be deactivated */
  636. /****************************************************************************/
  637. void RDPCALL SHCLASS SCDeactivateOther(NETPERSONID netPersonID)
  638. {
  639. unsigned pktLen;
  640. unsigned nameLen;
  641. PTS_DEACTIVATE_OTHER_PDU pPkt;
  642. NTSTATUS status;
  643. BOOL rc;
  644. DC_BEGIN_FN("SCDeactivateOther");
  645. /************************************************************************/
  646. /* Allocate a buffer */
  647. /************************************************************************/
  648. pktLen = sizeof(TS_DEACTIVATE_OTHER_PDU) - 1;
  649. nameLen = strlen(scPartyArray[0].name);
  650. nameLen = (unsigned)DC_ROUND_UP_4(nameLen);
  651. pktLen += nameLen;
  652. // fWait is TRUE means that we will always wait for a buffer to be avail
  653. status = SM_AllocBuffer(scPSMHandle, (PPVOID)(&pPkt), pktLen, TRUE, FALSE);
  654. if ( STATUS_SUCCESS == status ) {
  655. /********************************************************************/
  656. // Fill in the packet fields.
  657. /********************************************************************/
  658. pPkt->shareControlHeader.totalLength = (UINT16)pktLen;
  659. pPkt->shareControlHeader.pduType = TS_PDUTYPE_DEACTIVATEOTHERPDU |
  660. TS_PROTOCOL_VERSION;
  661. pPkt->shareControlHeader.pduSource = (UINT16)scUserID;
  662. pPkt->shareID = scShareID;
  663. pPkt->deactivateID = (UINT16)netPersonID;
  664. memcpy(&(pPkt->sourceDescriptor[0]), scPartyArray[0].name, nameLen);
  665. // Send it.
  666. rc = SM_SendData(scPSMHandle, pPkt, pktLen, TS_HIGHPRIORITY, 0,
  667. FALSE, RNS_SEC_ENCRYPT, FALSE);
  668. if (!rc) {
  669. TRC_ERR((TB, "Failed to send TS_DEACTIVATE_OTHER_PDU"));
  670. }
  671. }
  672. else {
  673. /********************************************************************/
  674. /* Failed to allocate a buffer. This Bad News. Give up. */
  675. /********************************************************************/
  676. TRC_ERR((TB, "Failed to alloc %d bytes for TS_DEACTIVATE_OTHER_PDU",
  677. pktLen));
  678. }
  679. DC_END_FN();
  680. } /* SCDeactivateOther */
  681. /****************************************************************************/
  682. /* Name: SCEndShare */
  683. /* */
  684. /* Purpose: Clean up the local side of the share */
  685. /* */
  686. /* Operation: Call all PartyLeftShare functions for each party. */
  687. /****************************************************************************/
  688. void RDPCALL SHCLASS SCEndShare(void)
  689. {
  690. BOOL acceptedArray[SC_NUM_PARTY_JOINING_FCTS];
  691. int i;
  692. DC_BEGIN_FN("SCEndShare");
  693. /************************************************************************/
  694. /* If no-one has joined the Share yet, there's nothing to do */
  695. /************************************************************************/
  696. if (scNumberInShare == 0)
  697. {
  698. TRC_ALT((TB, "Ending Share before it was started"));
  699. DC_QUIT;
  700. }
  701. /************************************************************************/
  702. /* Call PLS for all remote people. */
  703. /************************************************************************/
  704. memset(acceptedArray, TRUE, sizeof(acceptedArray));
  705. for (i = SC_DEF_MAX_PARTIES - 1; i > 0; i--)
  706. {
  707. if (scPartyArray[i].netPersonID != 0)
  708. {
  709. TRC_NRM((TB, "Party %d left Share", i));
  710. scNumberInShare--;
  711. SCCallPartyLeftShare(i, acceptedArray, scNumberInShare);
  712. memset(&(scPartyArray[i]), 0, sizeof(*scPartyArray));
  713. }
  714. }
  715. /************************************************************************/
  716. /* Now call PLS functions for the local person. Don't clear */
  717. /* scPartyArray for the local person, as the info is still valid. */
  718. /************************************************************************/
  719. scNumberInShare--;
  720. TRC_ASSERT((scNumberInShare == 0),
  721. (TB, "Still %d people in the Share", scNumberInShare));
  722. TRC_NRM((TB, "Local party left Share"));
  723. SCCallPartyLeftShare(0, acceptedArray, scNumberInShare);
  724. DC_EXIT_POINT:
  725. /************************************************************************/
  726. /* Return to the inititalized state */
  727. /************************************************************************/
  728. SC_SET_STATE(SCS_INITED);
  729. DC_END_FN();
  730. } /* SCEndShare */
  731. /****************************************************************************/
  732. /* Name: SCSynchronizePDU */
  733. /* */
  734. /* Purpose: Handle incoming Synchronize PDUs */
  735. /* */
  736. /* Params: netPersonID - user ID of the sender */
  737. /* pPkt - SynchronizePDU */
  738. /****************************************************************************/
  739. void RDPCALL SHCLASS SCSynchronizePDU(NETPERSONID netPersonID,
  740. UINT32 priority,
  741. PTS_SYNCHRONIZE_PDU pPkt)
  742. {
  743. LOCALPERSONID localID;
  744. DC_BEGIN_FN("SCSynchronizePDU");
  745. localID = SC_NetworkIDToLocalID(netPersonID);
  746. TRC_NRM((TB, "SynchronizePDU person [%d] {%d}, priority %d",
  747. netPersonID, localID, priority));
  748. scPartyArray[localID].sync[priority] = TRUE;
  749. DC_END_FN();
  750. } /* SCSynchronizePDU */
  751. /****************************************************************************/
  752. /* Name: SCReceivedControlPacket */
  753. /* */
  754. /* Purpose: Handle incoming control packets */
  755. /* */
  756. /* Params: netPersonID - ID of the sender */
  757. /* priority - priority on which the packet was sent */
  758. /* pPkt - the packet */
  759. /****************************************************************************/
  760. void RDPCALL SHCLASS SCReceivedControlPacket(
  761. NETPERSONID netPersonID,
  762. UINT32 priority,
  763. void *pPkt,
  764. unsigned DataLength)
  765. {
  766. unsigned pduType;
  767. LOCALPERSONID locPersonID;
  768. BOOL pduOK = FALSE;
  769. BOOL status;
  770. DC_BEGIN_FN("SCReceivedControlPacket");
  771. // We have enough data to read the flow control marker since the marker
  772. // is overlaid over the SHARECONTROLHEADER.totalLength. We checked earlier
  773. // for having enough data to read the share ctrl hdr.
  774. /************************************************************************/
  775. /* First, check for Flow Control packets */
  776. /************************************************************************/
  777. if (((PTS_FLOW_PDU)pPkt)->flowMarker != TS_FLOW_MARKER)
  778. {
  779. /********************************************************************/
  780. /* Check for control packets */
  781. /********************************************************************/
  782. // SC_CHECK_STATE(SCE_CONTROLPACKET);
  783. pduOK = TRUE;
  784. pduType = ((PTS_SHARECONTROLHEADER)pPkt)->pduType & TS_MASK_PDUTYPE;
  785. switch (pduType) {
  786. case TS_PDUTYPE_CONFIRMACTIVEPDU:
  787. TRC_ALT((TB, "%s Stack: ConfirmActivePDU",
  788. m_pTSWd->StackClass == Stack_Primary ? "Primary" :
  789. (m_pTSWd->StackClass == Stack_Passthru ? "Passthru" :
  790. "Shadow")));
  791. SCConfirmActive((PTS_CONFIRM_ACTIVE_PDU)pPkt, DataLength,
  792. netPersonID);
  793. break;
  794. case TS_PDUTYPE_CLIENTRANDOMPDU:
  795. TRC_ALT((TB, "ClientRandomPDU"));
  796. status = SC_SaveClientRandom((PTS_CLIENT_RANDOM_PDU) pPkt, DataLength);
  797. if (status != TRUE)
  798. {
  799. TRC_ERR((TB, "Error in SC_SaveClientRandom, data length = %u", DataLength));
  800. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  801. Log_RDP_InputPDUBadLength,
  802. (BYTE *) pPkt,
  803. DataLength);
  804. }
  805. break;
  806. default:
  807. {
  808. /************************************************************/
  809. /* At the moment, we don't expect or process any other */
  810. /* control packets */
  811. /************************************************************/
  812. TRC_ERR((TB, "Unexpected packet type %d", pduType));
  813. TRC_DATA_NRM("Packet", pPkt,
  814. ((PTS_SHARECONTROLHEADER)&pPkt)->totalLength);
  815. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  816. Log_RDP_UnknownPDUType,
  817. (BYTE *) &pduType,
  818. sizeof(pduType));
  819. }
  820. break;
  821. }
  822. }
  823. else
  824. {
  825. /********************************************************************/
  826. /* For the purposes of state checking, treat Flow Control packets */
  827. /* as data packets. */
  828. /********************************************************************/
  829. SC_CHECK_STATE(SCE_DATAPACKET);
  830. pduOK = TRUE;
  831. // Make sure we have enough data to access the TS_FLOW_PDU fields.
  832. if (DataLength >= sizeof(TS_FLOW_PDU)) {
  833. pduType = ((PTS_FLOW_PDU)pPkt)->pduType;
  834. locPersonID = SC_NetworkIDToLocalID(netPersonID);
  835. }
  836. else {
  837. TRC_ERR((TB,"Data length %u too short for FlowPDU", DataLength));
  838. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_FlowPDUTooShort,
  839. (BYTE *)pPkt, DataLength);
  840. DC_QUIT;
  841. }
  842. switch (pduType)
  843. {
  844. case TS_PDUTYPE_FLOWTESTPDU:
  845. {
  846. TRC_NRM((TB, "[%d] {%d} Flow Test PDU on priority %d",
  847. netPersonID, locPersonID, priority));
  848. SCFlowTestPDU(locPersonID, (PTS_FLOW_PDU)pPkt, priority);
  849. }
  850. break;
  851. default:
  852. {
  853. TRC_ERR((TB, "[%d] {%d} Unknown Flow PDU %d on priority %d",
  854. netPersonID, locPersonID, pduType, priority));
  855. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  856. Log_RDP_UnknownFlowPDU,
  857. (BYTE *) &pduType,
  858. sizeof(pduType));
  859. }
  860. break;
  861. }
  862. }
  863. DC_EXIT_POINT:
  864. if (!pduOK)
  865. {
  866. /********************************************************************/
  867. /* Out-of-sequence control PDU - log and disconnect */
  868. /********************************************************************/
  869. WCHAR detailData[(sizeof(pduType)*2) + (sizeof(scState)*2) + 2];
  870. TRC_ERR((TB, "Out-of-sequence control PDU %hx, state %d",
  871. pduType, scState));
  872. swprintf(detailData, L"%hx %x", pduType, scState);
  873. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  874. Log_RDP_ControlPDUSequence,
  875. (BYTE *)detailData,
  876. sizeof(detailData));
  877. }
  878. DC_END_FN();
  879. } /* SCReceivedControlPacket */
  880. /****************************************************************************/
  881. /* Name: SCFlowTestPDU */
  882. /* */
  883. /* Purpose: Handle incoming Flow Test PDUs */
  884. /* */
  885. /* Params: locPersonID - id of the sender */
  886. /* pPkt - the Flow Test PDU */
  887. /****************************************************************************/
  888. void RDPCALL SHCLASS SCFlowTestPDU(
  889. LOCALPERSONID locPersonID,
  890. PTS_FLOW_PDU pPkt,
  891. UINT32 priority)
  892. {
  893. PTS_FLOW_PDU pRsp;
  894. NTSTATUS status;
  895. BOOL rc;
  896. DC_BEGIN_FN("SCFlowTestPDU");
  897. // Build and send a flow response PDU.
  898. // fWait is TRUE means that we will always wait for a buffer to be avail
  899. status = SM_AllocBuffer(scPSMHandle, (PPVOID)(&pRsp), sizeof(*pRsp), TRUE, FALSE);
  900. if ( STATUS_SUCCESS == status ) {
  901. pRsp->flowMarker = TS_FLOW_MARKER;
  902. pRsp->pduType = TS_PDUTYPE_FLOWRESPONSEPDU;
  903. pRsp->flowIdentifier = pPkt->flowIdentifier;
  904. pRsp->flowNumber = pPkt->flowNumber;
  905. pRsp->pduSource = pPkt->pduSource;
  906. rc = SM_SendData(scPSMHandle, pRsp, sizeof(*pRsp), priority,
  907. scPartyArray[locPersonID].netPersonID, FALSE, RNS_SEC_ENCRYPT, FALSE);
  908. if (!rc) {
  909. TRC_ERR((TB, "Failed to send Flow Response PDU"));
  910. }
  911. }
  912. else {
  913. TRC_ERR((TB, "Failed to alloc Flow Response PDU"));
  914. }
  915. DC_END_FN();
  916. } /* SCFlowTestPDU */
  917. //
  918. // SCUpdateVCCaps update VirtualChannel capabilities based on
  919. // remote person's caps.
  920. //
  921. void RDPCALL SHCLASS SCUpdateVCCaps()
  922. {
  923. DC_BEGIN_FN("SCUpdateVCCaps");
  924. PTS_VIRTUALCHANNEL_CAPABILITYSET pVcCaps = NULL;
  925. //
  926. //Determine if the client supports VC compression
  927. //What we're determining here is that the client supports
  928. //the server sending it compressed VC data. The capability in the
  929. //other direction, i.e can the server send the client VC data
  930. //is a capability the server exposes to the client and it may choose
  931. //to then send compressed VC data to the server
  932. //
  933. pVcCaps = (PTS_VIRTUALCHANNEL_CAPABILITYSET)CPCGetCapabilities(
  934. SC_REMOTE_PERSON_ID, TS_CAPSETTYPE_VIRTUALCHANNEL);
  935. if(pVcCaps && (pVcCaps->vccaps1 & TS_VCCAPS_COMPRESSION_64K))
  936. {
  937. m_pTSWd->bClientSupportsVCCompression = TRUE;
  938. TRC_NRM((TB, "Client supports VC compression"));
  939. }
  940. else
  941. {
  942. m_pTSWd->bClientSupportsVCCompression = FALSE;
  943. TRC_NRM((TB, "Client doesn't support VC compression"));
  944. }
  945. DC_END_FN();
  946. }