|
|
#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); }
|