|
|
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.