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.

599 lines
20 KiB

  1. /******************************Module*Header*******************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: screen.c
  8. *
  9. * Initializes the GDIINFO and DEVINFO structures for DrvEnablePDEV.
  10. *
  11. * Copyright (c) 1992-1998 Microsoft Corporation
  12. \**************************************************************************/
  13. #include "driver.h"
  14. #define SYSTM_LOGFONT {16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH | FF_DONTCARE,L"System"}
  15. #define HELVE_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_STROKE_PRECIS,PROOF_QUALITY,VARIABLE_PITCH | FF_DONTCARE,L"MS Sans Serif"}
  16. #define COURI_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_STROKE_PRECIS,PROOF_QUALITY,FIXED_PITCH | FF_DONTCARE, L"Courier"}
  17. // This is the basic devinfo for a default driver. This is used as a base and customized based
  18. // on information passed back from the miniport driver.
  19. const DEVINFO gDevInfoFrameBuffer = {
  20. ( GCAPS_OPAQUERECT
  21. | GCAPS_MONO_DITHER
  22. ), /* Graphics capabilities */
  23. SYSTM_LOGFONT, /* Default font description */
  24. HELVE_LOGFONT, /* ANSI variable font description */
  25. COURI_LOGFONT, /* ANSI fixed font description */
  26. 0, /* Count of device fonts */
  27. 0, /* Preferred DIB format */
  28. 8, /* Width of color dither */
  29. 8, /* Height of color dither */
  30. 0 /* Default palette to use for this device */
  31. };
  32. /******************************Public*Routine******************************\
  33. * bInitSURF
  34. *
  35. * Enables the surface. Maps the frame buffer into memory.
  36. *
  37. \**************************************************************************/
  38. BOOL bInitSURF(PPDEV ppdev, BOOL bFirst)
  39. {
  40. DWORD returnedDataLength;
  41. DWORD MaxWidth, MaxHeight;
  42. VIDEO_MEMORY videoMemory;
  43. VIDEO_MEMORY_INFORMATION videoMemoryInformation;
  44. ULONG RemappingNeeded = 0;
  45. //
  46. // Set the current mode into the hardware.
  47. //
  48. if (EngDeviceIoControl(ppdev->hDriver,
  49. IOCTL_VIDEO_SET_CURRENT_MODE,
  50. &(ppdev->ulMode),
  51. sizeof(ULONG),
  52. &RemappingNeeded,
  53. sizeof(ULONG),
  54. &returnedDataLength))
  55. {
  56. DISPDBG((1, "DISP bInitSURF failed IOCTL_SET_MODE\n"));
  57. return(FALSE);
  58. }
  59. //
  60. // If this is the first time we enable the surface we need to map in the
  61. // memory also.
  62. //
  63. if (bFirst || RemappingNeeded)
  64. {
  65. videoMemory.RequestedVirtualAddress = NULL;
  66. if (EngDeviceIoControl(ppdev->hDriver,
  67. IOCTL_VIDEO_MAP_VIDEO_MEMORY,
  68. &videoMemory,
  69. sizeof(VIDEO_MEMORY),
  70. &videoMemoryInformation,
  71. sizeof(VIDEO_MEMORY_INFORMATION),
  72. &returnedDataLength))
  73. {
  74. DISPDBG((1, "DISP bInitSURF failed IOCTL_VIDEO_MAP\n"));
  75. return(FALSE);
  76. }
  77. ppdev->pjScreen = (PBYTE)(videoMemoryInformation.FrameBufferBase);
  78. if (videoMemoryInformation.FrameBufferBase !=
  79. videoMemoryInformation.VideoRamBase)
  80. {
  81. DISPDBG((0, "VideoRamBase does not correspond to FrameBufferBase\n"));
  82. }
  83. //
  84. // Make sure we can access this video memory
  85. //
  86. *(PULONG)(ppdev->pjScreen) = 0xaa55aa55;
  87. if (*(PULONG)(ppdev->pjScreen) != 0xaa55aa55) {
  88. DISPDBG((1, "Frame buffer memory is not accessible.\n"));
  89. return(FALSE);
  90. }
  91. ppdev->cScreenSize = videoMemoryInformation.VideoRamLength;
  92. //
  93. // Initialize the head of the offscreen list to NULL.
  94. //
  95. ppdev->pOffscreenList = NULL;
  96. // It's a hardware pointer; set up pointer attributes.
  97. MaxHeight = ppdev->PointerCapabilities.MaxHeight;
  98. // Allocate space for two DIBs (data/mask) for the pointer. If this
  99. // device supports a color Pointer, we will allocate a larger bitmap.
  100. // If this is a color bitmap we allocate for the largest possible
  101. // bitmap because we have no idea of what the pixel depth might be.
  102. // Width rounded up to nearest byte multiple
  103. if (!(ppdev->PointerCapabilities.Flags & VIDEO_MODE_COLOR_POINTER))
  104. {
  105. MaxWidth = (ppdev->PointerCapabilities.MaxWidth + 7) / 8;
  106. }
  107. else
  108. {
  109. MaxWidth = ppdev->PointerCapabilities.MaxWidth * sizeof(DWORD);
  110. }
  111. ppdev->cjPointerAttributes =
  112. sizeof(VIDEO_POINTER_ATTRIBUTES) +
  113. ((sizeof(UCHAR) * MaxWidth * MaxHeight) * 2);
  114. ppdev->pPointerAttributes = (PVIDEO_POINTER_ATTRIBUTES)
  115. EngAllocMem(0, ppdev->cjPointerAttributes, ALLOC_TAG);
  116. if (ppdev->pPointerAttributes == NULL) {
  117. DISPDBG((0, "bInitPointer EngAllocMem failed\n"));
  118. return(FALSE);
  119. }
  120. ppdev->pPointerAttributes->Flags = ppdev->PointerCapabilities.Flags;
  121. ppdev->pPointerAttributes->WidthInBytes = MaxWidth;
  122. ppdev->pPointerAttributes->Width = ppdev->PointerCapabilities.MaxWidth;
  123. ppdev->pPointerAttributes->Height = MaxHeight;
  124. ppdev->pPointerAttributes->Column = 0;
  125. ppdev->pPointerAttributes->Row = 0;
  126. ppdev->pPointerAttributes->Enable = 0;
  127. }
  128. return(TRUE);
  129. }
  130. /******************************Public*Routine******************************\
  131. * vDisableSURF
  132. *
  133. * Disable the surface. Un-Maps the frame in memory.
  134. *
  135. \**************************************************************************/
  136. VOID vDisableSURF(PPDEV ppdev)
  137. {
  138. DWORD returnedDataLength;
  139. VIDEO_MEMORY videoMemory;
  140. videoMemory.RequestedVirtualAddress = (PVOID) ppdev->pjScreen;
  141. if (EngDeviceIoControl(ppdev->hDriver,
  142. IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
  143. &videoMemory,
  144. sizeof(VIDEO_MEMORY),
  145. NULL,
  146. 0,
  147. &returnedDataLength))
  148. {
  149. DISPDBG((0, "DISP vDisableSURF failed IOCTL_VIDEO_UNMAP\n"));
  150. }
  151. }
  152. /******************************Public*Routine******************************\
  153. * bInitPDEV
  154. *
  155. * Determine the mode we should be in based on the DEVMODE passed in.
  156. * Query mini-port to get information needed to fill in the DevInfo and the
  157. * GdiInfo .
  158. *
  159. \**************************************************************************/
  160. BOOL bInitPDEV(
  161. PPDEV ppdev,
  162. DEVMODEW *pDevMode,
  163. GDIINFO *pGdiInfo,
  164. DEVINFO *pDevInfo)
  165. {
  166. ULONG cModes;
  167. PVIDEO_MODE_INFORMATION pVideoBuffer, pVideoModeSelected, pVideoTemp;
  168. VIDEO_COLOR_CAPABILITIES colorCapabilities;
  169. ULONG ulTemp;
  170. BOOL bSelectDefault;
  171. ULONG cbModeSize;
  172. //
  173. // calls the miniport to get mode information.
  174. //
  175. cModes = getAvailableModes(ppdev->hDriver, &pVideoBuffer, &cbModeSize);
  176. if (cModes == 0)
  177. {
  178. return(FALSE);
  179. }
  180. //
  181. // Now see if the requested mode has a match in that table.
  182. //
  183. pVideoModeSelected = NULL;
  184. pVideoTemp = pVideoBuffer;
  185. if ((pDevMode->dmPelsWidth == 0) &&
  186. (pDevMode->dmPelsHeight == 0) &&
  187. (pDevMode->dmBitsPerPel == 0) &&
  188. (pDevMode->dmDisplayFrequency == 0))
  189. {
  190. DISPDBG((2, "Default mode requested"));
  191. bSelectDefault = TRUE;
  192. }
  193. else
  194. {
  195. DISPDBG((2, "Requested mode...\n"));
  196. DISPDBG((2, " Screen width -- %li\n", pDevMode->dmPelsWidth));
  197. DISPDBG((2, " Screen height -- %li\n", pDevMode->dmPelsHeight));
  198. DISPDBG((2, " Bits per pel -- %li\n", pDevMode->dmBitsPerPel));
  199. DISPDBG((2, " Frequency -- %li\n", pDevMode->dmDisplayFrequency));
  200. bSelectDefault = FALSE;
  201. }
  202. while (cModes--)
  203. {
  204. if (pVideoTemp->Length != 0)
  205. {
  206. if (bSelectDefault ||
  207. ((pVideoTemp->VisScreenWidth == pDevMode->dmPelsWidth) &&
  208. (pVideoTemp->VisScreenHeight == pDevMode->dmPelsHeight) &&
  209. (pVideoTemp->BitsPerPlane *
  210. pVideoTemp->NumberOfPlanes == pDevMode->dmBitsPerPel) &&
  211. (pVideoTemp->Frequency == pDevMode->dmDisplayFrequency)))
  212. {
  213. pVideoModeSelected = pVideoTemp;
  214. DISPDBG((3, "Found a match\n")) ;
  215. break;
  216. }
  217. }
  218. pVideoTemp = (PVIDEO_MODE_INFORMATION)
  219. (((PUCHAR)pVideoTemp) + cbModeSize);
  220. }
  221. //
  222. // If no mode has been found, return an error
  223. //
  224. if (pVideoModeSelected == NULL)
  225. {
  226. EngFreeMem(pVideoBuffer);
  227. DISPDBG((0,"DISP bInitPDEV failed - no valid modes\n"));
  228. return(FALSE);
  229. }
  230. //
  231. // Fill in the GDIINFO data structure with the information returned from
  232. // the kernel driver.
  233. //
  234. ppdev->ulMode = pVideoModeSelected->ModeIndex;
  235. ppdev->cxScreen = pVideoModeSelected->VisScreenWidth;
  236. ppdev->cyScreen = pVideoModeSelected->VisScreenHeight;
  237. ppdev->ulBitCount = pVideoModeSelected->BitsPerPlane *
  238. pVideoModeSelected->NumberOfPlanes;
  239. ppdev->lDeltaScreen = pVideoModeSelected->ScreenStride;
  240. ppdev->flRed = pVideoModeSelected->RedMask;
  241. ppdev->flGreen = pVideoModeSelected->GreenMask;
  242. ppdev->flBlue = pVideoModeSelected->BlueMask;
  243. pGdiInfo->ulVersion = GDI_DRIVER_VERSION;
  244. pGdiInfo->ulTechnology = DT_RASDISPLAY;
  245. pGdiInfo->ulHorzSize = pVideoModeSelected->XMillimeter;
  246. pGdiInfo->ulVertSize = pVideoModeSelected->YMillimeter;
  247. pGdiInfo->ulHorzRes = ppdev->cxScreen;
  248. pGdiInfo->ulVertRes = ppdev->cyScreen;
  249. pGdiInfo->ulPanningHorzRes = ppdev->cxScreen;
  250. pGdiInfo->ulPanningVertRes = ppdev->cyScreen;
  251. pGdiInfo->cBitsPixel = pVideoModeSelected->BitsPerPlane;
  252. pGdiInfo->cPlanes = pVideoModeSelected->NumberOfPlanes;
  253. pGdiInfo->ulVRefresh = pVideoModeSelected->Frequency;
  254. pGdiInfo->ulBltAlignment = 1; // We don't have accelerated screen-
  255. // to-screen blts, and any
  256. // window alignment is okay
  257. pGdiInfo->ulLogPixelsX = pDevMode->dmLogPixels;
  258. pGdiInfo->ulLogPixelsY = pDevMode->dmLogPixels;
  259. #ifdef MIPS
  260. if (ppdev->ulBitCount == 8)
  261. pGdiInfo->flTextCaps = (TC_RA_ABLE | TC_SCROLLBLT);
  262. else
  263. #endif
  264. pGdiInfo->flTextCaps = TC_RA_ABLE;
  265. pGdiInfo->flRaster = 0; // flRaster is reserved by DDI
  266. pGdiInfo->ulDACRed = pVideoModeSelected->NumberRedBits;
  267. pGdiInfo->ulDACGreen = pVideoModeSelected->NumberGreenBits;
  268. pGdiInfo->ulDACBlue = pVideoModeSelected->NumberBlueBits;
  269. pGdiInfo->ulAspectX = 0x24; // One-to-one aspect ratio
  270. pGdiInfo->ulAspectY = 0x24;
  271. pGdiInfo->ulAspectXY = 0x33;
  272. pGdiInfo->xStyleStep = 1; // A style unit is 3 pels
  273. pGdiInfo->yStyleStep = 1;
  274. pGdiInfo->denStyleStep = 3;
  275. pGdiInfo->ptlPhysOffset.x = 0;
  276. pGdiInfo->ptlPhysOffset.y = 0;
  277. pGdiInfo->szlPhysSize.cx = 0;
  278. pGdiInfo->szlPhysSize.cy = 0;
  279. // RGB and CMY color info.
  280. //
  281. // try to get it from the miniport.
  282. // if the miniport doesn ot support this feature, use defaults.
  283. //
  284. if (EngDeviceIoControl(ppdev->hDriver,
  285. IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES,
  286. NULL,
  287. 0,
  288. &colorCapabilities,
  289. sizeof(VIDEO_COLOR_CAPABILITIES),
  290. &ulTemp))
  291. {
  292. DISPDBG((2, "getcolorCapabilities failed \n"));
  293. pGdiInfo->ciDevice.Red.x = 6700;
  294. pGdiInfo->ciDevice.Red.y = 3300;
  295. pGdiInfo->ciDevice.Red.Y = 0;
  296. pGdiInfo->ciDevice.Green.x = 2100;
  297. pGdiInfo->ciDevice.Green.y = 7100;
  298. pGdiInfo->ciDevice.Green.Y = 0;
  299. pGdiInfo->ciDevice.Blue.x = 1400;
  300. pGdiInfo->ciDevice.Blue.y = 800;
  301. pGdiInfo->ciDevice.Blue.Y = 0;
  302. pGdiInfo->ciDevice.AlignmentWhite.x = 3127;
  303. pGdiInfo->ciDevice.AlignmentWhite.y = 3290;
  304. pGdiInfo->ciDevice.AlignmentWhite.Y = 0;
  305. pGdiInfo->ciDevice.RedGamma = 20000;
  306. pGdiInfo->ciDevice.GreenGamma = 20000;
  307. pGdiInfo->ciDevice.BlueGamma = 20000;
  308. }
  309. else
  310. {
  311. pGdiInfo->ciDevice.Red.x = colorCapabilities.RedChromaticity_x;
  312. pGdiInfo->ciDevice.Red.y = colorCapabilities.RedChromaticity_y;
  313. pGdiInfo->ciDevice.Red.Y = 0;
  314. pGdiInfo->ciDevice.Green.x = colorCapabilities.GreenChromaticity_x;
  315. pGdiInfo->ciDevice.Green.y = colorCapabilities.GreenChromaticity_y;
  316. pGdiInfo->ciDevice.Green.Y = 0;
  317. pGdiInfo->ciDevice.Blue.x = colorCapabilities.BlueChromaticity_x;
  318. pGdiInfo->ciDevice.Blue.y = colorCapabilities.BlueChromaticity_y;
  319. pGdiInfo->ciDevice.Blue.Y = 0;
  320. pGdiInfo->ciDevice.AlignmentWhite.x = colorCapabilities.WhiteChromaticity_x;
  321. pGdiInfo->ciDevice.AlignmentWhite.y = colorCapabilities.WhiteChromaticity_y;
  322. pGdiInfo->ciDevice.AlignmentWhite.Y = colorCapabilities.WhiteChromaticity_Y;
  323. // if we have a color device store the three color gamma values,
  324. // otherwise store the unique gamma value in all three.
  325. if (colorCapabilities.AttributeFlags & VIDEO_DEVICE_COLOR)
  326. {
  327. pGdiInfo->ciDevice.RedGamma = colorCapabilities.RedGamma;
  328. pGdiInfo->ciDevice.GreenGamma = colorCapabilities.GreenGamma;
  329. pGdiInfo->ciDevice.BlueGamma = colorCapabilities.BlueGamma;
  330. }
  331. else
  332. {
  333. pGdiInfo->ciDevice.RedGamma = colorCapabilities.WhiteGamma;
  334. pGdiInfo->ciDevice.GreenGamma = colorCapabilities.WhiteGamma;
  335. pGdiInfo->ciDevice.BlueGamma = colorCapabilities.WhiteGamma;
  336. }
  337. };
  338. pGdiInfo->ciDevice.Cyan.x = 0;
  339. pGdiInfo->ciDevice.Cyan.y = 0;
  340. pGdiInfo->ciDevice.Cyan.Y = 0;
  341. pGdiInfo->ciDevice.Magenta.x = 0;
  342. pGdiInfo->ciDevice.Magenta.y = 0;
  343. pGdiInfo->ciDevice.Magenta.Y = 0;
  344. pGdiInfo->ciDevice.Yellow.x = 0;
  345. pGdiInfo->ciDevice.Yellow.y = 0;
  346. pGdiInfo->ciDevice.Yellow.Y = 0;
  347. // No dye correction for raster displays.
  348. pGdiInfo->ciDevice.MagentaInCyanDye = 0;
  349. pGdiInfo->ciDevice.YellowInCyanDye = 0;
  350. pGdiInfo->ciDevice.CyanInMagentaDye = 0;
  351. pGdiInfo->ciDevice.YellowInMagentaDye = 0;
  352. pGdiInfo->ciDevice.CyanInYellowDye = 0;
  353. pGdiInfo->ciDevice.MagentaInYellowDye = 0;
  354. pGdiInfo->ulDevicePelsDPI = 0; // For printers only
  355. pGdiInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA;
  356. // Note: this should be modified later to take into account the size
  357. // of the display and the resolution.
  358. pGdiInfo->ulHTPatternSize = HT_PATSIZE_4x4_M;
  359. pGdiInfo->flHTFlags = HT_FLAG_ADDITIVE_PRIMS;
  360. // Fill in the basic devinfo structure
  361. *pDevInfo = gDevInfoFrameBuffer;
  362. // Fill in the rest of the devinfo and GdiInfo structures.
  363. if (ppdev->ulBitCount == 8)
  364. {
  365. // It is Palette Managed.
  366. pGdiInfo->ulNumColors = 20;
  367. pGdiInfo->ulNumPalReg = 1 << ppdev->ulBitCount;
  368. pDevInfo->flGraphicsCaps |= (GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  369. pGdiInfo->ulHTOutputFormat = HT_FORMAT_8BPP;
  370. pDevInfo->iDitherFormat = BMF_8BPP;
  371. // Assuming palette is orthogonal - all colors are same size.
  372. ppdev->cPaletteShift = 8 - pGdiInfo->ulDACRed;
  373. }
  374. else
  375. {
  376. pGdiInfo->ulNumColors = (ULONG) (-1);
  377. pGdiInfo->ulNumPalReg = 0;
  378. if (ppdev->ulBitCount == 16)
  379. {
  380. pGdiInfo->ulHTOutputFormat = HT_FORMAT_16BPP;
  381. pDevInfo->iDitherFormat = BMF_16BPP;
  382. }
  383. else if (ppdev->ulBitCount == 24)
  384. {
  385. pGdiInfo->ulHTOutputFormat = HT_FORMAT_24BPP;
  386. pDevInfo->iDitherFormat = BMF_24BPP;
  387. }
  388. else
  389. {
  390. pGdiInfo->ulHTOutputFormat = HT_FORMAT_32BPP;
  391. pDevInfo->iDitherFormat = BMF_32BPP;
  392. }
  393. }
  394. EngFreeMem(pVideoBuffer);
  395. return(TRUE);
  396. }
  397. /******************************Public*Routine******************************\
  398. * getAvailableModes
  399. *
  400. * Calls the miniport to get the list of modes supported by the kernel driver,
  401. * and returns the list of modes supported by the diplay driver among those
  402. *
  403. * returns the number of entries in the videomode buffer.
  404. * 0 means no modes are supported by the miniport or that an error occured.
  405. *
  406. * NOTE: the buffer must be freed up by the caller.
  407. *
  408. \**************************************************************************/
  409. DWORD getAvailableModes(
  410. HANDLE hDriver,
  411. PVIDEO_MODE_INFORMATION *modeInformation,
  412. DWORD *cbModeSize)
  413. {
  414. ULONG ulTemp;
  415. VIDEO_NUM_MODES modes;
  416. PVIDEO_MODE_INFORMATION pVideoTemp;
  417. //
  418. // Get the number of modes supported by the mini-port
  419. //
  420. if (EngDeviceIoControl(hDriver,
  421. IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES,
  422. NULL,
  423. 0,
  424. &modes,
  425. sizeof(VIDEO_NUM_MODES),
  426. &ulTemp))
  427. {
  428. DISPDBG((0, "getAvailableModes failed VIDEO_QUERY_NUM_AVAIL_MODES\n"));
  429. return(0);
  430. }
  431. *cbModeSize = modes.ModeInformationLength;
  432. //
  433. // Allocate the buffer for the mini-port to write the modes in.
  434. //
  435. *modeInformation = (PVIDEO_MODE_INFORMATION)
  436. EngAllocMem(0, modes.NumModes *
  437. modes.ModeInformationLength, ALLOC_TAG);
  438. if (*modeInformation == (PVIDEO_MODE_INFORMATION) NULL)
  439. {
  440. DISPDBG((0, "getAvailableModes failed EngAllocMem\n"));
  441. return 0;
  442. }
  443. //
  444. // Ask the mini-port to fill in the available modes.
  445. //
  446. if (EngDeviceIoControl(hDriver,
  447. IOCTL_VIDEO_QUERY_AVAIL_MODES,
  448. NULL,
  449. 0,
  450. *modeInformation,
  451. modes.NumModes * modes.ModeInformationLength,
  452. &ulTemp))
  453. {
  454. DISPDBG((0, "getAvailableModes failed VIDEO_QUERY_AVAIL_MODES\n"));
  455. EngFreeMem(*modeInformation);
  456. *modeInformation = (PVIDEO_MODE_INFORMATION) NULL;
  457. return(0);
  458. }
  459. //
  460. // Now see which of these modes are supported by the display driver.
  461. // As an internal mechanism, set the length to 0 for the modes we
  462. // DO NOT support.
  463. //
  464. ulTemp = modes.NumModes;
  465. pVideoTemp = *modeInformation;
  466. //
  467. // Mode is rejected if it is not one plane, or not graphics, or is not
  468. // one of 8, 16 or 32 bits per pel.
  469. //
  470. while (ulTemp--)
  471. {
  472. if ((pVideoTemp->NumberOfPlanes != 1 ) ||
  473. !(pVideoTemp->AttributeFlags & VIDEO_MODE_GRAPHICS) ||
  474. (pVideoTemp->AttributeFlags & VIDEO_MODE_BANKED) ||
  475. ((pVideoTemp->BitsPerPlane != 8) &&
  476. (pVideoTemp->BitsPerPlane != 16) &&
  477. (pVideoTemp->BitsPerPlane != 24) &&
  478. (pVideoTemp->BitsPerPlane != 32)))
  479. {
  480. pVideoTemp->Length = 0;
  481. }
  482. pVideoTemp = (PVIDEO_MODE_INFORMATION)
  483. (((PUCHAR)pVideoTemp) + modes.ModeInformationLength);
  484. }
  485. return modes.NumModes;
  486. }