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.

922 lines
32 KiB

  1. /****************************************************************************/
  2. // nddint.c
  3. //
  4. // RDP DD internal functions.
  5. //
  6. // Copyright (C) 1996-2000 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <precmpdd.h>
  9. #define hdrstop
  10. #define TRC_FILE "nddint"
  11. #include <adcg.h>
  12. #include <atrcapi.h>
  13. #include <nddapi.h>
  14. #include <nsbcdisp.h>
  15. #include <nbadisp.h>
  16. #include <nshmapi.h>
  17. #include <nwdwioct.h>
  18. #include <nwdwapi.h>
  19. #include <noadisp.h>
  20. #include <nssidisp.h>
  21. #include <abcapi.h>
  22. #include <nchdisp.h>
  23. #include <ncmdisp.h>
  24. #include <noedisp.h>
  25. #include <nschdisp.h>
  26. #include <oe2.h>
  27. #define DC_INCLUDE_DATA
  28. #include <ndddata.c>
  29. #undef DC_INCLUDE_DATA
  30. /****************************************************************************/
  31. // DDInitializeModeFields
  32. //
  33. // Initializes a bunch of fields in the pdev, devcaps (aka gdiinfo), and
  34. // devinfo based on the requested mode. Returns FALSE on failure.
  35. /****************************************************************************/
  36. void RDPCALL DDInitializeModeFields(
  37. PDD_PDEV ppdev,
  38. GDIINFO *pGdiInfoOrg,
  39. GDIINFO *pgdi,
  40. DEVINFO *pdi,
  41. DEVMODEW *pdm)
  42. {
  43. HPALETTE hpal;
  44. DC_BEGIN_FN("DDInitializeModeFields");
  45. TRC_NRM((TB, "Size of pdm: %d (should be %d)",
  46. pdm->dmSize, sizeof(DEVMODEW)));
  47. TRC_NRM((TB, "Requested mode..."));
  48. TRC_NRM((TB, " Screen width -- %li", pdm->dmPelsWidth));
  49. TRC_NRM((TB, " Screen height -- %li", pdm->dmPelsHeight));
  50. TRC_NRM((TB, " Bits per pel -- %li", pdm->dmBitsPerPel));
  51. TRC_NRM((TB, " Frequency -- %li", pdm->dmDisplayFrequency));
  52. // Set up screen information from the DEVMODE structure.
  53. ppdev->ulMode = 0;
  54. ppdev->cxScreen = pdm->dmPelsWidth;
  55. ppdev->cyScreen = pdm->dmPelsHeight;
  56. ppdev->cClientBitsPerPel = pdm->dmBitsPerPel;
  57. ppdev->cProtocolBitsPerPel = 8;
  58. // Mark which functions we provide hooks for.
  59. ppdev->flHooks = ( HOOK_TEXTOUT |
  60. HOOK_STROKEPATH |
  61. HOOK_BITBLT |
  62. HOOK_COPYBITS |
  63. HOOK_FILLPATH |
  64. HOOK_LINETO |
  65. HOOK_PAINT |
  66. HOOK_STRETCHBLT |
  67. HOOK_SYNCHRONIZEACCESS);
  68. // Fill in the GDIINFO data structure with the default 8bpp values.
  69. *pgdi = ddDefaultGdi;
  70. // Now overwrite the defaults with the relevant information returned
  71. // from the kernel driver:
  72. pgdi->ulHorzRes = ppdev->cxScreen;
  73. pgdi->ulVertRes = ppdev->cyScreen;
  74. pgdi->ulPanningHorzRes = 0;
  75. pgdi->ulPanningVertRes = 0;
  76. pgdi->cBitsPixel = ppdev->cClientBitsPerPel;
  77. pgdi->cPlanes = 1;
  78. pgdi->ulVRefresh = 0;
  79. pgdi->ulDACRed = 8;
  80. pgdi->ulDACGreen = 8;
  81. pgdi->ulDACBlue = 8;
  82. pgdi->ulLogPixelsX = pdm->dmLogPixels;
  83. pgdi->ulLogPixelsY = pdm->dmLogPixels;
  84. #ifdef DC_HICOLOR
  85. /************************************************************************/
  86. /* Fill in the mask values. */
  87. /************************************************************************/
  88. if (pgdi->cBitsPixel == 24)
  89. {
  90. ppdev->flRed = TS_RED_MASK_24BPP;
  91. ppdev->flGreen = TS_GREEN_MASK_24BPP;
  92. ppdev->flBlue = TS_BLUE_MASK_24BPP;
  93. }
  94. else if (pgdi->cBitsPixel == 16)
  95. {
  96. ppdev->flRed = TS_RED_MASK_16BPP;
  97. ppdev->flGreen = TS_GREEN_MASK_16BPP;
  98. ppdev->flBlue = TS_BLUE_MASK_16BPP;
  99. }
  100. else if (pgdi->cBitsPixel == 15)
  101. {
  102. ppdev->flRed = TS_RED_MASK_15BPP;
  103. ppdev->flGreen = TS_GREEN_MASK_15BPP;
  104. ppdev->flBlue = TS_BLUE_MASK_15BPP;
  105. }
  106. else
  107. {
  108. ppdev->flRed = 0;
  109. ppdev->flGreen = 0;
  110. ppdev->flBlue = 0;
  111. }
  112. #else
  113. ppdev->flRed = 0;
  114. ppdev->flGreen = 0;
  115. ppdev->flBlue = 0;
  116. #endif
  117. // Fill in the devinfo structure with the default 8bpp values, taking
  118. // care not to trash the supplied hpalDefault (which allows us to
  119. // query information about the real display driver's color format).
  120. hpal = pdi->hpalDefault;
  121. *pdi = ddDefaultDevInfo;
  122. pdi->hpalDefault = hpal;
  123. switch (ppdev->cClientBitsPerPel) {
  124. case 8:
  125. ppdev->iBitmapFormat = BMF_8BPP;
  126. pgdi->ulNumColors = 20;
  127. pgdi->ulNumPalReg = 256;
  128. pgdi->ulHTOutputFormat = HT_FORMAT_8BPP;
  129. pdi->iDitherFormat = BMF_8BPP;
  130. break;
  131. case 4:
  132. ppdev->iBitmapFormat = BMF_4BPP;
  133. pgdi->ulNumColors = 16;
  134. pgdi->ulNumPalReg = 0;
  135. pgdi->ulHTOutputFormat = HT_FORMAT_4BPP;
  136. pdi->iDitherFormat = BMF_4BPP;
  137. pdi->flGraphicsCaps &= ~GCAPS_PALMANAGED;
  138. pgdi->ulDACRed = 4;
  139. pgdi->ulDACGreen = 4;
  140. pgdi->ulDACBlue = 4;
  141. break;
  142. case 15:
  143. case 16:
  144. ppdev->iBitmapFormat = BMF_16BPP;
  145. pgdi->ulHTOutputFormat = HT_FORMAT_16BPP;
  146. pdi->iDitherFormat = BMF_16BPP;
  147. pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  148. break;
  149. case 24:
  150. // DIB conversions will only work if we have a standard RGB
  151. // surface for 24bpp.
  152. TRC_ASSERT((ppdev->flRed == 0x00ff0000), (TB,"Invalid red"));
  153. TRC_ASSERT((ppdev->flGreen == 0x0000ff00), (TB,"Invalid green"));
  154. TRC_ASSERT((ppdev->flBlue == 0x000000ff), (TB,"Invalid blue"));
  155. ppdev->iBitmapFormat = BMF_24BPP;
  156. pgdi->ulHTOutputFormat = HT_FORMAT_24BPP;
  157. pdi->iDitherFormat = BMF_24BPP;
  158. pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  159. break;
  160. case 32:
  161. ppdev->iBitmapFormat = BMF_32BPP;
  162. pgdi->ulHTOutputFormat = HT_FORMAT_32BPP;
  163. pdi->iDitherFormat = BMF_32BPP;
  164. pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  165. break;
  166. default:
  167. // Unsupported bpp - pretend we are 8 bpp.
  168. TRC_ERR((TB, "Unsupported bpp value: %d",
  169. pGdiInfoOrg->cBitsPixel * pGdiInfoOrg->cPlanes));
  170. break;
  171. }
  172. DC_END_FN();
  173. }
  174. /****************************************************************************/
  175. // DDInitializePalette
  176. //
  177. // Set up the default palette for the display driver. Returns FALSE on
  178. // failure.
  179. /****************************************************************************/
  180. BOOL RDPCALL DDInitializePalette(PDD_PDEV ppdev, DEVINFO *pdi)
  181. {
  182. BOOL rc;
  183. PALETTEENTRY *ppalTmp;
  184. ULONG ulLoop;
  185. BYTE jRed;
  186. BYTE jGre;
  187. BYTE jBlu;
  188. HPALETTE hpal;
  189. DC_BEGIN_FN("DDInitializePalette");
  190. if (ppdev->iBitmapFormat == BMF_8BPP || ppdev->iBitmapFormat == BMF_4BPP) {
  191. if (ppdev->iBitmapFormat == BMF_8BPP) {
  192. // cColors == 256: Generate 256 (8*8*4) RGB combinations to fill
  193. // the palette.
  194. jRed = 0;
  195. jGre = 0;
  196. jBlu = 0;
  197. ppalTmp = ppdev->Palette;
  198. for (ulLoop = 256; ulLoop != 0; ulLoop--) {
  199. // JPB: The values used in the default rainbow set of
  200. // colors do not particularly matter. However, we do not
  201. // want any of the entries to match entries in the default
  202. // VGA colors. Therefore we tweak the color values
  203. // slightly to ensure that there are no matches.
  204. ppalTmp->peRed = ((jRed == 0) ? (jRed+1) : (jRed-1));
  205. ppalTmp->peGreen = ((jGre == 0) ? (jGre+1) : (jGre-1));
  206. ppalTmp->peBlue = ((jBlu == 0) ? (jBlu+1) : (jBlu-1));
  207. ppalTmp->peFlags = 0;
  208. ppalTmp++;
  209. if (!(jRed += 32))
  210. if (!(jGre += 32))
  211. jBlu += 64;
  212. }
  213. // Fill in Windows reserved colors from the WIN 3.0 DDK. The
  214. // Windows Manager reserved the first and last 10 colours for
  215. // painting windows borders and for non-palette managed
  216. // applications.
  217. memcpy(ppdev->Palette, ddDefaultPalette, sizeof(PALETTEENTRY) *
  218. 10);
  219. memcpy(&(ppdev->Palette[246]), &(ddDefaultPalette[10]),
  220. sizeof(PALETTEENTRY) * 10);
  221. // Create handle for palette.
  222. hpal = EngCreatePalette(PAL_INDEXED, 256, (ULONG*)ppdev->Palette, 0,
  223. 0, 0);
  224. }
  225. else {
  226. // Set up the new palette. The palette contains 256 colors, as
  227. // that is the color depth of the protocol. For convenience,
  228. // - copy entire 16-color palette into slots 0-15
  229. // - copy high colors (8-15) into high end of palette (240-255)
  230. // This means that we can use indices 0-15, or 0-7, 248-255
  231. // later.
  232. memcpy(ppdev->Palette, ddDefaultVgaPalette,
  233. sizeof(ddDefaultVgaPalette));
  234. // Zero the middle entries since the palette was uninitialized.
  235. memset(&(ppdev->Palette[16]), 0, sizeof(PALETTEENTRY) * 208);
  236. memcpy(&(ppdev->Palette[248]), &(ddDefaultVgaPalette[8]),
  237. sizeof(*ddDefaultVgaPalette) * 8);
  238. // Create handle for palette.
  239. hpal = EngCreatePalette(PAL_INDEXED, 16, (ULONG*)ppdev->Palette, 0,
  240. 0, 0);
  241. }
  242. }
  243. else {
  244. TRC_ASSERT(((ppdev->iBitmapFormat == BMF_16BPP) ||
  245. (ppdev->iBitmapFormat == BMF_24BPP) ||
  246. (ppdev->iBitmapFormat == BMF_32BPP)),
  247. (TB, "This case handles only 16, 24 or 32bpp"));
  248. hpal = EngCreatePalette(PAL_BITFIELDS, 0, NULL, ppdev->flRed,
  249. ppdev->flGreen, ppdev->flBlue);
  250. }
  251. ppdev->hpalDefault = hpal;
  252. pdi->hpalDefault = hpal;
  253. if (hpal != 0) {
  254. rc = TRUE;
  255. }
  256. else {
  257. rc = FALSE;
  258. TRC_ERR((TB, "EngCreatePalette returned zero"));
  259. }
  260. // Note that we don't need to free the memory for the palette as that
  261. // is always tidied up in the driver termination code
  262. // (DrvDisableDriver).
  263. DC_END_FN();
  264. return rc;
  265. }
  266. /****************************************************************************/
  267. // DDGetModes
  268. //
  269. // Returns the list of modes supported. Sends an IOCtl to the miniport
  270. // driver (the WD) to get the information. NOTE: the buffer must be freed up
  271. // by the caller. Returns the number of entries in the videomode buffer.
  272. // A return code of 0 is an error.
  273. // A return code of -1 indicates that we are in chained mode.
  274. /****************************************************************************/
  275. INT32 RDPCALL DDGetModes(
  276. HANDLE hDriver,
  277. PVIDEO_MODE_INFORMATION *modeInformation,
  278. PINT32 pModeSize)
  279. {
  280. ULONG ulTemp;
  281. VIDEO_NUM_MODES modes;
  282. INT32 rc = 0;
  283. UINT32 bytesReturned;
  284. NTSTATUS status;
  285. DC_BEGIN_FN("DDGetModes");
  286. // Get the number of modes supported by the mini-port.
  287. if (!EngDeviceIoControl(hDriver, IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES,
  288. NULL, 0, &modes, sizeof(VIDEO_NUM_MODES), &ulTemp)) {
  289. // When we're chained into the console session, our miniport will
  290. // return 0 for the number of modes, indicating that we'll do whatever
  291. // was specified in the registry when we got loaded.
  292. if (modes.NumModes != 0) {
  293. // Allocate the buffer to receive the modes from the miniport.
  294. *pModeSize = modes.ModeInformationLength;
  295. *modeInformation = (PVIDEO_MODE_INFORMATION)EngAllocMem(0,
  296. modes.NumModes*modes.ModeInformationLength, DD_ALLOC_TAG);
  297. if (*modeInformation != NULL) {
  298. // Ask the mini-port to fill in the available modes.
  299. if (!EngDeviceIoControl(hDriver, IOCTL_VIDEO_QUERY_AVAIL_MODES,
  300. NULL, 0, *modeInformation,
  301. modes.NumModes * modes.ModeInformationLength,
  302. &ulTemp)) {
  303. // Store the number of modes.
  304. rc = modes.NumModes;
  305. }
  306. else {
  307. TRC_ERR((TB, "getAvailableModes failed "
  308. "VIDEO_QUERY_AVAIL_MODES"));
  309. // Free the memory and quit.
  310. EngFreeMem(*modeInformation);
  311. *modeInformation = NULL;
  312. }
  313. }
  314. else {
  315. TRC_ERR((TB, "getAvailableModes failed EngAllocMem"));
  316. }
  317. }
  318. else {
  319. TRC_NRM((TB, "Num modes is 0 - chained"));
  320. rc = -1;
  321. }
  322. }
  323. else {
  324. TRC_ERR((TB, "getAvailableModes failed VIDEO_QUERY_NUM_AVAIL_MODES"));
  325. }
  326. DC_END_FN();
  327. return rc;
  328. }
  329. /****************************************************************************/
  330. // DDInit
  331. //
  332. // Initialize the display protocol components of RDPDD. Returns FALSE on
  333. // failure.
  334. /****************************************************************************/
  335. #define PERSISTENT_CACHE_ENTRIES_DEFAULT 3072
  336. BOOL RDPCALL DDInit(
  337. PDD_PDEV pPDev,
  338. BOOL reconnect,
  339. BOOL reinit,
  340. PTSHARE_VIRTUAL_MODULE_DATA pVirtModuleData,
  341. UINT32 virtModuleDataLen)
  342. {
  343. TSHARE_DD_CONNECT_IN connIn;
  344. TSHARE_DD_CONNECT_OUT *connOut = NULL;
  345. ULONG connOutSize;
  346. ULONG bytesReturned;
  347. NTSTATUS status;
  348. BOOL rc = FALSE;
  349. UINT32 IOCtlCode;
  350. DC_BEGIN_FN("DDInit");
  351. // Set the reconnect flag for debugging purposes.
  352. ddReconnected = reconnect;
  353. // Clear the order encoding histories since the client just reset its
  354. // history as well.
  355. OE_ClearOrderEncoding();
  356. SSI_ClearOrderEncoding();
  357. OE2_Reset();
  358. OE_Reset();
  359. // For reconnect, pPDev can be NULL. For connect, it is required.
  360. TRC_ASSERT((reconnect || pPDev || reinit), (TB,"Bad call %d, %p", reconnect, pPDev));
  361. DD_UPD_STATE(DD_INIT_IN);
  362. // Create shared memory (SHM).
  363. if (SHM_Init(pPDev)) {
  364. DD_UPD_STATE(DD_INIT_SHM_OUT);
  365. }
  366. else {
  367. TRC_ERR((TB, "Failed to init SHM"));
  368. DC_QUIT;
  369. }
  370. // IOCtl to the WD.
  371. connIn.pShm = pddShm;
  372. connIn.DDShmSize = sizeof(SHM_SHARED_MEMORY);
  373. // Following 3 fields have meaning only for reconnect - set them
  374. // anyway, RDPWD doesn't look at them for connect.
  375. connIn.pKickTimer = pddWdTimer;
  376. connIn.desktopHeight = ddDesktopHeight;
  377. connIn.desktopWidth = ddDesktopWidth;
  378. #ifdef DC_HICOLOR
  379. // Need to supply this on the 'in' parameter - but note that it is not
  380. // updated until DrvEnableSurface is called.
  381. connIn.desktopBpp = ddFrameBufBpp;
  382. #endif
  383. // Fields for shadow connect, NULL for normal connection processing
  384. connIn.pVirtModuleData = pVirtModuleData;
  385. connIn.virtModuleDataLen = virtModuleDataLen;
  386. connOutSize = sizeof(TSHARE_DD_CONNECT_OUT) + sizeof(SBC_BITMAP_CACHE_KEY_INFO) +
  387. (PERSISTENT_CACHE_ENTRIES_DEFAULT - 1) * sizeof(SBC_MRU_KEY);
  388. connOut = (TSHARE_DD_CONNECT_OUT *)EngAllocMem(0, connOutSize, DD_ALLOC_TAG);
  389. if (connOut == NULL) {
  390. TRC_ERR((TB, "Failed to allocate memory for connOut"));
  391. DC_QUIT;
  392. }
  393. memset(connOut, 0, connOutSize);
  394. connOut->primaryStatus = STATUS_SUCCESS;
  395. connOut->secondaryStatus = STATUS_SUCCESS;
  396. connOut->bitmapKeyDatabaseSize = sizeof(SBC_BITMAP_CACHE_KEY_INFO) +
  397. (PERSISTENT_CACHE_ENTRIES_DEFAULT - 1) * sizeof(SBC_MRU_KEY);
  398. if (pVirtModuleData == NULL)
  399. IOCtlCode = (reconnect && !reinit)? IOCTL_WDTS_DD_RECONNECT :
  400. IOCTL_WDTS_DD_CONNECT;
  401. else
  402. IOCtlCode = IOCTL_WDTS_DD_SHADOW_CONNECT;
  403. bytesReturned = 0;
  404. status = EngFileIoControl(ddWdHandle, IOCtlCode, &connIn,
  405. sizeof(TSHARE_DD_CONNECT_IN), connOut,
  406. connOutSize, &bytesReturned);
  407. DD_UPD_STATE(DD_INIT_IOCTL_OUT);
  408. // If the primary stack connected, then we can continue output
  409. // regardless of whether or not the shadow stack came up.
  410. status = connOut->primaryStatus;
  411. if (connOut->primaryStatus == STATUS_SUCCESS) {
  412. ddConnected = TRUE;
  413. }
  414. else {
  415. TRC_ERR((TB, "Primary stack failed to connect! -> %lx", status));
  416. DD_UPD_STATE(DD_INIT_FAIL1);
  417. DC_QUIT;
  418. }
  419. if (bytesReturned && bytesReturned <= connOutSize) {
  420. DD_UPD_STATE(DD_INIT_OK1);
  421. // Save off the returned values that we need.
  422. if (IOCtlCode != IOCTL_WDTS_DD_SHADOW_CONNECT)
  423. pddTSWd = connOut->pTSWd;
  424. else
  425. pddTSWdShadow = connOut->pTSWd;
  426. }
  427. else {
  428. TRC_ERR((TB, "Wrong no %lu of bytes returned", bytesReturned));
  429. DD_UPD_STATE(DD_INIT_FAIL2);
  430. DC_QUIT;
  431. }
  432. // Enable trace to WD, since the correct config will now be in SHM.
  433. #ifdef DC_DEBUG
  434. ddTrcToWD = TRUE;
  435. #endif
  436. #ifdef DC_COUNTERS
  437. // Zero out the counters and cache statistics.
  438. // We do not use counters unless specifically built to do so using
  439. // DC_COUNTERS. However, even if we wanted to, there is a bad
  440. // corruption problem owing to a timing problem where the counters are
  441. // freed while the DD still believes they are present. This is Windows NT
  442. // Bug #391762. If we want to have counters in production code we need
  443. // to fix that Win32K timing bug. Enable DC_COUNTERS and special pool
  444. // for rdpdd to make the bug come back.
  445. pddProtStats = connOut->pProtocolStatus;
  446. pddProtStats->Input.ProtocolType = PROTOCOL_ICA;
  447. pddProtStats->Output.ProtocolType = PROTOCOL_ICA;
  448. memset(pddCacheStats, 0, sizeof(ICA_CACHE));
  449. memset(&(pddProtStats->Output.Specific),
  450. 0, sizeof(pddProtStats->Output.Specific));
  451. memset(&(pddProtStats->Input.Specific),
  452. 0, sizeof(pddProtStats->Input.Specific));
  453. #endif
  454. TRC_ERR((TB, "Received pTSWD %p", pddTSWd));
  455. ddDesktopHeight = connOut->desktopHeight;
  456. ddDesktopWidth = connOut->desktopWidth;
  457. // Once pddShm is set up, tracing should work - try it now.
  458. TRC_NRM((TB, "Handshake with RDPWD complete"));
  459. // Perform any other init that may be required for the wire protocol.
  460. if (!reconnect && !reinit) {
  461. TRC_NRM((TB, "Connect"));
  462. DD_UPD_STATE(DD_INIT_CONNECT);
  463. BA_DDInit();
  464. OA_DDInit();
  465. SSI_DDInit();
  466. if (!CM_DDInit(pPDev)) {
  467. TRC_ERR((TB, "CM Failed"));
  468. DC_QUIT;
  469. }
  470. SBC_DDInit(pPDev);
  471. } /* !reconnect */
  472. // RDPWD waits to receive all of ConfirmActivePDU, persistent bitmap
  473. // cache keys, and font lists from the Client before returning from the
  474. // IOCTL_WDTS_DD_(RE)CONNECT above. Hence, by the time we get here,
  475. // the capabilities have been updated in SHM. We do this for connect and
  476. // reconnect cases.
  477. TRC_NRM((TB, "Update capabilities"));
  478. OE_Update();
  479. CM_Update();
  480. // If bitmapKeyDatabaseSize is 0, then we failed to get the keydatabase
  481. // or there is no persistent caching
  482. if (connOut->bitmapKeyDatabaseSize) {
  483. if (connOut->bitmapKeyDatabaseSize <= sizeof(SBC_BITMAP_CACHE_KEY_INFO) +
  484. (PERSISTENT_CACHE_ENTRIES_DEFAULT - 1) * sizeof(SBC_MRU_KEY)) {
  485. SBC_Update((SBC_BITMAP_CACHE_KEY_INFO *)(&(connOut->bitmapKeyDatabase)));
  486. }
  487. else {
  488. PTSHARE_DD_BITMAP_KEYDATABASE_OUT pKeyDBOut;
  489. unsigned keyDBOutSize;
  490. unsigned bytesReturned;
  491. // the buffer is too small, reallocate a big one and try once more
  492. keyDBOutSize = sizeof(TSHARE_DD_BITMAP_KEYDATABASE_OUT) - 1+
  493. connOut->bitmapKeyDatabaseSize;
  494. pKeyDBOut = (PTSHARE_DD_BITMAP_KEYDATABASE_OUT)
  495. EngAllocMem(0, keyDBOutSize, DD_ALLOC_TAG);
  496. if (pKeyDBOut == NULL) {
  497. TRC_ERR((TB, "Failed to allocate memory for connOut"));
  498. SBC_Update(NULL);
  499. }
  500. else {
  501. pKeyDBOut->bitmapKeyDatabaseSize = connOut->bitmapKeyDatabaseSize;
  502. status = EngFileIoControl(ddWdHandle, IOCTL_WDTS_DD_GET_BITMAP_KEYDATABASE,
  503. NULL, 0, pKeyDBOut,
  504. keyDBOutSize, &bytesReturned);
  505. if (status == STATUS_SUCCESS && pKeyDBOut->bitmapKeyDatabaseSize <=
  506. connOut->bitmapKeyDatabaseSize) {
  507. SBC_Update((SBC_BITMAP_CACHE_KEY_INFO *)(&(pKeyDBOut->bitmapKeyDatabase)));
  508. }
  509. else {
  510. SBC_Update(NULL);
  511. }
  512. EngFreeMem(pKeyDBOut);
  513. }
  514. }
  515. }
  516. else {
  517. SBC_Update(NULL);
  518. }
  519. SSI_Update(pVirtModuleData != NULL);
  520. // All OK for Primary Stack
  521. ddInitialised = TRUE;
  522. DD_UPD_STATE(DD_INIT_OK_ALL);
  523. // If the shadow stack failed to init, then flag it so we disconnect
  524. // the failed shadow stack via DrvShadowDisconnect
  525. if (connOut->secondaryStatus != STATUS_SUCCESS) {
  526. status = connOut->secondaryStatus;
  527. TRC_ERR((TB, "Shadow stack failed to connect! -> %lx", status));
  528. DD_UPD_STATE(DD_SHADOW_FAIL);
  529. DC_QUIT;
  530. }
  531. // If we got here then absolutely everything went OK
  532. rc = TRUE;
  533. DC_EXIT_POINT:
  534. if (connOut != NULL) {
  535. EngFreeMem(connOut);
  536. connOut = NULL;
  537. }
  538. DC_END_FN();
  539. return rc;
  540. } /* DDInit */
  541. /****************************************************************************/
  542. /* Name: DDDisconnect */
  543. /* */
  544. /* Purpose: Terminate the share aspects of the DD. */
  545. /* */
  546. /* Params: bShadowDisconnect - TRUE is this is being done in preparation */
  547. /* for a shadow session request. */
  548. /* */
  549. /* Operation: Terminates all sub-components, and then IOCtls to the WD to */
  550. /* tell it that we're going. */
  551. /* */
  552. /* Finally it cleans up all refereces to WD data. */
  553. /* */
  554. /* NB This routine can be called on connect failure - so all the */
  555. /* XX_Disc() APIs called by this routine must be robust to the */
  556. /* component not having been initialized. */
  557. /****************************************************************************/
  558. void RDPCALL DDDisconnect(BOOL bShadowDisconnect)
  559. {
  560. NTSTATUS status;
  561. ULONG bytesReturned;
  562. TSHARE_DD_DISCONNECT_IN disconnIn;
  563. DC_BEGIN_FN("DDDisconnect");
  564. DD_UPD_STATE(DD_DISCONNECT_IN);
  565. // Call disconnect functions where needed.
  566. CM_DDDisc();
  567. // Now tell the WD we're disconnecting. We don't do anything with a
  568. // failure here - there's no point - we're already disconnecting!
  569. memset(&disconnIn, 0, sizeof(disconnIn));
  570. disconnIn.pShm = pddShm;
  571. disconnIn.bShadowDisconnect = bShadowDisconnect;
  572. status = EngFileIoControl(ddWdHandle, IOCTL_WDTS_DD_DISCONNECT,
  573. &disconnIn, sizeof(disconnIn), NULL, 0, &bytesReturned);
  574. // Send Bitmap Cache. Must be destroyed after the IOCTL to allow the
  575. // IOCTL to dump the cache contents for reconnect.
  576. SBC_DDDisc();
  577. // Finally, free SHM.
  578. SHM_Term();
  579. // If this is a real session disconnect, then blow away the WD ioctl
  580. // handle since we will get a new on one DrvReconnect(). Otherwise
  581. // we need to keep it since we will immediately reconnect back to the
  582. // same stack.
  583. if (!bShadowDisconnect)
  584. ddWdHandle = NULL;
  585. // Don't allow any drawing while we are disconnected!
  586. ddConnected = FALSE;
  587. TRC_NRM((TB, "Status on Disc IOCtl to WD %lu", status));
  588. DD_UPD_STATE(DD_DISCONNECT_OUT);
  589. DC_END_FN();
  590. } /* DDDisconnect */
  591. /****************************************************************************/
  592. // DDTerm
  593. //
  594. // Terminate the output-remoting components of the DD.
  595. /****************************************************************************/
  596. void RDPCALL DDTerm(void)
  597. {
  598. BOOL rc;
  599. NTSTATUS status;
  600. DC_BEGIN_FN("DDTerm");
  601. // Call terminate functions where needed.
  602. SBC_DDTerm();
  603. CM_DDTerm();
  604. // Finally, free SHM.
  605. SHM_Term();
  606. ddWdHandle = NULL;
  607. pddWdTimer = NULL;
  608. if (pddFrameBuf != NULL) {
  609. if (ddSectionObject != NULL) {
  610. TRC_NRM((TB, "Freeing section mem frame buffer %p", pddFrameBuf));
  611. rc = EngFreeSectionMem(ddSectionObject, pddFrameBuf);
  612. if (!rc) {
  613. TRC_ABORT((TB, "EngFreeSectionMem failed, section object will "
  614. "leak"));
  615. }
  616. #ifdef DC_DEBUG
  617. else {
  618. // NT BUG 539912 - Instance count section memory objects
  619. dbg_ddSectionAllocs--;
  620. TRC_DBG(( TB, "DDTerm - %d outstanding surfaces allocated",
  621. dbg_ddSectionAllocs ));
  622. DBG_DD_FNCALL_HIST_ADD( DBG_DD_FREE_SECTIONOBJ_DDTERM,
  623. dbg_ddSectionAllocs, 0, pddFrameBuf, ddSectionObject);
  624. }
  625. #endif // DC_DEBUG
  626. ddSectionObject = NULL;
  627. } else {
  628. TRC_NRM((TB, "Freeing non-section frame buffer %p", pddFrameBuf));
  629. EngFreeMem(pddFrameBuf);
  630. }
  631. pddFrameBuf = NULL;
  632. }
  633. #ifdef DC_DEBUG
  634. if (0 != dbg_ddSectionAllocs) {
  635. TRC_ABORT(( TB, "DDTerm - no section allocations should be outstanding" ));
  636. }
  637. #endif
  638. // Reset the frame buffer size to 0
  639. ddFrameBufX = ddFrameBufY = 0;
  640. ddInitialised = FALSE;
  641. DC_END_FN();
  642. }
  643. #define TS_GDIPLUS_LOCK_FALG 0x00000001
  644. /****************************************************************************/
  645. /* DdLock - see NT DDK documentation. */
  646. /* */
  647. /****************************************************************************/
  648. DWORD DdLock(PDD_LOCKDATA lpLock)
  649. {
  650. DC_BEGIN_FN("DdLock");
  651. TRC_NRM((TB, "DdLock"));
  652. #ifdef DRAW_GDIPLUS
  653. if (lpLock->dwFlags & DDLOCK_NODIRTYUPDATE) {
  654. // The lock is from GDI+ through DCI
  655. // set the flag
  656. lpLock->lpDDSurface->dwReserved1 |= TS_GDIPLUS_LOCK_FALG;
  657. }
  658. else {
  659. #endif
  660. // We assume that DdLock and DdUnlock will be called in pair.
  661. // If this is not the case, we return error in DdLock
  662. if(ddLocked){
  663. TRC_ERR((TB, "Error: DdLock is called twice in a row"));
  664. lpLock->ddRVal = DDERR_GENERIC;
  665. return(DDHAL_DRIVER_HANDLED);
  666. }
  667. // Record the locked area
  668. ddLockAreaLeft = lpLock->rArea.left;
  669. ddLockAreaTop= lpLock->rArea.top;
  670. ddLockAreaRight = lpLock->rArea.right;
  671. ddLockAreaBottom = lpLock->rArea.bottom;
  672. // Record that DdLock is called
  673. ddLocked = TRUE;
  674. #ifdef DRAW_GDIPLUS
  675. }
  676. #endif
  677. return(DDHAL_DRIVER_NOTHANDLED );
  678. DC_END_FN();
  679. }
  680. /****************************************************************************/
  681. /* DdUnlock - see NT DDK documentation. */
  682. /* */
  683. /****************************************************************************/
  684. DWORD DdUnlock(PDD_UNLOCKDATA lpUnlock)
  685. {
  686. PDD_PDEV pPDev;
  687. RECTL rLockArea;
  688. DC_BEGIN_FN("DdUnlock");
  689. TRC_NRM((TB, "DdUnlock"));
  690. pPDev = (PDD_PDEV)lpUnlock->lpDD->dhpdev;
  691. #ifdef DRAW_GDIPLUS
  692. if (lpUnlock->lpDDSurface->dwReserved1 & TS_GDIPLUS_LOCK_FALG) {
  693. // The lock is from GDI+ through DCI
  694. }
  695. else {
  696. #endif
  697. // We assume that DdLock and DdUnlock will be called in pair.
  698. // If this is not the case, we return error in DdLock
  699. if(!ddLocked){
  700. TRC_ERR((TB, "Error: DdUnlock is called before DdLock"));
  701. lpUnlock->ddRVal = DDERR_GENERIC;
  702. return(DDHAL_DRIVER_HANDLED);
  703. }
  704. // Reset the lock flag
  705. ddLocked = FALSE;
  706. // Sometimes, we're called after being disconnected.
  707. if (ddConnected && pddShm != NULL) {
  708. rLockArea.left = ddLockAreaLeft;
  709. rLockArea.right = ddLockAreaRight;
  710. rLockArea.top = ddLockAreaTop;
  711. rLockArea.bottom = ddLockAreaBottom;
  712. // Send changed rectangle of framebuffer to the client
  713. OEClipAndAddScreenDataArea(&rLockArea, NULL);
  714. // Have scheduler consider sending output
  715. SCH_DDOutputAvailable(pPDev, FALSE);
  716. }
  717. else {
  718. TRC_ERR((TB, "Called when disconnected"));
  719. }
  720. #ifdef DRAW_GDIPLUS
  721. }
  722. #endif
  723. return(DDHAL_DRIVER_NOTHANDLED );
  724. DC_END_FN();
  725. }
  726. /******************************Public*Routine********************************/
  727. /* DdMapMemory - see NT DDK documentation. */
  728. /* */
  729. /* This is a new DDI call specific to Windows NT that is used to map */
  730. /* or unmap all the application modifiable portions of the frame buffer */
  731. /* into the specified process's address space. */
  732. /****************************************************************************/
  733. DWORD DdMapMemory(PDD_MAPMEMORYDATA lpMapMemory)
  734. {
  735. PDD_PDEV pPDev;
  736. PVOID pMapped = NULL;
  737. NTSTATUS Status;
  738. BOOL bEngMap;
  739. DC_BEGIN_FN("DdMapMemory");
  740. TRC_NRM((TB, "DdMapMemory"));
  741. pPDev = (PDD_PDEV) lpMapMemory->lpDD->dhpdev;
  742. // In case the section object is null our frame buffer is not allocated
  743. // as section mem. We don't support DDraw in this case.
  744. if (NULL == pPDev->SectionObject) {
  745. TRC_ERR((TB,"Null SectionObject"));
  746. lpMapMemory->ddRVal = DDERR_GENERIC;
  747. DC_QUIT;
  748. }
  749. if(lpMapMemory->bMap) //Map the meory
  750. pMapped = NULL;
  751. else //Unmap the memory
  752. pMapped = (PVOID)lpMapMemory->fpProcess;
  753. bEngMap = EngMapSection(
  754. pPDev->SectionObject,
  755. lpMapMemory->bMap,
  756. lpMapMemory->hProcess,
  757. &pMapped);
  758. if(lpMapMemory->bMap && bEngMap)
  759. lpMapMemory->fpProcess = (FLATPTR)pMapped;
  760. if(bEngMap)
  761. lpMapMemory->ddRVal = DD_OK;
  762. else
  763. lpMapMemory->ddRVal = DDERR_GENERIC;
  764. DC_EXIT_POINT:
  765. DC_END_FN();
  766. return(DDHAL_DRIVER_HANDLED);
  767. }