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.
2293 lines
64 KiB
2293 lines
64 KiB
/*++
|
|
|
|
Copyright (c) 1996-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
enable.c
|
|
|
|
Abstract:
|
|
|
|
Implementation of device and surface related DDI entry points:
|
|
DrvEnableDriver
|
|
DrvDisableDriver
|
|
DrvEnablePDEV
|
|
DrvResetPDEV
|
|
DrvCompletePDEV
|
|
DrvDisablePDEV
|
|
DrvEnableSurface
|
|
DrvDisableSurface
|
|
|
|
Environment:
|
|
|
|
Windows NT Unidrv driver
|
|
|
|
Revision History:
|
|
|
|
10/14/96 -amandan-
|
|
Created
|
|
|
|
03/31/97 -zhanw-
|
|
Added OEM customization support. Hooked out all DDI drawing functions.
|
|
|
|
--*/
|
|
|
|
#include "unidrv.h"
|
|
#pragma hdrstop("unidrv.h")
|
|
|
|
//Comment out this line to disable FTRACE and FVALUE.
|
|
//#define FILETRACE
|
|
#include "unidebug.h"
|
|
|
|
#ifdef WINNT_40
|
|
|
|
DECLARE_CRITICAL_SECTION;
|
|
|
|
//
|
|
// The global link list of ref counts for currently loaded OEM render plugin DLLs
|
|
//
|
|
|
|
extern POEM_PLUGIN_REFCOUNT gpOEMPluginRefCount;
|
|
|
|
#endif // WINNT_40
|
|
|
|
//
|
|
// Our DRVFN table which tells the engine where to find the routines we support.
|
|
//
|
|
|
|
static DRVFN UniDriverFuncs[] = {
|
|
//
|
|
// enable.c
|
|
//
|
|
{ INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV },
|
|
{ INDEX_DrvResetPDEV, (PFN) DrvResetPDEV },
|
|
{ INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV },
|
|
{ INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV },
|
|
{ INDEX_DrvEnableSurface, (PFN) DrvEnableSurface },
|
|
{ INDEX_DrvDisableSurface, (PFN) DrvDisableSurface },
|
|
#ifndef WINNT_40
|
|
{ INDEX_DrvDisableDriver, (PFN)DrvDisableDriver },
|
|
#endif
|
|
//
|
|
// print.c
|
|
//
|
|
{ INDEX_DrvStartDoc, (PFN)DrvStartDoc },
|
|
{ INDEX_DrvStartPage, (PFN)DrvStartPage },
|
|
{ INDEX_DrvSendPage, (PFN)DrvSendPage },
|
|
{ INDEX_DrvEndDoc, (PFN)DrvEndDoc },
|
|
{ INDEX_DrvStartBanding, (PFN)DrvStartBanding },
|
|
{ INDEX_DrvNextBand, (PFN)DrvNextBand },
|
|
//
|
|
// graphics.c
|
|
//
|
|
{ INDEX_DrvPaint, (PFN)DrvPaint }, // new hook
|
|
{ INDEX_DrvBitBlt, (PFN)DrvBitBlt },
|
|
{ INDEX_DrvStretchBlt, (PFN)DrvStretchBlt },
|
|
#ifndef WINNT_40
|
|
{ INDEX_DrvStretchBltROP, (PFN)DrvStretchBltROP }, // new in NT5
|
|
{ INDEX_DrvPlgBlt, (PFN)DrvPlgBlt }, // new in NT5
|
|
#endif
|
|
{ INDEX_DrvCopyBits, (PFN)DrvCopyBits },
|
|
{ INDEX_DrvDitherColor, (PFN)DrvDitherColor },
|
|
{ INDEX_DrvRealizeBrush, (PFN)DrvRealizeBrush }, // in case OEM wants
|
|
{ INDEX_DrvLineTo, (PFN)DrvLineTo }, // new hook
|
|
{ INDEX_DrvStrokePath, (PFN)DrvStrokePath }, // new hook
|
|
{ INDEX_DrvFillPath, (PFN)DrvFillPath }, // new hook
|
|
{ INDEX_DrvStrokeAndFillPath, (PFN)DrvStrokeAndFillPath }, // new hook
|
|
#ifndef WINNT_40
|
|
{ INDEX_DrvGradientFill, (PFN)DrvGradientFill }, // new in NT5
|
|
{ INDEX_DrvAlphaBlend, (PFN)DrvAlphaBlend }, // new in NT5
|
|
{ INDEX_DrvTransparentBlt, (PFN)DrvTransparentBlt }, // new in NT5
|
|
#endif
|
|
//
|
|
// textout.c
|
|
//
|
|
{ INDEX_DrvTextOut, (PFN)DrvTextOut },
|
|
//
|
|
// escape.c
|
|
//
|
|
{ INDEX_DrvEscape, (PFN) DrvEscape },
|
|
//
|
|
// font.c
|
|
//
|
|
{ INDEX_DrvQueryFont, (PFN) DrvQueryFont },
|
|
{ INDEX_DrvQueryFontTree, (PFN) DrvQueryFontTree },
|
|
{ INDEX_DrvQueryFontData, (PFN) DrvQueryFontData },
|
|
{ INDEX_DrvGetGlyphMode, (PFN) DrvGetGlyphMode },
|
|
{ INDEX_DrvFontManagement, (PFN) DrvFontManagement },
|
|
{ INDEX_DrvQueryAdvanceWidths, (PFN) DrvQueryAdvanceWidths },
|
|
};
|
|
|
|
//
|
|
// Unidrv hooks out every drawing DDI to analyze page content for optimization
|
|
//
|
|
#ifndef WINNT_40
|
|
#define HOOK_UNIDRV_FLAGS (HOOK_BITBLT | \
|
|
HOOK_STRETCHBLT | \
|
|
HOOK_PLGBLT | \
|
|
HOOK_TEXTOUT | \
|
|
HOOK_PAINT | \
|
|
HOOK_STROKEPATH | \
|
|
HOOK_FILLPATH | \
|
|
HOOK_STROKEANDFILLPATH | \
|
|
HOOK_LINETO | \
|
|
HOOK_COPYBITS | \
|
|
HOOK_STRETCHBLTROP | \
|
|
HOOK_TRANSPARENTBLT | \
|
|
HOOK_ALPHABLEND | \
|
|
HOOK_GRADIENTFILL)
|
|
#else
|
|
#define HOOK_UNIDRV_FLAGS (HOOK_BITBLT | \
|
|
HOOK_STRETCHBLT | \
|
|
HOOK_TEXTOUT | \
|
|
HOOK_PAINT | \
|
|
HOOK_STROKEPATH | \
|
|
HOOK_FILLPATH | \
|
|
HOOK_STROKEANDFILLPATH | \
|
|
HOOK_LINETO | \
|
|
HOOK_COPYBITS)
|
|
#endif
|
|
|
|
//
|
|
// Unidrv driver memory pool tag, required by common library headers
|
|
//
|
|
|
|
DWORD gdwDrvMemPoolTag = '5nuD';
|
|
|
|
#if ENABLE_STOCKGLYPHSET
|
|
//
|
|
// Stock glyphset data
|
|
//
|
|
|
|
FD_GLYPHSET *pStockGlyphSet[MAX_STOCK_GLYPHSET];
|
|
HSEMAPHORE hGlyphSetSem = NULL;
|
|
|
|
VOID FreeGlyphSet(VOID);
|
|
|
|
#endif //ENABLE_STOCKGLYPHSET
|
|
|
|
|
|
#ifdef WINNT_40 //NT 4.0
|
|
|
|
HSEMAPHORE hSemBrushColor = NULL;
|
|
|
|
#endif //WINNT_40
|
|
|
|
|
|
//
|
|
// Forward declarations
|
|
//
|
|
|
|
PPDEV PAllocPDEVData(HANDLE);
|
|
VOID VFreePDEVData( PDEV *);
|
|
VOID VDisableSurface(PDEV *);
|
|
BPaperSizeSourceSame(PDEV * , PDEV *);
|
|
HSURF HCreateDeviceSurface(PDEV *, INT);
|
|
HBITMAP HCreateBitmapSurface(PDEV *, INT);
|
|
|
|
|
|
HINSTANCE ghInstance;
|
|
|
|
|
|
BOOL WINAPI
|
|
DllMain(
|
|
HANDLE hModule,
|
|
ULONG ulReason,
|
|
PCONTEXT pContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
DLL initialization procedure.
|
|
|
|
Arguments:
|
|
|
|
hModule - DLL instance handle
|
|
ulReason - Reason for the call
|
|
pContext - Pointer to context (not used by us)
|
|
|
|
Return Value:
|
|
|
|
TRUE if DLL is initialized successfully, FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (ulReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
ghInstance = hModule;
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
DrvQueryDriverInfo(
|
|
DWORD dwMode,
|
|
PVOID pBuffer,
|
|
DWORD cbBuf,
|
|
PDWORD pcbNeeded
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Query driver information
|
|
|
|
Arguments:
|
|
|
|
dwMode - Specify the information being queried
|
|
pBuffer - Points to output buffer
|
|
cbBuf - Size of output buffer in bytes
|
|
pcbNeeded - Return the expected size of output buffer
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (dwMode)
|
|
{
|
|
#ifndef WINNT_40
|
|
case DRVQUERY_USERMODE:
|
|
|
|
ASSERT(pcbNeeded != NULL);
|
|
*pcbNeeded = sizeof(DWORD);
|
|
|
|
if (pBuffer == NULL || cbBuf < sizeof(DWORD))
|
|
{
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
return FALSE;
|
|
}
|
|
|
|
*((PDWORD) pBuffer) = TRUE;
|
|
return TRUE;
|
|
#endif
|
|
|
|
default:
|
|
|
|
ERR(("Unknown dwMode in DrvQueryDriverInfo: %d\n", dwMode));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
DrvEnableDriver(
|
|
ULONG iEngineVersion,
|
|
ULONG cb,
|
|
PDRVENABLEDATA pDrvEnableData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvEnableDriver.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
iEngineVersion - Specifies the DDI version number that GDI is written for
|
|
cb - Size of the buffer pointed to by pDrvEnableData
|
|
pDrvEnableData - Points to an DRVENABLEDATA structure
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
VERBOSE(("Entering DrvEnableDriver...\n"));
|
|
|
|
//
|
|
// Make sure we have a valid engine version and
|
|
// we're given enough room for the DRVENABLEDATA.
|
|
//
|
|
|
|
if (iEngineVersion < DDI_DRIVER_VERSION_NT4 || cb < sizeof(DRVENABLEDATA))
|
|
{
|
|
ERR(("DrvEnableDriver failed\n"));
|
|
SetLastError(ERROR_BAD_DRIVER_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Fill in the DRVENABLEDATA structure for the engine.
|
|
//
|
|
|
|
pDrvEnableData->iDriverVersion = DDI_DRIVER_VERSION_NT4;
|
|
pDrvEnableData->c = sizeof(UniDriverFuncs) / sizeof(DRVFN);
|
|
pDrvEnableData->pdrvfn = UniDriverFuncs;
|
|
|
|
#ifdef WINNT_40 // NT 4.0
|
|
|
|
INIT_CRITICAL_SECTION();
|
|
if (!IS_VALID_DRIVER_SEMAPHORE())
|
|
{
|
|
ERR(("Failed to initialize semaphore.\n"));
|
|
SetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
|
return FALSE;
|
|
}
|
|
|
|
ENTER_CRITICAL_SECTION();
|
|
|
|
gpOEMPluginRefCount = NULL;
|
|
|
|
LEAVE_CRITICAL_SECTION();
|
|
|
|
if (!(hSemBrushColor = EngCreateSemaphore()))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
#endif //WINNT_40
|
|
|
|
#if ENABLE_STOCKGLYPHSET
|
|
|
|
//
|
|
// Initialize stock glyphset data
|
|
//
|
|
|
|
if (!(hGlyphSetSem = EngCreateSemaphore()))
|
|
{
|
|
ERR(("DrvEnableDriver: EngCreateSemaphore failed.\n"));
|
|
SetLastError(ERROR_BAD_DRIVER_LEVEL);
|
|
return FALSE;
|
|
}
|
|
EngAcquireSemaphore(hGlyphSetSem);
|
|
ZeroMemory(pStockGlyphSet, MAX_STOCK_GLYPHSET * sizeof(FD_GLYPHSET*));
|
|
EngReleaseSemaphore(hGlyphSetSem);
|
|
|
|
#endif //ENABLE_STOCKGLYPHSET
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
DHPDEV
|
|
DrvEnablePDEV(
|
|
PDEVMODE pdm,
|
|
PWSTR pLogAddress,
|
|
ULONG cPatterns,
|
|
HSURF *phsurfPatterns,
|
|
ULONG cjGdiInfo,
|
|
ULONG *pGdiInfo,
|
|
ULONG cjDevInfo,
|
|
DEVINFO *pDevInfo,
|
|
HDEV hdev,
|
|
PWSTR pDeviceName,
|
|
HANDLE hPrinter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvEnablePDEV.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
pdm - Points to a DEVMODEW structure that contains driver data
|
|
pLogAddress - Points to the logical address string
|
|
cPatterns - Specifies the number of standard patterns
|
|
phsurfPatterns - Buffer to hold surface handles to standard patterns
|
|
cjGdiInfo - Size of GDIINFO buffer
|
|
pGdiInfo - Points to a GDIINFO structure
|
|
cjDevInfo - Size of DEVINFO buffer
|
|
pDevInfo - Points to a DEVINFO structure
|
|
hdev - GDI device handle
|
|
pDeviceName - Points to device name string
|
|
hPrinter - Spooler printer handle
|
|
|
|
Return Value:
|
|
|
|
Driver device handle, NULL if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PDEV *pPDev;
|
|
RECTL rcFormImageArea;
|
|
DRVENABLEDATA ded; // for OEM customization support
|
|
PDEVOEM pdevOem;
|
|
PFN_OEMEnablePDEV pfnOEMEnablePDEV;
|
|
|
|
VERBOSE(("Entering DrvEnablePDEV...\n"));
|
|
|
|
ZeroMemory(phsurfPatterns, sizeof(HSURF) * cPatterns);
|
|
|
|
//
|
|
// Allocate PDEV,
|
|
// Initializes binary data,
|
|
// Get default binary data snapshot,
|
|
//
|
|
|
|
if (! (pPDev = PAllocPDEVData(hPrinter)) ||
|
|
! (pPDev->pDriverInfo3 = MyGetPrinterDriver(hPrinter, hdev, 3)) ||
|
|
! (pPDev->pRawData = LoadRawBinaryData(pPDev->pDriverInfo3->pDataFile)) ||
|
|
! (pPDev->pDriverInfo = PGetDefaultDriverInfo(hPrinter, pPDev->pRawData) ) ||
|
|
! (pPDev->pInfoHeader = pPDev->pDriverInfo->pInfoHeader) ||
|
|
! (pPDev->pUIInfo = OFFSET_TO_POINTER(pPDev->pInfoHeader, pPDev->pInfoHeader->loUIInfoOffset)) )
|
|
{
|
|
ERR(("DrvEnablePDEV failed: %d\n", GetLastError()));
|
|
|
|
VFreePDEVData(pPDev);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Must load OEM dll's before setting devmode
|
|
//
|
|
|
|
if( ! BLoadAndInitOemPlugins(pPDev) ||
|
|
! BInitWinResData(&pPDev->WinResData, pPDev->pDriverInfo3->pDriverPath, pPDev->pUIInfo) ||
|
|
! (pPDev->pOptionsArray = MemAllocZ(MAX_PRINTER_OPTIONS * sizeof(OPTSELECT))))
|
|
|
|
{
|
|
ERR(("DrvEnablePDEV failed: %d\n", GetLastError()));
|
|
|
|
VFreePDEVData(pPDev);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Since output is expected to follow this call, allocate storage
|
|
// for the output buffer. This used to be statically allocated
|
|
// within UNIDRV's PDEV, but now we can save that space for INFO
|
|
// type DCs.
|
|
//
|
|
// Not! according to Bug 150881 StartDoc and EndDoc
|
|
// are optional calls, but pbOBuf is required.
|
|
//
|
|
|
|
if( !(pPDev->pbOBuf = MemAllocZ( CCHSPOOL )) )
|
|
{
|
|
ERR(("DrvEnablePDEV failed: %d\n", GetLastError()));
|
|
|
|
VFreePDEVData(pPDev);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Use the default binary data to validate input devmode
|
|
// and merges with the system, devmode.
|
|
// Get printer properties.
|
|
// and loads minidriver resource data
|
|
//
|
|
|
|
if (! BGetPrinterProperties(pPDev->devobj.hPrinter, pPDev->pRawData, &pPDev->PrinterData) ||
|
|
! BMergeAndValidateDevmode(pPDev, pdm, &rcFormImageArea))
|
|
{
|
|
ERR(("DrvEnablePDEV failed: %d\n", GetLastError()));
|
|
|
|
VFreePDEVData(pPDev);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// get updated binary snapshot with the validated/merged devmode
|
|
//
|
|
|
|
if (! (pPDev->pDriverInfo = PGetUpdateDriverInfo (
|
|
pPDev,
|
|
hPrinter,
|
|
pPDev->pInfoHeader,
|
|
pPDev->pOptionsArray,
|
|
pPDev->pRawData,
|
|
MAX_PRINTER_OPTIONS,
|
|
pPDev->pdm,
|
|
&pPDev->PrinterData)))
|
|
{
|
|
ERR(("PGetUpdateDriverInfo failed: %d\n", GetLastError()));
|
|
pPDev->pInfoHeader = NULL ; // deleted by PGetUpdateDriverInfo
|
|
// better fix is to pass a pointer to pPDev->pInfoHeader so PGetUpdateDriverInfo
|
|
// can update the pointer immediately.
|
|
VFreePDEVData(pPDev);
|
|
return NULL;
|
|
}
|
|
|
|
if(! (pPDev->pInfoHeader = pPDev->pDriverInfo->pInfoHeader) ||
|
|
! (pPDev->pUIInfo = OFFSET_TO_POINTER(pPDev->pInfoHeader, pPDev->pInfoHeader->loUIInfoOffset)) )
|
|
|
|
{
|
|
ERR(("DrvEnablePDEV failed: %d\n", GetLastError()));
|
|
VFreePDEVData(pPDev);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// pPDev->pUIInfo is reset so update the winresdata pUIInfo also.
|
|
//
|
|
pPDev->WinResData.pUIInfo = pPDev->pUIInfo;
|
|
|
|
//
|
|
// Initialize the rest of PDEV and GDIINFO, DEVINFO and
|
|
// call the Font, Raster modules to
|
|
// initialize their parts of the PDEVICE, GDIINFO and DEVINFO
|
|
// Palette initialization is done by control module.
|
|
//
|
|
|
|
//
|
|
// This is necessary to initialize for FMInit.
|
|
//
|
|
|
|
pPDev->devobj.hEngine = hdev;
|
|
pPDev->fHooks = HOOK_UNIDRV_FLAGS;
|
|
|
|
if (! BInitPDEV(pPDev, &rcFormImageArea ) ||
|
|
! BInitGdiInfo(pPDev, pGdiInfo, cjGdiInfo) ||
|
|
! BInitDevInfo(pPDev, pDevInfo, cjDevInfo) ||
|
|
! VMInit(pPDev, pDevInfo, (PGDIINFO)pGdiInfo) ||
|
|
! RMInit(pPDev, pDevInfo, (PGDIINFO)pGdiInfo) ||
|
|
! BInitPalDevInfo(pPDev, pDevInfo, (PGDIINFO)pGdiInfo) ||
|
|
! FMInit(pPDev, pDevInfo, (PGDIINFO)pGdiInfo))
|
|
{
|
|
ERR(("DrvEnablePDEV failed: %d\n", GetLastError()));
|
|
|
|
VFreePDEVData(pPDev);
|
|
return NULL;
|
|
}
|
|
|
|
FTRACE(Tracing Palette);
|
|
FVALUE((pDevInfo->flGraphicsCaps & GCAPS_ARBRUSHTEXT), 0x%x);
|
|
|
|
|
|
ded.iDriverVersion = PRINTER_OEMINTF_VERSION;
|
|
ded.c = sizeof(UniDriverFuncs) / sizeof(DRVFN);
|
|
ded.pdrvfn = (DRVFN*) UniDriverFuncs;
|
|
|
|
//
|
|
// Call EnablePDEV for the vector plugins.
|
|
// Put the return value in (((PDEVOBJ)pPDev)->pdevOEM)
|
|
//
|
|
|
|
HANDLE_VECTORPROCS_RET(pPDev, VMEnablePDEV, (pPDev)->pVectorPDEV,
|
|
((PDEVOBJ) pPDev,
|
|
pDeviceName,
|
|
cPatterns,
|
|
phsurfPatterns,
|
|
cjGdiInfo,
|
|
(GDIINFO *)pGdiInfo,
|
|
cjDevInfo,
|
|
(DEVINFO *)pDevInfo,
|
|
&ded) ) ;
|
|
|
|
//
|
|
// If there is present a vector module and it exports EnablePDEV
|
|
// but its EnablePDEV has failed, then we cannot continue.
|
|
//
|
|
if ( pPDev->pVectorProcs &&
|
|
( (PVMPROCS)(pPDev->pVectorProcs) )->VMEnablePDEV &&
|
|
!(pPDev->pVectorPDEV)
|
|
)
|
|
{
|
|
ERR(("Vector Module's EnablePDEV failed \n"));
|
|
VFreePDEVData(pPDev);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Call OEMEnablePDEV entrypoint for each OEM dll
|
|
//
|
|
START_OEMENTRYPOINT_LOOP(pPDev)
|
|
|
|
if (pOemEntry->pIntfOem != NULL)
|
|
{
|
|
if (HComOEMEnablePDEV(pOemEntry,
|
|
(PDEVOBJ)pPDev,
|
|
pDeviceName,
|
|
cPatterns,
|
|
phsurfPatterns,
|
|
cjGdiInfo,
|
|
(GDIINFO *) pGdiInfo,
|
|
cjDevInfo,
|
|
(DEVINFO *) pDevInfo,
|
|
&ded,
|
|
&pOemEntry->pParam) == E_NOTIMPL)
|
|
continue;
|
|
|
|
}
|
|
else
|
|
{
|
|
if ((pfnOEMEnablePDEV = GET_OEM_ENTRYPOINT(pOemEntry, OEMEnablePDEV)))
|
|
{
|
|
pOemEntry->pParam = pfnOEMEnablePDEV(
|
|
(PDEVOBJ) pPDev,
|
|
pDeviceName,
|
|
cPatterns,
|
|
phsurfPatterns,
|
|
cjGdiInfo,
|
|
(GDIINFO *) pGdiInfo,
|
|
cjDevInfo,
|
|
(DEVINFO *) pDevInfo,
|
|
&ded);
|
|
|
|
}
|
|
else
|
|
continue;
|
|
|
|
}
|
|
|
|
if (pOemEntry->pParam == NULL)
|
|
{
|
|
ERR(("OEMEnablePDEV failed for '%ws': %d\n",
|
|
pOemEntry->ptstrDriverFile,
|
|
GetLastError()));
|
|
|
|
VFreePDEVData(pPDev);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Add support for OEM's 8bpp multi-level color
|
|
//
|
|
if (((GDIINFO *)pGdiInfo)->ulHTOutputFormat == HT_FORMAT_8BPP &&
|
|
((GDIINFO *)pGdiInfo)->flHTFlags & HT_FLAG_8BPP_CMY332_MASK &&
|
|
((GDIINFO *)pGdiInfo)->flHTFlags & HT_FLAG_USE_8BPP_BITMASK)
|
|
{
|
|
VInitPal8BPPMaskMode(pPDev,(GDIINFO *)pGdiInfo);
|
|
}
|
|
pOemEntry->dwFlags |= OEMENABLEPDEV_CALLED;
|
|
|
|
#if 0
|
|
//
|
|
// in the extremely simple case, OEM dll may not need to create
|
|
// a PDEV at all.
|
|
//
|
|
|
|
else // OEMEnablePDEV is not exported. Error!
|
|
{
|
|
ERR(("OEMEnablePDEV is not exported for '%ws'\n",
|
|
pOemEntry->ptstrDriverFile));
|
|
|
|
VFreePDEVData(pPDev);
|
|
return NULL;
|
|
|
|
}
|
|
|
|
//
|
|
// for every OEM DLL, OEMDisablePDEV is also a required export.
|
|
//
|
|
if (!GET_OEM_ENTRYPOINT(pOemEntry, OEMDisablePDEV))
|
|
{
|
|
ERR(("OEMDisablePDEV is not exported for '%ws'\n",
|
|
pOemEntry->ptstrDriverFile));
|
|
|
|
VFreePDEVData(pPDev);
|
|
return NULL;
|
|
|
|
}
|
|
#endif
|
|
|
|
END_OEMENTRYPOINT_LOOP
|
|
|
|
|
|
//
|
|
// Unload and free binary data allocated by the parser.
|
|
// Will need to reload at DrvEnableSurface
|
|
//
|
|
|
|
VUnloadFreeBinaryData(pPDev);
|
|
|
|
return (DHPDEV) pPDev;
|
|
}
|
|
|
|
|
|
BOOL
|
|
DrvResetPDEV(
|
|
DHPDEV dhpdevOld,
|
|
DHPDEV dhpdevNew
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvResetPDEV.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
phpdevOld - Driver handle to the old device
|
|
phpdevNew - Driver handle to the new device
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PPDEV pPDevOld, pPDevNew;
|
|
PFN_OEMResetPDEV pfnOEMResetPDEV;
|
|
POEM_PLUGIN_ENTRY pOemEntryOld;
|
|
BOOL bResult = TRUE;
|
|
|
|
VERBOSE(("Entering DrvResetPDEV...\n"));
|
|
|
|
pPDevOld = (PDEV *) dhpdevOld;
|
|
pPDevNew = (PDEV *) dhpdevNew;
|
|
|
|
ASSERT_VALID_PDEV(pPDevOld);
|
|
ASSERT_VALID_PDEV(pPDevNew);
|
|
|
|
//
|
|
// Carry relevant information from old pdev to new pdev
|
|
// BUG_BUG, what other information should we carry over here ?
|
|
//
|
|
|
|
//
|
|
// Set the PF_SEND_ONLY_NOEJECT_CMDS flag if the only
|
|
// thing that changed between the old and new devmode
|
|
// require only commands that do not cause a page ejection.
|
|
//
|
|
|
|
//
|
|
// Don't need to resend the page initialization iff
|
|
// The Document has started printing AND
|
|
// The device support DUPLEX AND
|
|
// The Duplex option selected is DM_DUPLEX AND
|
|
// The previous duplex option matches the current duplex option AND
|
|
// The Paper Size, Paper Source , and Orientation is the same
|
|
// Due to unloading of rawbinary data and snapshot, pPDevNew->pDuplex
|
|
// and other related fields are null at this time. must use devmode.
|
|
//
|
|
|
|
|
|
|
|
if( (pPDevOld->fMode & PF_DOCSTARTED) &&
|
|
(pPDevNew->pdm->dmFields & DM_DUPLEX) &&
|
|
(pPDevOld->pdm->dmFields & DM_DUPLEX) &&
|
|
(pPDevNew->pdm->dmDuplex != DMDUP_SIMPLEX) &&
|
|
(pPDevNew->pdm->dmDuplex == pPDevOld->pdm->dmDuplex) )
|
|
{
|
|
BOOL bUseNoEjectSubset = TRUE ;
|
|
COMMAND *pSeqCmd;
|
|
DWORD dwCmdIndex ;
|
|
|
|
if (!BPaperSizeSourceSame(pPDevNew,pPDevOld))
|
|
bUseNoEjectSubset = FALSE ;
|
|
|
|
//
|
|
// if orientation command is not NO_PageEject
|
|
//
|
|
if( bUseNoEjectSubset &&
|
|
(pPDevNew->pdm->dmFields & DM_ORIENTATION) &&
|
|
(pPDevOld->pdm->dmFields & DM_ORIENTATION) &&
|
|
(pPDevNew->pdm->dmOrientation != pPDevOld->pdm->dmOrientation) &&
|
|
pPDevOld->pOrientation &&
|
|
((dwCmdIndex = pPDevOld->pOrientation->GenericOption.dwCmdIndex) != UNUSED_ITEM) &&
|
|
(pSeqCmd = INDEXTOCOMMANDPTR(pPDevOld->pDriverInfo, dwCmdIndex)) &&
|
|
!(pSeqCmd->bNoPageEject))
|
|
bUseNoEjectSubset = FALSE ;
|
|
|
|
//
|
|
// if colormode command is not NO_PageEject
|
|
//
|
|
if( bUseNoEjectSubset &&
|
|
(pPDevNew->pdm->dmFields & DM_COLOR) &&
|
|
(pPDevOld->pdm->dmFields & DM_COLOR) &&
|
|
(pPDevNew->pdm->dmColor != pPDevOld->pdm->dmColor) &&
|
|
pPDevOld->pColorMode &&
|
|
((dwCmdIndex = pPDevOld->pColorMode->GenericOption.dwCmdIndex) != UNUSED_ITEM) &&
|
|
(pSeqCmd = INDEXTOCOMMANDPTR(pPDevOld->pDriverInfo, dwCmdIndex)) &&
|
|
!(pSeqCmd->bNoPageEject))
|
|
bUseNoEjectSubset = FALSE ;
|
|
|
|
//check all other doc properties if you want:
|
|
if(bUseNoEjectSubset)
|
|
pPDevNew->fMode |= PF_SEND_ONLY_NOEJECT_CMDS;
|
|
}
|
|
|
|
//
|
|
// if Job commands already sent, don't send them again.
|
|
//
|
|
if( pPDevOld->fMode & PF_JOB_SENT)
|
|
pPDevNew->fMode |= PF_JOB_SENT;
|
|
|
|
//
|
|
// if Doc commands already sent, don't send them again.
|
|
//
|
|
if( pPDevOld->fMode & PF_DOC_SENT)
|
|
pPDevNew->fMode |= PF_DOC_SENT;
|
|
|
|
pPDevNew->dwPageNumber = pPDevOld->dwPageNumber ;
|
|
// preserve pageNumber across ResetDC.
|
|
|
|
//
|
|
// Call Raster and Font module to carry over their stuff from old
|
|
// pPDev to new pPDev
|
|
//
|
|
|
|
if (!(((PRMPROCS)(pPDevNew->pRasterProcs))->RMResetPDEV(pPDevOld, pPDevNew)) ||
|
|
!(((PFMPROCS)(pPDevNew->pFontProcs))->FMResetPDEV(pPDevOld, pPDevNew)))
|
|
{
|
|
bResult = FALSE;
|
|
}
|
|
|
|
//
|
|
// Also call the vector module.
|
|
//
|
|
if ( pPDevOld->pVectorProcs )
|
|
{
|
|
pPDevOld->devobj.pdevOEM = pPDevOld->pVectorPDEV;
|
|
HANDLE_VECTORPROCS_RET( pPDevNew, VMResetPDEV, bResult,
|
|
((PDEVOBJ) pPDevOld,
|
|
(PDEVOBJ) pPDevNew ) ) ;
|
|
}
|
|
|
|
//
|
|
// Call OEMResetPDEV entrypoint
|
|
//
|
|
|
|
ASSERT(pPDevNew->pOemPlugins);
|
|
ASSERT(pPDevOld->pOemPlugins);
|
|
|
|
START_OEMENTRYPOINT_LOOP(pPDevNew)
|
|
|
|
pOemEntryOld = PFindOemPluginWithSignature(pPDevOld->pOemPlugins,
|
|
pOemEntry->dwSignature);
|
|
|
|
if (pOemEntryOld != NULL)
|
|
{
|
|
pPDevOld->devobj.pdevOEM = pOemEntryOld->pParam;
|
|
pPDevOld->devobj.pOEMDM = pOemEntryOld->pOEMDM;
|
|
|
|
if (pOemEntry->pIntfOem != NULL)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = HComOEMResetPDEV(pOemEntry,
|
|
(PDEVOBJ)pPDevOld,
|
|
(PDEVOBJ)pPDevNew);
|
|
|
|
if (hr == E_NOTIMPL)
|
|
continue;
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
ERR(("OEMResetPDEV failed for '%ws': %d\n",
|
|
pOemEntry->ptstrDriverFile,
|
|
GetLastError()));
|
|
|
|
bResult = FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (!(pfnOEMResetPDEV = GET_OEM_ENTRYPOINT(pOemEntry, OEMResetPDEV)))
|
|
continue;
|
|
|
|
if (! pfnOEMResetPDEV((PDEVOBJ) pPDevOld, (PDEVOBJ) pPDevNew))
|
|
{
|
|
ERR(("OEMResetPDEV failed for '%ws': %d\n",
|
|
pOemEntry->ptstrDriverFile,
|
|
GetLastError()));
|
|
|
|
bResult = FALSE;
|
|
}
|
|
}
|
|
}
|
|
END_OEMENTRYPOINT_LOOP
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
HSURF
|
|
DrvEnableSurface(
|
|
DHPDEV dhpdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvEnableSurface.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
dhpdev - Driver device handle
|
|
|
|
Return Value:
|
|
|
|
Handle to newly created surface, NULL if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HSURF hSurface; // Handle to the surface
|
|
HBITMAP hBitmap; // The bitmap handle
|
|
// SIZEL szSurface; // Device surface size
|
|
INT iFormat; // Bitmap format
|
|
ULONG cbScan; // Scan line byte length (DWORD aligned)
|
|
int iBPP; // Bits per pel, as # of bits
|
|
int iPins; // Basic rounding factor for banding size
|
|
PDEV *pPDev = (PDEV*)dhpdev;
|
|
DWORD dwNumBands; // Number of bands to use
|
|
|
|
PFN_OEMDriverDMS pfnOEMDriverDMS;
|
|
DWORD dwHooks = 0, dwHooksSize = 0; // used to query what kind of surface should be created
|
|
POEM_PLUGINS pOemPlugins; // OEM Plugin Module
|
|
PTSTR ptstrDllName;
|
|
|
|
DEVOBJ DevObj;
|
|
BOOL bReturn = FALSE;
|
|
|
|
VERBOSE(("Entering DrvEnableSurface...\n"));
|
|
|
|
//
|
|
// Reloads the binary data and reinit the offsets and pointers
|
|
// to binary data
|
|
//
|
|
|
|
if (!BReloadBinaryData(pPDev))
|
|
return NULL;
|
|
|
|
//
|
|
// BUG_BUG, Need to put test code here to force banding for testing purposes
|
|
//
|
|
|
|
// szSurface.cx = pPDev->sf.szImageAreaG.cx;
|
|
// szSurface.cy = pPDev->sf.szImageAreaG.cy;
|
|
|
|
iBPP = pPDev->sBitsPixel;
|
|
|
|
switch (pPDev->sBitsPixel)
|
|
{
|
|
case 1:
|
|
iFormat = BMF_1BPP;
|
|
break;
|
|
case 4:
|
|
iFormat = BMF_4BPP;
|
|
break;
|
|
case 8:
|
|
iFormat = BMF_8BPP;
|
|
break;
|
|
case 24:
|
|
iFormat = BMF_24BPP;
|
|
break;
|
|
default:
|
|
ERR(("Unknown sBitsPixels in DrvEnableSurface"));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Time to allocate surface bitmap
|
|
DevObj = pPDev->devobj;
|
|
//
|
|
|
|
//
|
|
// First call Vector pseudo-plugin
|
|
//
|
|
HANDLE_VECTORPROCS_RET( pPDev, VMDriverDMS, bReturn,
|
|
((PDEVOBJ) pPDev,
|
|
&dwHooks,
|
|
sizeof(DWORD),
|
|
&dwHooksSize) ) ;
|
|
{
|
|
if ( bReturn && dwHooks)
|
|
pPDev->fMode |= PF_DEVICE_MANAGED;
|
|
else
|
|
pPDev->fMode &= ~PF_DEVICE_MANAGED;
|
|
}
|
|
|
|
|
|
|
|
// Call OEMGetInfo to find out if the Oem wants to create
|
|
// a bitmap surface or a device surface
|
|
pOemPlugins = pPDev->pOemPlugins;
|
|
if (pOemPlugins->dwCount > 0)
|
|
{
|
|
//
|
|
// Before the HANDLE_VECTORPROCS_RET was placed above, it made sense to initialize
|
|
// dwHooks. But now we dont want to reinitialize it.
|
|
//
|
|
// dwHooks = 0;
|
|
dwHooksSize = 0;
|
|
START_OEMENTRYPOINT_LOOP(pPDev)
|
|
|
|
VERBOSE(("Getting the OEMDriverDMS address\n"));
|
|
|
|
if (pOemEntry->pIntfOem != NULL)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = HComDriverDMS(pOemEntry,
|
|
(PDEVOBJ)pPDev,
|
|
&dwHooks,
|
|
sizeof(DWORD),
|
|
&dwHooksSize);
|
|
//
|
|
// We need to explicitly check for E_NOTIMPL. SUCCEEDED macro
|
|
// will fail for this error.
|
|
//
|
|
if (hr == E_NOTIMPL)
|
|
continue;
|
|
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
WARNING(("OEMDriverDMS returned FALSE '%ws': ErrorCode = %d\n",
|
|
pOemEntry->ptstrDriverFile,
|
|
GetLastError()));
|
|
dwHooks = 0;
|
|
|
|
}
|
|
if (dwHooks)
|
|
pPDev->fMode |= PF_DEVICE_MANAGED;
|
|
else
|
|
pPDev->fMode &= ~PF_DEVICE_MANAGED;
|
|
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
if ((pfnOEMDriverDMS = GET_OEM_ENTRYPOINT(pOemEntry, OEMDriverDMS)))
|
|
{
|
|
bReturn = pfnOEMDriverDMS((PDEVOBJ)pPDev,
|
|
&dwHooks,
|
|
sizeof(DWORD),
|
|
&dwHooksSize);
|
|
|
|
if (bReturn == FALSE)
|
|
{
|
|
WARNING(("OEMDriverDMS returned FALSE '%ws': ErrorCode = %d\n",
|
|
pOemEntry->ptstrDriverFile,
|
|
GetLastError()));
|
|
dwHooks = 0;
|
|
|
|
}
|
|
if (dwHooks)
|
|
pPDev->fMode |= PF_DEVICE_MANAGED;
|
|
else
|
|
pPDev->fMode &= ~PF_DEVICE_MANAGED;
|
|
}
|
|
}
|
|
|
|
|
|
END_OEMENTRYPOINT_LOOP
|
|
}
|
|
|
|
|
|
//
|
|
// If the OEM Plugin Module wants a device managed surface
|
|
// (from OEMGetInfo) - then create it.
|
|
// Otherwise a bitmap surface is created. Note: Banding must be
|
|
// turned off for a device surface.
|
|
//
|
|
if (DRIVER_DEVICEMANAGED (pPDev)) // device surface
|
|
{
|
|
VERBOSE(("DrvEnableSurface: creating a DEVICE surface.\n"));
|
|
|
|
//
|
|
// Hack for monochrome HPGL2 pseudo-plugin driver.
|
|
// The gpd indicates the driver is monochrome, but the plugin wants the
|
|
// driver surface to be 24bpp color. Even though the rendering is done in monochrome,
|
|
// but the plugin wants GDI to send it all color information. So it wants destination
|
|
// surface to be declared color surface. Putting color information in gpd, though simple,
|
|
// breaks backward compatibility (e.g. if new gpd is used with old unidrv). Therefore
|
|
// this hack. If the personality in gpd is hpgl2 and the VectorProc structure is
|
|
// initialized (which means that Graphics Mode has been chosen as HP-GL/2 from the UI),
|
|
// then we assume we are printing to monochrome HPGL printer.
|
|
// Therefore for plugin's happiness we create the device managed surface
|
|
// as 24bpp.
|
|
// Question: This creates a wierd situation, where the surface is color, but
|
|
// unidrv thinks it is monochrome and creates palette accordingly.
|
|
// Answer: Since all the rendering is done by the plugin and unidrv is not used,
|
|
// I think we should be ok.
|
|
//
|
|
if ((pPDev->ePersonality == kHPGL2 ||
|
|
pPDev->ePersonality == kPCLXL ) &&
|
|
pPDev->pVectorProcs != NULL &&
|
|
iFormat == BMF_1BPP)
|
|
{
|
|
hSurface = HCreateDeviceSurface (pPDev, BMF_24BPP);
|
|
}
|
|
else
|
|
{
|
|
hSurface = HCreateDeviceSurface (pPDev, iFormat);
|
|
}
|
|
|
|
// if we can't create the surface fail the call.
|
|
|
|
if (!hSurface)
|
|
{
|
|
ERR(("Unidrv!DrvEnableSurface:HCreateBitmapSurface Failed"));
|
|
VDisableSurface( pPDev );
|
|
return NULL;
|
|
}
|
|
|
|
pPDev->hSurface = hSurface;
|
|
pPDev->hbm = NULL;
|
|
pPDev->pbScanBuf = NULL; // Don't need this buffer
|
|
}
|
|
else // bitmap surface
|
|
{
|
|
//
|
|
// Create a surface. Try for a bitmap for the entire surface.
|
|
// If this fails, then switch to journalling and a somewhat smaller
|
|
// surface. If journalling, we still create the bitmap here. While
|
|
// it is nicer to do this at DrvSendPage() time, we do it here to
|
|
// ensure that it is possible. By maintaining the bitmap for the
|
|
// life of the DC, we can be reasonably certain of being able to
|
|
// complete printing regardless of how tight memory becomes later.
|
|
//
|
|
VERBOSE(("DrvEnableSurface: creating a BITMAP surface.\n"));
|
|
hBitmap = HCreateBitmapSurface (pPDev, iFormat);
|
|
|
|
// if we can't create the bitmap fail the call.
|
|
if (!hBitmap)
|
|
{
|
|
ERR(("Unidrv!DrvEnableSurface:HCreateBitmapSurface Failed"));
|
|
VDisableSurface( pPDev );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// We will always use szBand to describe the bitmap surface, a band
|
|
// could be the whole page or a part of a page.
|
|
//
|
|
|
|
//
|
|
// Allocate array to represent the page in scanlines,
|
|
// for z-ordering fix
|
|
//
|
|
|
|
if( (pPDev->pbScanBuf = MemAllocZ(pPDev->szBand.cy)) == NULL)
|
|
{
|
|
VDisableSurface( pPDev );
|
|
return NULL;
|
|
}
|
|
//
|
|
// Allocate array to represents the page in scanlines, for erasing surface
|
|
//
|
|
|
|
if( (pPDev->pbRasterScanBuf = MemAllocZ((pPDev->szBand.cy / LINESPERBLOCK)+1)) == NULL)
|
|
{
|
|
VDisableSurface( pPDev );
|
|
return NULL;
|
|
}
|
|
#ifndef DISABLE_NEWRULES
|
|
//
|
|
// Allocate array to store black rectangle optimization
|
|
// Device must support rectangle commands and unidrv must dump the raster
|
|
//
|
|
if ((pPDev->fMode & PF_RECT_FILL) &&
|
|
!(pPDev->pdmPrivate->dwFlags & DXF_TEXTASGRAPHICS) &&
|
|
!(pPDev->fMode2 & PF2_MIRRORING_ENABLED) &&
|
|
((COMMANDPTR(pPDev->pDriverInfo,CMD_RECTBLACKFILL)) ||
|
|
(COMMANDPTR(pPDev->pDriverInfo,CMD_RECTGRAYFILL)) ||
|
|
!(COMMANDPTR(pPDev->pDriverInfo,CMD_RECTWHITEFILL))) &&
|
|
(pPDev->pColorModeEx == NULL || pPDev->pColorModeEx->dwPrinterBPP))
|
|
{
|
|
if( (pPDev->pbRulesArray = MemAlloc(sizeof(RECTL) * MAX_NUM_RULES)) == NULL)
|
|
{
|
|
VDisableSurface( pPDev );
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
pPDev->pbRulesArray = NULL;
|
|
#endif
|
|
pPDev->dwDelta = pPDev->szBand.cx / MAX_COLUMM;
|
|
|
|
pPDev->hbm = hBitmap;
|
|
pPDev->hSurface = NULL;
|
|
|
|
}
|
|
|
|
//
|
|
// Call Raster and Font module EnableSurface for surface intialization
|
|
//
|
|
|
|
if ( !(((PRMPROCS)(pPDev->pRasterProcs))->RMEnableSurface(pPDev)) ||
|
|
!(((PFMPROCS)(pPDev->pFontProcs))->FMEnableSurface(pPDev)) )
|
|
{
|
|
VDisableSurface( pPDev );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Now need to associate this surface with the pdev passed in at
|
|
// DrvCompletePDev time.
|
|
// Note: BUG_BUG, The RMInit() and FMInit() calls should have
|
|
// initialized the pPDev->fHooks already. All we need to do here is use it
|
|
//
|
|
|
|
ASSERT(pPDev->fHooks != 0);
|
|
|
|
if (DRIVER_DEVICEMANAGED (pPDev)) // device surface
|
|
{
|
|
pPDev->fHooks = dwHooks;
|
|
EngAssociateSurface (hSurface, pPDev->devobj.hEngine, pPDev->fHooks);
|
|
return hSurface;
|
|
}
|
|
else
|
|
{
|
|
#ifdef DISABLEDEVSURFACE
|
|
EngAssociateSurface( (HSURF)hBitmap, pPDev->devobj.hEngine, pPDev->fHooks );
|
|
pPDev->pso = EngLockSurface( (HSURF)hBitmap);
|
|
if (pPDev->pso == NULL)
|
|
{
|
|
ERR(("Unidrv!DrvEnableSurface:EngLockSurface Failed"));
|
|
VDisableSurface( pPDev );
|
|
return NULL;
|
|
}
|
|
return (HSURF)hBitmap;
|
|
|
|
#else
|
|
// HSURF hSurface;
|
|
// SIZEL szSurface;
|
|
|
|
EngAssociateSurface( (HSURF)hBitmap, pPDev->devobj.hEngine, 0 );
|
|
pPDev->pso = EngLockSurface( (HSURF)hBitmap);
|
|
if (pPDev->pso == NULL)
|
|
{
|
|
ERR(("Unidrv!DrvEnableSurface:EngLockSurface Failed"));
|
|
VDisableSurface( pPDev );
|
|
return NULL;
|
|
}
|
|
//
|
|
// Create a device surface to make sure GDI always calls the driver first
|
|
// for any drawing
|
|
//
|
|
hSurface = EngCreateDeviceSurface((DHSURF)pPDev, pPDev->szBand, iFormat);
|
|
if (!hSurface)
|
|
{
|
|
ERR(("Unidrv!DrvEnableSurface:EngCreateDeviceSurface Failed"));
|
|
VDisableSurface( pPDev );
|
|
return NULL;
|
|
}
|
|
// If banding is enabled mark the device surface as a banding surface
|
|
//
|
|
if (pPDev->bBanding)
|
|
EngMarkBandingSurface(hSurface);
|
|
|
|
pPDev->hSurface = hSurface;
|
|
|
|
EngAssociateSurface( (HSURF)hSurface, pPDev->devobj.hEngine, pPDev->fHooks );
|
|
|
|
return (HSURF)hSurface;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
DrvDisableSurface(
|
|
DHPDEV dhpdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvDisableSurface.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
dhpdev - Driver device handle
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
VERBOSE(("Entering DrvDisableSurface...\n"));
|
|
|
|
VDisableSurface( (PDEV *)dhpdev );
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
DrvDisablePDEV(
|
|
DHPDEV dhpdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvDisablePDEV.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Free up all memory allocated for PDEV
|
|
|
|
Arguments:
|
|
|
|
dhpdev - Driver device handle
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PDEV *pPDev = (PDEV *) dhpdev;
|
|
|
|
VERBOSE(("Entering DrvDisablePDEV...\n"));
|
|
|
|
if (!VALID_PDEV(pPDev))
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return;
|
|
}
|
|
|
|
// ASSERT_VALID_PDEV(pPDev);
|
|
|
|
//
|
|
// Free up resources associated with the PDEV
|
|
//
|
|
|
|
FlushSpoolBuf( pPDev ); // may need to do this per bug 250963
|
|
VFreePDEVData(pPDev);
|
|
}
|
|
|
|
VOID
|
|
DrvDisableDriver(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvDisableDriver.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Free everything that is allocated at DrvEnableDriver
|
|
//
|
|
|
|
VERBOSE(("Entering DrvDisableDriver...\n"));
|
|
|
|
#if ENABLE_STOCKGLYPHSET
|
|
EngAcquireSemaphore(hGlyphSetSem);
|
|
FreeGlyphSet();
|
|
EngReleaseSemaphore(hGlyphSetSem);
|
|
EngDeleteSemaphore(hGlyphSetSem) ;
|
|
#endif
|
|
|
|
#ifdef WINNT_40
|
|
|
|
ENTER_CRITICAL_SECTION();
|
|
|
|
VFreePluginRefCountList(&gpOEMPluginRefCount);
|
|
|
|
LEAVE_CRITICAL_SECTION();
|
|
|
|
DELETE_CRITICAL_SECTION();
|
|
|
|
#endif // WINNT_40
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
VOID
|
|
DrvCompletePDEV(
|
|
DHPDEV dhpdev,
|
|
HDEV hdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvCompletePDEV.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
This function is called when the engine completed the installation of
|
|
the physical device, some Engine functions requires the engine hdev as
|
|
a parameter, so we save it in our PDEVICE for later use.
|
|
|
|
Arguments:
|
|
|
|
dhpdev - Driver device handle
|
|
hdev - GDI device handle
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEV *pPDev = (PDEV *) dhpdev;
|
|
|
|
VERBOSE(("Entering DrvCompletePDEV...\n"));
|
|
|
|
if (!VALID_PDEV(pPDev))
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return;
|
|
}
|
|
// ASSERT_VALID_PDEV(pPDev);
|
|
|
|
pPDev->devobj.hEngine = hdev;
|
|
|
|
}
|
|
|
|
|
|
|
|
PPDEV
|
|
PAllocPDEVData(
|
|
HANDLE hPrinter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocate a new PDEV structure
|
|
|
|
Arguments:
|
|
|
|
hPrinter - handle to the current printer
|
|
|
|
Return Value:
|
|
|
|
Pointer to newly allocated PDEV structure,
|
|
NULL if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEV *pPDev;
|
|
|
|
//
|
|
// Allocate a zero-init PDEV structure and
|
|
// mark the signature fields
|
|
//
|
|
|
|
ASSERT(hPrinter != NULL);
|
|
|
|
if ((pPDev = MemAllocZ(sizeof(PDEV))) != NULL)
|
|
{
|
|
pPDev->pvStartSig = pPDev->pvEndSig = (PVOID) pPDev;
|
|
pPDev->devobj.dwSize = sizeof(DEVOBJ);
|
|
pPDev->devobj.hPrinter = hPrinter;
|
|
//
|
|
// set up pPDev->devobj.pPublicDM after pPDev->pdm has been set up
|
|
// (init.c)
|
|
//
|
|
pPDev->ulID = PDEV_ID;
|
|
}
|
|
else
|
|
ERR(("PAllocPDEVData: Memory allocation failed: %d\n", GetLastError()));
|
|
|
|
return pPDev;
|
|
}
|
|
|
|
|
|
VOID
|
|
VFreePDEVData(
|
|
PDEV * pPDev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dispose of a PDEV structure
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to a previously allocated PDEV structure
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
if (pPDev == NULL)
|
|
return;
|
|
|
|
VUnloadOemPlugins(pPDev);
|
|
|
|
//
|
|
// Call parser to free memory allocated for binary data
|
|
//
|
|
|
|
VUnloadFreeBinaryData(pPDev);
|
|
|
|
//
|
|
// Free other memory allocated for PDEV
|
|
//
|
|
|
|
if(pPDev->pSplForms)
|
|
{
|
|
MemFree(pPDev->pSplForms);
|
|
pPDev->pSplForms = NULL ;
|
|
}
|
|
|
|
//
|
|
// Free the output buffer
|
|
//
|
|
|
|
if(pPDev->pbOBuf )
|
|
{
|
|
MemFree(pPDev->pbOBuf);
|
|
pPDev->pbOBuf = NULL;
|
|
}
|
|
|
|
|
|
|
|
if (pPDev->pOptionsArray)
|
|
MemFree(pPDev->pOptionsArray);
|
|
|
|
//Unload Unidrv Module Handle, loaded for Unidrv resources
|
|
if (pPDev->hUniResDLL)
|
|
EngFreeModule(pPDev->hUniResDLL);
|
|
//
|
|
// Call Raster and Font module to clean up at DrvDisablePDEV
|
|
//
|
|
|
|
if (pPDev->pRasterProcs)
|
|
{
|
|
((PRMPROCS)(pPDev->pRasterProcs))->RMDisablePDEV(pPDev);
|
|
}
|
|
|
|
if (pPDev->pFontProcs)
|
|
{
|
|
((PFMPROCS)(pPDev->pFontProcs))->FMDisablePDEV(pPDev);
|
|
}
|
|
|
|
HANDLE_VECTORPROCS( pPDev, VMDisablePDEV, ((PDEVOBJ) pPDev)) ;
|
|
HANDLE_VECTORPROCS( pPDev, VMDisableDriver, ()) ;
|
|
|
|
//
|
|
// Free the Palette data
|
|
//
|
|
if (pPDev->pPalData)
|
|
{
|
|
//
|
|
// Free the Palette
|
|
//
|
|
if ( ((PAL_DATA *)pPDev->pPalData)->hPalette )
|
|
EngDeletePalette( ((PAL_DATA *)pPDev->pPalData)->hPalette );
|
|
|
|
if (((PAL_DATA*)(pPDev->pPalData))->pulDevPalCol)
|
|
MemFree(((PAL_DATA*)(pPDev->pPalData))->pulDevPalCol);
|
|
|
|
MemFree(pPDev->pPalData);
|
|
pPDev->pPalData = NULL;
|
|
}
|
|
|
|
//
|
|
// Free Resource Data
|
|
//
|
|
|
|
VWinResClose(&pPDev->WinResData);
|
|
// VWinResClose(&pPDev->localWinResData);
|
|
|
|
//
|
|
// Free devmode data
|
|
//
|
|
|
|
MemFree(pPDev->pdm);
|
|
|
|
MemFree(pPDev->pDriverInfo3);
|
|
|
|
if (pPDev->pbScanBuf) // may be NULL for a device surface
|
|
{
|
|
MemFree(pPDev->pbScanBuf);
|
|
}
|
|
|
|
if (pPDev->pbRasterScanBuf)
|
|
{
|
|
MemFree(pPDev->pbRasterScanBuf);
|
|
}
|
|
#ifndef DISABLE_NEWRULES
|
|
if (pPDev->pbRulesArray)
|
|
{
|
|
MemFree(pPDev->pbRulesArray);
|
|
}
|
|
#endif
|
|
//
|
|
// Free cached patterns
|
|
//
|
|
|
|
MemFree(pPDev->GState.pCachedPatterns);
|
|
|
|
|
|
//
|
|
// Free the PDEV structure itself
|
|
//
|
|
|
|
MemFree(pPDev);
|
|
|
|
}
|
|
|
|
HSURF
|
|
HCreateDeviceSurface(
|
|
PDEV * pPDev,
|
|
INT iFormat
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a device surface and returns a handle that the driver
|
|
will manage.
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to PDEV structure
|
|
iFormat - pixel depth of the device
|
|
|
|
Return Value:
|
|
|
|
Handle to the surface if successful, NULL otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
HSURF hSurface;
|
|
SIZEL szSurface;
|
|
|
|
ASSERT_VALID_PDEV(pPDev);
|
|
|
|
szSurface.cx = pPDev->sf.szImageAreaG.cx;
|
|
szSurface.cy = pPDev->sf.szImageAreaG.cy;
|
|
|
|
hSurface = EngCreateDeviceSurface((DHSURF)pPDev, szSurface, iFormat);
|
|
if (hSurface == NULL)
|
|
{
|
|
ERR(("EngCreateDeviceSurface failed\n"));
|
|
SetLastError(ERROR_BAD_DRIVER_LEVEL);
|
|
return NULL;
|
|
}
|
|
|
|
pPDev->rcClipRgn.top = 0;
|
|
pPDev->rcClipRgn.left = 0;
|
|
pPDev->rcClipRgn.right = pPDev->sf.szImageAreaG.cx;
|
|
pPDev->rcClipRgn.bottom = pPDev->sf.szImageAreaG.cy;
|
|
|
|
pPDev->bBanding = FALSE;
|
|
|
|
pPDev->szBand.cx = szSurface.cx;
|
|
pPDev->szBand.cy = szSurface.cy;
|
|
|
|
return hSurface;
|
|
}
|
|
|
|
HBITMAP
|
|
HCreateBitmapSurface(
|
|
PDEV * pPDev,
|
|
INT iFormat
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a bitmap surface and returns a handle that the driver
|
|
will manage.
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to PDEV structure
|
|
iFormat - pixel depth of the device
|
|
|
|
Return Value:
|
|
|
|
Handle to the bitmap if successful, NULL otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
SIZEL szSurface;
|
|
HBITMAP hBitmap;
|
|
ULONG cbScan; // Scan line byte length (DWORD aligned)
|
|
DWORD dwNumBands; // Number of bands to use
|
|
int iBPP; // Bits per pel, as # of bits
|
|
int iPins; // Basic rounding factor for banding size
|
|
PFN_OEMMemoryUsage pfnOEMMemoryUsage;
|
|
DWORD dwMaxBandSize; // Maximum size of band to use
|
|
|
|
szSurface.cx = pPDev->sf.szImageAreaG.cx;
|
|
szSurface.cy = pPDev->sf.szImageAreaG.cy;
|
|
|
|
iBPP = pPDev->sBitsPixel;
|
|
|
|
//
|
|
// define the maximum size bitmap band we will allow
|
|
//
|
|
dwMaxBandSize = MAX_SIZE_OF_BITMAP;
|
|
|
|
//
|
|
// adjust the maximum size of the bitmap buffer based on
|
|
// the amount of memory used by the OEM driver.
|
|
//
|
|
if (pPDev->pOemHookInfo && (pfnOEMMemoryUsage = (PFN_OEMMemoryUsage)pPDev->pOemHookInfo[EP_OEMMemoryUsage].pfnHook))
|
|
{
|
|
OEMMEMORYUSAGE MemoryUsage;
|
|
MemoryUsage.dwPercentMemoryUsage = 0;
|
|
MemoryUsage.dwFixedMemoryUsage = 0;
|
|
MemoryUsage.dwMaxBandSize = dwMaxBandSize;
|
|
FIX_DEVOBJ(pPDev,EP_OEMMemoryUsage);
|
|
|
|
if(pPDev->pOemEntry)
|
|
{
|
|
if(((POEM_PLUGIN_ENTRY)pPDev->pOemEntry)->pIntfOem ) // OEM plug in uses COM and function is implemented.
|
|
{
|
|
HRESULT hr ;
|
|
hr = HComMemoryUsage((POEM_PLUGIN_ENTRY)pPDev->pOemEntry,
|
|
(PDEVOBJ)pPDev,&MemoryUsage);
|
|
if(SUCCEEDED(hr))
|
|
; // cool !
|
|
}
|
|
else
|
|
{
|
|
pfnOEMMemoryUsage((PDEVOBJ)pPDev,&MemoryUsage);
|
|
}
|
|
}
|
|
|
|
|
|
dwMaxBandSize = ((dwMaxBandSize - MemoryUsage.dwFixedMemoryUsage) * 100) /
|
|
(100 + MemoryUsage.dwPercentMemoryUsage);
|
|
}
|
|
if (dwMaxBandSize < (MIN_SIZE_OF_BITMAP*2L))
|
|
dwMaxBandSize = MIN_SIZE_OF_BITMAP*2L;
|
|
|
|
//
|
|
// Create a surface. Try for a bitmap for the entire surface.
|
|
// If this fails, then switch to journalling and a somewhat smaller
|
|
// surface. If journalling, we still create the bitmap here. While
|
|
// it is nicer to do this at DrvSendPage() time, we do it here to
|
|
// ensure that it is possible. By maintaining the bitmap for the
|
|
// life of the DC, we can be reasonably certain of being able to
|
|
// complete printing regardless of how tight memory becomes later.
|
|
//
|
|
cbScan = ((szSurface.cx * iBPP + DWBITS - 1) & ~(DWBITS - 1)) / BBITS;
|
|
|
|
//
|
|
// Determine the number of bands to use based on the max size of
|
|
// a band.
|
|
//
|
|
dwNumBands = ((cbScan * szSurface.cy) / dwMaxBandSize)+1;
|
|
|
|
//
|
|
// Test registry for forced number of bands for testing
|
|
//
|
|
#if DBG
|
|
{
|
|
DWORD dwType;
|
|
DWORD ul;
|
|
int RegistryBands;
|
|
if( !GetPrinterData( pPDev->devobj.hPrinter, L"Banding", &dwType,
|
|
(BYTE *)&RegistryBands, sizeof( RegistryBands ), &ul ) &&
|
|
ul == sizeof( RegistryBands ) )
|
|
{
|
|
/* Some sanity checking: if iShrinkFactor == 0, disable banding */
|
|
if (RegistryBands > 0)
|
|
dwNumBands = RegistryBands;
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef BANDTEST
|
|
//
|
|
// Test code for forcing number of bands via GPD
|
|
//
|
|
if (pPDev->pGlobals->dwMaxNumPalettes > 0)
|
|
dwNumBands = pPDev->pGlobals->dwMaxNumPalettes;
|
|
#endif
|
|
|
|
//
|
|
// Time to allocate surface bitmap
|
|
//
|
|
if (dwNumBands > 1 || pPDev->fMode & PF_FORCE_BANDING ||
|
|
pPDev->pUIInfo->dwFlags & FLAG_REVERSE_BAND_ORDER ||
|
|
!(hBitmap = EngCreateBitmap( szSurface, (LONG) cbScan, iFormat, BMF_TOPDOWN|
|
|
BMF_NOZEROINIT|BMF_USERMEM, NULL )) )
|
|
{
|
|
//
|
|
// The bitmap creation failed, so we will try for smaller ones
|
|
// until we find one that is OK OR we cannot create one with
|
|
// enough scan lines to be useful.
|
|
//
|
|
|
|
//
|
|
// Calculate the rounding factor for band shrink operations.
|
|
// Basically this is to allow more effective use of the printer,
|
|
// by making the bands a multiple of the number of pins per
|
|
// pass. In interlaced mode, this is the number of scan lines
|
|
// in the interlaced band, not the number of pins in the print head.
|
|
// For single pin printers, make this a multiple of 8. This
|
|
// speeds up processing a little.
|
|
//
|
|
// If this is 1bpp we need to make the band size a multiple of the halftone
|
|
// pattern to avoid a certain GDI bug where it doesn't correctly align
|
|
// a pattern brush at the beginning of each band.
|
|
//
|
|
if (iBPP == 1 && pPDev->pResolutionEx->dwPinsPerLogPass == 1)
|
|
{
|
|
INT iPatID;
|
|
if (pPDev->pHalftone)
|
|
iPatID = pPDev->pHalftone->dwHTID;
|
|
else
|
|
iPatID= HT_PATSIZE_AUTO;
|
|
if (iPatID == HT_PATSIZE_AUTO)
|
|
{
|
|
INT dpi = pPDev->ptGrxRes.x;
|
|
if (dpi > pPDev->ptGrxRes.y)
|
|
dpi = pPDev->ptGrxRes.y;
|
|
if (dpi >= 2400) // 16x16 pattern
|
|
iPins = 16;
|
|
else if (dpi >= 1800) // 14x14 pattern
|
|
iPins = 56;
|
|
else if (dpi >= 1200) // 12x12 pattern
|
|
iPins = 24;
|
|
else if (dpi >= 800) // 10x10 pattern
|
|
iPins = 40;
|
|
else
|
|
iPins = 8;
|
|
}
|
|
else if (iPatID == HT_PATSIZE_6x6_M || iPatID == HT_PATSIZE_12x12_M)
|
|
iPins = 24;
|
|
else if (iPatID == HT_PATSIZE_10x10_M)
|
|
iPins = 40;
|
|
else if (iPatID == HT_PATSIZE_14x14_M)
|
|
iPins = 56;
|
|
else if (iPatID == HT_PATSIZE_16x16_M)
|
|
iPins = 16;
|
|
else
|
|
iPins = 8;
|
|
}
|
|
else
|
|
iPins = (pPDev->pResolutionEx->dwPinsPerLogPass + BBITS - 1) & ~(BBITS - 1);
|
|
|
|
if (dwNumBands <= 1)
|
|
dwNumBands = SHRINK_FACTOR;
|
|
|
|
while (1)
|
|
{
|
|
//
|
|
// Shrink the bitmap each time around. Note that we are
|
|
// rotation sensitive. In portrait mode, we shrink the
|
|
// Y coordinate, so that the bands fit across the page.
|
|
// In landscape when we rotate, shrink the X coordinate, since
|
|
// that becomes the Y coordinate after transposing.
|
|
//
|
|
if( pPDev->fMode & PF_ROTATE )
|
|
{
|
|
//
|
|
// We rotate the bitmap, so shrink the X coordinates.
|
|
//
|
|
|
|
szSurface.cx = pPDev->sf.szImageAreaG.cx / dwNumBands;
|
|
if( szSurface.cx < iPins)
|
|
return NULL;
|
|
szSurface.cx += iPins - (szSurface.cx % iPins);
|
|
cbScan = ((szSurface.cx * iBPP + DWBITS - 1) & ~(DWBITS - 1)) / BBITS;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Normal operation, so shrink the Y coordinate.
|
|
//
|
|
|
|
szSurface.cy = pPDev->sf.szImageAreaG.cy / dwNumBands;
|
|
if( szSurface.cy < iPins)
|
|
return NULL;
|
|
szSurface.cy += iPins - (szSurface.cy % iPins);
|
|
}
|
|
dwNumBands *= SHRINK_FACTOR;
|
|
|
|
//
|
|
// Try to allocate the bitmap surface
|
|
//
|
|
|
|
if (hBitmap = EngCreateBitmap( szSurface, (LONG) cbScan, iFormat, BMF_TOPDOWN|BMF_NOZEROINIT|BMF_USERMEM, NULL ))
|
|
break;
|
|
|
|
//
|
|
// if we failed to allocate the bitmap surface we will give up
|
|
// at some point if the band becomes too small
|
|
//
|
|
if ((cbScan * szSurface.cy / 2) < MIN_SIZE_OF_BITMAP)
|
|
return NULL;
|
|
}
|
|
//
|
|
// Success so mark the surface for banding
|
|
//
|
|
#ifdef DISABLEDEVSURFACE
|
|
EngMarkBandingSurface((HSURF)hBitmap);
|
|
#endif
|
|
pPDev->bBanding = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The speedy way: into a big bitmap. Set the clipping region
|
|
// to full size, and the journal handle to 0.
|
|
//
|
|
|
|
pPDev->rcClipRgn.top = 0;
|
|
pPDev->rcClipRgn.left = 0;
|
|
pPDev->rcClipRgn.right = pPDev->sf.szImageAreaG.cx;
|
|
pPDev->rcClipRgn.bottom = pPDev->sf.szImageAreaG.cy;
|
|
|
|
pPDev->bBanding = FALSE;
|
|
}
|
|
|
|
pPDev->szBand.cx = szSurface.cx;
|
|
pPDev->szBand.cy = szSurface.cy;
|
|
return hBitmap;
|
|
}
|
|
|
|
VOID
|
|
VDisableSurface(
|
|
PDEV * pPDev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Clean up resources allocated at DrvEnableSurface and
|
|
call Raster and Font module to clean up their internal data
|
|
and deallocated memory associated with the surface
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to PDEV structure
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Call the Raster and Font module to free
|
|
// rendering storage, position sorting memory etc.
|
|
//
|
|
|
|
((PRMPROCS)(pPDev->pRasterProcs))->RMDisableSurface(pPDev);
|
|
((PFMPROCS)(pPDev->pFontProcs))->FMDisableSurface(pPDev);
|
|
|
|
|
|
//
|
|
// Delete the surface
|
|
//
|
|
|
|
if( pPDev->hbm )
|
|
{
|
|
//
|
|
// unlock surface first if necessary
|
|
//
|
|
if (pPDev->pso)
|
|
{
|
|
EngUnlockSurface(pPDev->pso);
|
|
pPDev->pso = NULL;
|
|
}
|
|
EngDeleteSurface( (HSURF)pPDev->hbm );
|
|
pPDev->hbm = (HBITMAP)0;
|
|
}
|
|
|
|
if (pPDev->hSurface)
|
|
{
|
|
EngDeleteSurface (pPDev->hSurface);
|
|
pPDev->hSurface = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
BPaperSizeSourceSame(
|
|
PDEV * pPDevNew,
|
|
PDEV * pPDevOld
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function check for the following condition:
|
|
- paper size and souce has not changed.
|
|
|
|
Arguments:
|
|
|
|
pPDevNew - Pointer to the new PDEV
|
|
pPDevOld - Pointer to the old PDEV
|
|
|
|
Return Value:
|
|
|
|
TRUE if both are unchanged, otherwise FALSE
|
|
|
|
--*/
|
|
{
|
|
|
|
// if (pPDevNew->pdm->dmOrientation == pPDevOld->pdm->dmOrientation)
|
|
// return FALSE;
|
|
|
|
//
|
|
// Check paper size, Note PDEVICE->pf.szPhysSize is in Portrait mode.
|
|
//
|
|
|
|
return (pPDevNew->pf.szPhysSizeM.cx == pPDevOld->pf.szPhysSizeM.cx &&
|
|
pPDevNew->pf.szPhysSizeM.cy == pPDevOld->pf.szPhysSizeM.cy &&
|
|
pPDevNew->pdm->dmDefaultSource == pPDevOld->pdm->dmDefaultSource
|
|
);
|
|
|
|
}
|
|
|
|
BOOL
|
|
BMergeFormToTrayAssignments(
|
|
PDEV * pPDev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads the form to tray table and merges the values in the devmode.
|
|
Arguments:
|
|
|
|
pPDev - Pointer to the PDEV
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE for success, otherwise FALSE
|
|
|
|
--*/
|
|
|
|
{
|
|
PFEATURE pInputSlotFeature;
|
|
DWORD dwInputSlotIndex, dwIndex;
|
|
POPTION pOption;
|
|
FORM_TRAY_TABLE pFormTrayTable = NULL;
|
|
PUIINFO pUIInfo = pPDev->pUIInfo;
|
|
POPTSELECT pOptionArray = pPDev->pOptionsArray;
|
|
BOOL bFound = FALSE;
|
|
PDEVMODE pdm = pPDev->pdm;
|
|
|
|
#if DBG
|
|
PTSTR pTmp;
|
|
PFEATURE pPageSizeFeature;
|
|
DWORD dwPageSizeIndex;
|
|
#endif
|
|
|
|
//
|
|
// If there is no *InputSlot feature (which shouldn't happen),
|
|
// simply ignore and return success
|
|
//
|
|
|
|
if (! (pInputSlotFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_INPUTSLOT)))
|
|
return TRUE;
|
|
|
|
dwInputSlotIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pInputSlotFeature);
|
|
|
|
//
|
|
// If the input slot is "AutoSelect", then go through
|
|
// the form-to-tray assignment table and see if the
|
|
// requested form is assigned to an input slot.
|
|
//
|
|
|
|
if (((pdm->dmFields & DM_DEFAULTSOURCE) &&
|
|
(pdm->dmDefaultSource == DMBIN_FORMSOURCE)) &&
|
|
(pdm->dmFormName[0] != NUL) &&
|
|
(pFormTrayTable = PGetFormTrayTable(pPDev->devobj.hPrinter, NULL)))
|
|
{
|
|
FINDFORMTRAY FindData;
|
|
PTSTR ptstrName;
|
|
|
|
//
|
|
// Find the tray name corresponding to the requested form name
|
|
//
|
|
|
|
RESET_FINDFORMTRAY(pFormTrayTable, &FindData);
|
|
ptstrName = pdm->dmFormName;
|
|
|
|
#if 0
|
|
pTmp = pFormTrayTable;
|
|
VERBOSE(("Looking for form [%ws] in the Form Tray Table\n",ptstrName));
|
|
VERBOSE(("BEFORE SETTING: Value of pOptionArray[dwInputSlotIndex].ubCurOptIndex is = %d \n",pOptionArray[dwInputSlotIndex].ubCurOptIndex));
|
|
#endif
|
|
|
|
while (!bFound && *FindData.ptstrNextEntry)
|
|
{
|
|
if (BSearchFormTrayTable(pFormTrayTable, NULL, ptstrName, &FindData))
|
|
{
|
|
//
|
|
// Convert the tray name to an option index
|
|
//
|
|
|
|
bFound = FALSE;
|
|
|
|
//
|
|
//Search from index 1 as the first input slot is a dummy tray
|
|
//for DMBIN_FORMSOURCE.
|
|
//
|
|
|
|
for (dwIndex = 1; dwIndex < pInputSlotFeature->Options.dwCount; dwIndex++)
|
|
{
|
|
pOption = PGetIndexedOption(pUIInfo, pInputSlotFeature, dwIndex);
|
|
|
|
if (pOption->loDisplayName & GET_RESOURCE_FROM_DLL)
|
|
{
|
|
//
|
|
// loOffset specifies a string resource ID
|
|
// in the resource DLL
|
|
//
|
|
|
|
WCHAR wchbuf[MAX_DISPLAY_NAME];
|
|
|
|
//#ifdef RCSTRINGSUPPORT
|
|
#if 0
|
|
if(((pOption->loDisplayName & ~GET_RESOURCE_FROM_DLL) >= RESERVED_STRINGID_START)
|
|
&& ((pOption->loDisplayName & ~GET_RESOURCE_FROM_DLL) <= RESERVED_STRINGID_END))
|
|
{
|
|
if (!ILoadStringW ( &(pPDev->localWinResData),
|
|
(pOption->loDisplayName & ~GET_RESOURCE_FROM_DLL),
|
|
wchbuf, MAX_DISPLAY_NAME) )
|
|
{
|
|
WARNING(("\n UniFont!BMergeFormToTrayAssignments:Input Tray Name not found in resource DLL\n"));
|
|
continue;
|
|
}
|
|
}
|
|
|
|
else
|
|
#endif
|
|
|
|
if (!ILoadStringW ( &(pPDev->WinResData),
|
|
(pOption->loDisplayName & ~GET_RESOURCE_FROM_DLL),
|
|
wchbuf, MAX_DISPLAY_NAME) )
|
|
{
|
|
WARNING(("\n UniFont!BMergeFormToTrayAssignments:Input Tray Name not found in resource DLL\n"));
|
|
continue;
|
|
}
|
|
|
|
ptstrName = wchbuf;
|
|
}
|
|
else
|
|
ptstrName = OFFSET_TO_POINTER(pPDev->pDriverInfo->pubResourceData, pOption->loDisplayName);
|
|
|
|
ASSERTMSG((ptstrName && FindData.ptstrTrayName),("\n NULL Tray Name,\
|
|
ptstrName = 0x%p,FindData.ptstrTrayName = 0x%p\n",
|
|
ptstrName, FindData.ptstrTrayName ));
|
|
#if 0
|
|
VERBOSE(("\nInput Tray Name for Option %d = %ws\n",dwIndex, ptstrName));
|
|
VERBOSE(("The required Tray Name = %ws\n",FindData.ptstrTrayName));
|
|
VERBOSE(("\tInput TrayName for FormTray table index %d = %ws\n",dwIndex, pTmp));
|
|
pTmp += (wcslen(pTmp) + 1);
|
|
VERBOSE(("\tForm Name for FormTray table index %d = %ws\n\n",dwIndex, pTmp));
|
|
#endif
|
|
|
|
if (ptstrName && (_tcsicmp(ptstrName, FindData.ptstrTrayName) == EQUAL_STRING))
|
|
{
|
|
pOptionArray[dwInputSlotIndex].ubCurOptIndex = (BYTE) dwIndex;
|
|
bFound = TRUE;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MemFree(pFormTrayTable);
|
|
}
|
|
|
|
if (!bFound)
|
|
{
|
|
if (pFormTrayTable)
|
|
{
|
|
TERSE(("Form '%ws' is not currently assigned to a tray.\n",
|
|
pdm->dmFormName));
|
|
}
|
|
|
|
//
|
|
// Set the Inputbin option to default input Bin, if current value is
|
|
// set to dummy one.
|
|
//
|
|
|
|
if (pOptionArray[dwInputSlotIndex].ubCurOptIndex == 0)
|
|
{
|
|
pOptionArray[dwInputSlotIndex].ubCurOptIndex =
|
|
(BYTE)pInputSlotFeature->dwDefaultOptIndex;
|
|
|
|
}
|
|
}
|
|
|
|
pPDev->pdmPrivate->aOptions[dwInputSlotIndex].ubCurOptIndex = pOptionArray[dwInputSlotIndex].ubCurOptIndex;
|
|
|
|
//
|
|
//TRACE CODE
|
|
//
|
|
|
|
#if 0
|
|
if (pPageSizeFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_PAGESIZE))
|
|
dwPageSizeIndex = GET_INDEX_FROM_FEATURE(pUIInfo, pPageSizeFeature);
|
|
|
|
if (pdm->dmFields & DM_DEFAULTSOURCE)
|
|
{
|
|
VERBOSE(("DM_DEFAULTSOURCE BIT IS ON. \n"));
|
|
}
|
|
else
|
|
{
|
|
VERBOSE(("DM_DEFAULTSOURCE BIT IS OFF.\n"));
|
|
}
|
|
|
|
VERBOSE(("pdm->dmDefaultSource = %d\n",pdm->dmDefaultSource));
|
|
VERBOSE(("pFormTrayTable = 0x%p\n",pFormTrayTable));
|
|
VERBOSE(("Value of pOptionArray[dwPageSizeIndex].ubCurOptIndex = %d \n",pOptionArray[dwPageSizeIndex].ubCurOptIndex));
|
|
VERBOSE(("AFTER SETTING:Value of pOptionArray[dwInputSlotIndex].ubCurOptIndex = %d\n",pOptionArray[dwInputSlotIndex].ubCurOptIndex));
|
|
VERBOSE(("AFTER SETTING:Value of pdmPrivate->aOptions[dwInputSlotIndex].ubCurOptIndex = %d\n",pPDev->pdmPrivate->aOptions[dwInputSlotIndex].ubCurOptIndex));
|
|
VERBOSE(("Value of pInputSlotFeature->dwDefaultOptIndex is %d \n",pInputSlotFeature->dwDefaultOptIndex));
|
|
VERBOSE(("END TRACING BMergeFormToTrayAssignments.\n\n"));
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#undef FILETRACE
|