|
|
1.1 ! root 1: //-------------------------------------------------------------------------- ! 2: // ! 3: // Module Name: QURYPRNT.C ! 4: // ! 5: // Brief Description: This module contains the PSCRIPT driver's ! 6: // DevQueryPrint routine. ! 7: // ! 8: // Author: Kent Settle (kentse) ! 9: // Created: 01-Apr-1992 ! 10: // ! 11: // Copyright (c) 1992 Microsoft Corporation ! 12: // ! 13: //-------------------------------------------------------------------------- ! 14: ! 15: #include "pscript.h" ! 16: #include "enable.h" ! 17: #include "pscrptui.h" ! 18: #include <winspool.h> ! 19: ! 20: extern PNTPD UIGetNTPD(PWSTR); ! 21: ! 22: PFORM_INFO_1 GetFormsDataBase(HANDLE, DWORD *, PNTPD); ! 23: ! 24: //-------------------------------------------------------------------------- ! 25: // BOOL DevQueryPrint(hPrinter, pDevMode, pResID) ! 26: // HANDLE hPrinter; ! 27: // DEVMODE *pDevMode; ! 28: // DWORD *pResID; ! 29: // ! 30: // This routine determines whether or not the driver can print the ! 31: // job described by pDevMode on the printer described by hPrinter. ! 32: // If if can, it puts zero into pResID. If it cannot, it puts the ! 33: // resource id of the string describing why it could not. ! 34: // ! 35: // This routine returns TRUE for success, FALSE for failure. ! 36: // ! 37: // History: ! 38: // 01-Apr-1992 -by- Kent Settle (kentse) ! 39: // Wrote it. ! 40: //-------------------------------------------------------------------------- ! 41: ! 42: BOOL DevQueryPrint(hPrinter, pDevMode, pResID) ! 43: HANDLE hPrinter; ! 44: DEVMODE *pDevMode; ! 45: DWORD *pResID; ! 46: { ! 47: DWORD count; ! 48: PNTPD pntpd; ! 49: DWORD i; ! 50: PSRESOLUTION *pRes; ! 51: BOOL bFound; ! 52: FORM_INFO_1 *pdbForms, *pdbForm; ! 53: PWSTR pwstrFormName; ! 54: #if DBG ! 55: DWORD *pID; ! 56: #endif ! 57: ! 58: // if we have a NULL pDevMode, then we have nothing to do. ! 59: // the printer will just use defaults. ! 60: ! 61: if (pDevMode == NULL) ! 62: return(TRUE); ! 63: ! 64: // assume everything will work. ! 65: ! 66: *pResID = 0; ! 67: ! 68: if (!(pntpd = MapPrinter(hPrinter))) ! 69: { ! 70: RIP("PSCRPTUI!DevQueryPrinter: MapPrinter failed.\n"); ! 71: return(FALSE); ! 72: } ! 73: ! 74: // verify a bunch of stuff in the DEVMODE structure. ! 75: ! 76: //!!! we should do some kind of version checking, once it has ! 77: //!!! been defined what we should check for. ! 78: #if 0 ! 79: if ((pDevMode->dmSpecVersion != DM_SPECVERSION) || ! 80: (pDevMode->dmDriverVersion != DRIVER_VERSION)) ! 81: { ! 82: *pResID = STRING_BASE + IDS_INVALID_VERSION; ! 83: GlobalFree((HGLOBAL)pntpd); ! 84: return(TRUE); ! 85: } ! 86: #endif ! 87: ! 88: // check the size of the DEVMODE. ! 89: ! 90: if (pDevMode->dmSize != sizeof(DEVMODE)) ! 91: { ! 92: *pResID = STRING_BASE + IDS_INVALID_DEVMODE_SIZE; ! 93: GlobalFree((HGLOBAL)pntpd); ! 94: return(TRUE); ! 95: } ! 96: ! 97: // make sure the user provided a valid orientation. ! 98: ! 99: if ((pDevMode->dmOrientation != DMORIENT_PORTRAIT) && ! 100: (pDevMode->dmOrientation != DMORIENT_LANDSCAPE)) ! 101: { ! 102: *pResID = STRING_BASE + IDS_INVALID_ORIENTATION; ! 103: GlobalFree((HGLOBAL)pntpd); ! 104: return(TRUE); ! 105: } ! 106: ! 107: // when a form is specified in the DEVMODE structure, first search ! 108: // to see if it can be found in the forms database. if it is not ! 109: // found, return that fact to the caller. if it is found, then ! 110: // check to see if the current printer can print on the form. ! 111: ! 112: bFound = FALSE; ! 113: ! 114: // get a pointer to the form name supported by the user. ! 115: ! 116: pwstrFormName = pDevMode->dmFormName; ! 117: ! 118: // now enumerate the forms in the forms database. ! 119: ! 120: if (!(pdbForms = GetFormsDataBase(hPrinter, &count, pntpd))) ! 121: { ! 122: *pResID = STRING_BASE + IDS_INVALID_FORM; ! 123: GlobalFree((HGLOBAL)pntpd); ! 124: return(TRUE); ! 125: } ! 126: else ! 127: { ! 128: // search each form in the database for a matching name, ! 129: // when it has been found, then search the forms supported ! 130: // by the printer to make sure the printer can print it. ! 131: ! 132: pdbForm = pdbForms; ! 133: ! 134: for (i = 0; i < count; i++) ! 135: { ! 136: if (!(wcscmp(pdbForm->pName, pwstrFormName))) ! 137: { ! 138: // we have found the form in the database, ! 139: // now make sure the printer can print it. ! 140: ! 141: if (pdbForm->Flags & PSCRIPT_VALID_FORM) ! 142: { ! 143: bFound = TRUE; ! 144: break; ! 145: } ! 146: } ! 147: ! 148: // search the next form in the database. ! 149: ! 150: pdbForm++; ! 151: } ! 152: ! 153: GlobalFree((HGLOBAL)pdbForms); ! 154: ! 155: if (!bFound) ! 156: { ! 157: *pResID = STRING_BASE + IDS_INVALID_FORM; ! 158: GlobalFree((HGLOBAL)pntpd); ! 159: return(TRUE); ! 160: } ! 161: } ! 162: ! 163: // override the paper size if both the paper length and width ! 164: // fields are set, and the corresponding values are valid. ! 165: ! 166: if ((pDevMode->dmFields & DM_PAPERLENGTH) && ! 167: (pDevMode->dmFields & DM_PAPERWIDTH)) ! 168: { ! 169: if (!pDevMode->dmPaperLength || !pDevMode->dmPaperWidth) ! 170: { ! 171: RIP("PSCRIPT!bValidateSetDEVMODE: invalid scale.\n"); ! 172: SetLastError(ERROR_INVALID_PARAMETER); ! 173: GlobalFree((HGLOBAL)pntpd); ! 174: return(FALSE); ! 175: } ! 176: } ! 177: ! 178: if ((pDevMode->dmScale < MIN_SCALE) || (pDevMode->dmScale > MAX_SCALE)) ! 179: { ! 180: *pResID = STRING_BASE + IDS_INVALID_SCALE; ! 181: GlobalFree((HGLOBAL)pntpd); ! 182: return(TRUE); ! 183: } ! 184: ! 185: // how 'bout a valid number of copies. ! 186: ! 187: if ((pDevMode->dmCopies < MIN_COPIES) || (pDevMode->dmCopies > MAX_COPIES)) ! 188: { ! 189: *pResID = STRING_BASE + IDS_INVALID_NUMBER_OF_COPIES; ! 190: GlobalFree((HGLOBAL)pntpd); ! 191: return(TRUE); ! 192: } ! 193: ! 194: // make sure the user supplied a valid resolution to print with. ! 195: ! 196: // if cResolutions == 0, then only the default resolutions is valid. ! 197: ! 198: bFound = FALSE; ! 199: ! 200: if (pntpd->cResolutions == 0) ! 201: { ! 202: if (pDevMode->dmPrintQuality == (SHORT)pntpd->iDefResolution) ! 203: bFound = TRUE; ! 204: } ! 205: else ! 206: { ! 207: // the current device supports multiple resolutions, so make ! 208: // sure that the user has selected one of them. ! 209: ! 210: pRes = (PSRESOLUTION *)((CHAR *)pntpd + pntpd->loResolution); ! 211: ! 212: for (i = 0; i < pntpd->cResolutions; i++) ! 213: { ! 214: if ((pDevMode->dmPrintQuality == (SHORT)pRes++->iValue)) ! 215: { ! 216: bFound = TRUE; ! 217: break; ! 218: } ! 219: } ! 220: ! 221: } ! 222: ! 223: if (!bFound) ! 224: { ! 225: *pResID = STRING_BASE + IDS_INVALID_RESOLUTION; ! 226: GlobalFree((HGLOBAL)pntpd); ! 227: return(TRUE); ! 228: } ! 229: ! 230: // make sure we have a valid color mode. ! 231: ! 232: if ((pDevMode->dmColor != DMCOLOR_COLOR) && ! 233: (pDevMode->dmColor != DMCOLOR_MONOCHROME)) ! 234: { ! 235: *pResID = STRING_BASE + IDS_INVALID_COLOR; ! 236: GlobalFree((HGLOBAL)pntpd); ! 237: return(TRUE); ! 238: } ! 239: ! 240: // if the user is trying to print color to a b/w ! 241: // printer, let them know. ! 242: ! 243: if ((pDevMode->dmColor == DMCOLOR_COLOR) && ! 244: (!(pntpd->flFlags & COLOR_DEVICE))) ! 245: { ! 246: *pResID = STRING_BASE + IDS_COLOR_ON_BW; ! 247: GlobalFree((HGLOBAL)pntpd); ! 248: return(TRUE); ! 249: } ! 250: ! 251: // make sure we have a valid duplex mode. ! 252: ! 253: if ((pDevMode->dmDuplex != DMDUP_SIMPLEX) && ! 254: (pDevMode->dmDuplex != DMDUP_HORIZONTAL) && ! 255: (pDevMode->dmDuplex != DMDUP_VERTICAL)) ! 256: { ! 257: *pResID = STRING_BASE + IDS_INVALID_DUPLEX; ! 258: GlobalFree((HGLOBAL)pntpd); ! 259: return(TRUE); ! 260: } ! 261: ! 262: // handle the driver specific data. make sure it is ours. ! 263: ! 264: if (pDevMode->dmDriverExtra != 0) ! 265: { ! 266: if (pDevMode->dmDriverExtra != (sizeof(PSDEVMODE) - pDevMode->dmSize)) ! 267: { ! 268: *pResID = STRING_BASE + IDS_INVALID_DRIVER_EXTRA_SIZE; ! 269: GlobalFree((HGLOBAL)pntpd); ! 270: return(TRUE); ! 271: } ! 272: } ! 273: ! 274: // free up the NTPD resource. ! 275: ! 276: #if DBG ! 277: // do a little sanity checking. ! 278: ! 279: pID = (DWORD *)((CHAR *)pntpd + pntpd->cjThis); ! 280: ! 281: ASSERTPS((*pID != DRIVER_ID), ! 282: "PSCRPTUI!NTPD structure overran buffer!!!\n"); ! 283: #endif ! 284: ! 285: GlobalFree((HGLOBAL)pntpd); ! 286: ! 287: return(TRUE); ! 288: } ! 289: ! 290: ! 291: //-------------------------------------------------------------------------- ! 292: // PNTPD MapPrinter(hPrinter) ! 293: // HANDLE hPrinter; ! 294: // ! 295: // This routine takes a handle to a printer and returns a pointer ! 296: // to the memory mapped for the corresponding NTPD structure. ! 297: // ! 298: // This routine returns NULL for failure. ! 299: // ! 300: // History: ! 301: // 15-Apr-1992 -by- Kent Settle (kentse) ! 302: // Wrote it. ! 303: //-------------------------------------------------------------------------- ! 304: ! 305: PNTPD MapPrinter(hPrinter) ! 306: HANDLE hPrinter; ! 307: { ! 308: LPDRIVER_INFO_2 pDriverInfo; ! 309: DWORD cbNeeded; ! 310: PNTPD pntpd; ! 311: ! 312: // Call Winspool to get information on PrinterAlias, such as fully ! 313: // qualified pathname to printer data file. call it once to find ! 314: // how big the DRIVERINFO is for this printer. call it again to ! 315: // fill in the structure. ! 316: ! 317: GetPrinterDriver (hPrinter, NULL, 2, NULL, 0, &cbNeeded); ! 318: ! 319: if (!(pDriverInfo = (LPDRIVER_INFO_2)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, cbNeeded))) ! 320: { ! 321: RIP("PSCRPTUI!MapPrinter: GlobalAlloc for pDriverInfo failed.\n"); ! 322: return((PNTPD)NULL); ! 323: } ! 324: ! 325: if (!GetPrinterDriver (hPrinter, NULL, 2, (LPBYTE)pDriverInfo, ! 326: cbNeeded, &cbNeeded)) ! 327: { ! 328: RIP("PSCRPTUI!MapPrinter: GetPrinterDriver failed.\n"); ! 329: GlobalFree ((HGLOBAL)pDriverInfo); ! 330: return((PNTPD)NULL); ! 331: } ! 332: ! 333: // pDriverInfo now contains everything we need to know about our ! 334: // device, or at least how to get it. the first thing to do is ! 335: // open the .PPD file for the current device. ! 336: ! 337: if (!(pntpd = UIGetNTPD(pDriverInfo->pDataFile))) ! 338: { ! 339: RIP("PSCRPTUI!MapPrinter: MapFile failed.\n"); ! 340: GlobalFree((HGLOBAL)pDriverInfo); ! 341: return((PNTPD)NULL); ! 342: } ! 343: ! 344: // free up memory allocated above. ! 345: ! 346: GlobalFree((HGLOBAL)pDriverInfo); ! 347: ! 348: return(pntpd); ! 349: } ! 350: ! 351: ! 352: //-------------------------------------------------------------------------- ! 353: // PFORM_INFO_1 GetFormsDataBase(hPrinter, pcount, pntpd) ! 354: // HANDLE hPrinter; ! 355: // DWORD *pcount; ! 356: // PNTPD pntpd; ! 357: // ! 358: // This routine takes a handle to a printer, enumerates the forms ! 359: // database, determines which forms are valid for the specified printer, ! 360: // and returns a pointer to an array of PFORM_INFO_1 structures. ! 361: // It also fills in the count of the forms enumerated. ! 362: // ! 363: // This routine returns NULL for failure. ! 364: // ! 365: // History: ! 366: // 21-Apr-1993 -by- Kent Settle (kentse) ! 367: // Made a seperate routine. ! 368: //-------------------------------------------------------------------------- ! 369: ! 370: PFORM_INFO_1 GetFormsDataBase(hPrinter, pcount, pntpd) ! 371: HANDLE hPrinter; ! 372: DWORD *pcount; ! 373: PNTPD pntpd; ! 374: { ! 375: DWORD cbNeeded, count; ! 376: DWORD i, j; ! 377: PFORM_INFO_1 pdbForms, pdbForm; ! 378: PSFORM *pPSForm; ! 379: SIZEL sizlForm, sizlPSForm; ! 380: ! 381: // enumerate all the forms in the forms database. first, pass in a ! 382: // NULL buffer pointer, to get the size of buffer needed. ! 383: ! 384: if (!EnumForms(hPrinter, 1, NULL, 0, &cbNeeded, &count)) ! 385: { ! 386: if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) ! 387: { ! 388: RIP("PSCRPTUI!GetFormsDataBase: 1st EnumForms failed.\n"); ! 389: return((PFORM_INFO_1)NULL); ! 390: } ! 391: } ! 392: ! 393: // now allocate the buffer needed to enumerate all the forms. ! 394: ! 395: if (!(pdbForms = (PFORM_INFO_1)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, ! 396: cbNeeded))) ! 397: { ! 398: RIP("PSCRPTUI!GetFormsDataBase: GlobalAlloc failed.\n"); ! 399: return((PFORM_INFO_1)NULL); ! 400: } ! 401: ! 402: // now get all the forms. ! 403: ! 404: if (!EnumForms(hPrinter, 1, (LPBYTE)pdbForms, cbNeeded, ! 405: &cbNeeded, &count)) ! 406: { ! 407: // something went wrong. let the caller know the enumeration failed. ! 408: ! 409: *pcount = 0; ! 410: GlobalFree((HGLOBAL)pdbForms); ! 411: return((PFORM_INFO_1)NULL); ! 412: } ! 413: ! 414: // we now have a list of all the forms in the database. now determine ! 415: // which are valid for the current printer. ! 416: ! 417: // enumerate each form name. check to see if it is ! 418: // valid for the current printer. mark the high bit of the ! 419: // Flags element of the FORM_INFO_1 structure. ! 420: ! 421: pdbForm = pdbForms; ! 422: ! 423: for (i = 0; i < count; i++) ! 424: { ! 425: sizlForm = pdbForm->Size; ! 426: ! 427: pPSForm = (PSFORM *)((CHAR *)pntpd + pntpd->loPSFORMArray); ! 428: ! 429: // clear the valid form bit. ! 430: ! 431: pdbForm->Flags &= ~PSCRIPT_VALID_FORM; ! 432: ! 433: for (j = 0; j < pntpd->cPSForms; j++) ! 434: { ! 435: // convert the PSFORM sizlPaper from USER to ! 436: // .001mm coordinates. ! 437: ! 438: sizlPSForm.cx = USERTO001MM(pPSForm->sizlPaper.cx); ! 439: sizlPSForm.cy = USERTO001MM(pPSForm->sizlPaper.cy); ! 440: ! 441: // look for each form which matches in size. ! 442: // (within one mm). ! 443: ! 444: if ((sizlForm.cx <= sizlPSForm.cx + 1000) && ! 445: (sizlForm.cx >= sizlPSForm.cx - 1000) && ! 446: (sizlForm.cy <= sizlPSForm.cy + 1000) && ! 447: (sizlForm.cy >= sizlPSForm.cy - 1000)) ! 448: { ! 449: // mark the form as valid for this printer, and update the ! 450: // valid form counter. ! 451: ! 452: pdbForm->Flags |= PSCRIPT_VALID_FORM; ! 453: break; ! 454: } ! 455: ! 456: // point to the next PSFORM. ! 457: ! 458: pPSForm++; ! 459: } ! 460: ! 461: pdbForm++; ! 462: } ! 463: ! 464: // everything must have worked. ! 465: ! 466: *pcount = count; ! 467: return(pdbForms); ! 468: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.