Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1875 lines
54 KiB

/******************************Module*Header*******************************\
* Module Name: pdevobj.cxx
*
* Non-inline methods of PDEVOBJ objects.
*
* Copyright (c) 1990-1995 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
//
// This flag is TRUE if the default GUI stock font is partially intialized.
// During stock font initialization there is no display driver and therefore
// we do not have one of the parameters (vertical DPI) needed to compute
// the font height. Therefore, we do it when the first display driver is
// initialized.
//
extern BOOL gbFinishDefGUIFontInit;
// Use this as the default height if LOGFONTs provided by DEVINFO do not
// specify.
#define DEFAULT_POINT_SIZE 12L
#if ((HT_PATSIZE_2x2 != HTPAT_SIZE_2x2) || \
(HT_PATSIZE_2x2_M != HTPAT_SIZE_2x2_M) || \
(HT_PATSIZE_4x4 != HTPAT_SIZE_4x4) || \
(HT_PATSIZE_4x4_M != HTPAT_SIZE_4x4_M) || \
(HT_PATSIZE_6x6 != HTPAT_SIZE_6x6) || \
(HT_PATSIZE_6x6_M != HTPAT_SIZE_6x6_M) || \
(HT_PATSIZE_8x8 != HTPAT_SIZE_8x8) || \
(HT_PATSIZE_8x8_M != HTPAT_SIZE_8x8_M) || \
(HT_PATSIZE_10x10 != HTPAT_SIZE_10x10) || \
(HT_PATSIZE_10x10_M != HTPAT_SIZE_10x10_M) || \
(HT_PATSIZE_12x12 != HTPAT_SIZE_12x12) || \
(HT_PATSIZE_12x12_M != HTPAT_SIZE_12x12_M) || \
(HT_PATSIZE_14x14 != HTPAT_SIZE_14x14) || \
(HT_PATSIZE_14x14_M != HTPAT_SIZE_14x14_M) || \
(HT_PATSIZE_16x16 != HTPAT_SIZE_16x16) || \
(HT_PATSIZE_16x16_M != HTPAT_SIZE_16x16_M))
#error * HT_PATSIZE different in winddi.h and ht.h *
#endif
#if ((HT_FLAG_SQUARE_DEVICE_PEL != HIF_SQUARE_DEVICE_PEL) || \
(HT_FLAG_HAS_BLACK_DYE != HIF_HAS_BLACK_DYE) || \
(HT_FLAG_ADDITIVE_PRIMS != HIF_ADDITIVE_PRIMS))
#error * HT_FLAG different in winddi.h and ht.h *
#endif
//
// Global variable that can be set in the debugger.
// This will allow the printer driver developers to unload printer drivers
// until the spooler can be fixed properly
//
BOOL gbUnloadPrinterDrivers = FALSE;
//
// Global linked list of all PDEVs in the system.
//
extern "C"
{
extern PFAST_MUTEX pgfmMemory;
}
PPDEV gppdevList = NULL;
PPDEV gppdevTrueType = NULL;
VOID
vConvertLogFontW(
EXTLOGFONTW *pelfw,
LOGFONTW *plfw
);
/******************************Member*Function*****************************\
* PDEVOBJ::bMakeSurface ()
*
* Asks the device driver to create a surface for the PDEV. This function
* can be called even if the PDEV already has a surface.
*
\**************************************************************************/
BOOL PDEVOBJ::bMakeSurface()
{
if (ppdev->pSurface != NULL)
return(TRUE);
TRACE_INIT(("PDEVOBJ::bMakeSurface: ENTERING\n"));
HSURF hTemp = (HSURF) 0;
// Ask the driver for a surface.
PDEVOBJ po((HDEV)ppdev);
hTemp = (*PPFNDRV(po,EnableSurface))(ppdev->dhpdev);
if (hTemp == (HSURF) 0)
{
WARNING("EnableSurface on device return hsurf 0\n");
return(FALSE);
}
SURFREF sr(hTemp);
ASSERTGDI(sr.bValid(),"Bad surface for device");
// Mark this as a device surface.
sr.ps->vPDEVSurface();
sr.vKeepIt();
ppdev->pSurface = sr.ps;
// For 1.0 compatibility, set the pSurface iFormat to iDitherFormat. This can
// be changed to an ASSERT if we no longer wants to support NT 1.0 drivers,
// which has BMF_DEVICE in the iFormat for device surfaces.
if (sr.ps->iFormat() == BMF_DEVICE)
{
sr.ps->iFormat(ppdev->devinfo.iDitherFormat);
ASSERTGDI(ppdev->devinfo.iDitherFormat != BMF_DEVICE,
"ERROR iformat is hosed\n");
}
// Put the PDEV's palette in the main device surface.
// Reference count the palette, it has a new user.
ppdev->pSurface->ppal(ppdev->ppalSurf);
HmgShareLock((HOBJ) ppdev->ppalSurf->hGet(), PAL_TYPE);
// ASSERT it has an owner and a palette.
// ASSERTGDI(ppdev->pSurface->ppal() != NULL, "ERROR GDI bMakeSurface2");
TRACE_INIT(("PDEVOBJ::bMakeSurface: SUCCESS\n"));
return(TRUE);
}
/******************************Member*Function*****************************\
* PDEVOBJ::bEnableHalftone(pca)
*
* Creates and initializes a device halftone info. The space is allocated
* by the halftone.dll with heapCreate() and heapAlloc() calls. All
* the halftone resources are managed by the halftone.dll.
*
* History:
* 07-Nov-1991 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
COLORADJUSTMENT gcaDefault =
{
sizeof(COLORADJUSTMENT), // WORD caSize
0, // WORD caFlags
ILLUMINANT_DEFAULT, // WORD caIlluminantIndex
10000, // WORD caRedPowerGamma
10000, // WORD caGreenPowerGamma
10000, // WORD caBluePowerGamma
REFERENCE_BLACK_DEFAULT, // WORD caReferenceBlack
REFERENCE_WHITE_DEFAULT, // WORD caReferenceWhite
CONTRAST_ADJ_DEFAULT, // SHORT caContrast
BRIGHTNESS_ADJ_DEFAULT, // SHORT caBrightness
COLORFULNESS_ADJ_DEFAULT, // SHORT caColorfulness
REDGREENTINT_ADJ_DEFAULT, // SHORT caRedGreenTint
};
BOOL PDEVOBJ::bEnableHalftone(PCOLORADJUSTMENT pca)
{
ASSERTGDI(pDevHTInfo() == NULL, "bEnableHalftone: pDevHTInfo not null\n");
//
// Create a halftone palette based on the format specified in GDIINFO.
//
PALMEMOBJ palHT;
if (!palHT.bCreateHTPalette(GdiInfo()->ulHTOutputFormat, GdiInfo()))
return(FALSE);
//
// Create the device halftone info.
//
HTINITINFO htInitInfo;
htInitInfo.Version = HTINITINFO_VERSION;
htInitInfo.Flags = (BYTE)ppdev->GdiInfo.flHTFlags;
if (ppdev->GdiInfo.ulHTPatternSize <= HTPAT_SIZE_MAX_INDEX)
htInitInfo.HTPatternIndex = (BYTE)ppdev->GdiInfo.ulHTPatternSize;
else
htInitInfo.HTPatternIndex = HTPAT_SIZE_DEFAULT;
PCOLORINFO pci = &GdiInfo()->ciDevice;
htInitInfo.DevicePowerGamma = (UDECI4)((pci->RedGamma + pci->GreenGamma +
pci->BlueGamma) / 3);
htInitInfo.HTCallBackFunction = NULL;
htInitInfo.pHalftonePattern = NULL;
htInitInfo.pInputRGBInfo = NULL;
CIEINFO cie;
cie.Red.x = (DECI4)pci->Red.x;
cie.Red.y = (DECI4)pci->Red.y;
cie.Red.Y = (DECI4)pci->Red.Y;
cie.Green.x = (DECI4)pci->Green.x;
cie.Green.y = (DECI4)pci->Green.y;
cie.Green.Y = (DECI4)pci->Green.Y;
cie.Blue.x = (DECI4)pci->Blue.x;
cie.Blue.y = (DECI4)pci->Blue.y;
cie.Blue.Y = (DECI4)pci->Blue.Y;
cie.Cyan.x = (DECI4)pci->Cyan.x;
cie.Cyan.y = (DECI4)pci->Cyan.y;
cie.Cyan.Y = (DECI4)pci->Cyan.Y;
cie.Magenta.x = (DECI4)pci->Magenta.x;
cie.Magenta.y = (DECI4)pci->Magenta.y;
cie.Magenta.Y = (DECI4)pci->Magenta.Y;
cie.Yellow.x = (DECI4)pci->Yellow.x;
cie.Yellow.y = (DECI4)pci->Yellow.y;
cie.Yellow.Y = (DECI4)pci->Yellow.Y;
cie.AlignmentWhite.x = (DECI4)pci->AlignmentWhite.x;
cie.AlignmentWhite.y = (DECI4)pci->AlignmentWhite.y;
cie.AlignmentWhite.Y = (DECI4)pci->AlignmentWhite.Y;
htInitInfo.pDeviceCIEInfo = &cie;
SOLIDDYESINFO DeviceSolidDyesInfo;
DeviceSolidDyesInfo.MagentaInCyanDye = (UDECI4)pci->MagentaInCyanDye;
DeviceSolidDyesInfo.YellowInCyanDye = (UDECI4)pci->YellowInCyanDye;
DeviceSolidDyesInfo.CyanInMagentaDye = (UDECI4)pci->CyanInMagentaDye;
DeviceSolidDyesInfo.YellowInMagentaDye = (UDECI4)pci->YellowInMagentaDye;
DeviceSolidDyesInfo.CyanInYellowDye = (UDECI4)pci->CyanInYellowDye;
DeviceSolidDyesInfo.MagentaInYellowDye = (UDECI4)pci->MagentaInYellowDye;
htInitInfo.pDeviceSolidDyesInfo = &DeviceSolidDyesInfo;
htInitInfo.DeviceResXDPI = (WORD)ppdev->GdiInfo.ulLogPixelsX;
htInitInfo.DeviceResYDPI = (WORD)ppdev->GdiInfo.ulLogPixelsY;
htInitInfo.DevicePelsDPI = (WORD)ppdev->GdiInfo.ulDevicePelsDPI;
if (pca == NULL)
htInitInfo.DefHTColorAdjustment = gcaDefault;
else
htInitInfo.DefHTColorAdjustment = *pca;
if (HT_CreateDeviceHalftoneInfo(&htInitInfo,
(PPDEVICEHALFTONEINFO)&(ppdev->pDevHTInfo)) <= 0L)
{
SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
ppdev->pDevHTInfo = NULL;
return(FALSE);
}
// Check if halftone palette is the same as the device palette.
//
// For now, don't do display devices because dynamic mode changes may
// cause their palette to change at any time.
vHTPalIsDevPal(FALSE);
if (!bDisplayPDEV())
{
XEPALOBJ palSurf(ppalSurf());
if (palHT.bEqualEntries(palSurf))
vHTPalIsDevPal(TRUE);
}
// Keep the halftone palette since this function won't fail.
((DEVICEHALFTONEINFO *)pDevHTInfo())->DeviceOwnData = (DWORD)palHT.hpal();
palHT.vSetPID(OBJECT_OWNER_PUBLIC);
palHT.vKeepIt();
return(TRUE);
}
/******************************Member*Function*****************************\
* PDEVOBJ::bDisableHalftone()
*
* Delete the device halftone info structure.
*
* History:
* 07-Nov-1991 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
BOOL PDEVOBJ::bDisableHalftone()
{
ASSERTGDI((pDevHTInfo() != NULL), "bDisableHalftone: DevHTInfo null\n");
DEVICEHALFTONEINFO *pDevHTInfo_ = (DEVICEHALFTONEINFO *)pDevHTInfo();
if (bAllocatedBrushes())
for(int iPat = 0; iPat < HS_DDI_MAX; iPat++)
{
bDeleteSurface(ppdev->ahsurf[iPat]);
}
ppdev->pDevHTInfo = NULL;
// Delete the halftone palette.
BOOL bStatusPal = bDeletePalette((HPAL)pDevHTInfo_->DeviceOwnData);
BOOL bStatusHT = HT_DestroyDeviceHalftoneInfo(pDevHTInfo_);
return(bStatusPal && bStatusHT);
}
typedef BOOL (*RFN)(DHPDEV,DEVMODE *,ULONG,HSURF *,ULONG,ULONG *,ULONG,DEVINFO *);
/**************************************************************************\
* PDEVOBJ::bCreateDefaultBrushes()
*
\**************************************************************************/
ULONG gaaulPat[HS_DDI_MAX][8] = {
// Scans have to be DWORD aligned:
{ 0x00, // ........ HS_HORIZONTAL 0
0x00, // ........
0x00, // ........
0xff, // ********
0x00, // ........
0x00, // ........
0x00, // ........
0x00 }, // ........
{ 0x08, // ....*... HS_VERTICAL 1
0x08, // ....*...
0x08, // ....*...
0x08, // ....*...
0x08, // ....*...
0x08, // ....*...
0x08, // ....*...
0x08 }, // ....*...
{ 0x80, // *....... HS_FDIAGONAL 2
0x40, // .*......
0x20, // ..*.....
0x10, // ...*....
0x08, // ....*...
0x04, // .....*..
0x02, // ......*.
0x01 }, // .......*
{ 0x01, // .......* HS_BDIAGONAL 3
0x02, // ......*.
0x04, // .....*..
0x08, // ....*...
0x10, // ...*....
0x20, // ..*.....
0x40, // .*......
0x80 }, // *.......
{ 0x08, // ....*... HS_CROSS 4
0x08, // ....*...
0x08, // ....*...
0xff, // ********
0x08, // ....*...
0x08, // ....*...
0x08, // ....*...
0x08 }, // ....*...
{ 0x81, // *......* HS_DIAGCROSS 5
0x42, // .*....*.
0x24, // ..*..*..
0x18, // ...**...
0x18, // ...**...
0x24, // ..*..*..
0x42, // .*....*.
0x81 } // *......*
};
/******************************Public*Routine******************************\
* BOOL bInitializePatterns
*
* Initialize the default patterns.
*
\**************************************************************************/
BOOL PDEVOBJ::bCreateDefaultBrushes()
{
SIZEL sizl;
LONG i;
sizl.cx = 8;
sizl.cy = 8;
for (i = 0; i < HS_DDI_MAX; i++)
{
ppdev->ahsurf[i] = (HSURF) EngCreateBitmap(sizl,
(LONG) sizeof(ULONG),
BMF_1BPP,
BMF_TOPDOWN,
&gaaulPat[i][0]);
if (ppdev->ahsurf[i] == NULL)
{
TRACE_INIT(("Failed bCreateDefaultBrushes - BAD !"));
return(FALSE);
}
}
return(TRUE);
}
/******************************Member*Function*****************************\
* PDEVOBJ::bInitHalftoneBrushs()
*
* History:
* The standard patterns for the NT/window has following order
*
* Index 0 - Horizontal Line
* Index 1 - Vertical Line
* Index 2 - 45 degree line going up
* Index 3 - 45 degree line going down
* Index 4 - Horizontal/Vertical cross
* Index 5 - 45 degree line up/down cross
* Index 6 - 30 degree line going up
* Index 7 - 30 degree line going down
* Index 8 - 0% Lightness (BLACK)
* Index 9 - 11% Lightness (very light Gray)
* Index 10 - 22% Lightness
* Index 11 - 33% Lightness
* Index 12 - 44% Lightness
* Index 13 - 56% Lightness
* Index 14 - 67% Lightness
* Index 15 - 78% Lightness
* Index 16 - 89% Lightness
* Index 17 - 100% Lightness (White)
* Index 18 - 50% Lightness (GRAY)
*
*Return Value:
*
* return value is total patterns created, if return value is <= 0 then an
* error occurred.
*
*
*Author:
*
* 10-Mar-1992 Tue 20:30:44 created -by- Daniel Chou (danielc)
*
* 24-Nov-1992 -by- Eric Kutter [erick] and DanielChou (danielc)
* moved from printers\lib
\**************************************************************************/
BOOL PDEVOBJ::bCreateHalftoneBrushs()
{
STDMONOPATTERN SMP;
LONG cbPat;
LONG cb2;
INT cPatRet;
static BYTE HTStdPatIndex[HS_DDI_MAX] = {
HT_SMP_HORZ_LINE,
HT_SMP_VERT_LINE,
HT_SMP_DIAG_45_LINE_DOWN,
HT_SMP_DIAG_45_LINE_UP,
HT_SMP_HORZ_VERT_CROSS,
HT_SMP_DIAG_45_CROSS
};
// better initialize the halftone stuff if it isn't already
if ((pDevHTInfo() == NULL) && !bEnableHalftone(NULL))
return(FALSE);
cbPat = (LONG)sizeof(LPBYTE) * (LONG)(HS_DDI_MAX + 1);
// go through all the standard patterns
for(cPatRet = 0; cPatRet < HS_DDI_MAX;)
{
// We will using default 0.01" line width and 10 lines per inch
// halftone default
SMP.Flags = SMP_TOPDOWN;
SMP.ScanLineAlignBytes = BMF_ALIGN_DWORD;
SMP.PatternIndex = HTStdPatIndex[cPatRet];
SMP.LineWidth = 8;
SMP.LinesPerInch = 15;
// Get the cx/cy size of the pattern and total bytes required
// to stored the pattern
SMP.pPattern = NULL; /* To find the size */
if ((cbPat = HT_CreateStandardMonoPattern((PDEVICEHALFTONEINFO)pDevHTInfo(), &SMP)) <= 0)
{
break;
}
//
// create the bitmap
//
DEVBITMAPINFO dbmi;
dbmi.iFormat = BMF_1BPP;
dbmi.cxBitmap = SMP.cxPels;
dbmi.cyBitmap = SMP.cyPels;
dbmi.hpal = (HPALETTE) 0;
dbmi.fl = BMF_TOPDOWN;
SURFMEM SurfDimo;
SurfDimo.bCreateDIB(&dbmi, NULL);
if (!SurfDimo.bValid())
{
break;
}
SurfDimo.vKeepIt();
SurfDimo.vSetPID(OBJECT_OWNER_PUBLIC);
ppdev->ahsurf[cPatRet] = SurfDimo.ps->hsurf();
SMP.pPattern = (PBYTE)SurfDimo.ps->pvBits();
//
// advance the count now so we clean up as appropriate
//
++cPatRet;
// now set the bits
if ((cb2 = HT_CreateStandardMonoPattern((PDEVICEHALFTONEINFO)pDevHTInfo(), &SMP)) != cbPat)
{
break;
}
}
// if we failed, we had better delete what we created.
if (cPatRet < HS_DDI_MAX)
{
while (cPatRet-- > 0)
{
bDeleteSurface(ppdev->ahsurf[cPatRet]);
}
return(FALSE);
}
bAllocatedBrushes(TRUE);
return(TRUE);
}
/******************************Public*Routine******************************\
* FLONG flRaster(ulTechnology, flGraphicsCaps)
*
* Computes the appropriate Win3.1 style 'flRaster' flags for the device
* given GDIINFO data.
*
* History:
* 1-Feb-1993 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
*
\**************************************************************************/
FLONG flRaster(ULONG ulTechnology, FLONG flGraphicsCaps)
{
// Flags Win32 never sets:
// -----------------------
//
// RC_BANDING -- Banding is always transparent to programmer
// RC_SCALING -- Special scaling support is never required
// RC_GDI20_OUTPUT -- Win2.0 state blocks in device contexts not supported
// RC_SAVEBITMAP -- Bitmap saving is transparent and SaveScreenBitmap not
// exported
// RC_DEVBITS -- Drivers don't export BitmapBits or SelectBitmap
// Flags Win32 always sets:
// ------------------------
FLONG fl = (RC_BIGFONT | // All devices support fonts > 64k
RC_GDI20_OUTPUT | // We handle most Win 2.0 features
// All devices must provide support for BitBlt operations to the device.
// Although many plotters can't support Blts to the device, they can just
// fail the call:
RC_BITBLT | // Can transfer bitmaps
RC_BITMAP64 | // Can support bitmaps > 64k
RC_DI_BITMAP | // Support SetDIBIts and GetDIBits
RC_DIBTODEV | // Support SetDIBitsToDevice
RC_STRETCHBLT | // Support StretchBlts
RC_STRETCHDIB | // Support SetchDIBits
// Set that not-terribly-well documented text flag:
RC_OP_DX_OUTPUT); // Can do opaque ExtTextOuts with dx array
// Printers can't journal FloodFill cals, so only allow raster displays:
if (ulTechnology == DT_RASDISPLAY)
fl |= RC_FLOODFILL;
// Set palette flag from capabilities bit:
if (flGraphicsCaps & GCAPS_PALMANAGED)
fl |= RC_PALETTE;
return(fl);
}
/******************************Member*Function*****************************\
* PDEVREF::PDEVREF (hdev) *
* *
* Increments the reference count of an existing PDEV. *
* *
* Leaves the PDEV locked longterm. *
* *
\**************************************************************************/
PDEVREF::PDEVREF(HDEV hdev)
{
//
// We protect the cRefs count with the DriverMgmt semaphore. This is the
// same semaphore which protects the LDEV counts.
//
SEMOBJ so(gpsemDriverMgmt);
bKeep = FALSE;
ppdev = (PDEV *) hdev;
ppdev->cPdevRefs++;
}
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* HACK !!!
*
*/
LPWSTR
EngGetPrinterDataFileName(
HDEV hdev)
{
return ((PPDEV)hdev)->pwszDataFile;
}
/*
* HACK !!!
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
LPWSTR
EngGetDriverName(
HDEV hdev)
{
return ((PPDEV)hdev)->pldev->pGdiDriverInfo->DriverName.Buffer;
}
/******************************Member*Function*****************************\
* PDEVREF::PDEVREF
*
* Allocates and initializes a PDEV, i.e. takes the reference count from
* zero to one.
*
* The object must be completely constructed, otherwise completely destroyed.
*
\**************************************************************************/
PDEVREF::PDEVREF
(
LDEVREF& lr,
PDEVMODEW pdriv,
PWSZ pwszLogAddr,
PWSZ pwszDataFile,
PWSZ pwszDeviceName,
HANDLE hSpool,
PREMOTETYPEONENODE pRemoteTypeOne
)
{
bKeep = FALSE;
TRACE_INIT(("PDEVREF::PDEVREF: ENTERING\n"));
//
// Allocate the PDEV.
//
ppdev = (PDEV *) PALLOCMEM(sizeof(PDEV), 'veDG');
if (ppdev == NULL)
{
WARNING("PDEVREF::PDEVREF failed allocation of PDEV\n");
return;
}
ppdev->ppdevParent = ppdev;
ppdev->pldev = lr.pldevGet();
TRACE_INIT(("PDEVREF::PDEVREF: Calling driver to initialize PDEV\n"));
PDEVOBJ pdo((HDEV) ppdev);
//
// BUGBUG fill in the dispatch table until it comes in from the driver.
//
RtlMoveMemory(&(ppdev->apfn[0]),
&(ppdev->pldev->apfn[0]),
sizeof(PFN) * INDEX_LAST);
//
// if we are doing a ResetDC then we need to transfer over remote type 1
// fonts from previous PDEV
//
ppdev->RemoteTypeOne = pRemoteTypeOne;
//
// HACK - temporary
//
ppdev->pwszDataFile = pwszDataFile;
//
// Ask the device driver to create a PDEV.
//
ppdev->dhpdev = (*PPFNDRV(pdo,EnablePDEV)) (
pdriv, // Driver Data.
pwszLogAddr, // Logical Address.
HS_DDI_MAX, // Count of standard patterns.
ppdev->ahsurf, // Buffer for standard patterns
sizeof(GDIINFO), // Size of GdiInfo
&ppdev->GdiInfo, // Buffer for GdiInfo
sizeof(DEVINFO), // Number of bytes in devinfo.
&ppdev->devinfo, // Device info.
(HDEV)ppdev, // Data File
pwszDeviceName, // Device Name
hSpool); // Base driver handle
if (ppdev->dhpdev)
{
TRACE_INIT(("PDEVREF::PDEVREF: PDEV initialized by the driver\n"));
if (ppdev->pldev->ldevType != LDEV_FONT)
{
//
// Make sure that units are in MicroMeters for HorzSize, VertSize
//
if ( (LONG)ppdev->GdiInfo.ulHorzSize < 0 )
{
ppdev->GdiInfo.ulHorzSize = (ULONG)(-(LONG)ppdev->GdiInfo.ulHorzSize);
}
else
{
ppdev->GdiInfo.ulHorzSize *= 1000;
}
if ( (LONG)ppdev->GdiInfo.ulVertSize < 0 )
{
ppdev->GdiInfo.ulVertSize = (ULONG)(-(LONG)ppdev->GdiInfo.ulVertSize);
}
else
{
ppdev->GdiInfo.ulVertSize *= 1000;
}
//
// Fill in defaults for new GDIINFO fields if this is a down-level
// driver.
//
// NO longer needed since we do not support those drivers !
//
// if (lr.ulDriverVersion() < ENGINE_VERSION10A)
// {
// ppdev->GdiInfo.ulVRefresh = 0;
// }
//
// NO longer needed since we do not support those drivers !
//
// if ((lr.ulDriverVersion() < ENGINE_VERSION10B) ||
// (ppdev->GdiInfo.ulTechnology != DT_RASDISPLAY))
// {
// ppdev->GdiInfo.ulDesktopHorzRes = ppdev->GdiInfo.ulHorzRes;
// ppdev->GdiInfo.ulDesktopVertRes = ppdev->GdiInfo.ulVertRes;
// ppdev->GdiInfo.ulBltAlignment = 1;
// }
//
ASSERTGDI(ppdev->GdiInfo.ulAspectX != 0, "Device gave AspectX of 0");
ASSERTGDI(ppdev->GdiInfo.ulAspectY != 0, "Device gave AspectY of 0");
ASSERTGDI(ppdev->GdiInfo.ulAspectXY != 0, "Device gave AspectXY of 0");
ASSERTGDI(ppdev->GdiInfo.xStyleStep != 0, "Device gave xStyleStep of 0");
ASSERTGDI(ppdev->GdiInfo.yStyleStep != 0, "Device gave yStyleStep of 0");
ASSERTGDI(ppdev->GdiInfo.denStyleStep != 0, "Device gave denStyleStep of 0");
//
// Compute the appropriate raster flags:
//
ppdev->GdiInfo.flRaster = flRaster(ppdev->GdiInfo.ulTechnology,
ppdev->devinfo.flGraphicsCaps);
#if defined(_MIPS_)
//
// turn off 64 bit copies on hardware that doe snot support it
//
if (ppdev->devinfo.flGraphicsCaps & GCAPS_NO64BITMEMACCESS)
{
WARNING("Disable 64 bit access on this device !\n");
CopyMemFn = RtlMoveMemory32;
FillMemFn = memset32;
FillMemUlongFn = RtlFillMemoryUlong32;
Gdip64bitDisabled = 1;
}
#endif
TRACE_INIT(("PDEVREF::PDEVREF: Creating the default palette\n"));
//
// The default palette is stored in devinfo in the pdev.
// This will be the palette we use for the main surface enabled.
//
ASSERTGDI(ppdev->devinfo.hpalDefault != 0,
"ERROR devinfo.hpalDefault invalid");
{
EPALOBJ palDefault(ppdev->devinfo.hpalDefault);
ASSERTGDI(palDefault.bValid(), "ERROR hpalDefault invalid");
if (ppdev->GdiInfo.flRaster & RC_PALETTE)
{
//
// Attempt to make it palette managed.
// This function can't really fail, if it does
// we just have a fixed palette.
//
// !!! That's not really true about it failing -- the
// bIsPalManaged() flag in the PDEV will still be set,
// and the palette gets confused if that's the case.
// We should really fail here if this happens.
//
CreateSurfacePal(palDefault,
PAL_MANAGED,
ppdev->GdiInfo.ulNumColors,
ppdev->GdiInfo.ulNumPalReg);
}
ppalSurf(palDefault.ppalGet());
//
// Leave a reference count of 1 on this palette.
//
palDefault.ppalSet(NULL);
}
//
// if the driver didn't fill in the brushes, we'll do it.
//
// if it's a display driver, we'll overwrite its brushes with our
// own, regardless of whether it already filled in the brushes or
// not. Note that it's okay even if a display driver filled in
// these values -- the driver already had to keep its own copy of
// the handles and will clean them up at DrvDisablePDEV time.
// Supplying our own defaults also simplifies GreDynamicModeChange.
//
if ( (ppdev->ahsurf[0] == NULL) ||
(ppdev->pldev->ldevType & LDEV_DEVICE_DISPLAY) )
{
TRACE_INIT(("PDEVREF::PDEVREF: Creating brushes dor the driver\n"));
if ( (ppdev->pldev->ldevType & LDEV_DEVICE_DISPLAY) ||
(ppdev->pldev->ldevType & LDEV_META_DEVICE) )
{
//
// BUGBUG Andre
// replace this with a breakpoint or bugcheck since driver
// writers don't necessarily test on a checked system !
//
// ASSERTGDI(ppdev->ahsurf[0] == NULL,
// "Display Driver should NOT create brushes !\n");
// Andre Vachon
// 6-6-95 Kernel mode cleanup
//
// BUGBUG The old behaviour is the call the halftoneBrushes function
// It ends up in a bunch of very complex halftoning code that I have
// no idead what it does.
// For now, to clean up drivers in kernel mode, replace this call
// with a simple function that will create the 6 bitmaps just
// like display drivers did.
//
if (!bCreateDefaultBrushes())
{
//
// Free the PDEV.
//
VFREEMEM(ppdev);
ppdev = (PDEV *) NULL;
//
// Device should have logged correct error code.
//
WARNING("PDEVREF::PDEVREF Device failed DrvEnablePDEV\n");
return;
}
}
else
{
if (!bCreateHalftoneBrushs())
{
//
// Free the PDEV.
//
VFREEMEM(ppdev);
ppdev = (PDEV *) NULL;
//
// Device should have logged correct error code.
//
WARNING("PDEVREF::PDEVREF Device failed DrvEnablePDEV\n");
return;
}
}
}
#if DBG
// We fault in the brush realization code if all the standard patterns are
// not passed in. The brush realization code should probably attempt to
// lock and if the pattern is invalid, then default to some generic pattern.
// Right now I'm tracking down a Rasdd bug and need to verify the standard
// patterns are valid. This check should be left in for DBG
// case to better check that the drivers initialize correctly.
// [patrickh 4-27-92]
ULONG ulTemp;
for (ulTemp = 0; ulTemp < HS_DDI_MAX; ulTemp++)
{
SURFREF soTemp(ppdev->ahsurf[ulTemp]);
if (!soTemp.bValid())
{
DbgPrint("Index %lu Handle %lx is not valid\n", ulTemp, ppdev->ahsurf[ulTemp]);
}
}
#endif
//
// set the hSpooler first
//
hSpooler(hSpool);
//
// Create a semaphore of the mouse pointer (only for displays)
//
if ( (ppdev->pldev->ldevType & LDEV_DEVICE_DISPLAY) ||
(ppdev->pldev->ldevType & LDEV_META_DEVICE) )
{
//
// Mouse pointer accelerators.
//
if (PPFNVALID(pdo,MovePointer) && PPFNVALID(pdo,SetPointerShape))
{
ppdev->pfnDrvMovePointer =
(PFN_DrvMovePointer) PPFNDRV(pdo,MovePointer);
ppdev->pfnDrvSetPointerShape =
(PFN_DrvSetPointerShape) PPFNDRV(pdo,SetPointerShape);
}
else
{
ASSERTGDI(!(PPFNVALID(pdo,MovePointer)),"Video driver implemented MovePointer but not SetPointerShape");
ppdev->pfnDrvMovePointer = NULL;
ppdev->pfnDrvSetPointerShape = NULL;
}
//
// Init fmPointer
//
SEMOBJ so(gpsemDriverMgmt);
TRACE_INIT(("PDEVREF::PDEVREF: Create pointer semaphore\n"));
if (!NT_SUCCESS(InitializeGreResource(&ppdev->fmPointer)))
{
//
// Disable the halfone
//
bDisableHalftone();
//
// Free the PDEV.
//
VFREEMEM(ppdev);
ppdev = (PDEV *) NULL;
//
// Device should have logged correct error code.
//
WARNING("PDEVREF::PDEVREF Device failed linking pdevs\n");
SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
return;
}
//
// Mark the PDEV as a display.
//
ppdev->fs |= PDEV_DISPLAY | PDEV_POINTER_HIDDEN;
}
//
// Create semaphores so the device can be locked.
//
ppdev->pDevLock = hsemCreate();
ppdev->pfnSync = PPFNDRV(pdo, Synchronize);
ptlPointer((LONG) ppdev->GdiInfo.ulHorzRes/2,(LONG) ppdev->GdiInfo.ulVertRes/2);
//
// we now load font info only when needed. The driver still must have
// setup the default font information.
//
bGotFonts(FALSE);
//
// If any of the LOGFONTs in DEVINFO do not specify a height,
// substitute the default.
//
LONG lHeightDefault = (DEFAULT_POINT_SIZE * ppdev->GdiInfo.ulLogPixelsY) / POINTS_PER_INCH ;
EXTLOGFONTW elfw;
if ( ppdev->devinfo.lfDefaultFont.lfHeight == 0 )
ppdev->devinfo.lfDefaultFont.lfHeight = lHeightDefault;
if ( ppdev->devinfo.lfAnsiVarFont.lfHeight == 0 )
ppdev->devinfo.lfAnsiVarFont.lfHeight = lHeightDefault;
if ( ppdev->devinfo.lfAnsiFixFont.lfHeight == 0 )
ppdev->devinfo.lfAnsiFixFont.lfHeight = lHeightDefault;
//
// Create LFONTs from the LOGFONTs in the DEVINFO.
// the LOGFONTs should become EXTLOGFONTWs
//
vConvertLogFontW(&elfw, &(ppdev->devinfo.lfDefaultFont));
#ifdef FE_SB
// We are doing away with the concept of default device fonts for display
// drivers since it doesnt make sense. Assuming this change gets approved
// I will remove these before SUR ships.
if ( ppdev->GdiInfo.ulTechnology == DT_RASDISPLAY )
ppdev->hlfntDefault = STOCKOBJ_SYSFONT;
else
#endif
if ((ppdev->hlfntDefault
= (HLFONT) hfontCreate(&elfw,
LF_TYPE_DEVICE_DEFAULT,
LF_FLAG_STOCK,
NULL)) == HLFONT_INVALID)
{
ppdev->hlfntDefault = STOCKOBJ_SYSFONT;
}
else
{
//
// Set to public.
//
if (!GreSetLFONTOwner(ppdev->hlfntDefault, OBJECT_OWNER_PUBLIC))
{
//
// If it failed, get rid of the LFONT and resort to System font.
//
bDeleteFont(ppdev->hlfntDefault, TRUE);
ppdev->hlfntDefault = STOCKOBJ_SYSFONT;
}
}
vConvertLogFontW(&elfw, &(ppdev->devinfo.lfAnsiVarFont));
if ((ppdev->hlfntAnsiVariable
= (HLFONT) hfontCreate(&elfw,
LF_TYPE_ANSI_VARIABLE,
LF_FLAG_STOCK,
NULL)) == HLFONT_INVALID)
{
ppdev->hlfntAnsiVariable = STOCKOBJ_SYSFONT;
}
else
{
//
// Set to public.
//
if (!GreSetLFONTOwner(ppdev->hlfntAnsiVariable, OBJECT_OWNER_PUBLIC))
{
//
// If it failed, get rid of the LFONT and resort to System font.
//
bDeleteFont(ppdev->hlfntAnsiVariable, TRUE);
ppdev->hlfntAnsiVariable = STOCKOBJ_SYSFONT;
}
}
vConvertLogFontW(&elfw, &(ppdev->devinfo.lfAnsiFixFont));
if ((ppdev->hlfntAnsiFixed
= (HLFONT) hfontCreate(&elfw,
LF_TYPE_ANSI_FIXED,
LF_FLAG_STOCK,
NULL)) == HLFONT_INVALID)
{
ppdev->hlfntAnsiFixed = STOCKOBJ_SYSFIXEDFONT;
}
else
{
//
// Set to public.
//
if (!GreSetLFONTOwner(ppdev->hlfntAnsiFixed, OBJECT_OWNER_PUBLIC))
{
//
// If it failed, get rid of the LFONT and resort to System Fixed font.
//
bDeleteFont(ppdev->hlfntAnsiFixed, TRUE);
ppdev->hlfntAnsiFixed = STOCKOBJ_SYSFIXEDFONT;
}
}
#ifdef DRIVER_DEBUG
LFONTOBJ lfo1(ppdev->hlfntDefault);
DbgPrint("GRE!PDEVREF(): Device default font\n");
if (lfo1.bValid())
{
lfo1.vDump();
}
DbgPrint("GRE!PDEVREF(): Ansi variable font\n");
LFONTOBJ lfo2(ppdev->hlfntAnsiVariable);
if (lfo2.bValid())
{
lfo2.vDump();
}
DbgPrint("GRE!PDEVREF(): Ansi fixed font\n");
LFONTOBJ lfo3(ppdev->hlfntAnsiFixed);
if (lfo3.bValid())
{
lfo3.vDump();
}
#endif
//
// (see bInitDefaultGuiFont() in stockfnt.cxx)
//
// If we haven't yet computed the adjusted height of the
// DEFAULT_GUI_FONT stock object, do so now. We couldn't do
// this during normal stock font initialization because the
// display driver had not yet been loaded.
//
if ( gbFinishDefGUIFontInit &&
(ppdev->pldev->ldevType & LDEV_DEVICE_DISPLAY) )
{
LFONTOBJ lfo(STOCKOBJ_DEFAULTGUIFONT);
if (lfo.bValid())
lfo.plfw()->lfHeight = -(LONG)((lfo.plfw()->lfHeight * ppdev->GdiInfo.ulLogPixelsY + 36) / 72);
gbFinishDefGUIFontInit = FALSE;
}
}
//
// Initialize the PDEV fields.
//
ppdev->cPdevRefs = 1;
//
// Just stick it at the start of the list.
//
// BUGBUG this list need to be protectted by a semaphore !!!
//
ppdev->ppdevNext = gppdevList;
gppdevList = ppdev;
TRACE_INIT(("PDEVREF::PDEVREF: list of display pdevs %08lx\n", gppdevList));
//
// NOTE after this point, the object will be "permanent" and will
// end up being destroyed by the destructor
//
//
// Add a reference to the ldev for it
//
lr.vReference();
//
// Inform the driver that the PDEV is complete.
//
(*PPFNDRV(pdo,CompletePDEV)) (ppdev->dhpdev,hdev());
//
// We will return with success.
//
return;
}
//
// Free the PDEV.
//
VFREEMEM(ppdev);
ppdev = (PDEV *) NULL;
//
// Device should have logged correct error code.
//
WARNING("PDEVREF::PDEVREF Device failed DrvEnablePDEV\n");
return;
}
/******************************Member*Function*****************************\
* PDEVOBJ::cFonts()
*
* History:
* 3-Feb-1994 -by- Gerrit van Wingerden
* Wrote it.
\**************************************************************************/
ULONG PDEVOBJ::cFonts()
{
ULONG id;
//
// see if the device already told us how many fonts it has
//
if (ppdev->devinfo.cFonts == (ULONG)-1)
{
PDEVOBJ pdo(hdev());
//
// if not query the device to see how many there are
//
if (PPFNDRV(pdo,QueryFont) != NULL)
{
ppdev->devinfo.cFonts = (ULONG)(*PPFNDRV(pdo,QueryFont))(dhpdev(),0,0,&id);
}
else
{
ppdev->devinfo.cFonts = 0;
}
}
return(ppdev->devinfo.cFonts);
}
/******************************Member*Function*****************************\
* PDEVOBJ::bGetDeviceFonts()
*
* History:
* 27-Jul-1992 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL PDEVOBJ::bGetDeviceFonts()
{
ASSERTGDI(!bGotFonts(),"PDEVOBJ::bGetDeviceFonts - already gotten\n");
//
// mark that we have gotten the fonts.
//
bGotFonts(TRUE);
//
// need an ldevobj for calling the device
//
PDEVOBJ pdo(hdev());
//
// compute the number of device fonts
//
cFonts();
//
// If there are any device fonts, load the device fonts into the public PFT table.
//
if (ppdev->devinfo.cFonts)
{
DEVICE_PFTOBJ pfto; // get the device font table
if (!pfto.bLoadFonts(this))
{
WARNING("PDEVOBJ(): couldn't load device fonts\n");
ppdev->devinfo.cFonts = 0;
}
}
return(TRUE);
}
/******************************Member*Function*****************************\
* PDEVREF::~PDEVREF() *
* *
* Removes a reference to the PDEV. Deletes the PDEV if all references are *
* gone. *
* *
* This is the destructor for any PDEVREF. *
* *
\**************************************************************************/
PDEVREF::~PDEVREF()
{
if ((ppdev != (PDEV *) NULL) && !bKeep)
{
vUnreferencePdev();
}
ppdev = (PDEV *) NULL;
}
/******************************Public*Routine******************************\
* vDisableSurface()
*
* Disables the surface for the pdev.
*
\**************************************************************************/
VOID PDEVOBJ::vDisableSurface()
{
TRACE_INIT(("PDEVOBJ::vDisableSurface: ENTERING\n"));
//
// Locate the LDEV.
//
PDEVOBJ pdo(hdev());
//
// Disable the surface. Note we don't have to
// fix up the palette because it doesn't get
// reference counted when put in the palette.
//
if (ppdev->pSurface != NULL)
{
SURFREF su(ppdev->pSurface);
ppdev->pSurface = NULL;
su.vUnreference();
//
// The driver created the surface the driver must delete the surface.
//
(*PPFNDRV(pdo,DisableSurface))(ppdev->dhpdev);
}
TRACE_INIT(("PDEVOBJ::vDisableSurface: LEAVING\n"));
}
/******************************Member*Function*****************************\
* PDEVOBJ::vUnreferencePdev()
*
* Removes a reference to the PDEV. Deletes the PDEV if all references are
* gone.
*
\**************************************************************************/
VOID PDEVOBJ::vUnreferencePdev()
{
HANDLE hSpooler = NULL;
TRACE_INIT(("PDEVOBJ::vCommonDelete: ENTERING\n"));
//
// These brackets are needed because we need to do some cleanup after
// the semaphore is released
//
{
SEMOBJ so(gpsemDriverMgmt);
if (--(ppdev->cPdevRefs) == 0)
{
//
// Unlink the PDEV from the display list.
//
hsemDestroy(ppdev->pDevLock);
if (ppdev->fs & PDEV_DISPLAY)
{
WARNING("PDEVOBJ::vCommonDelete Deleting a display PDEV");
//
// Remove the display locking semaphore
//
DeleteGreResource(&ppdev->fmPointer);
}
//
// BUGBUG we need a lock around the PDEV to do this stuff
//
// Delete it from the list.
//
if (gppdevList == ppdev)
{
gppdevList = ppdev->ppdevNext;
}
else
{
PDEV *pp;
for (pp = gppdevList; pp != NULL; pp = pp->ppdevNext)
{
if (pp->ppdevNext == ppdev)
{
pp->ppdevNext = ppdev->ppdevNext;
break;
}
}
}
//
// Since we are going to delete this PDEV, there shouldn't be any
// active RFONTs lying around for this PDEV.
//
ASSERTGDI(ppdev->prfntActive == NULL,
"gdisrv!vCommonDeleteInvalidPDEVOBJ(): active rfonts on pdev being deleted!\n");
//
// Ordinarily, we would grab the gpsemRFONTList semaphore because
// we are going to access the RFONT list. However, since we're in
// the process of tearing down the PDEV, we don't really need to.
//
//
// Delete all the rfonts on the PDEV.
//
PRFONT prfnt;
while ( (prfnt = ppdev->prfntInactive) != (PRFONT) NULL )
{
RFONTTMPOBJ rflo(prfnt);
PFFOBJ pffo(rflo.pPFF());
ASSERTGDI (
pffo.bValid(),
"gdisrv!vCommonDeletePDEVOBJ(): bad HPFF"
);
rflo.bDeleteRFONT(this, &pffo); // bDelete keeps the list head ptrs updated
}
//
// Destroy the LFONTs.
//
if (ppdev->hlfntDefault != STOCKOBJ_SYSFONT)
bDeleteFont(ppdev->hlfntDefault, TRUE);
if (ppdev->hlfntAnsiVariable != STOCKOBJ_SYSFONT)
bDeleteFont(ppdev->hlfntAnsiVariable, TRUE);
if (ppdev->hlfntAnsiFixed != STOCKOBJ_SYSFIXEDFONT)
bDeleteFont(ppdev->hlfntAnsiFixed, TRUE);
//
// If device fonts exist, remove them
//
if ((ppdev->devinfo.cFonts != 0) && bGotFonts())
{
PFF *pPFF = 0;
PFF **ppPFF;
DEVICE_PFTOBJ pfto;
pPFF = pfto.pPFFGet(hdev(), &ppPFF);
if (!pfto.bUnloadWorkhorse(pPFF, ppPFF, 0))
{
WARNING("vCommonDeletePDEVOBJ(): couldn't unload device fonts\n");
}
}
//
// If a type one font list exists dereference it
//
if(ppdev->TypeOneInfo)
{
PTYPEONEINFO FreeTypeOneInfo;
FreeTypeOneInfo = NULL;
AcquireFastMutex(pgfmMemory);
ppdev->TypeOneInfo->cRef -= 1;
if(!ppdev->TypeOneInfo->cRef)
{
//
// Don't free pool while holding a mutex.
//
FreeTypeOneInfo = ppdev->TypeOneInfo;
}
ReleaseFastMutex(pgfmMemory);
if (FreeTypeOneInfo)
{
VFREEMEM(FreeTypeOneInfo);
}
}
//
// If any remote type one fonts exist free those
//
PREMOTETYPEONENODE RemoteTypeOne = ppdev->RemoteTypeOne;
while(RemoteTypeOne)
{
PVOID Tmp = (PVOID) RemoteTypeOne;
// ulRegionSize and hSecureMem will be stored in the PFM fileview
MmUnsecureVirtualMemory(RemoteTypeOne->fvPFM.hSecureMem);
ZwFreeVirtualMemory(NtCurrentProcess(),
(PVOID*)&(RemoteTypeOne->pDownloadHeader),
&(RemoteTypeOne->fvPFM.ulRegionSize),
MEM_RELEASE);
RemoteTypeOne = RemoteTypeOne->pNext;
VFREEMEM(Tmp);
WARNING1("Freeing Type1\n");
}
//
// Delete the patterns if they are created by the graphics engine on the
// behalf of the driver.
// This is what happends for all display drivers.
//
if (ppdev->fs & PDEV_DISPLAY)
{
for (int iPat = 0; iPat < HS_DDI_MAX; iPat++)
{
bDeleteSurface(ppdev->ahsurf[iPat]);
}
}
//
// Disable the surface for the pdev.
//
vDisableSurface();
//
// Destroy the device halftone info.
//
if (ppdev->pDevHTInfo != NULL)
{
bDisableHalftone();
}
//
// Unreference the palette we used for this PDEV.
//
DEC_SHARE_REF_CNT(ppdev->ppalSurf);
//
// Disable the driver's PDEV.
//
(*PPFNDRV((*this),DisablePDEV))(ppdev->dhpdev);
//
// Delete a reference count for the ldev on which this pdev is
// located.
//
// However, for printers, we artificially want to keep the driver
// loaded even if the ref count goes to zero ...
//
XLDEVOBJ lo(ppdev->pldev);
if ( (!(ppdev->fs & PDEV_PRINTER)) || gbUnloadPrinterDrivers)
{
TRACE_INIT(("PDEVOBJ::vCommonDelete: delete LDEV\n"));
ldevUnloadImage(lo.pldevGet());
}
else
{
//
// Remove the LDEV reference. We unload only extra drivers loaded by
// CreateDC.
//
TRACE_INIT(("PDEVOBJ::vCommonDelete: Dereference LDEV\n"));
lo.vUnreference();
}
TRACE_INIT(("PDEVOBJ::vCommonDelete: Closing Device handle.\n"));
if (ppdev->fs & PDEV_PRINTER)
{
//
// note the spool handle so we can close connection outside
// of the spooler management semaphore
//
hSpooler = ppdev->hSpooler;
}
else
{
//
// For video drivers, we do not manipulate the kernel mode handle
// since USER is managing it.
//
}
//
// If this is a secondary screen device, call USER to tell it the PDEV
// is no longer used
//
if (ppdev->pPhysicalDevice)
{
UserDeleteExclusiveDC(NULL, ppdev->pPhysicalDevice);
}
//
// Free the PDEV.
//
VFREEMEM(ppdev);
}
ppdev = (PDEV *) NULL;
}
//
// this needs to be done outside of the driver management semaphore
//
if (hSpooler)
{
ClosePrinter(hSpooler);
}
TRACE_INIT(("PDEVOBJ::vCommonDelete: SUCCESS\n"));
}
/******************************Member*Function*****************************\
* PDEVOBJ::bDisabled()
*
* Marks a PDEV as enabled or disabled, and modifies all updates the
* cached state in all affected DCs.
*
\**************************************************************************/
BOOL PDEVOBJ::bDisabled
(
BOOL bDisable
)
{
HDEV hdev;
HOBJ hobj;
DC *pdc;
ASSERTGDI(bDisplayPDEV(), "Expected only display devices");
SETFLAG(bDisable, ppdev->fs, PDEV_DISABLED);
hdev = (HDEV) ppdev;
//
// We have to hold the handle manager lock while we traverse all
// the handle manager objects.
//
MLOCKFAST mo;
hobj = 0;
while (pdc = (DC*) HmgSafeNextObjt(hobj, DC_TYPE))
{
hobj = (HOBJ) pdc->hGet();
if ((pdc->dctp() == DCTYPE_DIRECT) &&
(pdc->hdev() == hdev))
{
pdc->bInFullScreen(bDisable);
}
}
return(ppdev->fs & PDEV_DISABLED);
}
/******************************Member*Function*****************************\
* PDEVOBJ::AssertDynaLock()
*
* This routine verifies that appropriate locks are held before accessing
* DC fields that may otherwise be changed asynchronously by the dynamic
* mode-change code.
*
\**************************************************************************/
#if DBG
VOID PDEVOBJ::vAssertDynaLock()
{
//
// One of the following conditions is enough to allow the thread
// to safely access fields that may be modified by the dyanmic
// mode changing:
//
// 1. It's a non-display device -- this will not change modes;
// 2. That the DEVLOCK is held for this object;
// 3. That the DEVLOCK is held for this object's parent;
// 4. That the Palette semaphore is held;
// 5. That the Handle Manager semaphore is held;
// 6. That the Pointer semaphore is held.
//
ASSERTGDI(!bDisplayPDEV() ||
(pDevLock()->OwnerThreads[0].OwnerThread
== (ERESOURCE_THREAD) PsGetCurrentThread()) ||
(ppdev->ppdevParent->pDevLock->OwnerThreads[0].OwnerThread
== (ERESOURCE_THREAD) PsGetCurrentThread()) ||
(gpsemPalette->OwnerThreads[0].OwnerThread
== (ERESOURCE_THREAD) PsGetCurrentThread()) ||
(gResourceHmgr.pResource->OwnerThreads[0].OwnerThread
== (ERESOURCE_THREAD) PsGetCurrentThread()) ||
(pfmPointer()->pResource->OwnerThreads[0].OwnerThread
== (ERESOURCE_THREAD) PsGetCurrentThread()),
"PDEVOBJ: A dynamic mode change lock must be held to access this field");
}
#endif