|
|
/*++
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); }
}
|