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.

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