windows-nt/Source/XPSP1/NT/base/mvdm/fax/wowfax/wowfax.c
2020-09-26 16:20:57 +08:00

462 lines
14 KiB
C

//************************************************************************
// Generic Win 3.1 fax printer driver support. 32-bit printer driver
// functions. Runs in the graphics engine context (CSRSS).
//
// History:
// 02-jan-95 nandurir created.
// 01-feb-95 reedb Clean-up, support printer install and bug fixes.
// 14-mar-95 reedb Use GDI hooks to move most functionality to UI.
// 16-aug-95 reedb Move to kernel mode. Debug output and validate
// functions moved from FAXCOMM.C.
//
//************************************************************************
#include "wowfaxdd.h"
//************************************************************************
// Globals
//************************************************************************
DRVFN DrvFnTab[] = {
{INDEX_DrvEnablePDEV, (PFN)DrvEnablePDEV },
{INDEX_DrvDisablePDEV, (PFN)DrvDisablePDEV },
{INDEX_DrvCompletePDEV, (PFN)DrvCompletePDEV },
{INDEX_DrvEnableSurface, (PFN)DrvEnableSurface },
{INDEX_DrvDisableSurface, (PFN)DrvDisableSurface },
{INDEX_DrvStartDoc, (PFN)DrvStartDoc },
{INDEX_DrvStartPage, (PFN)DrvStartPage },
{INDEX_DrvSendPage, (PFN)DrvSendPage },
{INDEX_DrvEndDoc, (PFN)DrvEndDoc },
{INDEX_DrvDitherColor, (PFN)DrvDitherColor },
{INDEX_DrvEscape, (PFN)DrvEscape},
};
#define NO_DRVFN (sizeof(DrvFnTab) / sizeof(DrvFnTab[0]))
#if DBG
//************************************************************************
// faxlogprintf - Driver version of the debug output function.
//
//************************************************************************
VOID faxlogprintf(PCHAR pszFmt, ...)
{
va_list ap;
char buffer[256];
va_start(ap, pszFmt);
EngDebugPrint("", pszFmt, ap);
va_end(ap);
}
#endif
//************************************************************************
// ValidateFaxDev - Validates the FAXDEV structure by checking the DWORD
// signature, which is a known fixed value.
//
//************************************************************************
BOOL ValidateFaxDev(LPFAXDEV lpFaxDev)
{
if (lpFaxDev) {
if (lpFaxDev->id == FAXDEV_ID) {
return TRUE;
}
LOGDEBUG(("ValidateFaxDev failed, bad id, lpFaxDev: %X\n", lpFaxDev));
}
else {
LOGDEBUG(("ValidateFaxDev failed, lpFaxDev: NULL\n"));
}
return FALSE;
}
//************************************************************************
// DllInitProc
//************************************************************************
BOOL DllInitProc(HMODULE hModule, DWORD Reason, PCONTEXT pContext)
{
UNREFERENCED_PARAMETER(hModule);
UNREFERENCED_PARAMETER(Reason);
UNREFERENCED_PARAMETER(pContext);
return TRUE;
}
//***************************************************************************
// DrvEnableDriver
//***************************************************************************
BOOL DrvEnableDriver(ULONG iEngineVersion, ULONG cb, DRVENABLEDATA *pded)
{
LOGDEBUG(("WOWFAX!DrvEnableDriver, iEngineVersion: %X, cb: %X, pded: %X\n", iEngineVersion, cb, pded));
pded->iDriverVersion = DDI_DRIVER_VERSION_NT4;
if (cb < sizeof(DRVENABLEDATA)) {
LOGDEBUG(("WOWFAX!DrvEnableDriver, failed\n"));
return FALSE;
}
pded->c = NO_DRVFN;
pded->pdrvfn = DrvFnTab;
return TRUE;
}
//***************************************************************************
// DrvDisableDriver
//***************************************************************************
VOID DrvDisableDriver(VOID)
{
LOGDEBUG(("WOWFAX!DrvDisableDriver\n"));
return;
}
//***************************************************************************
// DrvEnablePDEV
//***************************************************************************
DHPDEV DrvEnablePDEV(DEVMODEW *pdevmode, // Driver data, Client FAXDEV
PWSTR pwstrPrtName, // Printer's name in CreateDC()
ULONG cPatterns, // Count of standard patterns
HSURF *phsurfPatterns, // Buffer for standard patterns
ULONG cjGdiInfo, // Size of buffer for GdiInfo
ULONG *pulGdiInfo, // Buffer for GDIINFO
ULONG cjDevInfo, // Number of bytes in devinfo
DEVINFO *pdevinfo, // Device info
HDEV hdev,
PWSTR pwstrDeviceName, // Device Name - "LaserJet II"
HANDLE hDriver // Printer handle for spooler access
)
{
LPFAXDEV lpCliFaxDev, lpSrvFaxDev = NULL;
LOGDEBUG(("WOWFAX!DrvEnablePDEV, pdevmode: %X, pwstrPrtName: %S\n", pdevmode, pwstrPrtName));
if (pdevmode) {
// Point to the end of the DEVMODE where the FAXDEV is located.
lpCliFaxDev = (LPFAXDEV) ((PBYTE)pdevmode + pdevmode->dmSize);
// Allocate a server side FAXDEV to be passed back to GDI. Copy the
// client side FAXDEV to the server side FAXDEV. Note all pointers in
// the client FAXDEV reference client side memory and cannot be
// dereferenced on the server side.
lpSrvFaxDev = (LPFAXDEV)EngAllocMem(0, sizeof(FAXDEV), FAXDEV_ID);
LOGDEBUG(("WOWFAX!DrvEnablePDEV, allocated lpSrvFaxDev: %X\n", lpSrvFaxDev));
if (InitPDEV(lpCliFaxDev, lpSrvFaxDev,
cPatterns, phsurfPatterns,
cjGdiInfo, pulGdiInfo,
cjDevInfo, pdevinfo)) {
lpSrvFaxDev->hDriver = hDriver;
return (DHPDEV)lpSrvFaxDev;
}
else {
LOGDEBUG(("WOWFAX!DrvEnablePDEV, failed\n"));
if (lpSrvFaxDev) {
EngFreeMem(lpSrvFaxDev);
lpSrvFaxDev = NULL;
}
}
}
return (DHPDEV)lpSrvFaxDev;
}
//***************************************************************************
// InitPDEV - Called by DrvEnablePDEV and DrvRestartPDEV to initialize the
// server side PDEV/FAXDEV.
//***************************************************************************
BOOL InitPDEV(
LPFAXDEV lpCliFaxDev, // Pointer to the client side FAXDEV
LPFAXDEV lpSrvFaxDev, // Pointer to the server side FAXDEV
ULONG cPatterns, // Count of standard patterns
HSURF *phsurfPatterns, // Buffer for standard patterns
ULONG cjGdiInfo, // Size of buffer for GdiInfo
ULONG *pulGdiInfo, // Buffer for GDIINFO
ULONG cjDevInfo, // Number of bytes in devinfo
DEVINFO *pdevinfo // Device info
)
{
PGDIINFO pgdiinfo = (PGDIINFO)pulGdiInfo;
ULONG uColors[2];
if (!ValidateFaxDev(lpCliFaxDev)) {
return FALSE;
}
// lpSrvFaxDev hasn't been initialized yet, so just check pointer.
if (lpSrvFaxDev == NULL) {
LOGDEBUG(("WOWFAX!InitPDEV, failed, NULL lpSrvFaxDev parameter\n"));
return FALSE;
}
// Copy client FAXDEV to server.
RtlCopyMemory(lpSrvFaxDev, lpCliFaxDev, sizeof(FAXDEV));
// Copy GDIINFO from client FAXDEV to the GDI buffer for GDIINFO.
RtlCopyMemory(pgdiinfo, &(lpCliFaxDev->gdiinfo), sizeof(GDIINFO));
// Initialize the DEVINFO structure.
uColors[0] = RGB(0x00, 0x00, 0x00);
uColors[1] = RGB(0xff, 0xff, 0xff);
pdevinfo->hpalDefault = EngCreatePalette(PAL_INDEXED, 2, uColors, 0, 0, 0);
pdevinfo->iDitherFormat = BMF_1BPP;
// Make sure we don't journal.
pdevinfo->flGraphicsCaps |= GCAPS_DONTJOURNAL;
// Make sure we do dither.
pdevinfo->flGraphicsCaps |= GCAPS_HALFTONE | GCAPS_MONO_DITHER |
GCAPS_COLOR_DITHER;
// Copy the DEVINFO data to the server side FAXDEV.
RtlCopyMemory(&(lpSrvFaxDev->devinfo), pdevinfo, sizeof(DEVINFO));
return TRUE;
}
//***************************************************************************
// DrvCompletePDEV
//***************************************************************************
VOID DrvCompletePDEV(DHPDEV dhpdev, HDEV hdev)
{
LPFAXDEV lpSrvFaxDev = (LPFAXDEV) dhpdev;
LOGDEBUG(("WOWFAX!DrvCompletePDEV, dhpdev %X\n", dhpdev));
if (ValidateFaxDev(lpSrvFaxDev)) {
// Store the gdi handle.
lpSrvFaxDev->hdev = hdev;
}
else {
LOGDEBUG(("WOWFAX!DrvCompletePDEV, failed\n"));
}
return;
}
//***************************************************************************
// DrvDisablePDEV
//***************************************************************************
VOID DrvDisablePDEV(DHPDEV dhpdev)
{
LPFAXDEV lpSrvFaxDev = (LPFAXDEV) dhpdev;
LOGDEBUG(("WOWFAX!DrvDisablePDEV, dhpdev %X\n", dhpdev));
if (ValidateFaxDev(lpSrvFaxDev)) {
if (lpSrvFaxDev->devinfo.hpalDefault) {
EngDeletePalette(lpSrvFaxDev->devinfo.hpalDefault);
}
EngFreeMem(lpSrvFaxDev);
LOGDEBUG(("WOWFAX!DrvDisablePDEV, deallocated lpSrvFaxDev: %X\n", lpSrvFaxDev));
}
else {
LOGDEBUG(("WOWFAX!DrvDisablePDEV, failed\n"));
}
return;
}
//***************************************************************************
// DrvEnableSurface
//***************************************************************************
HSURF DrvEnableSurface(DHPDEV dhpdev)
{
LPFAXDEV lpFaxDev = (LPFAXDEV)dhpdev;
HBITMAP hbm = 0;
LOGDEBUG(("WOWFAX!DrvEnableSurface, lpFaxDev: %X\n", lpFaxDev));
if (ValidateFaxDev(lpFaxDev)) {
// GDI will allocate space for the bitmap bits. We'll use a DrvEscape
// to copy them to the client side.
hbm = EngCreateBitmap(lpFaxDev->gdiinfo.szlPhysSize,
lpFaxDev->bmWidthBytes,
lpFaxDev->bmFormat, BMF_TOPDOWN, NULL);
if (hbm) {
lpFaxDev->hbm = hbm;
EngAssociateSurface((HSURF)hbm, lpFaxDev->hdev, 0);
return (HSURF)hbm;
}
LOGDEBUG(("WOWFAX!DrvEnableSurface, EngCreateBitmap failed\n"));
}
return (HSURF)hbm;
}
//***************************************************************************
// DrvDisableSurface
//***************************************************************************
VOID DrvDisableSurface(
DHPDEV dhpdev
)
{
LPFAXDEV lpFaxDev = (LPFAXDEV)dhpdev;
LOGDEBUG(("WOWFAX!DrvDisableSurface, lpFaxDev: %X\n", lpFaxDev));
if (ValidateFaxDev(lpFaxDev)) {
if (lpFaxDev->hbm) {
EngDeleteSurface((HSURF)lpFaxDev->hbm);
lpFaxDev->hbm = 0;
return;
}
}
return;
}
//***************************************************************************
// DrvStartDoc
//***************************************************************************
BOOL DrvStartDoc(
SURFOBJ *pso,
PWSTR pwszDocName,
DWORD dwJobId
)
{
LOGDEBUG(("WOWFAX!DrvStartDoc, pso: %X, pwszDocName: %S, dwJobId: %X\n", pso, pwszDocName, dwJobId));
return TRUE;
}
//***************************************************************************
// DrvStartPage
//***************************************************************************
BOOL DrvStartPage(
SURFOBJ *pso
)
{
LPFAXDEV lpFaxDev = (LPFAXDEV)pso->dhpdev;
BITMAP bm;
RECTL rc;
LOGDEBUG(("WOWFAX!DrvStartPage, pso: %X\n", pso));
// Calculate the size of the rectangle based on the input data
// in 'pso' - this will ensure that the entire bitmap is erased.
if (ValidateFaxDev(lpFaxDev)) {
rc.left = 0;
rc.top = 0;
rc.right = pso->lDelta * lpFaxDev->cPixPerByte;
rc.bottom = pso->cjBits / pso->lDelta;
EngEraseSurface(pso, &rc, COLOR_INDEX_WHITE);
return TRUE;
}
return FALSE;
}
//***************************************************************************
// DrvSendPage
//***************************************************************************
BOOL DrvSendPage(SURFOBJ *pso)
{
LOGDEBUG(("WOWFAX!DrvSendPage, pso %X\n", pso));
return TRUE;
}
//***************************************************************************
// DrvEndDoc
//***************************************************************************
BOOL DrvEndDoc(SURFOBJ *pso, FLONG fl)
{
LOGDEBUG(("WOWFAX!DrvEndDoc, pso %X\n", pso));
return TRUE;
}
ULONG
DrvDitherColor(
DHPDEV dhpdev,
ULONG iMode,
ULONG rgbColor,
ULONG *pulDither
)
{
return DCR_HALFTONE;
}
//***************************************************************************
// DrvEscape - Allows client side to get server side data.
//***************************************************************************
ULONG DrvEscape(
SURFOBJ *pso,
ULONG iEsc,
ULONG cjIn,
PVOID *pvIn,
ULONG cjOut,
PVOID *pvOut
)
{
LPFAXDEV lpSrvFaxDev;
ULONG ulRet = 0;
LOGDEBUG(("WOWFAX!DrvEscape, pso %X, iEsc: %X\n", pso, iEsc));
if (pso) {
lpSrvFaxDev = (LPFAXDEV)pso->dhpdev;
if (ValidateFaxDev(lpSrvFaxDev)) {
LOGDEBUG(("WOWFAX!DrvEscape, lpSrvFaxDev: %X\n", lpSrvFaxDev));
switch (iEsc) {
case DRV_ESC_GET_DEVMODE_PTR:
return (ULONG) lpSrvFaxDev->pdevmode;
case DRV_ESC_GET_FAXDEV_PTR:
return (ULONG) lpSrvFaxDev->lpClient;
case DRV_ESC_GET_SURF_INFO:
if (pvOut) {
if (cjOut == sizeof(LONG)) {
(LONG) *pvOut = pso->lDelta;
return (ULONG) pso->cjBits;
}
}
break;
case DRV_ESC_GET_BITMAP_BITS:
// Validate the buffer pointer and copy the bits.
if (pvOut) {
if (cjOut == pso->cjBits) {
RtlCopyMemory(pvOut, pso->pvBits, cjOut);
return cjOut;
}
LOGDEBUG(("WOWFAX!DrvEscape, bitmap size mismatch cjIn: %X, pso->cjBits: %X\n", cjIn, pso->cjBits));
}
break;
// default:
LOGDEBUG(("WOWFAX!DrvEscape, unknown escape: %X\n", iEsc));
} //switch
}
}
LOGDEBUG(("WOWFAX!DrvEscape, failed\n"));
return ulRet;
}