Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

814 lines
19 KiB

/*++
Copyright (c) 1990-2003 Microsoft Corporation
Module Name:
devcaps.c
Abstract:
This module contains API function DrvDeviceCapabilities and other support
functions
Author:
02-Dec-1993 Thu 16:49:08 created
22-Mar-1994 Tue 13:00:04 updated
Update RESOLUTION caps so it return as not supported, this way the
application will not used to setup the DMRES_xxx fields
[Environment:]
GDI Device Driver - Plotter.
[Notes:]
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#define DBG_PLOTFILENAME DbgDevCaps
extern HMODULE hPlotUIModule;
#define DBG_DEVCAPS_0 0x00000001
#define DBG_DEVCAPS_1 0x00000002
DEFINE_DBGVAR(0);
//
// Local defines only used in this module
//
// The following sizes are copied from the Win 3.1 driver. They do not appear
// to be defined in any public place, although it looks like they should be.
//
#define CCHBINNAME 24 // Characters allowed for bin names
#define CCHPAPERNAME 64 // Max length of paper size names
#define DC_SPL_PAPERNAMES 0xFFFF
#define DC_SPL_MEDIAREADY 0xFFFE
#ifdef DBG
LPSTR pDCCaps[] = {
"FIELDS",
"PAPERS",
"PAPERSIZE",
"MINEXTENT",
"MAXEXTENT",
"BINS",
"DUPLEX",
"SIZE",
"EXTRA",
"VERSION",
"DRIVER",
"BINNAMES",
"ENUMRESOLUTIONS",
"FILEDEPENDENCIES",
"TRUETYPE",
"PAPERNAMES",
"ORIENTATION",
"COPIES",
//
// 4.00
//
"BINADJUST",
"EMF_COMPLIANT",
"DATATYPE_PRODUCED",
"COLLATE",
"MANUFACTURER",
"MODEL",
//
// 5.00
//
"PERSONALITY",
"PRINTRATE",
"PRINTRATEUNIT",
"PRINTERMEM",
"MEDIAREADY",
"STAPLE",
"PRINTRATEPPM",
"COLORDEVICE",
"NUP",
"NULL"
};
#endif
INT
CALLBACK
DevCapEnumFormProc(
PFORM_INFO_1 pFI1,
DWORD Index,
PENUMFORMPARAM pEFP
)
/*++
Routine Description:
This is callback function from PlotEnumForm()
Arguments:
pFI1 - pointer to the current FORM_INFO_1 data structure passed
Index - pFI1 index related to the pFI1Base (0 based)
pEFP - Pointer to the EnumFormParam
Return Value:
> 0: Continue enumerate the next
= 0: Stop enumerate, but keep the pFI1Base when return from PlotEnumForms
< 0: Stop enumerate, and free pFI1Base memory
the form enumerate will only the one has FI1F_VALID_SIZE bit set in the
flag field, it also call one more time with pFI1 NULL to give the callback
function a chance to free the memory (by return < 0)
Author:
03-Dec-1993 Fri 23:00:25 created
27-Jan-1994 Thu 16:06:00 updated
Fixed the pptOutput which we did not increment the pointer
12-Jul-1994 Tue 12:47:22 updated
Move paper tray checking into the PlotEnumForms() itselft
Revision History:
--*/
{
#define pwOutput ((WORD *)pEFP->pCurForm)
#define pptOutput ((POINT *)pEFP->pCurForm)
#define pwchOutput ((WCHAR *)pEFP->pCurForm)
#define DeviceCap (pEFP->ReqIndex)
if (!pwOutput) {
PLOTASSERT(0, "DevCapEnumFormProc(DevCaps=%ld) pvOutput=NULL",
pwOutput, DeviceCap);
return(0);
}
if (!pFI1) {
//
// extra call, or no pvOutput, return a -1 to free memory for pFI1Base
// We want to add the custom paper size so that application know we
// supports that
//
switch (DeviceCap) {
case DC_PAPERNAMES:
LoadString(hPlotUIModule,
IDS_USERFORM,
pwchOutput,
CCHPAPERNAME);
PLOTDBG(DBG_DEVCAPS_1, ("!!! Extra FormName = %s", pwchOutput));
break;
case DC_PAPERS:
*pwOutput = (WORD)DMPAPER_USER;
PLOTDBG(DBG_DEVCAPS_1, ("!!! Extra FormID = %ld", *pwOutput));
break;
case DC_PAPERSIZE:
//
// I'm not sure we should return POINT or POINTS structure here, what
// is Window 3.1 do, because at here we return as dmPaperWidth and
// dmPaperLength, these fields only as a SHORT (16 bits), we will do
// win32 documentation said, POINT (32-bit version)
//
//
// Return custom paper sizes as 8.5" x 11"
//
pptOutput->x = (LONG)2159;
pptOutput->y = (LONG)2794;
PLOTDBG(DBG_DEVCAPS_1, ("!!! Extra FormSize = %ld x %ld",
pptOutput->x, pptOutput->y));
break;
}
return(-1);
}
switch (DeviceCap) {
case DC_PAPERNAMES:
case DC_MEDIAREADY:
_WCPYSTR(pwchOutput, pFI1->pName, CCHPAPERNAME);
pwchOutput += CCHPAPERNAME;
break;
case DC_PAPERS:
*pwOutput++ = (WORD)(Index + DMPAPER_FIRST);
break;
case DC_PAPERSIZE:
//
// I'm not sure we should return POINT or POINTS structure here, what
// is Window 3.1 do, because at here we return as dmPaperWidth and
// dmPaperLength, these fields only as a SHORT (16 bits), we will do
// win32 documentation said, POINT (32-bit version)
//
pptOutput->x = (LONG)SPLTODM(pFI1->Size.cx);
pptOutput->y = (LONG)SPLTODM(pFI1->Size.cy);
pptOutput++;
break;
}
return(1);
#undef DeviceCap
#undef pwOutput
#undef pptOutput
#undef pwchOutput
}
DWORD
WINAPI
DrvDeviceCapabilities(
HANDLE hPrinter,
LPWSTR pwDeviceName,
WORD DeviceCap,
VOID *pvOutput,
DEVMODE *pDM
)
/*++
Routine Description:
Arguments:
hPrinter - handle the to specific printer.
pwDeviceName - pointer to the device name
DeviceCap - specific capability to get.
pvOutput - Pointer to the output buffer
pDM - Ponter to the input DEVMODE
Return Value:
DWORD depends on the DeviceCap
Author:
02-Dec-1993 Thu 16:50:36 created
05-Jan-1994 Wed 23:35:19 updated
Replace PLOTTER_UNIT_DPI with pPlotGPC->PlotXDPI, pPlotGPC->PlotYDPI,
06-Jan-1994 Thu 13:10:11 updated
Change RasterDPI always be the resoluton reports back to the apps
Revision History:
--*/
{
#define pbOutput ((BYTE *)pvOutput)
#define psOutput ((SHORT *)pvOutput)
#define pwOutput ((WORD *)pvOutput)
#define pptOutput ((POINT *)pvOutput)
#define pwchOutput ((WCHAR *)pvOutput)
#define pdwOutput ((DWORD *)pvOutput)
#define plOutput ((LONG *)pvOutput)
#define pptsdwRet ((POINTS *)&dwRet)
PPRINTERINFO pPI;
ENUMFORMPARAM EnumFormParam;
DWORD dwRet;
ZeroMemory(&EnumFormParam, sizeof(ENUMFORMPARAM));
//
// The MapPrinter will allocate memory, set default devmode, reading and
// validating the GPC then update from current pritner registry, it also
// will cached the PlotGPC.
//
if (!(pPI = MapPrinter(hPrinter,
(PPLOTDEVMODE)pDM,
NULL,
(DeviceCap == DC_MEDIAREADY) ?
MPF_DEVICEDATA : 0))) {
PLOTERR(("DrvDeviceCapabilities: MapPrinter() failed"));
return(GDI_ERROR);
}
//
// Start checking DeviceCap now, set dwRet to 0 first for anything we do
// not support. We can do return() at any point in this function because
// we use cached PI, and it will get destroy when the this module
// get unloaded.
//
EnumFormParam.cMaxOut = 0x7FFFFFFF;
dwRet = 0;
switch (DeviceCap) {
case DC_BINNAMES:
case DC_BINS:
//
// For current plotter, it always only have ONE bin
//
if (pvOutput) {
if (DeviceCap == DC_BINS) {
*pwOutput = DMBIN_ONLYONE;
} else {
if (pPI->pPlotGPC->Flags & PLOTF_ROLLFEED) {
dwRet = IDS_ROLLFEED;
} else {
dwRet = IDS_MAINFEED;
}
LoadString(hPlotUIModule, dwRet, pwchOutput, CCHBINNAME);
}
}
dwRet = 1;
break;
case DC_COPIES:
dwRet = (DWORD)pPI->pPlotGPC->MaxCopies;
break;
case DC_DRIVER:
dwRet = (DWORD)pPI->PlotDM.dm.dmDriverVersion;
break;
case DC_COLLATE:
case DC_DUPLEX:
//
// plotter now have no duplex support or collation support
//
break;
case DC_ENUMRESOLUTIONS:
//
// We only have one resolution setting which will be RasterXDPI and
// RasterYDPI in the GPC data for the raster able plotter, for pen
// plotter now we returned pPlotGPC->PlotXDPI, pPlotGPC->PlotYDPI
//
// The RasterDPI will be used for raster printer resolution, for pen
// plotter this is the GPC's ideal resolution
//
//
// We will return not supported (dwRet=0) so that application will not
// use this to set the DEVMODE's print quality and use the DMRES_XXXX
// as print qualities which is use by us to send to the plotter
//
//
// 26-Mar-1999 Fri 09:43:38 updated
// We will return one pair of current PlotXDPI, PlotYDPI for DS
//
if (pdwOutput) {
if (pPI->pPlotGPC->Flags & PLOTF_RASTER) {
pdwOutput[0] = (DWORD)pPI->pPlotGPC->RasterXDPI;
pdwOutput[1] = (DWORD)pPI->pPlotGPC->RasterYDPI;
} else {
pdwOutput[0] = (DWORD)pPI->pPlotGPC->PlotXDPI;
pdwOutput[1] = (DWORD)pPI->pPlotGPC->PlotYDPI;
}
}
dwRet = 1;
break;
case DC_EXTRA:
dwRet = (DWORD)pPI->PlotDM.dm.dmDriverExtra;
break;
case DC_FIELDS:
dwRet = (DWORD)pPI->PlotDM.dm.dmFields;
break;
case DC_FILEDEPENDENCIES:
//
// we are supposed to fill in an array of 64 character filenames,
// this will include the DataFileName, HelpFileName and UIFileName
// but, if we are to be of any use, we would need to use the
// fully qualified pathnames, and 64 characters is probably not
// enough
if (pwchOutput) {
*pwchOutput = (WCHAR)0;
}
break;
case DC_MAXEXTENT:
//
// This is real problem, the document said that we return a POINT
// structure but a POINT structure here contains 2 LONGs, so for
// Windows 3.1 compatibility reason we return a POINTS structure, if device have
// variable length paper support then return 0x7fff as Window 3.1
// because a maximum positive number in POINTS is 0x7fff, this number
// will actually only allowed us to support the paper length up to
// 10.75 feet.
//
pptsdwRet->x = SPLTODM(pPI->pPlotGPC->DeviceSize.cx);
if (pPI->pPlotGPC->DeviceSize.cy >= 3276700) {
pptsdwRet->y = 0x7fff; // 10.75" maximum.
} else {
pptsdwRet->y = SPLTODM(pPI->pPlotGPC->DeviceSize.cy);
}
break;
case DC_MINEXTENT:
//
// This is real problem, the document said that we return a POINT
// structure but a POINT structure here contains 2 LONGs, so for Win3.1
// compatibility reason we return a POINTS structure
//
pptsdwRet->x = MIN_DM_FORM_CX;
pptsdwRet->y = MIN_DM_FORM_CY;
break;
case DC_ORIENTATION:
//
// We always rotate the page to the left 90 degree from the user's
// perspective
//
dwRet = 90;
break;
case DC_SPL_PAPERNAMES:
if (!pvOutput) {
PLOTERR(("DrvDeviceCapabilities: Spool's DC_PAPERNAMES, pvOutput=NULL"));
dwRet = (DWORD)GDI_ERROR;
break;
}
EnumFormParam.cMaxOut = pdwOutput[0];
DeviceCap = DC_PAPERNAMES;
//
// Fall through
//
case DC_PAPERNAMES:
case DC_PAPERS:
case DC_PAPERSIZE:
//
// One of the problem here is we can cached the FORM_INFO_1 which
// enum through spooler, because in between calls the data could
// changed, such as someone add/delete form through the printman, so
// at here we always free (LocalAlloc() used in PlotEnumForms) the
// memory afterward
//
EnumFormParam.pPlotDM = &(pPI->PlotDM);
EnumFormParam.pPlotGPC = pPI->pPlotGPC;
EnumFormParam.ReqIndex = DeviceCap;
EnumFormParam.pCurForm = (PFORMSIZE)pvOutput;
if (!PlotEnumForms(hPrinter, DevCapEnumFormProc, &EnumFormParam)) {
PLOTERR(("DrvDeviceCapabilities: PlotEnumForms() failed"));
dwRet = GDI_ERROR;
} else {
dwRet = EnumFormParam.ValidCount;
}
break;
case DC_SIZE:
dwRet = (DWORD)pPI->PlotDM.dm.dmSize;
break;
case DC_TRUETYPE:
//
// For now we do not return anything, because we draw truetype font
// as truetype (ie. line/curve segment), if we eventually doing ATM or
// bitmap truetype download then we will return DCFF_BITMAP but for
// now return 0
//
break;
case DC_VERSION:
dwRet = (DWORD)pPI->PlotDM.dm.dmSpecVersion;
break;
case DC_PERSONALITY:
if (pwchOutput) {
//
// DDK says an array of string buffers, each 32 characters in length.
//
_WCPYSTR(pwchOutput, L"HP-GL/2", 32);
}
dwRet = 1;
break;
case DC_COLORDEVICE:
dwRet = (pPI->pPlotGPC->Flags & PLOTF_COLOR) ? 1 : 0;
break;
case DC_SPL_MEDIAREADY:
if (!pwchOutput) {
PLOTERR(("DrvDeviceCapabilities: Spool's DC_MEDIAREADY, pwchOutput=NULL"));
dwRet = (DWORD)GDI_ERROR;
break;
}
EnumFormParam.cMaxOut = pdwOutput[0];
//
// Fall through for DC_MEDIAREADY
//
case DC_MEDIAREADY:
PLOTDBG(DBG_DEVCAPS_0,
("DevCaps(DC_MEDIAREADY:pvOut=%p): CurPaper=%ws, %ldx%ld",
pwchOutput, pPI->CurPaper.Name,
pPI->CurPaper.Size.cx, pPI->CurPaper.Size.cy));
if (pPI->CurPaper.Size.cy) {
//
// Non Roll Paper
//
dwRet = 1;
if (pwchOutput) {
if (EnumFormParam.cMaxOut >= 1) {
_WCPYSTR(pwchOutput, pPI->CurPaper.Name, CCHPAPERNAME);
} else {
dwRet = 0;
}
}
} else {
//
// Roll Paper Installed
//
EnumFormParam.pPlotDM = &(pPI->PlotDM);
EnumFormParam.pPlotGPC = pPI->pPlotGPC;
EnumFormParam.ReqIndex = DC_MEDIAREADY;
EnumFormParam.pCurForm = (PFORMSIZE)pvOutput;
if (!PlotEnumForms(hPrinter, DevCapEnumFormProc, &EnumFormParam)) {
PLOTERR(("DrvDeviceCapabilities: PlotEnumForms() failed"));
dwRet = GDI_ERROR;
} else {
//
// Remove Custom paper size
//
dwRet = EnumFormParam.ValidCount - 1;
}
}
break;
case DC_STAPLE:
case DC_NUP:
break;
default:
//
// something is wrong here
//
PLOTERR(("DrvDeviceCapabilities: Invalid DeviceCap (%ld) passed.",
DeviceCap));
dwRet = (DWORD)GDI_ERROR;
}
PLOTDBG(DBG_DEVCAPS_0,
("DrvDeviceCapabilities: DC_%hs, pvOut=%p, dwRet=%ld",
pDCCaps[DeviceCap-1], (DWORD_PTR)pvOutput, dwRet));
UnMapPrinter(pPI);
return(dwRet);
#undef pbOutput
#undef psOutput
#undef pwOutput
#undef pptOutput
#undef pwchOutput
#undef pdwOutput
#undef plOutput
#undef pptsdwRet
}
DWORD
DrvSplDeviceCaps(
HANDLE hPrinter,
LPWSTR pwDeviceName,
WORD DeviceCap,
VOID *pvOutput,
DWORD cchBuf,
DEVMODE *pDM
)
/*++
Routine Description:
This function supports the querrying of device capabilities.
Arguments:
hPrinter - handle the to specific printer.
pwDeviceName - pointer to the device name
DeviceCap - specific capability to get.
pvOutput - Pointer to the output buffer
cchBuf - Count of character for the pvOutput
pDM - Ponter to the input DEVMODE
Return Value:
DWORD depends on the DeviceCap
Revision History:
--*/
{
switch (DeviceCap) {
case DC_PAPERNAMES:
case DC_MEDIAREADY:
if (pvOutput) {
if (cchBuf >= CCHPAPERNAME) {
DeviceCap = (DeviceCap == DC_PAPERNAMES) ?
DC_SPL_PAPERNAMES :
DC_SPL_MEDIAREADY;
*((LPDWORD)pvOutput) = (DWORD)(cchBuf / CCHPAPERNAME);
PLOTDBG(DBG_DEVCAPS_0,
("SplDeviceCap: DC_SPL_MEDIAREADY, cchBuf=%ld (%ld)",
cchBuf, *((LPDWORD)pvOutput)));
} else {
return(GDI_ERROR);
}
}
return(DrvDeviceCapabilities(hPrinter,
pwDeviceName,
DeviceCap,
pvOutput,
pDM));
break;
default:
return(GDI_ERROR);
}
}