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.
506 lines
11 KiB
506 lines
11 KiB
/*++
|
|
|
|
Copyright (c) 1990-2003 Microsoft Corporation
|
|
|
|
|
|
Module Name:
|
|
|
|
devmode.c
|
|
|
|
|
|
Abstract:
|
|
|
|
This module contains devmode conversion
|
|
|
|
|
|
|
|
Development History:
|
|
|
|
08-Jun-1995 Thu 13:47:33 created
|
|
|
|
|
|
[Environment:]
|
|
|
|
GDI printer drivers, user and kernel mode
|
|
|
|
|
|
[Notes:]
|
|
|
|
|
|
Revision History:
|
|
|
|
11/09/95
|
|
New conversion routines
|
|
|
|
09-Feb-1999 Tue 11:15:55 updated
|
|
Move from printers\lib directory
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
//
|
|
// This is the devmode version 320 (DM_SPECVERSION)
|
|
//
|
|
|
|
#define DM_SPECVERSION320 0x0320
|
|
#define DM_SPECVERSION400 0x0400
|
|
#define DM_SPECVERSION401 0x0401
|
|
#define DM_SPECVER_BASE DM_SPECVERSION320
|
|
|
|
//
|
|
// size of a device name string
|
|
//
|
|
|
|
#define CCHDEVICENAME320 32
|
|
#define CCHFORMNAME320 32
|
|
|
|
typedef struct _devicemode320A {
|
|
BYTE dmDeviceName[CCHDEVICENAME320];
|
|
WORD dmSpecVersion;
|
|
WORD dmDriverVersion;
|
|
WORD dmSize;
|
|
WORD dmDriverExtra;
|
|
DWORD dmFields;
|
|
short dmOrientation;
|
|
short dmPaperSize;
|
|
short dmPaperLength;
|
|
short dmPaperWidth;
|
|
short dmScale;
|
|
short dmCopies;
|
|
short dmDefaultSource;
|
|
short dmPrintQuality;
|
|
short dmColor;
|
|
short dmDuplex;
|
|
short dmYResolution;
|
|
short dmTTOption;
|
|
short dmCollate;
|
|
BYTE dmFormName[CCHFORMNAME320];
|
|
WORD dmLogPixels;
|
|
DWORD dmBitsPerPel;
|
|
DWORD dmPelsWidth;
|
|
DWORD dmPelsHeight;
|
|
DWORD dmDisplayFlags;
|
|
DWORD dmDisplayFrequency;
|
|
} DEVMODE320A, *PDEVMODE320A, *NPDEVMODE320A, *LPDEVMODE320A;
|
|
|
|
typedef struct _devicemode320W {
|
|
WCHAR dmDeviceName[CCHDEVICENAME320];
|
|
WORD dmSpecVersion;
|
|
WORD dmDriverVersion;
|
|
WORD dmSize;
|
|
WORD dmDriverExtra;
|
|
DWORD dmFields;
|
|
short dmOrientation;
|
|
short dmPaperSize;
|
|
short dmPaperLength;
|
|
short dmPaperWidth;
|
|
short dmScale;
|
|
short dmCopies;
|
|
short dmDefaultSource;
|
|
short dmPrintQuality;
|
|
short dmColor;
|
|
short dmDuplex;
|
|
short dmYResolution;
|
|
short dmTTOption;
|
|
short dmCollate;
|
|
WCHAR dmFormName[CCHFORMNAME320];
|
|
WORD dmLogPixels;
|
|
DWORD dmBitsPerPel;
|
|
DWORD dmPelsWidth;
|
|
DWORD dmPelsHeight;
|
|
DWORD dmDisplayFlags;
|
|
DWORD dmDisplayFrequency;
|
|
} DEVMODE320W, *PDEVMODE320W, *NPDEVMODE320W, *LPDEVMODE320W;
|
|
|
|
|
|
|
|
#ifdef UNICODE
|
|
|
|
typedef DEVMODE320W DEVMODE320;
|
|
typedef PDEVMODE320W PDEVMODE320;
|
|
typedef NPDEVMODE320W NPDEVMODE320;
|
|
typedef LPDEVMODE320W LPDEVMODE320;
|
|
|
|
#else
|
|
|
|
typedef DEVMODE320A DEVMODE320;
|
|
typedef PDEVMODE320A PDEVMODE320;
|
|
typedef NPDEVMODE320A NPDEVMODE320;
|
|
typedef LPDEVMODE320A LPDEVMODE320;
|
|
|
|
#endif // UNICODE
|
|
|
|
|
|
typedef struct _DMEXTRA400 {
|
|
DWORD dmICMMethod;
|
|
DWORD dmICMIntent;
|
|
DWORD dmMediaType;
|
|
DWORD dmDitherType;
|
|
DWORD dmICCManufacturer;
|
|
DWORD dmICCModel;
|
|
} DMEXTRA400;
|
|
|
|
|
|
typedef struct _DMEXTRA401 {
|
|
DWORD dmPanningWidth;
|
|
DWORD dmPanningHeight;
|
|
} DMEXTRA401;
|
|
|
|
|
|
#define DM_SIZE320 sizeof(DEVMODE320)
|
|
#define DM_SIZE400 (DM_SIZE320 + sizeof(DMEXTRA400))
|
|
#define DM_SIZE401 (DM_SIZE400 + sizeof(DMEXTRA401))
|
|
|
|
// Current version devmode size - public portion only
|
|
|
|
#ifdef UNICODE
|
|
#define DM_SIZE_CURRENT sizeof(DEVMODEW)
|
|
#else
|
|
#define DM_SIZE_CURRENT sizeof(DEVMODEA)
|
|
#endif
|
|
|
|
|
|
|
|
WORD
|
|
CheckDevmodeVersion(
|
|
PDEVMODE pdm
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Verify dmSpecVersion and dmSize fields of a devmode
|
|
|
|
Arguments:
|
|
|
|
pdm - Specifies a devmode to be version-checked
|
|
|
|
Return Value:
|
|
|
|
0 if the input devmode is unacceptable
|
|
Otherwise, return the expected dmSpecVersion value
|
|
|
|
--*/
|
|
|
|
{
|
|
WORD expectedVersion;
|
|
|
|
if (pdm == NULL)
|
|
return 0;
|
|
|
|
// Check against known devmode sizes
|
|
|
|
switch (pdm->dmSize) {
|
|
|
|
case DM_SIZE320:
|
|
expectedVersion = DM_SPECVERSION320;
|
|
break;
|
|
|
|
case DM_SIZE400:
|
|
expectedVersion = DM_SPECVERSION400;
|
|
break;
|
|
|
|
case DM_SIZE401:
|
|
expectedVersion = DM_SPECVERSION401;
|
|
break;
|
|
|
|
default:
|
|
expectedVersion = pdm->dmSpecVersion;
|
|
break;
|
|
}
|
|
|
|
|
|
return expectedVersion;
|
|
}
|
|
|
|
|
|
|
|
LONG
|
|
ConvertDevmode(
|
|
PDEVMODE pdmIn,
|
|
PDEVMODE pdmOut
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert an input devmode to a different version devmode.
|
|
|
|
Whenever driver gets an input devmode, it should call this
|
|
routine to convert it to current version.
|
|
|
|
Arguments:
|
|
|
|
pdmIn - Points to an input devmode
|
|
pdmOut - Points to an initialized/valid output devmode
|
|
|
|
Return Value:
|
|
|
|
Total number of bytes copied
|
|
-1 if either input or output devmode is invalid
|
|
|
|
--*/
|
|
|
|
{
|
|
WORD dmSpecVersion, dmDriverVersion;
|
|
WORD dmSize, dmDriverExtra;
|
|
LONG cbCopied = 0;
|
|
|
|
//
|
|
// Parameter check
|
|
//
|
|
if (NULL == pdmIn ||
|
|
NULL == pdmOut )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// Look for inconsistency between dmSpecVersion and dmSize
|
|
|
|
if (! CheckDevmodeVersion(pdmIn) ||
|
|
! (dmSpecVersion = CheckDevmodeVersion(pdmOut)))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// Copy public devmode fields
|
|
|
|
dmDriverVersion = pdmOut->dmDriverVersion;
|
|
dmSize = pdmOut->dmSize;
|
|
dmDriverExtra = pdmOut->dmDriverExtra;
|
|
|
|
cbCopied = min(dmSize, pdmIn->dmSize);
|
|
memcpy(pdmOut, pdmIn, cbCopied);
|
|
|
|
pdmOut->dmSpecVersion = dmSpecVersion;
|
|
pdmOut->dmDriverVersion = dmDriverVersion;
|
|
pdmOut->dmSize = dmSize;
|
|
pdmOut->dmDriverExtra = dmDriverExtra;
|
|
|
|
// Copy private devmode fields
|
|
|
|
cbCopied += min(dmDriverExtra, pdmIn->dmDriverExtra);
|
|
memcpy((PBYTE) pdmOut + pdmOut->dmSize,
|
|
(PBYTE) pdmIn + pdmIn->dmSize,
|
|
min(dmDriverExtra, pdmIn->dmDriverExtra));
|
|
|
|
return cbCopied;
|
|
}
|
|
|
|
|
|
#if defined(UMODE) || defined(USERMODE_DRIVER)
|
|
|
|
|
|
|
|
BOOL
|
|
ConvertDevmodeOut(
|
|
PDEVMODE pdmSrc,
|
|
PDEVMODE pdmIn,
|
|
PDEVMODE pdmOut
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy a source devmode to an output devmode buffer.
|
|
|
|
Driver should call this routine before it returns to the caller
|
|
of DrvDocumentPropertySheets.
|
|
|
|
Arguments:
|
|
|
|
pdmSrc - Points to a current version source devmode
|
|
pdmIn - Points to input devmode passed to DrvDocumentPropertySheets through lparam
|
|
pdmOut - Output buffer pointer passed to DrvDocumentPropertySheets through lparam
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
if (pdmIn == NULL) {
|
|
|
|
if (pdmSrc == NULL || pdmOut == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
memcpy(pdmOut, pdmSrc, pdmSrc->dmSize + pdmSrc->dmDriverExtra);
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
if (pdmSrc == NULL || pdmOut == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// We have to deal with the public fields and private fields
|
|
// separately. Also remember pdmIn and pdmOut may point to
|
|
// the same buffer.
|
|
|
|
// Public fields: take dmSpecVersion and dmSize from
|
|
// the smaller of pdmSrc and pdmIn
|
|
|
|
if (pdmIn->dmSize < pdmSrc->dmSize) {
|
|
|
|
pdmOut->dmSpecVersion = pdmIn->dmSpecVersion;
|
|
pdmOut->dmSize = pdmIn->dmSize;
|
|
|
|
} else {
|
|
|
|
pdmOut->dmSpecVersion = pdmSrc->dmSpecVersion;
|
|
pdmOut->dmSize = pdmSrc->dmSize;
|
|
}
|
|
|
|
// Similarly for private fields
|
|
|
|
if (pdmIn->dmDriverExtra < pdmSrc->dmDriverExtra) {
|
|
|
|
pdmOut->dmDriverVersion = pdmIn->dmDriverVersion;
|
|
pdmOut->dmDriverExtra = pdmIn->dmDriverExtra;
|
|
|
|
} else {
|
|
|
|
pdmOut->dmDriverVersion = pdmSrc->dmDriverVersion;
|
|
pdmOut->dmDriverExtra = pdmSrc->dmDriverExtra;
|
|
}
|
|
|
|
return ConvertDevmode(pdmSrc, pdmOut) > 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
INT
|
|
CommonDrvConvertDevmode(
|
|
PWSTR pPrinterName,
|
|
PDEVMODE pdmIn,
|
|
PDEVMODE pdmOut,
|
|
PLONG pcbNeeded,
|
|
DWORD fMode,
|
|
PDRIVER_VERSION_INFO pDriverVersions
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Library routine to handle common cases of DrvConvertDevMode
|
|
|
|
Arguments:
|
|
|
|
pPrinterName, pdmIn, pdmOut, pcbNeeded, fMode
|
|
Correspond to parameters passed to DrvConvertDevMode
|
|
pDriverVersions - Specifies driver version numbers and private devmode sizes
|
|
|
|
Return Value:
|
|
|
|
CDM_RESULT_TRUE
|
|
If the case is handled by the library routine and driver
|
|
shoud return TRUE to the caller of DrvConvertDevMode.
|
|
|
|
CDM_RESULT_FALSE
|
|
If the case is handled by the library routine and driver
|
|
shoud return FALSE to the caller of DrvConvertDevMode.
|
|
|
|
CDM_RESULT_NOT_HANDLED
|
|
The case is NOT handled by the library routine and driver
|
|
should continue on with whatever it needs to do.
|
|
|
|
--*/
|
|
|
|
{
|
|
LONG size;
|
|
|
|
// Make sure pcbNeeded parameter is not NULL
|
|
|
|
if (pcbNeeded == NULL) {
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return CDM_RESULT_FALSE;
|
|
}
|
|
|
|
switch (fMode) {
|
|
|
|
case CDM_CONVERT:
|
|
|
|
// Convert any input devmode to any output devmode.
|
|
// Both input and output must be valid.
|
|
|
|
if (pdmOut != NULL &&
|
|
*pcbNeeded >= (pdmOut->dmSize + pdmOut->dmDriverExtra) &&
|
|
ConvertDevmode(pdmIn, pdmOut) > 0)
|
|
{
|
|
*pcbNeeded = pdmOut->dmSize + pdmOut->dmDriverExtra;
|
|
return CDM_RESULT_TRUE;
|
|
}
|
|
break;
|
|
|
|
case CDM_CONVERT351:
|
|
|
|
// Convert any input devmode to 3.51 version devmode
|
|
// First check if the caller provided buffer is large enough
|
|
|
|
size = DM_SIZE320 + pDriverVersions->dmDriverExtra351;
|
|
|
|
if (*pcbNeeded < size || pdmOut == NULL) {
|
|
|
|
*pcbNeeded = size;
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
return CDM_RESULT_FALSE;
|
|
}
|
|
|
|
// Do the conversion from input devmode to 3.51 devmode
|
|
|
|
pdmOut->dmSpecVersion = DM_SPECVERSION320;
|
|
pdmOut->dmSize = DM_SIZE320;
|
|
pdmOut->dmDriverVersion = pDriverVersions->dmDriverVersion351;
|
|
pdmOut->dmDriverExtra = pDriverVersions->dmDriverExtra351;
|
|
|
|
if (ConvertDevmode(pdmIn, pdmOut) > 0) {
|
|
|
|
*pcbNeeded = size;
|
|
return CDM_RESULT_TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
case CDM_DRIVER_DEFAULT:
|
|
|
|
// Convert any input devmode to current version devmode
|
|
// First check if the caller provided buffer is large enough
|
|
|
|
size = DM_SIZE_CURRENT + pDriverVersions->dmDriverExtra;
|
|
|
|
if (*pcbNeeded < size || pdmOut == NULL) {
|
|
|
|
*pcbNeeded = size;
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
return CDM_RESULT_FALSE;
|
|
}
|
|
|
|
// This case (getting driver-default devmode) is not handled
|
|
// by the library routine.
|
|
|
|
*pcbNeeded = size;
|
|
|
|
// FALL THROUGH TO THE DEFAULT CASE!
|
|
|
|
default:
|
|
return CDM_RESULT_NOT_HANDLED;
|
|
}
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return CDM_RESULT_FALSE;
|
|
}
|
|
|
|
#endif // USER MODE
|