File:  [WindowsNT SDKs] / ntddk / src / perf / vgacode / enable.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:31:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntddk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

/******************************Module*Header*******************************\
* Module Name: enable.c
*
* Functions to enable and disable the driver
*
* Copyright (c) 1992 Microsoft Corporation
\**************************************************************************/


#include "driver.h"
#include "winperf.h"        // for Performance API strucuture definitions  (PERFCTR)

PPERF_COUNTER_BLOCK     pCounterBlock;  // data structure for counter values (PERFCTR)

FLONG   gflDrv = 0;
#ifdef  FIREWALLS
LONG    cPDEV = 0;                  // PDEV counter for checking Engine
#endif

extern GDIINFO gaulCap;             // in gdiinfo.c
extern LOGPALETTE logPalVGA;        // in gdiinfo.c
extern BYTE gaajPat[19][32];        // in gdiinfo.c
extern DEVINFO devinfoVGA;          // in gdiinfo.c
extern LPBYTE pPtrSave;

BOOL SetUpBanking(PDEVSURF, PPDEV);
BOOL bInitPointer(PPDEV);

extern ajConvertBuffer[1];            // Arbitrary sized array!

static  DRVFN   gadrvfn[] = {
    {   INDEX_DrvEnablePDEV,            (PFN) DrvEnablePDEV             },
    {   INDEX_DrvCompletePDEV,          (PFN) DrvCompletePDEV           },
    {   INDEX_DrvDisablePDEV,           (PFN) DrvDisablePDEV            },
    {   INDEX_DrvEnableSurface,         (PFN) DrvEnableSurface          },
    {   INDEX_DrvDisableSurface,        (PFN) DrvDisableSurface         },
    {   INDEX_DrvRealizeBrush,          (PFN) DrvRealizeBrush           },
    {   INDEX_DrvBitBlt,                (PFN) DrvBitBlt                 },
    {   INDEX_DrvTextOut,               (PFN) DrvTextOut                },
    {   INDEX_DrvSetPointerShape,       (PFN) DrvSetPointerShape        },
    {   INDEX_DrvMovePointer,           (PFN) DrvMovePointer            },
    {   INDEX_DrvStrokePath,            (PFN) DrvStrokePath             },
    {   INDEX_DrvCopyBits,              (PFN) DrvCopyBits               },
    {   INDEX_DrvDitherColor,           (PFN) DrvDitherColor            },
    {   INDEX_DrvAssertMode,            (PFN) DrvAssertMode             },
    {   INDEX_DrvSaveScreenBits,        (PFN) DrvSaveScreenBits         },
    {   INDEX_DrvGetModes,              (PFN) DrvGetModes               },
    {   INDEX_DrvFillPath,              (PFN) DrvFillPath               },
    {   INDEX_DrvPaint,                 (PFN) DrvPaint                  }
};

/******************************Public*Routine******************************\
* BOOL bInitProc(HMODULE hmod)
*
* DLL initialization procedure.  Save the module handle and exit.
*
*   This routine creates a named mapped memory section that is used
*   to communicate the driver's performance data to the extensible counter
*   DLL. This method will only work with "user" mode driver DLL's. 
*   Kernel or privileged drivers need to provide an IOCTL interface that
*   will communicate the performance data to the extensible counter DLL.
*
\**************************************************************************/

BOOL bInitProc(HMODULE hmod, ULONG Reason, LPVOID Reserved)
{
    HANDLE hMappedObject;
    TCHAR  szMappedObjectName[] = TEXT("VGA_COUNTER_BLOCK");

    if (Reason == DLL_PROCESS_ATTACH)
    {
        //
        //  create named section for the performance data
        //
        hMappedObject = CreateFileMapping((HANDLE)0xFFFFFFFF,
                     NULL,
                     PAGE_READWRITE,
                     0,
                     4096,
                     szMappedObjectName);
        if (hMappedObject == NULL)
        {
            // Should put out an EventLog error message here
            DISPDBG((0, "VGA: Could not Create Mapped Object for Counters %x",
		          GetLastError()));
	         pCounterBlock = NULL;
	     }
        else
        {
	         // Mapped object created okay
            // 
            // map the section and assign the counter block pointer
            // to this section of memory
            //
            pCounterBlock = (PPERF_COUNTER_BLOCK)
                     MapViewOfFile(hMappedObject,
                     FILE_MAP_ALL_ACCESS,
                     0,
                     0,
                     0);
            if (pCounterBlock == NULL)
            {
                // Failed to Map View of file
                DISPDBG((0, "VGA: Failed to Map View of File %x",
                        GetLastError()));
            }
        }
    }

    return(TRUE);

    Reserved=Reserved;
}



/******************************Public*Routine******************************\
* BOOL bEnableDriver(iEngineVersion, cb, pded)
*
* Enables the driver by filling the function table.  This call is made by
* the Engine to fill its driver function table in the LDEV (Logical DEVice).
* This call should only be made once per driver but we can handle being
* called multiple times.
*
\**************************************************************************/

BOOL DrvEnableDriver
(
    ULONG           iEngineVersion,
    ULONG           cb,
    PDRVENABLEDATA  pded
)
{
    DISPDBG((2, "VGA: enabling Driver\n"));

    cb /= sizeof(ULONG);

    switch(cb)
    {
    case 3:
        pded->pdrvfn = gadrvfn;
    case 2:
        pded->c = sizeof(gadrvfn) / sizeof(DRVFN);
    case 1:
        pded->iDriverVersion = DDI_DRIVER_VERSION;
    }

    return(TRUE);
}

/******************************Public*Routine******************************\
* VOID vDisableDriver
*
* Unload the driver and any data in may have created.
*
\**************************************************************************/

VOID DrvDisableDriver()
{
    DISPDBG((2, "VGA: disabling Driver\n"));
}

/******************************Public*Routine******************************\
* BOOL bLoadResources()
*
* Load the resources used by the PDEV
*
\**************************************************************************/

BOOL bLoadResources(PPDEV ppdev)
{
// Load the font resources

    return(TRUE);

    UNREFERENCED_PARAMETER(ppdev);
}

/******************************Public*Routine******************************\
* bInitDefaultPatterns
*
* Creates the default monochrome patterns to be used on it's surface.
*
\**************************************************************************/

BOOL bInitDefaultPatterns(PPDEV ppdev)
{
    SIZEL           sizl;
    INT             iLoop;
    PULONG          pulInit;

    sizl.cx = 8;
    sizl.cy = 8;

    DISPDBG((2, "VGA: initializing defailt patterns\n"));

    for (iLoop = 0; iLoop < HS_DDI_MAX; iLoop++)
    {
        pulInit = (PULONG) (&gaajPat[iLoop][0]);
        ppdev->ahbmPat[iLoop] = EngCreateBitmap(sizl, sizl.cx / 8, BMF_1BPP,
                                                BMF_TOPDOWN, pulInit);

        if (ppdev->ahbmPat[iLoop] == (HBITMAP)0)
        {
        // Release any bitmaps we have created.

            while(iLoop--)
                EngDeleteSurface((HSURF) ppdev->ahbmPat[iLoop]);

            return(FALSE);
        }
    }

    return(TRUE);
}

/******************************Public*Routine******************************\
* DHPDEV DrvEnablePDEV
*
* Enable the Physical DEVice
*
* Warnings:
*   The PDEV isn't complete until bCompletePDEV is called.
*
\**************************************************************************/

DHPDEV DrvEnablePDEV
(
    DEVMODEW *pdrivw,
    PWSTR     pwszLogAddress,
    ULONG     cPatterns,
    PHSURF    ahsurfPatterns,
    ULONG     cjGdiInfo,
    ULONG    *pdevcaps,
    ULONG     cb,
    PDEVINFO  pdevinfo,
    PWSTR     pwszDataFile,
    PWSTR     pwszDeviceName,
    HANDLE    hDriver          // Handle to base driver
)
{
    FLONG   fl = 0;
    DHPDEV  dhpdev = (DHPDEV) 0;
    PPDEV   ppdev;
    SYSTEM_INFO SystemInfo;

    DISPDBG((2, "VGA: enabling PDEV\n"));

// Define flag to keep track of allocation

#define PDEV_ALLOCED    0x01

#ifdef DRV_ONE_PDEV
    if (gflDrv & DRV_ENABLED_PDEV)
    {
        // SAVE_ERROR_CODE(DDI_PDEV_ALREADY_ENABLED);
        goto error;
    }
#endif

    dhpdev = (DHPDEV) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(PDEV));
    if (dhpdev == (DHPDEV) 0)
        goto error;

    fl |= PDEV_ALLOCED;

    ppdev = (PPDEV) dhpdev;

    // Identifier, for debugging purposes
    ppdev->ident = PDEV_IDENT;

    // Determine whether this is a 386 or a better processor
    GetSystemInfo(&SystemInfo);
    if (SystemInfo.dwProcessorType == PROCESSOR_INTEL_386) {
        ppdev->ulIs386 = 1;
    } else {
        ppdev->ulIs386 = 0;
    }

    // Cache the device driver handle away for later use.

    ppdev->hDriver = hDriver;

    // Initialize the cursor stuff.  We can violate the atomic rule here
    // since nobody can talk to the driver yet.

    ppdev->xyCursor.x = 320;            // Non-atomic
    ppdev->xyCursor.y = 240;            // Non-atomic

    ppdev->ptlExtent.x = 0;
    ppdev->ptlExtent.y = 0;
    ppdev->cExtent = 0;

    ppdev->flCursor = CURSOR_DOWN;

    //
    // Get the current screen mode information.  Set up device caps and devinfo.
    //

    if (!bInitPDEV(ppdev, pdrivw, &gaulCap, &devinfoVGA))
    {
        DISPDBG((1, "DISP VGA DrvEnablePDEV failed bInitPDEV\n"));
        goto error;
    }

    if (!bLoadResources(ppdev))
        goto error;

    if (!bInitDefaultPatterns(ppdev))
        goto error;

#ifdef DRV_ONE_PDEV
    gflDrv |= DRV_ENABLED_PDEV;             // So we're not called twice
#endif

    cPatterns=min(cPatterns, HS_DDI_MAX);

    memcpy((PVOID)ahsurfPatterns, ppdev->ahbmPat, cPatterns*sizeof(HBITMAP));

    cjGdiInfo=min(cjGdiInfo, sizeof(GDIINFO));

    memcpy(pdevcaps, &gaulCap, cjGdiInfo);

     // Now let's pass back the devinfo

    devinfoVGA.hpalDefault = EngCreatePalette(PAL_INDEXED, 16,
                                              (PULONG) (logPalVGA.palPalEntry),
                                              0, 0, 0);

    // *pdevinfo  = devinfoVGA;
    memcpy((PVOID) pdevinfo, (PVOID) &devinfoVGA, (ULONG) sizeof(DEVINFO));

    // Try to preallocate a saved screen bits buffer. If we fail, set the flag
    // to indicate the buffer is in use, so that we'll never attempt to use it.
    // If we succeed, mark the buffer as free.

    if ((ppdev->pjPreallocSSBBuffer = (PUCHAR)
              LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, PREALLOC_SSB_SIZE))
              != NULL) {
        ppdev->flPreallocSSBBufferInUse = FALSE;
        ppdev->ulPreallocSSBSize = PREALLOC_SSB_SIZE;
    } else {
        ppdev->flPreallocSSBBufferInUse = TRUE;
    }

    // Fill in the DIB4->VGA conversion tables. Allow 256 extra bytes so that
    // we can always safely align the tables to a 256-byte boundary, for
    // look-up reasons. There are four tables, each 256 bytes long

    ppdev->pucDIB4ToVGAConvBuffer =
            (UCHAR *) LocalAlloc((LMEM_FIXED | LMEM_ZEROINIT),
            ((256*4+256)*sizeof(UCHAR)));

    if (ppdev->pucDIB4ToVGAConvBuffer == NULL) {
        goto error;
    }

    // Round the table start up to the nearest 256 byte boundary, because the
    // tables must start on 256-byte boundaries for look-up reasons

    ppdev->pucDIB4ToVGAConvTables =
            (UCHAR *) ((ULONG) (ppdev->pucDIB4ToVGAConvBuffer + 0xFF) & ~0xFF);

    vSetDIB4ToVGATables(ppdev->pucDIB4ToVGAConvTables);

    return(dhpdev);

error:
    if (fl & PDEV_ALLOCED)
        LocalFree(dhpdev);

    return((DHPDEV) 0);

    UNREFERENCED_PARAMETER(cb);
    UNREFERENCED_PARAMETER(pwszLogAddress);
    UNREFERENCED_PARAMETER(pwszDataFile);
    UNREFERENCED_PARAMETER(pwszDeviceName);
}

/******************************Public*Routine******************************\
* BOOL bCompletePDEV(dhpdev, hpdev)
*
* Complete the initialization of the PDEV
*
\**************************************************************************/

VOID DrvCompletePDEV(
    DHPDEV dhpdev,
    HDEV  hdev)
{
    PPDEV   ppdev;

    ppdev = (PPDEV) dhpdev;

    ppdev->hdevEng = hdev;
}

/******************************Public*Routine******************************\
* VOID vFreeResources(ppdev)
*
* Free the resources used by the PDEV
*
* Effects:
*
* Warnings:
*
\**************************************************************************/

VOID vFreeResources(PPDEV ppdev)
{

    UNREFERENCED_PARAMETER(ppdev);
}

/******************************Public*Routine******************************\
* VOID vKillPatterns(ppdev)
*
* Clear the standard patterns
*
\**************************************************************************/

VOID vKillPatterns(PPDEV ppdev)
{
    INT     ii;

    for (ii = 0; ii < HS_DDI_MAX; ii++)
        EngDeleteSurface((HSURF) ppdev->ahbmPat[ii]);
}

/******************************Public*Routine******************************\
* VOID DrvDisablePDEV(dhpdev)
*
* Shutdown this physical device.
*
* Warnings:
*   If a surface is still active for this PDEV it will be freed.
*

\**************************************************************************/

VOID DrvDisablePDEV(DHPDEV dhpdev)
{
    PPDEV   ppdev;

    ppdev = (PPDEV) dhpdev;

    DISPDBG((2, "VGA:disabling PDEV\n"));

//    ASSERT(ppdev != (PPDEV) NULL, "PDEV error");

// Is there a deliquent surface still in the PDEV?

    if (ppdev->hsurfEng != (HSURF) 0)
        DrvDisableSurface(dhpdev);

// Check if the Engine has called us to many times.

//    ASSERT(--cPDEV >= 0, "PDEV - too many disables");

// Free the resources and bitmaps associated with this PDEV

    vFreeResources(ppdev);
    vKillPatterns(ppdev);

// Free the preallocated saved screen bits buffer, if there is one.

    if (ppdev->pjPreallocSSBBuffer != NULL) {
        LocalFree(ppdev->pjPreallocSSBBuffer);
    }

// Free the conversion table buffer

    if (ppdev->pucDIB4ToVGAConvBuffer != NULL) {
        LocalFree(ppdev->pucDIB4ToVGAConvBuffer);
    }

// Delete the PDEV

    LocalFree(dhpdev);

    DISPDBG((2, "VGA: disabled PDEV\n"));

#ifdef  DRV_ONE_PDEV
    gflDrv &= ~DRV_ENABLED_PDEV;
#endif
}

/******************************Public*Routine******************************\
* HSURF DrvEnableSurface(dhpdev)
*
* Enable the surface for the device.  This will actually intialize the
* screen on the VGA.
*
* Warnings:
*   This routine should only be called ONCE per PDEV.
*
\**************************************************************************/

HSURF DrvEnableSurface(DHPDEV dhpdev)
{
    PPDEV    ppdev;
    PDEVSURF pdsurf;
    DHSURF   dhsurf;
    HSURF    hsurf;

    DISPDBG((2, "VGA:enabling Surface\n"));

    ppdev = (PPDEV) dhpdev;

    //
    // Initialize the VGA device into the selected mode which will also map
    // the video frame buffer
    //

    if (!bInitVGA(ppdev, TRUE))
    {
        goto error_done;
    }

    dhsurf = (DHSURF) LocalAlloc(LMEM_FIXED, (SIZE_T) sizeof(DEVSURF));

    if (dhsurf == (DHSURF) 0)
        goto error_done;

    pdsurf = (PDEVSURF) dhsurf;

    pdsurf->ident           = DEVSURF_IDENT;
    pdsurf->flSurf          = 0;
    pdsurf->iFormat         = BMF_PHYSDEVICE;
    pdsurf->jReserved1      = 0;
    pdsurf->jReserved2      = 0;
    pdsurf->ppdev           = ppdev;
    pdsurf->sizlSurf.cx     = ppdev->sizlSurf.cx;
    pdsurf->sizlSurf.cy     = ppdev->sizlSurf.cy;
    pdsurf->lNextPlane      = 0;
    pdsurf->pvScan0         = ppdev->pjScreen;
    pdsurf->pvBitmapStart   = ppdev->pjScreen;
    pdsurf->pvStart         = ppdev->pjScreen;
    pdsurf->pvConv          = &ajConvertBuffer[0];

    if (!bInitPointer(ppdev)) {
        DISPDBG((0, "VGA DrvEnablePDEV failed bInitPointer\n"));
        goto error_clean;
    }

    if (!SetUpBanking(pdsurf, ppdev)) {
        DISPDBG((0, "VGA DrvEnablePDEV failed SetUpBanking\n"));
        goto error_clean;
    }

    // Initialize pointer information.

    if ((hsurf = EngCreateSurface(dhsurf, ppdev->sizlSurf)) == (HSURF) 0)
    {
        DISPDBG((0, "VGA DrvEnablePDEV failed EngCreateSurface\n"));
        goto error_clean;
    }

    if (EngAssociateSurface(hsurf, ppdev->hdevEng,
                        HOOK_BITBLT | HOOK_TEXTOUT | HOOK_STROKEPATH |
                        HOOK_COPYBITS | HOOK_PAINT | HOOK_FILLPATH))
    {
        ppdev->hsurfEng = hsurf;
        ppdev->pdsurf = pdsurf;

        // Set up an empty saved screen block list
        pdsurf->ssbList = NULL;
        // Initialize the offscreen adapter memory heap to currently all
        // available
        // Beginning of heap starts right after the displayed bitmap ends
        pdsurf->pjAdapterHeapStart = ((PBYTE)pdsurf->pvBitmapStart) +
             (pdsurf->lNextScan * pdsurf->sizlSurf.cy);

        // End of heap is the start of either the pointer work area or the
        // hardware pointer reserved memory area, whichever comes first
        pdsurf->pjAdapterHeapEnd = pPtrSave;
        if (ppdev->pPointerAttributes != NULL)
        {
            // There's a hardware pointer, so check what display memory it
            //  uses, if any
            if (ppdev->PointerCapabilities.HWPtrBitmapStart != -1)
            {
                // The hardware pointer does use display memory
                if (( ((PBYTE)pdsurf->pvBitmapStart) +
                        ppdev->PointerCapabilities.HWPtrBitmapStart) <
                        pdsurf->pjAdapterHeapEnd)
                {
                    // The hardware pointer marks the end of the heap
                    pdsurf->pjAdapterHeapEnd = ((PBYTE)pdsurf->pvBitmapStart) +
                        ppdev->PointerCapabilities.HWPtrBitmapStart;
                }
            }
        }

        // The current top of the heap is the end of the heap, because the heap
        // is empty
        pdsurf->pjAdapterHeapTop = pdsurf->pjAdapterHeapEnd;

        DISPDBG((2, "VGA: enabled surface\n"));

        return(hsurf);

    }

    DISPDBG((0, "VGA DrvEnablePDEV failed EngDeleteSurface\n"));
    EngDeleteSurface(hsurf);

error_clean:
    // We created the surface, so delete it
    LocalFree(dhsurf);

error_done:
    return((HSURF) 0);
}


/******************************Public*Routine******************************\
* DrvDisableSurface
*
* Free resources associated with this surface.
*
\**************************************************************************/

VOID DrvDisableSurface(DHPDEV dhpdev)
{
    PPDEV   ppdev = (PPDEV) dhpdev;
    PDEVSURF pdsurf = ppdev->pdsurf;
    PSAVED_SCREEN_BITS pSSB, pSSBNext;

    DISPDBG((2, "VGA:disabling surface\n"));

    // Free up banking-related stuff.
    LocalFree(pdsurf->pBankSelectInfo);

    if (pdsurf->pbiBankInfo != NULL) {
        LocalFree(pdsurf->pbiBankInfo);
    }

    if (pdsurf->pbiBankInfo2RW != NULL) {
        LocalFree(pdsurf->pbiBankInfo2RW);
    }

    if (pdsurf->pvBankBufferPlane0 != NULL) {
        LocalFree(pdsurf->pvBankBufferPlane0);
    }

    if (ppdev->pPointerAttributes != NULL) {
        LocalFree(ppdev->pPointerAttributes);
    }

    // Free any pending saved screen bit blocks.
    pSSB = pdsurf->ssbList;
    while (pSSB != (PSAVED_SCREEN_BITS) NULL) {
        // Point to the next saved screen bits block
        pSSBNext = (PSAVED_SCREEN_BITS) pSSB->pvNextSSB;
        // Free the current block
        LocalFree(pSSB);
        pSSB = pSSBNext;
    }

    EngDeleteSurface((HSURF) ppdev->hsurfEng);

    LocalFree(pdsurf);  // free the surface

    DISPDBG((2, "VGA:disabled surface\n"));

}

/******************************Public*Routine******************************\
* DrvAssertMode
*
* Ping the device back into its last known mode
*
\**************************************************************************/

VOID DrvAssertMode(DHPDEV dhpdev, BOOL Enable)
{
    PPDEV   ppdev = (PPDEV) dhpdev;
    ULONG   returnedDataLength;

    DISPDBG((2, "VGA: DrvAssertMode\n"));

    if (Enable) {

        //
        // The screen must be reenabled since we had gone to full screen.
        // Re-initialize the device.
        // !!! BUGBUG what happens if this fails ??
        //

        bInitVGA(ppdev, FALSE);

        vForceBank0(ppdev);

    } else {

        //
        // We must give up the display.
        // Call the kernel driver to reset the device to a known state.
        //

        if (!DeviceIoControl(ppdev->hDriver,
                             IOCTL_VIDEO_RESET_DEVICE,
                             NULL,
                             0,
                             NULL,
                             0,
                             &returnedDataLength,
                             NULL)) {

            RIP("VGA.DLL: Reset Device Failed");

        }
    }

    return;
}

/******************************Public*Routine******************************\
* DrvGetModes
*
* Returns the list of available modes for the device.
*
\**************************************************************************/

ULONG DrvGetModes(
HANDLE hDriver,
ULONG cjSize,
DEVMODEW *pdm)

{

    DWORD cModes;
    DWORD cbOutputSize;
    PVIDEO_MODE_INFORMATION pVideoModeInformation, pVideoTemp;
    DWORD cOutputModes = cjSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
    DWORD cbModeSize;

    DISPDBG((2, "Vga.dll:DrvGetModes\n"));

    cModes = getAvailableModes(hDriver,
                               (PVIDEO_MODE_INFORMATION *) &pVideoModeInformation,
                               &cbModeSize);

    if (cModes == 0)
    {
        DISPDBG((0, "VGA DISP DrvGetModes failed to get mode information"));
        return 0;
    }

    if (pdm == NULL)
    {
        cbOutputSize = cModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
    }
    else
    {
        //
        // Now copy the information for the supported modes back into the output
        // buffer
        //

        cbOutputSize = 0;

        pVideoTemp = pVideoModeInformation;

        do
        {
            if (pVideoTemp->Length != 0)
            {
                if (cOutputModes == 0)
                {
                    break;
                }

                //
                // Zero the entire structure to start off with.
                //

                memset(pdm, 0, sizeof(DEVMODEW));

                //
                // Set the name of the device to the name of the DLL.
                //

                memcpy(&(pdm->dmDeviceName), L"vga", sizeof(L"vga"));

                pdm->dmSpecVersion = DM_SPECVERSION;
                pdm->dmDriverVersion = DM_SPECVERSION;

                //
                // We currently do not support Extra information in the driver
                //

                pdm->dmDriverExtra = DRIVER_EXTRA_SIZE;

                pdm->dmSize = sizeof(DEVMODEW);
                pdm->dmBitsPerPel = pVideoTemp->NumberOfPlanes *
                                    pVideoTemp->BitsPerPlane;
                pdm->dmPelsWidth = pVideoTemp->VisScreenWidth;
                pdm->dmPelsHeight = pVideoTemp->VisScreenHeight;
                pdm->dmDisplayFrequency = pVideoTemp->Frequency;

                if (pVideoTemp->AttributeFlags & VIDEO_MODE_INTERLACED)
                {
                    pdm->dmDisplayFlags |= DM_INTERLACED;
                }

                //
                // Go to the next DEVMODE entry in the buffer.
                //

                cOutputModes--;

                pdm = (LPDEVMODEW) ( ((ULONG)pdm) + sizeof(DEVMODEW) +
                                                   DRIVER_EXTRA_SIZE);

                cbOutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);

            }

            pVideoTemp = (PVIDEO_MODE_INFORMATION)
                (((PUCHAR)pVideoTemp) + cbModeSize);

        } while (--cModes);
    }

    LocalFree(pVideoModeInformation);

    return cbOutputSize;

}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.