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.

2996 lines
134 KiB

  1. /****************************************************************************/
  2. // ascapi.c
  3. //
  4. // Share Controller API Functions.
  5. //
  6. // Copyright (C) Microsoft Corp., PictureTel 1992-1997
  7. // Copyright (C) 1997-2000 Microsoft Corporation
  8. /****************************************************************************/
  9. #include <precomp.h>
  10. #pragma hdrstop
  11. #define TRC_FILE "ascapi"
  12. #include <as_conf.hpp>
  13. extern "C"
  14. {
  15. #include <acomapi.h>
  16. #include <asmapi.h>
  17. #include <asmint.h>
  18. }
  19. #include <string.h>
  20. /****************************************************************************/
  21. // SC_Init
  22. // Initializes the Share Controller.
  23. //
  24. // PARAMETERS:
  25. // pSMHandle - Handle to pass to SM calls
  26. //
  27. // RETURNS: FALSE on failure.
  28. /****************************************************************************/
  29. BOOL RDPCALL SHCLASS SC_Init(PVOID pSMHandle)
  30. {
  31. BOOL rc;
  32. unsigned MaxPDUSize;
  33. DC_BEGIN_FN("SC_Init");
  34. // Don't check the state - there's no static data init in the C++ App
  35. // Serving build so this will see complete garbage in scState and fail.
  36. #define DC_INIT_DATA
  37. #include <ascdata.c>
  38. #undef DC_INIT_DATA
  39. // Register with SM.
  40. rc = SM_Register(pSMHandle, &MaxPDUSize, &scUserID);
  41. if (rc) {
  42. // Save the User ID.
  43. scPartyArray[0].netPersonID = scUserID;
  44. scPSMHandle = pSMHandle;
  45. TRC_NRM((TB, "Local user id [%d]", scUserID));
  46. // Set the user name.
  47. strcpy(scPartyArray[0].name, "RDP");
  48. // Get the usable space (and hence the allocation request size) for
  49. // our 8K and 16K OutBufs.
  50. sc8KOutBufUsableSpace = IcaBufferGetUsableSpace(OUTBUF_8K_ALLOC_SIZE)
  51. - OUTBUF_HEADER_OVERHEAD;
  52. sc16KOutBufUsableSpace = IcaBufferGetUsableSpace(
  53. OUTBUF_16K_ALLOC_SIZE) - OUTBUF_HEADER_OVERHEAD;
  54. // Move onto the next state.
  55. SC_SET_STATE(SCS_INITED)
  56. }
  57. else {
  58. TRC_ERR((TB, "Failed to register with SM"));
  59. }
  60. DC_END_FN();
  61. return rc;
  62. }
  63. /****************************************************************************/
  64. // SC_Update
  65. // Update the Share Controller after shadow.
  66. //
  67. /****************************************************************************/
  68. void RDPCALL SHCLASS SC_Update()
  69. {
  70. DC_BEGIN_FN("SC_Update");
  71. scNoBitmapCompressionHdr = TS_EXTRA_NO_BITMAP_COMPRESSION_HDR;
  72. DC_END_FN();
  73. }
  74. /****************************************************************************/
  75. /* SC_Term() */
  76. /* */
  77. /* Terminates the Share Controller. */
  78. /****************************************************************************/
  79. void RDPCALL SHCLASS SC_Term(void)
  80. {
  81. DC_BEGIN_FN("SC_Term");
  82. SC_CHECK_STATE(SCE_TERM);
  83. // Reset state.
  84. SC_SET_STATE(SCS_STARTED);
  85. DC_EXIT_POINT:
  86. DC_END_FN();
  87. }
  88. /****************************************************************************/
  89. /* SC_CreateShare() */
  90. /* */
  91. /* Creates a share for the current session. */
  92. /****************************************************************************/
  93. BOOL RDPCALL SHCLASS SC_CreateShare(void)
  94. {
  95. BOOL rc = FALSE;
  96. unsigned pktLen;
  97. unsigned nameLen;
  98. unsigned capsSize;
  99. UINT32 sessionId;
  100. PTS_COMBINED_CAPABILITIES caps;
  101. PTS_DEMAND_ACTIVE_PDU pPkt = NULL;
  102. PTS_BITMAP_CAPABILITYSET pBitmapCaps;
  103. NTSTATUS status;
  104. DC_BEGIN_FN("SC_CreateShare");
  105. SC_CHECK_STATE(SCE_CREATE_SHARE);
  106. /************************************************************************/
  107. /* For console sessions, there's no client, so not much point in */
  108. /* sending a demand active PDU. We also have to set up caps ourselves. */
  109. /************************************************************************/
  110. if (m_pTSWd->StackClass == Stack_Console)
  111. {
  112. LOCALPERSONID localPersonID = 0;
  113. unsigned localCapsSize;
  114. PTS_COMBINED_CAPABILITIES pLocalCaps;
  115. BOOL acceptedArray[SC_NUM_PARTY_JOINING_FCTS];
  116. BOOL callingPJS = FALSE;
  117. TRC_NRM((TB, "SC_CreateShare called for console stack"));
  118. /********************************************************************/
  119. /* Move onto the next state. */
  120. /********************************************************************/
  121. SC_SET_STATE(SCS_IN_SHARE);
  122. /********************************************************************/
  123. /* carry on as if a confirm active has been received */
  124. /********************************************************************/
  125. callingPJS = TRUE;
  126. if (scNumberInShare == 0)
  127. {
  128. CPC_GetCombinedCapabilities(SC_LOCAL_PERSON_ID,
  129. &localCapsSize,
  130. &pLocalCaps);
  131. if (!SCCallPartyJoiningShare(SC_LOCAL_PERSON_ID,
  132. localCapsSize,
  133. pLocalCaps,
  134. acceptedArray,
  135. 0))
  136. {
  137. /************************************************************/
  138. /* Some component rejected the local party */
  139. /************************************************************/
  140. TRC_ERR((TB, "The local party should never be rejected"));
  141. DC_QUIT;
  142. }
  143. /****************************************************************/
  144. /* There is now one party in the share (the local one). */
  145. /****************************************************************/
  146. scNumberInShare = 1;
  147. TRC_NRM((TB, "Added local person"));
  148. }
  149. /********************************************************************/
  150. /* Calculate a localPersonID for the remote party and store their */
  151. /* details in the party array. */
  152. /********************************************************************/
  153. for ( localPersonID = 1;
  154. localPersonID < SC_DEF_MAX_PARTIES;
  155. localPersonID++ )
  156. {
  157. if (scPartyArray[localPersonID].netPersonID == 0)
  158. {
  159. /************************************************************/
  160. /* Found an empty slot. */
  161. /************************************************************/
  162. TRC_NRM((TB, "Allocated local person ID %d", localPersonID));
  163. break;
  164. }
  165. }
  166. /********************************************************************/
  167. /* If we don't find an empty slot, we can't keep running because */
  168. /* we write past the end of the scPartyArray below. */
  169. /********************************************************************/
  170. if (SC_DEF_MAX_PARTIES <= localPersonID)
  171. {
  172. TRC_ABORT((TB, "Couldn't find room to store local person"));
  173. DC_QUIT;
  174. }
  175. /********************************************************************/
  176. /* Store the new person's details */
  177. /********************************************************************/
  178. scPartyArray[localPersonID].netPersonID = 42;
  179. strncpy(scPartyArray[localPersonID].name,
  180. "Console",
  181. sizeof(scPartyArray[0].name) );
  182. memset(scPartyArray[localPersonID].sync,
  183. 0,
  184. sizeof(scPartyArray[localPersonID].sync));
  185. TRC_NRM((TB, "{%d} person name %s",
  186. (unsigned)localPersonID, scPartyArray[localPersonID].name));
  187. /********************************************************************/
  188. /* We need to set up client caps ourselves, since there's no actual */
  189. /* client to do it. We set up a maximal set that will get */
  190. /* negotiated down when someone shadows us. */
  191. /********************************************************************/
  192. typedef struct tagCC_COMBINED_CAPABILITIES
  193. {
  194. UINT16 numberCapabilities;
  195. #ifdef DRAW_GDIPLUS
  196. #ifdef DRAW_NINEGRID
  197. #define CC_COMBINED_CAPS_NUMBER_CAPABILITIES 18
  198. #else
  199. #define CC_COMBINED_CAPS_NUMBER_CAPABILITIES 17
  200. #endif
  201. #else // DRAW_GDIPLUS
  202. #ifdef DRAW_NINEGRID
  203. #define CC_COMBINED_CAPS_NUMBER_CAPABILITIES 17
  204. #else
  205. #define CC_COMBINED_CAPS_NUMBER_CAPABILITIES 16
  206. #endif
  207. #endif // DRAW_GDIPLUS
  208. UINT16 pad2octets;
  209. TS_GENERAL_CAPABILITYSET generalCapabilitySet;
  210. TS_BITMAP_CAPABILITYSET bitmapCapabilitySet;
  211. TS_ORDER_CAPABILITYSET orderCapabilitySet;
  212. TS_BITMAPCACHE_CAPABILITYSET bitmapCacheCaps;
  213. TS_COLORTABLECACHE_CAPABILITYSET colorTableCacheCapabilitySet;
  214. TS_WINDOWACTIVATION_CAPABILITYSET windowActivationCapabilitySet;
  215. TS_CONTROL_CAPABILITYSET controlCapabilitySet;
  216. TS_POINTER_CAPABILITYSET pointerCapabilitySet;
  217. TS_SHARE_CAPABILITYSET shareCapabilitySet;
  218. TS_INPUT_CAPABILITYSET inputCapabilitySet;
  219. TS_SOUND_CAPABILITYSET soundCapabilitySet;
  220. TS_FONT_CAPABILITYSET fontCapabilitySet;
  221. TS_GLYPHCACHE_CAPABILITYSET glyphCacheCapabilitySet;
  222. TS_BRUSH_CAPABILITYSET brushCapabilitySet;
  223. TS_OFFSCREEN_CAPABILITYSET offscreenCapabilitySet;
  224. TS_VIRTUALCHANNEL_CAPABILITYSET virtualchannelCapabilitySet;
  225. #ifdef DRAW_NINEGRID
  226. TS_DRAW_NINEGRID_CAPABILITYSET drawNineGridCapabilitySet;
  227. #endif
  228. #ifdef DRAW_GDIPLUS
  229. TS_DRAW_GDIPLUS_CAPABILITYSET drawGdiplusCapabilitySet;
  230. #endif
  231. } CC_COMBINED_CAPABILITIES;
  232. // ARG! Why isn't this const!!!
  233. CC_COMBINED_CAPABILITIES caps =
  234. {
  235. CC_COMBINED_CAPS_NUMBER_CAPABILITIES, /* Number of capabilities */
  236. 0, /* padding */
  237. /****************************************************************/
  238. /* General caps */
  239. /****************************************************************/
  240. {
  241. TS_CAPSETTYPE_GENERAL, /* capabilitySetType */
  242. sizeof(TS_GENERAL_CAPABILITYSET), /* lengthCapability */
  243. TS_OSMAJORTYPE_WINDOWS, /* OSMajorType */
  244. TS_OSMINORTYPE_WINDOWS_NT, /* OSMinorType */
  245. TS_CAPS_PROTOCOLVERSION, /* protocolVersion */
  246. 0, /* pad1 */
  247. 0, /* generalCompressionTypes */
  248. TS_EXTRA_NO_BITMAP_COMPRESSION_HDR |
  249. TS_FASTPATH_OUTPUT_SUPPORTED |
  250. TS_LONG_CREDENTIALS_SUPPORTED |
  251. TS_AUTORECONNECT_COOKIE_SUPPORTED |
  252. TS_ENC_SECURE_CHECKSUM,/*recv safer checksums */
  253. FALSE, /* updateCapabilityFlag */
  254. FALSE, /* remoteUnshareFlag */
  255. 0, /* generalCompressionLevel */
  256. 0, /* refreshRectSupport */
  257. 0 /* suppressOutputSupport */
  258. },
  259. /****************************************************************/
  260. /* Bitmap caps */
  261. /****************************************************************/
  262. {
  263. TS_CAPSETTYPE_BITMAP, /* capabilitySetType */
  264. sizeof(TS_BITMAP_CAPABILITYSET), /* lengthCapability */
  265. 8, /* Set in CC */ /* preferredBitsPerPixel */
  266. TRUE, /* receive1BitPerPixel */
  267. TRUE, /* receive4BitsPerPixel */
  268. TRUE, /* receive8BitsPerPixel */
  269. 1024, /* Set in CC */ /* desktopWidth */
  270. 768, /* Set in CC */ /* desktopHeight */
  271. 0, /* pad2 */
  272. FALSE, /* desktopResizeFlag */
  273. 1, /* bitmapCompressionFlag */
  274. 0, /* highColorFlags */
  275. 0, /* pad1 */
  276. TRUE, /* multipleRectangleSupport*/
  277. 0 /* pad2 */
  278. },
  279. /****************************************************************/
  280. /* Order Caps */
  281. /****************************************************************/
  282. {
  283. TS_CAPSETTYPE_ORDER, /* capabilitySetType */
  284. sizeof(TS_ORDER_CAPABILITYSET), /* lengthCapability */
  285. {'\0','\0','\0','\0','\0','\0','\0','\0',
  286. '\0','\0','\0','\0','\0','\0','\0','\0'}, /* terminalDescriptor */
  287. 0, /* pad1 */
  288. 1, /* desktopSaveXGranularity */
  289. 20, /* desktopSaveYGranularity */
  290. 0, /* pad2 */
  291. 1, /* maximumOrderLevel */
  292. 0, /* numberFonts */
  293. TS_ORDERFLAGS_ZEROBOUNDSDELTASSUPPORT | /* orderFlags */
  294. TS_ORDERFLAGS_NEGOTIATEORDERSUPPORT |
  295. TS_ORDERFLAGS_COLORINDEXSUPPORT,
  296. {
  297. /********************************************************/
  298. /* Order Support flags. */
  299. /* */
  300. /* The array index corresponds to the TS_NEG_xxx_INDEX */
  301. /* value indicated (from at128.h) The values marked */
  302. /* with an x in the first column are overwritten at run */
  303. /* time by UH before CC sends the combined */
  304. /* capabilities. */
  305. /********************************************************/
  306. 1, /* 0 TS_NEG_DSTBLT_INDEX destinationBltSupport */
  307. 1, /* 1 TS_NEG_PATBLT_INDEX patternBltSupport */
  308. 1, /* x 2 TS_NEG_SCRBLT_INDEX screenBltSupport */
  309. 1, /* 3 TS_NEG_MEMBLT_INDEX memoryBltSupport */
  310. 1, /* 4 TS_NEG_MEM3BLT_INDEX memoryThreeWayBltSupport */
  311. 0, /* x 5 TS_NEG_ATEXTOUT_INDEX textASupport */
  312. 0, /* x 6 TS_NEG_AEXTTEXTOUT_INDEX extendedTextASupport */
  313. #ifdef DRAW_NINEGRID
  314. 1, /* 7 TS_NEG_RECTANGLE_INDEX rectangleSupport */
  315. #else
  316. 0,
  317. #endif
  318. 1, /* 8 TS_NEG_LINETO_INDEX lineSupport */
  319. #ifdef DRAW_NINEGRID
  320. 1, /* 9 TS_NEG_FASTFRAME_INDEX frameSupport */
  321. #else
  322. 0,
  323. #endif
  324. 0, /* 10 TS_NEG_OPAQUERECT_INDEX opaqueRectangleSupport */
  325. 1, /* x11 TS_NEG_SAVEBITMAP_INDEX desktopSaveSupport */
  326. 0, /* x12 TS_NEG_WTEXTOUT_INDEX textWSupport */
  327. 1, /* 13 TS_NEG_MEMBLT_R2_INDEX Reserved entry */
  328. 1, /* 14 TS_NEG_MEM3BLT_R2_INDEX Reserved entry */
  329. 1, /* 15 TS_NEG_MULTIDSTBLT_INDEX multi DstBlt support */
  330. 1, /* 16 TS_NEG_MULTIPATBLT_INDEX multi PatBlt support */
  331. 1, /* 17 TS_NEG_MULTISCRBLT_INDEX multi ScrBlt support */
  332. 1, /* 18 TS_NEG_MULTIOPAQUERECT_INDEX multi OpaqueRect support */
  333. 1, /* 19 TS_NEG_FAST_INDEX */
  334. 1, /* 20 TS_NEG_POLYGON_SC_INDEX */
  335. 1, /* 21 TS_NEG_POLYGON_CB_INDEX */
  336. 1, /* 22 TS_NEG_POLYLINE_INDEX polyLineSupport */
  337. 0, /* 23 MS reserved entry 2 */
  338. 1, /* 24 TS_NEG_FAST_GLYPH_INDEX */
  339. 1, /* 25 TS_NEG_ELLIPSE_SC_INDEX */
  340. 1, /* 26 TS_NEG_ELLIPSE_CB_INDEX */
  341. 0, /* 27 MS reserved entry 6 */
  342. 0, /* x28 TS_NEG_WEXTTEXTOUT_INDEX extendedTextWSupport */
  343. 0, /* x29 TS_NEG_WLONGTEXTOUT_INDEX longTextWSupport */
  344. 0, /* x30 TS_NEG_WLONGEXTTEXTOUT_INDEX longExtendedTextWSupport */
  345. 0, /* 31 DCL reserved entry 3 */
  346. },
  347. (TS_TEXT_AND_MASK)|(TS_TEXT_OR_MASK), /* textFlags */
  348. 0, /* pad2 */
  349. 0, /* pad4 */
  350. 480 * 480, /* desktopSaveSize */
  351. 0, /* pad2 */
  352. 0, /* pad2 */
  353. 0, /* textANSICodePage */
  354. 0 /* pad2 */
  355. },
  356. /****************************************************************/
  357. /* BitmapCache Caps Note that this same space is used for rev1 */
  358. /* and rev2, we declare as rev1 because it is the larger of the */
  359. /* two. We will cast to rev2 if we get a server advertisement */
  360. /* that it supports rev2 (via */
  361. /* TS_BITMAPCACHE_CAPABILITYSET_HOSTSUPPORT). */
  362. /****************************************************************/
  363. {
  364. TS_CAPSETTYPE_BITMAPCACHE_REV2, /* capabilitySetType */
  365. sizeof(TS_BITMAPCACHE_CAPABILITYSET), /* lengthCapability */
  366. 0, /* pad DWORDs 1 */
  367. 0, /* pad DWORDs 2 */
  368. 0, /* pad DWORDs 3 */
  369. 0, /* pad DWORDs 4 */
  370. 0, /* pad DWORDs 5 */
  371. 0, /* pad DWORDs 6 */
  372. 0, 0, /* Cache1 */
  373. 0, 0, /* Cache2 */
  374. 0, 0, /* Cache3 */
  375. },
  376. /****************************************************************/
  377. /* ColorTableCache Caps */
  378. /****************************************************************/
  379. {
  380. TS_CAPSETTYPE_COLORCACHE, /* capabilitySetType */
  381. sizeof(TS_COLORTABLECACHE_CAPABILITYSET), /* lengthCapability */
  382. 6, /* colortableCacheSize */
  383. 0 /* notpartOfTSharePad */
  384. },
  385. /****************************************************************/
  386. /* WindowActivation Caps */
  387. /****************************************************************/
  388. {
  389. TS_CAPSETTYPE_ACTIVATION, /* capabilitySetType */
  390. sizeof(TS_WINDOWACTIVATION_CAPABILITYSET), /* lengthCapability */
  391. FALSE, /* helpKeyFlag */
  392. FALSE, /* helpKeyIndexFlag */
  393. FALSE, /* helpExtendedKeyFlag */
  394. FALSE /* windowManagerKeyFlag */
  395. },
  396. /****************************************************************/
  397. /* Control Caps */
  398. /****************************************************************/
  399. {
  400. TS_CAPSETTYPE_CONTROL, /* capabilitySetType */
  401. sizeof(TS_CONTROL_CAPABILITYSET), /* lengthCapability */
  402. 0, /* controlFlags */
  403. FALSE, /* remoteDetachFlag */
  404. TS_CONTROLPRIORITY_NEVER, /* controlInterest */
  405. TS_CONTROLPRIORITY_NEVER /* detachInterest */
  406. },
  407. /****************************************************************/
  408. /* Pointer Caps */
  409. /****************************************************************/
  410. {
  411. TS_CAPSETTYPE_POINTER, /* capabilitySetType */
  412. sizeof(TS_POINTER_CAPABILITYSET), /* lengthCapability */
  413. TRUE, /* colorPointerFlag */
  414. 20, /* colorPointerCacheSize */
  415. 21 /* pointerCacheSize */
  416. },
  417. /****************************************************************/
  418. /* Share Caps */
  419. /****************************************************************/
  420. {
  421. TS_CAPSETTYPE_SHARE, /* capabilitySetType */
  422. sizeof(TS_SHARE_CAPABILITYSET), /* lengthCapability */
  423. 0, /* nodeId */
  424. 0 /* padding */
  425. },
  426. /****************************************************************/
  427. /* Input Caps */
  428. /****************************************************************/
  429. {
  430. TS_CAPSETTYPE_INPUT,
  431. sizeof(TS_INPUT_CAPABILITYSET), /* lengthCapability */
  432. TS_INPUT_FLAG_SCANCODES
  433. | TS_INPUT_FLAG_MOUSEX, /* inputFlags */
  434. TS_INPUT_FLAG_FASTPATH_INPUT2, /* padding */
  435. 0 /* keyboard layout */
  436. },
  437. /****************************************************************/
  438. /* Sound */
  439. /****************************************************************/
  440. {
  441. TS_CAPSETTYPE_SOUND,
  442. sizeof(TS_SOUND_CAPABILITYSET), /* lengthCapability */
  443. TS_SOUND_FLAG_BEEPS, /* soundFlags */
  444. 0, /* padding */
  445. },
  446. /****************************************************************/
  447. /* Font */
  448. /****************************************************************/
  449. {
  450. TS_CAPSETTYPE_FONT,
  451. sizeof(TS_FONT_CAPABILITYSET), /* lengthCapability */
  452. TS_FONTSUPPORT_FONTLIST, /* fontSupportFlags */
  453. 0, /* padding */
  454. },
  455. /****************************************************************/
  456. /* GlyphCache Caps */
  457. /****************************************************************/
  458. {
  459. TS_CAPSETTYPE_GLYPHCACHE, /* capabilitySetType */
  460. sizeof(TS_GLYPHCACHE_CAPABILITYSET), /* lengthCapability */
  461. { /* GlyphCache */
  462. { 254, 4 },
  463. { 254, 4 },
  464. { 254, 8 },
  465. { 254, 8 },
  466. { 254, 16 },
  467. { 254, 32 },
  468. { 254, 64 },
  469. { 254, 128 },
  470. { 254, 256 },
  471. { 254, 2048 }
  472. },
  473. { 256, 256 }, /* FragCache */
  474. 2, /* GlyphSupportLevel */
  475. },
  476. /****************************************************************/
  477. /* Brush Caps */
  478. /****************************************************************/
  479. {
  480. TS_CAPSETTYPE_BRUSH, /* capabilitySetType */
  481. sizeof(TS_BRUSH_CAPABILITYSET), /* lengthCapability */
  482. 1, /* TS_BRUSH_COLOR8x8 */ /* brushSupportLevel */
  483. },
  484. // Enable this capability when GDI supports Device Bitmaps in mirroring
  485. // display drivers.
  486. /************************************************************************/
  487. /* Offscreen Caps */
  488. /************************************************************************/
  489. {
  490. TS_CAPSETTYPE_OFFSCREENCACHE, /* capabilitySetType */
  491. sizeof(TS_OFFSCREEN_CAPABILITYSET), /* lengthCapability */
  492. TS_OFFSCREEN_SUPPORTED, /* offscreenSupportLevel */
  493. TS_OFFSCREEN_CACHE_SIZE_SERVER_DEFAULT, /* offscreenCacheSize */
  494. TS_OFFSCREEN_CACHE_ENTRIES_DEFAULT, /* offscreenCacheEntries */
  495. },
  496. /************************************************************************/
  497. /* Virtual Channel Caps */
  498. /************************************************************************/
  499. {
  500. TS_CAPSETTYPE_VIRTUALCHANNEL, /* capabilitySetType */
  501. sizeof(TS_VIRTUALCHANNEL_CAPABILITYSET), /* lengthCapability */
  502. //
  503. // What this particular cap means is that the client understands
  504. // virtual channels compressed from the server at 64K.
  505. //
  506. // The client recevies what compression cap the server supports
  507. // from the client and compresses appropriately
  508. //
  509. TS_VCCAPS_COMPRESSION_64K,//TS_VCCAPS_DEFAULT?/* vc support flags */
  510. #ifdef DRAW_NINEGRID
  511. },
  512. {
  513. TS_CAPSETTYPE_DRAWNINEGRIDCACHE, // capabilitySetType
  514. sizeof(TS_DRAW_NINEGRID_CAPABILITYSET), // lengthCapability
  515. TS_DRAW_NINEGRID_SUPPORTED_REV2, // drawNineGridSupportLevel
  516. TS_DRAW_NINEGRID_CACHE_SIZE_DEFAULT, // drawNineGridCacheSize
  517. TS_DRAW_NINEGRID_CACHE_ENTRIES_DEFAULT, // drawNineGridCacheEntries
  518. #endif
  519. #ifdef DRAW_GDIPLUS
  520. },
  521. {
  522. TS_CAPSETTYPE_DRAWGDIPLUS, // capabilitySetType
  523. sizeof(TS_DRAW_GDIPLUS_CAPABILITYSET), // lengthCapability
  524. TS_DRAW_GDIPLUS_SUPPORTED, // drawEscapeSupportLevel
  525. 0xFFFFFFFF, // TSGdiplusVersion
  526. TS_DRAW_GDIPLUS_CACHE_LEVEL_ONE, // drawGdiplusCacheLevel
  527. TS_GDIP_GRAPHICS_CACHE_ENTRIES_DEFAULT,
  528. TS_GDIP_BRUSH_CACHE_ENTRIES_DEFAULT,
  529. TS_GDIP_PEN_CACHE_ENTRIES_DEFAULT,
  530. TS_GDIP_IMAGE_CACHE_ENTRIES_DEFAULT,
  531. TS_GDIP_IMAGEATTRIBUTES_CACHE_ENTRIES_DEFAULT,
  532. TS_GDIP_GRAPHICS_CACHE_CHUNK_SIZE_DEFAULT,
  533. TS_GDIP_BRUSH_CACHE_CHUNK_SIZE_DEFAULT,
  534. TS_GDIP_PEN_CACHE_CHUNK_SIZE_DEFAULT,
  535. TS_GDIP_IMAGEATTRIBUTES_CACHE_CHUNK_SIZE_DEFAULT,
  536. TS_GDIP_IMAGE_CACHE_CHUNK_SIZE_DEFAULT, // Chunk size to store image cache
  537. TS_GDIP_IMAGE_CACHE_TOTAL_SIZE_DEFAULT, // Total size of image cache in number of chunks
  538. TS_GDIP_IMAGE_CACHE_MAX_SIZE_DEFAULT, // Maximun size of image to cache, in number of chunks
  539. #endif
  540. }
  541. };
  542. /********************************************************************/
  543. /* set up bitmap cache caps */
  544. /********************************************************************/
  545. {
  546. TS_BITMAPCACHE_CAPABILITYSET_REV2 *pRev2Caps;
  547. // Rev2 caps.
  548. pRev2Caps = (TS_BITMAPCACHE_CAPABILITYSET_REV2 *)&caps.bitmapCacheCaps;
  549. TRC_ALT((TB,"Preparing REV2 caps for server\n"));
  550. pRev2Caps->capabilitySetType = TS_CAPSETTYPE_BITMAPCACHE_REV2;
  551. pRev2Caps->NumCellCaches = 3;
  552. pRev2Caps->bPersistentKeysExpected = FALSE;
  553. pRev2Caps->bAllowCacheWaitingList = FALSE;
  554. pRev2Caps->CellCacheInfo[0].bSendBitmapKeys = FALSE;
  555. pRev2Caps->CellCacheInfo[0].NumEntries = 600;
  556. pRev2Caps->CellCacheInfo[1].bSendBitmapKeys = FALSE;
  557. pRev2Caps->CellCacheInfo[1].NumEntries = 300;
  558. pRev2Caps->CellCacheInfo[2].bSendBitmapKeys = FALSE;
  559. pRev2Caps->CellCacheInfo[2].NumEntries = 300;
  560. pRev2Caps->CellCacheInfo[3].bSendBitmapKeys = 0;
  561. pRev2Caps->CellCacheInfo[3].NumEntries = 0;
  562. pRev2Caps->CellCacheInfo[4].bSendBitmapKeys = 0;
  563. pRev2Caps->CellCacheInfo[4].NumEntries = 0;
  564. }
  565. /********************************************************************/
  566. /* and screen size */
  567. /********************************************************************/
  568. {
  569. PTS_BITMAP_CAPABILITYSET pBmpCaps;
  570. pBmpCaps = (TS_BITMAP_CAPABILITYSET *)&caps.bitmapCapabilitySet;
  571. pBmpCaps->desktopWidth = (TSUINT16)(m_pTSWd->desktopWidth);
  572. pBmpCaps->desktopHeight = (TSUINT16)(m_pTSWd->desktopHeight);
  573. #ifdef DC_HICOLOR
  574. pBmpCaps->preferredBitsPerPixel = (TSUINT16)(m_pTSWd->desktopBpp);
  575. #endif
  576. }
  577. if (!SCCallPartyJoiningShare(localPersonID,
  578. sizeof(caps),
  579. &caps,
  580. acceptedArray,
  581. scNumberInShare))
  582. {
  583. /****************************************************************/
  584. /* Some component rejected the remote party */
  585. /****************************************************************/
  586. TRC_ERR((TB, "Remote party rejected"));
  587. DC_QUIT;
  588. }
  589. /********************************************************************/
  590. /* The remote party is now in the share. */
  591. /********************************************************************/
  592. callingPJS = FALSE;
  593. rc = TRUE;
  594. scNumberInShare++;
  595. TRC_NRM((TB, "Number in share %d", (unsigned)scNumberInShare));
  596. /********************************************************************/
  597. /* Synchronise only for primary stacks. Shadow stacks will be */
  598. /* sync'd by the DD right before output starts. */
  599. /********************************************************************/
  600. SCInitiateSync(m_pTSWd->StackClass == Stack_Shadow);
  601. /********************************************************************/
  602. /* don't wait for a response - there isn't a client out there. */
  603. /* Just wake up the WD now */
  604. /********************************************************************/
  605. TRC_NRM((TB, "Wake up WDW"));
  606. WDW_ShareCreated(m_pTSWd, TRUE);
  607. DC_QUIT;
  608. }
  609. /************************************************************************/
  610. /* Get the combined capabilities */
  611. /************************************************************************/
  612. CPC_GetCombinedCapabilities(SC_LOCAL_PERSON_ID, &capsSize, &caps);
  613. /************************************************************************/
  614. /* If we support dynamic client resizing, then we need to update the */
  615. /* desktop width and height in the caps passed out on the demand active */
  616. /* PDU to notify the client of the change */
  617. /************************************************************************/
  618. pBitmapCaps = (PTS_BITMAP_CAPABILITYSET) WDW_GetCapSet(
  619. m_pTSWd, TS_CAPSETTYPE_BITMAP, caps, capsSize);
  620. if (pBitmapCaps)
  621. {
  622. if (pBitmapCaps->desktopResizeFlag == TS_CAPSFLAG_SUPPORTED)
  623. {
  624. TRC_ALT((TB, "Update client desktop size"));
  625. pBitmapCaps->desktopHeight = (TSUINT16)(m_pTSWd->desktopHeight);
  626. pBitmapCaps->desktopWidth = (TSUINT16)(m_pTSWd->desktopWidth);
  627. }
  628. #ifdef DC_HICOLOR
  629. /********************************************************************/
  630. /* For high color, update the color depth too */
  631. /********************************************************************/
  632. pBitmapCaps->preferredBitsPerPixel = (TSUINT16)(m_pTSWd->desktopBpp);
  633. #endif
  634. }
  635. /************************************************************************/
  636. /* Get the sessionId from the WD structure */
  637. /************************************************************************/
  638. sessionId = m_pTSWd->sessionId;
  639. /************************************************************************/
  640. /* Calculate the size of the various bits of the TS_DEMAND_ACTIVE_PDU */
  641. /************************************************************************/
  642. pktLen = sizeof(TS_DEMAND_ACTIVE_PDU) - 1 + sizeof(UINT32);
  643. nameLen = strlen(scPartyArray[0].name);
  644. nameLen = (unsigned)DC_ROUND_UP_4(nameLen);
  645. pktLen += nameLen;
  646. pktLen += capsSize;
  647. /************************************************************************/
  648. // Get a buffer - this should not fail, so abort if it does
  649. // fWait is TRUE means that we will always wait for a buffer to be avail
  650. /************************************************************************/
  651. status = SM_AllocBuffer(scPSMHandle, (PPVOID)(&pPkt), pktLen, TRUE, FALSE);
  652. if ( STATUS_SUCCESS == status ) {
  653. // Calculate a new shareID.
  654. scGeneration++;
  655. scShareID = scUserID | (((UINT32)(scGeneration & 0xFFFF)) << 16);
  656. // Fill in the packet fields.
  657. pPkt->shareControlHeader.totalLength = (UINT16)pktLen;
  658. pPkt->shareControlHeader.pduType = TS_PDUTYPE_DEMANDACTIVEPDU |
  659. TS_PROTOCOL_VERSION;
  660. pPkt->shareControlHeader.pduSource = (UINT16)scUserID;
  661. pPkt->shareID = scShareID;
  662. pPkt->lengthSourceDescriptor = (UINT16)nameLen;
  663. pPkt->lengthCombinedCapabilities = (UINT16)capsSize;
  664. memcpy(&(pPkt->data[0]), scPartyArray[0].name, nameLen);
  665. memcpy(&(pPkt->data[nameLen]), caps, capsSize);
  666. memcpy(&(pPkt->data[nameLen+capsSize]),
  667. &sessionId,
  668. sizeof(sessionId));
  669. // Send it.
  670. rc = SM_SendData(scPSMHandle, pPkt, pktLen, TS_HIGHPRIORITY, 0,
  671. FALSE, RNS_SEC_ENCRYPT, FALSE);
  672. if (rc) {
  673. TRC_ALT((TB, "%s Stack sent TS_DEMAND_ACTIVE_PDU",
  674. m_pTSWd->StackClass == Stack_Primary ? "Primary" :
  675. (m_pTSWd->StackClass == Stack_Shadow ? "Shadow" :
  676. "PassThru")));
  677. }
  678. else {
  679. TRC_ERR((TB, "Failed to send TS_DEMAND_ACTIVE_PDU"));
  680. }
  681. }
  682. else {
  683. TRC_ERR((TB, "Failed to alloc %d bytes for TS_DEMAND_ACTIVE_PDU",
  684. pktLen));
  685. rc = FALSE;
  686. DC_QUIT;
  687. }
  688. /************************************************************************/
  689. /* Change SC state. */
  690. /************************************************************************/
  691. SC_SET_STATE(SCS_SHARE_STARTING)
  692. DC_EXIT_POINT:
  693. DC_END_FN();
  694. return rc;
  695. }
  696. /****************************************************************************/
  697. /* SC_SendServerCert */
  698. /* */
  699. /* Sends the target server's random + certificate to a client server for */
  700. /* use in shadowing. */
  701. /****************************************************************************/
  702. NTSTATUS RDPCALL SHCLASS SC_SendServerCert(PSHADOWCERT pCert, ULONG ulLength)
  703. {
  704. PTS_SERVER_CERTIFICATE_PDU pPkt;
  705. ULONG ulPktSize;
  706. NTSTATUS status;
  707. BOOL rc;
  708. DC_BEGIN_FN("SC_SendServerCert");
  709. ulPktSize = sizeof(TS_SERVER_CERTIFICATE_PDU) - 1 +
  710. pCert->shadowRandomLen + pCert->shadowCertLen;
  711. TRC_ERR((TB, "handle: %p, &pPkt: %p, size: %ld",
  712. m_pTSWd->pSmInfo, &pPkt, ulPktSize));
  713. status = SM_AllocBuffer(m_pTSWd->pSmInfo, (PPVOID) &pPkt, ulPktSize, TRUE, FALSE);
  714. if ( STATUS_SUCCESS == status ) {
  715. // Fill in the packet fields.
  716. pPkt->shareControlHeader.totalLength = (UINT16) ulPktSize;
  717. pPkt->shareControlHeader.pduType = TS_PDUTYPE_SERVERCERTIFICATEPDU |
  718. TS_PROTOCOL_VERSION;
  719. pPkt->shareControlHeader.pduSource = (UINT16) scUserID;
  720. pPkt->encryptionMethod = pCert->encryptionMethod;
  721. pPkt->encryptionLevel = pCert->encryptionLevel;
  722. pPkt->shadowRandomLen = pCert->shadowRandomLen;
  723. pPkt->shadowCertLen = pCert->shadowCertLen;
  724. // Copy over the random + cert
  725. if (pPkt->encryptionLevel != 0) {
  726. memcpy(pPkt->data, pCert->data,
  727. pCert->shadowRandomLen + pCert->shadowCertLen);
  728. }
  729. // Send ServerCertificatePDU
  730. rc = SM_SendData(m_pTSWd->pSmInfo, pPkt, ulPktSize, TS_HIGHPRIORITY,
  731. 0, FALSE, RNS_SEC_ENCRYPT, FALSE);
  732. if (rc) {
  733. status = STATUS_SUCCESS;
  734. TRC_ALT((TB, "Sent TS_SERVER_CERTIFICATE_PDU: %ld", ulPktSize));
  735. }
  736. else {
  737. status = STATUS_UNEXPECTED_IO_ERROR;
  738. TRC_ERR((TB, "Failed to send TS_SERVER_CERTIFICATE_PDU"));
  739. }
  740. }
  741. else {
  742. status = STATUS_NO_MEMORY;
  743. TRC_ERR((TB, "Failed to alloc %d bytes for TS_SERVER_CERTIFICATE_PDU",
  744. ulPktSize));
  745. }
  746. DC_END_FN();
  747. return status;
  748. }
  749. /****************************************************************************/
  750. /* SC_SaveServerCert */
  751. /* */
  752. /* Save the server certificate + random for subsequent validation by rdpwsx.*/
  753. /* A NULL pPkt indicates we should save an empty certificate. */
  754. /****************************************************************************/
  755. BOOL RDPCALL SHCLASS SC_SaveServerCert(PTS_SERVER_CERTIFICATE_PDU pPkt,
  756. ULONG ulLength)
  757. {
  758. PSHADOWCERT pCert;
  759. ULONG ulCertLen;
  760. DC_BEGIN_FN("SC_SaveServerCert");
  761. // Save off the data and signal rdpwsx that we got it. We will actually
  762. // perform the validation in user mode.
  763. if (pPkt != NULL) {
  764. ulCertLen = pPkt->shadowRandomLen + pPkt->shadowCertLen;
  765. pCert = (PSHADOWCERT) COM_Malloc(sizeof(SHADOWCERT) + ulCertLen - 1);
  766. if (pCert != NULL) {
  767. pCert->encryptionMethod = pPkt->encryptionMethod;
  768. pCert->encryptionLevel = pPkt->encryptionLevel;
  769. pCert->shadowRandomLen = pPkt->shadowRandomLen;
  770. pCert->shadowCertLen = pPkt->shadowCertLen;
  771. // If the encryption level is non-zero, then we should have a server random
  772. // and certificate following the initial header
  773. if (pCert->encryptionLevel != 0) {
  774. memcpy(pCert->data, pPkt->data, ulCertLen);
  775. }
  776. TRC_ALT((TB, "Received certificate[%ld], level=%ld, method=%lx, random[%ld]",
  777. pCert->shadowCertLen,
  778. pCert->encryptionLevel,
  779. pCert->encryptionMethod,
  780. pCert->shadowRandomLen));
  781. // Update SM parameters with negotiated values
  782. SM_SetEncryptionParams(m_pTSWd->pSmInfo, pCert->encryptionLevel,
  783. pCert->encryptionMethod);
  784. }
  785. else {
  786. TRC_ERR((TB, "Could not allocate space for server cert: %ld!",
  787. ulCertLen));
  788. }
  789. }
  790. // Else, the target server did not send back a certificate (B3)
  791. else {
  792. pCert = (PSHADOWCERT) COM_Malloc(sizeof(SHADOWCERT));
  793. if (pCert != NULL) {
  794. memset(pCert, 0, sizeof(SHADOWCERT));
  795. }
  796. else {
  797. TRC_ERR((TB, "Could not allocate space for server cert: %ld!",
  798. sizeof(SHADOWCERT)));
  799. }
  800. }
  801. // wake up the rdpwsx thread which is waiting on this information
  802. m_pTSWd->pShadowCert = pCert;
  803. KeSetEvent(m_pTSWd->pSecEvent, 0, FALSE);
  804. DC_END_FN();
  805. return TRUE;
  806. } /* SC_SaveServerCert */
  807. /****************************************************************************/
  808. /* SC_SendClientRandom */
  809. /* */
  810. /* Send the encrypted client random to the shadow target server. */
  811. /****************************************************************************/
  812. NTSTATUS RDPCALL SHCLASS SC_SendClientRandom(PBYTE pClientRandom,
  813. ULONG ulLength)
  814. {
  815. PTS_CLIENT_RANDOM_PDU pPkt;
  816. ULONG ulPktSize;
  817. NTSTATUS status;
  818. BOOL rc;
  819. DC_BEGIN_FN("SC_SendClientRandom");
  820. ulPktSize = sizeof(TS_CLIENT_RANDOM_PDU) - 1 + ulLength;
  821. status = NM_AllocBuffer(m_pTSWd->pNMInfo,
  822. (PPVOID) &pPkt, ulPktSize, TRUE);
  823. if (STATUS_SUCCESS == status) {
  824. // Fill in the packet fields.
  825. pPkt->shareControlHeader.totalLength = (UINT16) ulPktSize;
  826. pPkt->shareControlHeader.pduType = TS_PDUTYPE_CLIENTRANDOMPDU |
  827. TS_PROTOCOL_VERSION;
  828. pPkt->shareControlHeader.pduSource = (UINT16)scUserID;
  829. pPkt->clientRandomLen = ulLength;
  830. // Copy over the random
  831. TRC_ALT((TB, "PDUType: %lx, random length: %ld, pktSize: %ld",
  832. pPkt->shareControlHeader.pduType, ulLength, ulPktSize));
  833. memcpy(pPkt->data, pClientRandom, ulLength);
  834. TRC_DATA_DBG("snd random: ", pClientRandom, ulLength);
  835. rc = NM_SendData(m_pTSWd->pNMInfo,
  836. (PBYTE) pPkt, ulPktSize, TS_HIGHPRIORITY, 0, FALSE);
  837. if (rc) {
  838. status = STATUS_SUCCESS;
  839. TRC_ALT((TB, "Sent TS_CLIENT_RANDOM_PDU: %ld", ulPktSize));
  840. }
  841. else {
  842. status = STATUS_UNEXPECTED_IO_ERROR;
  843. TRC_ERR((TB, "Failed to send TS_CLIENT_RANDOM_PDU"));
  844. }
  845. }
  846. else {
  847. status = STATUS_NO_MEMORY;
  848. TRC_ERR((TB, "Failed to alloc %d bytes for TS_CLIENT_RANDOM_PDU",
  849. ulPktSize));
  850. }
  851. DC_END_FN();
  852. return status;
  853. }
  854. /****************************************************************************/
  855. /* SC_SaveClientRandom */
  856. /* */
  857. /* Save the encrypted client random for subsequent use by rdpwsx. */
  858. /****************************************************************************/
  859. BOOL RDPCALL SHCLASS SC_SaveClientRandom(PTS_CLIENT_RANDOM_PDU pPkt,
  860. ULONG ulLength)
  861. {
  862. PCLIENTRANDOM pClientRandom;
  863. BOOL rc = FALSE;
  864. DC_BEGIN_FN("SC_SaveClientRandom");
  865. //Validate data length
  866. if ((ulLength < sizeof(TS_CLIENT_RANDOM_PDU)) ||
  867. (ulLength + sizeof(TSUINT8) - sizeof(TS_CLIENT_RANDOM_PDU)) < pPkt->clientRandomLen) {
  868. TRC_ERR((TB, "Bad client random length: %ld", pPkt->clientRandomLen));
  869. return FALSE;
  870. }
  871. // The largest possible client random size is 512,
  872. // defined in SendClientRandom() in tsrvsec.c
  873. if (pPkt->clientRandomLen > CLIENT_RANDOM_MAX_SIZE) {
  874. TRC_ERR((TB, "Client random length is too large: %ld", pPkt->clientRandomLen));
  875. return FALSE;
  876. }
  877. // Save off the data and signal rdpwsx that we got it. We will actually
  878. // perform the decryption in user mode.
  879. pClientRandom = (PCLIENTRANDOM) COM_Malloc(sizeof(CLIENTRANDOM) - 1 +
  880. pPkt->clientRandomLen);
  881. if (pClientRandom != NULL) {
  882. pClientRandom->clientRandomLen = pPkt->clientRandomLen;
  883. memcpy(pClientRandom->data, pPkt->data, pPkt->clientRandomLen);
  884. TRC_ALT((TB, "Received encrypted client random: @%p, len=%ld",
  885. pClientRandom, pPkt->clientRandomLen));
  886. TRC_DATA_DBG("sav random: ", pClientRandom->data,
  887. pClientRandom->clientRandomLen);
  888. }
  889. else {
  890. TRC_ERR((TB, "Could not allocate space for client random: %ld!",
  891. pPkt->clientRandomLen));
  892. }
  893. // Free pShadowRandom in case it was allocated before
  894. if (NULL != m_pTSWd->pShadowRandom) {
  895. COM_Free(m_pTSWd->pShadowRandom);
  896. m_pTSWd->pShadowRandom = NULL;
  897. }
  898. // wake up the termsrv thread which is waiting on this information
  899. m_pTSWd->pShadowRandom = pClientRandom;
  900. KeSetEvent (m_pTSWd->pSecEvent, 0, FALSE);
  901. DC_END_FN();
  902. return TRUE;
  903. }
  904. /****************************************************************************/
  905. /* SC_GetSecurityData */
  906. /* */
  907. /* Wait for either a server certificate or a client random and return the */
  908. /* data to rdpwsx. */
  909. /****************************************************************************/
  910. NTSTATUS RDPCALL SHCLASS SC_GetSecurityData(PSD_IOCTL pSdIoctl)
  911. {
  912. PSECURITYTIMEOUT pSecurityTimeout = (PSECURITYTIMEOUT) pSdIoctl->InputBuffer;
  913. ULONG ulBytesNeeded = 0;
  914. NTSTATUS status;
  915. DC_BEGIN_FN("SC_GetSecurityData");
  916. // Wait for the connected indication from SC (if necessary)
  917. if (((pSdIoctl->IoControlCode == IOCTL_TSHARE_GET_CERT_DATA) &&
  918. (pSdIoctl->OutputBufferLength == 0)) ||
  919. (pSdIoctl->IoControlCode == IOCTL_TSHARE_GET_CLIENT_RANDOM)) {
  920. TRC_ALT((TB, "About to wait for %s data",
  921. pSdIoctl->IoControlCode == IOCTL_TSHARE_GET_CERT_DATA ?
  922. "Server Certificate" : "Client Random"));
  923. if (pSdIoctl->InputBufferLength == sizeof(SECURITYTIMEOUT)) {
  924. status = WDW_WaitForConnectionEvent(m_pTSWd, m_pTSWd->pSecEvent,
  925. pSecurityTimeout->ulTimeout);
  926. }
  927. else {
  928. status = STATUS_INVALID_PARAMETER;
  929. TRC_ERR((TB, "Bogus timeout value structure: Length [%ld] != Expected [%ld]",
  930. pSdIoctl->InputBufferLength, sizeof(SECURITYTIMEOUT)));
  931. DC_QUIT;
  932. }
  933. TRC_ALT((TB, "Back from wait for security data"));
  934. if (status != STATUS_SUCCESS) {
  935. TRC_ERR((TB, "Error waiting for security data: %lx, msec=%ld",
  936. status, pSecurityTimeout->ulTimeout));
  937. if (!NT_ERROR(status)) {
  938. status = STATUS_IO_TIMEOUT;
  939. }
  940. DC_QUIT;
  941. }
  942. }
  943. // Server certificate + random
  944. if (pSdIoctl->IoControlCode == IOCTL_TSHARE_GET_CERT_DATA) {
  945. if (m_pTSWd->pShadowCert != NULL) {
  946. ULONG ulCertLength = m_pTSWd->pShadowCert->shadowCertLen +
  947. m_pTSWd->pShadowCert->shadowRandomLen;
  948. ulBytesNeeded = sizeof(SHADOWCERT) - 1 + ulCertLength;
  949. // Return the length so rdpwsx can alloc the right amount of memory.
  950. if ((pSdIoctl->OutputBuffer == NULL) ||
  951. (pSdIoctl->OutputBufferLength < ulBytesNeeded)) {
  952. TRC_ALT((TB, "Cert[%ld] + Rand[%ld] buffer too small: %ld < %ld",
  953. m_pTSWd->pShadowCert->shadowCertLen,
  954. m_pTSWd->pShadowCert->shadowRandomLen,
  955. pSdIoctl->OutputBufferLength, ulBytesNeeded));
  956. status = STATUS_BUFFER_TOO_SMALL;
  957. }
  958. // else, return the data to rdpwsx
  959. else {
  960. PSHADOWCERT pShadowCertOut = (PSHADOWCERT) pSdIoctl->OutputBuffer;
  961. PSHADOWCERT pShadowCertIn = m_pTSWd->pShadowCert;
  962. pShadowCertOut->encryptionMethod = pShadowCertIn->encryptionMethod;
  963. pShadowCertOut->encryptionLevel = pShadowCertIn->encryptionLevel;
  964. pShadowCertOut->shadowRandomLen = pShadowCertIn->shadowRandomLen;
  965. pShadowCertOut->shadowCertLen = pShadowCertIn->shadowCertLen;
  966. memcpy(pShadowCertOut->data, pShadowCertIn->data, ulCertLength);
  967. // Free up the temporary buffer
  968. COM_Free(m_pTSWd->pShadowCert);
  969. m_pTSWd->pShadowCert = NULL;
  970. status = STATUS_SUCCESS;
  971. }
  972. }
  973. // We were unable to save the certificate!
  974. else {
  975. TRC_ERR((TB, "Saved certificate not found!"));
  976. status = STATUS_NO_MEMORY;
  977. }
  978. }
  979. // Encrypted client random
  980. else if (pSdIoctl->IoControlCode == IOCTL_TSHARE_GET_CLIENT_RANDOM) {
  981. if (m_pTSWd->pShadowRandom != NULL) {
  982. ulBytesNeeded = m_pTSWd->pShadowRandom->clientRandomLen;
  983. // Return the length so rdpwsx can alloc the right amount of memory.
  984. if ((pSdIoctl->OutputBuffer == NULL) ||
  985. (pSdIoctl->OutputBufferLength < ulBytesNeeded)) {
  986. status = STATUS_BUFFER_TOO_SMALL;
  987. TRC_ALT((TB, "Client random buffer too small: %ld < %ld",
  988. pSdIoctl->OutputBufferLength, ulBytesNeeded));
  989. }
  990. // else, return the data to rdpwsx
  991. else {
  992. PCLIENTRANDOM pRandomIn = m_pTSWd->pShadowRandom;
  993. PBYTE pRandomOut = (PBYTE) pSdIoctl->OutputBuffer;
  994. TRC_ALT((TB, "Received client random: @%p, len=%ld",
  995. pRandomIn, ulBytesNeeded));
  996. memcpy(pRandomOut, pRandomIn->data, ulBytesNeeded);
  997. TRC_DATA_DBG("rcv random: ", pRandomOut, ulBytesNeeded);
  998. // Free up the temporary buffer
  999. COM_Free(m_pTSWd->pShadowRandom);
  1000. m_pTSWd->pShadowRandom = NULL;
  1001. status = STATUS_SUCCESS;
  1002. }
  1003. }
  1004. // We were unable to save the encrypted random!
  1005. else {
  1006. TRC_ERR((TB, "Saved encrypted random not found!"));
  1007. status = STATUS_NO_MEMORY;
  1008. }
  1009. }
  1010. else {
  1011. TRC_ERR((TB, "Unrecognized ioctl: %lx", pSdIoctl->IoControlCode));
  1012. status = STATUS_INVALID_PARAMETER;
  1013. }
  1014. DC_EXIT_POINT:
  1015. pSdIoctl->BytesReturned = ulBytesNeeded;
  1016. DC_END_FN();
  1017. return status;
  1018. }
  1019. /****************************************************************************/
  1020. /* Name: SC_ShadowSyncShares */
  1021. /* */
  1022. /* See ascapi.h */
  1023. /****************************************************************************/
  1024. #ifdef DC_HICOLOR
  1025. BOOL RDPCALL SHCLASS SC_ShadowSyncShares(PTS_COMBINED_CAPABILITIES pCaps,
  1026. ULONG capsLen)
  1027. #else
  1028. BOOL RDPCALL SHCLASS SC_ShadowSyncShares(void)
  1029. #endif
  1030. {
  1031. BOOL rc = TRUE;
  1032. ShareClass *dcShare = (ShareClass *)m_pTSWd->dcShare;
  1033. DC_BEGIN_FN("SC_SyncShare");
  1034. TRC_ASSERT((dcShare != NULL), (TB, "NULL Share Class"));
  1035. #ifdef DC_HICOLOR
  1036. /************************************************************************/
  1037. /* if we're the primary or console, update the caps with those supplied */
  1038. /* for the shadower. It can only "lower" the capabilities, so there's */
  1039. /* no problem with setting up caps the target can't cope with */
  1040. /************************************************************************/
  1041. if ((m_pTSWd->StackClass == Stack_Primary) ||
  1042. (m_pTSWd->StackClass == Stack_Console))
  1043. {
  1044. BOOL acceptedArray[SC_NUM_PARTY_JOINING_FCTS];
  1045. TRC_ALT((TB, "Update caps for shadower"));
  1046. // Free the memory
  1047. if (cpcRemoteCombinedCaps[SC_SHADOW_PERSON_ID - 1] != NULL) {
  1048. COM_Free((PVOID)cpcRemoteCombinedCaps[SC_SHADOW_PERSON_ID - 1]);
  1049. cpcRemoteCombinedCaps[SC_SHADOW_PERSON_ID - 1] = NULL;
  1050. }
  1051. SCCallPartyJoiningShare(SC_SHADOW_PERSON_ID,
  1052. capsLen,
  1053. pCaps,
  1054. acceptedArray,
  1055. scNumberInShare);
  1056. /********************************************************************/
  1057. /* Now update the DD caps via the shared mem */
  1058. /********************************************************************/
  1059. DCS_TriggerUpdateShmCallback();
  1060. }
  1061. #endif
  1062. SCInitiateSync(TRUE);
  1063. TRC_ALT((TB, "Synchronized Shares"));
  1064. DC_END_FN();
  1065. return(rc);
  1066. } /* SC_ShadowSyncShares */
  1067. /****************************************************************************/
  1068. /* Name: SC_EndShare */
  1069. /* */
  1070. /* Ends a share */
  1071. /****************************************************************************/
  1072. void RDPCALL SHCLASS SC_EndShare(BOOLEAN bForce)
  1073. {
  1074. PTS_DEACTIVATE_ALL_PDU pPkt;
  1075. NTSTATUS status;
  1076. BOOL rc;
  1077. DC_BEGIN_FN("SC_EndShare");
  1078. // Due to the way a shadow hotkey terminates a session, we sometimes need
  1079. // to force sending of a deactivate all PDU. This is done explicitly
  1080. // instead of changing the state table so we don't effect normal connect
  1081. // processing.
  1082. if (!bForce) {
  1083. SC_CHECK_STATE(SCE_END_SHARE);
  1084. }
  1085. else {
  1086. TRC_ALT((TB, "Forcing deactivate all PDU"));
  1087. }
  1088. /************************************************************************/
  1089. // Get a buffer - this should not fail, so abort if it does
  1090. // fWait is TRUE means that we will always wait for a buffer to be avail
  1091. /************************************************************************/
  1092. status = SM_AllocBuffer(scPSMHandle, (PPVOID)(&pPkt),
  1093. sizeof(TS_DEACTIVATE_ALL_PDU), TRUE, FALSE);
  1094. if ( STATUS_SUCCESS == status ) {
  1095. // Fill in the packet fields.
  1096. pPkt->shareControlHeader.totalLength = sizeof(TS_DEACTIVATE_ALL_PDU);
  1097. pPkt->shareControlHeader.pduType = TS_PDUTYPE_DEACTIVATEALLPDU |
  1098. TS_PROTOCOL_VERSION;
  1099. pPkt->shareControlHeader.pduSource = (UINT16)scUserID;
  1100. pPkt->shareID = scShareID;
  1101. pPkt->lengthSourceDescriptor = 1;
  1102. pPkt->sourceDescriptor[0] = 0;
  1103. // Send DeactivateAllPDU.
  1104. rc = SM_SendData(scPSMHandle, pPkt, sizeof(TS_DEACTIVATE_ALL_PDU),
  1105. TS_HIGHPRIORITY, 0, FALSE, RNS_SEC_ENCRYPT, FALSE);
  1106. if (rc) {
  1107. TRC_ALT((TB, "Sent DeactivateAllPDU"));
  1108. SCEndShare();
  1109. }
  1110. else {
  1111. TRC_ERR((TB, "Failed to send TS_DEACTIVATE_ALL_PDU"));
  1112. }
  1113. }
  1114. else {
  1115. TRC_ERR((TB, "Failed to alloc %d bytes for TS_DEACTIVATE_ALL_PDU",
  1116. sizeof(PTS_DEACTIVATE_ALL_PDU)));
  1117. }
  1118. DC_EXIT_POINT:
  1119. DC_END_FN();
  1120. }
  1121. /****************************************************************************/
  1122. // SC_OnDisconnected
  1123. //
  1124. // Handles disconnection notification.
  1125. /****************************************************************************/
  1126. void RDPCALL SHCLASS SC_OnDisconnected(UINT32 userID)
  1127. {
  1128. DC_BEGIN_FN("SC_OnDisconnected");
  1129. if (scNumberInShare != 0) {
  1130. SC_CHECK_STATE(SCE_DETACH_USER);
  1131. TRC_NRM((TB, "User %u detached", userID));
  1132. // Do the real work...
  1133. SCEndShare();
  1134. }
  1135. else {
  1136. TRC_NRM((TB, "Share already ended: nothing more to do"));
  1137. }
  1138. DC_EXIT_POINT:
  1139. DC_END_FN();
  1140. } /* SC_OnDisconnected */
  1141. /****************************************************************************/
  1142. /* Name: SC_OnDataReceived */
  1143. /* */
  1144. /* Purpose: Callback from SM for data receive path. */
  1145. /* */
  1146. /* Params: netPersonID - MCS UserID of the data sender */
  1147. /* priority - MCS data priority the data was sent on */
  1148. /* pPkt - pointer to start of packet */
  1149. /****************************************************************************/
  1150. void RDPCALL ShareClass::SC_OnDataReceived(
  1151. PBYTE pPkt,
  1152. NETPERSONID netPersonID,
  1153. unsigned DataLength,
  1154. UINT32 priority)
  1155. {
  1156. UINT16 pduType, pduType2;
  1157. LOCALPERSONID localID;
  1158. BOOL pduOK = FALSE;
  1159. DC_BEGIN_FN("SC_OnDataReceived");
  1160. TRC_NRM((TB, "Data Received"));
  1161. if (DataLength >= sizeof(TS_SHARECONTROLHEADER)) {
  1162. pduType = (((PTS_SHARECONTROLHEADER)pPkt)->pduType) & TS_MASK_PDUTYPE;
  1163. TRC_NRM((TB, "[%u]SC packet type %u", netPersonID, pduType));
  1164. }
  1165. else {
  1166. TRC_ERR((TB,"Data len %u too small for share ctrl header",
  1167. DataLength));
  1168. goto ShortPDU;
  1169. }
  1170. if (pduType == TS_PDUTYPE_DATAPDU)
  1171. {
  1172. /********************************************************************/
  1173. /* Data PDU. This is critical path so decode inline. */
  1174. /********************************************************************/
  1175. if (DataLength >= sizeof(TS_SHAREDATAHEADER)) {
  1176. pduType2 = ((PTS_SHAREDATAHEADER)pPkt)->pduType2;
  1177. SC_CHECK_STATE(SCE_DATAPACKET);
  1178. pduOK = TRUE;
  1179. }
  1180. else {
  1181. TRC_ERR((TB,"Data len %u too small for share data header",
  1182. DataLength));
  1183. goto ShortPDU;
  1184. }
  1185. #ifdef DC_DEBUG
  1186. {
  1187. /****************************************************************/
  1188. /* Ok, this is ugly. I'm trying to trace the PDU name without */
  1189. /* - searching a table */
  1190. /* - implementing a sparse table */
  1191. /* - a huge if ... else if switch. */
  1192. /* If you don't like it or don't understand it, ask MF. Before */
  1193. /* you get too het up, bear in mind the #ifdef DC_DEBUG above. */
  1194. /****************************************************************/
  1195. unsigned pduIndex =
  1196. (pduType2 == TS_PDUTYPE2_UPDATE) ? 1 :
  1197. (pduType2 == TS_PDUTYPE2_FONT) ? 2 :
  1198. (pduType2 == TS_PDUTYPE2_CONTROL) ? 3 :
  1199. ((pduType2 >= TS_PDUTYPE2_WINDOWACTIVATION) &&
  1200. (pduType2 <= TS_PDUTYPE2_BITMAPCACHE_ERROR_PDU)) ?
  1201. pduType2 - 19 : 0;
  1202. TRC_NRM((TB, "DataPDU type %s (%u)", scPktName[pduIndex],
  1203. pduType2));
  1204. }
  1205. #endif
  1206. /********************************************************************/
  1207. /* First check for synchronize packets */
  1208. /********************************************************************/
  1209. if (pduType2 != TS_PDUTYPE2_SYNCHRONIZE) {
  1210. /****************************************************************/
  1211. /* Now check that this priority has been synchronized */
  1212. /****************************************************************/
  1213. localID = SC_NetworkIDToLocalID(netPersonID);
  1214. if (!scPartyArray[localID].sync[priority])
  1215. {
  1216. TRC_ALT((TB,
  1217. "[%d] {%d} Discarding packet on unsynched priority %d",
  1218. netPersonID, localID, priority));
  1219. DC_QUIT;
  1220. }
  1221. /****************************************************************/
  1222. /* All is well - pass the packet to its destination */
  1223. /****************************************************************/
  1224. switch (pduType2) {
  1225. case TS_PDUTYPE2_INPUT:
  1226. // Note that changes to this path should be examined
  1227. // in light of fast-path input (IM_DecodeFastPathInput).
  1228. IM_PlaybackEvents((PTS_INPUT_PDU)pPkt, DataLength);
  1229. break;
  1230. case TS_PDUTYPE2_CONTROL:
  1231. CA_ReceivedPacket((PTS_CONTROL_PDU)pPkt, DataLength,
  1232. localID);
  1233. break;
  1234. case TS_PDUTYPE2_FONTLIST:
  1235. USR_ProcessRemoteFonts((PTS_FONT_LIST_PDU)pPkt,
  1236. DataLength, localID);
  1237. break;
  1238. case TS_PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST:
  1239. // Persistent bitmap cache key list PDU.
  1240. SBC_HandlePersistentCacheList(
  1241. (TS_BITMAPCACHE_PERSISTENT_LIST *)pPkt, DataLength,
  1242. localID);
  1243. break;
  1244. case TS_PDUTYPE2_BITMAPCACHE_ERROR_PDU:
  1245. // For future support of bitmap error PDU
  1246. SBC_HandleBitmapCacheErrorPDU(
  1247. (TS_BITMAPCACHE_ERROR_PDU *)pPkt, DataLength,
  1248. localID);
  1249. break;
  1250. case TS_PDUTYPE2_OFFSCRCACHE_ERROR_PDU:
  1251. // offscreen cache error PDU
  1252. SBC_HandleOffscrCacheErrorPDU(
  1253. (TS_OFFSCRCACHE_ERROR_PDU *)pPkt, DataLength,
  1254. localID);
  1255. break;
  1256. #ifdef DRAW_NINEGRID
  1257. case TS_PDUTYPE2_DRAWNINEGRID_ERROR_PDU:
  1258. // drawninegrid error PDU
  1259. SBC_HandleDrawNineGridErrorPDU(
  1260. (TS_DRAWNINEGRID_ERROR_PDU *)pPkt, DataLength,
  1261. localID);
  1262. break;
  1263. #endif
  1264. #ifdef DRAW_GDIPLUS
  1265. case TS_PDUTYPE2_DRAWGDIPLUS_ERROR_PDU:
  1266. SBC_HandleDrawGdiplusErrorPDU(
  1267. (TS_DRAWGDIPLUS_ERROR_PDU *)pPkt, DataLength,
  1268. localID);
  1269. break;
  1270. #endif
  1271. case TS_PDUTYPE2_REFRESH_RECT:
  1272. WDW_InvalidateRect(m_pTSWd, (PTS_REFRESH_RECT_PDU)pPkt,
  1273. DataLength);
  1274. break;
  1275. case TS_PDUTYPE2_SUPPRESS_OUTPUT:
  1276. UP_ReceivedPacket((PTS_SUPPRESS_OUTPUT_PDU)pPkt,
  1277. DataLength, localID);
  1278. break;
  1279. case TS_PDUTYPE2_SHUTDOWN_REQUEST:
  1280. DCS_ReceivedShutdownRequestPDU((PTS_SHAREDATAHEADER)pPkt,
  1281. DataLength, localID);
  1282. break;
  1283. default:
  1284. /********************************************************/
  1285. /* Unknown pduType2 */
  1286. /********************************************************/
  1287. TRC_ERR((TB, "Unknown data packet %d", pduType2));
  1288. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  1289. Log_RDP_UnknownPDUType2,
  1290. (BYTE *)&pduType2,
  1291. sizeof(pduType2));
  1292. break;
  1293. }
  1294. }
  1295. else
  1296. {
  1297. TRC_NRM((TB, "Synchronize PDU"));
  1298. SCSynchronizePDU(netPersonID, priority,(PTS_SYNCHRONIZE_PDU)pPkt);
  1299. }
  1300. }
  1301. else
  1302. {
  1303. /********************************************************************/
  1304. /* Control PDU. Not critical so throw to handler. */
  1305. /********************************************************************/
  1306. TRC_DBG((TB, "Control PDU"));
  1307. SCReceivedControlPacket(netPersonID, priority, (PVOID)pPkt,
  1308. DataLength);
  1309. pduOK = TRUE;
  1310. }
  1311. DC_EXIT_POINT:
  1312. if (!pduOK)
  1313. {
  1314. /********************************************************************/
  1315. /* An out-of-sequence packet has been received. It's possible we */
  1316. /* might receive an input PDU just after we brought the share down, */
  1317. /* so don't kick off the client for that. */
  1318. /********************************************************************/
  1319. TRC_ERR((TB, "Out-of-sequence packet %hx/%hd received in state %d",
  1320. pduType, pduType2, scState));
  1321. if ((pduType == TS_PDUTYPE_DATAPDU) &&
  1322. (pduType2 == TS_PDUTYPE2_INPUT))
  1323. {
  1324. TRC_ERR((TB, "Not kicking client off: it was only an input PDU"));
  1325. }
  1326. else
  1327. {
  1328. /****************************************************************/
  1329. /* Disconnect the client. */
  1330. /****************************************************************/
  1331. wchar_t detailData[(sizeof(pduType) * 2) +
  1332. (sizeof(pduType2) * 2) +
  1333. (sizeof(scState) * 2) + 3];
  1334. TRC_ERR((TB, "Kicking client off"));
  1335. swprintf(detailData,
  1336. L"%hx %hx %x",
  1337. pduType,
  1338. pduType2,
  1339. scState);
  1340. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  1341. Log_RDP_DataPDUSequence,
  1342. (BYTE *)&detailData,
  1343. sizeof(detailData));
  1344. }
  1345. }
  1346. DC_END_FN();
  1347. return;
  1348. // Error handling.
  1349. ShortPDU:
  1350. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_ShareDataTooShort, pPkt, DataLength);
  1351. DC_END_FN();
  1352. } /* SC_OnDataReceived */
  1353. /****************************************************************************/
  1354. /* Name: SC_OnShadowDataReceived */
  1355. /* */
  1356. /* Purpose: Callback from SM for shadow data receive path. Main purpose */
  1357. /* is to scan for the shadow hotkey being pressed. */
  1358. /* */
  1359. /* Params: netPersonID - MCS UserID of the data sender */
  1360. /* priority - MCS data priority the data was sent on */
  1361. /* pPkt - pointer to start of packet */
  1362. /****************************************************************************/
  1363. void RDPCALL ShareClass::SC_OnShadowDataReceived(
  1364. PBYTE pPkt,
  1365. NETPERSONID netPersonID,
  1366. unsigned DataLength,
  1367. UINT32 priority)
  1368. {
  1369. UINT16 pduType, pduType2;
  1370. LOCALPERSONID localID;
  1371. BOOLEAN bShadowData = TRUE;
  1372. NTSTATUS status;
  1373. DC_BEGIN_FN("SC_OnShadowDataReceived");
  1374. TRC_NRM((TB, "Shadow data Received"));
  1375. // If this is the primary client stack, then process the data and figure out
  1376. // whether or not the PDU should be passed on to the target. Else this is
  1377. // a passthru stack and we should forward PDUs regardless.
  1378. // Note IM_DecodeFastPathInput() performs this logic for fast-path input.
  1379. if (m_pTSWd->StackClass == Stack_Primary) {
  1380. // check that we have enough data before we deref the pduType.
  1381. if (sizeof(TS_SHARECONTROLHEADER) > DataLength) {
  1382. TRC_ERR((TB,"The PDU is not long enough to contain the TS_SHARECONTROLHEADER %d",
  1383. DataLength));
  1384. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_ShadowDataTooShort,
  1385. (PBYTE)pPkt, DataLength);
  1386. DC_QUIT;
  1387. }
  1388. pduType = (((PTS_SHARECONTROLHEADER)pPkt)->pduType) & TS_MASK_PDUTYPE;
  1389. TRC_NRM((TB, "[%u]SC packet type %u", netPersonID, pduType));
  1390. if (pduType == TS_PDUTYPE_DATAPDU)
  1391. {
  1392. /********************************************************************/
  1393. /* Data PDU. This is critical path so decode inline. */
  1394. /********************************************************************/
  1395. if (sizeof(TS_SHAREDATAHEADER) > DataLength) {
  1396. TRC_ERR((TB,"The PDU is not long enough to contain the TS_SHAREDATAHEADER %d",
  1397. DataLength));
  1398. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_ShadowDataTooShort,
  1399. (PBYTE)pPkt, DataLength);
  1400. DC_QUIT;
  1401. }
  1402. pduType2 = ((PTS_SHAREDATAHEADER)pPkt)->pduType2;
  1403. #ifdef DC_DEBUG
  1404. {
  1405. /****************************************************************/
  1406. /* Ok, this is ugly. I'm trying to trace the PDU name without */
  1407. /* - searching a table */
  1408. /* - implementing a sparse table */
  1409. /* - a huge if ... else if switch. */
  1410. /* If you don't like it or don't understand it, ask MF. Before */
  1411. /* you get too het up, bear in mind the #ifdef DC_DEBUG above. */
  1412. /****************************************************************/
  1413. unsigned pduIndex =
  1414. (pduType2 == TS_PDUTYPE2_UPDATE) ? 1 :
  1415. (pduType2 == TS_PDUTYPE2_FONT) ? 2 :
  1416. (pduType2 == TS_PDUTYPE2_CONTROL) ? 3 :
  1417. ((pduType2 >= TS_PDUTYPE2_WINDOWACTIVATION) &&
  1418. (pduType2 <= TS_PDUTYPE2_BITMAPCACHE_ERROR_PDU)) ?
  1419. pduType2 - 19 : 0;
  1420. if (pduIndex != (TS_PDUTYPE2_INPUT - 19)) {
  1421. TRC_NRM((TB, "Shadow DataPDU type %s (%d)",
  1422. scPktName[pduIndex], pduType2));
  1423. }
  1424. }
  1425. #endif
  1426. /********************************************************************/
  1427. /* First check for synchronize packets */
  1428. /********************************************************************/
  1429. if (pduType2 != TS_PDUTYPE2_SYNCHRONIZE)
  1430. {
  1431. /****************************************************************/
  1432. /* Now check that this priority has been synchronized */
  1433. /****************************************************************/
  1434. localID = SC_NetworkIDToLocalID(netPersonID);
  1435. if (!scPartyArray[localID].sync[priority])
  1436. {
  1437. TRC_ALT((TB,
  1438. "[%d] {%d} Discarding packet on unsynched priority %d",
  1439. netPersonID, localID, priority));
  1440. DC_QUIT;
  1441. }
  1442. /****************************************************************/
  1443. /* All is well - pass the packet to its destination */
  1444. /****************************************************************/
  1445. switch (pduType2)
  1446. {
  1447. case TS_PDUTYPE2_INPUT:
  1448. {
  1449. // Note that changes to this path should be examined
  1450. // in light of fast-path input (IM_DecodeFastPathInput).
  1451. IM_PlaybackEvents((PTS_INPUT_PDU)pPkt, DataLength);
  1452. }
  1453. break;
  1454. case TS_PDUTYPE2_SUPPRESS_OUTPUT:
  1455. {
  1456. /********************************************************/
  1457. /* A SuppressOutputPDU. Don't process it as it would */
  1458. /* disable output for the shadow target as well! */
  1459. /********************************************************/
  1460. TRC_ALT((TB, "Not forwarding TS_PDUTYPE2_SUPPRESS_OUTPUT"));
  1461. bShadowData = FALSE;
  1462. }
  1463. break;
  1464. case TS_PDUTYPE2_SHUTDOWN_REQUEST:
  1465. {
  1466. /********************************************************/
  1467. /* A ShutdownRequestPDU. Process locally only. It */
  1468. /* should apply to the shadow client and not the target.*/
  1469. /********************************************************/
  1470. // this does not actually use the pPkt member and we
  1471. // have at lest TS_SHAREDATAHEADER left
  1472. DCS_ReceivedShutdownRequestPDU((PTS_SHAREDATAHEADER)pPkt,
  1473. DataLength, localID);
  1474. TRC_ALT((TB, "Not forwarding TS_PDUTYPE2_SHUTDOWN_REQUEST"));
  1475. bShadowData = FALSE;
  1476. }
  1477. break;
  1478. case TS_PDUTYPE2_FONTLIST:
  1479. {
  1480. if (sizeof(TS_FONT_LIST_PDU) - sizeof(TS_FONT_ATTRIBUTE)
  1481. > DataLength) {
  1482. TRC_ERR((TB,"The PDU is not long enough to contain the TS_FONT_LIST_PDU %d",
  1483. DataLength));
  1484. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_ShadowDataTooShort,
  1485. (PBYTE)pPkt, DataLength);
  1486. DC_QUIT;
  1487. }
  1488. PTS_FONT_LIST_PDU pFontListPDU = (PTS_FONT_LIST_PDU) pPkt;
  1489. /********************************************************/
  1490. /* NT5 server doesn't do anything with a font packet so */
  1491. /* send the smallest possible packet accross the pipe. */
  1492. /********************************************************/
  1493. DataLength = sizeof(TS_FONT_LIST_PDU) -
  1494. sizeof(TS_FONT_ATTRIBUTE);
  1495. pFontListPDU->shareDataHeader.shareControlHeader.totalLength =
  1496. (UINT16)DataLength;
  1497. pFontListPDU->shareDataHeader.generalCompressedType = 0;
  1498. pFontListPDU->shareDataHeader.generalCompressedLength = 0;
  1499. pFontListPDU->numberFonts = 0;
  1500. pFontListPDU->totalNumFonts = 0;
  1501. pFontListPDU->entrySize = sizeof(TS_FONT_ATTRIBUTE);
  1502. }
  1503. break;
  1504. // Forward all other PDUs until we learn otherwise!
  1505. default:
  1506. break;
  1507. }
  1508. }
  1509. else
  1510. {
  1511. // TODO: Why are we processing this?
  1512. TRC_ALT((TB, "Shadow Synchronize PDU"));
  1513. SCSynchronizePDU(netPersonID, priority,(PTS_SYNCHRONIZE_PDU)pPkt);
  1514. }
  1515. }
  1516. else {
  1517. /********************************************************************/
  1518. /* Need to watch for confirm actives so we can determine how to */
  1519. /* terminate the shadow session. */
  1520. /********************************************************************/
  1521. if (sizeof(TS_FLOW_PDU) > DataLength) {
  1522. TRC_ERR((TB,"The PDU is not long enough to contain the TS_SHAREDATAHEADER %d",
  1523. DataLength));
  1524. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_ShadowDataTooShort,
  1525. (PBYTE)pPkt, DataLength);
  1526. DC_QUIT;
  1527. }
  1528. if (((PTS_FLOW_PDU)pPkt)->flowMarker != TS_FLOW_MARKER)
  1529. {
  1530. // here we already checked that we have enough buffer
  1531. // for a TS_SHARECONTROLHEADER
  1532. pduType = ((PTS_SHARECONTROLHEADER)pPkt)->pduType & TS_MASK_PDUTYPE;
  1533. switch (pduType)
  1534. {
  1535. case TS_PDUTYPE_CONFIRMACTIVEPDU:
  1536. TRC_ALT((TB, "Shadow Client ConfirmActivePDU - shadow active!"));
  1537. m_pTSWd->bInShadowShare = TRUE;
  1538. break;
  1539. default:
  1540. break;
  1541. }
  1542. }
  1543. }
  1544. }
  1545. else if (m_pTSWd->StackClass == Stack_Passthru) {
  1546. // If we see a demand active and no server certificate has been received
  1547. // then wake up rdpwsx.
  1548. // check that we have enough data before we deref the flow marker
  1549. if (sizeof(TS_FLOW_PDU) > DataLength) {
  1550. TRC_ERR((TB,"The PDU is not long enough to contain the TS_FLOW_PDU %d",
  1551. DataLength));
  1552. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_ShadowDataTooShort,
  1553. (PBYTE)pPkt, DataLength);
  1554. DC_QUIT;
  1555. }
  1556. if (((PTS_FLOW_PDU)pPkt)->flowMarker != TS_FLOW_MARKER) {
  1557. // Check that we have enough data before we deref the
  1558. // TS_SHARECONTROLHEADER marker.
  1559. // As of today we know exaclty that we have enough buffer
  1560. // size sizeof(TS_FLOW_PDU) is grater then sizeof TS_SHARECONTROLHEADER.
  1561. if (sizeof(TS_SHARECONTROLHEADER) > DataLength) {
  1562. TRC_ERR((TB,"The PDU is not long enough to contain the TS_SHARECONTROLHEADER %d",
  1563. DataLength));
  1564. WDW_LogAndDisconnect(m_pTSWd, TRUE, Log_RDP_ShadowDataTooShort,
  1565. (PBYTE)pPkt, DataLength);
  1566. DC_QUIT;
  1567. }
  1568. pduType = ((PTS_SHARECONTROLHEADER)pPkt)->pduType & TS_MASK_PDUTYPE;
  1569. switch (pduType)
  1570. {
  1571. case TS_PDUTYPE_DEMANDACTIVEPDU:
  1572. TRC_ALT((TB, "Passthru stack - demand active!"));
  1573. SC_SaveServerCert(NULL, 0);
  1574. m_pTSWd->bInShadowShare = TRUE;
  1575. break;
  1576. case TS_PDUTYPE_SERVERCERTIFICATEPDU:
  1577. // check that we have enough data before we pass the
  1578. // TS_SERVER_CERTIFICATE_PDU marker.
  1579. if (sizeof(TS_SERVER_CERTIFICATE_PDU) > DataLength) {
  1580. TRC_ERR((TB,
  1581. "The PDU is not long enough to contain the TS_SERVER_CERTIFICATE_PDU %d",
  1582. DataLength));
  1583. WDW_LogAndDisconnect(m_pTSWd, TRUE,
  1584. Log_RDP_BadServerCertificateData,
  1585. (PBYTE)pPkt, DataLength);
  1586. DC_QUIT;
  1587. }
  1588. TRC_ALT((TB, "ServerCertificatePDU"));
  1589. SC_SaveServerCert((PTS_SERVER_CERTIFICATE_PDU) pPkt, DataLength);
  1590. bShadowData = FALSE;
  1591. break;
  1592. default:
  1593. break;
  1594. }
  1595. }
  1596. }
  1597. // Forward PDU to shadow if it's OK.
  1598. // Note IM_DecodeFastPathInput() performs this logic for fast-path input.
  1599. if (bShadowData) {
  1600. TRC_NRM((TB, "Forwarding shadow data: %ld", DataLength));
  1601. status = IcaRawInput(m_pTSWd->pContext,
  1602. NULL,
  1603. pPkt,
  1604. DataLength);
  1605. if (!NT_SUCCESS(status)) {
  1606. TRC_ERR((TB, "Failed shadow input data [%ld]: %x",
  1607. DataLength, status));
  1608. }
  1609. }
  1610. DC_EXIT_POINT:
  1611. DC_END_FN();
  1612. } /* SC_OnShadowDataReceived */
  1613. /****************************************************************************/
  1614. /* Name: SC_AllocBuffer */
  1615. /* */
  1616. /* Purpose: Allocate a send buffer */
  1617. /* */
  1618. /* Returns: TRUE - buffer allocated OK */
  1619. /* FALSE - failed to allocate buffer */
  1620. /* */
  1621. /* Params: ppPkt - (returned) pointer to allocated packet */
  1622. /* pktLen - length of packet required */
  1623. /* priority - priority on which buffer will be used */
  1624. /****************************************************************************/
  1625. NTSTATUS __fastcall SHCLASS SC_AllocBuffer(PPVOID ppPkt, UINT32 pktLen)
  1626. {
  1627. NTSTATUS status;
  1628. DC_BEGIN_FN("SC_AllocBuffer");
  1629. // fWait is TRUE means that we will always wait for a buffer to be avail
  1630. status = SM_AllocBuffer(scPSMHandle, ppPkt, pktLen, TRUE, FALSE);
  1631. DC_END_FN();
  1632. return(status);
  1633. } /* SC_AllocBuffer */
  1634. /****************************************************************************/
  1635. /* Name: SC_FreeBuffer */
  1636. /* */
  1637. /* Purpose: Free an unused send buffer */
  1638. /* */
  1639. /* Params: pPkt - pointer to buffer to free */
  1640. /* pktLen - size of the packet */
  1641. /* priority - priority buffer was allocated on */
  1642. /****************************************************************************/
  1643. void __fastcall SHCLASS SC_FreeBuffer(PVOID pPkt)
  1644. {
  1645. SM_FreeBuffer(scPSMHandle, pPkt, FALSE);
  1646. } /* SC_FreeBuffer */
  1647. /****************************************************************************/
  1648. /* Name: SC_SendData */
  1649. /* */
  1650. /* Purpose: Send a packet */
  1651. /* */
  1652. /* Returns: TRUE - packet sent OK */
  1653. /* FALSE - failed to send packet */
  1654. /* */
  1655. /* Params: pPkt - packet to send */
  1656. /* dataLen - length of packet */
  1657. /* pduLen - length of PDU : this will be used as the length */
  1658. /* of the packet if it is non-zero */
  1659. /* priority - priority (0 = all priorities) */
  1660. /* personID - person to send packet to (0 = all persons) */
  1661. /****************************************************************************/
  1662. BOOL RDPCALL ShareClass::SC_SendData(
  1663. PTS_SHAREDATAHEADER pPkt,
  1664. UINT32 dataLen,
  1665. UINT32 pduLen,
  1666. UINT32 priority,
  1667. NETPERSONID personID)
  1668. {
  1669. BOOL rc;
  1670. DC_BEGIN_FN("SC_SendData");
  1671. /************************************************************************/
  1672. /* Fill in the Share control and data header(s) if this is a single PDU */
  1673. /* */
  1674. /* Since we can send multiple PDUs per packet, the total length of data */
  1675. /* to send and the PDU length are not always the same. Where they are */
  1676. /* not, each PDU will have had its length (and compression) set up as */
  1677. /* it was assembled and we should not interfere here! */
  1678. /************************************************************************/
  1679. pPkt->shareControlHeader.pduType = TS_PDUTYPE_DATAPDU |
  1680. TS_PROTOCOL_VERSION;
  1681. pPkt->shareControlHeader.pduSource = (UINT16)scUserID;
  1682. if (pduLen != 0)
  1683. {
  1684. pPkt->shareControlHeader.totalLength = (UINT16)pduLen;
  1685. // Fill in the Share data header.
  1686. pPkt->shareID = scShareID;
  1687. pPkt->streamID = (BYTE)priority;
  1688. pPkt->uncompressedLength = (UINT16)pduLen;
  1689. pPkt->generalCompressedType = 0;
  1690. pPkt->generalCompressedLength = 0;
  1691. m_pTSWd->pProtocolStatus->Output.CompressedBytes += pduLen;
  1692. }
  1693. // Send with false for fast-path flag.
  1694. rc = SM_SendData(scPSMHandle, (PVOID)pPkt, dataLen, TS_HIGHPRIORITY, 0,
  1695. FALSE, RNS_SEC_ENCRYPT, FALSE);
  1696. if (!rc)
  1697. {
  1698. TRC_ERR((TB, "Failed to send %d bytes", dataLen));
  1699. }
  1700. DC_END_FN();
  1701. return(rc);
  1702. } /* SC_SendData */
  1703. /****************************************************************************/
  1704. /* SC_GetMyNetworkPersonID */
  1705. /* */
  1706. /* Returns the network person ID for this machine. */
  1707. /****************************************************************************/
  1708. NETPERSONID RDPCALL SHCLASS SC_GetMyNetworkPersonID(void)
  1709. {
  1710. NETPERSONID rc = 0;
  1711. DC_BEGIN_FN("SC_GetMyNetworkPersonID");
  1712. SC_CHECK_STATE(SCE_GETMYNETWORKPERSONID);
  1713. rc = scPartyArray[0].netPersonID;
  1714. DC_EXIT_POINT:
  1715. DC_END_FN();
  1716. return rc;
  1717. }
  1718. /****************************************************************************/
  1719. /* Name: SC_KeepAlive */
  1720. /* */
  1721. /* Purpose: KeepAlive packet send processing */
  1722. /* */
  1723. /* Returns: TRUE/FALSE */
  1724. /* */
  1725. /* Operation: Send a KeepAlive PDU if required */
  1726. /****************************************************************************/
  1727. BOOL RDPCALL SHCLASS SC_KeepAlive(void)
  1728. {
  1729. BOOL rc = FALSE;
  1730. PTS_FLOW_PDU pFlowTestPDU;
  1731. DC_BEGIN_FN("SC_KeepAlive");
  1732. TRC_NRM((TB, "Time for a KeepAlive PDU"));
  1733. if (scState == SCS_IN_SHARE) {
  1734. // only send the FlowTestPDU if we are in the share
  1735. // fWait is FALSE means that we will not wait for a buffer to be available
  1736. // If the buffer is full, that means there are packets waiting to be send out,
  1737. // so there is no need to send out keep alive packet anyway.
  1738. if ( STATUS_SUCCESS == SM_AllocBuffer(scPSMHandle, (PPVOID) (&pFlowTestPDU), sizeof(*pFlowTestPDU), FALSE, FALSE) ) {
  1739. pFlowTestPDU->flowMarker = TS_FLOW_MARKER;
  1740. pFlowTestPDU->pduType = TS_PDUTYPE_FLOWTESTPDU;
  1741. pFlowTestPDU->flowIdentifier = 0;
  1742. pFlowTestPDU->flowNumber = 0;
  1743. pFlowTestPDU->pduSource = (TSUINT16) scUserID;
  1744. if (SM_SendData(scPSMHandle, pFlowTestPDU, sizeof(*pFlowTestPDU),
  1745. 0, 0, FALSE, RNS_SEC_ENCRYPT, FALSE)) {
  1746. TRC_NRM((TB, "Sent a KeepAlive PDU to the client"));
  1747. rc = TRUE;
  1748. }
  1749. else {
  1750. TRC_ERR((TB, "Failed to send KeepAlive PDU"));
  1751. }
  1752. }
  1753. else {
  1754. TRC_ERR((TB, "Failed to alloc buffer for KeepAlive PDU"));
  1755. }
  1756. }
  1757. else {
  1758. TRC_ERR((TB, "In the wrong state: scState=%d, no KeepAlive PDU sent", scState));
  1759. }
  1760. DC_END_FN();
  1761. return rc;
  1762. } /* SC_KeepAlive */
  1763. /****************************************************************************/
  1764. /* Name: SC_RedrawScreen */
  1765. /* */
  1766. /* Purpose: Redraw the desktop upon request */
  1767. /****************************************************************************/
  1768. void RDPCALL SHCLASS SC_RedrawScreen(void)
  1769. {
  1770. NTSTATUS Status;
  1771. ICA_CHANNEL_COMMAND Cmd;
  1772. DC_BEGIN_FN("SC_RedrawScreen");
  1773. TRC_NRM((TB, "Call IcaChannelInput for screen redraw"));
  1774. // redraw the whole desktop
  1775. Cmd.Header.Command = ICA_COMMAND_REDRAW_RECTANGLE;
  1776. Cmd.RedrawRectangle.Rect.Left = 0;
  1777. Cmd.RedrawRectangle.Rect.Top = 0;
  1778. Cmd.RedrawRectangle.Rect.Right = (short) m_desktopWidth;
  1779. Cmd.RedrawRectangle.Rect.Bottom = (short) m_desktopHeight;
  1780. /************************************************************/
  1781. // Pass the filled in structure to ICADD.
  1782. /************************************************************/
  1783. Status = IcaChannelInput(m_pTSWd->pContext, Channel_Command, 0, NULL,
  1784. (unsigned char *) &Cmd, sizeof(ICA_CHANNEL_COMMAND));
  1785. if (Status == STATUS_SUCCESS) {
  1786. TRC_NRM((TB, "Issued IcaChannelInput for Screen Redraw"));
  1787. }
  1788. else {
  1789. TRC_ERR((TB, "Error issuing an IcaChannelInput, status=%lu", Status));
  1790. }
  1791. DC_END_FN();
  1792. }
  1793. /****************************************************************************/
  1794. /* SC_LocalIDToNetworkID() */
  1795. /* */
  1796. /* Converts a local person ID to the corresponding network person ID. */
  1797. /* */
  1798. /* PARAMETERS: */
  1799. /* */
  1800. /* localPersonID - a local person ID. This must be a valid local person */
  1801. /* ID. */
  1802. /* */
  1803. /* RETURNS: a network person ID. */
  1804. /****************************************************************************/
  1805. NETPERSONID RDPCALL SHCLASS SC_LocalIDToNetworkID(
  1806. LOCALPERSONID localPersonID)
  1807. {
  1808. DC_BEGIN_FN("SC_LocalIDToNetworkID");
  1809. SC_CHECK_STATE(SCE_LOCALIDTONETWORKID);
  1810. /************************************************************************/
  1811. /* Validate the localPersonID. */
  1812. /************************************************************************/
  1813. TRC_ASSERT( (SC_IsLocalPersonID(localPersonID)),
  1814. (TB,"Invalid {%d}", localPersonID) );
  1815. /************************************************************************/
  1816. /* Return this party's personID. */
  1817. /************************************************************************/
  1818. TRC_DBG((TB, "localID %u is network %hu", (unsigned)localPersonID,
  1819. scPartyArray[localPersonID].netPersonID));
  1820. DC_EXIT_POINT:
  1821. DC_END_FN();
  1822. return(scPartyArray[localPersonID].netPersonID);
  1823. }
  1824. /****************************************************************************/
  1825. /* SC_IsLocalPersonID() */
  1826. /* */
  1827. /* Validates a local person ID */
  1828. /* */
  1829. /* PARAMETERS */
  1830. /* */
  1831. /* localPersonID - the local person ID to validate */
  1832. /****************************************************************************/
  1833. BOOL RDPCALL SHCLASS SC_IsLocalPersonID(LOCALPERSONID localPersonID)
  1834. {
  1835. BOOL rc = FALSE;
  1836. DC_BEGIN_FN("SC_IsLocalPersonID");
  1837. SC_CHECK_STATE(SCE_ISLOCALPERSONID);
  1838. /************************************************************************/
  1839. /* Return TRUE if the localPersonID is valid, FALSE otherwise. */
  1840. /************************************************************************/
  1841. rc = ((localPersonID < SC_DEF_MAX_PARTIES) &&
  1842. (scPartyArray[localPersonID].netPersonID)) ? TRUE : FALSE;
  1843. DC_EXIT_POINT:
  1844. DC_END_FN();
  1845. return(rc);
  1846. }
  1847. /****************************************************************************/
  1848. /* SC_IsNetworkPersonID() */
  1849. /* */
  1850. /* Validates a network person ID */
  1851. /* */
  1852. /* PARAMETERS */
  1853. /* */
  1854. /* personID - the network person ID to validate */
  1855. /****************************************************************************/
  1856. BOOL RDPCALL SHCLASS SC_IsNetworkPersonID(NETPERSONID netPersonID)
  1857. {
  1858. LOCALPERSONID localPersonID;
  1859. BOOL rc = FALSE;
  1860. DC_BEGIN_FN("SC_IsNetworkPersonID");
  1861. SC_CHECK_STATE(SCE_ISNETWORKPERSONID);
  1862. /************************************************************************/
  1863. /* Check for a zero personID. */
  1864. /************************************************************************/
  1865. if (netPersonID == 0)
  1866. {
  1867. DC_QUIT;
  1868. }
  1869. /************************************************************************/
  1870. /* Search for the personID. */
  1871. /************************************************************************/
  1872. for ( localPersonID = 0;
  1873. localPersonID < SC_DEF_MAX_PARTIES;
  1874. localPersonID++ )
  1875. {
  1876. if (netPersonID == scPartyArray[localPersonID].netPersonID)
  1877. {
  1878. rc = TRUE;
  1879. DC_QUIT;
  1880. }
  1881. }
  1882. DC_EXIT_POINT:
  1883. DC_END_FN();
  1884. return(rc);
  1885. }
  1886. /****************************************************************************/
  1887. /* SC_SetCapabilities() */
  1888. /* */
  1889. /* Sets the SC's capabilities at start of day. */
  1890. /* This function is required because the SC is initialized before the CPC, */
  1891. /* so cannot register its capabilities in SC_Init(). */
  1892. /****************************************************************************/
  1893. void RDPCALL SHCLASS SC_SetCapabilities(void)
  1894. {
  1895. TS_SHARE_CAPABILITYSET caps;
  1896. DC_BEGIN_FN("SC_SetCapabilities");
  1897. /************************************************************************/
  1898. /* Register capabilities. */
  1899. /************************************************************************/
  1900. caps.capabilitySetType = TS_CAPSETTYPE_SHARE;
  1901. caps.nodeID = (TSUINT16)scUserID;
  1902. CPC_RegisterCapabilities((PTS_CAPABILITYHEADER)&caps,
  1903. sizeof(TS_SHARE_CAPABILITYSET));
  1904. DC_END_FN();
  1905. }
  1906. /****************************************************************************/
  1907. /* SC_SetCombinedCapabilities() */
  1908. /* */
  1909. /* Sets the share's combined capabilities to a predetermined set of values. */
  1910. /* This is used by shadow stacks so that the host's capabilities start with */
  1911. /* the value of the previous stack. */
  1912. /****************************************************************************/
  1913. void RDPCALL SHCLASS SC_SetCombinedCapabilities(UINT cbCapsSize,
  1914. PTS_COMBINED_CAPABILITIES pCaps)
  1915. {
  1916. DC_BEGIN_FN("SC_SetCombinedCapabilities");
  1917. /************************************************************************/
  1918. /* Initialize capabilities. */
  1919. /************************************************************************/
  1920. CPC_SetCombinedCapabilities(cbCapsSize, pCaps);
  1921. DC_END_FN();
  1922. }
  1923. /****************************************************************************/
  1924. /* SC_GetCombinedCapabilities() */
  1925. /* */
  1926. /* Used during initiation of a shadow to gather the currently active set of */
  1927. /* combined capabilities for the shadow client. These will be passed to */
  1928. /* the shadow target for negotiation. */
  1929. /****************************************************************************/
  1930. void RDPCALL SHCLASS SC_GetCombinedCapabilities(LOCALPERSONID localID,
  1931. PUINT pcbCapsSize,
  1932. PTS_COMBINED_CAPABILITIES *ppCaps)
  1933. {
  1934. DC_BEGIN_FN("SC_GetCombinedCapabilities");
  1935. /************************************************************************/
  1936. /* Initialize capabilities. */
  1937. /************************************************************************/
  1938. CPC_GetCombinedCapabilities(localID, pcbCapsSize, ppCaps);
  1939. DC_END_FN();
  1940. }
  1941. /****************************************************************************/
  1942. /* Name: SC_AddPartyToShare */
  1943. /* */
  1944. /* Purpose: Add another party to the share such that we get a new set of */
  1945. /* negotiated capabilities. This function is used when a new */
  1946. /* shadow connects. */
  1947. /* */
  1948. /* Returns: none */
  1949. /* */
  1950. /* Params: netPersonID - ID of sender of capabilities */
  1951. /* pCaps - new capabilities for person */
  1952. /* capsLength - length of capability sets */
  1953. /* */
  1954. /* Operation: see purpose */
  1955. /****************************************************************************/
  1956. NTSTATUS RDPCALL SHCLASS SC_AddPartyToShare(
  1957. NETPERSONID netPersonID,
  1958. PTS_COMBINED_CAPABILITIES pCaps,
  1959. unsigned capsLength)
  1960. {
  1961. LOCALPERSONID localPersonID;
  1962. BOOL acceptedArray[SC_NUM_PARTY_JOINING_FCTS];
  1963. NTSTATUS status = STATUS_SUCCESS;
  1964. PTS_GENERAL_CAPABILITYSET pGenCapSet;
  1965. unsigned MPPCCompressionLevel;
  1966. DC_BEGIN_FN("SC_AddPartyToShare");
  1967. /************************************************************************/
  1968. /* Reject this party if it will exceed the maximum number of parties */
  1969. /* allowed in a share. (Not required for RNS V1.0, but left in as it */
  1970. /* doesn't do any harm). */
  1971. /************************************************************************/
  1972. if (scNumberInShare == SC_DEF_MAX_PARTIES)
  1973. {
  1974. TRC_ERR((TB, "Reached max parties in share %d",
  1975. SC_DEF_MAX_PARTIES));
  1976. status = STATUS_DEVICE_BUSY;
  1977. DC_QUIT;
  1978. }
  1979. /************************************************************************/
  1980. /* Calculate a localPersonID for the remote party and store their */
  1981. /* details in the party array. */
  1982. /************************************************************************/
  1983. for ( localPersonID = 1;
  1984. localPersonID < SC_DEF_MAX_PARTIES;
  1985. localPersonID++ )
  1986. {
  1987. if (scPartyArray[localPersonID].netPersonID == 0)
  1988. {
  1989. /****************************************************************/
  1990. /* Found an empty slot. */
  1991. /****************************************************************/
  1992. TRC_NRM((TB, "Allocated local person ID %d", localPersonID));
  1993. break;
  1994. }
  1995. }
  1996. /************************************************************************/
  1997. /* Even though scNumberInShare is checked against SC_DEF_MAX_PARTIES */
  1998. /* above, the loop above might still not find an empty slot. */
  1999. /************************************************************************/
  2000. if (SC_DEF_MAX_PARTIES <= localPersonID)
  2001. {
  2002. TRC_ABORT((TB, "Couldn't find room to store local person"));
  2003. DC_QUIT;
  2004. }
  2005. /************************************************************************/
  2006. /* Store the new person's details */
  2007. /************************************************************************/
  2008. scPartyArray[localPersonID].netPersonID = netPersonID;
  2009. memcpy(scPartyArray[localPersonID].name, L"Shadow", sizeof(L"Shadow"));
  2010. memset(scPartyArray[localPersonID].sync,
  2011. 0,
  2012. sizeof(scPartyArray[localPersonID].sync));
  2013. TRC_NRM((TB, "{%d} person name %s",
  2014. (unsigned)localPersonID, scPartyArray[localPersonID].name));
  2015. /************************************************************************/
  2016. /* Call the XX_PartyJoiningShare() functions for the remote party. */
  2017. /************************************************************************/
  2018. if (!SCCallPartyJoiningShare(localPersonID,
  2019. capsLength,
  2020. (PVOID) pCaps,
  2021. acceptedArray,
  2022. scNumberInShare))
  2023. {
  2024. /********************************************************************/
  2025. /* Some component rejected the remote party. */
  2026. /********************************************************************/
  2027. TRC_ERR((TB, "Remote party rejected"));
  2028. SCCallPartyLeftShare(localPersonID,
  2029. acceptedArray,
  2030. scNumberInShare );
  2031. scPartyArray[localPersonID].netPersonID = 0;
  2032. status = STATUS_REVISION_MISMATCH;
  2033. DC_QUIT;
  2034. }
  2035. // For shadow connections, we must force fast-path output off to prevent
  2036. // any fast-path encoding from going across the cross-server pipe.
  2037. // This is to maintain backward compatibility with TS5 beta 3.
  2038. // Checking for m_pTSWd->shadowState in SCPartyJoiningShare() is not
  2039. // sufficient since SHADOW_TARGET is likely not to have been set yet.
  2040. // Note we have to update *all* precalculated header sizes, in SC and
  2041. // UP.
  2042. TRC_ALT((TB,"Forcing fast-path output off in shadow"));
  2043. scUseFastPathOutput = FALSE;
  2044. scUpdatePDUHeaderSpace = sizeof(TS_SHAREDATAHEADER);
  2045. UP_UpdateHeaderSize();
  2046. // Update the compression level.
  2047. // assume no compression
  2048. scUseShadowCompression = FALSE;
  2049. if (pCaps != NULL) {
  2050. pGenCapSet = (PTS_GENERAL_CAPABILITYSET) WDW_GetCapSet(
  2051. m_pTSWd, TS_CAPSETTYPE_GENERAL, pCaps, capsLength);
  2052. if (pGenCapSet != NULL) {
  2053. // update the compression capability
  2054. if (m_pTSWd->bCompress &&
  2055. (pGenCapSet->extraFlags & TS_SHADOW_COMPRESSION_LEVEL) &&
  2056. (m_pTSWd->pMPPCContext->ClientComprType == pGenCapSet->generalCompressionLevel)) {
  2057. MPPCCompressionLevel = m_pTSWd->pMPPCContext->ClientComprType;
  2058. scUseShadowCompression = TRUE;
  2059. }
  2060. }
  2061. }
  2062. if (scUseShadowCompression) {
  2063. // the compression history will be flushed
  2064. m_pTSWd->bFlushed = PACKET_FLUSHED;
  2065. // the compression will restart over
  2066. initsendcontext(m_pTSWd->pMPPCContext, MPPCCompressionLevel);
  2067. }
  2068. /************************************************************************/
  2069. /* The remote party is now in the share. */
  2070. /************************************************************************/
  2071. scNumberInShare++;
  2072. TRC_ALT((TB, "Number in share %d", (unsigned)scNumberInShare));
  2073. DC_EXIT_POINT:
  2074. DC_END_FN();
  2075. return status;
  2076. } /* SC_AddPartyToShare */
  2077. /****************************************************************************/
  2078. /* Name: SC_RemovePartyFromShare */
  2079. /* */
  2080. /* Purpose: Remove a party from the share such that we get a new set of */
  2081. /* negotiated capabilities. This function is used when a shadow */
  2082. /* disconnects from the share. */
  2083. /* */
  2084. /* Params: localID - ID of person to remove. */
  2085. /****************************************************************************/
  2086. NTSTATUS RDPCALL SHCLASS SC_RemovePartyFromShare(NETPERSONID netPersonID)
  2087. {
  2088. BOOL acceptedArray[SC_NUM_PARTY_JOINING_FCTS];
  2089. NTSTATUS status = STATUS_SUCCESS;
  2090. UINT i;
  2091. DC_BEGIN_FN("SC_RemovePartyFromShare");
  2092. // Map network ID to the corresponding local ID
  2093. for (i = SC_DEF_MAX_PARTIES - 1; i > 0; i--)
  2094. {
  2095. if (scPartyArray[i].netPersonID != netPersonID)
  2096. continue;
  2097. else
  2098. break;
  2099. }
  2100. // Call PLS for remote person
  2101. if (scPartyArray[i].netPersonID == netPersonID) {
  2102. memset(acceptedArray, TRUE, sizeof(acceptedArray));
  2103. TRC_ALT((TB, "Party %d left Share", i));
  2104. scNumberInShare--;
  2105. SCCallPartyLeftShare(i, acceptedArray, scNumberInShare);
  2106. scPartyArray[i].netPersonID = 0;
  2107. memset(&(scPartyArray[i]), 0, sizeof(*scPartyArray));
  2108. }
  2109. else {
  2110. status = STATUS_INVALID_PARAMETER;
  2111. TRC_ERR((TB, "Unable to find netID: %ld. Party not removed!",
  2112. netPersonID));
  2113. }
  2114. scUseShadowCompression = FALSE;
  2115. DC_END_FN();
  2116. return status;
  2117. }
  2118. /****************************************************************************/
  2119. /* SC_NetworkIDToLocalID() */
  2120. /* */
  2121. /* Converts a network person ID to the corresponding local person ID. */
  2122. /* */
  2123. /* PARAMETERS: */
  2124. /* personID - a network person ID. This must be a valid network person ID. */
  2125. /* */
  2126. /* RETURNS: a local person ID. */
  2127. /****************************************************************************/
  2128. LOCALPERSONID __fastcall SHCLASS SC_NetworkIDToLocalID(
  2129. NETPERSONID netPersonID)
  2130. {
  2131. LOCALPERSONID localID;
  2132. LOCALPERSONID rc = 0;
  2133. DC_BEGIN_FN("SC_NetworkIDToLocalID");
  2134. /************************************************************************/
  2135. /* Fastpath if same ID passed in as last time. */
  2136. /************************************************************************/
  2137. if (netPersonID == scLastNetID)
  2138. {
  2139. TRC_DBG((TB, "Same Network ID - return same local ID"));
  2140. DC_END_FN();
  2141. return(scLastLocID);
  2142. }
  2143. SC_CHECK_STATE(SCE_NETWORKIDTOLOCALID);
  2144. TRC_ASSERT((netPersonID), (TB, "Zero personID"));
  2145. /************************************************************************/
  2146. /* Search for the personID. */
  2147. /************************************************************************/
  2148. if (SC_ValidateNetworkID(netPersonID, &localID))
  2149. {
  2150. rc = localID;
  2151. DC_QUIT;
  2152. }
  2153. TRC_ABORT((TB, "Invalid [%u]", (unsigned)netPersonID));
  2154. DC_EXIT_POINT:
  2155. scLastNetID = netPersonID;
  2156. scLastLocID = rc;
  2157. DC_END_FN();
  2158. return(rc);
  2159. }
  2160. /****************************************************************************/
  2161. /* SC_ValidateNetworkID() */
  2162. /* */
  2163. /* Checks that a network ID is valid and returns the local ID corresponding */
  2164. /* to it if it is. */
  2165. /* */
  2166. /* PARAMETERS: */
  2167. /* netPersonID - a network person ID. */
  2168. /* pLocalPersonID - (returned) corresponding local ID if network ID valid */
  2169. /* (can pass NULL if you do not want local ID) */
  2170. /* */
  2171. /* RETURNS: */
  2172. /* TRUE - Network ID is valid FALSE - Network ID is not valid */
  2173. /****************************************************************************/
  2174. BOOL RDPCALL SHCLASS SC_ValidateNetworkID(NETPERSONID netPersonID,
  2175. LOCALPERSONID * pLocalID)
  2176. {
  2177. BOOL rc = FALSE;
  2178. LOCALPERSONID localID;
  2179. DC_BEGIN_FN("SC_ValidateNetworkID");
  2180. /************************************************************************/
  2181. /* Search for the personID. */
  2182. /************************************************************************/
  2183. for (localID = 0; localID < SC_DEF_MAX_PARTIES; localID++)
  2184. {
  2185. if (netPersonID == scPartyArray[localID].netPersonID)
  2186. {
  2187. /****************************************************************/
  2188. /* Found required person, set return values and quit */
  2189. /****************************************************************/
  2190. rc = TRUE;
  2191. if (pLocalID)
  2192. {
  2193. *pLocalID = localID;
  2194. }
  2195. break;
  2196. }
  2197. }
  2198. TRC_DBG((TB, "Network ID 0x%04u rc = 0x%04x (localID=%u)",
  2199. netPersonID,
  2200. rc,
  2201. localID));
  2202. DC_END_FN();
  2203. return(rc);
  2204. }
  2205. /****************************************************************************/
  2206. // SC_FlushAndAllocPackage
  2207. //
  2208. // Combines a forced network flush of the current package contents with
  2209. // an allocation of the standard package buffer size.
  2210. // Returns FALSE on allocation failure.
  2211. /****************************************************************************/
  2212. NTSTATUS __fastcall ShareClass::SC_FlushAndAllocPackage(PPDU_PACKAGE_INFO pPkgInfo)
  2213. {
  2214. NTSTATUS status = STATUS_SUCCESS;
  2215. DC_BEGIN_FN("SC_FlushAndAllocPackage");
  2216. if (pPkgInfo->cbLen) {
  2217. if (pPkgInfo->cbInUse) {
  2218. // Send the package contents.
  2219. if (scUseFastPathOutput)
  2220. // Send with fast-path flag.
  2221. SM_SendData(scPSMHandle, (PVOID)pPkgInfo->pOutBuf,
  2222. pPkgInfo->cbInUse, TS_HIGHPRIORITY, 0, TRUE, RNS_SEC_ENCRYPT, FALSE);
  2223. else
  2224. SC_SendData((PTS_SHAREDATAHEADER)pPkgInfo->pOutBuf,
  2225. pPkgInfo->cbInUse, 0, PROT_PRIO_MISC, 0);
  2226. }
  2227. else {
  2228. // or free the buffer if it's been allocated but not used.
  2229. TRC_NRM((TB, "Freeing unused package"));
  2230. SC_FreeBuffer(pPkgInfo->pOutBuf);
  2231. }
  2232. }
  2233. // We always allocate 8K (unless the bytes needed are greater) to reduce
  2234. // the number of buffers we allocate in the OutBuf pool. It is up to
  2235. // the package users to pack to wire packet sizes within this
  2236. // block.
  2237. status = SC_AllocBuffer(&(pPkgInfo->pOutBuf), sc8KOutBufUsableSpace);
  2238. if ( STATUS_SUCCESS == status ) {
  2239. // If compression is not enabled, then output directly into the
  2240. // OutBuf, else output into a temporary buffer.
  2241. if (!m_pTSWd->bCompress)
  2242. pPkgInfo->pBuffer = (BYTE *)pPkgInfo->pOutBuf;
  2243. else
  2244. pPkgInfo->pBuffer = m_pTSWd->pCompressBuffer;
  2245. pPkgInfo->cbLen = sc8KOutBufUsableSpace;
  2246. pPkgInfo->cbInUse = 0;
  2247. }
  2248. else {
  2249. pPkgInfo->cbLen = 0;
  2250. pPkgInfo->cbInUse = 0;
  2251. pPkgInfo->pBuffer = NULL;
  2252. TRC_NRM((TB, "could not allocate package buffer"));
  2253. }
  2254. DC_END_FN();
  2255. return status;
  2256. }
  2257. /****************************************************************************/
  2258. /* SC_GetSpaceInPackage */
  2259. /* */
  2260. /* Purpose: Ensure there's enough space in a PDU package for the data */
  2261. /* sending the existing package if necessary */
  2262. /* */
  2263. /* Returns: pointer to the space, or NULL if none available */
  2264. /* FALSE - no space available (alloc failed) */
  2265. /* */
  2266. /* Params: pPkgInfo - pointer to package info */
  2267. /* cbNeeded - space needed in package */
  2268. /****************************************************************************/
  2269. PBYTE __fastcall SHCLASS SC_GetSpaceInPackage(
  2270. PPDU_PACKAGE_INFO pPkgInfo,
  2271. unsigned cbNeeded)
  2272. {
  2273. PBYTE pSpace;
  2274. unsigned cbPackageSize;
  2275. NTSTATUS status = STATUS_SUCCESS;
  2276. unsigned RealAllocSize;
  2277. DC_BEGIN_FN("SC_GetSpaceInPackage");
  2278. // Handle the most common case where we have an allocated buffer and
  2279. // enough space.
  2280. if (pPkgInfo->cbLen) {
  2281. if (cbNeeded <= (pPkgInfo->cbLen - pPkgInfo->cbInUse))
  2282. goto EnoughSpace;
  2283. // We have a buffer allocated, but from the fast-path check above
  2284. // we know we don't have enough space. Send what we have.
  2285. if (pPkgInfo->cbInUse != 0) {
  2286. TRC_NRM((TB, "Not enough space - sending current package "
  2287. "of %u bytes", pPkgInfo->cbInUse));
  2288. if (scUseFastPathOutput)
  2289. // Send with fast-path flag.
  2290. SM_SendData(scPSMHandle, (PVOID)pPkgInfo->pOutBuf,
  2291. pPkgInfo->cbInUse, TS_HIGHPRIORITY, 0, TRUE, RNS_SEC_ENCRYPT, FALSE);
  2292. else
  2293. SC_SendData((PTS_SHAREDATAHEADER)pPkgInfo->pOutBuf,
  2294. pPkgInfo->cbInUse, 0, PROT_PRIO_MISC, 0);
  2295. }
  2296. else {
  2297. // or free the buffer if it's been allocated but not used.
  2298. TRC_NRM((TB, "Freeing unused package"));
  2299. SC_FreeBuffer(pPkgInfo->pOutBuf);
  2300. }
  2301. }
  2302. // We always allocate 8K (unless the bytes needed are greater) to reduce
  2303. // the number of buffers we allocate in the OutBuf pool. It is up to
  2304. // the package users to pack to wire packet sizes within this
  2305. // block.
  2306. cbPackageSize = max(cbNeeded, sc8KOutBufUsableSpace);
  2307. status = SC_AllocBuffer(&(pPkgInfo->pOutBuf), cbPackageSize);
  2308. if ( STATUS_SUCCESS == status ) {
  2309. // If compression is not enabled, then output directly into the
  2310. // OutBuf, else output into a temporary buffer.
  2311. if (!m_pTSWd->bCompress)
  2312. pPkgInfo->pBuffer = (BYTE *)pPkgInfo->pOutBuf;
  2313. else
  2314. pPkgInfo->pBuffer = m_pTSWd->pCompressBuffer;
  2315. pPkgInfo->cbLen = cbPackageSize;
  2316. pPkgInfo->cbInUse = 0;
  2317. }
  2318. else {
  2319. pPkgInfo->cbLen = 0;
  2320. pPkgInfo->cbInUse = 0;
  2321. pPkgInfo->pBuffer = NULL;
  2322. TRC_NRM((TB, "could not allocate package buffer"));
  2323. pSpace = NULL;
  2324. DC_QUIT;
  2325. }
  2326. EnoughSpace:
  2327. pSpace = pPkgInfo->pBuffer + pPkgInfo->cbInUse;
  2328. DC_EXIT_POINT:
  2329. DC_END_FN();
  2330. return pSpace;
  2331. } /* SC_GetSpaceInPackage */
  2332. /****************************************************************************/
  2333. /* SC_AddToPackage */
  2334. /* */
  2335. /* Purpose: Add the bytes to the PDU package - fills in the per-pdu info */
  2336. /* */
  2337. /* Params: pPkgInfo - pointer to package info */
  2338. /* cbLen - Length of data to add */
  2339. /* bShadow - whether or not the data should be shadowed */
  2340. /****************************************************************************/
  2341. void RDPCALL SHCLASS SC_AddToPackage(
  2342. PPDU_PACKAGE_INFO pPkgInfo,
  2343. unsigned cbLen,
  2344. BOOL bShadow)
  2345. {
  2346. BYTE *pPktHdr;
  2347. UCHAR compressResult;
  2348. ULONG CompressedSize;
  2349. DC_BEGIN_FN("SC_AddToPackage");
  2350. pPktHdr = pPkgInfo->pBuffer + pPkgInfo->cbInUse;
  2351. // CompressedSize is the size of the data minus headers.
  2352. CompressedSize = cbLen - scUpdatePDUHeaderSpace;
  2353. compressResult = 0;
  2354. if (m_pTSWd->bCompress) {
  2355. UCHAR *pSrcBuf = pPktHdr + scUpdatePDUHeaderSpace;
  2356. // Compress or copy the data into the OutBuf.
  2357. if ((cbLen > WD_MIN_COMPRESS_INPUT_BUF) &&
  2358. (cbLen < MAX_COMPRESS_INPUT_BUF) &&
  2359. ((m_pTSWd->shadowState == SHADOW_NONE) || scUseShadowCompression)) {
  2360. // Copy the header over to the OutBuf
  2361. memcpy((BYTE *)pPkgInfo->pOutBuf + pPkgInfo->cbInUse, pPktHdr,
  2362. scUpdatePDUHeaderSpace);
  2363. pPktHdr = (BYTE *)pPkgInfo->pOutBuf + pPkgInfo->cbInUse;
  2364. // Attempt to compress the PDU body directly into the OutBuf
  2365. compressResult = compress(pSrcBuf,
  2366. pPktHdr + scUpdatePDUHeaderSpace,
  2367. &CompressedSize, m_pTSWd->pMPPCContext);
  2368. if (compressResult & PACKET_COMPRESSED) {
  2369. unsigned CompEst;
  2370. // Successful compression - update the compression ratio.
  2371. TRC_ASSERT(((cbLen - scUpdatePDUHeaderSpace) >=
  2372. CompressedSize),
  2373. (TB,"Compression created larger size than uncompr"));
  2374. scMPPCUncompTotal += cbLen - scUpdatePDUHeaderSpace;
  2375. scMPPCCompTotal += CompressedSize;
  2376. if (scMPPCUncompTotal >= SC_SAMPLE_SIZE) {
  2377. // Compression estimate is average # of bytes that
  2378. // SCH_UNCOMP_BYTES bytes of uncomp data compress to.
  2379. CompEst = SCH_UNCOMP_BYTES * scMPPCCompTotal /
  2380. scMPPCUncompTotal;
  2381. TRC_ASSERT((CompEst <= SCH_UNCOMP_BYTES),
  2382. (TB,"MPPC compression estimate above 1.0 (%u)",
  2383. CompEst));
  2384. scMPPCCompTotal = 0;
  2385. scMPPCUncompTotal = 0;
  2386. if (CompEst < SCH_COMP_LIMIT)
  2387. CompEst = SCH_COMP_LIMIT;
  2388. m_pShm->sch.MPPCCompressionEst = CompEst;
  2389. TRC_NRM((TB, "New MPPC compr estimate %u", CompEst));
  2390. }
  2391. compressResult |= m_pTSWd->bFlushed;
  2392. m_pTSWd->bFlushed = 0;
  2393. }
  2394. else if (compressResult & PACKET_FLUSHED) {
  2395. // Overran compression history, copy over the original
  2396. // uncompressed buffer.
  2397. m_pTSWd->bFlushed = PACKET_FLUSHED;
  2398. memcpy(pPktHdr + scUpdatePDUHeaderSpace, pSrcBuf,
  2399. cbLen - scUpdatePDUHeaderSpace);
  2400. m_pTSWd->pProtocolStatus->Output.CompressFlushes++;
  2401. }
  2402. else {
  2403. TRC_ALT((TB, "Compression FAILURE"));
  2404. }
  2405. }
  2406. else {
  2407. // This packet is too small or too big, copy over the header and
  2408. // uncompressed data.
  2409. memcpy((UCHAR *)pPkgInfo->pOutBuf + pPkgInfo->cbInUse,
  2410. pPktHdr, cbLen);
  2411. pPktHdr = (UCHAR *)pPkgInfo->pOutBuf + pPkgInfo->cbInUse;
  2412. }
  2413. }
  2414. // Fill in the header based on whether we're using fast-path.
  2415. if (scUseFastPathOutput) {
  2416. if (m_pTSWd->bCompress) {
  2417. // Set up compression flags if we're compressing, whether
  2418. // or not the compression succeeded above.
  2419. pPktHdr[1] = compressResult;
  2420. // Size is the size of the payload after this header.
  2421. *((PUINT16_UA)(pPktHdr + 2)) = (UINT16)CompressedSize;
  2422. }
  2423. else {
  2424. // Size is the size of the payload after this header.
  2425. *((PUINT16_UA)(pPktHdr + 1)) = (UINT16)CompressedSize;
  2426. }
  2427. }
  2428. else {
  2429. TS_SHAREDATAHEADER UNALIGNED *pHdr;
  2430. pHdr = (TS_SHAREDATAHEADER UNALIGNED *)pPktHdr;
  2431. // Fill in the Share control header.
  2432. pHdr->shareControlHeader.totalLength = (TSUINT16)
  2433. (CompressedSize + scUpdatePDUHeaderSpace);
  2434. pHdr->shareControlHeader.pduType = TS_PDUTYPE_DATAPDU |
  2435. TS_PROTOCOL_VERSION;
  2436. pHdr->shareControlHeader.pduSource = (TSUINT16)scUserID;
  2437. // Fill in the Share data header.
  2438. pHdr->shareID = scShareID;
  2439. pHdr->streamID = PROT_PRIO_MISC;
  2440. pHdr->uncompressedLength = (UINT16)cbLen;
  2441. pHdr->generalCompressedType = (compressResult | m_pTSWd->bFlushed);
  2442. pHdr->generalCompressedLength = (TSUINT16)(m_pTSWd->bCompress ?
  2443. CompressedSize + scUpdatePDUHeaderSpace : 0);
  2444. }
  2445. // Advance the usage size past the header and compressed or
  2446. // uncompressed data.
  2447. pPkgInfo->cbInUse += CompressedSize + scUpdatePDUHeaderSpace;
  2448. TRC_ASSERT((pPkgInfo->cbInUse <= pPkgInfo->cbLen),
  2449. (TB,"Overflowed package!"));
  2450. m_pTSWd->pProtocolStatus->Output.CompressedBytes += CompressedSize +
  2451. scUpdatePDUHeaderSpace;
  2452. #ifdef DC_HICOLOR
  2453. // If shadowing, we need to save this data so that the shadow stack can
  2454. // duplicate it.
  2455. if ((m_pTSWd->shadowState == SHADOW_TARGET) && bShadow)
  2456. {
  2457. if (m_pTSWd->pShadowInfo)
  2458. {
  2459. ULONG dataSize = CompressedSize +
  2460. scUpdatePDUHeaderSpace + sizeof(SHADOW_INFO) - 1;
  2461. // If we've not started on the extra space, see if this will fit
  2462. // in the main space
  2463. if ((m_pTSWd->pShadowInfo->messageSizeEx == 0) &&
  2464. (m_pTSWd->pShadowInfo->messageSize + dataSize)
  2465. <= WD_MAX_SHADOW_BUFFER)
  2466. {
  2467. memcpy(&m_pTSWd->pShadowInfo->data[m_pTSWd->pShadowInfo->messageSize],
  2468. pPktHdr,
  2469. CompressedSize + scUpdatePDUHeaderSpace);
  2470. TRC_NRM((TB, "Saving shadow data buffer[%ld] += %ld",
  2471. m_pTSWd->pShadowInfo->messageSize,
  2472. CompressedSize + scUpdatePDUHeaderSpace));
  2473. m_pTSWd->pShadowInfo->messageSize += CompressedSize +
  2474. scUpdatePDUHeaderSpace;
  2475. }
  2476. // Nope - will it fit in the extra buffer?
  2477. else if ((m_pTSWd->pShadowInfo->messageSizeEx + dataSize)
  2478. <= WD_MAX_SHADOW_BUFFER)
  2479. {
  2480. TRC_ALT((TB, "Using extra shadow space..."));
  2481. memcpy(&m_pTSWd->pShadowInfo->data[WD_MAX_SHADOW_BUFFER
  2482. + m_pTSWd->pShadowInfo->messageSizeEx],
  2483. pPktHdr,
  2484. CompressedSize + scUpdatePDUHeaderSpace);
  2485. TRC_NRM((TB, "Saving shadow data bufferEx[%ld] += %ld",
  2486. m_pTSWd->pShadowInfo->messageSizeEx,
  2487. CompressedSize + scUpdatePDUHeaderSpace));
  2488. m_pTSWd->pShadowInfo->messageSizeEx += CompressedSize +
  2489. scUpdatePDUHeaderSpace;
  2490. }
  2491. else
  2492. {
  2493. TRC_ERR((TB, "Shadow buffer too small: %p[%ld/%ld] + %ld = %ld/%ld",
  2494. m_pTSWd->pShadowInfo->data,
  2495. m_pTSWd->pShadowInfo->messageSizeEx,
  2496. m_pTSWd->pShadowInfo->messageSize,
  2497. CompressedSize + scUpdatePDUHeaderSpace,
  2498. m_pTSWd->pShadowInfo->messageSize + cbLen,
  2499. m_pTSWd->pShadowInfo->messageSizeEx + cbLen));
  2500. }
  2501. }
  2502. }
  2503. #else
  2504. // If shadowing, we need to save this data so that the shadow stack can
  2505. // duplicate it.
  2506. if ((m_pTSWd->shadowState == SHADOW_TARGET) && bShadow) {
  2507. if (m_pTSWd->pShadowInfo &&
  2508. ((m_pTSWd->pShadowInfo->messageSize + cbLen +
  2509. sizeof(SHADOW_INFO) - 1) <= WD_MAX_SHADOW_BUFFER)) {
  2510. memcpy(&m_pTSWd->pShadowInfo->data[m_pTSWd->pShadowInfo->messageSize],
  2511. pPktHdr, CompressedSize + scUpdatePDUHeaderSpace);
  2512. m_pTSWd->pShadowInfo->messageSize += CompressedSize +
  2513. scUpdatePDUHeaderSpace;
  2514. TRC_NRM((TB, "Saving shadow data buffer[%ld] += %ld",
  2515. m_pTSWd->pShadowInfo->messageSize - CompressedSize -
  2516. scUpdatePDUHeaderSpace,
  2517. CompressedSize + scUpdatePDUHeaderSpace));
  2518. }
  2519. else {
  2520. TRC_ERR((TB, "Shadow buffer too small: %p[%ld] + %ld = %ld",
  2521. m_pTSWd->pShadowInfo->data,
  2522. m_pTSWd->pShadowInfo->messageSize,
  2523. CompressedSize + scUpdatePDUHeaderSpace,
  2524. m_pTSWd->pShadowInfo->messageSize + cbLen));
  2525. }
  2526. }
  2527. #endif
  2528. DC_END_FN();
  2529. } /* SC_AddToPackage */
  2530. /****************************************************************************/
  2531. /* SC_FlushPackage */
  2532. /* */
  2533. /* Purpose: Send any remaining data, or free the buffer if allocated */
  2534. /* */
  2535. /* Params: pPkgInfo - pointer to package info */
  2536. /****************************************************************************/
  2537. void RDPCALL SHCLASS SC_FlushPackage(PPDU_PACKAGE_INFO pPkgInfo)
  2538. {
  2539. DC_BEGIN_FN("SC_FlushPackage");
  2540. /************************************************************************/
  2541. /* If there's anything there, send it */
  2542. /************************************************************************/
  2543. if (pPkgInfo->cbInUse > 0) {
  2544. // Send the package contents.
  2545. if (scUseFastPathOutput)
  2546. // Send directly to SM with fast-path flag.
  2547. SM_SendData(scPSMHandle, (PVOID)pPkgInfo->pOutBuf,
  2548. pPkgInfo->cbInUse, TS_HIGHPRIORITY, 0, TRUE, RNS_SEC_ENCRYPT, FALSE);
  2549. else
  2550. SC_SendData((PTS_SHAREDATAHEADER)pPkgInfo->pOutBuf,
  2551. pPkgInfo->cbInUse, 0, PROT_PRIO_MISC, 0);
  2552. }
  2553. /************************************************************************/
  2554. /* If there's nothing in use but a buffer has been allocated, then free */
  2555. /* it */
  2556. /************************************************************************/
  2557. else if ((pPkgInfo->cbLen != 0) && (pPkgInfo->pBuffer != NULL))
  2558. SC_FreeBuffer(pPkgInfo->pOutBuf);
  2559. // Reset the package info.
  2560. pPkgInfo->cbLen = 0;
  2561. pPkgInfo->cbInUse = 0;
  2562. pPkgInfo->pBuffer = NULL;
  2563. pPkgInfo->pOutBuf = NULL;
  2564. DC_END_FN();
  2565. }
  2566. /****************************************************************************/
  2567. /* Name: SC_UpdateShm */
  2568. /* */
  2569. /* Purpose: Update the Shm data with sc data */
  2570. /****************************************************************************/
  2571. void RDPCALL SHCLASS SC_UpdateShm(void)
  2572. {
  2573. DC_BEGIN_FN("SC_UpdateShm");
  2574. m_pShm->bc.noBitmapCompressionHdr = scNoBitmapCompressionHdr;
  2575. DC_END_FN();
  2576. }
  2577. //
  2578. // Accessor for scUseAutoReconnect
  2579. // returns TRUE if we can autoreconnect
  2580. //
  2581. BOOL RDPCALL SHCLASS SC_IsAutoReconnectEnabled()
  2582. {
  2583. DC_BEGIN_FN("SC_IsAutoReconnectEnabled");
  2584. DC_END_FN();
  2585. return scUseAutoReconnect;
  2586. }