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