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.

3747 lines
150 KiB

  1. /****************************************************************************/
  2. // nwdwcpp.cpp
  3. //
  4. // WDW internal functions.
  5. //
  6. // Copyright (C) 1997-2000 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <precomp.h>
  9. #pragma hdrstop
  10. #define pTRCWd pTSWd
  11. #define TRC_FILE "nwdwcpp"
  12. #include <as_conf.hpp>
  13. extern "C" {
  14. #include <nwdwint.h>
  15. #include <asmint.h>
  16. #include <asmapi.h>
  17. #include <ntverp.h>
  18. }
  19. #include "slicense.h"
  20. #include <anmapi.h>
  21. #include <mcsioctl.h>
  22. #include "domain.h"
  23. //Client side error reporting
  24. #include "tserrs.h"
  25. #ifdef DC_DEBUG
  26. extern "C" {
  27. VOID IcaBreakOnDebugger( );
  28. }
  29. #endif
  30. extern "C" {
  31. /****************************************************************************/
  32. /* Data returned on IOCTL_VIDEO_QUERY_CURRENT_MODE */
  33. /* */
  34. /* This code unashamedly filched from Remotedd code developed for */
  35. /* NetMeeting. */
  36. /****************************************************************************/
  37. const VIDEO_MODE_INFORMATION wdSimModes[] =
  38. {
  39. sizeof(VIDEO_MODE_INFORMATION), /* length */
  40. 0, /* Mode index */
  41. /************************************************************************/
  42. /* VisScreenWidth and VisScreenHeight can be in two forms: */
  43. /* - 0xaaaabbbb - range of values supported (aaaa = max, bbbb = min) */
  44. /* - 0x0000aaaa - single value supported */
  45. /* For example: */
  46. /* - 0x07d0012c = 2000-300 */
  47. /* - 0x0640012c = 1600-300 */
  48. /* - 0x04b000c8 = 1200-200 */
  49. /* */
  50. /* @@@MF For now, support 800x600 only */
  51. /************************************************************************/
  52. 0x00000320, /* VisScreenWidth */
  53. 0x00000258, /* VisScrenHeight */
  54. 0x00000320, /* ScreenStride (0xffff0000 = any) */
  55. 0x00000001, /* NumberOfPlanes */
  56. 0x00000008, /* BitsPerPlane */
  57. 0, /* Frequency */
  58. 0, /* XMillimeter */
  59. 0, /* YMillimeter */
  60. 0, /* NumberRedBits */
  61. 0, /* NumberGreenBits */
  62. 0, /* NumberBlueBits */
  63. 0x00000000, /* RedMask */
  64. 0x00000000, /* GreenMask */
  65. 0x00000000, /* BlueMask */
  66. VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS,
  67. /* AttributeFlags */
  68. 0x00000320, /* VideoMemoryBitmapWidth */
  69. 0x00000258, /* VideoMemoryBitmapHeight */
  70. 0 /* DriverSpecificAttributeFlags */
  71. };
  72. #ifdef DC_DEBUG
  73. /****************************************************************************/
  74. /* IOCtl descriptions (debug build only) */
  75. /****************************************************************************/
  76. const char *wdIoctlA[] =
  77. {
  78. "IOCTL_ICA_SET_TRACE",
  79. "IOCTL_ICA_TRACE",
  80. "IOCTL_ICA_SET_SYSTEM_TRACE",
  81. "IOCTL_ICA_SYSTEM_TRACE",
  82. "IOCTL_ICA_UNBIND_VIRTUAL_CHANNEL",
  83. "Unknown",
  84. "Unknown",
  85. "Unknown",
  86. "Unknown",
  87. "Unknown",
  88. "IOCTL_ICA_STACK_PUSH",
  89. "IOCTL_ICA_STACK_POP",
  90. "IOCTL_ICA_STACK_CREATE_ENDPOINT",
  91. "IOCTL_ICA_STACK_CD_CREATE_ENDPOINT",
  92. "IOCTL_ICA_STACK_OPEN_ENDPOINT",
  93. "IOCTL_ICA_STACK_CLOSE_ENDPOINT",
  94. "IOCTL_ICA_STACK_ENABLE_DRIVER",
  95. "IOCTL_ICA_STACK_CONNECTION_WAIT",
  96. "IOCTL_ICA_STACK_WAIT_FOR_ICA",
  97. "IOCTL_ICA_STACK_CONNECTION_QUERY",
  98. "IOCTL_ICA_STACK_CONNECTION_SEND",
  99. "IOCTL_ICA_STACK_CONNECTION_REQUEST",
  100. "IOCTL_ICA_STACK_QUERY_PARAMS",
  101. "IOCTL_ICA_STACK_SET_PARAMS",
  102. "IOCTL_ICA_STACK_ENCRYPTION_OFF",
  103. "IOCTL_ICA_STACK_ENCRYPTION_PERM",
  104. "IOCTL_ICA_STACK_CALLBACK_INITIATE",
  105. "IOCTL_ICA_STACK_QUERY_LAST_ERROR",
  106. "IOCTL_ICA_STACK_WAIT_FOR_STATUS",
  107. "IOCTL_ICA_STACK_QUERY_STATUS",
  108. "IOCTL_ICA_STACK_REGISTER_HOTKEY",
  109. "IOCTL_ICA_STACK_CANCEL_IO",
  110. "IOCTL_ICA_STACK_QUERY_STATE",
  111. "IOCTL_ICA_STACK_SET_STATE",
  112. "IOCTL_ICA_STACK_QUERY_LAST_INPUT_TIME",
  113. "IOCTL_ICA_STACK_TRACE",
  114. "IOCTL_ICA_STACK_CALLBACK_COMPLETE",
  115. "IOCTL_ICA_STACK_CD_CANCEL_IO",
  116. "IOCTL_ICA_STACK_QUERY_CLIENT",
  117. "IOCTL_ICA_STACK_QUERY_MODULE_DATA",
  118. "IOCTL_ICA_STACK_REGISTER_BROKEN",
  119. "IOCTL_ICA_STACK_ENABLE_IO",
  120. "IOCTL_ICA_STACK_DISABLE_IO",
  121. "IOCTL_ICA_STACK_SET_CONNECTED",
  122. "IOCTL_ICA_STACK_SET_CLIENT_DATA",
  123. "IOCTL_ICA_STACK_QUERY_BUFFER",
  124. "IOCTL_ICA_STACK_DISCONNECT",
  125. "IOCTL_ICA_STACK_RECONNECT",
  126. "IOCTL_ICA_STACK_CONSOLE_CONNECT",
  127. "IOCTL_ICA_STACK_SET_CONFIG"
  128. };
  129. const char *wdIoctlB[] =
  130. {
  131. "IOCTL_ICA_CHANNEL_TRACE",
  132. "IOCTL_ICA_CHANNEL_ENABLE_SHADOW",
  133. "Unknown",
  134. "Unknown",
  135. "Unknown",
  136. "Unknown",
  137. "Unknown",
  138. "Unknown",
  139. "Unknown",
  140. "Unknown",
  141. "IOCTL_ICA_VIRTUAL_LOAD_FILTER",
  142. "IOCTL_ICA_VIRTUAL_UNLOAD_FILTER",
  143. "IOCTL_ICA_VIRTUAL_ENABLE_FILTER",
  144. "IOCTL_ICA_VIRTUAL_DISABLE_FILTER",
  145. "IOCTL_ICA_VIRTUAL_BOUND",
  146. "IOCTL_ICA_VIRTUAL_CANCEL_INPUT",
  147. "IOCTL_ICA_VIRTUAL_CANCEL_OUTPUT",
  148. "IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA",
  149. "IOCTL_ICA_VIRTUAL_QUERY_BINDINGS",
  150. "IOCTL_ICA_STACK_QUERY_LICENSE_CAPABILITIES",
  151. "IOCTL_ICA_STACK_REQUEST_CLIENT_LICENSE",
  152. "IOCTL_ICA_STACK_SEND_CLIENT_LICENSE",
  153. "IOCTL_ICA_STACK_LICENSE_PROTOCOL_COMPLETE",
  154. "IOCTL_ICA_STACK_GET_LICENSE_DATA",
  155. "IOCTL_ICA_STACK_SEND_KEEPALIVE_PDU",
  156. "IOCTL_TS_STACK_QUERY_LOAD_BALANCE_INFO",
  157. "IOCTL_TS_STACK_SEND_CLIENT_REDIRECTION",
  158. "IOCTL_ICA_STACK_QUERY_CLIENT_EXTENDED",
  159. "IOCTL_ICA_STACK_QUERY_AUTORECONNECT"
  160. };
  161. const char *wdIoctlC[] =
  162. {
  163. "IOCTL_VIDEO_QUERY_AVAIL_MODES",
  164. "IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES",
  165. "IOCTL_VIDEO_QUERY_CURRENT_MODE",
  166. "IOCTL_VIDEO_SET_CURRENT_MODE",
  167. "IOCTL_VIDEO_RESET_DEVICE",
  168. "IOCTL_VIDEO_LOAD_AND_SET_FONT",
  169. "IOCTL_VIDEO_SET_PALETTE_REGISTERS",
  170. "IOCTL_VIDEO_SET_COLOR_REGISTERS",
  171. "IOCTL_VIDEO_ENABLE_CURSOR",
  172. "IOCTL_VIDEO_DISABLE_CURSOR",
  173. "IOCTL_VIDEO_SET_CURSOR_ATTR",
  174. "IOCTL_VIDEO_QUERY_CURSOR_ATTR",
  175. "IOCTL_VIDEO_SET_CURSOR_POSITION",
  176. "IOCTL_VIDEO_QUERY_CURSOR_POSITION",
  177. "IOCTL_VIDEO_ENABLE_POINTER",
  178. "IOCTL_VIDEO_DISABLE_POINTER",
  179. "IOCTL_VIDEO_SET_POINTER_ATTR",
  180. "IOCTL_VIDEO_QUERY_POINTER_ATTR",
  181. "IOCTL_VIDEO_SET_POINTER_POSITION",
  182. "IOCTL_VIDEO_QUERY_POINTER_POSITION",
  183. "IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES",
  184. "IOCTL_VIDEO_GET_BANK_SELECT_CODE",
  185. "IOCTL_VIDEO_MAP_VIDEO_MEMORY",
  186. "IOCTL_VIDEO_UNMAP_VIDEO_MEMORY",
  187. "IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES",
  188. "IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES",
  189. "IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES",
  190. "IOCTL_VIDEO_SET_POWER_MANAGEMENT",
  191. "IOCTL_VIDEO_GET_POWER_MANAGEMENT",
  192. "IOCTL_VIDEO_SHARE_VIDEO_MEMORY",
  193. "IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY",
  194. };
  195. const char *wdIoctlD[] =
  196. {
  197. "IOCTL_KEYBOARD_ICA_INPUT",
  198. "IOCTL_KEYBOARD_ICA_LAYOUT",
  199. "IOCTL_KEYBOARD_ICA_SCANMAP",
  200. "IOCTL_KEYBOARD_ICA_TYPE"
  201. };
  202. const char *wdIoctlE[] =
  203. {
  204. "IOCTL_VIDEO_ICA_QUERY_FONT_PAIRS",
  205. "IOCTL_VIDEO_ICA_ENABLE_GRAPHICS",
  206. "IOCTL_VIDEO_ICA_DISABLE_GRAPHICS",
  207. "IOCTL_VIDEO_ICA_SET_CP",
  208. "IOCTL_VIDEO_ICA_STOP_OK",
  209. "IOCTL_VIDEO_ICA_REVERSE_MOUSE_POINTER",
  210. "IOCTL_VIDEO_ICA_COPY_FRAME_BUFFER",
  211. "IOCTL_VIDEO_ICA_WRITE_TO_FRAME_BUFFER",
  212. "IOCTL_VIDEO_ICA_INVALIDATE_MODES",
  213. "IOCTL_VIDEO_ICA_SCROLL",
  214. "Unknown",
  215. "Unknown",
  216. "Unknown",
  217. "Unknown",
  218. "Unknown",
  219. "Unknown",
  220. "IOCTL_ICA_STACK_ENCRYPTION_ENTER",
  221. "IOCTL_ICA_STACK_ENCRYPTION_EXIT",
  222. };
  223. const char *wdIoctlTsh[] =
  224. {
  225. "IOCTL_WDTS_DD_CONNECT",
  226. "IOCTL_WDTS_DD_DISCONNECT",
  227. "IOCTL_WDTS_DD_RECONNECT",
  228. "IOCTL_WDTS_DD_OUTPUT_AVAILABLE",
  229. "IOCTL_WDTS_DD_TIMER_INFO",
  230. "IOCTL_WDTS_DD_CLIP",
  231. "IOCTL_WDTS_DD_SHADOW_CONNECT",
  232. "IOCTL_WDTS_DD_SHADOW_DISCONNECT",
  233. "IOCTL_WDTS_DD_SHADOW_SYNCHRONIZE",
  234. "IOCTL_WDTS_DD_REDRAW_SCREEN",
  235. "IOCTL_WDTS_DD_QUERY_SHADOW_CAPS",
  236. "IOCTL_WDTS_DD_GET_BITMAP_KEYDATABASE",
  237. };
  238. #endif /* DC_DEBUG */
  239. /****************************************************************************/
  240. // WD_Ioctl
  241. //
  242. // Query/Set configuration information for the WD.
  243. /****************************************************************************/
  244. NTSTATUS WD_Ioctl(PTSHARE_WD pTSWd, PSD_IOCTL pSdIoctl)
  245. {
  246. NTSTATUS status = STATUS_SUCCESS;
  247. UINT32 bufferLen;
  248. unsigned fn;
  249. PVIDEO_MODE_INFORMATION pVidInfo;
  250. DC_BEGIN_FN("WD_Ioctl");
  251. // Special-case output-available DD ioctl for speed - separating the
  252. // most commonly-run case into a separate if that will tend to fall
  253. // through greatly speeds up Pentium Pro branch prediction and cache
  254. // line hit probability.
  255. if (pSdIoctl->IoControlCode == IOCTL_WDTS_DD_OUTPUT_AVAILABLE) {
  256. PTSHARE_DD_OUTPUT_IN pOutputIn;
  257. PTSHARE_DD_OUTPUT_OUT pOutputOut;
  258. ShareClass *dcShare;
  259. // Local variables to make the code more readable.
  260. pOutputIn = (PTSHARE_DD_OUTPUT_IN)pSdIoctl->InputBuffer;
  261. pOutputOut = (PTSHARE_DD_OUTPUT_OUT)pSdIoctl->OutputBuffer;
  262. dcShare = (ShareClass *)(pTSWd->dcShare);
  263. dcShare->m_pShm = (PSHM_SHARED_MEMORY)pOutputIn->pShm;
  264. WDW_CHECK_SHM((pOutputIn->pShm));
  265. if ((pTSWd->StackClass == Stack_Primary) ||
  266. (pTSWd->StackClass == Stack_Console)) {
  267. INT32 milliSecs;
  268. TRC_DBG((TB, "IOCTL_WDTS_DD_OUTPUT_AVAILABLE"));
  269. if (!pTSWd->dead) {
  270. TRC_DBG((TB, "OK to process the IOCtl"));
  271. TRC_ASSERT((dcShare != NULL), (TB, "NULL Share Class"));
  272. // NB There is no code here to check the size of the buffers
  273. // on the IOCtl. This is a performance critical path which
  274. // can do without it.
  275. TRC_DBG((TB, "OutputAvailable IOCtl: force send=%d",
  276. pOutputIn->forceSend));
  277. // Check if the framebuffer is valid
  278. if (pOutputIn->pFrameBuf != NULL &&
  279. pOutputIn->frameBufHeight != 0 &&
  280. pOutputIn->frameBufWidth != 0) {
  281. // For normal output IOCTLs, call DCS_TTDS.
  282. if (!pOutputIn->schedOnly) {
  283. TRC_DBG((TB, "Normal output"));
  284. // Stop the timer (in the main we don't use it, so
  285. // avoid excess context switches).
  286. WDWStopRITTimer(pTSWd);
  287. // Call the Share Core to do the work.
  288. // need to return status code so caller can bail out
  289. // in case of error
  290. status = dcShare->DCS_TimeToDoStuff(pOutputIn,
  291. &(pOutputOut->schCurrentMode), &milliSecs);
  292. // Restart the timer if requested by the core.
  293. if (milliSecs != -1L) {
  294. TRC_DBG((TB, "Run the RIT timer for %ld ms", milliSecs));
  295. WDW_StartRITTimer(pTSWd, milliSecs);
  296. }
  297. else {
  298. TRC_DBG((TB, "Skipped starting the timer!"));
  299. }
  300. }
  301. else {
  302. // It's just a wake-up call to the scheduler.
  303. TRC_NRM((TB, "Just wake up the scheduler"));
  304. dcShare->SCH_ContinueScheduling(SCH_MODE_NORMAL);
  305. // Be sure to set the current scheduler mode.
  306. pOutputOut->schCurrentMode = dcShare->SCH_GetCurrentMode();
  307. }
  308. pOutputOut->schInputKickMode = dcShare->SCH_GetInputKickMode();
  309. }
  310. else {
  311. TRC_ERR((TB, "Bad FrameBuffer input parameter"));
  312. status = STATUS_INVALID_PARAMETER;
  313. }
  314. }
  315. else {
  316. dcShare->DCS_DiscardAllOutput();
  317. TRC_ERR((TB, "Dead - ignoring IOCTL_WDTS_DD_OUTPUT_AVAILABLE"));
  318. status = STATUS_DEVICE_NOT_READY;
  319. }
  320. dcShare->m_pShm = NULL;
  321. WDW_CHECK_SHM((pOutputIn->pShm));
  322. DC_QUIT;
  323. }
  324. // Shadow stack: Duplicate the data send. Note that the target's primary
  325. // stack will have already placed the data in the shadow buffer so we
  326. // don't need to re-encode it. There may be multiple shadow stacks
  327. // consuming data from the primary stack so don't touch it!
  328. else {
  329. PSHADOW_INFO pShadowInfo = dcShare->m_pShm->pShadowInfo;
  330. if (pShadowInfo && pShadowInfo->messageSize) {
  331. PBYTE pShadowBuffer;
  332. //
  333. //find out if the stack doesn't want a low water mark
  334. //if so, allocate out of the ring (8192)
  335. //
  336. UINT32 sizeToAlloc = IcaGetSizeForNoLowWaterMark(pTSWd->pContext);
  337. // fWait is TRUE means that we will always wait for a buffer to be avail
  338. status = SM_AllocBuffer(dcShare->m_pSmInfo, (PPVOID) &pShadowBuffer,
  339. sizeToAlloc > pShadowInfo->messageSize? sizeToAlloc : pShadowInfo->messageSize,
  340. TRUE, FALSE);
  341. if ( STATUS_SUCCESS == status ) {
  342. memcpy(pShadowBuffer, pShadowInfo->data,
  343. pShadowInfo->messageSize);
  344. if (SM_SendData(dcShare->m_pSmInfo, pShadowBuffer,
  345. pShadowInfo->messageSize, PROT_PRIO_MISC, 0,
  346. FALSE, RNS_SEC_ENCRYPT, FALSE)) {
  347. status = STATUS_SUCCESS;
  348. TRC_NRM((TB, "Shadow stack send: %ld",
  349. pShadowInfo->messageSize));
  350. }
  351. else {
  352. status = STATUS_UNEXPECTED_IO_ERROR;
  353. TRC_ALT((TB, "Shadow stack send failed: %ld",
  354. pShadowInfo->messageSize));
  355. }
  356. #ifdef DC_HICOLOR
  357. // Is there any overflow data too send?
  358. if (pShadowInfo->messageSizeEx)
  359. {
  360. status = SM_AllocBuffer(dcShare->m_pSmInfo,(PPVOID)&pShadowBuffer,
  361. (sizeToAlloc > pShadowInfo->messageSizeEx )?
  362. sizeToAlloc : pShadowInfo->messageSizeEx,
  363. TRUE, FALSE);
  364. if ( STATUS_SUCCESS == status )
  365. {
  366. memcpy(
  367. pShadowBuffer,
  368. &pShadowInfo->data[WD_MAX_SHADOW_BUFFER],
  369. pShadowInfo->messageSizeEx);
  370. if (SM_SendData(dcShare->m_pSmInfo,
  371. pShadowBuffer,
  372. pShadowInfo->messageSizeEx,
  373. PROT_PRIO_MISC, 0, FALSE, RNS_SEC_ENCRYPT, FALSE))
  374. {
  375. status = STATUS_SUCCESS;
  376. TRC_NRM((TB, "Shadow stack send: %ld",
  377. pShadowInfo->messageSizeEx));
  378. }
  379. else
  380. {
  381. status = STATUS_UNEXPECTED_IO_ERROR;
  382. TRC_ALT((TB, "Shadow stack send failed: %ld",
  383. pShadowInfo->messageSizeEx));
  384. }
  385. }
  386. else
  387. {
  388. // Prevent regression, keep original return code
  389. status = STATUS_UNEXPECTED_IO_ERROR;
  390. TRC_ERR((TB, "Failed to allocate shadow stack send buffer"));
  391. }
  392. }
  393. #endif
  394. }
  395. else {
  396. // Prevent regression, keep original return code
  397. status = STATUS_UNEXPECTED_IO_ERROR;
  398. TRC_ERR((TB, "Failed to allocate shadow stack send buffer"));
  399. }
  400. }
  401. dcShare->m_pShm = NULL;
  402. WDW_CHECK_SHM((pOutputIn->pShm));
  403. DC_QUIT;
  404. }
  405. }
  406. else {
  407. // Non-perf path IOCTLs.
  408. fn = WDW_IOCTL_FUNCTION(pSdIoctl->IoControlCode);
  409. TRC_NRM((TB, "%s (%d)",
  410. fn == 6 ? "IOCTL_VIDEO_ENUM_MONITOR_PDO" :
  411. fn < 49 ? wdIoctlA[fn] :
  412. fn < 50 ? "Unknown Ioctl" :
  413. fn < 77 ? wdIoctlB[fn - 50] :
  414. fn < 0x100 ? "Unknown Ioctl" :
  415. fn < 0x11f ? wdIoctlC[fn - 0x100] :
  416. fn < 0x200 ? "Unknown Ioctl" :
  417. fn < 0x204 ? wdIoctlD[fn - 0x200] :
  418. fn == 0x300 ? "IOCTL_MOUSE_ICA_INPUT" :
  419. fn < 0x400 ? "Unknown Ioctl" :
  420. fn < 0x412 ? wdIoctlE[fn - 0x400] :
  421. fn == 0x500 ? "IOCTL_T120_REQUEST" :
  422. fn < 0x510 ? "Unknown Ioctl" :
  423. fn < 0x520 ? wdIoctlTsh[fn - 0x510] :
  424. fn == 0x900 ? "IOCTL_TSHARE_CONF_CONNECT" :
  425. fn == 0x901 ? "IOCTL_TSHARE_CONF_DISCONNECT" :
  426. fn == 0x903 ? "IOCTL_TSHARE_USER_LOGON" :
  427. fn == 0x904 ? "IOCTL_TSHARE_GET_SEC_DATA" :
  428. fn == 0x905 ? "IOCTL_TSHARE_SET_SEC_DATA" :
  429. fn == 0x906 ? "IOCTL_TSHARE_SET_NO_ENCRYPT" :
  430. fn == 0x907 ? "IOCTL_TSHARE_QUERY_CHANNELS" :
  431. fn == 0x908 ? "IOCTL_TSHARE_CONSOLE_CONNECT" :
  432. fn == 0x909 ? "IOCTL_TSHARE_SEND_CERT_DATA" :
  433. fn == 0x90A ? "IOCTL_TSHARE_GET_CERT_DATA" :
  434. fn == 0x90B ? "IOCTL_TSHARE_SEND_CLIENT_RANDOM" :
  435. fn == 0x90C ? "IOCTL_TSHARE_GET_CLIENT_RANDOM" :
  436. fn == 0x90D ? "IOCTL_TSHARE_SHADOW_CONNECT" :
  437. fn == 0x90E ? "IOCTL_TSHARE_SET_ERROR_INFO" :
  438. "Unknown Ioctl",
  439. fn));
  440. }
  441. /************************************************************************/
  442. /* Firstly, zero the no. of returned bytes. */
  443. /************************************************************************/
  444. pSdIoctl->BytesReturned = 0;
  445. switch ( pSdIoctl->IoControlCode ) {
  446. /********************************************************************/
  447. // We expect IOCTL_ICA_TRACE before tracing anything. Check for NULL
  448. // Inbuf - we've seen this happen.
  449. //
  450. // *** DO NOT TRACE IN THIS BRANCH ***
  451. /********************************************************************/
  452. case IOCTL_ICA_TRACE:
  453. {
  454. PICA_TRACE_BUFFER pTrc = (PICA_TRACE_BUFFER)pSdIoctl->InputBuffer;
  455. if (pTrc != NULL)
  456. {
  457. IcaStackTrace(pTSWd->pContext,
  458. TC_DISPLAY, // @@@MF Should be pTrc->TraceClass
  459. // but it's overwritten with '7'
  460. pTrc->TraceEnable,
  461. (char *)pTrc->Data);
  462. }
  463. break;
  464. }
  465. /****************************************************************************/
  466. /****************************************************************************/
  467. /* Firstly, for debug purposes, group together those IOCtls that we do not */
  468. /* expect to get (ICA uses them for text mode support, which we do not */
  469. /* implement). */
  470. /****************************************************************************/
  471. /****************************************************************************/
  472. case IOCTL_VIDEO_QUERY_CURSOR_ATTR :
  473. case IOCTL_VIDEO_SET_CURSOR_ATTR :
  474. case IOCTL_VIDEO_QUERY_CURSOR_POSITION :
  475. case IOCTL_VIDEO_SET_CURSOR_POSITION :
  476. case IOCTL_VIDEO_ENABLE_CURSOR :
  477. case IOCTL_VIDEO_DISABLE_CURSOR :
  478. case IOCTL_VIDEO_QUERY_POINTER_ATTR :
  479. case IOCTL_VIDEO_SET_POINTER_ATTR :
  480. case IOCTL_VIDEO_QUERY_POINTER_POSITION :
  481. case IOCTL_VIDEO_ENABLE_POINTER :
  482. case IOCTL_VIDEO_DISABLE_POINTER :
  483. case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES :
  484. case IOCTL_VIDEO_SET_PALETTE_REGISTERS :
  485. case IOCTL_VIDEO_LOAD_AND_SET_FONT :
  486. case IOCTL_VIDEO_MAP_VIDEO_MEMORY :
  487. case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY :
  488. case IOCTL_VIDEO_ICA_QUERY_FONT_PAIRS :
  489. case IOCTL_VIDEO_ICA_COPY_FRAME_BUFFER :
  490. case IOCTL_VIDEO_ICA_WRITE_TO_FRAME_BUFFER :
  491. case IOCTL_VIDEO_ICA_REVERSE_MOUSE_POINTER :
  492. case IOCTL_VIDEO_ICA_SET_CP :
  493. case IOCTL_VIDEO_ICA_SCROLL :
  494. {
  495. TRC_ALT((TB, "Unexpected IOCtl %x (function %d)",
  496. pSdIoctl->IoControlCode,
  497. WDW_IOCTL_FUNCTION(pSdIoctl->IoControlCode)));
  498. }
  499. break;
  500. /****************************************************************************/
  501. /****************************************************************************/
  502. /* Now the IOCtls that we do nothing with but just return OK. */
  503. /****************************************************************************/
  504. /****************************************************************************/
  505. /********************************************************************/
  506. /* Both of the following are expected (they occur whenever we */
  507. /* enable or disable graphics - typically when the client is */
  508. /* minimized and restored). However we don't need to do anything */
  509. /* with them. */
  510. /********************************************************************/
  511. case IOCTL_VIDEO_ICA_ENABLE_GRAPHICS :
  512. case IOCTL_VIDEO_ICA_DISABLE_GRAPHICS :
  513. /********************************************************************/
  514. /* Miscellaneous IOCTLs we don't process. */
  515. /********************************************************************/
  516. case IOCTL_ICA_STACK_DISCONNECT:
  517. case IOCTL_VIDEO_SET_POINTER_POSITION :
  518. case IOCTL_VIDEO_ICA_STOP_OK :
  519. case IOCTL_ICA_STACK_SET_CLIENT_DATA:
  520. case IOCTL_ICA_STACK_ENCRYPTION_OFF:
  521. case IOCTL_ICA_STACK_ENCRYPTION_PERM:
  522. case IOCTL_VIDEO_ICA_INVALIDATE_MODES :
  523. {
  524. TRC_NRM((TB, "Nothing to do"));
  525. }
  526. break;
  527. /****************************************************************************/
  528. /****************************************************************************/
  529. /* Here are a block of IOCtls that we process exactly as per Citrix. The */
  530. /* calls are to unmodified Citrix routines. */
  531. /****************************************************************************/
  532. /****************************************************************************/
  533. case IOCTL_KEYBOARD_QUERY_ATTRIBUTES :
  534. {
  535. status = KeyboardQueryAttributes( pTSWd, pSdIoctl );
  536. }
  537. break;
  538. case IOCTL_KEYBOARD_QUERY_TYPEMATIC :
  539. {
  540. status = KeyboardQueryTypematic( pTSWd, pSdIoctl );
  541. }
  542. break;
  543. case IOCTL_KEYBOARD_SET_TYPEMATIC :
  544. {
  545. status = KeyboardSetTypematic( pTSWd, pSdIoctl );
  546. }
  547. break;
  548. case IOCTL_KEYBOARD_QUERY_INDICATORS :
  549. {
  550. status = KeyboardQueryIndicators( pTSWd, pSdIoctl );
  551. }
  552. break;
  553. case IOCTL_KEYBOARD_SET_INDICATORS :
  554. {
  555. status = KeyboardSetIndicators( pTSWd, pSdIoctl );
  556. }
  557. break;
  558. case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION :
  559. {
  560. status = KeyboardQueryIndicatorTranslation( pTSWd, pSdIoctl );
  561. }
  562. break;
  563. case IOCTL_KEYBOARD_SET_IME_STATUS :
  564. {
  565. status = KeyboardSetImeStatus( pTSWd, pSdIoctl );
  566. }
  567. break;
  568. case IOCTL_MOUSE_QUERY_ATTRIBUTES :
  569. {
  570. status = MouseQueryAttributes( pTSWd, pSdIoctl );
  571. }
  572. break;
  573. case IOCTL_KEYBOARD_ICA_LAYOUT :
  574. status = KeyboardSetLayout( pTSWd, pSdIoctl );
  575. break;
  576. case IOCTL_KEYBOARD_ICA_SCANMAP :
  577. status = KeyboardSetScanMap( pTSWd, pSdIoctl );
  578. break;
  579. case IOCTL_KEYBOARD_ICA_TYPE :
  580. status = KeyboardSetType( pTSWd, pSdIoctl );
  581. break;
  582. /****************************************************************************/
  583. /****************************************************************************/
  584. /* The next set of cases are the IOCtls with which we do significant real */
  585. /* work. */
  586. /****************************************************************************/
  587. /****************************************************************************/
  588. // stash our new session ID
  589. case IOCTL_ICA_STACK_RECONNECT:
  590. {
  591. TRC_NRM((TB, "Got reconnect IOCTL"));
  592. TRC_ASSERT((pSdIoctl->InputBufferLength == sizeof(ICA_STACK_RECONNECT)),
  593. (TB, "Bad Reconnect Info"));
  594. pTSWd->sessionId =
  595. ((PICA_STACK_RECONNECT)(pSdIoctl->InputBuffer))->sessionId;
  596. }
  597. break;
  598. case IOCTL_ICA_SET_TRACE:
  599. {
  600. #ifdef DC_DEBUG
  601. TRC_UpdateConfig(pTSWd, pSdIoctl);
  602. TRC_NRM((TB, "Got Set Trace IOCtl"));
  603. #endif
  604. }
  605. break;
  606. case IOCTL_BEEP_SET:
  607. {
  608. TRC_NRM((TB, "Got Beep Set IOCtl"));
  609. WDWSendBeep(pTSWd, pSdIoctl);
  610. }
  611. break;
  612. case IOCTL_TSHARE_USER_LOGON:
  613. {
  614. TRC_NRM((TB, "Got user logon IOCtl"));
  615. WDWUserLoggedOn(pTSWd, pSdIoctl);
  616. pSdIoctl->BytesReturned = 0;
  617. }
  618. break;
  619. case IOCTL_TSHARE_GET_SEC_DATA:
  620. {
  621. TRC_NRM((TB, "Got GetSecurityData IOCtl"));
  622. status = SM_GetSecurityData(pTSWd->pSmInfo, pSdIoctl);
  623. }
  624. break;
  625. case IOCTL_TSHARE_SET_SEC_DATA:
  626. {
  627. TRC_NRM((TB, "Got SetSecurityData IOCtl"));
  628. if ((pSdIoctl->InputBuffer != NULL) &&
  629. (pSdIoctl->InputBufferLength >= sizeof(SECINFO))) {
  630. status = pTSWd->SessKeyCreationStatus =
  631. SM_SetSecurityData(pTSWd->pSmInfo,
  632. (PSECINFO) pSdIoctl->InputBuffer);
  633. }
  634. else {
  635. // NULL data is sent when the client random or shadow
  636. // stack random could not be generated in user mode,
  637. // likely because of decryption failure on the random value.
  638. // We need to succeedd the IOCTL, but fail the key creation
  639. // return to the pSessKeyEvent waiter.
  640. status = STATUS_SUCCESS;
  641. pTSWd->SessKeyCreationStatus = STATUS_UNSUCCESSFUL;
  642. }
  643. // We always set the session key event to prevent a deadlock
  644. // if we are being attacked with bad client security data. This
  645. // set used to be in SM_SetSecurityData(), but there it might
  646. // not have been set if any encryption errors occurred.
  647. KeSetEvent(pTSWd->pSessKeyEvent, 0, FALSE);
  648. }
  649. break;
  650. // The shadow server sends it's certificate and shadow random to the
  651. // shadow client, which then sends an encrypted client random. This
  652. // is identical to the standard connection sequence.
  653. case IOCTL_TSHARE_SEND_CERT_DATA:
  654. {
  655. ShareClass *dcShare;
  656. dcShare = (ShareClass *)(pTSWd->dcShare);
  657. status = dcShare->SC_SendServerCert(
  658. (PSHADOWCERT) pSdIoctl->InputBuffer,
  659. pSdIoctl->InputBufferLength);
  660. }
  661. break;
  662. case IOCTL_TSHARE_SEND_CLIENT_RANDOM:
  663. {
  664. ShareClass *dcShare;
  665. dcShare = (ShareClass *)(pTSWd->dcShare);
  666. status = dcShare->SC_SendClientRandom((PBYTE) pSdIoctl->InputBuffer,
  667. pSdIoctl->InputBufferLength);
  668. }
  669. break;
  670. case IOCTL_TSHARE_GET_CERT_DATA:
  671. case IOCTL_TSHARE_GET_CLIENT_RANDOM:
  672. {
  673. ShareClass *dcShare;
  674. dcShare = (ShareClass *)(pTSWd->dcShare);
  675. status = dcShare->SC_GetSecurityData(pSdIoctl);
  676. }
  677. break;
  678. case IOCTL_ICA_STACK_SET_CONFIG:
  679. {
  680. PICA_STACK_CONFIG_DATA pConfigData;
  681. pConfigData = (PICA_STACK_CONFIG_DATA) pSdIoctl->InputBuffer;
  682. TRC_NRM((TB, "Got stack config data"));
  683. WDWSetConfigData(pTSWd, pConfigData);
  684. }
  685. break;
  686. case IOCTL_ICA_STACK_WAIT_FOR_ICA :
  687. {
  688. /****************************************************************/
  689. /* Return the "default query stack," meaning reuse these */
  690. /* drivers. */
  691. /****************************************************************/
  692. TRC_NRM((TB, "Stack wait for ICA"));
  693. }
  694. break;
  695. case IOCTL_ICA_STACK_CONSOLE_CONNECT :
  696. {
  697. /****************************************************************/
  698. /* Return the "default query stack," meaning reuse these */
  699. /* drivers. */
  700. /****************************************************************/
  701. TRC_NRM((TB, "Stack Console Connect"));
  702. }
  703. break;
  704. case IOCTL_ICA_STACK_QUERY_BUFFER :
  705. {
  706. ICA_STACK_QUERY_BUFFER *pBuffers;
  707. pBuffers = (ICA_STACK_QUERY_BUFFER *) pSdIoctl->OutputBuffer;
  708. pBuffers->WdBufferCount = TSHARE_WD_BUFFER_COUNT;
  709. pBuffers->TdBufferSize = TSHARE_TD_BUFFER_SIZE;
  710. pSdIoctl->BytesReturned = sizeof(ICA_STACK_QUERY_BUFFER);
  711. TRC_NRM((TB, "Stack query buffer, num %d, size %d",
  712. pBuffers->WdBufferCount,
  713. pBuffers->TdBufferSize));
  714. }
  715. break;
  716. case IOCTL_TSHARE_CONF_CONNECT:
  717. {
  718. TRC_NRM((TB, "Got TSHARE_CONF_CONNECT IOCtl"));
  719. status = WDWConfConnect(pTSWd, pSdIoctl);
  720. }
  721. break;
  722. case IOCTL_TSHARE_CONSOLE_CONNECT:
  723. {
  724. TRC_NRM((TB, "Got TSHARE_CONSOLE_CONNECT IOCtl"));
  725. status = WDWConsoleConnect(pTSWd, pSdIoctl);
  726. }
  727. break;
  728. case IOCTL_TSHARE_SHADOW_CONNECT:
  729. status = WDWShadowConnect(pTSWd, pSdIoctl) ;
  730. break;
  731. case IOCTL_TSHARE_SET_ERROR_INFO:
  732. {
  733. TRC_NRM((TB, "Got SetErrorInfo IOCtl"));
  734. status = WDWSetErrorInfo(pTSWd, pSdIoctl);
  735. pSdIoctl->BytesReturned = 0;
  736. }
  737. break;
  738. case IOCTL_TSHARE_SEND_ARC_STATUS:
  739. {
  740. TRC_NRM((TB, "Got SetArcStatus IOCtl"));
  741. status = WDWSendArcStatus(pTSWd, pSdIoctl);
  742. pSdIoctl->BytesReturned = 0;
  743. }
  744. break;
  745. case IOCTL_ICA_STACK_SET_CONNECTED:
  746. status = STATUS_SUCCESS;
  747. break;
  748. case IOCTL_ICA_STACK_CONNECTION_QUERY :
  749. {
  750. PICA_STACK_CONFIG pIcaStackConfig;
  751. pIcaStackConfig = (PICA_STACK_CONFIG) pSdIoctl->OutputBuffer;
  752. memcpy(pIcaStackConfig->WdDLL,
  753. pTSWd->DLLName,
  754. sizeof(pIcaStackConfig->WdDLL));
  755. pIcaStackConfig->SdClass[0] = SdNone;
  756. pSdIoctl->BytesReturned = pSdIoctl->OutputBufferLength;
  757. TRC_NRM((TB, "Stack Connection Query"));
  758. }
  759. break;
  760. case IOCTL_TSHARE_QUERY_CHANNELS:
  761. {
  762. TRC_NRM((TB, "Query Virtual Channel data"));
  763. status = NM_QueryChannels(pTSWd->pNMInfo,
  764. pSdIoctl->OutputBuffer,
  765. pSdIoctl->OutputBufferLength,
  766. &(pSdIoctl->BytesReturned));
  767. }
  768. break;
  769. case IOCTL_WDTS_DD_CONNECT:
  770. {
  771. if (pSdIoctl->InputBuffer &&
  772. (((PTSHARE_DD_CONNECT_IN)pSdIoctl->InputBuffer)->pShm)) {
  773. WDW_CHECK_SHM(
  774. (((PTSHARE_DD_CONNECT_IN)pSdIoctl->InputBuffer)->pShm));
  775. TRC_DBG((TB, "Got TSHARE_DD_CONNECT IOCtl"));
  776. status = WDWDDConnect(pTSWd, pSdIoctl, FALSE);
  777. WDW_CHECK_SHM(
  778. (((PTSHARE_DD_CONNECT_IN)pSdIoctl->InputBuffer)->pShm));
  779. }
  780. else {
  781. status = STATUS_INVALID_PARAMETER;
  782. }
  783. }
  784. break;
  785. case IOCTL_WDTS_DD_DISCONNECT:
  786. {
  787. if (pSdIoctl->InputBuffer &&
  788. (((PTSHARE_DD_DISCONNECT_IN)pSdIoctl->InputBuffer)->pShm)) {
  789. WDW_CHECK_SHM(
  790. (((PTSHARE_DD_DISCONNECT_IN)pSdIoctl->InputBuffer)->pShm));
  791. TRC_ALT((TB, "Got TSHARE_DD_DISCONNECT IOCtl: Stack (%ld)",
  792. pTSWd->StackClass));
  793. if ((pTSWd->StackClass == Stack_Primary) ||
  794. (pTSWd->StackClass == Stack_Console)) {
  795. status = WDWDDDisconnect(pTSWd, pSdIoctl, FALSE);
  796. }
  797. WDW_CHECK_SHM(
  798. (((PTSHARE_DD_DISCONNECT_IN)pSdIoctl->InputBuffer)->pShm));
  799. }
  800. else {
  801. status = STATUS_INVALID_PARAMETER;
  802. }
  803. }
  804. break;
  805. case IOCTL_WDTS_DD_RECONNECT:
  806. {
  807. if (pSdIoctl->InputBuffer &&
  808. (((PTSHARE_DD_CONNECT_IN)pSdIoctl->InputBuffer)->pShm)) {
  809. WDW_CHECK_SHM(
  810. (((PTSHARE_DD_CONNECT_IN)pSdIoctl->InputBuffer)->pShm));
  811. TRC_DBG((TB, "Got TSHARE_DD_RECONNECT IOCtl"));
  812. if (pTSWd->shadowState == SHADOW_CLIENT) {
  813. TRC_ALT((TB, "Shadow termination on reconnect, in share(%ld)",
  814. pTSWd->bInShadowShare));
  815. pTSWd->shadowState = SHADOW_NONE;
  816. // If we were formerly in an active shadow, then we need to
  817. // deactivate the client before reconnecting in a new share
  818. if (pTSWd->bInShadowShare) {
  819. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  820. pSC->SC_EndShare(TRUE);
  821. pTSWd->bInShadowShare = FALSE;
  822. }
  823. // Make sure that Domain.StatusDead is consistent with TSWd.dead
  824. pTSWd->dead = TRUE;
  825. ((PDomain)(pTSWd->hDomainKernel))->StatusDead = TRUE;
  826. SM_Dead(pTSWd->pSmInfo, TRUE);
  827. if (pTSWd->bCompress == TRUE) {
  828. // the compression history will be flushed
  829. pTSWd->bFlushed = PACKET_FLUSHED;
  830. // the compression will restart over
  831. initsendcontext(pTSWd->pMPPCContext, pTSWd->pMPPCContext->ClientComprType);
  832. }
  833. }
  834. status = WDWDDConnect(pTSWd, pSdIoctl, TRUE);
  835. WDW_CHECK_SHM(
  836. (((PTSHARE_DD_CONNECT_IN)pSdIoctl->InputBuffer)->pShm));
  837. }
  838. else {
  839. status = STATUS_INVALID_PARAMETER;
  840. }
  841. }
  842. break;
  843. case IOCTL_WDTS_DD_TIMER_INFO:
  844. {
  845. if (pSdIoctl->InputBufferLength < sizeof(TSHARE_DD_TIMER_INFO))
  846. {
  847. TRC_ERR((TB, "Timer info IOCtl too small at %lu",
  848. pSdIoctl->InputBufferLength));
  849. status = STATUS_BUFFER_TOO_SMALL;
  850. }
  851. else
  852. {
  853. /************************************************************/
  854. /* Store the timer handle */
  855. /************************************************************/
  856. pTSWd->ritTimer =
  857. ((PTSHARE_DD_TIMER_INFO)(pSdIoctl->InputBuffer))->
  858. pKickTimer;
  859. TRC_DBG((TB, "Got TSHARE_DD_TIMER_INFO IOCtl, handle %p",
  860. pTSWd->ritTimer));
  861. /************************************************************/
  862. /* Start a timer to get things moving */
  863. /************************************************************/
  864. WDW_StartRITTimer(pTSWd, pTSWd->outBufDelay);
  865. }
  866. }
  867. break;
  868. case IOCTL_WDTS_DD_REDRAW_SCREEN :
  869. {
  870. ShareClass *dcShare;
  871. dcShare = (ShareClass *)(pTSWd->dcShare);
  872. TRC_NRM((TB, "RDPDD requests to redraw screen\n"));
  873. if (dcShare != NULL) {
  874. // We have a valid share class, do screen redraw
  875. dcShare->SC_RedrawScreen();
  876. }
  877. }
  878. break;
  879. case IOCTL_ICA_STACK_CONNECTION_SEND :
  880. {
  881. // Wait for the connected indication from SM.
  882. TRC_DBG((TB, "About to wait for connected indication"));
  883. status = WDW_WaitForConnectionEvent(pTSWd,
  884. pTSWd->pConnEvent, 60000);
  885. TRC_DBG((TB, "Back from wait for connected indication"));
  886. if (status != STATUS_SUCCESS) {
  887. TRC_ERR((TB, "Connected indication timed out (%x)",
  888. status));
  889. status = STATUS_IO_TIMEOUT;
  890. DC_QUIT;
  891. }
  892. // Pass the IOCtl on to the next driver.
  893. status = IcaCallNextDriver(pTSWd->pContext, SD$IOCTL, pSdIoctl);
  894. }
  895. break;
  896. case IOCTL_ICA_STACK_QUERY_CLIENT :
  897. {
  898. status = WDWGetClientData( pTSWd, pSdIoctl );
  899. TRC_NRM((TB, "Return client data"));
  900. }
  901. break;
  902. // This IOCTL was introduced to support long UserName, Password and Domain names
  903. case IOCTL_ICA_STACK_QUERY_CLIENT_EXTENDED :
  904. {
  905. status = WDWGetExtendedClientData(pTSWd->pInfoPkt, pSdIoctl);
  906. TRC_NRM((TB, "Return Extended client data"));
  907. }
  908. break;
  909. case IOCTL_ICA_STACK_QUERY_AUTORECONNECT:
  910. {
  911. TRC_NRM((TB, "Query autoreconnect information"));
  912. status = WDWGetAutoReconnectInfo(pTSWd, pTSWd->pInfoPkt, pSdIoctl);
  913. }
  914. break;
  915. /****************************************************************************/
  916. /****************************************************************************/
  917. /* Here are some IOCtls that we have to deal with in our guise of miniport */
  918. /* driver. */
  919. /****************************************************************************/
  920. /****************************************************************************/
  921. case IOCTL_VIDEO_QUERY_CURRENT_MODE:
  922. {
  923. TRC_NRM((TB, "QueryCurrentModes"));
  924. if (pSdIoctl->OutputBufferLength <
  925. sizeof(VIDEO_MODE_INFORMATION))
  926. {
  927. TRC_ERR((TB,
  928. "QueryCurrentMode buffer too small: got/expected %d/%d",
  929. pSdIoctl->OutputBufferLength,
  930. sizeof(VIDEO_MODE_INFORMATION) ));
  931. status = STATUS_BUFFER_TOO_SMALL;
  932. }
  933. else
  934. {
  935. TRC_NRM((TB, "Return current mode"));
  936. /************************************************************/
  937. /* Copy the default mode information, and then update it */
  938. /* with our current screen dimensions. */
  939. /************************************************************/
  940. pVidInfo =
  941. (PVIDEO_MODE_INFORMATION)pSdIoctl->OutputBuffer;
  942. memcpy(pVidInfo,
  943. wdSimModes,
  944. sizeof(wdSimModes));
  945. pVidInfo->Length = sizeof(VIDEO_MODE_INFORMATION);
  946. pVidInfo->VisScreenWidth = pTSWd->desktopWidth;
  947. pVidInfo->VisScreenHeight = pTSWd->desktopHeight;
  948. pVidInfo->BitsPerPlane = pTSWd->desktopBpp;
  949. pVidInfo->VideoMemoryBitmapWidth = pTSWd->desktopWidth;
  950. pVidInfo->VideoMemoryBitmapHeight = pTSWd->desktopHeight;
  951. #ifdef DC_HICOLOR
  952. switch (pTSWd->desktopBpp)
  953. {
  954. case 24:
  955. {
  956. pVidInfo->RedMask = TS_RED_MASK_24BPP;
  957. pVidInfo->GreenMask = TS_GREEN_MASK_24BPP;
  958. pVidInfo->BlueMask = TS_BLUE_MASK_24BPP;
  959. }
  960. break;
  961. case 16:
  962. {
  963. pVidInfo->RedMask = TS_RED_MASK_16BPP;
  964. pVidInfo->GreenMask = TS_GREEN_MASK_16BPP;
  965. pVidInfo->BlueMask = TS_BLUE_MASK_16BPP;
  966. }
  967. break;
  968. case 15:
  969. {
  970. pVidInfo->RedMask = TS_RED_MASK_15BPP;
  971. pVidInfo->GreenMask = TS_GREEN_MASK_15BPP;
  972. pVidInfo->BlueMask = TS_BLUE_MASK_15BPP;
  973. }
  974. break;
  975. default:
  976. {
  977. pVidInfo->RedMask = 0;
  978. pVidInfo->GreenMask = 0;
  979. pVidInfo->BlueMask = 0;
  980. }
  981. break;
  982. }
  983. #endif
  984. pSdIoctl->BytesReturned = sizeof(wdSimModes);
  985. }
  986. }
  987. break;
  988. case IOCTL_VIDEO_QUERY_AVAIL_MODES:
  989. {
  990. TRC_NRM((TB, "QueryAvailableModes"));
  991. if (pSdIoctl->OutputBufferLength <
  992. sizeof(VIDEO_MODE_INFORMATION))
  993. {
  994. TRC_ERR((TB,
  995. "QueryCurrentMode buffer too small: got/expected %d/%d",
  996. pSdIoctl->OutputBufferLength,
  997. sizeof(VIDEO_MODE_INFORMATION) ));
  998. status = STATUS_BUFFER_TOO_SMALL;
  999. }
  1000. else
  1001. {
  1002. TRC_NRM((TB, "Return just one mode"));
  1003. // Copy the default mode information, and then update it
  1004. // with our current screen dimensions.
  1005. pVidInfo = (PVIDEO_MODE_INFORMATION)pSdIoctl->OutputBuffer;
  1006. memcpy(pVidInfo,
  1007. wdSimModes,
  1008. sizeof(wdSimModes));
  1009. pVidInfo->Length = sizeof(VIDEO_MODE_INFORMATION);
  1010. pVidInfo->VisScreenWidth = pTSWd->desktopWidth;
  1011. pVidInfo->VisScreenHeight = pTSWd->desktopHeight;
  1012. pVidInfo->BitsPerPlane = pTSWd->desktopBpp;
  1013. pVidInfo->VideoMemoryBitmapWidth = pTSWd->desktopWidth;
  1014. pVidInfo->VideoMemoryBitmapHeight = pTSWd->desktopHeight;
  1015. pVidInfo->Frequency = 42; // required by the display cpl
  1016. #ifdef DC_HICOLOR
  1017. switch (pTSWd->desktopBpp)
  1018. {
  1019. case 24:
  1020. {
  1021. pVidInfo->RedMask = TS_RED_MASK_24BPP;
  1022. pVidInfo->GreenMask = TS_GREEN_MASK_24BPP;
  1023. pVidInfo->BlueMask = TS_BLUE_MASK_24BPP;
  1024. }
  1025. break;
  1026. case 16:
  1027. {
  1028. pVidInfo->RedMask = TS_RED_MASK_16BPP;
  1029. pVidInfo->GreenMask = TS_GREEN_MASK_16BPP;
  1030. pVidInfo->BlueMask = TS_BLUE_MASK_16BPP;
  1031. }
  1032. break;
  1033. case 15:
  1034. {
  1035. pVidInfo->RedMask = TS_RED_MASK_15BPP;
  1036. pVidInfo->GreenMask = TS_GREEN_MASK_15BPP;
  1037. pVidInfo->BlueMask = TS_BLUE_MASK_15BPP;
  1038. }
  1039. break;
  1040. default:
  1041. {
  1042. pVidInfo->RedMask = 0;
  1043. pVidInfo->GreenMask = 0;
  1044. pVidInfo->BlueMask = 0;
  1045. }
  1046. break;
  1047. }
  1048. #endif
  1049. pSdIoctl->BytesReturned = sizeof(wdSimModes);
  1050. }
  1051. }
  1052. break;
  1053. case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
  1054. {
  1055. TRC_NRM((TB, "QueryNumAvailableModes"));
  1056. if (pSdIoctl->OutputBufferLength < sizeof(VIDEO_NUM_MODES))
  1057. {
  1058. TRC_ERR((TB,
  1059. "QueryNumAvailableModes buffer too small: got/expected %d/%d",
  1060. pSdIoctl->OutputBufferLength,
  1061. sizeof(VIDEO_NUM_MODES)));
  1062. status = STATUS_BUFFER_TOO_SMALL;
  1063. }
  1064. else
  1065. {
  1066. PVIDEO_NUM_MODES pNumModes =
  1067. (PVIDEO_NUM_MODES)(pSdIoctl->OutputBuffer);
  1068. TRC_NRM((TB, "Return 1 mode available"));
  1069. pNumModes->NumModes = 1;
  1070. pNumModes->ModeInformationLength =
  1071. sizeof(VIDEO_MODE_INFORMATION);
  1072. pSdIoctl->BytesReturned = sizeof(VIDEO_NUM_MODES);
  1073. }
  1074. }
  1075. break;
  1076. case IOCTL_VIDEO_SET_CURRENT_MODE:
  1077. {
  1078. /****************************************************************/
  1079. /* Not clear why we might get this, hence we trace at high */
  1080. /* level for now. In any case, the IOCtl is sent to set a */
  1081. /* particular VGA mode: we have told Win32 what we support: */
  1082. /* either it is setting that, or we have a problem waiting to */
  1083. /* happen. */
  1084. /****************************************************************/
  1085. TRC_ALT((TB, "SetCurrentMode"));
  1086. if (pSdIoctl->InputBufferLength < sizeof(VIDEO_MODE))
  1087. {
  1088. TRC_ERR((TB,
  1089. "SetCurrentMode buffer too small: got/expected %d/%d",
  1090. pSdIoctl->InputBufferLength, sizeof(VIDEO_MODE) ));
  1091. status = STATUS_BUFFER_TOO_SMALL;
  1092. }
  1093. else
  1094. {
  1095. TRC_ALT((TB, "Set current mode to %d",
  1096. ((PVIDEO_MODE)(pSdIoctl->InputBuffer))->RequestedMode));
  1097. }
  1098. }
  1099. break;
  1100. case IOCTL_VIDEO_SET_COLOR_REGISTERS:
  1101. {
  1102. TRC_NRM((TB, "SetColorRegisters"));
  1103. }
  1104. break;
  1105. case IOCTL_VIDEO_RESET_DEVICE:
  1106. {
  1107. TRC_NRM((TB, "ResetDevice"));
  1108. }
  1109. break;
  1110. /****************************************************************************/
  1111. /****************************************************************************/
  1112. /* IOCtls that require translation for MCS */
  1113. /****************************************************************************/
  1114. /****************************************************************************/
  1115. /********************************************************************/
  1116. /* Process Query Bindings for local and MCS virtual channels */
  1117. /********************************************************************/
  1118. case IOCTL_ICA_VIRTUAL_QUERY_BINDINGS :
  1119. {
  1120. PSD_VCBIND pVBind;
  1121. /****************************************************************/
  1122. /* This IOCtl is issued twice */
  1123. /****************************************************************/
  1124. if (!pTSWd->bVirtualChannelBound)
  1125. {
  1126. /************************************************************/
  1127. /* First time, return internal channels */
  1128. /************************************************************/
  1129. pVBind = (PSD_VCBIND) pSdIoctl->OutputBuffer;
  1130. /************************************************************/
  1131. /* Let MCS define channel(s) */
  1132. /************************************************************/
  1133. MCSIcaVirtualQueryBindings(pTSWd->hDomainKernel,
  1134. &pVBind,
  1135. (unsigned int *)&pSdIoctl->
  1136. BytesReturned);
  1137. // Add RDPDD->RDPWD channel.
  1138. RtlCopyMemory(pVBind->VirtualName,
  1139. VIRTUAL_THINWIRE,
  1140. sizeof(VIRTUAL_THINWIRE));
  1141. pVBind->VirtualClass = WD_THINWIRE_CHANNEL;
  1142. pSdIoctl->BytesReturned += sizeof(SD_VCBIND);
  1143. pTSWd->bVirtualChannelBound = TRUE;
  1144. TRC_NRM((TB, "%d Virtual Channels (first time)",
  1145. pSdIoctl->BytesReturned/sizeof(SD_VCBIND)));
  1146. }
  1147. else
  1148. {
  1149. /************************************************************/
  1150. /* Second time, return virtual channels */
  1151. /************************************************************/
  1152. pVBind = (PSD_VCBIND)pSdIoctl->OutputBuffer;
  1153. status = NM_VirtualQueryBindings(pTSWd->pNMInfo,
  1154. pVBind,
  1155. pSdIoctl->OutputBufferLength,
  1156. &(pSdIoctl->BytesReturned));
  1157. TRC_NRM((TB, "%d Virtual Channels (second time)",
  1158. pSdIoctl->BytesReturned/sizeof(SD_VCBIND)));
  1159. }
  1160. }
  1161. break;
  1162. /********************************************************************/
  1163. /* T.120 request from user mode - pass it on */
  1164. /********************************************************************/
  1165. case IOCTL_T120_REQUEST:
  1166. {
  1167. status = MCSIcaT120Request(pTSWd->hDomainKernel, pSdIoctl);
  1168. }
  1169. break;
  1170. #ifdef USE_LICENSE
  1171. /****************************************************************************/
  1172. /****************************************************************************/
  1173. /* Licensing IOCtls */
  1174. /****************************************************************************/
  1175. /****************************************************************************/
  1176. /********************************************************************/
  1177. /* Query the client licensing capabilities
  1178. /********************************************************************/
  1179. case IOCTL_ICA_STACK_QUERY_LICENSE_CAPABILITIES:
  1180. {
  1181. PLICENSE_CAPABILITIES pLicenseCap;
  1182. if( pSdIoctl->OutputBufferLength < sizeof( LICENSE_CAPABILITIES ) )
  1183. {
  1184. TRC_ERR( ( TB,
  1185. "QueryLicenseCapabilities buffer too small: got/expected %d/%d",
  1186. pSdIoctl->OutputBufferLength, sizeof( LICENSE_CAPABILITIES ) ) );
  1187. status = STATUS_BUFFER_TOO_SMALL;
  1188. }
  1189. else
  1190. {
  1191. //
  1192. // set the client licensing capability. Here we temporarily hard-code
  1193. // the client to use the RSA key exchange algorithm and the licensing
  1194. // protocol version.
  1195. //
  1196. pLicenseCap = ( PLICENSE_CAPABILITIES )( pSdIoctl->OutputBuffer );
  1197. pLicenseCap->KeyExchangeAlg = KEY_EXCHANGE_ALG_RSA;
  1198. if( RNS_TERMSRV_40_UD_VERSION >= pTSWd->version )
  1199. {
  1200. //
  1201. // this is a hydra 4.0 client, use the corresponding licensing
  1202. // protocol.
  1203. //
  1204. pLicenseCap->ProtocolVer = LICENSE_HYDRA_40_PROTOCOL_VERSION;
  1205. pLicenseCap->fAuthenticateServer = TRUE;
  1206. }
  1207. else
  1208. {
  1209. //
  1210. // Use the latest licensing protocol for later clients
  1211. //
  1212. pLicenseCap->ProtocolVer = LICENSE_HIGHEST_PROTOCOL_VERSION;
  1213. //
  1214. // if encryption is enabled, then the server has already been
  1215. // authenticated in the earlier key exchange protocol and the
  1216. // licensing protocol does not have to authenticate the server
  1217. // again.
  1218. //
  1219. pLicenseCap->fAuthenticateServer = ( SM_IsSecurityExchangeCompleted(
  1220. pTSWd->pSmInfo,
  1221. &pLicenseCap->CertType ) ?
  1222. FALSE : TRUE );
  1223. }
  1224. TRC_NRM( ( TB, "Key Exchange Alg = %d", pLicenseCap->KeyExchangeAlg ) );
  1225. TRC_NRM( ( TB, "License Protocol Version = %x", pLicenseCap->ProtocolVer ) );
  1226. //
  1227. // copy the client name
  1228. //
  1229. if( pLicenseCap->pbClientName )
  1230. {
  1231. memcpy( pLicenseCap->pbClientName,
  1232. pTSWd->clientName,
  1233. ( ( pLicenseCap->cbClientName < sizeof( pTSWd->clientName ) ) ?
  1234. pLicenseCap->cbClientName : sizeof( pTSWd->clientName ) ) );
  1235. }
  1236. pSdIoctl->BytesReturned = sizeof( LICENSE_CAPABILITIES );
  1237. }
  1238. }
  1239. break;
  1240. /********************************************************************/
  1241. /* Send and receive licensing protocol data to and from client.
  1242. /********************************************************************/
  1243. case IOCTL_ICA_STACK_REQUEST_CLIENT_LICENSE:
  1244. {
  1245. PLicense_Handle pLicenseHandle;
  1246. BOOL rc = FALSE;
  1247. BOOL encrypingLicToCli;
  1248. NTSTATUS waitStatus;
  1249. PBYTE pOutBuffer;
  1250. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)(pTSWd->pSmInfo);
  1251. PRNS_SECURITY_HEADER pLicenseHeader;
  1252. pLicenseHandle = ( PLicense_Handle )pTSWd->pSLicenseHandle;
  1253. //
  1254. // validate input parameters
  1255. //
  1256. ASSERT( NULL != pLicenseHandle );
  1257. ASSERT( NULL != pSdIoctl->InputBuffer );
  1258. ASSERT( 0 < pSdIoctl->InputBufferLength );
  1259. if( ( NULL == pLicenseHandle ) ||
  1260. ( NULL == pSdIoctl->InputBuffer ) ||
  1261. ( 0 >= pSdIoctl->InputBufferLength ) )
  1262. {
  1263. TRC_ERR( ( TB, "invalid Licensing IOCTL parameters" ) );
  1264. status = STATUS_INVALID_PARAMETER;
  1265. break;
  1266. }
  1267. if( ( pSdIoctl->OutputBuffer ) && ( pSdIoctl->OutputBufferLength > 0 ) )
  1268. {
  1269. //
  1270. // set the output buffer pointer so that we can receive data
  1271. // when the client response
  1272. //
  1273. pLicenseHandle->pDataBuf = ( PBYTE )pSdIoctl->OutputBuffer;
  1274. pLicenseHandle->cbDataBuf = pSdIoctl->OutputBufferLength;
  1275. }
  1276. else
  1277. {
  1278. pLicenseHandle->pDataBuf = NULL;
  1279. pLicenseHandle->cbDataBuf = 0;
  1280. }
  1281. //
  1282. // We will encrypt the S->C licensing packet if encryption is
  1283. // on AND if the client told us they can decrypt this particular
  1284. // packet.
  1285. // If encryptDisplayData is not set (low encryption), we don't
  1286. // encrypt the S->C licensing packet
  1287. //
  1288. encrypingLicToCli = (pRealSMHandle->encrypting &&
  1289. pRealSMHandle->encryptingLicToClient &&
  1290. pRealSMHandle->encryptDisplayData);
  1291. if (!encrypingLicToCli)
  1292. {
  1293. //
  1294. // Allocate an NM buffer for sending the data. we are allocating an extra
  1295. // DWORD to hack around the encryption problem.
  1296. // fWait is TRUE means that we will always wait for a buffer to be avail
  1297. status = NM_AllocBuffer( pTSWd->pNMInfo,
  1298. ( PPVOID )&pOutBuffer,
  1299. pSdIoctl->InputBufferLength +
  1300. sizeof( RNS_SECURITY_HEADER ),
  1301. TRUE );
  1302. if( STATUS_SUCCESS != status || pTSWd->hDomainKernel == NULL)
  1303. {
  1304. TRC_ERR( ( TB, "Failed to allocate NM buffer" ) );
  1305. if (STATUS_SUCCESS == status) {
  1306. NM_FreeBuffer(pTSWd->pNMInfo, pOutBuffer);
  1307. status = STATUS_NET_WRITE_FAULT;
  1308. }
  1309. else {
  1310. // Follow old code path.
  1311. status = STATUS_NO_MEMORY;
  1312. }
  1313. break;
  1314. }
  1315. //
  1316. // initialize the license data header
  1317. //
  1318. pLicenseHeader = ( PRNS_SECURITY_HEADER )pOutBuffer;
  1319. //
  1320. // Indicate this is a licensing packet and then cheat and sneak
  1321. // in the flag that indicates the client should encrypt all
  1322. // licensing data sent to the server (early capabilities)
  1323. //
  1324. pLicenseHeader->flags = RNS_SEC_LICENSE_PKT |
  1325. RDP_SEC_LICENSE_ENCRYPT_CS;
  1326. pLicenseHeader->flagsHi = ( WORD )pSdIoctl->InputBufferLength;
  1327. //
  1328. // copy the data over
  1329. //
  1330. ASSERT( NULL != pOutBuffer );
  1331. memcpy( pOutBuffer + sizeof( RNS_SECURITY_HEADER ),
  1332. pSdIoctl->InputBuffer,
  1333. pSdIoctl->InputBufferLength );
  1334. }
  1335. else
  1336. {
  1337. if (STATUS_SUCCESS == SM_AllocBuffer(pTSWd->pSmInfo, (PPVOID) &pOutBuffer, pSdIoctl->InputBufferLength, TRUE, FALSE))
  1338. {
  1339. memcpy(pOutBuffer, (PBYTE)pSdIoctl->InputBuffer, pSdIoctl->InputBufferLength);
  1340. }
  1341. else {
  1342. TRC_ERR((TB, "FAILED to alloc license data buffer"));
  1343. status = STATUS_NO_MEMORY;
  1344. break;
  1345. }
  1346. }
  1347. //
  1348. // clear the incoming data event
  1349. //
  1350. KeClearEvent( pLicenseHandle->pDataEvent );
  1351. //
  1352. // send the data in the input buffer
  1353. //
  1354. if (encrypingLicToCli)
  1355. {
  1356. rc = SM_SendData(pTSWd->pSmInfo, pOutBuffer, pSdIoctl->InputBufferLength,
  1357. TS_HIGHPRIORITY, 0, FALSE, RNS_SEC_LICENSE_PKT | RDP_SEC_LICENSE_ENCRYPT_CS | RNS_SEC_ENCRYPT, FALSE);
  1358. }
  1359. else
  1360. {
  1361. rc = NM_SendData(pTSWd->pNMInfo, (BYTE *)pOutBuffer,
  1362. pSdIoctl->InputBufferLength + sizeof(RNS_SECURITY_HEADER),
  1363. TS_HIGHPRIORITY, 0, FALSE);
  1364. }
  1365. if (!rc)
  1366. {
  1367. TRC_ERR((TB, "Failed to send licensing data"));
  1368. status = STATUS_NET_WRITE_FAULT;
  1369. break;
  1370. }
  1371. if (pLicenseHandle->pDataBuf)
  1372. {
  1373. //
  1374. // caller supplied a return buffer, wait for the client response
  1375. //
  1376. waitStatus = WDW_WaitForConnectionEvent(pTSWd,
  1377. pLicenseHandle->pDataEvent, 60000L);
  1378. if (STATUS_TIMEOUT == waitStatus)
  1379. {
  1380. TRC_ERR( ( TB, "Timeout waiting for client licensing response" ) );
  1381. pSdIoctl->BytesReturned = 0;
  1382. status = STATUS_IO_TIMEOUT;
  1383. }
  1384. else
  1385. {
  1386. //
  1387. // got the client response, check that the data is received
  1388. // correctly
  1389. //
  1390. if( !NT_SUCCESS( pLicenseHandle->Status ) )
  1391. {
  1392. status = pLicenseHandle->Status;
  1393. //
  1394. // The data was not copied correctly. If the buffer provided is
  1395. // too small, let the caller know the right size of the
  1396. // buffer to provide.
  1397. //
  1398. if( STATUS_BUFFER_TOO_SMALL == status )
  1399. {
  1400. TRC_ERR( ( TB,
  1401. "IOCTL_ICA_STACK_REQUEST_CLIENT_LICENSE buffer too small: got/expected %d/%d",
  1402. pSdIoctl->InputBufferLength, pLicenseHandle->cbCacheBuf ) );
  1403. pSdIoctl->BytesReturned = pLicenseHandle->cbCacheBuf;
  1404. }
  1405. else
  1406. {
  1407. pSdIoctl->BytesReturned = 0;
  1408. }
  1409. }
  1410. else
  1411. {
  1412. pSdIoctl->BytesReturned = pLicenseHandle->cbDataBuf;
  1413. }
  1414. }
  1415. if (status != STATUS_SUCCESS)
  1416. {
  1417. // Make sure we don't try to write to pointer when
  1418. // client data comes in
  1419. pLicenseHandle->pDataBuf = NULL;
  1420. pLicenseHandle->cbDataBuf = 0;
  1421. }
  1422. }
  1423. else
  1424. {
  1425. //
  1426. // caller did not supply a return buffer, simply return
  1427. //
  1428. pSdIoctl->BytesReturned = 0;
  1429. }
  1430. }
  1431. break;
  1432. /********************************************************************/
  1433. /* Send licensing protocol data to client without waiting for reply.
  1434. /********************************************************************/
  1435. case IOCTL_ICA_STACK_SEND_CLIENT_LICENSE:
  1436. {
  1437. PLicense_Handle pLicenseHandle;
  1438. BOOL rc = FALSE;
  1439. BOOL encrypingLicToCli;
  1440. PBYTE pOutBuffer;
  1441. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)(pTSWd->pSmInfo);
  1442. PRNS_SECURITY_HEADER pLicenseHeader;
  1443. pLicenseHandle = ( PLicense_Handle )pTSWd->pSLicenseHandle;
  1444. //
  1445. // validate input parameters
  1446. //
  1447. ASSERT( NULL != pLicenseHandle );
  1448. ASSERT( NULL != pSdIoctl->InputBuffer );
  1449. ASSERT( 0 < pSdIoctl->InputBufferLength );
  1450. if( ( NULL == pLicenseHandle ) ||
  1451. ( NULL == pSdIoctl->InputBuffer ) ||
  1452. ( 0 >= pSdIoctl->InputBufferLength ) )
  1453. {
  1454. TRC_ERR( ( TB, "invalid Licensing IOCTL parameters" ) );
  1455. status = STATUS_INVALID_PARAMETER;
  1456. break;
  1457. }
  1458. //
  1459. // We will encrypt the S->C licensing packet if encryption is
  1460. // on AND if the client told us they can decrypt this particular
  1461. // packet.
  1462. // If encryptDisplayData is not set (low encryption), we don't
  1463. // encrypt the S->C licensing packet
  1464. //
  1465. encrypingLicToCli = (pRealSMHandle->encrypting &&
  1466. pRealSMHandle->encryptingLicToClient &&
  1467. pRealSMHandle->encryptDisplayData);
  1468. if (!encrypingLicToCli)
  1469. {
  1470. //
  1471. // allocate NM buffer for sending
  1472. // fWait is TRUE means that we will always wait for a buffer to be avail
  1473. status = NM_AllocBuffer( pTSWd->pNMInfo,
  1474. ( PPVOID )&pOutBuffer,
  1475. pSdIoctl->InputBufferLength + sizeof( RNS_SECURITY_HEADER ),
  1476. TRUE );
  1477. if( STATUS_SUCCESS != status || pTSWd->hDomainKernel == NULL)
  1478. {
  1479. TRC_ERR( ( TB, "Failed to allocate SM buffer" ) );
  1480. if (STATUS_SUCCESS == status) {
  1481. NM_FreeBuffer(pTSWd->pNMInfo, pOutBuffer);
  1482. status = STATUS_NET_WRITE_FAULT;
  1483. }
  1484. else {
  1485. // Follow old code path.
  1486. status = STATUS_NO_MEMORY;
  1487. }
  1488. break;
  1489. }
  1490. //
  1491. // initialize the license data header
  1492. //
  1493. pLicenseHeader = ( PRNS_SECURITY_HEADER )pOutBuffer;
  1494. //
  1495. // Indicate this is a licensing packet and then cheat and sneak
  1496. // in the flag that indicates the client should encrypt all
  1497. // licensing data sent to the server (early capabilities)
  1498. //
  1499. pLicenseHeader->flags = RNS_SEC_LICENSE_PKT |
  1500. RDP_SEC_LICENSE_ENCRYPT_CS;
  1501. pLicenseHeader->flagsHi = ( WORD )pSdIoctl->InputBufferLength;
  1502. //
  1503. // copy the data over
  1504. //
  1505. ASSERT( NULL != pOutBuffer );
  1506. memcpy( pOutBuffer + sizeof( RNS_SECURITY_HEADER ),
  1507. pSdIoctl->InputBuffer,
  1508. pSdIoctl->InputBufferLength );
  1509. }
  1510. else
  1511. {
  1512. if (STATUS_SUCCESS == SM_AllocBuffer(pTSWd->pSmInfo, (PPVOID) &pOutBuffer, pSdIoctl->InputBufferLength, TRUE, FALSE))
  1513. {
  1514. memcpy(pOutBuffer, (PBYTE)pSdIoctl->InputBuffer, pSdIoctl->InputBufferLength);
  1515. }
  1516. else {
  1517. TRC_ERR((TB, "FAILED to alloc license data buffer"));
  1518. status = STATUS_NO_MEMORY;
  1519. break;
  1520. }
  1521. }
  1522. //
  1523. // clear the incoming data event
  1524. //
  1525. KeClearEvent(pLicenseHandle->pDataEvent);
  1526. //
  1527. // send the data in the input buffer
  1528. //
  1529. if (encrypingLicToCli)
  1530. {
  1531. rc = SM_SendData(pTSWd->pSmInfo, pOutBuffer, pSdIoctl->InputBufferLength,
  1532. TS_HIGHPRIORITY, 0, FALSE, RNS_SEC_LICENSE_PKT | RDP_SEC_LICENSE_ENCRYPT_CS | RNS_SEC_ENCRYPT, FALSE);
  1533. }
  1534. else
  1535. {
  1536. rc = NM_SendData(pTSWd->pNMInfo, (BYTE *)pOutBuffer,
  1537. pSdIoctl->InputBufferLength + sizeof(RNS_SECURITY_HEADER),
  1538. TS_HIGHPRIORITY, 0, FALSE);
  1539. }
  1540. if (!rc)
  1541. {
  1542. TRC_ERR( ( TB, "Failed to send licensing data" ) );
  1543. status = STATUS_NET_WRITE_FAULT;
  1544. }
  1545. }
  1546. break;
  1547. /********************************************************************/
  1548. /* Indicate that the licensing protocol has completed.
  1549. /********************************************************************/
  1550. case IOCTL_ICA_STACK_LICENSE_PROTOCOL_COMPLETE:
  1551. {
  1552. PULONG pResult;
  1553. //
  1554. // validate input parameters
  1555. //
  1556. ASSERT( NULL != pSdIoctl->InputBuffer );
  1557. ASSERT( 0 < pSdIoctl->InputBufferLength );
  1558. if( ( NULL == pSdIoctl->InputBuffer ) ||
  1559. ( 0 >= pSdIoctl->InputBufferLength ) )
  1560. {
  1561. TRC_ERR( ( TB, "invalid Licensing IOCTL parameters" ) );
  1562. status = STATUS_INVALID_PARAMETER;
  1563. break;
  1564. }
  1565. //
  1566. // Tell SM if the client license has been validated successfully
  1567. //
  1568. pResult = ( PULONG )( pSdIoctl->InputBuffer );
  1569. if( LICENSE_PROTOCOL_SUCCESS == ( *pResult ) )
  1570. {
  1571. SM_LicenseOK(pTSWd->pSmInfo);
  1572. }
  1573. }
  1574. break;
  1575. /********************************************************************/
  1576. /* Indicate to retrieve the licensing data that was previously
  1577. /* cached.
  1578. /********************************************************************/
  1579. case IOCTL_ICA_STACK_GET_LICENSE_DATA:
  1580. {
  1581. PLicense_Handle pLicenseHandle = ( PLicense_Handle )pTSWd->pSLicenseHandle;
  1582. //
  1583. // validate input parameters
  1584. //
  1585. if ((NULL == pSdIoctl->OutputBuffer) ||
  1586. (NULL == pLicenseHandle))
  1587. {
  1588. pSdIoctl->BytesReturned = 0;
  1589. status = STATUS_INVALID_PARAMETER;
  1590. break;
  1591. }
  1592. //
  1593. // check that there's actually cached data
  1594. //
  1595. if( NULL == pLicenseHandle->pCacheBuf )
  1596. {
  1597. pSdIoctl->BytesReturned = 0;
  1598. status = STATUS_NO_DATA_DETECTED;
  1599. break;
  1600. }
  1601. if( pSdIoctl->OutputBufferLength < pLicenseHandle->cbCacheBuf )
  1602. {
  1603. pSdIoctl->BytesReturned = 0;
  1604. status = STATUS_BUFFER_TOO_SMALL;
  1605. break;
  1606. }
  1607. //
  1608. // copy the cached data and free the cached data buffer
  1609. //
  1610. memcpy(pSdIoctl->OutputBuffer,
  1611. pLicenseHandle->pCacheBuf,
  1612. pLicenseHandle->cbCacheBuf );
  1613. pSdIoctl->BytesReturned = pLicenseHandle->cbCacheBuf;
  1614. ExFreePool( pLicenseHandle->pCacheBuf );
  1615. pLicenseHandle->pCacheBuf = NULL;
  1616. }
  1617. break;
  1618. #endif // #ifdef USE_LICENSE
  1619. /********************************************************************/
  1620. /* shadow only IOCTLS */
  1621. /********************************************************************/
  1622. // Pass all relevent stack data from the client's primary stack to the
  1623. // target's shadow stack.
  1624. case IOCTL_ICA_STACK_QUERY_MODULE_DATA:
  1625. TRC_ALT((TB, "IOCTL_ICA_STACK_QUERY_MODULE_DATA(%p) - stack class %d",
  1626. pTSWd, pTSWd->StackClass));
  1627. if ((pTSWd->StackClass == Stack_Primary) ||
  1628. (pTSWd->StackClass == Stack_Console)) {
  1629. status = WDWGetModuleData(pTSWd, pSdIoctl);
  1630. }
  1631. break;
  1632. // Pass all relevant capabilities data from the client to the shadow
  1633. // target display driver.
  1634. case IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA:
  1635. PTSHARE_VIRTUAL_MODULE_DATA pVirtModuleData;
  1636. PTS_COMBINED_CAPABILITIES pCaps;
  1637. PTS_GENERAL_CAPABILITYSET pGenCapSet;
  1638. unsigned capsLength;
  1639. ShareClass * dcShare;
  1640. dcShare = (ShareClass *)(pTSWd->dcShare);
  1641. dcShare->SC_GetCombinedCapabilities(SC_REMOTE_PERSON_ID,
  1642. &capsLength, &pCaps);
  1643. if (pCaps != NULL) {
  1644. pGenCapSet = (PTS_GENERAL_CAPABILITYSET) WDW_GetCapSet(
  1645. pTSWd, TS_CAPSETTYPE_GENERAL, pCaps, capsLength);
  1646. if (pGenCapSet != NULL) {
  1647. // update the compression capability
  1648. if (pTSWd->bCompress) {
  1649. pGenCapSet->extraFlags |= TS_SHADOW_COMPRESSION_LEVEL;
  1650. pGenCapSet->generalCompressionLevel = (TSUINT16)pTSWd->pMPPCContext->ClientComprType;
  1651. }
  1652. }
  1653. if (pSdIoctl->OutputBufferLength >=
  1654. (capsLength + sizeof(TSHARE_VIRTUAL_MODULE_DATA) - 1)) {
  1655. pVirtModuleData = (PTSHARE_VIRTUAL_MODULE_DATA) pSdIoctl->OutputBuffer;
  1656. pVirtModuleData->capsLength = capsLength;
  1657. memcpy(&pVirtModuleData->combinedCapabilities,
  1658. pCaps, capsLength);
  1659. }
  1660. else {
  1661. status = STATUS_BUFFER_OVERFLOW;
  1662. }
  1663. }
  1664. else {
  1665. status = STATUS_NO_MEMORY;
  1666. }
  1667. pSdIoctl->BytesReturned = capsLength +
  1668. sizeof(TSHARE_VIRTUAL_MODULE_DATA) - 1;
  1669. TRC_ALT((TB, "IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA: rc=%lx, in=%ld, out=%ld",
  1670. status, pSdIoctl->OutputBufferLength, pSdIoctl->BytesReturned));
  1671. break;
  1672. case IOCTL_WDTS_DD_SHADOW_CONNECT:
  1673. {
  1674. if (pSdIoctl->InputBuffer &&
  1675. (((PTSHARE_DD_CONNECT_IN)pSdIoctl->InputBuffer)->pShm)) {
  1676. WDW_CHECK_SHM(
  1677. (((PTSHARE_DD_CONNECT_IN)pSdIoctl->InputBuffer)->pShm));
  1678. TRC_ALT((TB, "++TSHARE_DD_SHADOW_CONNECT(%p) - stack class %d",
  1679. pTSWd, pTSWd->StackClass));
  1680. status = WDWDDShadowConnect(pTSWd, pSdIoctl);
  1681. TRC_ALT((TB, "--TSHARE_DD_SHADOW_CONNECT(%p) - stack class %d",
  1682. pTSWd, pTSWd->StackClass));
  1683. WDW_CHECK_SHM(
  1684. (((PTSHARE_DD_CONNECT_IN)pSdIoctl->InputBuffer)->pShm));
  1685. }
  1686. else {
  1687. status = STATUS_INVALID_PARAMETER;
  1688. }
  1689. }
  1690. break;
  1691. #ifdef DC_HICOLOR
  1692. // Maybe get the caps of the shadower
  1693. case IOCTL_WDTS_DD_QUERY_SHADOW_CAPS:
  1694. {
  1695. // only respond to this if we're a shadow stack
  1696. if (pTSWd->StackClass == Stack_Shadow)
  1697. {
  1698. PTS_COMBINED_CAPABILITIES pCaps;
  1699. PTSHARE_VIRTUAL_MODULE_DATA pVMData = NULL;
  1700. unsigned capsLength;
  1701. ShareClass * dcShare;
  1702. dcShare = (ShareClass *)(pTSWd->dcShare);
  1703. if (pSdIoctl->OutputBufferLength >= sizeof(unsigned))
  1704. {
  1705. pVMData = (PTSHARE_VIRTUAL_MODULE_DATA)pSdIoctl->OutputBuffer;
  1706. }
  1707. dcShare->SC_GetCombinedCapabilities(SC_REMOTE_PERSON_ID,
  1708. &capsLength, &pCaps);
  1709. if (pCaps != NULL)
  1710. {
  1711. if (pSdIoctl->OutputBufferLength >=
  1712. (capsLength + sizeof(unsigned)))
  1713. {
  1714. memcpy(&pVMData->combinedCapabilities,
  1715. pCaps, capsLength);
  1716. }
  1717. else
  1718. {
  1719. status = STATUS_BUFFER_OVERFLOW;
  1720. }
  1721. }
  1722. else
  1723. {
  1724. status = STATUS_NO_MEMORY;
  1725. }
  1726. pSdIoctl->BytesReturned = capsLength + sizeof(unsigned);
  1727. if (pVMData)
  1728. {
  1729. pVMData->capsLength = capsLength;
  1730. }
  1731. TRC_ALT((TB, "IOCTL_WDTS_DD_QUERY_SHADOW_CAPS:" \
  1732. " rc=%lx, in=%ld, out=%ld",
  1733. status, pSdIoctl->OutputBufferLength,
  1734. pSdIoctl->BytesReturned));
  1735. }
  1736. else
  1737. {
  1738. TRC_ALT((TB, "IOCTL_WDTS_DD_QUERY_SHADOW_CAPS: " \
  1739. "not shadow stack so ignoring"));
  1740. TRC_ALT((TB, " rc=%lx, in=%ld, out=%ld",
  1741. status, pSdIoctl->OutputBufferLength,
  1742. pSdIoctl->BytesReturned));
  1743. }
  1744. }
  1745. break;
  1746. case IOCTL_WDTS_DD_SHADOW_SYNCHRONIZE:
  1747. {
  1748. ShareClass * dcShare;
  1749. PTS_COMBINED_CAPABILITIES pCaps;
  1750. unsigned capsLen;
  1751. if (pSdIoctl->InputBuffer &&
  1752. (((PTSHARE_DD_SHADOWSYNC_IN)pSdIoctl->InputBuffer)->pShm)) {
  1753. WDW_CHECK_SHM(
  1754. (((PTSHARE_DD_SHADOWSYNC_IN)pSdIoctl->InputBuffer)->pShm));
  1755. // synchronize this stack, this is required so that OE2 will match up
  1756. // for both shadow client and target.
  1757. dcShare = (ShareClass *)(pTSWd->dcShare);
  1758. pCaps = ((PTSHARE_DD_SHADOWSYNC_IN)pSdIoctl->InputBuffer)->pShadowCaps;
  1759. capsLen = ((PTSHARE_DD_SHADOWSYNC_IN)pSdIoctl->InputBuffer)->capsLen;
  1760. dcShare->SC_ShadowSyncShares(pCaps, capsLen);
  1761. TRC_ALT((TB, "Synchronized share for stack [%ld]", pTSWd->StackClass));
  1762. WDW_CHECK_SHM(
  1763. (((PTSHARE_DD_SHADOWSYNC_IN)pSdIoctl->InputBuffer)->pShm));
  1764. }
  1765. else {
  1766. status = STATUS_INVALID_PARAMETER;
  1767. }
  1768. }
  1769. break;
  1770. #else
  1771. case IOCTL_WDTS_DD_SHADOW_SYNCHRONIZE:
  1772. {
  1773. ShareClass * dcShare;
  1774. if (pSdIoctl->InputBuffer &&
  1775. (((PTSHARE_DD_SHADOWSYNC_IN)pSdIoctl->InputBuffer)->pShm)) {
  1776. WDW_CHECK_SHM(
  1777. (((PTSHARE_DD_SHADOWSYNC_IN)pSdIoctl->InputBuffer)->pShm));
  1778. // synchronize this stack, this is required so that OE2 will match up
  1779. // for both shadow client and target.
  1780. dcShare = (ShareClass *)(pTSWd->dcShare);
  1781. dcShare->SC_ShadowSyncShares();
  1782. TRC_ALT((TB, "Synchronized share for stack [%ld]", pTSWd->StackClass));
  1783. WDW_CHECK_SHM(
  1784. (((PTSHARE_DD_SHADOWSYNC_IN)pSdIoctl->InputBuffer)->pShm));
  1785. }
  1786. else {
  1787. status = STATUS_INVALID_PARAMETER;
  1788. }
  1789. }
  1790. break;
  1791. #endif
  1792. case IOCTL_WDTS_DD_SHADOW_DISCONNECT:
  1793. {
  1794. if (pSdIoctl->InputBuffer &&
  1795. (((PTSHARE_DD_DISCONNECT_IN)pSdIoctl->InputBuffer)->pShm)) {
  1796. WDW_CHECK_SHM(
  1797. (((PTSHARE_DD_DISCONNECT_IN)pSdIoctl->InputBuffer)->pShm));
  1798. status = WDWDDShadowDisconnect(pTSWd, pSdIoctl);
  1799. WDW_CHECK_SHM(
  1800. (((PTSHARE_DD_DISCONNECT_IN)pSdIoctl->InputBuffer)->pShm));
  1801. }
  1802. else {
  1803. status = STATUS_INVALID_PARAMETER;
  1804. }
  1805. }
  1806. break;
  1807. case IOCTL_ICA_STACK_REGISTER_HOTKEY :
  1808. {
  1809. PICA_STACK_HOTKEY pHotkey = (PICA_STACK_HOTKEY) pSdIoctl->InputBuffer;
  1810. if (pHotkey->HotkeyVk) {
  1811. pTSWd->shadowState = SHADOW_CLIENT;
  1812. pTSWd->HotkeyVk = pHotkey->HotkeyVk;
  1813. pTSWd->HotkeyModifiers = pHotkey->HotkeyModifiers;
  1814. TRC_ALT((TB, "IOCTL_ICA_STACK_REGISTER_HOTKEY - Enable Vk(%ld, %lx)",
  1815. pHotkey->HotkeyVk, pHotkey->HotkeyModifiers));
  1816. // Allocate and initialize a physical key state array
  1817. status = KeyboardSetKeyState(pTSWd, &pTSWd->pgafPhysKeyState);
  1818. if (NT_SUCCESS(status)) {
  1819. TRC_ALT((TB, "Allocated phys key state"));
  1820. }
  1821. else {
  1822. TRC_ALT((TB, "Failed to alloc phys key states: %lx", status));
  1823. }
  1824. // VCs don't work when shadowing. Tell VC subsystem to
  1825. // suspend now.
  1826. WDWVCMessage(pTSWd, CHANNEL_FLAG_SUSPEND);
  1827. }
  1828. else
  1829. {
  1830. pTSWd->shadowState = SHADOW_NONE;
  1831. pTSWd->HotkeyVk = 0;
  1832. pTSWd->HotkeyModifiers = 0;
  1833. TRC_ALT((TB, "IOCTL_ICA_STACK_REGISTER_HOTKEY - Disable"));
  1834. if (pTSWd->pShadowInfo != NULL) {
  1835. TRC_ALT((TB, "Primary client stack freeing reassembly info [%p]",
  1836. pTSWd->pShadowInfo));
  1837. COM_Free(pTSWd->pShadowInfo);
  1838. pTSWd->pShadowInfo = NULL;
  1839. }
  1840. // VCs don't work when shadowing. Tell VC subsystem to
  1841. // resume now.
  1842. WDWVCMessage(pTSWd, CHANNEL_FLAG_RESUME);
  1843. }
  1844. }
  1845. break;
  1846. case IOCTL_WDTS_DD_GET_BITMAP_KEYDATABASE:
  1847. {
  1848. ShareClass *dcShare;
  1849. PTSHARE_DD_BITMAP_KEYDATABASE_OUT pKDBOut =
  1850. (PTSHARE_DD_BITMAP_KEYDATABASE_OUT) pSdIoctl->OutputBuffer;
  1851. dcShare = (ShareClass *)(pTSWd->dcShare);
  1852. TRC_NRM((TB, "DD tries to get keydatabase\n"));
  1853. if (dcShare != NULL) {
  1854. // We have a valid share class, get the key database
  1855. dcShare->SBC_GetBitmapKeyDatabase(&pKDBOut->bitmapKeyDatabaseSize,
  1856. &pKDBOut->bitmapKeyDatabase);
  1857. }
  1858. }
  1859. break;
  1860. #ifdef DC_DEBUG
  1861. case IOCTL_WDTS_DD_ICABREAKONDEBUGGER:
  1862. {
  1863. IcaBreakOnDebugger();
  1864. }
  1865. break;
  1866. #endif
  1867. /********************************************************************/
  1868. // Send KeepAlive PDU IOCTL
  1869. /********************************************************************/
  1870. case IOCTL_ICA_STACK_SEND_KEEPALIVE_PDU:
  1871. {
  1872. ShareClass *dcShare;
  1873. dcShare = (ShareClass *)(pTSWd->dcShare);
  1874. TRC_NRM((TB, "TermDD requests to send a keepalive pkt to client\n"));
  1875. if (dcShare != NULL) {
  1876. // We have a valid share class, send a keepalive pdu to client
  1877. dcShare->SC_KeepAlive();
  1878. }
  1879. }
  1880. break;
  1881. /********************************************************************/
  1882. // Load balancing IOCTLs.
  1883. /********************************************************************/
  1884. case IOCTL_TS_STACK_QUERY_LOAD_BALANCE_INFO:
  1885. {
  1886. TS_LOAD_BALANCE_INFO *pLBInfo =
  1887. (TS_LOAD_BALANCE_INFO *)pSdIoctl->OutputBuffer;
  1888. TRC_ASSERT((pSdIoctl->OutputBufferLength >=
  1889. sizeof(TS_LOAD_BALANCE_INFO)),
  1890. (TB,"Invalid output buf size %u for STACK_QUERY_LBINFO",
  1891. pSdIoctl->OutputBufferLength));
  1892. // We need to fill in the IOCTL info from the gathered client
  1893. // info packet and the initial capabilities.
  1894. pLBInfo->bClientSupportsRedirection =
  1895. pTSWd->bClientSupportsRedirection;
  1896. pLBInfo->bRequestedSessionIDFieldValid =
  1897. pTSWd->bRequestedSessionIDFieldValid;
  1898. pLBInfo->RequestedSessionID = pTSWd->RequestedSessionID;
  1899. pLBInfo->bUseSmartcardLogon = pTSWd->bUseSmartcardLogon;
  1900. pLBInfo->ProtocolType = PROTOCOL_RDP;
  1901. pLBInfo->bClientRequireServerAddr =
  1902. pTSWd->ClientRedirectionVersion > TS_CLUSTER_REDIRECTION_VERSION1 ? 0 : 1;
  1903. pLBInfo->ClientRedirectionVersion = pTSWd->ClientRedirectionVersion;
  1904. wcsncpy(pLBInfo->UserName, (WCHAR *)pTSWd->pInfoPkt->UserName,
  1905. sizeof(pLBInfo->UserName) / sizeof(WCHAR) - 1);
  1906. pLBInfo->UserName[sizeof(pLBInfo->UserName) / sizeof(WCHAR) - 1] =
  1907. L'\0';
  1908. wcsncpy(pLBInfo->Domain, (WCHAR *)pTSWd->pInfoPkt->Domain,
  1909. sizeof(pLBInfo->Domain) / sizeof(WCHAR) - 1);
  1910. pLBInfo->Domain[sizeof(pLBInfo->Domain) / sizeof(WCHAR) - 1] =
  1911. L'\0';
  1912. wcsncpy(pLBInfo->InitialProgram,
  1913. (WCHAR *)pTSWd->pInfoPkt->AlternateShell,
  1914. sizeof(pLBInfo->InitialProgram) / sizeof(WCHAR) - 1);
  1915. pLBInfo->InitialProgram[sizeof(pLBInfo->InitialProgram) /
  1916. sizeof(WCHAR) - 1] = L'\0';
  1917. break;
  1918. }
  1919. case IOCTL_TS_STACK_SEND_CLIENT_REDIRECTION:
  1920. {
  1921. BOOL rc;
  1922. TS_CLIENT_REDIRECTION_INFO *pRedirInfo =
  1923. (TS_CLIENT_REDIRECTION_INFO *)pSdIoctl->InputBuffer;
  1924. TRC_ASSERT((pSdIoctl->InputBufferLength >=
  1925. sizeof(TS_CLIENT_REDIRECTION_INFO)),
  1926. (TB,"Invalid input buf size %u for STACK_CLIENT_REDIR",
  1927. pSdIoctl->InputBufferLength));
  1928. if (pTSWd->ClientRedirectionVersion == TS_CLUSTER_REDIRECTION_VERSION1) {
  1929. RDP_SERVER_REDIRECTION_PACKET *pPkt;
  1930. PBYTE ServerName;
  1931. unsigned PktSize;
  1932. unsigned ServerNameLen;
  1933. // Get the server name length in bytes, including null.
  1934. ServerNameLen = *((ULONG UNALIGNED*)(pRedirInfo + 1));
  1935. ServerName = (PBYTE)(pRedirInfo + 1) + sizeof(ULONG);
  1936. // Calculate the PDU size.
  1937. PktSize = sizeof(RDP_SERVER_REDIRECTION_PACKET) + ServerNameLen -
  1938. sizeof(WCHAR);
  1939. // The client username/domain info resulted in an off-machine
  1940. // session to be redirected-to. We receive this IOCTL before
  1941. // the licensing protocll occurs, hence we need to send a
  1942. // non-data packet. If the client indicated support for
  1943. // redirection, it must know how to parse this type of packet.
  1944. status = NM_AllocBuffer(pTSWd->pNMInfo, (PPVOID)&pPkt,
  1945. PktSize, TRUE);
  1946. if ( STATUS_SUCCESS == status && pTSWd->hDomainKernel != NULL) {
  1947. // Fill in the packet fields.
  1948. pPkt->Flags = RDP_SEC_REDIRECTION_PKT;
  1949. pPkt->Length = (UINT16)PktSize;
  1950. pPkt->SessionID = pRedirInfo->SessionID;
  1951. memcpy(pPkt->ServerAddress, ServerName, ServerNameLen);
  1952. TRC_DBG((TB, "Client Redirection PDU V1, ServerName: %S, ServerNameLen: %d",
  1953. ServerName, ServerNameLen));
  1954. rc = NM_SendData(pTSWd->pNMInfo, (BYTE *)pPkt, PktSize,
  1955. TS_HIGHPRIORITY, 0, FALSE);
  1956. if (rc) {
  1957. TRC_ALT((TB, "Sent TS_SERVER_REDIRECT_PDU: %u", PktSize));
  1958. status = STATUS_SUCCESS;
  1959. }
  1960. else {
  1961. TRC_ERR((TB,"Failed to send redir PDU"));
  1962. status = STATUS_UNSUCCESSFUL;
  1963. }
  1964. }
  1965. else {
  1966. TRC_ERR((TB, "Failed to alloc %d bytes for redir PDU",
  1967. PktSize));
  1968. if (STATUS_SUCCESS == status) {
  1969. NM_FreeBuffer(pTSWd->pNMInfo, pPkt);
  1970. }
  1971. // prevent regression, keep original return code.
  1972. status = STATUS_UNSUCCESSFUL;
  1973. }
  1974. }
  1975. else if (pTSWd->ClientRedirectionVersion == TS_CLUSTER_REDIRECTION_VERSION2) {
  1976. RDP_SERVER_REDIRECTION_PACKET_V2 *pPkt;
  1977. unsigned PktSize, DataLen;
  1978. // Calculate the PDU size
  1979. DataLen = pSdIoctl->InputBufferLength - sizeof(TS_CLIENT_REDIRECTION_INFO);
  1980. PktSize = sizeof(RDP_SERVER_REDIRECTION_PACKET_V2) + DataLen;
  1981. // The client username/domain info resulted in an off-machine
  1982. // session to be redirected-to. We receive this IOCTL before
  1983. // the licensing protocll occurs, hence we need to send a
  1984. // non-data packet. If the client indicated support for
  1985. // redirection, it must know how to parse this type of packet.
  1986. status = NM_AllocBuffer(pTSWd->pNMInfo, (PPVOID)&pPkt,
  1987. PktSize, TRUE);
  1988. if ( STATUS_SUCCESS == status && pTSWd->hDomainKernel != NULL) {
  1989. // Fill in the packet fields.
  1990. pPkt->Flags = RDP_SEC_REDIRECTION_PKT2;
  1991. pPkt->Length = (UINT16)PktSize;
  1992. pPkt->SessionID = pRedirInfo->SessionID;
  1993. pPkt->RedirFlags = pRedirInfo->Flags;
  1994. memcpy(pPkt + 1, pRedirInfo + 1, DataLen);
  1995. TRC_DBG((TB, "Client Redirection PDU V2"));
  1996. rc = NM_SendData(pTSWd->pNMInfo, (BYTE *)pPkt, PktSize,
  1997. TS_HIGHPRIORITY, 0, FALSE);
  1998. if (rc) {
  1999. TRC_ALT((TB, "Sent TS_SERVER_REDIRECT_PDU: %u", PktSize));
  2000. status = STATUS_SUCCESS;
  2001. }
  2002. else {
  2003. TRC_ERR((TB,"Failed to send redir PDU"));
  2004. status = STATUS_UNSUCCESSFUL;
  2005. }
  2006. }
  2007. else {
  2008. TRC_ERR((TB, "Failed to alloc %d bytes for redir PDU",
  2009. PktSize));
  2010. if (STATUS_SUCCESS == status) {
  2011. NM_FreeBuffer(pTSWd->pNMInfo, pPkt);
  2012. }
  2013. // prevent regression, keep original return code.
  2014. status = STATUS_UNSUCCESSFUL;
  2015. }
  2016. }
  2017. else {
  2018. RDP_SERVER_REDIRECTION_PACKET_V3 *pPkt;
  2019. unsigned PktSize, DataLen;
  2020. // Calculate the PDU size
  2021. DataLen = pSdIoctl->InputBufferLength - sizeof(TS_CLIENT_REDIRECTION_INFO);
  2022. PktSize = sizeof(RDP_SERVER_REDIRECTION_PACKET_V3) + DataLen;
  2023. status = SM_AllocBuffer(pTSWd->pSmInfo, (PPVOID)&pPkt,
  2024. PktSize, TRUE, TRUE);
  2025. if ( STATUS_SUCCESS == status ) {
  2026. // Fill in the packet fields.
  2027. pPkt->Flags = RDP_SEC_REDIRECTION_PKT3;
  2028. pPkt->Length = (UINT16)PktSize;
  2029. pPkt->SessionID = pRedirInfo->SessionID;
  2030. pPkt->RedirFlags = pRedirInfo->Flags;
  2031. if (pTSWd->fDontDisplayLastUserName) {
  2032. pPkt->RedirFlags |= LB_DONTSTOREUSERNAME;
  2033. }
  2034. memcpy(pPkt + 1, pRedirInfo + 1, DataLen);
  2035. TRC_DBG((TB, "Client Redirection PDU V3"));
  2036. rc = SM_SendData(pTSWd->pSmInfo, (BYTE *)pPkt, PktSize,
  2037. TS_HIGHPRIORITY, 0, FALSE, RDP_SEC_REDIRECTION_PKT3, TRUE);
  2038. if (rc) {
  2039. TRC_NRM((TB, "Sent TS_SERVER_REDIRECT_PDU: %u", PktSize));
  2040. status = STATUS_SUCCESS;
  2041. }
  2042. else {
  2043. TRC_ERR((TB,"Failed to send redir PDU"));
  2044. status = STATUS_UNSUCCESSFUL;
  2045. }
  2046. }
  2047. else {
  2048. TRC_ERR((TB, "Failed to alloc %d bytes for redir PDU",
  2049. PktSize));
  2050. // prevent regression, keep original return code.
  2051. status = STATUS_UNSUCCESSFUL;
  2052. }
  2053. }
  2054. break;
  2055. }
  2056. /****************************************************************************/
  2057. /****************************************************************************/
  2058. /* Finally the IOCtls that we pass on to the rest of the stack without */
  2059. /* getting in the way. */
  2060. /****************************************************************************/
  2061. /****************************************************************************/
  2062. /********************************************************************/
  2063. /* This IOCtl indicates the connection is down. Tell MCS before */
  2064. /* forwarding the IOCtl */
  2065. /********************************************************************/
  2066. case IOCTL_ICA_STACK_CANCEL_IO :
  2067. {
  2068. MCSIcaStackCancelIo(pTSWd->hDomainKernel);
  2069. TRC_NRM((TB, "CancelIO - set WD dead"));
  2070. // Make sure that Domain.StatusDead is consistent with TSWd.dead
  2071. pTSWd->dead = TRUE;
  2072. ((PDomain)(pTSWd->hDomainKernel))->StatusDead = TRUE;
  2073. }
  2074. /********************************************************************/
  2075. /* NB NOTE NO BREAK here - we drop through deliberately. */
  2076. /********************************************************************/
  2077. /********************************************************************/
  2078. /* modem callback and some others we're not interested in but lower */
  2079. /* layers might be */
  2080. /********************************************************************/
  2081. case IOCTL_ICA_STACK_CALLBACK_INITIATE :
  2082. case IOCTL_ICA_STACK_CALLBACK_COMPLETE :
  2083. case IOCTL_ICA_STACK_CREATE_ENDPOINT :
  2084. case IOCTL_ICA_STACK_OPEN_ENDPOINT :
  2085. case IOCTL_ICA_STACK_CLOSE_ENDPOINT :
  2086. case IOCTL_ICA_STACK_CONNECTION_WAIT :
  2087. case IOCTL_ICA_STACK_CONNECTION_REQUEST : // required for shadowing
  2088. case IOCTL_ICA_STACK_QUERY_LOCALADDRESS :
  2089. {
  2090. status =
  2091. IcaCallNextDriver( pTSWd->pContext, SD$IOCTL, pSdIoctl );
  2092. TRC_DBG((TB,
  2093. "Chaining on IOCtl %#x (function %d): status %#x",
  2094. pSdIoctl->IoControlCode,
  2095. WDW_IOCTL_FUNCTION(pSdIoctl->IoControlCode),
  2096. status));
  2097. }
  2098. break;
  2099. // Returning bad status for this makes GRE ignore it.
  2100. case IOCTL_VIDEO_ENUM_MONITOR_PDO:
  2101. status = STATUS_DEVICE_NOT_READY;
  2102. break;
  2103. default:
  2104. {
  2105. TRC_ALT((TB, "UNKNOWN WdIoctl %#x (function %d): status %#x",
  2106. pSdIoctl->IoControlCode,
  2107. WDW_IOCTL_FUNCTION(pSdIoctl->IoControlCode),
  2108. status));
  2109. status =
  2110. IcaCallNextDriver( pTSWd->pContext, SD$IOCTL, pSdIoctl );
  2111. break;
  2112. }
  2113. }
  2114. DC_END_FN();
  2115. DC_EXIT_POINT:
  2116. return status;
  2117. }
  2118. /****************************************************************************/
  2119. /* Name: WD_RawWrite */
  2120. /* */
  2121. /* Purpose: Handle I/O writes to and from the client of a shadow operation*/
  2122. /* */
  2123. /* Params: IN pTSWd - Points to wd data structure */
  2124. /* INOUT pSdRawWrite - Points to a SD_RAWWRITE structure */
  2125. /* */
  2126. /* Operation: Forward the data to the client of this stack. */
  2127. /****************************************************************************/
  2128. NTSTATUS WD_RawWrite(PTSHARE_WD pTSWd, PSD_RAWWRITE pSdRawWrite)
  2129. {
  2130. PUCHAR pInBuffer;
  2131. PBYTE pOutBuffer;
  2132. ULONG newBytes;
  2133. BOOL bSuccess = TRUE;
  2134. NTSTATUS status;
  2135. DC_BEGIN_FN("WD_RawWrite");
  2136. pInBuffer = pSdRawWrite->pBuffer;
  2137. newBytes = pSdRawWrite->ByteCount;
  2138. status = SM_AllocBuffer(pTSWd->pSmInfo, (PPVOID) &pOutBuffer, newBytes, TRUE, FALSE);
  2139. if ( STATUS_SUCCESS == status ) {
  2140. memcpy(pOutBuffer, pInBuffer, newBytes);
  2141. bSuccess = SM_SendData(pTSWd->pSmInfo, pOutBuffer, newBytes,
  2142. PROT_PRIO_MISC, 0, FALSE, RNS_SEC_ENCRYPT, FALSE);
  2143. if (bSuccess) {
  2144. TRC_NRM((TB, "Sent shadow data to %s: %ld",
  2145. (pTSWd->StackClass == Stack_Primary) ? "client" : "target",
  2146. newBytes));
  2147. status=STATUS_SUCCESS;
  2148. }
  2149. else {
  2150. TRC_ERR((TB, "FAILED to Send shadow data to %s: %ld",
  2151. (pTSWd->StackClass == Stack_Primary) ? "client" : "target",
  2152. newBytes));
  2153. status = STATUS_UNEXPECTED_IO_ERROR;
  2154. }
  2155. }
  2156. else {
  2157. TRC_ERR((TB, "FAILED to alloc shadow buffer for %s: %ld",
  2158. (pTSWd->StackClass == Stack_Primary) ? "client" : "target",
  2159. newBytes));
  2160. // prevent regression, keep original return code.
  2161. status = STATUS_NO_MEMORY;
  2162. }
  2163. DC_END_FN();
  2164. return status;
  2165. }
  2166. /****************************************************************************/
  2167. /* Name: WDWNewShareClass */
  2168. /* */
  2169. /* Purpose: Create a new ShareClass object */
  2170. /****************************************************************************/
  2171. NTSTATUS WDWNewShareClass(PTSHARE_WD pTSWd)
  2172. {
  2173. NTSTATUS status = STATUS_SUCCESS;
  2174. ShareClass *pSC;
  2175. DC_BEGIN_FN("WDWNewShareClass");
  2176. #ifdef DC_HICOLOR
  2177. pSC = new ShareClass(pTSWd, pTSWd->desktopHeight, pTSWd->desktopWidth,
  2178. pTSWd->desktopBpp, pTSWd->pSmInfo);
  2179. #else
  2180. pSC = new ShareClass(pTSWd, pTSWd->desktopHeight, pTSWd->desktopWidth,
  2181. 8, pTSWd->pSmInfo);
  2182. #endif
  2183. if (pSC != NULL) {
  2184. TRC_NRM((TB, "Created Share Class"));
  2185. pTSWd->dcShare = (PVOID)pSC;
  2186. }
  2187. else {
  2188. TRC_ERR((TB, "Failed to create Share Class"));
  2189. status = STATUS_NO_MEMORY;
  2190. }
  2191. DC_END_FN();
  2192. return status;
  2193. } /* WDWNewShareClass */
  2194. /****************************************************************************/
  2195. /* Name: WDWDeleteShareClass */
  2196. /* */
  2197. /* Purpose: Delete a Share Class object */
  2198. /****************************************************************************/
  2199. void WDWDeleteShareClass(PTSHARE_WD pTSWd)
  2200. {
  2201. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  2202. DC_BEGIN_FN("WDWDeleteShareClass");
  2203. TRC_ASSERT((pSC != NULL), (TB, "NULL Share Class"));
  2204. TRC_NRM((TB, "Delete Share Class"));
  2205. delete pSC;
  2206. pTSWd->dcShare = NULL;
  2207. DC_END_FN();
  2208. } /* WDWDeleteShareClass */
  2209. /****************************************************************************/
  2210. /* Name: WDWTermShareClass */
  2211. /* */
  2212. /* Purpose: Terminate the Share Class */
  2213. /****************************************************************************/
  2214. void WDWTermShareClass(PTSHARE_WD pTSWd)
  2215. {
  2216. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  2217. DC_BEGIN_FN("WDWTermShareClass");
  2218. TRC_ASSERT((pSC != NULL), (TB, "NULL Share Class"));
  2219. if (pTSWd->shareClassInit) {
  2220. pSC->DCS_Term();
  2221. TRC_NRM((TB, "Share Class terminated"));
  2222. pTSWd->shareClassInit = FALSE;
  2223. }
  2224. else {
  2225. TRC_ALT((TB, "Can't terminate uninitialized Share Core"));
  2226. }
  2227. DC_END_FN();
  2228. } /* WDWTermShareClass */
  2229. /****************************************************************************/
  2230. /* Name: WDWDDConnect */
  2231. /* */
  2232. /* Purpose: Process an IOCTL_WDTS_DD_CONNECT or */
  2233. /* IOCTL_WDTS_DD_SHADOW_CONNECT from the client. */
  2234. /* */
  2235. /* Params: IN pTSWd - pointer to WD struct */
  2236. /* INOUT PSD_IOCTL - pointer to received IOCtl */
  2237. /* IN reconnect - TRUE - this is a reconnect */
  2238. /* FALSE - this is a connect */
  2239. /* */
  2240. /* Operation: Save the frame buffer pointer */
  2241. /* Initialize the share core (will start to bring the share up) */
  2242. /* Return the required pointers to the DD. */
  2243. /****************************************************************************/
  2244. NTSTATUS WDWDDConnect(PTSHARE_WD pTSWd, PSD_IOCTL pSdIoctl, BOOL reconnect)
  2245. {
  2246. NTSTATUS status = STATUS_UNSUCCESSFUL;
  2247. NTSTATUS waitStatus;
  2248. BOOL rc;
  2249. PTS_BITMAP_CAPABILITYSET pBitmapCaps;
  2250. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  2251. PTSHARE_DD_CONNECT_IN pIn = (PTSHARE_DD_CONNECT_IN)pSdIoctl->InputBuffer;
  2252. PTSHARE_DD_CONNECT_OUT pOut =
  2253. (PTSHARE_DD_CONNECT_OUT)pSdIoctl->OutputBuffer;
  2254. DC_BEGIN_FN("WDWDDConnect");
  2255. TRC_ASSERT((pSC != NULL), (TB, "NULL Share Class"));
  2256. // Check we're connected OK.
  2257. if (!pTSWd->connected) {
  2258. TRC_ERR((TB, "Not connected"));
  2259. status = STATUS_CONNECTION_DISCONNECTED;
  2260. DC_QUIT;
  2261. }
  2262. // Check we've been given a sensible IOCtl.
  2263. if ((pIn == NULL) ||
  2264. (pOut == NULL) ||
  2265. (pSdIoctl->InputBufferLength < sizeof(TSHARE_DD_CONNECT_IN)) ||
  2266. (pSdIoctl->OutputBufferLength < sizeof(TSHARE_DD_CONNECT_OUT)))
  2267. {
  2268. status = STATUS_BUFFER_TOO_SMALL;
  2269. TRC_ERR((TB, "A buffer not present or big enough, %p, %lu; %p, %lu",
  2270. pIn, pSdIoctl->InputBufferLength,
  2271. pOut, pSdIoctl->OutputBufferLength));
  2272. DC_QUIT;
  2273. }
  2274. // Check that the DD sizeof(SHM_SHARED_MEMORY) matches our expectations.
  2275. // If not, we have mismatched binaries.
  2276. if (pIn->DDShmSize != sizeof(SHM_SHARED_MEMORY)) {
  2277. DbgPrint("****** RDPWD: Mismatched DD/WD - DD Shm size=%u, WD=%u\n",
  2278. pIn->DDShmSize, sizeof(SHM_SHARED_MEMORY));
  2279. return STATUS_INVALID_PARAMETER;
  2280. }
  2281. // Set returned buffer length.
  2282. pSdIoctl->BytesReturned = sizeof(TSHARE_DD_CONNECT_OUT);
  2283. // Increment the loadcount
  2284. pTSWd->shareId = InterlockedIncrement(&WD_ShareId);
  2285. ((PSHM_SHARED_MEMORY) (pIn->pShm))->shareId = pTSWd->shareId;
  2286. // Now get the share core initialized or reconnected.
  2287. if (reconnect) {
  2288. // Restore the timer info.
  2289. TRC_NRM((TB, "Reconnect Share Core"));
  2290. pTSWd->ritTimer = pIn->pKickTimer;
  2291. WDW_StartRITTimer(pTSWd, pTSWd->interactiveDelay);
  2292. }
  2293. else {
  2294. // Check for re-initialization.
  2295. // This is now legal with console disconnect.
  2296. // if (pTSWd->shareClassInit)
  2297. // {
  2298. //
  2299. // if (pTSWd->StackClass != Stack_Console)
  2300. // {
  2301. // TRC_ERR((TB, "Re-initialization - fail it"));
  2302. // status = STATUS_UNSUCCESSFUL;
  2303. // DC_QUIT;
  2304. // }
  2305. // else
  2306. // {
  2307. // TRC_ALT((TB, "Re-initialize console stack"));
  2308. // }
  2309. // }
  2310. //Make sure the sbcKeyDatabase is freed before initialization
  2311. if (pTSWd->shareClassInit)
  2312. {
  2313. pSC->SBC_FreeBitmapKeyDatabase();
  2314. }
  2315. // Initialize the Share Core.
  2316. TRC_NRM((TB, "Initialize Share Core"));
  2317. pSC->m_pShm = (SHM_SHARED_MEMORY *)pIn->pShm;
  2318. rc = pSC->DCS_Init(pTSWd, pTSWd->pSmInfo);
  2319. pSC->m_pShm = NULL;
  2320. if (rc) {
  2321. // Initialized OK
  2322. TRC_NRM((TB, "Share Class initialized, rc %d", rc));
  2323. pTSWd->shareClassInit = TRUE;
  2324. }
  2325. else {
  2326. TRC_ERR((TB, "Failed to initialize Share Class"));
  2327. status = STATUS_UNSUCCESSFUL;
  2328. DC_QUIT;
  2329. }
  2330. }
  2331. // If this is the primary stack, tell the display driver the desktop
  2332. // width/height we need to use.
  2333. if ((pTSWd->StackClass == Stack_Primary) ||
  2334. (pTSWd->StackClass == Stack_Console)) {
  2335. pOut->desktopHeight = pTSWd->desktopHeight;
  2336. pOut->desktopWidth = pTSWd->desktopWidth;
  2337. // Share's on its way up, so give the key values back to the DD.
  2338. pOut->pTSWd = (PVOID)pTSWd;
  2339. pOut->pProtocolStatus = pTSWd->pProtocolStatus;
  2340. TRC_ERR((TB, "Stored pTSWD %p, protocol status %p",
  2341. pTSWd, pTSWd->pProtocolStatus));
  2342. }
  2343. else {
  2344. // For shadow connects, the DD tells the shadow WD the width/height
  2345. // of the shadow target's desktop such that input from the shadow client
  2346. // can be scaled appropriately.
  2347. /********************************************************************/
  2348. /* See if the shadowing client supports dynamic resizing. First we */
  2349. /* need to extract the bitmap caps from the connect data */
  2350. /********************************************************************/
  2351. pBitmapCaps = (PTS_BITMAP_CAPABILITYSET) WDW_GetCapSet(
  2352. pTSWd,
  2353. TS_CAPSETTYPE_BITMAP,
  2354. &pIn->pVirtModuleData->combinedCapabilities,
  2355. pIn->pVirtModuleData->capsLength);
  2356. /********************************************************************/
  2357. /* If we found the bitmap caps, and the client does support dynamic */
  2358. /* resizing, then just go ahead and assign the size. */
  2359. /********************************************************************/
  2360. if (pBitmapCaps &&
  2361. (pBitmapCaps->desktopResizeFlag == TS_CAPSFLAG_SUPPORTED))
  2362. {
  2363. TRC_ALT((TB, "Client supports dynamic resizing"));
  2364. pTSWd->desktopHeight = pIn->desktopHeight;
  2365. pTSWd->desktopWidth = pIn->desktopWidth;
  2366. pSC->m_desktopHeight = pIn->desktopHeight;
  2367. pSC->m_desktopWidth = pIn->desktopWidth;
  2368. }
  2369. /********************************************************************/
  2370. /* If the client does NOT support dynamic resizing, then make sure */
  2371. /* that the shadower client is at least as big as the shadow target */
  2372. /* client - or the shadower client will trap */
  2373. /********************************************************************/
  2374. else if ((pTSWd->desktopHeight >= pIn->desktopHeight) &&
  2375. (pTSWd->desktopWidth >= pIn->desktopWidth)) {
  2376. pTSWd->desktopHeight = pIn->desktopHeight;
  2377. pTSWd->desktopWidth = pIn->desktopWidth;
  2378. pSC->m_desktopHeight = pIn->desktopHeight;
  2379. pSC->m_desktopWidth = pIn->desktopWidth;
  2380. }
  2381. else {
  2382. TRC_ERR((TB, "Rejecting attempt to shadow a higher res client"));
  2383. status = STATUS_UNSUCCESSFUL;
  2384. DC_QUIT;
  2385. }
  2386. #ifdef DC_HICOLOR
  2387. /********************************************************************/
  2388. /* Can the shadower cope with the target BPP?
  2389. /********************************************************************/
  2390. TRC_ALT((TB, "Shadower WD: %d bpp", pTSWd->desktopBpp ));
  2391. TRC_ALT((TB, "Target WD: %d bpp", pIn->desktopBpp ));
  2392. if (pTSWd->desktopBpp == pIn->desktopBpp) {
  2393. TRC_ALT((TB, "Color depths match - ok"));
  2394. pSC->m_desktopBpp = pIn->desktopBpp;
  2395. }
  2396. else {
  2397. TRC_ALT((TB, "Color depth mismatch"));
  2398. /****************************************************************/
  2399. /* Test the shadower's supported color depths */
  2400. /****************************************************************/
  2401. status = STATUS_SUCCESS;
  2402. switch (pIn->desktopBpp)
  2403. {
  2404. case 24:
  2405. {
  2406. if (pTSWd->supportedBpps & RNS_UD_24BPP_SUPPORT)
  2407. {
  2408. TRC_DBG((TB, "24bpp supported"));
  2409. break;
  2410. }
  2411. status = STATUS_UNSUCCESSFUL;
  2412. }
  2413. break;
  2414. case 16:
  2415. {
  2416. if (pTSWd->supportedBpps & RNS_UD_16BPP_SUPPORT)
  2417. {
  2418. TRC_DBG((TB, "16bpp supported"));
  2419. break;
  2420. }
  2421. status = STATUS_UNSUCCESSFUL;
  2422. }
  2423. break;
  2424. case 15:
  2425. {
  2426. if (pTSWd->supportedBpps & RNS_UD_15BPP_SUPPORT)
  2427. {
  2428. TRC_DBG((TB, "15bpp supported"));
  2429. break;
  2430. }
  2431. status = STATUS_UNSUCCESSFUL;
  2432. }
  2433. break;
  2434. case 8:
  2435. case 4:
  2436. {
  2437. TRC_DBG((TB, "8/4 bpp supported"));
  2438. }
  2439. break;
  2440. default:
  2441. {
  2442. TRC_ASSERT((FALSE), (TB, "Attempt to shadow unknown" \
  2443. " target color depth %d", pIn->desktopBpp));
  2444. }
  2445. break;
  2446. }
  2447. /****************************************************************/
  2448. /* Did they support it? */
  2449. /****************************************************************/
  2450. if (status == STATUS_UNSUCCESSFUL)
  2451. {
  2452. TRC_ERR((TB, "Rejecting shadow: unsupported color depth"));
  2453. DC_QUIT;
  2454. }
  2455. else
  2456. {
  2457. TRC_ALT((TB, "but client claims to cope..."));
  2458. pTSWd->desktopBpp = pIn->desktopBpp;
  2459. pSC->m_desktopBpp = pIn->desktopBpp;
  2460. }
  2461. }
  2462. #endif
  2463. }
  2464. /************************************************************************/
  2465. /* Share Core is no longer dead */
  2466. /************************************************************************/
  2467. // Make sure that Domain.StatusDead is consistent with TSWd.dead
  2468. pTSWd->dead = FALSE;
  2469. ((PDomain)(pTSWd->hDomainKernel))->StatusDead = FALSE;
  2470. SM_Dead(pTSWd->pSmInfo, FALSE);
  2471. /************************************************************************/
  2472. /* Clear the create event before creating the Share */
  2473. /************************************************************************/
  2474. KeClearEvent(pTSWd->pCreateEvent);
  2475. /************************************************************************/
  2476. /* Now create a Share */
  2477. /************************************************************************/
  2478. #ifdef DC_HICOLOR
  2479. TRC_ALT((TB, "Creating share at %d bpp", pTSWd->desktopBpp ));
  2480. #endif
  2481. rc = pSC->SC_CreateShare();
  2482. if (rc) {
  2483. // Initialized OK - save the Shared Memory pointer.
  2484. TRC_NRM((TB, "Share create started"));
  2485. }
  2486. else {
  2487. TRC_ERR((TB, "Failed to create Share"));
  2488. status = STATUS_CONNECTION_DISCONNECTED;
  2489. DC_QUIT;
  2490. }
  2491. /************************************************************************/
  2492. /* Wait for Share creation to complete before returning to TShareDD */
  2493. /************************************************************************/
  2494. TRC_NRM((TB, "Wait for Share Core to create the Share"));
  2495. waitStatus = WDW_WaitForConnectionEvent(pTSWd,
  2496. pTSWd->pCreateEvent,
  2497. 60000L);
  2498. /************************************************************************/
  2499. /* It is possible that the WD has been closed while we were waiting for */
  2500. /* the Share creation to complete. If this is the case, the Share */
  2501. /* class will have been deleted, so we can't continue. Return a */
  2502. /* failure to TShareDD. */
  2503. /************************************************************************/
  2504. if (pTSWd->dcShare == NULL)
  2505. {
  2506. TRC_ERR((TB, "Share Class ended while waiting for Share creation"));
  2507. status = STATUS_CONNECTION_DISCONNECTED;
  2508. DC_QUIT;
  2509. }
  2510. if (waitStatus == STATUS_TIMEOUT)
  2511. {
  2512. /********************************************************************/
  2513. /* The wait timed out - probably because the connection was */
  2514. /* disconnected before the Share was created. Tidy up the Share. */
  2515. /********************************************************************/
  2516. TRC_ERR((TB, "Timeout waiting for Share creation"));
  2517. pSC->m_pShm = (SHM_SHARED_MEMORY *)pIn->pShm;
  2518. pSC->SC_EndShare(FALSE);
  2519. pSC->m_pShm = NULL;
  2520. TRC_NRM((TB, "Share ended"));
  2521. status = STATUS_CONNECTION_DISCONNECTED;
  2522. // Can no longer accept input from RDPDD or PDMCS.
  2523. if (pTSWd->shadowState != SHADOW_CLIENT) {
  2524. // Make sure that Domain.StatusDead is consistent with TSWd.dead
  2525. pTSWd->dead = TRUE;
  2526. ((PDomain)(pTSWd->hDomainKernel))->StatusDead = TRUE;
  2527. SM_Dead(pTSWd->pSmInfo, TRUE);
  2528. }
  2529. else {
  2530. // The client shadow stack is disconnected from its display driver
  2531. // during a shadow, but must still be able to send/receive data
  2532. // to/from the target shadow stack and shadow client.
  2533. TRC_ALT((TB, "In shadow: leaving SM active"));
  2534. }
  2535. DC_QUIT;
  2536. }
  2537. /************************************************************************/
  2538. /* Check whether the Share was created OK. If not, quit now. */
  2539. /************************************************************************/
  2540. if (!pTSWd->shareCreated)
  2541. {
  2542. TRC_ERR((TB, "Share creation failed"));
  2543. status = STATUS_UNSUCCESSFUL;
  2544. DC_QUIT;
  2545. }
  2546. // We have successfully received the initial share creation PDUs.
  2547. // Update the received info for the DD to use.
  2548. pSC->SBC_GetBitmapKeyDatabase(&pOut->bitmapKeyDatabaseSize,
  2549. &pOut->bitmapKeyDatabase);
  2550. // For shadow connects, we need to add in the remote party to negotiate
  2551. // capabilities correctly.
  2552. if ((pSdIoctl->IoControlCode == IOCTL_WDTS_DD_SHADOW_CONNECT) &&
  2553. ((pTSWd->StackClass == Stack_Primary) ||
  2554. (pTSWd->StackClass == Stack_Console))) {
  2555. TRC_ALT((TB, "Negotiating shadow capabilities"));
  2556. status = pSC->SC_AddPartyToShare(
  2557. SC_SHADOW_PERSON_ID,
  2558. &pIn->pVirtModuleData->combinedCapabilities,
  2559. pIn->pVirtModuleData->capsLength);
  2560. if (status != STATUS_SUCCESS) {
  2561. TRC_ERR((TB, "Failed to negotiate shadow capabilities: %lx", status));
  2562. DC_QUIT;
  2563. }
  2564. }
  2565. /************************************************************************/
  2566. /* By now, the capabilities have been exchanged with the Client. Call */
  2567. /* the core to update SHM. */
  2568. /************************************************************************/
  2569. if ((pTSWd->StackClass == Stack_Primary) ||
  2570. (pTSWd->StackClass == Stack_Console)) {
  2571. TRC_NRM((TB, "Update SHM"));
  2572. pSC->m_pShm = (SHM_SHARED_MEMORY *)pIn->pShm;
  2573. pSC->DCS_UpdateShm();
  2574. pSC->m_pShm = NULL;
  2575. #ifdef DC_DEBUG
  2576. // Make sure trace config is updated in SHM.
  2577. pTSWd->trcShmNeedsUpdate = TRUE;
  2578. TRC_MaybeCopyConfig(pTSWd, &(((SHM_SHARED_MEMORY *)(pIn->pShm))->trc));
  2579. #endif
  2580. }
  2581. // All worked OK.
  2582. TRC_NRM((TB, "Share created"));
  2583. status = STATUS_SUCCESS;
  2584. DC_EXIT_POINT:
  2585. // record the individual connection status of each stack.
  2586. if (pTSWd->StackClass == Stack_Primary)
  2587. pOut->primaryStatus = status;
  2588. else
  2589. pOut->secondaryStatus |= status;
  2590. DC_END_FN();
  2591. return (status);
  2592. } /* WDWDDConnect */
  2593. /****************************************************************************/
  2594. /* Name: WDWDDDisconnect */
  2595. /* */
  2596. /* Purpose: Handle the disconnect IOCtl from the DD */
  2597. /* */
  2598. /* Params: IN pTSWd - pointer to WD struct */
  2599. /* INOUT PSD_IOCTL - pointer to received IOCtl */
  2600. /* IN bForce - used by shadow to force sending of a */
  2601. /* deactivate all PDU. */
  2602. /****************************************************************************/
  2603. NTSTATUS WDWDDDisconnect(PTSHARE_WD pTSWd, PSD_IOCTL pSdIoctl, BOOLEAN bForce)
  2604. {
  2605. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  2606. PTSHARE_DD_DISCONNECT_IN pIn =
  2607. (PTSHARE_DD_DISCONNECT_IN)pSdIoctl->InputBuffer;
  2608. DC_BEGIN_FN("WDWDDDisconnect");
  2609. TRC_ASSERT((pTSWd->dcShare != NULL),
  2610. (TB,"Got a disconnect with no share obj!"));
  2611. // Remove all references to WinStation resources.
  2612. WDWStopRITTimer(pTSWd);
  2613. pTSWd->ritTimer = NULL;
  2614. // Dump the bitmap cache key database to system memory. If this disconnect
  2615. // is in preparation for a reconnect, the database will allow us to
  2616. // preserve the bitmap cache state.
  2617. //
  2618. // If this is a disconnect in preparation for a shadow, then we can't save
  2619. // off the keys. For the shadow target, bShadowDisconnect will be set by
  2620. // the DD in DrvShadowConnect() processing. The shadow state for the shadow
  2621. // client will be other than NONE since we would have seen hotkey enable
  2622. // requests prior to the disconnect.
  2623. pSC->m_pShm = (SHM_SHARED_MEMORY *)pIn->pShm;
  2624. if (pSC->m_pShm != NULL) {
  2625. pSC->SBC_DumpBitmapKeyDatabase(!pIn->bShadowDisconnect &&
  2626. (pTSWd->shadowState == SHADOW_NONE));
  2627. }
  2628. // First of all, end the Share.
  2629. pSC->SC_EndShare(bForce);
  2630. TRC_NRM((TB, "Share ended"));
  2631. // Can no longer accept input from RDPDD or PDMCS.
  2632. if (pTSWd->shadowState != SHADOW_CLIENT) {
  2633. // Make sure that Domain.StatusDead is consistent with TSWd.dead
  2634. pTSWd->dead = TRUE;
  2635. ((PDomain)(pTSWd->hDomainKernel))->StatusDead = TRUE;
  2636. SM_Dead(pTSWd->pSmInfo, TRUE);
  2637. }
  2638. else {
  2639. // The client shadow stack is disconnected from its display driver
  2640. // during a shadow, but must still be able to send/receive data
  2641. // to/from the target shadow stack and shadow client.
  2642. TRC_ALT((TB, "In shadow: leaving SM active"));
  2643. }
  2644. // Tell Share Class to disconnect.
  2645. pSC->DCS_Disconnect();
  2646. TRC_NRM((TB, "Share Class disconnected"));
  2647. pSC->m_pShm = NULL;
  2648. DC_END_FN();
  2649. return STATUS_SUCCESS;
  2650. } /* WDWDDDisconnect */
  2651. /****************************************************************************/
  2652. /* Name: WDWDDShadowConnect */
  2653. /* */
  2654. /* Purpose: Process an IOCTL_WDTS_DD_SHADOW_CONNECT from the DD */
  2655. /* */
  2656. /* Params: IN pTSWd - pointer to WD struct */
  2657. /* INOUT PSD_IOCTL - pointer to received IOCtl */
  2658. /* */
  2659. /* Operation: Initialize either the primary stack or the shadow stack for */
  2660. /* a shadowing session. */
  2661. /****************************************************************************/
  2662. NTSTATUS WDWDDShadowConnect(PTSHARE_WD pTSWd, PSD_IOCTL pSdIoctl)
  2663. {
  2664. NTSTATUS status = STATUS_SUCCESS;
  2665. PTSHARE_DD_CONNECT_IN pIn = (PTSHARE_DD_CONNECT_IN)pSdIoctl->InputBuffer;
  2666. PTSHARE_DD_CONNECT_OUT pOut = (PTSHARE_DD_CONNECT_OUT)pSdIoctl->OutputBuffer;
  2667. PSHM_SHARED_MEMORY pShm = (PSHM_SHARED_MEMORY) pIn->pShm;
  2668. DC_BEGIN_FN("WDWDDShadowConnect");
  2669. switch (pTSWd->StackClass) {
  2670. case Stack_Primary:
  2671. case Stack_Console:
  2672. // Reconnect the primary stack
  2673. status = WDWDDConnect(pTSWd, pSdIoctl, TRUE);
  2674. if (NT_SUCCESS(status)) {
  2675. TRC_ALT((TB, "Primary target stack reconnected!"));
  2676. }
  2677. else {
  2678. TRC_ERR((TB, "Primary target stack could not reconnect: %lx)", status));
  2679. DC_QUIT;
  2680. }
  2681. // Set up the shadow data buffer. The primary stack will copy output to
  2682. // this location so all other shadow stacks can just squirt it.
  2683. #ifdef DC_HICOLOR
  2684. pTSWd->pShadowInfo = (PSHADOW_INFO)COM_Malloc(2 * WD_MAX_SHADOW_BUFFER);
  2685. #else
  2686. pTSWd->pShadowInfo = (PSHADOW_INFO)COM_Malloc(WD_MAX_SHADOW_BUFFER);
  2687. #endif
  2688. // Stash the shadow buffer so the DD can pass it to all shadow stacks
  2689. // via the Shm.
  2690. if (pTSWd->pShadowInfo != NULL) {
  2691. pTSWd->shadowState = SHADOW_TARGET;
  2692. memset(pTSWd->pShadowInfo, 0, sizeof(SHADOW_INFO));
  2693. pShm->pShadowInfo = pTSWd->pShadowInfo;
  2694. #ifdef DC_HICOLOR
  2695. TRC_ALT((TB, "Primary stack allocated shadow info: %p[%ld]",
  2696. pTSWd->pShadowInfo, 2 * WD_MAX_SHADOW_BUFFER));
  2697. #else
  2698. TRC_ALT((TB, "Primary stack allocated shadow info: %p[%ld]",
  2699. pTSWd->pShadowInfo, WD_MAX_SHADOW_BUFFER));
  2700. #endif
  2701. }
  2702. // Primary stack is really OK in this scenario, however it is fatal
  2703. // for the shadow stack
  2704. else {
  2705. pTSWd->pShadowInfo = NULL;
  2706. pShm->pShadowInfo = NULL;
  2707. pOut->secondaryStatus = STATUS_NO_MEMORY;
  2708. TRC_ERR((TB, "Could not allocate shadow data buffer"));
  2709. DC_QUIT;
  2710. }
  2711. break;
  2712. // Drive the shadow stack thru the normal connection phase
  2713. case Stack_Shadow:
  2714. status = WDWDDConnect(pTSWd, pSdIoctl, FALSE);
  2715. if (NT_SUCCESS(status)) {
  2716. TRC_ALT((TB, "Shadow stack connected!"));
  2717. }
  2718. else {
  2719. TRC_ERR((TB, "Shadow stack could not connect: %lx", status));
  2720. }
  2721. break;
  2722. default:
  2723. TRC_ERR((TB, "Unknown stack class: %ld", pTSWd->StackClass));
  2724. status = STATUS_INVALID_PARAMETER;
  2725. break;
  2726. }
  2727. DC_EXIT_POINT:
  2728. DC_END_FN();
  2729. return (status);
  2730. }
  2731. /****************************************************************************/
  2732. /* Name: WDWDDShadowDisconnect */
  2733. /* */
  2734. /* Purpose: Process an IOCTL_WDTS_DD_SHADOW_DISCONNECT from the DD */
  2735. /* */
  2736. /* Params: IN pTSWd - pointer to WD struct */
  2737. /* INOUT PSD_IOCTL - pointer to received IOCtl */
  2738. /* */
  2739. /* Operation: Stop shadowing on the primary stack. */
  2740. /****************************************************************************/
  2741. NTSTATUS WDWDDShadowDisconnect(PTSHARE_WD pTSWd, PSD_IOCTL pSdIoctl)
  2742. {
  2743. NTSTATUS status = STATUS_SUCCESS;
  2744. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  2745. PTSHARE_DD_DISCONNECT_IN pIn =
  2746. (PTSHARE_DD_DISCONNECT_IN)pSdIoctl->InputBuffer;
  2747. DC_BEGIN_FN("WDWDDShadowDisconnect");
  2748. switch (pTSWd->StackClass) {
  2749. // Deallocate the shadow buffer
  2750. case Stack_Primary:
  2751. case Stack_Console:
  2752. pTSWd->shadowState = SHADOW_NONE;
  2753. if (pTSWd->pShadowInfo != NULL)
  2754. COM_Free(pTSWd->pShadowInfo);
  2755. pTSWd->pShadowInfo = NULL;
  2756. if (pTSWd->bCompress == TRUE) {
  2757. unsigned MPPCCompressionLevel;
  2758. // Negotiate down to our highest level of compression support
  2759. // if we receive a larger number.
  2760. MPPCCompressionLevel =
  2761. (pTSWd->pInfoPkt->flags & RNS_INFO_COMPR_TYPE_MASK) >>
  2762. RNS_INFO_COMPR_TYPE_SHIFT;
  2763. if (MPPCCompressionLevel > PACKET_COMPR_TYPE_MAX)
  2764. MPPCCompressionLevel = PACKET_COMPR_TYPE_MAX;
  2765. // the compression history will be flushed
  2766. pTSWd->bFlushed = PACKET_FLUSHED;
  2767. // the compression will restart over
  2768. initsendcontext(pTSWd->pMPPCContext, MPPCCompressionLevel);
  2769. }
  2770. pSC->SC_RemovePartyFromShare(SC_SHADOW_PERSON_ID);
  2771. TRC_ALT((TB, "Update SHM after party left share"));
  2772. pSC->m_pShm = (SHM_SHARED_MEMORY *)pIn->pShm;
  2773. // Bump up the share ID to invalidate any old GRE cache entries for
  2774. // glyphs or brushes. This is necessary when RDP caches are destroyed
  2775. // since GRE may keep around the brush or font structure in its cache
  2776. pTSWd->shareId = InterlockedIncrement(&WD_ShareId);
  2777. pSC->m_pShm->shareId = pTSWd->shareId;
  2778. pSC->SC_Update();
  2779. pSC->DCS_UpdateShm();
  2780. pSC->m_pShm = NULL;
  2781. TRC_ALT((TB, "TSHARE_DD_SHADOW_DISCONNECT: Primary target stack"));
  2782. break;
  2783. // By the time this ioctl arrives TermDD should have already stopped echoing
  2784. // calls to the shadow stack.
  2785. case Stack_Shadow:
  2786. TRC_ERR((TB, "Shadow stack received an unexpected disconnect!"));
  2787. break;
  2788. default:
  2789. TRC_ERR((TB, "Unexpected stack class: %ld", pTSWd->StackClass));
  2790. break;
  2791. }
  2792. DC_END_FN();
  2793. return status;
  2794. }
  2795. /****************************************************************************/
  2796. /* Name: WDWUserLoggedOn */
  2797. /* */
  2798. /* Purpose: Notify the core that a user has logged on */
  2799. /****************************************************************************/
  2800. void WDWUserLoggedOn(PTSHARE_WD pTSWd, PSD_IOCTL pSdIoctl)
  2801. {
  2802. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  2803. DC_BEGIN_FN("WDWUserLoggedOn");
  2804. TRC_ASSERT((pSC != NULL),
  2805. (TB, "NULL Share Class"));
  2806. TRC_ASSERT((pSdIoctl->InputBufferLength == sizeof(LOGONINFO)),
  2807. (TB, "Bad LogonInfo"));
  2808. pSC->DCS_UserLoggedOn((PLOGONINFO)pSdIoctl->InputBuffer);
  2809. DC_END_FN();
  2810. } /* WDWUserLoggedOn */
  2811. /****************************************************************************/
  2812. /* Name: WDWKeyboardSetIndicators */
  2813. /* */
  2814. /* Purpose: Notify the core of new keyboard indicators */
  2815. /****************************************************************************/
  2816. void WDWKeyboardSetIndicators(PTSHARE_WD pTSWd)
  2817. {
  2818. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  2819. DC_BEGIN_FN("WDWUserLoggedOn");
  2820. TRC_ASSERT((pSC != NULL),
  2821. (TB, "NULL Share Class"));
  2822. pSC->DCS_WDWKeyboardSetIndicators();
  2823. DC_END_FN();
  2824. } /* WDWKeyboardSetIndicators */
  2825. /****************************************************************************/
  2826. /* Name: WDWKeyboardSetImeStatus */
  2827. /* */
  2828. /* Purpose: Notify the core of new ime status */
  2829. /****************************************************************************/
  2830. void WDWKeyboardSetImeStatus(PTSHARE_WD pTSWd)
  2831. {
  2832. ShareClass *dcShare = (ShareClass *)pTSWd->dcShare;
  2833. DC_BEGIN_FN("WDWKeyboardSetImeStatus");
  2834. TRC_ASSERT((dcShare != NULL),
  2835. (TB, "NULL Share Class"));
  2836. dcShare->DCS_WDWKeyboardSetImeStatus();
  2837. DC_END_FN();
  2838. } /* WDWKeyboardSetImeStatus */
  2839. /****************************************************************************/
  2840. /* Name: WDWSendBeep */
  2841. /* */
  2842. /* Purpose: Send a beep PDU to the client */
  2843. /* */
  2844. /* Params: IN pTSWd - pointer to WD struct */
  2845. /* INOUT PSD_IOCTL - pointer to received IOCtl */
  2846. /* */
  2847. /* Operation: Check validity of IOCtl & call through to UP. */
  2848. /****************************************************************************/
  2849. NTSTATUS WDWSendBeep(PTSHARE_WD pTSWd, PSD_IOCTL pSdIoctl)
  2850. {
  2851. NTSTATUS status = STATUS_UNSUCCESSFUL;
  2852. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  2853. DC_BEGIN_FN("WDWSendBeep");
  2854. if (pSdIoctl->InputBufferLength == sizeof(BEEP_SET_PARAMETERS) &&
  2855. pSdIoctl->InputBuffer != NULL) {
  2856. /************************************************************************/
  2857. /* Call into the Share Class to allocate and send the beep PDU */
  2858. /************************************************************************/
  2859. if (pSC != NULL && pTSWd->shareClassInit) {
  2860. if (pSC->UP_SendBeep(
  2861. ((PBEEP_SET_PARAMETERS)pSdIoctl->InputBuffer)->Duration,
  2862. ((PBEEP_SET_PARAMETERS)pSdIoctl->InputBuffer)->Frequency))
  2863. status = STATUS_SUCCESS;
  2864. }
  2865. pSdIoctl->BytesReturned = 0;
  2866. }
  2867. else {
  2868. TRC_ASSERT((TRUE), (TB,"Got Beep Ioctl but input buffer too small"));
  2869. }
  2870. DC_END_FN();
  2871. return status;
  2872. } /* WDWSendBeep */
  2873. /****************************************************************************/
  2874. /* Name: WDWGetModuleData */
  2875. /* */
  2876. /* Purpose: Processes an IOCTL_ICA_STACK_QUERY_MODULE_DATA from Termsrv. */
  2877. /* */
  2878. /* Params: IN pTSWd - pointer to WD struct */
  2879. /* INOUT PSD_IOCTL - pointer to received IOCtl */
  2880. /* */
  2881. /* Operation: return all the relevant conference creation info */
  2882. /****************************************************************************/
  2883. NTSTATUS WDWGetModuleData(PTSHARE_WD pTSWd, PSD_IOCTL pSdIoctl)
  2884. {
  2885. NTSTATUS status = STATUS_SUCCESS;
  2886. ShareClass *dcShare = (ShareClass *)pTSWd->dcShare;
  2887. PTSHARE_MODULE_DATA pModuleData = (PTSHARE_MODULE_DATA)
  2888. pSdIoctl->OutputBuffer;
  2889. PBYTE pData;
  2890. ULONG ulDataSize;
  2891. PRNS_UD_CS_CORE pCoreData;
  2892. PRNS_UD_CS_SEC pSecurityData;
  2893. DC_BEGIN_FN("WDWGetModuleData");
  2894. ulDataSize = sizeof(TSHARE_MODULE_DATA) - sizeof(RNS_UD_HEADER) +
  2895. sizeof(RNS_UD_CS_CORE) +
  2896. sizeof(RNS_UD_CS_SEC);
  2897. // Make sure the output buffer is big enough!
  2898. pSdIoctl->BytesReturned = ulDataSize;
  2899. if (pSdIoctl->OutputBufferLength < ulDataSize) {
  2900. status = STATUS_BUFFER_TOO_SMALL;
  2901. DC_QUIT;
  2902. }
  2903. pModuleData->ulLength = ulDataSize;
  2904. pModuleData->ulVersion = 2;
  2905. pModuleData->userDataLen = sizeof(RNS_UD_CS_CORE) + sizeof(RNS_UD_CS_SEC);
  2906. pData = (PBYTE) &pModuleData->userData;
  2907. // Client to server core data
  2908. pCoreData = (PRNS_UD_CS_CORE) pData;
  2909. pCoreData->header.type = RNS_UD_CS_CORE_ID;
  2910. pCoreData->header.length = sizeof(RNS_UD_CS_CORE);
  2911. pCoreData->version = RNS_UD_VERSION;
  2912. pCoreData->desktopWidth = (UINT16)pTSWd->desktopWidth;
  2913. pCoreData->desktopHeight = (UINT16)pTSWd->desktopHeight;
  2914. // Re-munge the color depth
  2915. switch (pTSWd->desktopBpp) {
  2916. case 8:
  2917. pCoreData->colorDepth = RNS_UD_COLOR_8BPP;
  2918. break;
  2919. case 4:
  2920. pCoreData->colorDepth = RNS_UD_COLOR_4BPP;
  2921. break;
  2922. #ifdef DC_HICOLOR
  2923. case 15:
  2924. pCoreData->colorDepth = RNS_UD_COLOR_16BPP_555;
  2925. break;
  2926. #endif
  2927. case 16:
  2928. pCoreData->colorDepth = RNS_UD_COLOR_16BPP_565;
  2929. break;
  2930. case 24:
  2931. pCoreData->colorDepth = RNS_UD_COLOR_24BPP;
  2932. break;
  2933. default:
  2934. status = STATUS_UNSUCCESSFUL;
  2935. DC_QUIT;
  2936. }
  2937. pCoreData->postBeta2ColorDepth = pCoreData->colorDepth;
  2938. #ifdef DC_HICOLOR
  2939. /************************************************************************/
  2940. /* Copy across the current color depth */
  2941. /************************************************************************/
  2942. pCoreData->highColorDepth = (TSUINT16)pTSWd->desktopBpp;
  2943. pCoreData->supportedColorDepths = (TSUINT16)pTSWd->supportedBpps;
  2944. #endif
  2945. // Other useful stuff from user data
  2946. pCoreData->version = pTSWd->version;
  2947. pCoreData->SASSequence = pTSWd->sas;
  2948. pCoreData->keyboardLayout = pTSWd->kbdLayout;
  2949. pCoreData->clientBuild = pTSWd->clientBuild;
  2950. memcpy(pCoreData->clientName, pTSWd->clientName, sizeof(pTSWd->clientName));
  2951. //Whistler post Beta2 - shadow loop fix
  2952. memcpy( pCoreData->clientDigProductId, pTSWd->clientDigProductId, sizeof( pTSWd->clientDigProductId ));
  2953. // FE data
  2954. pCoreData->keyboardType = pTSWd->keyboardType;
  2955. pCoreData->keyboardSubType = pTSWd->keyboardSubType;
  2956. pCoreData->keyboardFunctionKey = pTSWd->keyboardFunctionKey;
  2957. memcpy(pCoreData->imeFileName, pTSWd->imeFileName, sizeof(pTSWd->imeFileName));
  2958. // Win2000 Post Beta3 fields added
  2959. pCoreData->clientProductId = pTSWd->clientProductId;
  2960. pCoreData->serialNumber = pTSWd->serialNumber;
  2961. // client to server security data
  2962. pSecurityData = (PRNS_UD_CS_SEC) (pCoreData + 1);
  2963. pSecurityData->header.type = RNS_UD_CS_SEC_ID;
  2964. pSecurityData->header.length = sizeof(RNS_UD_CS_SEC);
  2965. SM_GetEncryptionMethods(pTSWd->pSmInfo, pSecurityData );
  2966. // UGH! Now copy this data in a redundant form so we won't break
  2967. // compatibility with TS5 B3.
  2968. memcpy(&pModuleData->clientCoreData, pCoreData, sizeof(RNS_UD_CS_CORE_V0));
  2969. memcpy(&pModuleData->clientSecurityData, pSecurityData, sizeof(RNS_UD_CS_SEC_V0));
  2970. MCSGetDefaultDomain(pTSWd->pContext,
  2971. &pModuleData->DomParams,
  2972. &pModuleData->MaxSendSize,
  2973. &pModuleData->MaxX224DataSize,
  2974. &pModuleData->X224SourcePort);
  2975. pModuleData->shareId = pTSWd->shareId;
  2976. DC_EXIT_POINT:
  2977. DC_END_FN();
  2978. return status;
  2979. } /* WDWGetModuleData */
  2980. /****************************************************************************/
  2981. /* Name: WDW_GetCapSet */
  2982. /* */
  2983. /* Purpose: Extract the specific capabilities from a combined */
  2984. /* capabilities set */
  2985. /* */
  2986. /* Returns: pointer to caps or NULL if not found */
  2987. /* */
  2988. /* Params: IN pTSWd - pointer to WD struct */
  2989. /* IN CapSetType - type of capability set */
  2990. /* IN pCombinedCaps - pointer to combined capabilites */
  2991. /* IN lengthCaps - length of supplied caps */
  2992. /* */
  2993. /* Operation: find the specific caps in supplied capability set */
  2994. /****************************************************************************/
  2995. PTS_CAPABILITYHEADER WDW_GetCapSet(
  2996. PTSHARE_WD pTSWd,
  2997. UINT32 CapSetType,
  2998. PTS_COMBINED_CAPABILITIES pCaps,
  2999. UINT32 capsLength)
  3000. {
  3001. PTS_CAPABILITYHEADER pCapsHeader = NULL;
  3002. UINT32 capsOffset;
  3003. DC_BEGIN_FN("WDW_GetCapSet");
  3004. /************************************************************************/
  3005. /* Set up the pointer to the first capability set, and check that there */
  3006. /* is at least one set of caps! */
  3007. /************************************************************************/
  3008. pCapsHeader = (PTS_CAPABILITYHEADER)pCaps->data;
  3009. capsOffset = sizeof(TS_COMBINED_CAPABILITIES) - 1;
  3010. if (capsOffset >= capsLength)
  3011. {
  3012. TRC_NRM((TB, "No Caps found"));
  3013. DC_QUIT;
  3014. }
  3015. /************************************************************************/
  3016. /* Now loop through all the caps, looking for the specified capabilities*/
  3017. /************************************************************************/
  3018. while (pCapsHeader->capabilitySetType != CapSetType)
  3019. {
  3020. /****************************************************************/
  3021. /* Add the length of this capability to the offset, to keep */
  3022. /* track of how much of the combined caps we have processed. */
  3023. /****************************************************************/
  3024. capsOffset += pCapsHeader->lengthCapability;
  3025. if (capsOffset >= capsLength)
  3026. {
  3027. TRC_NRM((TB, "Bitmap Caps not found"));
  3028. pCapsHeader = NULL;
  3029. break;
  3030. }
  3031. /****************************************************************/
  3032. /* Add the length of this capability to the header pointer, so */
  3033. /* it points to the next capability set. */
  3034. /****************************************************************/
  3035. pCapsHeader = (PTS_CAPABILITYHEADER)
  3036. (((PBYTE)pCapsHeader) + pCapsHeader->lengthCapability);
  3037. TRC_NRM((TB, "Next set: %u", pCapsHeader->capabilitySetType));
  3038. }
  3039. /************************************************************************/
  3040. /* pCapsHeader is either NULL or a pointer to the desired caps - which */
  3041. /* is what we want to return */
  3042. /************************************************************************/
  3043. DC_EXIT_POINT:
  3044. DC_END_FN();
  3045. return(pCapsHeader);
  3046. } /* WDW_GetCapSet */
  3047. /****************************************************************************/
  3048. /* Name: WDWGetDefaultCoreParams */
  3049. /* */
  3050. /* Purpose: Defaults the core params used by the shadow stacks */
  3051. /* */
  3052. /* Params: OUT pClientCoreData - WD core data */
  3053. /* */
  3054. /* Operation: Default the core params used by the shadow stacks */
  3055. /****************************************************************************/
  3056. NTSTATUS WDWGetDefaultCoreParams(PRNS_UD_CS_CORE pClientCoreData)
  3057. {
  3058. DC_BEGIN_FN("WDWGetDefaultCoreParams");
  3059. // Client to server core data
  3060. pClientCoreData->header.type = RNS_UD_CS_CORE_ID;
  3061. pClientCoreData->header.length = sizeof(RNS_UD_CS_CORE);
  3062. // Desktop parameters
  3063. pClientCoreData->desktopHeight = 640;
  3064. pClientCoreData->desktopWidth = 480;
  3065. pClientCoreData->colorDepth = RNS_UD_COLOR_8BPP;
  3066. pClientCoreData->postBeta2ColorDepth = RNS_UD_COLOR_8BPP;
  3067. #ifdef DC_HICOLOR
  3068. pClientCoreData->highColorDepth = 15;
  3069. pClientCoreData->supportedColorDepths = RNS_UD_24BPP_SUPPORT ||
  3070. RNS_UD_16BPP_SUPPORT ||
  3071. RNS_UD_15BPP_SUPPORT;
  3072. #endif
  3073. // Other useful stuff from user data
  3074. pClientCoreData->version = RNS_TERMSRV_40_UD_VERSION;
  3075. pClientCoreData->SASSequence = RNS_UD_SAS_NONE;
  3076. pClientCoreData->keyboardLayout = 0;
  3077. pClientCoreData->clientBuild = VER_PRODUCTBUILD;
  3078. memcpy(pClientCoreData->clientName, L"Passthru Stack", sizeof(L"Passthru Stack"));
  3079. //Whistler post Beta2 - shadow loop fix
  3080. pClientCoreData->clientDigProductId[0] = 0;
  3081. // FE data
  3082. pClientCoreData->keyboardType = 0;
  3083. pClientCoreData->keyboardSubType = 0;
  3084. pClientCoreData->keyboardFunctionKey = 0;
  3085. memset(pClientCoreData->imeFileName, 0, sizeof(pClientCoreData->imeFileName));
  3086. return STATUS_SUCCESS;
  3087. }
  3088. /****************************************************************************/
  3089. // Name: WDWSetConfigData
  3090. //
  3091. // Purpose: Sets the stack configuration/Policy settings from winstation
  3092. //
  3093. // Params: IN pConfigData
  3094. /****************************************************************************/
  3095. NTSTATUS WDWSetConfigData(PTSHARE_WD pTSWd, PICA_STACK_CONFIG_DATA pConfigData)
  3096. {
  3097. PSM_HANDLE_DATA pRealSMHandle = (PSM_HANDLE_DATA)pTSWd->pSmInfo;
  3098. DC_BEGIN_FN("WDWSetConfigData");
  3099. if (pConfigData->colorDepth == TS_24BPP_SUPPORT) {
  3100. pTSWd->maxServerBpp = 24;
  3101. }
  3102. else if (pConfigData->colorDepth == TS_16BPP_SUPPORT) {
  3103. pTSWd->maxServerBpp = 16;
  3104. }
  3105. else if (pConfigData->colorDepth == TS_15BPP_SUPPORT) {
  3106. pTSWd->maxServerBpp = 15;
  3107. }
  3108. else {
  3109. pTSWd->maxServerBpp = 8;
  3110. }
  3111. TRC_DBG((TB, "Max Color Depth support: %d", pTSWd->maxServerBpp));
  3112. pRealSMHandle->encryptionLevel = pConfigData->encryptionLevel;
  3113. pRealSMHandle->encryptAfterLogon =
  3114. (pConfigData->fDisableEncryption == 0) ? TRUE : FALSE;
  3115. TRC_DBG((TB, "Encryption after logon: %d", pRealSMHandle->encryptAfterLogon));
  3116. TRC_DBG((TB, "Encryption level: %d", pRealSMHandle->encryptionLevel));
  3117. pTSWd->fPolicyDisablesArc = pConfigData->fDisableAutoReconnect;
  3118. TRC_DBG((TB, "AutoReconnect disabled: %d", pTSWd->fPolicyDisablesArc));
  3119. DC_END_FN();
  3120. return STATUS_SUCCESS;
  3121. }
  3122. /****************************************************************************/
  3123. /* Name: WDWSetErrorInfo */
  3124. /* */
  3125. /* Purpose: Send error info to the client */
  3126. /****************************************************************************/
  3127. NTSTATUS WDWSetErrorInfo(PTSHARE_WD pTSWd, PSD_IOCTL pSdIoctl)
  3128. {
  3129. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  3130. DC_BEGIN_FN("WDWSetErrorInfo");
  3131. TRC_ASSERT((pSC != NULL),
  3132. (TB, "NULL Share Class"));
  3133. TRC_ASSERT((pSdIoctl->InputBufferLength == sizeof(TSUINT32)),
  3134. (TB, "Bad ErrorInfo"));
  3135. if(pSC)
  3136. {
  3137. if(pTSWd->bSupportErrorInfoPDU)
  3138. {
  3139. pSC->DCS_SendErrorInfo(*((PTSUINT32)pSdIoctl->InputBuffer));
  3140. }
  3141. else
  3142. {
  3143. TRC_NRM((TB,"SetErrorInfo called but client doesn't support error PDU"));
  3144. }
  3145. }
  3146. DC_END_FN();
  3147. return STATUS_SUCCESS;
  3148. } /* WDWSetErrorInfo */
  3149. /****************************************************************************/
  3150. /* Name: WDWSendArcStatus
  3151. /*
  3152. /* Purpose: Send autoreconnect status update to client
  3153. /****************************************************************************/
  3154. NTSTATUS WDWSendArcStatus(PTSHARE_WD pTSWd, PSD_IOCTL pSdIoctl)
  3155. {
  3156. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  3157. DC_BEGIN_FN("WDWSendArcStatus");
  3158. TRC_ASSERT((pSC != NULL),
  3159. (TB, "NULL Share Class"));
  3160. TRC_ASSERT((pSdIoctl->InputBufferLength == sizeof(TSUINT32)),
  3161. (TB, "Bad ErrorInfo"));
  3162. if(pSC)
  3163. {
  3164. if(pSC->SC_IsAutoReconnectEnabled())
  3165. {
  3166. pSC->DCS_SendAutoReconnectStatus(*((PTSUINT32)pSdIoctl->InputBuffer));
  3167. }
  3168. else
  3169. {
  3170. TRC_NRM((TB,"SetErrorInfo called but client doesn't ARC error PDU"));
  3171. }
  3172. }
  3173. DC_END_FN();
  3174. return STATUS_SUCCESS;
  3175. } /* WDWSendArcStatus */
  3176. /****************************************************************************/
  3177. /* Name: WDW_LogAndDisconnect */
  3178. /* */
  3179. /* Purpose: Log an event and disconnect the Client */
  3180. /* */
  3181. /* Returns: none */
  3182. /* */
  3183. /* Params: pTSWd */
  3184. /* errDetailCode - error code to log */
  3185. /* pDetailData - additional data */
  3186. /* detailDataLen - length of additional data */
  3187. /* */
  3188. /****************************************************************************/
  3189. void RDPCALL WDW_LogAndDisconnect(
  3190. PTSHARE_WD pTSWd,
  3191. BOOL fSendErrorToClient,
  3192. unsigned errDetailCode,
  3193. PBYTE pDetailData,
  3194. unsigned detailDataLen)
  3195. {
  3196. DC_BEGIN_FN("WDW_LogAndDisconnect");
  3197. //Report the error code back to the client
  3198. ShareClass *pSC = (ShareClass *)pTSWd->dcShare;
  3199. if(pSC)
  3200. {
  3201. if(fSendErrorToClient && pTSWd->bSupportErrorInfoPDU)
  3202. {
  3203. pSC->DCS_SendErrorInfo( (errDetailCode + TS_ERRINFO_PROTOCOL_BASE));
  3204. }
  3205. else
  3206. {
  3207. if( fSendErrorToClient )
  3208. {
  3209. TRC_NRM((TB,"SetErrorInfo called but client doesn't support error PDU"));
  3210. }
  3211. else
  3212. {
  3213. TRC_NRM((TB,"SetErrorInfo called but asked not to send error code to client"));
  3214. }
  3215. }
  3216. }
  3217. if( !pTSWd->dead )
  3218. MCSProtocolErrorEvent(pTSWd->pContext, pTSWd->pProtocolStatus,
  3219. errDetailCode, pDetailData, detailDataLen);
  3220. DC_END_FN();
  3221. }
  3222. } /* extern "C" */