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

#include "precomp.h"
//
// OSI.C
// OS Isolation layer, display driver side
//
// Copyright(c) Microsoft 1997-
//
#include <version.h>
#include <ndcgver.h>
//
// These are the default 20 Windows colors, lifted from the base S3 driver.
//
// Global Table defining the 20 Window default colours. For 256 colour
// palettes the first 10 must be put at the beginning of the palette
// and the last 10 at the end of the palette.
const PALETTEENTRY s_aWinColors[20] =
{
{ 0, 0, 0, 0 }, // 0
{ 0x80,0, 0, 0 }, // 1
{ 0, 0x80,0, 0 }, // 2
{ 0x80,0x80,0, 0 }, // 3
{ 0, 0, 0x80,0 }, // 4
{ 0x80,0, 0x80,0 }, // 5
{ 0, 0x80,0x80,0 }, // 6
{ 0xC0,0xC0,0xC0,0 }, // 7
{ 192, 220, 192, 0 }, // 8
{ 166, 202, 240, 0 }, // 9
{ 255, 251, 240, 0 }, // 10
{ 160, 160, 164, 0 }, // 11
{ 0x80,0x80,0x80,0 }, // 12
{ 0xFF,0, 0 ,0 }, // 13
{ 0, 0xFF,0 ,0 }, // 14
{ 0xFF,0xFF,0 ,0 }, // 15
{ 0 ,0, 0xFF,0 }, // 16
{ 0xFF,0, 0xFF,0 }, // 17
{ 0, 0xFF,0xFF,0 }, // 18
{ 0xFF,0xFF,0xFF,0 }, // 19
};
//
// Functions supported by our Display Driver. Each entry is of the form:
//
// index - NT DDK defined index for the DDI function
//
// function - pointer to our intercept function
//
//
const DRVFN s_osiDriverFns[] =
{
//
// NT4 FUNCTIONS
//
{ INDEX_DrvEnablePDEV, (PFN)DrvEnablePDEV },
{ INDEX_DrvCompletePDEV, (PFN)DrvCompletePDEV },
{ INDEX_DrvDisablePDEV, (PFN)DrvDisablePDEV },
{ INDEX_DrvEnableSurface, (PFN)DrvEnableSurface },
{ INDEX_DrvDisableSurface, (PFN)DrvDisableSurface },
{ INDEX_DrvAssertMode, (PFN)DrvAssertMode },
{ INDEX_DrvResetPDEV, (PFN)DrvResetPDEV },
// INDEX_DrvCreateDeviceBitmap not used
// INDEX_DrvDeleteDeviceBitmap not used
{ INDEX_DrvRealizeBrush, (PFN)DrvRealizeBrush },
// INDEX_DrvDitherColor not used
{ INDEX_DrvStrokePath, (PFN)DrvStrokePath },
{ INDEX_DrvFillPath, (PFN)DrvFillPath },
{ INDEX_DrvStrokeAndFillPath, (PFN)DrvStrokeAndFillPath },
{ INDEX_DrvPaint, (PFN)DrvPaint },
{ INDEX_DrvBitBlt, (PFN)DrvBitBlt },
{ INDEX_DrvCopyBits, (PFN)DrvCopyBits },
{ INDEX_DrvStretchBlt, (PFN)DrvStretchBlt },
{ INDEX_DrvSetPalette, (PFN)DrvSetPalette },
{ INDEX_DrvTextOut, (PFN)DrvTextOut },
{ INDEX_DrvEscape, (PFN)DrvEscape },
// INDEX_DrvDrawEscape not used
// INDEX_DrvQueryFont not used
// INDEX_DrvQueryFontTree not used
// INDEX_DrvQueryFontData not used
{ INDEX_DrvSetPointerShape, (PFN)DrvSetPointerShape },
{ INDEX_DrvMovePointer, (PFN)DrvMovePointer },
{ INDEX_DrvLineTo, (PFN)DrvLineTo },
// INDEX_DrvSendPage not used
// INDEX_DrvStartPage not used
// INDEX_DrvEndDoc not used
// INDEX_DrvStartDoc not used
// INDEX_DrvGetGlyphMode not used
// INDEX_DrvSynchronize not used
{ INDEX_DrvSaveScreenBits, (PFN)DrvSaveScreenBits },
{ INDEX_DrvGetModes, (PFN)DrvGetModes },
// INDEX_DrvFree not used
// INDEX_DrvDestroyFont not used
// INDEX_DrvQueryFontCaps not used
// INDEX_DrvLoadFontFile not used
// INDEX_DrvUnloadFontFile not used
// INDEX_DrvFontManagement not used
// INDEX_DrvQueryTrueTypeTable not used
// INDEX_DrvQueryTrueTypeOutline not used
// INDEX_DrvGetTrueTypeFile not used
// INDEX_DrvQueryFontFile not used
// INDEX_DrvQueryAdvanceWidths not used
// INDEX_DrvSetPixelFormat not used
// INDEX_DrvDescribePixelFormat not used
// INDEX_DrvSwapBuffers not used
// INDEX_DrvStartBanding not used
// INDEX_DrvNextBand not used
// INDEX_DrvGetDirectDrawInfo not used
// INDEX_DrvEnableDirectDraw not used
// INDEX_DrvDisableDirectDraw not used
// INDEX_DrvQuerySpoolType not used
//
// NT5 FUNCTIONS - 5 of them currently. If you add to this list,
// update CFN_NT5 below.
//
// INDEX_DrvIcmCreateColorTransform not used
// INDEX_DrvIcmDeleteColorTransform not used
// INDEX_DrvIcmCheckBitmapBits not used
// INDEX_DrvIcmSetDeviceGammaRamp not used
{ INDEX_DrvGradientFill, (PFN)DrvGradientFill },
{ INDEX_DrvStretchBltROP, (PFN)DrvStretchBltROP },
{ INDEX_DrvPlgBlt, (PFN)DrvPlgBlt },
{ INDEX_DrvAlphaBlend, (PFN)DrvAlphaBlend },
// INDEX_DrvSynthesizeFont not used
// INDEX_DrvGetSynthesizedFontFiles not used
{ INDEX_DrvTransparentBlt, (PFN)DrvTransparentBlt },
// INDEX_DrvQueryPerBandInfo not used
// INDEX_DrvQueryDeviceSupport not used
// INDEX_DrvConnect not used
// INDEX_DrvDisconnect not used
// INDEX_DrvReconnect not used
// INDEX_DrvShadowConnect not used
// INDEX_DrvShadowDisconnect not used
// INDEX_DrvInvalidateRect not used
// INDEX_DrvSetPointerPos not used
// INDEX_DrvDisplayIOCtl not used
// INDEX_DrvDeriveSurface not used
// INDEX_DrvQueryGlyphAttrs not used
{ INDEX_DrvDisableDriver, (PFN) DrvDisableDriver }
};
#define CFN_NT5 5
//
// s_osiDefaultGdi
//
// This contains the default GDIINFO fields that are passed back to GDI
// during DrvEnablePDEV.
//
// NOTE: This structure defaults to values for an 8bpp palette device.
// Some fields are overwritten for different colour depths.
//
// It is expected that DDML ignores a lot of these parameters and
// uses the values from the primary driver instead
//
const GDIINFO s_osiDefaultGdi =
{
GDI_DRIVER_VERSION,
DT_RASDISPLAY, // ulTechnology
400, // ulHorzSize (display width: mm)
300, // ulVertSize (display height: mm)
0, // ulHorzRes (filled in later)
0, // ulVertRes (filled in later)
0, // cBitsPixel (filled in later)
1, // cPlanes
(ULONG)-1, // ulNumColors (palette managed)
0, // flRaster (DDI reserved field)
96, // ulLogPixelsX (filled in later)
96, // ulLogPixelsY (filled in later)
TC_RA_ABLE, // flTextCaps - If we had wanted console windows
// to scroll by repainting the entire window,
// instead of doing a screen-to-screen blt, we
// would have set TC_SCROLLBLT (yes, the flag
// is backwards).
0, // ulDACRed (filled in later)
0, // ulDACGreen (filled in later)
0, // ulDACBlue (filled in later)
0x0024, // ulAspectX
0x0024, // ulAspectY
0x0033, // ulAspectXY (one-to-one aspect ratio)
1, // xStyleStep
1, // yStyleStep
3, // denStyleStep -- Styles have a one-to-one
// aspect ratio, and every dot is 3 pixels long
{ 0, 0 }, // ptlPhysOffset
{ 0, 0 }, // szlPhysSize
0, // ulNumPalReg
{
{ 6700, 3300, 0 }, // Red
{ 2100, 7100, 0 }, // Green
{ 1400, 800, 0 }, // Blue
{ 1750, 3950, 0 }, // Cyan
{ 4050, 2050, 0 }, // Magenta
{ 4400, 5200, 0 }, // Yellow
{ 3127, 3290, 0 }, // AlignmentWhite
20000, // RedGamma
20000, // GreenGamma
20000, // BlueGamma
0, 0, 0, 0, 0, 0 // No dye correction for raster displays
},
0, // ulDevicePelsDPI (for printers only)
PRIMARY_ORDER_CBA, // ulPrimaryOrder
HT_PATSIZE_4x4_M, // ulHTPatternSize
HT_FORMAT_8BPP, // ulHTOutputFormat
HT_FLAG_ADDITIVE_PRIMS, // flHTFlags
0, // ulVRefresh
0, // ulBltAlignment
0, // ulPanningHorzRes
0, // ulPanningVertRes
};
//
// s_osiDefaultDevInfo
//
// This contains the default DEVINFO fields that are passed back to GDI
// during DrvEnablePDEV.
//
// NOTE: This structure defaults to values for an 8bpp palette device.
// Some fields are overwritten for different colour depths.
//
//
const DEVINFO s_osiDefaultDevInfo =
{
{
GCAPS_OPAQUERECT |
GCAPS_DITHERONREALIZE |
GCAPS_PALMANAGED |
GCAPS_MONO_DITHER |
GCAPS_COLOR_DITHER |
GCAPS_LAYERED
}, // NOTE: Only enable ASYNCMOVE if your code
// and hardware can handle DrvMovePointer
// calls at any time, even while another
// thread is in the middle of a drawing
// call such as DrvBitBlt.
// flGraphicsFlags
{ 16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
VARIABLE_PITCH | FF_DONTCARE, L"System"
},
// lfDefaultFont
{
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"
},
// lfAnsiVarFont
{
12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
CLIP_STROKE_PRECIS,PROOF_QUALITY,
FIXED_PITCH | FF_DONTCARE, L"Courier"
},
// lfAnsiFixFont
0, // cFonts
BMF_8BPP, // iDitherFormat
8, // cxDither
8, // cyDither
0 // hpalDefault (filled in later)
};
//
// DrvEnableDriver - see NT DDK documentation.
//
// This is the only directly exported entry point to the display driver.
// All other entry points are exported through the data returned from this
// function.
//
BOOL DrvEnableDriver
(
ULONG iEngineVersion,
ULONG cj,
DRVENABLEDATA* pded
)
{
DebugEntry(DrvEnableDriver);
INIT_OUT(("DrvEnableDriver(iEngineVersion = 0x%08x)", iEngineVersion));
//
// Check that the engine version is correct - we refuse to load on
// other versions because we will almost certainly not work.
//
if ((iEngineVersion != DDI_DRIVER_VERSION_SP3) &&
(iEngineVersion != DDI_DRIVER_VERSION_NT5) &&
(iEngineVersion != DDI_DRIVER_VERSION_NT5_01))
{
INIT_OUT(("DrvEnableDriver: Not NT 4.0 SP-3 or NT 5.0; failing enable"));
return(FALSE);
}
//
// Fill in as much as we can. Start with the entry points.
//
if ( cj >= FIELD_OFFSET(DRVENABLEDATA, pdrvfn) +
FIELD_SIZE (DRVENABLEDATA, pdrvfn) )
{
pded->pdrvfn = (DRVFN *)s_osiDriverFns;
}
//
// Size of our entry point array.
//
if ( cj >= FIELD_OFFSET(DRVENABLEDATA, c) +
FIELD_SIZE (DRVENABLEDATA, c) )
{
//
// If this is NT4, return back a subset -- it doesn't like tables
// with unknown indeces
//
pded->c = sizeof(s_osiDriverFns) / sizeof(s_osiDriverFns[0]);
if (iEngineVersion != DDI_DRIVER_VERSION_NT5 &&
iEngineVersion != DDI_DRIVER_VERSION_NT5_01)
{
pded->c -= CFN_NT5;
}
INIT_OUT(("DrvEnableDriver: Returning driver function count %u", pded->c));
}
//
// DDI version this driver was targeted for is passed back to engine.
// Future graphics engines may break calls down to old driver format.
//
if ( cj >= FIELD_OFFSET(DRVENABLEDATA, iDriverVersion) +
FIELD_SIZE (DRVENABLEDATA, iDriverVersion) )
{
//
// Return back NT5 when we're on NT5. Hopefully this will work
// OK...
//
pded->iDriverVersion = iEngineVersion;
INIT_OUT(("DrvEnableDriver: Returning driver version 0x%08x", pded->iDriverVersion));
}
DebugExitVOID(DrvEnableDriver);
return(TRUE);
}
//
// DrvDisableDriver - see NT DDK documentation.
//
VOID DrvDisableDriver(VOID)
{
DebugEntry(DrvDisableDriver);
DebugExitVOID(DrvDisableDriver);
}
//
// DrvEnablePDEV - see NT DDK documentation.
//
// Initializes a bunch of fields for GDI, based on the mode we've been
// asked to do. This is the first thing called after DrvEnableDriver, when
// GDI wants to get some information about us.
//
// (This function mostly returns back information; DrvEnableSurface is used
// for initializing the hardware and driver components.)
//
//
DHPDEV DrvEnablePDEV(DEVMODEW* pdm,
PWSTR pwszLogAddr,
ULONG cPat,
HSURF* phsurfPatterns,
ULONG cjCaps,
ULONG* pdevcaps,
ULONG cjDevInfo,
DEVINFO* pdi,
HDEV hdev,
PWSTR pwszDeviceName,
HANDLE hDriver)
{
DHPDEV rc = NULL;
LPOSI_PDEV ppdev = NULL;
GDIINFO gdiInfoNew;
DebugEntry(DrvEnablePDEV);
INIT_OUT(("DrvEnablePDEV: Parameters:"));
INIT_OUT((" PWSTR pdm->dmDeviceName %ws", pdm->dmDeviceName));
INIT_OUT((" HDEV hdev 0x%08x", hdev));
INIT_OUT((" PWSTR pwszDeviceName %ws", pwszDeviceName));
INIT_OUT((" HANDLE hDriver 0x%08x", hDriver));
//
// This function only sets up local data, so shared memory protection
// is not required.
//
//
// Make sure that we have large enough data to reference.
//
if ((cjCaps < sizeof(GDIINFO)) || (cjDevInfo < sizeof(DEVINFO)))
{
ERROR_OUT(( "Buffer size too small %lu %lu", cjCaps, cjDevInfo));
DC_QUIT;
}
//
// Allocate a physical device structure.
//
ppdev = EngAllocMem(FL_ZERO_MEMORY, sizeof(OSI_PDEV), OSI_ALLOC_TAG);
if (ppdev == NULL)
{
ERROR_OUT(( "DrvEnablePDEV - Failed EngAllocMem"));
DC_QUIT;
}
ppdev->hDriver = hDriver;
//
// Set up the current screen mode information based upon the supplied
// mode settings.
//
if (!OSIInitializeMode((GDIINFO *)pdevcaps,
pdm,
ppdev,
&gdiInfoNew,
pdi))
{
ERROR_OUT(( "Failed to initialize mode"));
DC_QUIT;
}
memcpy(pdevcaps, &gdiInfoNew, min(sizeof(GDIINFO), cjCaps));
INIT_OUT(("DrvEnablePDEV: Returning DEVINFO:"));
INIT_OUT((" FLONG flGraphicsCaps 0x%08x", pdi->flGraphicsCaps));
INIT_OUT((" ULONG iDitherFormat %d", pdi->iDitherFormat));
INIT_OUT((" HPALETTE hpalDefault 0x%08x", pdi->hpalDefault));
INIT_OUT(("DrvEnablePDEV: Returning GDIINFO (pdevcaps):"));
INIT_OUT((" ULONG ulVersion 0x%08x", gdiInfoNew.ulVersion));
INIT_OUT((" ULONG ulHorzSize %d", gdiInfoNew.ulHorzSize));
INIT_OUT((" ULONG ulVertSize %d", gdiInfoNew.ulVertSize));
INIT_OUT((" ULONG ulHorzRes %d", gdiInfoNew.ulHorzRes));
INIT_OUT((" ULONG ulVertRes %d", gdiInfoNew.ulVertRes));
INIT_OUT((" ULONG cBitsPixel %d", gdiInfoNew.cBitsPixel));
INIT_OUT((" ULONG cPlanes %d", gdiInfoNew.cPlanes));
INIT_OUT((" ULONG ulNumColors %d", gdiInfoNew.ulNumColors));
INIT_OUT((" ULONG ulDACRed 0x%08x", gdiInfoNew.ulDACRed));
INIT_OUT((" ULONG ulDACGreen 0x%08x", gdiInfoNew.ulDACGreen));
INIT_OUT((" ULONG ulDACBlue 0x%08x", gdiInfoNew.ulDACBlue));
INIT_OUT((" ULONG ulHTOutputFormat %d", gdiInfoNew.ulHTOutputFormat));
//
// We have successfully initialized - return the new PDEV.
//
rc = (DHPDEV)ppdev;
DC_EXIT_POINT:
//
// Release any resources if we failed to initialize.
//
if (rc == NULL)
{
ERROR_OUT(("DrvEnablePDEV failed; cleaning up by disabling"));
DrvDisablePDEV(NULL);
}
DebugExitPVOID(DrvEnablePDEV, rc);
return(rc);
}
//
// DrvDisablePDEV - see NT DDK documentation
//
// Release the resources allocated in DrvEnablePDEV. If a surface has been
// enabled DrvDisableSurface will have already been called.
//
// Note that this function will be called when previewing modes in the
// Display Applet, but not at system shutdown.
//
// Note: In an error, we may call this before DrvEnablePDEV is done.
//
//
VOID DrvDisablePDEV(DHPDEV dhpdev)
{
LPOSI_PDEV ppdev = (LPOSI_PDEV)dhpdev;
DebugEntry(DrvDisablePDEV);
INIT_OUT(("DrvDisablePDEV(dhpdev = 0x%08x)", dhpdev));
//
// Free the resources we allocated for the display.
//
if (ppdev != NULL)
{
if (ppdev->hpalCreated != NULL)
{
EngDeletePalette(ppdev->hpalCreated);
ppdev->hpalCreated = NULL;
}
if (ppdev->pPal != NULL)
{
EngFreeMem(ppdev->pPal);
ppdev->pPal = NULL;
}
EngFreeMem(ppdev);
}
DebugExitVOID(DrvDisablePDEV);
}
//
// DrvCompletePDEV - see NT DDK documentation
//
// Stores the HPDEV, the engine's handle for this PDEV, in the DHPDEV.
//
VOID DrvCompletePDEV( DHPDEV dhpdev,
HDEV hdev )
{
DebugEntry(DrvCompletePDEV);
//
// Store the device handle for our display handle.
//
INIT_OUT(("DrvCompletePDEV(dhpdev = 0x%08x, hdev = 0x%08x)", dhpdev, hdev));
((LPOSI_PDEV)dhpdev)->hdevEng = hdev;
DebugExitVOID(DrvCompletePDEV);
}
//
// DrvResetPDEV - see NT DDK documentation
//
// Allows us to reject dynamic screen changes if necessary ON NT4 ONLY
// This is NOT CALLED on NT5.
//
BOOL DrvResetPDEV
(
DHPDEV dhpdevOld,
DHPDEV dhpdevNew
)
{
BOOL rc = TRUE;
DebugEntry(DrvResetPDEV);
INIT_OUT(("DrvResetPDEV(dhpdevOld = 0x%08x, dhpdevNew = 0x%08x)", dhpdevOld,
dhpdevNew));
//
// We can only allow the display driver to change modes while DC-Share
// is not running.
//
if (g_shmMappedMemory != NULL)
{
//
// Deny the request.
//
rc = FALSE;
}
DebugExitDWORD(DrvResetPDEV, rc);
return(rc);
}
//
// DrvEnableSurface - see NT DDK documentation
//
// Creates the drawing surface and initializes driver components. This
// function is called after DrvEnablePDEV, and performs the final device
// initialization.
//
//
HSURF DrvEnableSurface(DHPDEV dhpdev)
{
LPOSI_PDEV ppdev = (LPOSI_PDEV)dhpdev;
HSURF hsurf;
SIZEL sizl;
LPOSI_DSURF pdsurf;
HSURF rc = 0;
DWORD returnedDataLength;
DWORD MaxWidth, MaxHeight;
VIDEO_MEMORY videoMemory;
VIDEO_MEMORY_INFORMATION videoMemoryInformation;
DebugEntry(DrvEnableSurface);
INIT_OUT(("DrvEnableSurface: Parameters:"));
INIT_OUT((" LPOSI_PDEV ppdev 0x%08x", ppdev));
INIT_OUT((" HDRIVER ->hDriver 0x%08x", ppdev->hDriver));
INIT_OUT((" INT ->cxScreen %d", ppdev->cxScreen));
INIT_OUT((" INT ->cyScreen %d", ppdev->cyScreen));
//
// Now create our private surface structure.
//
// Whenever we get a call to draw directly to the screen, we'll get
// passed a pointer to a SURFOBJ whose 'dhpdev' field will point
// to our PDEV structure, and whose 'dhsurf' field will point to the
// DSURF structure allocated below.
//
// Every device bitmap we create in DrvCreateDeviceBitmap will also
// have its own unique DSURF structure allocated (but will share the
// same PDEV). To make our code more polymorphic for handling drawing
// to either the screen or an off-screen bitmap, we have the same
// structure for both.
//
pdsurf = EngAllocMem(FL_ZERO_MEMORY, sizeof(OSI_DSURF), OSI_ALLOC_TAG);
if (pdsurf == NULL)
{
ERROR_OUT(( "DrvEnableSurface - Failed pdsurf EngAllocMem"));
DC_QUIT;
}
//
// Store the screen surface details.
//
ppdev->pdsurfScreen = pdsurf;
pdsurf->sizl.cx = ppdev->cxScreen;
pdsurf->sizl.cy = ppdev->cyScreen;
pdsurf->ppdev = ppdev;
INIT_OUT(("DrvEnableSurface: Returning surface pointer 0x%08x", pdsurf));
//
// Only map the shared memory the first time we are called.
//
if (g_asSharedMemory == NULL)
{
//
// Map the pointer to the shared section in the miniport driver
//
videoMemory.RequestedVirtualAddress = NULL;
if (EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_MAP_VIDEO_MEMORY,
&videoMemory,
sizeof(VIDEO_MEMORY),
&videoMemoryInformation,
sizeof(VIDEO_MEMORY_INFORMATION),
&returnedDataLength))
{
ERROR_OUT(( "Could not MAP miniport section"));
DC_QUIT;
}
INIT_OUT(("DrvEnableSurface: Got video memory info from EngDeviceIoControl:"));
INIT_OUT((" FrameBufferBase 0x%08x", videoMemoryInformation.FrameBufferBase));
INIT_OUT((" FrameBufferLength 0x%08x", videoMemoryInformation.FrameBufferLength));
g_shmSharedMemorySize = videoMemoryInformation.FrameBufferLength;
// First block is shared memory header
g_asSharedMemory = (LPSHM_SHARED_MEMORY)
videoMemoryInformation.FrameBufferBase;
// Next are the two large OA_FAST_DATA blocks
g_poaData[0] = (LPOA_SHARED_DATA)(g_asSharedMemory + 1);
g_poaData[1] = (LPOA_SHARED_DATA)(g_poaData[0] + 1);
}
//
// Next, have GDI create the actual SURFOBJ.
//
// Our drawing surface is going to be 'device-managed', meaning that
// GDI cannot draw on the framebuffer bits directly, and as such we
// create the surface via EngCreateDeviceSurface. By doing this, we
// ensure that GDI will only ever access the bitmaps bits via the Drv
// calls that we've HOOKed.
//
sizl.cx = ppdev->cxScreen;
sizl.cy = ppdev->cyScreen;
//
// Otherwise the primary display driver has its own bitmap used by the
// physical hardware, so we do not need to do any drawing ourself.
//
INIT_OUT(("DrvEnableSurface: Calling EngCreateDeviceSurface with:"));
INIT_OUT((" Sizl.cx %d", sizl.cx));
INIT_OUT((" Sizl.cy %d", sizl.cy));
INIT_OUT((" BitmapFormat %d", ppdev->iBitmapFormat));
hsurf = EngCreateDeviceSurface( (DHSURF)pdsurf,
sizl,
ppdev->iBitmapFormat );
if (hsurf == 0)
{
ERROR_OUT(( "Could not allocate surface"));
DC_QUIT;
}
//
// Store the screen surface handle.
//
ppdev->hsurfScreen = hsurf;
//
// Now associate the surface and the PDEV.
//
// We have to associate the surface we just created with our physical
// device so that GDI can get information related to the PDEV when
// it's drawing to the surface (such as, for example, the length of
// styles on the device when simulating styled lines).
//
if (!EngAssociateSurface(hsurf, ppdev->hdevEng,
HOOK_BITBLT |
HOOK_STRETCHBLT |
HOOK_PLGBLT |
HOOK_TEXTOUT |
HOOK_PAINT | // OBSOLETE
HOOK_STROKEPATH |
HOOK_FILLPATH |
HOOK_STROKEANDFILLPATH |
HOOK_LINETO |
HOOK_COPYBITS |
HOOK_STRETCHBLTROP |
HOOK_TRANSPARENTBLT |
HOOK_ALPHABLEND |
HOOK_GRADIENTFILL |
HOOK_SYNCHRONIZEACCESS)) // OBSOLETE
{
ERROR_OUT(( "DrvEnableSurface - Failed EngAssociateSurface"));
DC_QUIT;
}
//
// We have successfully associated the surface so return it to the GDI.
//
rc = hsurf;
DC_EXIT_POINT:
//
// Tidy up any resources if we failed.
//
if (rc == 0)
{
DrvDisableSurface((DHPDEV) ppdev);
}
DebugExitPVOID(DrvEnableSurface, rc);
return(rc);
}
//
// DrvDisableSurface - see NT DDK documentation
//
// Free resources allocated by DrvEnableSurface. Release the surface.
//
// Note that this function will be called when previewing modes in the
// Display Applet, but not at system shutdown. If you need to reset the
// hardware at shutdown, you can do it in the miniport by providing a
// 'HwResetHw' entry point in the VIDEO_HW_INITIALIZATION_DATA structure.
//
// Note: In an error case, we may call this before DrvEnableSurface is
// completely done.
//
VOID DrvDisableSurface(DHPDEV dhpdev)
{
LPOSI_PDEV ppdev = (LPOSI_PDEV)dhpdev;
DebugEntry(DrvDisableSurface);
INIT_OUT(("DrvDisableSurface(dhpdev = 0x%08x)", dhpdev));
if (ppdev->hsurfScreen != 0)
{
EngDeleteSurface(ppdev->hsurfScreen);
}
if (ppdev->pdsurfScreen != NULL)
{
EngFreeMem(ppdev->pdsurfScreen);
}
DebugExitVOID(DrvDisableSurface);
}
//
// DrvEscape - see NT DDK documentation.
//
ULONG DrvEscape(SURFOBJ *pso,
ULONG iEsc,
ULONG cjIn,
PVOID pvIn,
ULONG cjOut,
PVOID pvOut)
{
ULONG rc = FALSE;
LPOSI_ESCAPE_HEADER pHeader;
DebugEntry(DrvEscape);
TRACE_OUT(("DrvEscape called with escape %d", iEsc));
//
// All functions we support use an identifier in the input data to make
// sure that we don't try to use another driver's escape functions. If
// the identifier is not present, we must not process the request.
//
// NOTE: This function is NOT protected for shared memory access
// because it is responsible for allocating / deallocating the shared
// memory.
//
//
// Check the data is long enough to store our standard escape header.
// If it is not big enough this must be an escape request for another
// driver.
//
if (cjIn < sizeof(OSI_ESCAPE_HEADER))
{
INIT_OUT(("DrvEscape ignoring; input size %04d too small", cjIn));
WARNING_OUT(("DrvEscape ignoring; input size %04d too small", cjIn));
DC_QUIT;
}
if (cjOut < sizeof(OSI_ESCAPE_HEADER))
{
INIT_OUT(("DrvEscape ignoring; output size %04d too small", cjOut));
WARNING_OUT(("DrvEscape ignoring; output size %04d too small", cjOut));
DC_QUIT;
}
//
// Check for our escape ID. If it is not our escape ID this must be an
// escape request for another driver.
//
pHeader = pvIn;
if (pHeader->identifier != OSI_ESCAPE_IDENTIFIER)
{
INIT_OUT(("DrvEscape ignoring; identifier 0x%08x is not for NetMtg", pHeader->identifier));
WARNING_OUT(("DrvEscape ignoring; identifier 0x%08x is not for NetMtg", pHeader->identifier));
DC_QUIT;
}
else if (pHeader->version != DCS_MAKE_VERSION())
{
INIT_OUT(("DrvEscape failing; version 0x%08x of NetMtg is not that of driver",
pHeader->version));
WARNING_OUT(("DrvEscape failing; version 0x%08x of NetMtg is not that of driver",
pHeader->version));
DC_QUIT;
}
//
// If we haven't initialized yet, fail all other escapes.
//
if (g_shmMappedMemory == NULL)
{
if ((iEsc != OSI_ESC_CODE) || (pHeader->escapeFn != OSI_ESC_INIT))
{
WARNING_OUT(("DrvEscape failing; driver not initialized"));
DC_QUIT;
}
}
//
// Everything is tickety boo - process the request.
//
switch (iEsc)
{
case OSI_ESC_CODE:
{
//
// This is a request from the share core. Pass it on to the
// correct component.
//
TRACE_OUT(( "Function %ld", pHeader->escapeFn));
if( // (pHeader->escapeFn >= OSI_ESC_FIRST) && Always True
(pHeader->escapeFn <= OSI_ESC_LAST ) )
{
//
// OSI requests.
//
rc = OSI_DDProcessRequest(pso, cjIn, pvIn, cjOut, pvOut);
}
else if( (pHeader->escapeFn >= OSI_OE_ESC_FIRST) &&
(pHeader->escapeFn <= OSI_OE_ESC_LAST ) )
{
//
// Order Encoder requests.
//
rc = OE_DDProcessRequest(pso, cjIn, pvIn, cjOut, pvOut);
}
else if( (pHeader->escapeFn >= OSI_HET_ESC_FIRST) &&
(pHeader->escapeFn <= OSI_HET_ESC_LAST) )
{
//
// Non-locking (wnd tracking) HET requests
//
rc = HET_DDProcessRequest(pso, cjIn, pvIn, cjOut, pvOut);
}
else if( (pHeader->escapeFn >= OSI_SBC_ESC_FIRST) &&
(pHeader->escapeFn <= OSI_SBC_ESC_LAST ) )
{
//
// Send Bitmap Cache requests
//
rc = SBC_DDProcessRequest(pso, pHeader->escapeFn, pvIn, pvOut, cjOut);
}
else if( (pHeader->escapeFn >= OSI_SSI_ESC_FIRST) &&
(pHeader->escapeFn <= OSI_SSI_ESC_LAST ) )
{
//
// Save Screen Bits requests.
//
rc = SSI_DDProcessRequest(pHeader->escapeFn, pHeader, cjIn);
}
else if( (pHeader->escapeFn >= OSI_CM_ESC_FIRST) &&
(pHeader->escapeFn <= OSI_CM_ESC_LAST ) )
{
//
// Cursor Manager requests
//
rc = CM_DDProcessRequest(pso, cjIn, pvIn, cjOut, pvOut);
}
else if( (pHeader->escapeFn >= OSI_OA_ESC_FIRST) &&
(pHeader->escapeFn <= OSI_OA_ESC_LAST ) )
{
//
// Order Accumulator requests.
//
rc = OA_DDProcessRequest(pHeader->escapeFn, pHeader, cjIn);
}
else if( (pHeader->escapeFn >= OSI_BA_ESC_FIRST) &&
(pHeader->escapeFn <= OSI_BA_ESC_LAST ) )
{
//
// Bounds Accumulator requests.
//
rc = BA_DDProcessRequest(pHeader->escapeFn, pHeader, cjIn,
pvOut, cjOut);
}
else
{
WARNING_OUT(( "Unknown function", pHeader->escapeFn));
}
}
break;
case WNDOBJ_SETUP:
{
if ((pHeader->escapeFn >= OSI_HET_WO_ESC_FIRST) &&
(pHeader->escapeFn <= OSI_HET_WO_ESC_LAST))
{
TRACE_OUT(("WNDOBJ_SETUP Escape code - pass to HET"));
rc = HET_DDProcessRequest(pso, cjIn, pvIn, cjOut, pvOut);
}
else
{
INIT_OUT(("WNDOBJ_SETUP Escape is unrecognized, ignore"));
WARNING_OUT(("WNDOBJ_SETUP Escape is unrecognized, ignore"));
}
}
break;
default:
{
ERROR_OUT(( "Unrecognised request %lu", iEsc));
}
break;
}
DC_EXIT_POINT:
DebugExitDWORD(DrvEscape, rc);
return(rc);
}
//
// DrvSetPalette - see NT DDK documentation.
//
BOOL DrvSetPalette(DHPDEV dhpdev,
PALOBJ* ppalo,
FLONG fl,
ULONG iStart,
ULONG cColors)
{
BOOL rc = FALSE;
LPOSI_PDEV ppdev = (LPOSI_PDEV)dhpdev;
DebugEntry(DrvSetPalette);
//
// Check that this doesn't hose our palette. Note that NT passes a
// zero indexed array element and a count, hence to fill a palette, the
// values are 'start at 0 with 256 colours'. Thus a total of 256 is
// the maximum for our 8-bit palette.
//
if (iStart + cColors > OSI_MAX_PALETTE)
{
ERROR_OUT(("Overflow: start %lu count %lu", iStart, cColors));
DC_QUIT;
}
//
// Fill in the palette
//
if (cColors != PALOBJ_cGetColors(ppalo,
iStart,
cColors,
(ULONG*)&ppdev->pPal[iStart]))
{
//
// Don't bother tracing the return code - it's always 0.
//
ERROR_OUT(("Failed to read palette"));
DC_QUIT;
}
//
// BOGUS LAURABU!
// For NT 5.0, do we need to turn around and reset the contents of
// our created palette object with these new color values? Real
// display drivers don't (S3 e.g.)
//
//
// Set the flag in the PDEV to indicate that the palette has changed
//
ppdev->paletteChanged = TRUE;
rc = TRUE;
DC_EXIT_POINT:
DebugExitBOOL(DrvSetPalette, rc);
return(rc);
}
//
// DrvGetModes - see NT DDK documentation
//
// Returns the list of available modes for the device.
// As a mirroring driver, we return 0. That will cause NT GRE to use
// whatever ChangeDisplaySettingsEx passed along.
//
ULONG DrvGetModes
(
HANDLE hDriver,
ULONG cjSize,
DEVMODEW* pdm
)
{
return(0);
}
//
// DrvAssertMode - see NT DDK documentation.
//
BOOL DrvAssertMode
(
DHPDEV dhpdev,
BOOL bEnable
)
{
LPOSI_PDEV ppdev = (LPOSI_PDEV)dhpdev;
DebugEntry(DrvAssertMode);
INIT_OUT(("DrvAssertMode(dhpdev = 0x%08x, bEnable = %d)", dhpdev, bEnable));
//
// Check for fullscreen switching.
//
if ((g_asSharedMemory != NULL) && (ppdev != NULL))
{
g_asSharedMemory->fullScreen = (BOOL)(!bEnable);
TRACE_OUT(("Fullscreen is now %d", g_asSharedMemory->fullScreen));
}
DebugExitVOID(DrvAssertMode);
return(TRUE);
}
//
// Name: OSIInitializeMode
//
// Purpose:
//
// Initializes a bunch of fields in the pdev, devcaps (aka gdiinfo), and
// devinfo based on the requested mode.
//
// Returns:
//
// TRUE - Successfully initialized the data
// FALSE - Failed to set up mode data
//
// Params:
//
// pgdiRequested - GDI info from the primary display driver (empty in NT 5.0)
// pdmRequested - DEVMODE info with GDI's requested settings for our driver
// ppdev - Our driver's private copy of settings, values
// pgdiReturn - GDI info to return for our driver
// pdiReturn - DEVINFO to return for our driver
//
BOOL OSIInitializeMode
(
const GDIINFO* pgdiRequested,
const DEVMODEW* pdmRequested,
LPOSI_PDEV ppdev,
GDIINFO* pgdiReturn,
DEVINFO* pdiReturn
)
{
BOOL rc = FALSE;
HPALETTE hpal;
ULONG cColors;
ULONG iMode;
DebugEntry(OSIInitializeMode);
INIT_OUT(("DrvEnablePDEV: DEVMODEW requested contains:"));
INIT_OUT((" Screen width -- %li", pdmRequested->dmPelsWidth));
INIT_OUT((" Screen height -- %li", pdmRequested->dmPelsHeight));
INIT_OUT((" Bits per pel -- %li", pdmRequested->dmBitsPerPel));
INIT_OUT(("DrvEnablePDEV: DEVINFO parameter contains:"));
INIT_OUT((" flGraphicsCaps -- 0x%08x", pdiReturn->flGraphicsCaps));
INIT_OUT((" iDitherFormat -- 0x%08x", pdiReturn->iDitherFormat));
INIT_OUT((" hpalDefault -- 0x%08x", pdiReturn->hpalDefault));
INIT_OUT(("DrvEnablePDEV: GDIINFO (devcaps) parameter contains:"));
INIT_OUT((" ULONG ulVersion 0x%08x", pgdiRequested->ulVersion));
INIT_OUT((" ULONG ulHorzSize %d", pgdiRequested->ulHorzSize));
INIT_OUT((" ULONG ulVertSize %d", pgdiRequested->ulVertSize));
INIT_OUT((" ULONG ulHorzRes %d", pgdiRequested->ulHorzRes));
INIT_OUT((" ULONG ulVertRes %d", pgdiRequested->ulVertRes));
INIT_OUT((" ULONG cBitsPixel %d", pgdiRequested->cBitsPixel));
INIT_OUT((" ULONG cPlanes %d", pgdiRequested->cPlanes));
INIT_OUT((" ULONG ulNumColors %d", pgdiRequested->ulNumColors));
INIT_OUT((" ULONG ulDACRed 0x%08x", pgdiRequested->ulDACRed));
INIT_OUT((" ULONG ulDACGreen 0x%08x", pgdiRequested->ulDACGreen));
INIT_OUT((" ULONG ulDACBlue 0x%08x", pgdiRequested->ulDACBlue));
INIT_OUT((" ULONG ulHTOutputFormat %d", pgdiRequested->ulHTOutputFormat));
//
// Fill in the GDIINFO we're returning with the info for our driver.
// First, copy the default settings.
//
*pgdiReturn = s_osiDefaultGdi;
//
// Second, update the values that vary depending on the requested
// mode and color depth.
//
pgdiReturn->ulHorzRes = pdmRequested->dmPelsWidth;
pgdiReturn->ulVertRes = pdmRequested->dmPelsHeight;
pgdiReturn->ulVRefresh = pdmRequested->dmDisplayFrequency;
pgdiReturn->ulLogPixelsX = pdmRequested->dmLogPixels;
pgdiReturn->ulLogPixelsY = pdmRequested->dmLogPixels;
//
// If this is NT 4.0 SP-3, we get passed in the original GDIINFO of
// the real display. If not, we need to fake up one.
//
if (pgdiRequested->cPlanes != 0)
{
//
// Now overwrite the defaults with the relevant information returned
// from the kernel driver:
//
pgdiReturn->cBitsPixel = pgdiRequested->cBitsPixel;
pgdiReturn->cPlanes = pgdiRequested->cPlanes;
pgdiReturn->ulDACRed = pgdiRequested->ulDACRed;
pgdiReturn->ulDACGreen = pgdiRequested->ulDACGreen;
pgdiReturn->ulDACBlue = pgdiRequested->ulDACBlue;
}
else
{
pgdiReturn->cBitsPixel = pdmRequested->dmBitsPerPel;
pgdiReturn->cPlanes = 1;
switch (pgdiReturn->cBitsPixel)
{
case 8:
pgdiReturn->ulDACRed = pgdiReturn->ulDACGreen = pgdiReturn->ulDACBlue = 8;
break;
case 24:
pgdiReturn->ulDACRed = 0x00FF0000;
pgdiReturn->ulDACGreen = 0x0000FF00;
pgdiReturn->ulDACBlue = 0x000000FF;
break;
default:
ERROR_OUT(("Invalid color depth in NT 5.0 mirror driver"));
DC_QUIT;
break;
}
}
//
// Now save private copies of info we're returning to GDI
//
ppdev->cxScreen = pgdiReturn->ulHorzRes;
ppdev->cyScreen = pgdiReturn->ulVertRes;
ppdev->cBitsPerPel = pgdiReturn->cBitsPixel * pgdiReturn->cPlanes;
if (ppdev->cBitsPerPel == 15)
ppdev->cBitsPerPel = 16;
ppdev->flRed = pgdiReturn->ulDACRed;
ppdev->flGreen = pgdiReturn->ulDACGreen;
ppdev->flBlue = pgdiReturn->ulDACBlue;
//
// Fill in the devinfo structure with the default 8bpp values, taking
// care not to trash the supplied hpalDefault (which allows us to
// query information about the real display driver's color format).
//
// On NT 5.0, we don't get passed on the screen palette at all, we need
// to create our own.
//
hpal = pdiReturn->hpalDefault;
*pdiReturn = s_osiDefaultDevInfo;
switch (pgdiReturn->cBitsPixel * pgdiReturn->cPlanes)
{
case 4:
{
//
// NT 4.0 SP-3 ONLY
//
pgdiReturn->ulNumColors = 16;
pgdiReturn->ulNumPalReg = 0;
pgdiReturn->ulHTOutputFormat = HT_FORMAT_4BPP;
pdiReturn->flGraphicsCaps &= ~GCAPS_PALMANAGED;
pdiReturn->iDitherFormat = BMF_4BPP;
ppdev->iBitmapFormat = BMF_4BPP;
cColors = 16;
goto AllocPalEntries;
}
break;
case 8:
{
pgdiReturn->ulNumColors = 20;
pgdiReturn->ulNumPalReg = 256;
pdiReturn->iDitherFormat = BMF_8BPP;
ppdev->iBitmapFormat = BMF_8BPP;
cColors = 256;
AllocPalEntries:
//
// Alloc memory for the palette entries.
//
ppdev->pPal = EngAllocMem( FL_ZERO_MEMORY,
sizeof(PALETTEENTRY) * cColors,
OSI_ALLOC_TAG );
if (ppdev->pPal == NULL)
{
ERROR_OUT(("Failed to allocate palette memory"));
DC_QUIT;
}
}
break;
case 15:
case 16:
{
//
// NT 4.0 SP-3 ONLY
//
pgdiReturn->ulHTOutputFormat = HT_FORMAT_16BPP;
pdiReturn->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
pdiReturn->iDitherFormat = BMF_16BPP;
ppdev->iBitmapFormat = BMF_16BPP;
}
break;
case 24:
{
//
// DIB conversions will only work if we have a standard RGB
// surface for 24bpp.
//
pgdiReturn->ulHTOutputFormat = HT_FORMAT_24BPP;
pdiReturn->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
pdiReturn->iDitherFormat = BMF_24BPP;
ppdev->iBitmapFormat = BMF_24BPP;
}
break;
case 32:
{
//
// NT 4.0 SP-3 ONLY
//
pgdiReturn->ulHTOutputFormat = HT_FORMAT_32BPP;
pdiReturn->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
pdiReturn->iDitherFormat = BMF_32BPP;
ppdev->iBitmapFormat = BMF_32BPP;
}
break;
default:
{
//
// Unsupported bpp - pretend we are 8 bpp.
//
ERROR_OUT(("Unsupported bpp value: %d",
pgdiReturn->cBitsPixel * pgdiReturn->cPlanes));
DC_QUIT;
}
break;
}
if (!hpal)
{
//
// This is NT 5.0. We need to create a palette, either an 8bpp
// indexed one, or a 24bpp bitfield one.
//
if (ppdev->iBitmapFormat == BMF_8BPP)
{
ULONG ulLoop;
//
// We have to initialize the fixed part (top 10 and bottom 10)
// of the palette entries.
//
for (ulLoop = 0; ulLoop < 10; ulLoop++)
{
// First 10
ppdev->pPal[ulLoop] = s_aWinColors[ulLoop];
// Last 10
ppdev->pPal[256 - 10 + ulLoop] = s_aWinColors[ulLoop + 10];
}
// Create the palette from the entries.
hpal = EngCreatePalette(PAL_INDEXED, 256, (ULONG*)ppdev->pPal,
0, 0, 0);
//
// Set the flag in the PDEV to indicate that the palette has
// changed.
//
ppdev->paletteChanged = TRUE;
}
else
{
ASSERT(ppdev->iBitmapFormat == BMF_24BPP);
hpal = EngCreatePalette(PAL_BITFIELDS, 0, NULL,
ppdev->flRed, ppdev->flGreen, ppdev->flBlue);
}
ppdev->hpalCreated = hpal;
if (!hpal)
{
ERROR_OUT(("DrvEnablePDEV: could not create DEVINFO palette"));
DC_QUIT;
}
}
else
{
//
// This is NT 4.0 SP-3. Get the real bitmasks for > 8 bpp and
// the current palette colors for <= 8 bpp.
//
if (pgdiReturn->cBitsPixel <= 8)
{
if (ppdev->iBitmapFormat == BMF_4BPP)
{
ASSERT(cColors == 16);
}
else
{
ASSERT(cColors == 256);
}
if (cColors != EngQueryPalette(hpal, &iMode, cColors,
(ULONG *)ppdev->pPal))
{
ERROR_OUT(("Failed to query current display palette"));
}
//
// Set the flag in the PDEV to indicate that the palette has
// changed.
//
ppdev->paletteChanged = TRUE;
}
else
{
ULONG aulBitmasks[3];
//
// Query the true color bitmasks.
//
cColors = EngQueryPalette(hpal,
&iMode,
sizeof(aulBitmasks) / sizeof(aulBitmasks[0]),
&aulBitmasks[0] );
if (cColors == 0)
{
ERROR_OUT(("Failed to query real bitmasks"));
}
if (iMode == PAL_INDEXED)
{
ERROR_OUT(("Bitmask palette is indexed"));
}
//
// Get the real bitmasks for NT 4.0 SP-3 displays since we
// get the same info the real global display does, and we need
// to parse the bits in BitBlts, color tanslations, etc.
//
ppdev->flRed = aulBitmasks[0];
ppdev->flGreen = aulBitmasks[1];
ppdev->flBlue = aulBitmasks[2];
}
}
pdiReturn->hpalDefault = hpal;
rc = TRUE;
INIT_OUT(("DrvEnablePDEV: Returning bitmasks of:"));
INIT_OUT((" red %08x", ppdev->flRed));
INIT_OUT((" green %08x", ppdev->flGreen));
INIT_OUT((" blue %08x", ppdev->flBlue));
DC_EXIT_POINT:
DebugExitBOOL(OSIInitializeMode, rc);
return(rc);
}
//
// FUNCTION: OSI_DDProcessRequest
//
// DESCRIPTION:
//
// Called by the display driver to process an OSI specific request
//
// PARAMETERS: pso - pointer to surface object
// cjIn - (IN) size of request block
// pvIn - (IN) pointer to request block
// cjOut - (IN) size of response block
// pvOut - (OUT) pointer to response block
//
// RETURNS: None
//
//
ULONG OSI_DDProcessRequest(SURFOBJ* pso,
UINT cjIn,
void * pvIn,
UINT cjOut,
void * pvOut)
{
ULONG rc;
LPOSI_ESCAPE_HEADER pHeader;
LPOSI_PDEV ppdev = (LPOSI_PDEV)pso->dhpdev;
DebugEntry(OSI_DDProcessRequest);
//
// Get the request number.
//
pHeader = pvIn;
switch (pHeader->escapeFn)
{
case OSI_ESC_INIT:
{
TRACE_OUT(("DrvEscape: OSI_ESC_INIT"));
ASSERT(cjOut == sizeof(OSI_INIT_REQUEST));
//
// Get shared memory block
//
OSI_DDInit(ppdev, (LPOSI_INIT_REQUEST)pvOut);
rc = TRUE;
}
break;
case OSI_ESC_TERM:
{
TRACE_OUT(("DrvEscape: OSI_ESC_TERM"));
ASSERT(cjIn == sizeof(OSI_TERM_REQUEST));
//
// Cleanup, NM is going away
//
OSI_DDTerm(ppdev);
rc = TRUE;
}
break;
case OSI_ESC_SYNC_NOW:
{
TRACE_OUT(("DrvEscape: OSI_ESC_SYNC_NOW"));
ASSERT(cjIn == sizeof(OSI_ESCAPE_HEADER));
//
// Resync with the 32-bit ring 3 core. This happens when
// somebody joins or leaves a share.
//
BA_ResetBounds();
OA_DDSyncUpdatesNow();
SBC_DDSyncUpdatesNow(ppdev);
rc = TRUE;
}
break;
default:
{
ERROR_OUT(("Unrecognised request %lu", pHeader->escapeFn));
rc = FALSE;
}
break;
}
DebugExitBOOL(OSI_DDProcessRequest, rc);
return(rc);
}
//
// Function: OSI_DDInit
//
// Description: Map the shared memory into Kernel and User space
//
// Parameters: count - size of the buffer to return to user space
// pData - pointer to the buffer to be returned to user space
//
// Returns: (none)
//
void OSI_DDInit(LPOSI_PDEV ppdev, LPOSI_INIT_REQUEST pResult)
{
DWORD memRemaining;
LPBYTE pBuffer;
LPVOID shmMappedMemory;
VIDEO_SHARE_MEMORY ShareMemory;
VIDEO_SHARE_MEMORY_INFORMATION ShareMemoryInformation;
DWORD ReturnedDataLength;
DebugEntry(OSI_DDInit);
// Init to FALSE
pResult->result = FALSE;
// Initialize these to NULL
pResult->pSharedMemory = NULL;
pResult->poaData[0] = NULL;
pResult->poaData[1] = NULL;
pResult->sbcEnabled = FALSE;
//
// Check that the memory is available to the driver and that we are not
// in a race condition.
//
if (g_asSharedMemory == NULL)
{
ERROR_OUT(("No memory available"));
DC_QUIT;
}
if (g_shmMappedMemory != NULL)
{
//
// We will never come in here with two copies of NetMeeting running.
// The UI code prevents the second instance from starting long
// before app sharing is in the picture. Therefore, these are the
// only possibilities:
//
// (1) Previous version is almost shutdown but hasn't called OSI_DDTerm
// yet and new version is starting up and calls OSI_DDInit
//
// (2) Previous version terminated abnormally and never called
// OSI_DDTerm(). This code handles the second case. The first one
// is handled by the same code in the UI that prevents two copies
// from starting around the same time.
//
WARNING_OUT(("OSI_DDInit: NetMeeting did not shutdown cleanly last time"));
OSI_DDTerm(ppdev);
}
//
// Map the shared section into the caller's process.
//
INIT_OUT(("OSI_DDInit: Mapping 0x%08x bytes of kernel memory at 0x%08x into caller process",
g_shmSharedMemorySize, g_asSharedMemory));
ShareMemory.ProcessHandle = LongToHandle(-1);
ShareMemory.ViewOffset = 0;
ShareMemory.ViewSize = g_shmSharedMemorySize;
ShareMemory.RequestedVirtualAddress = NULL;
if (EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_SHARE_VIDEO_MEMORY,
&ShareMemory,
sizeof(VIDEO_SHARE_MEMORY),
&ShareMemoryInformation,
sizeof(VIDEO_SHARE_MEMORY_INFORMATION),
&ReturnedDataLength) != 0)
{
ERROR_OUT(("Failed to map shared memory into calling process"));
DC_QUIT;
}
//
// USER MODE pointer (not valid in kernel mode)
//
INIT_OUT(("OSI_DDInit: Mapped 0x%08x bytes of kernel memory to user memory 0x%08x",
g_shmSharedMemorySize, ShareMemoryInformation.VirtualAddress));
shmMappedMemory = ShareMemoryInformation.VirtualAddress;
pResult->pSharedMemory = shmMappedMemory;
pResult->poaData[0] = ((LPSHM_SHARED_MEMORY)pResult->pSharedMemory) + 1;
pResult->poaData[1] = ((LPOA_SHARED_DATA)pResult->poaData[0]) + 1;
TRACE_OUT(("Shared memory %08lx %08lx %08lx",
pResult->pSharedMemory, pResult->poaData[0], pResult->poaData[1]));
//
// Clear out the shared memory, so it's ready for immediate use.
// NOTE THAT THIS SETS ALL VALUES TO FALSE.
// NOTE ALSO THAT THIS CLEARS the two OA_SHARED_DATAs also
//
RtlFillMemory(g_asSharedMemory, SHM_SIZE_USED, 0);
g_asSharedMemory->displayToCore.indexCount = 0;
//
// Set up our pointer to the variable part of the shared memory i.e.
// the part which is not used for the SHM_SHARED_MEMORY structure
// We must skip past g_asSharedMemory, two CM_FAST_DATA structs, and
// two OA_SHARED_DATA structs.
//
pBuffer = (LPBYTE)g_asSharedMemory;
pBuffer += SHM_SIZE_USED;
memRemaining = g_shmSharedMemorySize - SHM_SIZE_USED;
//
// Initialise the other components required for DC-Share
//
//
// Bounds accumulation
//
BA_DDInit();
//
// Cursor
//
if (!CM_DDInit(ppdev))
{
ERROR_OUT(("CM failed to init"));
DC_QUIT;
}
//
// Send Bitmap Cache
// NOTE that if it initializes OK but no caching allowed, we will continue.
//
// This will fill in the tile buffers & info. If no SBC caching allowed,
// the sbcEnabled field will be FALSE.
//
if (SBC_DDInit(ppdev, pBuffer, memRemaining, pResult))
{
pResult->sbcEnabled = TRUE;
}
//
// Mark memory as ready to use.
//
g_shmMappedMemory = shmMappedMemory;
pResult->result = TRUE;
DC_EXIT_POINT:
DebugExitVOID(OSI_DDInit);
}
//
// Function: OSI_DDTerm
//
// Description: Cleanup when NM shuts down
//
// Returns: (none)
//
void OSI_DDTerm(LPOSI_PDEV ppdev)
{
DebugEntry(OSI_DDTerm);
//
// Check for a valid address - must be non-NULL.
//
if (!g_asSharedMemory)
{
ERROR_OUT(("Invalid memory"));
DC_QUIT;
}
//
// Terminate the dependent components.
//
//
// Hosted Entity Tracker
//
HET_DDTerm();
//
// Order Encoding
//
OE_DDTerm();
//
// Send Bitmap Cache
//
SBC_DDTerm();
//
// Cursor manager.
//
CM_DDTerm();
//
// The shared memory will be unmapped automatically in this process
// by OS cleanup, in both NT4 and NT5
//
g_shmMappedMemory = NULL;
DC_EXIT_POINT:
DebugExitVOID(OSI_DDTerm);
}