Source code of Windows XP (NT5)
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.

1770 lines
53 KiB

  1. #include "precomp.h"
  2. //
  3. // OSI.C
  4. // OS Isolation layer, display driver side
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. #include <version.h>
  9. #include <ndcgver.h>
  10. //
  11. // These are the default 20 Windows colors, lifted from the base S3 driver.
  12. //
  13. // Global Table defining the 20 Window default colours. For 256 colour
  14. // palettes the first 10 must be put at the beginning of the palette
  15. // and the last 10 at the end of the palette.
  16. const PALETTEENTRY s_aWinColors[20] =
  17. {
  18. { 0, 0, 0, 0 }, // 0
  19. { 0x80,0, 0, 0 }, // 1
  20. { 0, 0x80,0, 0 }, // 2
  21. { 0x80,0x80,0, 0 }, // 3
  22. { 0, 0, 0x80,0 }, // 4
  23. { 0x80,0, 0x80,0 }, // 5
  24. { 0, 0x80,0x80,0 }, // 6
  25. { 0xC0,0xC0,0xC0,0 }, // 7
  26. { 192, 220, 192, 0 }, // 8
  27. { 166, 202, 240, 0 }, // 9
  28. { 255, 251, 240, 0 }, // 10
  29. { 160, 160, 164, 0 }, // 11
  30. { 0x80,0x80,0x80,0 }, // 12
  31. { 0xFF,0, 0 ,0 }, // 13
  32. { 0, 0xFF,0 ,0 }, // 14
  33. { 0xFF,0xFF,0 ,0 }, // 15
  34. { 0 ,0, 0xFF,0 }, // 16
  35. { 0xFF,0, 0xFF,0 }, // 17
  36. { 0, 0xFF,0xFF,0 }, // 18
  37. { 0xFF,0xFF,0xFF,0 }, // 19
  38. };
  39. //
  40. // Functions supported by our Display Driver. Each entry is of the form:
  41. //
  42. // index - NT DDK defined index for the DDI function
  43. //
  44. // function - pointer to our intercept function
  45. //
  46. //
  47. const DRVFN s_osiDriverFns[] =
  48. {
  49. //
  50. // NT4 FUNCTIONS
  51. //
  52. { INDEX_DrvEnablePDEV, (PFN)DrvEnablePDEV },
  53. { INDEX_DrvCompletePDEV, (PFN)DrvCompletePDEV },
  54. { INDEX_DrvDisablePDEV, (PFN)DrvDisablePDEV },
  55. { INDEX_DrvEnableSurface, (PFN)DrvEnableSurface },
  56. { INDEX_DrvDisableSurface, (PFN)DrvDisableSurface },
  57. { INDEX_DrvAssertMode, (PFN)DrvAssertMode },
  58. { INDEX_DrvResetPDEV, (PFN)DrvResetPDEV },
  59. // INDEX_DrvCreateDeviceBitmap not used
  60. // INDEX_DrvDeleteDeviceBitmap not used
  61. { INDEX_DrvRealizeBrush, (PFN)DrvRealizeBrush },
  62. // INDEX_DrvDitherColor not used
  63. { INDEX_DrvStrokePath, (PFN)DrvStrokePath },
  64. { INDEX_DrvFillPath, (PFN)DrvFillPath },
  65. { INDEX_DrvStrokeAndFillPath, (PFN)DrvStrokeAndFillPath },
  66. { INDEX_DrvPaint, (PFN)DrvPaint },
  67. { INDEX_DrvBitBlt, (PFN)DrvBitBlt },
  68. { INDEX_DrvCopyBits, (PFN)DrvCopyBits },
  69. { INDEX_DrvStretchBlt, (PFN)DrvStretchBlt },
  70. { INDEX_DrvSetPalette, (PFN)DrvSetPalette },
  71. { INDEX_DrvTextOut, (PFN)DrvTextOut },
  72. { INDEX_DrvEscape, (PFN)DrvEscape },
  73. // INDEX_DrvDrawEscape not used
  74. // INDEX_DrvQueryFont not used
  75. // INDEX_DrvQueryFontTree not used
  76. // INDEX_DrvQueryFontData not used
  77. { INDEX_DrvSetPointerShape, (PFN)DrvSetPointerShape },
  78. { INDEX_DrvMovePointer, (PFN)DrvMovePointer },
  79. { INDEX_DrvLineTo, (PFN)DrvLineTo },
  80. // INDEX_DrvSendPage not used
  81. // INDEX_DrvStartPage not used
  82. // INDEX_DrvEndDoc not used
  83. // INDEX_DrvStartDoc not used
  84. // INDEX_DrvGetGlyphMode not used
  85. // INDEX_DrvSynchronize not used
  86. { INDEX_DrvSaveScreenBits, (PFN)DrvSaveScreenBits },
  87. { INDEX_DrvGetModes, (PFN)DrvGetModes },
  88. // INDEX_DrvFree not used
  89. // INDEX_DrvDestroyFont not used
  90. // INDEX_DrvQueryFontCaps not used
  91. // INDEX_DrvLoadFontFile not used
  92. // INDEX_DrvUnloadFontFile not used
  93. // INDEX_DrvFontManagement not used
  94. // INDEX_DrvQueryTrueTypeTable not used
  95. // INDEX_DrvQueryTrueTypeOutline not used
  96. // INDEX_DrvGetTrueTypeFile not used
  97. // INDEX_DrvQueryFontFile not used
  98. // INDEX_DrvQueryAdvanceWidths not used
  99. // INDEX_DrvSetPixelFormat not used
  100. // INDEX_DrvDescribePixelFormat not used
  101. // INDEX_DrvSwapBuffers not used
  102. // INDEX_DrvStartBanding not used
  103. // INDEX_DrvNextBand not used
  104. // INDEX_DrvGetDirectDrawInfo not used
  105. // INDEX_DrvEnableDirectDraw not used
  106. // INDEX_DrvDisableDirectDraw not used
  107. // INDEX_DrvQuerySpoolType not used
  108. //
  109. // NT5 FUNCTIONS - 5 of them currently. If you add to this list,
  110. // update CFN_NT5 below.
  111. //
  112. // INDEX_DrvIcmCreateColorTransform not used
  113. // INDEX_DrvIcmDeleteColorTransform not used
  114. // INDEX_DrvIcmCheckBitmapBits not used
  115. // INDEX_DrvIcmSetDeviceGammaRamp not used
  116. { INDEX_DrvGradientFill, (PFN)DrvGradientFill },
  117. { INDEX_DrvStretchBltROP, (PFN)DrvStretchBltROP },
  118. { INDEX_DrvPlgBlt, (PFN)DrvPlgBlt },
  119. { INDEX_DrvAlphaBlend, (PFN)DrvAlphaBlend },
  120. // INDEX_DrvSynthesizeFont not used
  121. // INDEX_DrvGetSynthesizedFontFiles not used
  122. { INDEX_DrvTransparentBlt, (PFN)DrvTransparentBlt },
  123. // INDEX_DrvQueryPerBandInfo not used
  124. // INDEX_DrvQueryDeviceSupport not used
  125. // INDEX_DrvConnect not used
  126. // INDEX_DrvDisconnect not used
  127. // INDEX_DrvReconnect not used
  128. // INDEX_DrvShadowConnect not used
  129. // INDEX_DrvShadowDisconnect not used
  130. // INDEX_DrvInvalidateRect not used
  131. // INDEX_DrvSetPointerPos not used
  132. // INDEX_DrvDisplayIOCtl not used
  133. // INDEX_DrvDeriveSurface not used
  134. // INDEX_DrvQueryGlyphAttrs not used
  135. };
  136. #define CFN_NT5 5
  137. //
  138. // s_osiDefaultGdi
  139. //
  140. // This contains the default GDIINFO fields that are passed back to GDI
  141. // during DrvEnablePDEV.
  142. //
  143. // NOTE: This structure defaults to values for an 8bpp palette device.
  144. // Some fields are overwritten for different colour depths.
  145. //
  146. // It is expected that DDML ignores a lot of these parameters and
  147. // uses the values from the primary driver instead
  148. //
  149. const GDIINFO s_osiDefaultGdi =
  150. {
  151. GDI_DRIVER_VERSION,
  152. DT_RASDISPLAY, // ulTechnology
  153. 400, // ulHorzSize (display width: mm)
  154. 300, // ulVertSize (display height: mm)
  155. 0, // ulHorzRes (filled in later)
  156. 0, // ulVertRes (filled in later)
  157. 0, // cBitsPixel (filled in later)
  158. 1, // cPlanes
  159. (ULONG)-1, // ulNumColors (palette managed)
  160. 0, // flRaster (DDI reserved field)
  161. 96, // ulLogPixelsX (filled in later)
  162. 96, // ulLogPixelsY (filled in later)
  163. TC_RA_ABLE, // flTextCaps - If we had wanted console windows
  164. // to scroll by repainting the entire window,
  165. // instead of doing a screen-to-screen blt, we
  166. // would have set TC_SCROLLBLT (yes, the flag
  167. // is backwards).
  168. 0, // ulDACRed (filled in later)
  169. 0, // ulDACGreen (filled in later)
  170. 0, // ulDACBlue (filled in later)
  171. 0x0024, // ulAspectX
  172. 0x0024, // ulAspectY
  173. 0x0033, // ulAspectXY (one-to-one aspect ratio)
  174. 1, // xStyleStep
  175. 1, // yStyleStep
  176. 3, // denStyleStep -- Styles have a one-to-one
  177. // aspect ratio, and every dot is 3 pixels long
  178. { 0, 0 }, // ptlPhysOffset
  179. { 0, 0 }, // szlPhysSize
  180. 0, // ulNumPalReg
  181. {
  182. { 6700, 3300, 0 }, // Red
  183. { 2100, 7100, 0 }, // Green
  184. { 1400, 800, 0 }, // Blue
  185. { 1750, 3950, 0 }, // Cyan
  186. { 4050, 2050, 0 }, // Magenta
  187. { 4400, 5200, 0 }, // Yellow
  188. { 3127, 3290, 0 }, // AlignmentWhite
  189. 20000, // RedGamma
  190. 20000, // GreenGamma
  191. 20000, // BlueGamma
  192. 0, 0, 0, 0, 0, 0 // No dye correction for raster displays
  193. },
  194. 0, // ulDevicePelsDPI (for printers only)
  195. PRIMARY_ORDER_CBA, // ulPrimaryOrder
  196. HT_PATSIZE_4x4_M, // ulHTPatternSize
  197. HT_FORMAT_8BPP, // ulHTOutputFormat
  198. HT_FLAG_ADDITIVE_PRIMS, // flHTFlags
  199. 0, // ulVRefresh
  200. 0, // ulBltAlignment
  201. 0, // ulPanningHorzRes
  202. 0, // ulPanningVertRes
  203. };
  204. //
  205. // s_osiDefaultDevInfo
  206. //
  207. // This contains the default DEVINFO fields that are passed back to GDI
  208. // during DrvEnablePDEV.
  209. //
  210. // NOTE: This structure defaults to values for an 8bpp palette device.
  211. // Some fields are overwritten for different colour depths.
  212. //
  213. //
  214. const DEVINFO s_osiDefaultDevInfo =
  215. {
  216. {
  217. GCAPS_OPAQUERECT |
  218. GCAPS_DITHERONREALIZE |
  219. GCAPS_PALMANAGED |
  220. GCAPS_MONO_DITHER |
  221. GCAPS_COLOR_DITHER |
  222. GCAPS_LAYERED
  223. }, // NOTE: Only enable ASYNCMOVE if your code
  224. // and hardware can handle DrvMovePointer
  225. // calls at any time, even while another
  226. // thread is in the middle of a drawing
  227. // call such as DrvBitBlt.
  228. // flGraphicsFlags
  229. { 16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
  230. CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
  231. VARIABLE_PITCH | FF_DONTCARE, L"System"
  232. },
  233. // lfDefaultFont
  234. {
  235. 12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
  236. CLIP_STROKE_PRECIS,PROOF_QUALITY,
  237. VARIABLE_PITCH | FF_DONTCARE, L"MS Sans Serif"
  238. },
  239. // lfAnsiVarFont
  240. {
  241. 12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
  242. CLIP_STROKE_PRECIS,PROOF_QUALITY,
  243. FIXED_PITCH | FF_DONTCARE, L"Courier"
  244. },
  245. // lfAnsiFixFont
  246. 0, // cFonts
  247. BMF_8BPP, // iDitherFormat
  248. 8, // cxDither
  249. 8, // cyDither
  250. 0 // hpalDefault (filled in later)
  251. };
  252. //
  253. // DrvEnableDriver - see NT DDK documentation.
  254. //
  255. // This is the only directly exported entry point to the display driver.
  256. // All other entry points are exported through the data returned from this
  257. // function.
  258. //
  259. BOOL DrvEnableDriver
  260. (
  261. ULONG iEngineVersion,
  262. ULONG cj,
  263. DRVENABLEDATA* pded
  264. )
  265. {
  266. DebugEntry(DrvEnableDriver);
  267. INIT_OUT(("DrvEnableDriver(iEngineVersion = 0x%08x)", iEngineVersion));
  268. //
  269. // Check that the engine version is correct - we refuse to load on
  270. // other versions because we will almost certainly not work.
  271. //
  272. if ((iEngineVersion != DDI_DRIVER_VERSION_SP3) &&
  273. (iEngineVersion != DDI_DRIVER_VERSION_NT5))
  274. {
  275. INIT_OUT(("DrvEnableDriver: Not NT 4.0 SP-3 or NT 5.0; failing enable"));
  276. return(FALSE);
  277. }
  278. //
  279. // Fill in as much as we can. Start with the entry points.
  280. //
  281. if ( cj >= FIELD_OFFSET(DRVENABLEDATA, pdrvfn) +
  282. FIELD_SIZE (DRVENABLEDATA, pdrvfn) )
  283. {
  284. pded->pdrvfn = (DRVFN *)s_osiDriverFns;
  285. }
  286. //
  287. // Size of our entry point array.
  288. //
  289. if ( cj >= FIELD_OFFSET(DRVENABLEDATA, c) +
  290. FIELD_SIZE (DRVENABLEDATA, c) )
  291. {
  292. //
  293. // If this is NT4, return back a subset -- it doesn't like tables
  294. // with unknown indeces
  295. //
  296. pded->c = sizeof(s_osiDriverFns) / sizeof(s_osiDriverFns[0]);
  297. if (iEngineVersion != DDI_DRIVER_VERSION_NT5)
  298. {
  299. pded->c -= CFN_NT5;
  300. }
  301. INIT_OUT(("DrvEnableDriver: Returning driver function count %u", pded->c));
  302. }
  303. //
  304. // DDI version this driver was targeted for is passed back to engine.
  305. // Future graphics engines may break calls down to old driver format.
  306. //
  307. if ( cj >= FIELD_OFFSET(DRVENABLEDATA, iDriverVersion) +
  308. FIELD_SIZE (DRVENABLEDATA, iDriverVersion) )
  309. {
  310. //
  311. // Return back NT5 when we're on NT5. Hopefully this will work
  312. // OK...
  313. //
  314. pded->iDriverVersion = iEngineVersion;
  315. INIT_OUT(("DrvEnableDriver: Returning driver version 0x%08x", pded->iDriverVersion));
  316. }
  317. DebugExitVOID(DrvEnableDriver);
  318. return(TRUE);
  319. }
  320. //
  321. // DrvDisableDriver - see NT DDK documentation.
  322. //
  323. VOID DrvDisableDriver(VOID)
  324. {
  325. DebugEntry(DrvDisableDriver);
  326. DebugExitVOID(DrvDisableDriver);
  327. }
  328. //
  329. // DrvEnablePDEV - see NT DDK documentation.
  330. //
  331. // Initializes a bunch of fields for GDI, based on the mode we've been
  332. // asked to do. This is the first thing called after DrvEnableDriver, when
  333. // GDI wants to get some information about us.
  334. //
  335. // (This function mostly returns back information; DrvEnableSurface is used
  336. // for initializing the hardware and driver components.)
  337. //
  338. //
  339. DHPDEV DrvEnablePDEV(DEVMODEW* pdm,
  340. PWSTR pwszLogAddr,
  341. ULONG cPat,
  342. HSURF* phsurfPatterns,
  343. ULONG cjCaps,
  344. ULONG* pdevcaps,
  345. ULONG cjDevInfo,
  346. DEVINFO* pdi,
  347. HDEV hdev,
  348. PWSTR pwszDeviceName,
  349. HANDLE hDriver)
  350. {
  351. DHPDEV rc = NULL;
  352. LPOSI_PDEV ppdev = NULL;
  353. GDIINFO gdiInfoNew;
  354. DebugEntry(DrvEnablePDEV);
  355. INIT_OUT(("DrvEnablePDEV: Parameters:"));
  356. INIT_OUT((" PWSTR pdm->dmDeviceName %ws", pdm->dmDeviceName));
  357. INIT_OUT((" HDEV hdev 0x%08x", hdev));
  358. INIT_OUT((" PWSTR pwszDeviceName %ws", pwszDeviceName));
  359. INIT_OUT((" HANDLE hDriver 0x%08x", hDriver));
  360. //
  361. // This function only sets up local data, so shared memory protection
  362. // is not required.
  363. //
  364. //
  365. // Make sure that we have large enough data to reference.
  366. //
  367. if ((cjCaps < sizeof(GDIINFO)) || (cjDevInfo < sizeof(DEVINFO)))
  368. {
  369. ERROR_OUT(( "Buffer size too small %lu %lu", cjCaps, cjDevInfo));
  370. DC_QUIT;
  371. }
  372. //
  373. // Allocate a physical device structure.
  374. //
  375. ppdev = EngAllocMem(FL_ZERO_MEMORY, sizeof(OSI_PDEV), OSI_ALLOC_TAG);
  376. if (ppdev == NULL)
  377. {
  378. ERROR_OUT(( "DrvEnablePDEV - Failed EngAllocMem"));
  379. DC_QUIT;
  380. }
  381. ppdev->hDriver = hDriver;
  382. //
  383. // Set up the current screen mode information based upon the supplied
  384. // mode settings.
  385. //
  386. if (!OSIInitializeMode((GDIINFO *)pdevcaps,
  387. pdm,
  388. ppdev,
  389. &gdiInfoNew,
  390. pdi))
  391. {
  392. ERROR_OUT(( "Failed to initialize mode"));
  393. DC_QUIT;
  394. }
  395. memcpy(pdevcaps, &gdiInfoNew, min(sizeof(GDIINFO), cjCaps));
  396. INIT_OUT(("DrvEnablePDEV: Returning DEVINFO:"));
  397. INIT_OUT((" FLONG flGraphicsCaps 0x%08x", pdi->flGraphicsCaps));
  398. INIT_OUT((" ULONG iDitherFormat %d", pdi->iDitherFormat));
  399. INIT_OUT((" HPALETTE hpalDefault 0x%08x", pdi->hpalDefault));
  400. INIT_OUT(("DrvEnablePDEV: Returning GDIINFO (pdevcaps):"));
  401. INIT_OUT((" ULONG ulVersion 0x%08x", gdiInfoNew.ulVersion));
  402. INIT_OUT((" ULONG ulHorzSize %d", gdiInfoNew.ulHorzSize));
  403. INIT_OUT((" ULONG ulVertSize %d", gdiInfoNew.ulVertSize));
  404. INIT_OUT((" ULONG ulHorzRes %d", gdiInfoNew.ulHorzRes));
  405. INIT_OUT((" ULONG ulVertRes %d", gdiInfoNew.ulVertRes));
  406. INIT_OUT((" ULONG cBitsPixel %d", gdiInfoNew.cBitsPixel));
  407. INIT_OUT((" ULONG cPlanes %d", gdiInfoNew.cPlanes));
  408. INIT_OUT((" ULONG ulNumColors %d", gdiInfoNew.ulNumColors));
  409. INIT_OUT((" ULONG ulDACRed 0x%08x", gdiInfoNew.ulDACRed));
  410. INIT_OUT((" ULONG ulDACGreen 0x%08x", gdiInfoNew.ulDACGreen));
  411. INIT_OUT((" ULONG ulDACBlue 0x%08x", gdiInfoNew.ulDACBlue));
  412. INIT_OUT((" ULONG ulHTOutputFormat %d", gdiInfoNew.ulHTOutputFormat));
  413. //
  414. // We have successfully initialized - return the new PDEV.
  415. //
  416. rc = (DHPDEV)ppdev;
  417. DC_EXIT_POINT:
  418. //
  419. // Release any resources if we failed to initialize.
  420. //
  421. if (rc == NULL)
  422. {
  423. ERROR_OUT(("DrvEnablePDEV failed; cleaning up by disabling"));
  424. DrvDisablePDEV(NULL);
  425. }
  426. DebugExitPVOID(DrvEnablePDEV, rc);
  427. return(rc);
  428. }
  429. //
  430. // DrvDisablePDEV - see NT DDK documentation
  431. //
  432. // Release the resources allocated in DrvEnablePDEV. If a surface has been
  433. // enabled DrvDisableSurface will have already been called.
  434. //
  435. // Note that this function will be called when previewing modes in the
  436. // Display Applet, but not at system shutdown.
  437. //
  438. // Note: In an error, we may call this before DrvEnablePDEV is done.
  439. //
  440. //
  441. VOID DrvDisablePDEV(DHPDEV dhpdev)
  442. {
  443. LPOSI_PDEV ppdev = (LPOSI_PDEV)dhpdev;
  444. DebugEntry(DrvDisablePDEV);
  445. INIT_OUT(("DrvDisablePDEV(dhpdev = 0x%08x)", dhpdev));
  446. //
  447. // Free the resources we allocated for the display.
  448. //
  449. if (ppdev != NULL)
  450. {
  451. if (ppdev->hpalCreated != NULL)
  452. {
  453. EngDeletePalette(ppdev->hpalCreated);
  454. ppdev->hpalCreated = NULL;
  455. }
  456. if (ppdev->pPal != NULL)
  457. {
  458. EngFreeMem(ppdev->pPal);
  459. ppdev->pPal = NULL;
  460. }
  461. EngFreeMem(ppdev);
  462. }
  463. DebugExitVOID(DrvDisablePDEV);
  464. }
  465. //
  466. // DrvCompletePDEV - see NT DDK documentation
  467. //
  468. // Stores the HPDEV, the engine's handle for this PDEV, in the DHPDEV.
  469. //
  470. VOID DrvCompletePDEV( DHPDEV dhpdev,
  471. HDEV hdev )
  472. {
  473. DebugEntry(DrvCompletePDEV);
  474. //
  475. // Store the device handle for our display handle.
  476. //
  477. INIT_OUT(("DrvCompletePDEV(dhpdev = 0x%08x, hdev = 0x%08x)", dhpdev, hdev));
  478. ((LPOSI_PDEV)dhpdev)->hdevEng = hdev;
  479. DebugExitVOID(DrvCompletePDEV);
  480. }
  481. //
  482. // DrvResetPDEV - see NT DDK documentation
  483. //
  484. // Allows us to reject dynamic screen changes if necessary ON NT4 ONLY
  485. // This is NOT CALLED on NT5.
  486. //
  487. BOOL DrvResetPDEV
  488. (
  489. DHPDEV dhpdevOld,
  490. DHPDEV dhpdevNew
  491. )
  492. {
  493. BOOL rc = TRUE;
  494. DebugEntry(DrvResetPDEV);
  495. INIT_OUT(("DrvResetPDEV(dhpdevOld = 0x%08x, dhpdevNew = 0x%08x)", dhpdevOld,
  496. dhpdevNew));
  497. //
  498. // We can only allow the display driver to change modes while DC-Share
  499. // is not running.
  500. //
  501. if (g_shmMappedMemory != NULL)
  502. {
  503. //
  504. // Deny the request.
  505. //
  506. rc = FALSE;
  507. }
  508. DebugExitDWORD(DrvResetPDEV, rc);
  509. return(rc);
  510. }
  511. //
  512. // DrvEnableSurface - see NT DDK documentation
  513. //
  514. // Creates the drawing surface and initializes driver components. This
  515. // function is called after DrvEnablePDEV, and performs the final device
  516. // initialization.
  517. //
  518. //
  519. HSURF DrvEnableSurface(DHPDEV dhpdev)
  520. {
  521. LPOSI_PDEV ppdev = (LPOSI_PDEV)dhpdev;
  522. HSURF hsurf;
  523. SIZEL sizl;
  524. LPOSI_DSURF pdsurf;
  525. HSURF rc = 0;
  526. DWORD returnedDataLength;
  527. DWORD MaxWidth, MaxHeight;
  528. VIDEO_MEMORY videoMemory;
  529. VIDEO_MEMORY_INFORMATION videoMemoryInformation;
  530. DebugEntry(DrvEnableSurface);
  531. INIT_OUT(("DrvEnableSurface: Parameters:"));
  532. INIT_OUT((" LPOSI_PDEV ppdev 0x%08x", ppdev));
  533. INIT_OUT((" HDRIVER ->hDriver 0x%08x", ppdev->hDriver));
  534. INIT_OUT((" INT ->cxScreen %d", ppdev->cxScreen));
  535. INIT_OUT((" INT ->cyScreen %d", ppdev->cyScreen));
  536. //
  537. // Now create our private surface structure.
  538. //
  539. // Whenever we get a call to draw directly to the screen, we'll get
  540. // passed a pointer to a SURFOBJ whose 'dhpdev' field will point
  541. // to our PDEV structure, and whose 'dhsurf' field will point to the
  542. // DSURF structure allocated below.
  543. //
  544. // Every device bitmap we create in DrvCreateDeviceBitmap will also
  545. // have its own unique DSURF structure allocated (but will share the
  546. // same PDEV). To make our code more polymorphic for handling drawing
  547. // to either the screen or an off-screen bitmap, we have the same
  548. // structure for both.
  549. //
  550. pdsurf = EngAllocMem(FL_ZERO_MEMORY, sizeof(OSI_DSURF), OSI_ALLOC_TAG);
  551. if (pdsurf == NULL)
  552. {
  553. ERROR_OUT(( "DrvEnableSurface - Failed pdsurf EngAllocMem"));
  554. DC_QUIT;
  555. }
  556. //
  557. // Store the screen surface details.
  558. //
  559. ppdev->pdsurfScreen = pdsurf;
  560. pdsurf->sizl.cx = ppdev->cxScreen;
  561. pdsurf->sizl.cy = ppdev->cyScreen;
  562. pdsurf->ppdev = ppdev;
  563. INIT_OUT(("DrvEnableSurface: Returning surface pointer 0x%08x", pdsurf));
  564. //
  565. // Only map the shared memory the first time we are called.
  566. //
  567. if (g_asSharedMemory == NULL)
  568. {
  569. //
  570. // Map the pointer to the shared section in the miniport driver
  571. //
  572. videoMemory.RequestedVirtualAddress = NULL;
  573. if (EngDeviceIoControl(ppdev->hDriver,
  574. IOCTL_VIDEO_MAP_VIDEO_MEMORY,
  575. &videoMemory,
  576. sizeof(VIDEO_MEMORY),
  577. &videoMemoryInformation,
  578. sizeof(VIDEO_MEMORY_INFORMATION),
  579. &returnedDataLength))
  580. {
  581. ERROR_OUT(( "Could not MAP miniport section"));
  582. DC_QUIT;
  583. }
  584. INIT_OUT(("DrvEnableSurface: Got video memory info from EngDeviceIoControl:"));
  585. INIT_OUT((" FrameBufferBase 0x%08x", videoMemoryInformation.FrameBufferBase));
  586. INIT_OUT((" FrameBufferLength 0x%08x", videoMemoryInformation.FrameBufferLength));
  587. g_shmSharedMemorySize = videoMemoryInformation.FrameBufferLength;
  588. // First block is shared memory header
  589. g_asSharedMemory = (LPSHM_SHARED_MEMORY)
  590. videoMemoryInformation.FrameBufferBase;
  591. // Next are the two large OA_FAST_DATA blocks
  592. g_poaData[0] = (LPOA_SHARED_DATA)(g_asSharedMemory + 1);
  593. g_poaData[1] = (LPOA_SHARED_DATA)(g_poaData[0] + 1);
  594. }
  595. //
  596. // Next, have GDI create the actual SURFOBJ.
  597. //
  598. // Our drawing surface is going to be 'device-managed', meaning that
  599. // GDI cannot draw on the framebuffer bits directly, and as such we
  600. // create the surface via EngCreateDeviceSurface. By doing this, we
  601. // ensure that GDI will only ever access the bitmaps bits via the Drv
  602. // calls that we've HOOKed.
  603. //
  604. sizl.cx = ppdev->cxScreen;
  605. sizl.cy = ppdev->cyScreen;
  606. //
  607. // Otherwise the primary display driver has its own bitmap used by the
  608. // physical hardware, so we do not need to do any drawing ourself.
  609. //
  610. INIT_OUT(("DrvEnableSurface: Calling EngCreateDeviceSurface with:"));
  611. INIT_OUT((" Sizl.cx %d", sizl.cx));
  612. INIT_OUT((" Sizl.cy %d", sizl.cy));
  613. INIT_OUT((" BitmapFormat %d", ppdev->iBitmapFormat));
  614. hsurf = EngCreateDeviceSurface( (DHSURF)pdsurf,
  615. sizl,
  616. ppdev->iBitmapFormat );
  617. if (hsurf == 0)
  618. {
  619. ERROR_OUT(( "Could not allocate surface"));
  620. DC_QUIT;
  621. }
  622. //
  623. // Store the screen surface handle.
  624. //
  625. ppdev->hsurfScreen = hsurf;
  626. //
  627. // Now associate the surface and the PDEV.
  628. //
  629. // We have to associate the surface we just created with our physical
  630. // device so that GDI can get information related to the PDEV when
  631. // it's drawing to the surface (such as, for example, the length of
  632. // styles on the device when simulating styled lines).
  633. //
  634. if (!EngAssociateSurface(hsurf, ppdev->hdevEng,
  635. HOOK_BITBLT |
  636. HOOK_STRETCHBLT |
  637. HOOK_PLGBLT |
  638. HOOK_TEXTOUT |
  639. HOOK_PAINT | // OBSOLETE
  640. HOOK_STROKEPATH |
  641. HOOK_FILLPATH |
  642. HOOK_STROKEANDFILLPATH |
  643. HOOK_LINETO |
  644. HOOK_COPYBITS |
  645. HOOK_STRETCHBLTROP |
  646. HOOK_TRANSPARENTBLT |
  647. HOOK_ALPHABLEND |
  648. HOOK_GRADIENTFILL |
  649. HOOK_SYNCHRONIZEACCESS)) // OBSOLETE
  650. {
  651. ERROR_OUT(( "DrvEnableSurface - Failed EngAssociateSurface"));
  652. DC_QUIT;
  653. }
  654. //
  655. // We have successfully associated the surface so return it to the GDI.
  656. //
  657. rc = hsurf;
  658. DC_EXIT_POINT:
  659. //
  660. // Tidy up any resources if we failed.
  661. //
  662. if (rc == 0)
  663. {
  664. DrvDisableSurface((DHPDEV) ppdev);
  665. }
  666. DebugExitPVOID(DrvEnableSurface, rc);
  667. return(rc);
  668. }
  669. //
  670. // DrvDisableSurface - see NT DDK documentation
  671. //
  672. // Free resources allocated by DrvEnableSurface. Release the surface.
  673. //
  674. // Note that this function will be called when previewing modes in the
  675. // Display Applet, but not at system shutdown. If you need to reset the
  676. // hardware at shutdown, you can do it in the miniport by providing a
  677. // 'HwResetHw' entry point in the VIDEO_HW_INITIALIZATION_DATA structure.
  678. //
  679. // Note: In an error case, we may call this before DrvEnableSurface is
  680. // completely done.
  681. //
  682. VOID DrvDisableSurface(DHPDEV dhpdev)
  683. {
  684. LPOSI_PDEV ppdev = (LPOSI_PDEV)dhpdev;
  685. DebugEntry(DrvDisableSurface);
  686. INIT_OUT(("DrvDisableSurface(dhpdev = 0x%08x)", dhpdev));
  687. if (ppdev->hsurfScreen != 0)
  688. {
  689. EngDeleteSurface(ppdev->hsurfScreen);
  690. }
  691. if (ppdev->pdsurfScreen != NULL)
  692. {
  693. EngFreeMem(ppdev->pdsurfScreen);
  694. }
  695. DebugExitVOID(DrvDisableSurface);
  696. }
  697. //
  698. // DrvEscape - see NT DDK documentation.
  699. //
  700. ULONG DrvEscape(SURFOBJ *pso,
  701. ULONG iEsc,
  702. ULONG cjIn,
  703. PVOID pvIn,
  704. ULONG cjOut,
  705. PVOID pvOut)
  706. {
  707. ULONG rc = FALSE;
  708. LPOSI_ESCAPE_HEADER pHeader;
  709. DebugEntry(DrvEscape);
  710. TRACE_OUT(("DrvEscape called with escape %d", iEsc));
  711. //
  712. // All functions we support use an identifier in the input data to make
  713. // sure that we don't try to use another driver's escape functions. If
  714. // the identifier is not present, we must not process the request.
  715. //
  716. // NOTE: This function is NOT protected for shared memory access
  717. // because it is responsible for allocating / deallocating the shared
  718. // memory.
  719. //
  720. //
  721. // Check the data is long enough to store our standard escape header.
  722. // If it is not big enough this must be an escape request for another
  723. // driver.
  724. //
  725. if (cjIn < sizeof(OSI_ESCAPE_HEADER))
  726. {
  727. INIT_OUT(("DrvEscape ignoring; input size %04d too small", cjIn));
  728. WARNING_OUT(("DrvEscape ignoring; input size %04d too small", cjIn));
  729. DC_QUIT;
  730. }
  731. if (cjOut < sizeof(OSI_ESCAPE_HEADER))
  732. {
  733. INIT_OUT(("DrvEscape ignoring; output size %04d too small", cjOut));
  734. WARNING_OUT(("DrvEscape ignoring; output size %04d too small", cjOut));
  735. DC_QUIT;
  736. }
  737. //
  738. // Check for our escape ID. If it is not our escape ID this must be an
  739. // escape request for another driver.
  740. //
  741. pHeader = pvIn;
  742. if (pHeader->identifier != OSI_ESCAPE_IDENTIFIER)
  743. {
  744. INIT_OUT(("DrvEscape ignoring; identifier 0x%08x is not for Salem", pHeader->identifier));
  745. WARNING_OUT(("DrvEscape ignoring; identifier 0x%08x is not for Salem", pHeader->identifier));
  746. DC_QUIT;
  747. }
  748. else if (pHeader->version != DCS_MAKE_VERSION())
  749. {
  750. INIT_OUT(("DrvEscape failing; version 0x%08x of Salem is not that of driver",
  751. pHeader->version));
  752. WARNING_OUT(("DrvEscape failing; version 0x%08x of Salem is not that of driver",
  753. pHeader->version));
  754. DC_QUIT;
  755. }
  756. //
  757. // Everything is tickety boo - process the request.
  758. //
  759. switch (iEsc)
  760. {
  761. case OSI_ESC_CODE:
  762. {
  763. //
  764. // This is a request from the share core. Pass it on to the
  765. // correct component.
  766. //
  767. TRACE_OUT(( "Function %ld", pHeader->escapeFn));
  768. if( (pHeader->escapeFn >= OSI_ESC_FIRST) &&
  769. (pHeader->escapeFn <= OSI_ESC_LAST ) )
  770. {
  771. //
  772. // OSI requests.
  773. //
  774. rc = OSI_DDProcessRequest(pso, cjIn, pvIn, cjOut, pvOut);
  775. }
  776. else if( (pHeader->escapeFn >= OSI_OE_ESC_FIRST) &&
  777. (pHeader->escapeFn <= OSI_OE_ESC_LAST ) )
  778. {
  779. //
  780. // Order Encoder requests.
  781. //
  782. rc = OE_DDProcessRequest(pso, cjIn, pvIn, cjOut, pvOut);
  783. }
  784. else if( (pHeader->escapeFn >= OSI_HET_ESC_FIRST) &&
  785. (pHeader->escapeFn <= OSI_HET_ESC_LAST) )
  786. {
  787. //
  788. // Non-locking (wnd tracking) HET requests
  789. //
  790. rc = HET_DDProcessRequest(pso, cjIn, pvIn, cjOut, pvOut);
  791. }
  792. else if( (pHeader->escapeFn >= OSI_SBC_ESC_FIRST) &&
  793. (pHeader->escapeFn <= OSI_SBC_ESC_LAST ) )
  794. {
  795. //
  796. // Send Bitmap Cache requests
  797. //
  798. rc = SBC_DDProcessRequest(pso, pHeader->escapeFn, pvIn, pvOut, cjOut);
  799. }
  800. else if( (pHeader->escapeFn >= OSI_SSI_ESC_FIRST) &&
  801. (pHeader->escapeFn <= OSI_SSI_ESC_LAST ) )
  802. {
  803. //
  804. // Save Screen Bits requests.
  805. //
  806. rc = SSI_DDProcessRequest(pHeader->escapeFn, pHeader, cjIn);
  807. }
  808. else if( (pHeader->escapeFn >= OSI_CM_ESC_FIRST) &&
  809. (pHeader->escapeFn <= OSI_CM_ESC_LAST ) )
  810. {
  811. //
  812. // Cursor Manager requests
  813. //
  814. rc = CM_DDProcessRequest(pso, cjIn, pvIn, cjOut, pvOut);
  815. }
  816. else if( (pHeader->escapeFn >= OSI_OA_ESC_FIRST) &&
  817. (pHeader->escapeFn <= OSI_OA_ESC_LAST ) )
  818. {
  819. //
  820. // Order Accumulator requests.
  821. //
  822. rc = OA_DDProcessRequest(pHeader->escapeFn, pHeader, cjIn);
  823. }
  824. else if( (pHeader->escapeFn >= OSI_BA_ESC_FIRST) &&
  825. (pHeader->escapeFn <= OSI_BA_ESC_LAST ) )
  826. {
  827. //
  828. // Bounds Accumulator requests.
  829. //
  830. rc = BA_DDProcessRequest(pHeader->escapeFn, pHeader, cjIn,
  831. pvOut, cjOut);
  832. }
  833. else
  834. {
  835. WARNING_OUT(( "Unknown function", pHeader->escapeFn));
  836. }
  837. }
  838. break;
  839. case WNDOBJ_SETUP:
  840. {
  841. if ((pHeader->escapeFn >= OSI_HET_WO_ESC_FIRST) &&
  842. (pHeader->escapeFn <= OSI_HET_WO_ESC_LAST))
  843. {
  844. TRACE_OUT(("WNDOBJ_SETUP Escape code - pass to HET"));
  845. rc = HET_DDProcessRequest(pso, cjIn, pvIn, cjOut, pvOut);
  846. }
  847. else
  848. {
  849. INIT_OUT(("WNDOBJ_SETUP Escape is unrecognized, ignore"));
  850. WARNING_OUT(("WNDOBJ_SETUP Escape is unrecognized, ignore"));
  851. }
  852. }
  853. break;
  854. default:
  855. {
  856. ERROR_OUT(( "Unrecognised request %lu", iEsc));
  857. }
  858. break;
  859. }
  860. DC_EXIT_POINT:
  861. DebugExitDWORD(DrvEscape, rc);
  862. return(rc);
  863. }
  864. //
  865. // DrvSetPalette - see NT DDK documentation.
  866. //
  867. BOOL DrvSetPalette(DHPDEV dhpdev,
  868. PALOBJ* ppalo,
  869. FLONG fl,
  870. ULONG iStart,
  871. ULONG cColors)
  872. {
  873. BOOL rc = FALSE;
  874. LPOSI_PDEV ppdev = (LPOSI_PDEV)dhpdev;
  875. DebugEntry(DrvSetPalette);
  876. //
  877. // Check that this doesn't hose our palette. Note that NT passes a
  878. // zero indexed array element and a count, hence to fill a palette, the
  879. // values are 'start at 0 with 256 colours'. Thus a total of 256 is
  880. // the maximum for our 8-bit palette.
  881. //
  882. if (iStart + cColors > OSI_MAX_PALETTE)
  883. {
  884. ERROR_OUT(("Overflow: start %lu count %lu", iStart, cColors));
  885. DC_QUIT;
  886. }
  887. //
  888. // Fill in the palette
  889. //
  890. if (cColors != PALOBJ_cGetColors(ppalo,
  891. iStart,
  892. cColors,
  893. (ULONG*)&ppdev->pPal[iStart]))
  894. {
  895. //
  896. // Don't bother tracing the return code - it's always 0.
  897. //
  898. ERROR_OUT(("Failed to read palette"));
  899. DC_QUIT;
  900. }
  901. //
  902. // BOGUS LAURABU!
  903. // For NT 5.0, do we need to turn around and reset the contents of
  904. // our created palette object with these new color values? Real
  905. // display drivers don't (S3 e.g.)
  906. //
  907. //
  908. // Set the flag in the PDEV to indicate that the palette has changed
  909. //
  910. ppdev->paletteChanged = TRUE;
  911. rc = TRUE;
  912. DC_EXIT_POINT:
  913. DebugExitBOOL(DrvSetPalette, rc);
  914. return(rc);
  915. }
  916. //
  917. // DrvGetModes - see NT DDK documentation
  918. //
  919. // Returns the list of available modes for the device.
  920. // As a mirroring driver, we return 0. That will cause NT GRE to use
  921. // whatever ChangeDisplaySettingsEx passed along.
  922. //
  923. ULONG DrvGetModes
  924. (
  925. HANDLE hDriver,
  926. ULONG cjSize,
  927. DEVMODEW* pdm
  928. )
  929. {
  930. return(0);
  931. }
  932. //
  933. // DrvAssertMode - see NT DDK documentation.
  934. //
  935. BOOL DrvAssertMode
  936. (
  937. DHPDEV dhpdev,
  938. BOOL bEnable
  939. )
  940. {
  941. LPOSI_PDEV ppdev = (LPOSI_PDEV)dhpdev;
  942. DebugEntry(DrvAssertMode);
  943. INIT_OUT(("DrvAssertMode(dhpdev = 0x%08x, bEnable = %d)", dhpdev, bEnable));
  944. //
  945. // Check for fullscreen switching.
  946. //
  947. if ((g_asSharedMemory != NULL) && (ppdev != NULL))
  948. {
  949. g_asSharedMemory->fullScreen = (BOOL)(!bEnable);
  950. TRACE_OUT(("Fullscreen is now %d", g_asSharedMemory->fullScreen));
  951. }
  952. DebugExitVOID(DrvAssertMode);
  953. return(TRUE);
  954. }
  955. //
  956. // Name: OSIInitializeMode
  957. //
  958. // Purpose:
  959. //
  960. // Initializes a bunch of fields in the pdev, devcaps (aka gdiinfo), and
  961. // devinfo based on the requested mode.
  962. //
  963. // Returns:
  964. //
  965. // TRUE - Successfully initialized the data
  966. // FALSE - Failed to set up mode data
  967. //
  968. // Params:
  969. //
  970. // pgdiRequested - GDI info from the primary display driver (empty in NT 5.0)
  971. // pdmRequested - DEVMODE info with GDI's requested settings for our driver
  972. // ppdev - Our driver's private copy of settings, values
  973. // pgdiReturn - GDI info to return for our driver
  974. // pdiReturn - DEVINFO to return for our driver
  975. //
  976. BOOL OSIInitializeMode
  977. (
  978. const GDIINFO* pgdiRequested,
  979. const DEVMODEW* pdmRequested,
  980. LPOSI_PDEV ppdev,
  981. GDIINFO* pgdiReturn,
  982. DEVINFO* pdiReturn
  983. )
  984. {
  985. BOOL rc = FALSE;
  986. HPALETTE hpal;
  987. ULONG cColors;
  988. ULONG iMode;
  989. DebugEntry(OSIInitializeMode);
  990. INIT_OUT(("DrvEnablePDEV: DEVMODEW requested contains:"));
  991. INIT_OUT((" Screen width -- %li", pdmRequested->dmPelsWidth));
  992. INIT_OUT((" Screen height -- %li", pdmRequested->dmPelsHeight));
  993. INIT_OUT((" Bits per pel -- %li", pdmRequested->dmBitsPerPel));
  994. INIT_OUT(("DrvEnablePDEV: DEVINFO parameter contains:"));
  995. INIT_OUT((" flGraphicsCaps -- 0x%08x", pdiReturn->flGraphicsCaps));
  996. INIT_OUT((" iDitherFormat -- 0x%08x", pdiReturn->iDitherFormat));
  997. INIT_OUT((" hpalDefault -- 0x%08x", pdiReturn->hpalDefault));
  998. INIT_OUT(("DrvEnablePDEV: GDIINFO (devcaps) parameter contains:"));
  999. INIT_OUT((" ULONG ulVersion 0x%08x", pgdiRequested->ulVersion));
  1000. INIT_OUT((" ULONG ulHorzSize %d", pgdiRequested->ulHorzSize));
  1001. INIT_OUT((" ULONG ulVertSize %d", pgdiRequested->ulVertSize));
  1002. INIT_OUT((" ULONG ulHorzRes %d", pgdiRequested->ulHorzRes));
  1003. INIT_OUT((" ULONG ulVertRes %d", pgdiRequested->ulVertRes));
  1004. INIT_OUT((" ULONG cBitsPixel %d", pgdiRequested->cBitsPixel));
  1005. INIT_OUT((" ULONG cPlanes %d", pgdiRequested->cPlanes));
  1006. INIT_OUT((" ULONG ulNumColors %d", pgdiRequested->ulNumColors));
  1007. INIT_OUT((" ULONG ulDACRed 0x%08x", pgdiRequested->ulDACRed));
  1008. INIT_OUT((" ULONG ulDACGreen 0x%08x", pgdiRequested->ulDACGreen));
  1009. INIT_OUT((" ULONG ulDACBlue 0x%08x", pgdiRequested->ulDACBlue));
  1010. INIT_OUT((" ULONG ulHTOutputFormat %d", pgdiRequested->ulHTOutputFormat));
  1011. //
  1012. // Fill in the GDIINFO we're returning with the info for our driver.
  1013. // First, copy the default settings.
  1014. //
  1015. *pgdiReturn = s_osiDefaultGdi;
  1016. //
  1017. // Second, update the values that vary depending on the requested
  1018. // mode and color depth.
  1019. //
  1020. pgdiReturn->ulHorzRes = pdmRequested->dmPelsWidth;
  1021. pgdiReturn->ulVertRes = pdmRequested->dmPelsHeight;
  1022. pgdiReturn->ulVRefresh = pdmRequested->dmDisplayFrequency;
  1023. pgdiReturn->ulLogPixelsX = pdmRequested->dmLogPixels;
  1024. pgdiReturn->ulLogPixelsY = pdmRequested->dmLogPixels;
  1025. //
  1026. // If this is NT 4.0 SP-3, we get passed in the original GDIINFO of
  1027. // the real display. If not, we need to fake up one.
  1028. //
  1029. if (pgdiRequested->cPlanes != 0)
  1030. {
  1031. //
  1032. // Now overwrite the defaults with the relevant information returned
  1033. // from the kernel driver:
  1034. //
  1035. pgdiReturn->cBitsPixel = pgdiRequested->cBitsPixel;
  1036. pgdiReturn->cPlanes = pgdiRequested->cPlanes;
  1037. pgdiReturn->ulDACRed = pgdiRequested->ulDACRed;
  1038. pgdiReturn->ulDACGreen = pgdiRequested->ulDACGreen;
  1039. pgdiReturn->ulDACBlue = pgdiRequested->ulDACBlue;
  1040. }
  1041. else
  1042. {
  1043. pgdiReturn->cBitsPixel = pdmRequested->dmBitsPerPel;
  1044. pgdiReturn->cPlanes = 1;
  1045. switch (pgdiReturn->cBitsPixel)
  1046. {
  1047. case 8:
  1048. pgdiReturn->ulDACRed = pgdiReturn->ulDACGreen = pgdiReturn->ulDACBlue = 8;
  1049. break;
  1050. case 24:
  1051. pgdiReturn->ulDACRed = 0x00FF0000;
  1052. pgdiReturn->ulDACGreen = 0x0000FF00;
  1053. pgdiReturn->ulDACBlue = 0x000000FF;
  1054. break;
  1055. default:
  1056. ERROR_OUT(("Invalid color depth in NT 5.0 mirror driver"));
  1057. DC_QUIT;
  1058. break;
  1059. }
  1060. }
  1061. //
  1062. // Now save private copies of info we're returning to GDI
  1063. //
  1064. ppdev->cxScreen = pgdiReturn->ulHorzRes;
  1065. ppdev->cyScreen = pgdiReturn->ulVertRes;
  1066. ppdev->cBitsPerPel = pgdiReturn->cBitsPixel * pgdiReturn->cPlanes;
  1067. if (ppdev->cBitsPerPel == 15)
  1068. ppdev->cBitsPerPel = 16;
  1069. ppdev->flRed = pgdiReturn->ulDACRed;
  1070. ppdev->flGreen = pgdiReturn->ulDACGreen;
  1071. ppdev->flBlue = pgdiReturn->ulDACBlue;
  1072. //
  1073. // Fill in the devinfo structure with the default 8bpp values, taking
  1074. // care not to trash the supplied hpalDefault (which allows us to
  1075. // query information about the real display driver's color format).
  1076. //
  1077. // On NT 5.0, we don't get passed on the screen palette at all, we need
  1078. // to create our own.
  1079. //
  1080. hpal = pdiReturn->hpalDefault;
  1081. *pdiReturn = s_osiDefaultDevInfo;
  1082. switch (pgdiReturn->cBitsPixel * pgdiReturn->cPlanes)
  1083. {
  1084. case 4:
  1085. {
  1086. //
  1087. // NT 4.0 SP-3 ONLY
  1088. //
  1089. pgdiReturn->ulNumColors = 16;
  1090. pgdiReturn->ulNumPalReg = 0;
  1091. pgdiReturn->ulHTOutputFormat = HT_FORMAT_4BPP;
  1092. pdiReturn->flGraphicsCaps &= ~GCAPS_PALMANAGED;
  1093. pdiReturn->iDitherFormat = BMF_4BPP;
  1094. ppdev->iBitmapFormat = BMF_4BPP;
  1095. cColors = 16;
  1096. goto AllocPalEntries;
  1097. }
  1098. break;
  1099. case 8:
  1100. {
  1101. pgdiReturn->ulNumColors = 20;
  1102. pgdiReturn->ulNumPalReg = 256;
  1103. pdiReturn->iDitherFormat = BMF_8BPP;
  1104. ppdev->iBitmapFormat = BMF_8BPP;
  1105. cColors = 256;
  1106. AllocPalEntries:
  1107. //
  1108. // Alloc memory for the palette entries.
  1109. //
  1110. ppdev->pPal = EngAllocMem( FL_ZERO_MEMORY,
  1111. sizeof(PALETTEENTRY) * cColors,
  1112. OSI_ALLOC_TAG );
  1113. if (ppdev->pPal == NULL)
  1114. {
  1115. ERROR_OUT(("Failed to allocate palette memory"));
  1116. DC_QUIT;
  1117. }
  1118. }
  1119. break;
  1120. case 15:
  1121. case 16:
  1122. {
  1123. //
  1124. // NT 4.0 SP-3 ONLY
  1125. //
  1126. pgdiReturn->ulHTOutputFormat = HT_FORMAT_16BPP;
  1127. pdiReturn->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  1128. pdiReturn->iDitherFormat = BMF_16BPP;
  1129. ppdev->iBitmapFormat = BMF_16BPP;
  1130. }
  1131. break;
  1132. case 24:
  1133. {
  1134. //
  1135. // DIB conversions will only work if we have a standard RGB
  1136. // surface for 24bpp.
  1137. //
  1138. pgdiReturn->ulHTOutputFormat = HT_FORMAT_24BPP;
  1139. pdiReturn->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  1140. pdiReturn->iDitherFormat = BMF_24BPP;
  1141. ppdev->iBitmapFormat = BMF_24BPP;
  1142. }
  1143. break;
  1144. case 32:
  1145. {
  1146. //
  1147. // NT 4.0 SP-3 ONLY
  1148. //
  1149. pgdiReturn->ulHTOutputFormat = HT_FORMAT_32BPP;
  1150. pdiReturn->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  1151. pdiReturn->iDitherFormat = BMF_32BPP;
  1152. ppdev->iBitmapFormat = BMF_32BPP;
  1153. }
  1154. break;
  1155. default:
  1156. {
  1157. //
  1158. // Unsupported bpp - pretend we are 8 bpp.
  1159. //
  1160. ERROR_OUT(("Unsupported bpp value: %d",
  1161. pgdiReturn->cBitsPixel * pgdiReturn->cPlanes));
  1162. DC_QUIT;
  1163. }
  1164. break;
  1165. }
  1166. if (!hpal)
  1167. {
  1168. //
  1169. // This is NT 5.0. We need to create a palette, either an 8bpp
  1170. // indexed one, or a 24bpp bitfield one.
  1171. //
  1172. if (ppdev->iBitmapFormat == BMF_8BPP)
  1173. {
  1174. ULONG ulLoop;
  1175. //
  1176. // We have to initialize the fixed part (top 10 and bottom 10)
  1177. // of the palette entries.
  1178. //
  1179. for (ulLoop = 0; ulLoop < 10; ulLoop++)
  1180. {
  1181. // First 10
  1182. ppdev->pPal[ulLoop] = s_aWinColors[ulLoop];
  1183. // Last 10
  1184. ppdev->pPal[256 - 10 + ulLoop] = s_aWinColors[ulLoop + 10];
  1185. }
  1186. // Create the palette from the entries.
  1187. hpal = EngCreatePalette(PAL_INDEXED, 256, (ULONG*)ppdev->pPal,
  1188. 0, 0, 0);
  1189. //
  1190. // Set the flag in the PDEV to indicate that the palette has
  1191. // changed.
  1192. //
  1193. ppdev->paletteChanged = TRUE;
  1194. }
  1195. else
  1196. {
  1197. ASSERT(ppdev->iBitmapFormat == BMF_24BPP);
  1198. hpal = EngCreatePalette(PAL_BITFIELDS, 0, NULL,
  1199. ppdev->flRed, ppdev->flGreen, ppdev->flBlue);
  1200. }
  1201. ppdev->hpalCreated = hpal;
  1202. if (!hpal)
  1203. {
  1204. ERROR_OUT(("DrvEnablePDEV: could not create DEVINFO palette"));
  1205. DC_QUIT;
  1206. }
  1207. }
  1208. else
  1209. {
  1210. //
  1211. // This is NT 4.0 SP-3. Get the real bitmasks for > 8 bpp and
  1212. // the current palette colors for <= 8 bpp.
  1213. //
  1214. if (pgdiReturn->cBitsPixel <= 8)
  1215. {
  1216. if (ppdev->iBitmapFormat == BMF_4BPP)
  1217. {
  1218. ASSERT(cColors == 16);
  1219. }
  1220. else
  1221. {
  1222. ASSERT(cColors == 256);
  1223. }
  1224. if (cColors != EngQueryPalette(hpal, &iMode, cColors,
  1225. (ULONG *)ppdev->pPal))
  1226. {
  1227. ERROR_OUT(("Failed to query current display palette"));
  1228. }
  1229. //
  1230. // Set the flag in the PDEV to indicate that the palette has
  1231. // changed.
  1232. //
  1233. ppdev->paletteChanged = TRUE;
  1234. }
  1235. else
  1236. {
  1237. ULONG aulBitmasks[3];
  1238. //
  1239. // Query the true color bitmasks.
  1240. //
  1241. cColors = EngQueryPalette(hpal,
  1242. &iMode,
  1243. sizeof(aulBitmasks) / sizeof(aulBitmasks[0]),
  1244. &aulBitmasks[0] );
  1245. if (cColors == 0)
  1246. {
  1247. ERROR_OUT(("Failed to query real bitmasks"));
  1248. }
  1249. if (iMode == PAL_INDEXED)
  1250. {
  1251. ERROR_OUT(("Bitmask palette is indexed"));
  1252. }
  1253. //
  1254. // Get the real bitmasks for NT 4.0 SP-3 displays since we
  1255. // get the same info the real global display does, and we need
  1256. // to parse the bits in BitBlts, color tanslations, etc.
  1257. //
  1258. ppdev->flRed = aulBitmasks[0];
  1259. ppdev->flGreen = aulBitmasks[1];
  1260. ppdev->flBlue = aulBitmasks[2];
  1261. }
  1262. }
  1263. pdiReturn->hpalDefault = hpal;
  1264. rc = TRUE;
  1265. INIT_OUT(("DrvEnablePDEV: Returning bitmasks of:"));
  1266. INIT_OUT((" red %08x", ppdev->flRed));
  1267. INIT_OUT((" green %08x", ppdev->flGreen));
  1268. INIT_OUT((" blue %08x", ppdev->flBlue));
  1269. DC_EXIT_POINT:
  1270. DebugExitBOOL(OSIInitializeMode, rc);
  1271. return(rc);
  1272. }
  1273. //
  1274. // FUNCTION: OSI_DDProcessRequest
  1275. //
  1276. // DESCRIPTION:
  1277. //
  1278. // Called by the display driver to process an OSI specific request
  1279. //
  1280. // PARAMETERS: pso - pointer to surface object
  1281. // cjIn - (IN) size of request block
  1282. // pvIn - (IN) pointer to request block
  1283. // cjOut - (IN) size of response block
  1284. // pvOut - (OUT) pointer to response block
  1285. //
  1286. // RETURNS: None
  1287. //
  1288. //
  1289. ULONG OSI_DDProcessRequest(SURFOBJ* pso,
  1290. UINT cjIn,
  1291. void * pvIn,
  1292. UINT cjOut,
  1293. void * pvOut)
  1294. {
  1295. ULONG rc;
  1296. LPOSI_ESCAPE_HEADER pHeader;
  1297. LPOSI_PDEV ppdev = (LPOSI_PDEV)pso->dhpdev;
  1298. DebugEntry(OSI_DDProcessRequest);
  1299. //
  1300. // Get the request number.
  1301. //
  1302. pHeader = pvIn;
  1303. switch (pHeader->escapeFn)
  1304. {
  1305. case OSI_ESC_INIT:
  1306. {
  1307. TRACE_OUT(("DrvEscape: OSI_ESC_INIT"));
  1308. ASSERT(cjOut == sizeof(OSI_INIT_REQUEST));
  1309. //
  1310. // Get shared memory block
  1311. //
  1312. OSI_DDInit(ppdev, (LPOSI_INIT_REQUEST)pvOut);
  1313. rc = TRUE;
  1314. }
  1315. break;
  1316. case OSI_ESC_TERM:
  1317. {
  1318. TRACE_OUT(("DrvEscape: OSI_ESC_TERM"));
  1319. ASSERT(cjIn == sizeof(OSI_TERM_REQUEST));
  1320. //
  1321. // Cleanup, NM is going away
  1322. //
  1323. OSI_DDTerm(ppdev);
  1324. rc = TRUE;
  1325. }
  1326. break;
  1327. case OSI_ESC_SYNC_NOW:
  1328. {
  1329. TRACE_OUT(("DrvEscape: OSI_ESC_SYNC_NOW"));
  1330. ASSERT(cjIn == sizeof(OSI_ESCAPE_HEADER));
  1331. //
  1332. // Resync with the 32-bit ring 3 core. This happens when
  1333. // somebody joins or leaves a share.
  1334. //
  1335. BA_ResetBounds();
  1336. OA_DDSyncUpdatesNow();
  1337. SBC_DDSyncUpdatesNow(ppdev);
  1338. rc = TRUE;
  1339. }
  1340. break;
  1341. default:
  1342. {
  1343. ERROR_OUT(("Unrecognised request %lu", pHeader->escapeFn));
  1344. rc = FALSE;
  1345. }
  1346. break;
  1347. }
  1348. DebugExitBOOL(OSI_DDProcessRequest, rc);
  1349. return(rc);
  1350. }
  1351. //
  1352. // Function: OSI_DDInit
  1353. //
  1354. // Description: Map the shared memory into Kernel and User space
  1355. //
  1356. // Parameters: count - size of the buffer to return to user space
  1357. // pData - pointer to the buffer to be returned to user space
  1358. //
  1359. // Returns: (none)
  1360. //
  1361. void OSI_DDInit(LPOSI_PDEV ppdev, LPOSI_INIT_REQUEST pResult)
  1362. {
  1363. DWORD memRemaining;
  1364. LPBYTE pBuffer;
  1365. VIDEO_SHARE_MEMORY ShareMemory;
  1366. VIDEO_SHARE_MEMORY_INFORMATION ShareMemoryInformation;
  1367. DWORD ReturnedDataLength;
  1368. DebugEntry(OSI_DDInit);
  1369. // Init to FALSE
  1370. pResult->result = FALSE;
  1371. // Initialize these to NULL
  1372. pResult->pSharedMemory = NULL;
  1373. pResult->poaData[0] = NULL;
  1374. pResult->poaData[1] = NULL;
  1375. pResult->sbcEnabled = FALSE;
  1376. //
  1377. // Check that the memory is available to the driver and that we are not
  1378. // in a race condition.
  1379. //
  1380. if (g_asSharedMemory == NULL)
  1381. {
  1382. ERROR_OUT(("No memory available"));
  1383. DC_QUIT;
  1384. }
  1385. if (g_shmMappedMemory != NULL)
  1386. {
  1387. //
  1388. // We will never come in here with two copies of NetMeeting running.
  1389. // The UI code prevents the second instance from starting long
  1390. // before app sharing is in the picture. Therefore, these are the
  1391. // only possibilities:
  1392. //
  1393. // (1) Previous version is almost shutdown but hasn't called OSI_DDTerm
  1394. // yet and new version is starting up and calls OSI_DDInit
  1395. //
  1396. // (2) Previous version terminated abnormally and never called
  1397. // OSI_DDTerm(). This code handles the second case. The first one
  1398. // is handled by the same code in the UI that prevents two copies
  1399. // from starting around the same time.
  1400. //
  1401. WARNING_OUT(("OSI_DDInit: NetMeeting did not shutdown cleanly last time"));
  1402. OSI_DDTerm(ppdev);
  1403. }
  1404. //
  1405. // Map the shared section into the caller's process.
  1406. //
  1407. INIT_OUT(("OSI_DDInit: Mapping 0x%08x bytes of kernel memory at 0x%08x into caller process",
  1408. g_shmSharedMemorySize, g_asSharedMemory));
  1409. ShareMemory.ProcessHandle = LongToHandle(-1);
  1410. ShareMemory.ViewOffset = 0;
  1411. ShareMemory.ViewSize = g_shmSharedMemorySize;
  1412. ShareMemory.RequestedVirtualAddress = NULL;
  1413. if (EngDeviceIoControl(ppdev->hDriver,
  1414. IOCTL_VIDEO_SHARE_VIDEO_MEMORY,
  1415. &ShareMemory,
  1416. sizeof(VIDEO_SHARE_MEMORY),
  1417. &ShareMemoryInformation,
  1418. sizeof(VIDEO_SHARE_MEMORY_INFORMATION),
  1419. &ReturnedDataLength) != 0)
  1420. {
  1421. ERROR_OUT(("Failed to map shared memory into calling process"));
  1422. DC_QUIT;
  1423. }
  1424. //
  1425. // USER MODE pointer (not valid in kernel mode)
  1426. //
  1427. INIT_OUT(("OSI_DDInit: Mapped 0x%08x bytes of kernel memory to user memory 0x%08x",
  1428. g_shmSharedMemorySize, ShareMemoryInformation.VirtualAddress));
  1429. g_shmMappedMemory = ShareMemoryInformation.VirtualAddress;
  1430. pResult->pSharedMemory = g_shmMappedMemory;
  1431. pResult->poaData[0] = ((LPSHM_SHARED_MEMORY)pResult->pSharedMemory) + 1;
  1432. pResult->poaData[1] = ((LPOA_SHARED_DATA)pResult->poaData[0]) + 1;
  1433. TRACE_OUT(("Shared memory %08lx %08lx %08lx",
  1434. pResult->pSharedMemory, pResult->poaData[0], pResult->poaData[1]));
  1435. //
  1436. // Clear out the shared memory, so it's ready for immediate use.
  1437. // NOTE THAT THIS SETS ALL VALUES TO FALSE.
  1438. // NOTE ALSO THAT THIS CLEARS the two OA_SHARED_DATAs also
  1439. //
  1440. RtlFillMemory(g_asSharedMemory, SHM_SIZE_USED, 0);
  1441. g_asSharedMemory->displayToCore.indexCount = 0;
  1442. //
  1443. // Set up our pointer to the variable part of the shared memory i.e.
  1444. // the part which is not used for the SHM_SHARED_MEMORY structure
  1445. // We must skip past g_asSharedMemory, two CM_FAST_DATA structs, and
  1446. // two OA_SHARED_DATA structs.
  1447. //
  1448. pBuffer = (LPBYTE)g_asSharedMemory;
  1449. pBuffer += SHM_SIZE_USED;
  1450. memRemaining = g_shmSharedMemorySize - SHM_SIZE_USED;
  1451. //
  1452. // Initialise the other components required for DC-Share
  1453. //
  1454. //
  1455. // Bounds accumulation
  1456. //
  1457. BA_DDInit();
  1458. //
  1459. // Cursor
  1460. //
  1461. if (!CM_DDInit(ppdev))
  1462. {
  1463. ERROR_OUT(("CM failed to init"));
  1464. DC_QUIT;
  1465. }
  1466. //
  1467. // Send Bitmap Cache
  1468. // NOTE that if it initializes OK but no caching allowed, we will continue.
  1469. //
  1470. // This will fill in the tile buffers & info. If no SBC caching allowed,
  1471. // the sbcEnabled field will be FALSE.
  1472. //
  1473. if (SBC_DDInit(ppdev, pBuffer, memRemaining, pResult))
  1474. {
  1475. pResult->sbcEnabled = TRUE;
  1476. }
  1477. //
  1478. // Mark memory as ready to use.
  1479. //
  1480. pResult->result = TRUE;
  1481. DC_EXIT_POINT:
  1482. DebugExitVOID(OSI_DDInit);
  1483. }
  1484. //
  1485. // Function: OSI_DDTerm
  1486. //
  1487. // Description: Cleanup when NM shuts down
  1488. //
  1489. // Returns: (none)
  1490. //
  1491. void OSI_DDTerm(LPOSI_PDEV ppdev)
  1492. {
  1493. DebugEntry(OSI_DDTerm);
  1494. //
  1495. // Check for a valid address - must be non-NULL.
  1496. //
  1497. if (!g_asSharedMemory)
  1498. {
  1499. ERROR_OUT(("Invalid memory"));
  1500. DC_QUIT;
  1501. }
  1502. //
  1503. // Terminate the dependent components.
  1504. //
  1505. //
  1506. // Hosted Entity Tracker
  1507. //
  1508. HET_DDTerm();
  1509. //
  1510. // Order Encoding
  1511. //
  1512. OE_DDTerm();
  1513. //
  1514. // Send Bitmap Cache
  1515. //
  1516. SBC_DDTerm();
  1517. //
  1518. // Cursor manager.
  1519. //
  1520. CM_DDTerm();
  1521. //
  1522. // The shared memory will be unmapped automatically in this process
  1523. // by OS cleanup, in both NT4 and NT5
  1524. //
  1525. g_shmMappedMemory = NULL;
  1526. DC_EXIT_POINT:
  1527. DebugExitVOID(OSI_DDTerm);
  1528. }