Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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