Sample Code
Windows Driver Samples/ MSPLOT Plotter Driver Sample/ C++/ plotui/ devcaps.c/
/*++ 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_FILL_TRAIL_WITH_NULL(pwchOutput, CCHPAPERNAME, pFI1->pName); 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 } _Use_decl_annotations_ DWORD WINAPI #pragma prefast(suppress:6101, "For certain values of DeviceCap, *pvOutput is not used.") 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; UNREFERENCED_PARAMETER(pwDeviceName); 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; } #pragma prefast(suppress: 17000 __WARNING_WRITE_OVERRUN, "By design limit of the DeviceCapabilities API. String buffer lengths are fixed.") 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) { // // Output buffer sized assumed to be at least 32 since // DrvDeviceCapabilities does not pass in the buffer size. // DDK says an array of string buffers, each 32 characters in length. _WCPYSTR_FILL_TRAIL_WITH_NULL(pwchOutput, 32, L"HP-GL/2"); } 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_FILL_TRAIL_WITH_NULL(pwchOutput, CCHPAPERNAME, pPI->CurPaper.Name); } 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; } #ifdef DBG if ( (DeviceCap > 0 ) && (DeviceCap <= ARRAYSIZE(pDCCaps) ) ) { PLOTDBG(DBG_DEVCAPS_0, ("DrvDeviceCapabilities: DC_%hs, pvOut=%p, dwRet=%ld", pDCCaps[DeviceCap-1], (DWORD_PTR)pvOutput, dwRet)); } #endif UnMapPrinter(pPI); return(dwRet); #undef pbOutput #undef psOutput #undef pwOutput #undef pptOutput #undef pwchOutput #undef pdwOutput #undef plOutput #undef pptsdwRet } _Use_decl_annotations_ 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); } }
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials