1 /*
2 * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "awt.h"
27
28 #include "stdhdrs.h"
29 #include <commdlg.h>
30 #include <winspool.h>
31 #include <limits.h>
32 #include <float.h>
33
34 #include "awt_Toolkit.h"
35 #include "awt_PrintControl.h"
36
37 /* values for parameter "type" of XXX_getJobStatus() */
38 #define GETJOBCOUNT 1
39 #define ACCEPTJOB 2
40
41 static const char *HPRINTER_STR = "hPrintJob";
42
43 /* constants for DeviceCapability buffer lengths */
44 #define PAPERNAME_LENGTH 64
45 #define TRAYNAME_LENGTH 24
46
47
IsSupportedLevel(HANDLE hPrinter,DWORD dwLevel)48 static BOOL IsSupportedLevel(HANDLE hPrinter, DWORD dwLevel) {
49 BOOL isSupported = FALSE;
50 DWORD cbBuf = 0;
51 LPBYTE pPrinter = NULL;
52
53 DASSERT(hPrinter != NULL);
54
55 VERIFY(::GetPrinter(hPrinter, dwLevel, NULL, 0, &cbBuf) == 0);
56 if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
57 pPrinter = new BYTE[cbBuf];
58 if (::GetPrinter(hPrinter, dwLevel, pPrinter, cbBuf, &cbBuf)) {
59 isSupported = TRUE;
60 }
61 delete[] pPrinter;
62 }
63
64 return isSupported;
65 }
66
67
68 extern "C" {
69
70 JNIEXPORT jstring JNICALL
Java_sun_print_PrintServiceLookupProvider_getDefaultPrinterName(JNIEnv * env,jobject peer)71 Java_sun_print_PrintServiceLookupProvider_getDefaultPrinterName(JNIEnv *env,
72 jobject peer)
73 {
74 TRY;
75
76 TCHAR cBuffer[250];
77 OSVERSIONINFO osv;
78 PRINTER_INFO_2 *ppi2 = NULL;
79 DWORD dwNeeded = 0;
80 DWORD dwReturned = 0;
81 LPTSTR pPrinterName = NULL;
82 jstring jPrinterName;
83
84 // What version of Windows are you running?
85 osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
86 GetVersionEx(&osv);
87
88 // If Windows 2000, XP, Vista
89 if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT) {
90
91 // Retrieve the default string from Win.ini (the registry).
92 // String will be in form "printername,drivername,portname".
93
94 if (GetProfileString(TEXT("windows"), TEXT("device"), TEXT(",,,"),
95 cBuffer, 250) <= 0) {
96 return NULL;
97 }
98 // Copy printer name into passed-in buffer...
99 int index = 0;
100 int len = lstrlen(cBuffer);
101 while ((index < len) && cBuffer[index] != _T(',')) {
102 index++;
103 }
104 if (index==0) {
105 return NULL;
106 }
107
108 pPrinterName = (LPTSTR)GlobalAlloc(GPTR, (index+1)*sizeof(TCHAR));
109 lstrcpyn(pPrinterName, cBuffer, index+1);
110 jPrinterName = JNU_NewStringPlatform(env, pPrinterName);
111 GlobalFree(pPrinterName);
112 return jPrinterName;
113 } else {
114 return NULL;
115 }
116
117 CATCH_BAD_ALLOC_RET(NULL);
118 }
119
120
getPrinterNames(JNIEnv * env,DWORD flags)121 static jobjectArray getPrinterNames(JNIEnv *env, DWORD flags) {
122 TRY;
123
124 DWORD cbNeeded = 0;
125 DWORD cReturned = 0;
126 LPBYTE pPrinterEnum = NULL;
127
128 jstring utf_str;
129 jclass clazz = env->FindClass("java/lang/String");
130 if (clazz == NULL) {
131 return NULL;
132 }
133 jobjectArray nameArray;
134
135 try {
136 ::EnumPrinters(flags,
137 NULL, 4, NULL, 0, &cbNeeded, &cReturned);
138 pPrinterEnum = new BYTE[cbNeeded];
139 ::EnumPrinters(flags,
140 NULL, 4, pPrinterEnum, cbNeeded, &cbNeeded,
141 &cReturned);
142
143 if (cReturned > 0) {
144 nameArray = env->NewObjectArray(cReturned, clazz, NULL);
145 if (nameArray == NULL) {
146 throw std::bad_alloc();
147 }
148 } else {
149 nameArray = NULL;
150 }
151
152
153 for (DWORD i = 0; i < cReturned; i++) {
154 PRINTER_INFO_4 *info4 = (PRINTER_INFO_4 *)
155 (pPrinterEnum + i * sizeof(PRINTER_INFO_4));
156 utf_str = JNU_NewStringPlatform(env, info4->pPrinterName);
157 if (utf_str == NULL) {
158 throw std::bad_alloc();
159 }
160 env->SetObjectArrayElement(nameArray, i, utf_str);
161 env->DeleteLocalRef(utf_str);
162 }
163 } catch (std::bad_alloc&) {
164 delete [] pPrinterEnum;
165 throw;
166 }
167
168 delete [] pPrinterEnum;
169 return nameArray;
170
171 CATCH_BAD_ALLOC_RET(NULL);
172 }
173
174 JNIEXPORT jobjectArray JNICALL
Java_sun_print_PrintServiceLookupProvider_getAllPrinterNames(JNIEnv * env,jobject peer)175 Java_sun_print_PrintServiceLookupProvider_getAllPrinterNames(JNIEnv *env,
176 jobject peer)
177 {
178 return getPrinterNames(env, PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS);
179 }
180
181 JNIEXPORT jobjectArray JNICALL
Java_sun_print_PrintServiceLookupProvider_getRemotePrintersNames(JNIEnv * env,jobject peer)182 Java_sun_print_PrintServiceLookupProvider_getRemotePrintersNames(JNIEnv *env,
183 jobject peer)
184 {
185 return getPrinterNames(env, PRINTER_ENUM_CONNECTIONS);
186 }
187
188
189 JNIEXPORT jlong JNICALL
Java_sun_print_PrintServiceLookupProvider_notifyFirstPrinterChange(JNIEnv * env,jobject peer,jstring printer)190 Java_sun_print_PrintServiceLookupProvider_notifyFirstPrinterChange(JNIEnv *env,
191 jobject peer,
192 jstring printer) {
193 HANDLE hPrinter;
194
195 LPTSTR printerName = NULL;
196 if (printer != NULL) {
197 printerName = (LPTSTR)JNU_GetStringPlatformChars(env,
198 printer,
199 NULL);
200 JNU_ReleaseStringPlatformChars(env, printer, printerName);
201 }
202
203 // printerName - "Win NT/2K/XP: If NULL, it indicates the local printer
204 // server" - MSDN. Win9x : OpenPrinter returns 0.
205 BOOL ret = OpenPrinter(printerName, &hPrinter, NULL);
206 if (!ret) {
207 return (jlong)-1;
208 }
209
210 // PRINTER_CHANGE_PRINTER = PRINTER_CHANGE_ADD_PRINTER |
211 // PRINTER_CHANGE_SET_PRINTER |
212 // PRINTER_CHANGE_DELETE_PRINTER |
213 // PRINTER_CHANGE_FAILED_CONNECTION_PRINTER
214 HANDLE chgObj = FindFirstPrinterChangeNotification(hPrinter,
215 PRINTER_CHANGE_PRINTER,
216 0,
217 NULL);
218 return (chgObj == INVALID_HANDLE_VALUE) ? (jlong)-1 : (jlong)chgObj;
219 }
220
221
222
223 JNIEXPORT void JNICALL
Java_sun_print_PrintServiceLookupProvider_notifyClosePrinterChange(JNIEnv * env,jobject peer,jlong chgObject)224 Java_sun_print_PrintServiceLookupProvider_notifyClosePrinterChange(JNIEnv *env,
225 jobject peer,
226 jlong chgObject) {
227 FindClosePrinterChangeNotification((HANDLE)chgObject);
228 }
229
230
231 JNIEXPORT jint JNICALL
Java_sun_print_PrintServiceLookupProvider_notifyPrinterChange(JNIEnv * env,jobject peer,jlong chgObject)232 Java_sun_print_PrintServiceLookupProvider_notifyPrinterChange(JNIEnv *env,
233 jobject peer,
234 jlong chgObject) {
235 DWORD dwChange;
236
237 DWORD ret = WaitForSingleObject((HANDLE)chgObject, INFINITE);
238 if (ret == WAIT_OBJECT_0) {
239 return(FindNextPrinterChangeNotification((HANDLE)chgObject,
240 &dwChange, NULL, NULL));
241 } else {
242 return 0;
243 }
244 }
245
246
247 JNIEXPORT jfloatArray JNICALL
Java_sun_print_Win32PrintService_getMediaPrintableArea(JNIEnv * env,jobject peer,jstring printer,jint papersize)248 Java_sun_print_Win32PrintService_getMediaPrintableArea(JNIEnv *env,
249 jobject peer,
250 jstring printer,
251 jint papersize)
252 {
253 TRY;
254
255 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env,
256 printer, NULL);
257 if (printerName == NULL) {
258 return NULL;
259 }
260
261 jfloatArray printableArray = NULL;
262
263 SAVE_CONTROLWORD
264 HDC pdc = CreateDC(TEXT("WINSPOOL"), printerName, NULL, NULL);
265 RESTORE_CONTROLWORD
266 if (pdc) {
267 HANDLE hPrinter;
268 /* Start by opening the printer */
269 if (!::OpenPrinter(printerName, &hPrinter, NULL)) {
270 JNU_ReleaseStringPlatformChars(env, printer, printerName);
271 return printableArray;
272 }
273
274 PDEVMODE pDevMode;
275
276 if (!AwtPrintControl::getDevmode(hPrinter, printerName, &pDevMode)) {
277 /* if failure, cleanup and return failure */
278
279 if (pDevMode != NULL) {
280 ::GlobalFree(pDevMode);
281 }
282 DeleteDC(pdc);
283 ::ClosePrinter(hPrinter);
284 JNU_ReleaseStringPlatformChars(env, printer, printerName);
285 return printableArray;
286 }
287
288 pDevMode->dmFields |= (DM_PAPERSIZE | DM_ORIENTATION);
289 pDevMode->dmPaperSize = (short)papersize;
290 pDevMode->dmOrientation = DMORIENT_PORTRAIT;
291 ::ResetDC(pdc, pDevMode);
292 RESTORE_CONTROLWORD
293
294 int left = GetDeviceCaps(pdc, PHYSICALOFFSETX);
295 int top = GetDeviceCaps(pdc, PHYSICALOFFSETY);
296 int width = GetDeviceCaps(pdc, HORZRES);
297 int height = GetDeviceCaps(pdc, VERTRES);
298
299 int resx = GetDeviceCaps(pdc, LOGPIXELSX);
300 int resy = GetDeviceCaps(pdc, LOGPIXELSY);
301
302 printableArray=env->NewFloatArray(4);
303 if (printableArray != NULL) {
304 jfloat *iPrintables =
305 env->GetFloatArrayElements(printableArray, NULL);
306 if (iPrintables != NULL) {
307 iPrintables[0] = (float)left/resx;
308 iPrintables[1] = (float)top/resy;
309 iPrintables[2] = (float)width/resx;
310 iPrintables[3] = (float)height/resy;
311 env->ReleaseFloatArrayElements(printableArray, iPrintables, 0);
312 }
313 }
314 GlobalFree(pDevMode);
315 DeleteDC(pdc);
316 }
317
318 JNU_ReleaseStringPlatformChars(env, printer, printerName);
319
320 return printableArray;
321
322 CATCH_BAD_ALLOC_RET(NULL);
323 }
324
getIDs(JNIEnv * env,jstring printer,jstring port,int dm_id)325 jintArray getIDs(JNIEnv *env, jstring printer, jstring port, int dm_id)
326 {
327
328 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
329 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
330
331 if (printerName == NULL || printerPort == NULL) {
332 if (printerName != NULL) {
333 JNU_ReleaseStringPlatformChars(env, printer, printerName);
334 }
335 if (printerPort != NULL) {
336 JNU_ReleaseStringPlatformChars(env, port, printerPort);
337 }
338 return NULL;
339 }
340
341 SAVE_CONTROLWORD
342 int numIDs = ::DeviceCapabilities(printerName, printerPort, dm_id,
343 NULL, NULL);
344 RESTORE_CONTROLWORD
345
346 jintArray idArray = NULL;
347 if (numIDs > 0) {
348 idArray = env->NewIntArray(numIDs);
349 if (idArray != NULL) {
350 jint *jpcIndices = env->GetIntArrayElements(idArray, NULL);
351 if (jpcIndices != NULL) {
352 jint *saveFormats = jpcIndices;
353 LPTSTR buf = NULL;
354 try {
355 buf = (LPTSTR)new char[numIDs * sizeof(WORD)];
356 } catch (std::bad_alloc&) {
357 buf = NULL;
358 }
359 if (buf != NULL) {
360 if (::DeviceCapabilities(printerName, printerPort,
361 dm_id, buf, NULL) != -1) {
362 WORD *id = (WORD *)buf;
363 for (int i = 0; i < numIDs; i++, id++) {
364 jpcIndices[i] = *id;
365 }
366 }
367 RESTORE_CONTROLWORD
368 delete[] buf;
369 }
370 env->ReleaseIntArrayElements(idArray, saveFormats, 0);
371 }
372 }
373 }
374
375 JNU_ReleaseStringPlatformChars(env, printer, printerName);
376 JNU_ReleaseStringPlatformChars(env, port, printerPort);
377 return idArray;
378 }
379
380 JNIEXPORT jintArray JNICALL
Java_sun_print_Win32PrintService_getAllMediaIDs(JNIEnv * env,jobject peer,jstring printer,jstring port)381 Java_sun_print_Win32PrintService_getAllMediaIDs(JNIEnv *env,
382 jobject peer,
383 jstring printer,
384 jstring port)
385 {
386 return getIDs(env, printer, port, DC_PAPERS);
387 }
388
389
390 JNIEXPORT jintArray JNICALL
Java_sun_print_Win32PrintService_getAllMediaTrays(JNIEnv * env,jobject peer,jstring printer,jstring port)391 Java_sun_print_Win32PrintService_getAllMediaTrays(JNIEnv *env,
392 jobject peer,
393 jstring printer,
394 jstring port)
395 {
396 return getIDs(env, printer, port, DC_BINS);
397 }
398
399
400 JNIEXPORT jintArray JNICALL
Java_sun_print_Win32PrintService_getAllMediaSizes(JNIEnv * env,jobject peer,jstring printer,jstring port)401 Java_sun_print_Win32PrintService_getAllMediaSizes(JNIEnv *env,
402 jobject peer,
403 jstring printer,
404 jstring port)
405 {
406 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
407 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
408
409 if (printerName == NULL || printerPort == NULL) {
410 if (printerName != NULL) {
411 JNU_ReleaseStringPlatformChars(env, printer, printerName);
412 }
413 if (printerPort != NULL) {
414 JNU_ReleaseStringPlatformChars(env, port, printerPort);
415 }
416 return NULL;
417 }
418
419 SAVE_CONTROLWORD
420 int nPapers = ::DeviceCapabilities(printerName, printerPort, DC_PAPERSIZE,
421 NULL, NULL) ;
422 RESTORE_CONTROLWORD
423
424 jintArray mediaArray = NULL;
425 jint *saveFormats = NULL;
426
427 if (nPapers > 0) {
428 mediaArray = env->NewIntArray(nPapers*2);
429 if (mediaArray != NULL) {
430 jint *jpcIndices = env->GetIntArrayElements(mediaArray, NULL);
431 if (jpcIndices != NULL) {
432 saveFormats = jpcIndices;
433 LPTSTR buf = NULL;
434 try {
435 buf = (LPTSTR)new char[nPapers * sizeof(POINT)];
436 } catch (std::bad_alloc&) {
437 buf = NULL;
438 }
439 if (buf != NULL) {
440 if (::DeviceCapabilities(printerName, printerPort,
441 DC_PAPERSIZE, buf, NULL) != -1) {
442 POINT *pDim = (POINT *)buf;
443 for (int i = 0; i < nPapers; i++) {
444 jpcIndices[i*2] = (pDim+i)->x;
445 jpcIndices[i*2+1] = (pDim+i)->y;
446 }
447 }
448 RESTORE_CONTROLWORD
449 delete[] buf;
450 }
451 env->ReleaseIntArrayElements(mediaArray, saveFormats, 0);
452 saveFormats = NULL;
453 }
454 }
455 }
456
457 JNU_ReleaseStringPlatformChars(env, printer, printerName);
458 JNU_ReleaseStringPlatformChars(env, port, printerPort);
459 if (mediaArray != NULL && saveFormats != NULL) {
460 env->ReleaseIntArrayElements(mediaArray, saveFormats, 0);
461 }
462 return mediaArray;
463
464 }
465
466
getAllDCNames(JNIEnv * env,jobject peer,jstring printer,jstring port,unsigned int dc_id,unsigned int buf_len)467 jobjectArray getAllDCNames(JNIEnv *env, jobject peer, jstring printer,
468 jstring port, unsigned int dc_id, unsigned int buf_len)
469 {
470
471 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
472 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
473
474 if (printerName == NULL || printerPort == NULL) {
475 if (printerName != NULL) {
476 JNU_ReleaseStringPlatformChars(env, printer, printerName);
477 }
478 if (printerPort != NULL) {
479 JNU_ReleaseStringPlatformChars(env, port, printerPort);
480 }
481 return NULL;
482 }
483
484 jstring utf_str;
485 jobjectArray names = NULL;
486 LPTSTR buf = NULL;
487 SAVE_CONTROLWORD
488 int cReturned = ::DeviceCapabilities(printerName, printerPort,
489 dc_id, NULL, NULL);
490 RESTORE_CONTROLWORD
491 if (cReturned <= 0) {
492 JNU_ReleaseStringPlatformChars(env, printer, printerName);
493 JNU_ReleaseStringPlatformChars(env, port, printerPort);
494 return NULL;
495 }
496
497 try {
498 buf = (LPTSTR)new char[cReturned * buf_len * sizeof(TCHAR)];
499 } catch (std::bad_alloc&) {
500 buf = NULL;
501 }
502 if (buf == NULL) {
503 JNU_ReleaseStringPlatformChars(env, printer, printerName);
504 JNU_ReleaseStringPlatformChars(env, port, printerPort);
505 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
506 return NULL;
507 }
508
509 cReturned = ::DeviceCapabilities(printerName, printerPort,
510 dc_id, buf, NULL);
511 RESTORE_CONTROLWORD
512
513 JNU_ReleaseStringPlatformChars(env, printer, printerName);
514 JNU_ReleaseStringPlatformChars(env, port, printerPort);
515
516 if (cReturned > 0) {
517 jclass cls = env->FindClass("java/lang/String");
518 if (cls != NULL) {
519 names = env->NewObjectArray(cReturned, cls, NULL);
520 }
521 if (names == NULL || cls == NULL) {
522 delete[] buf;
523 return names;
524 }
525
526 for (int i = 0; i < cReturned; i++) {
527 utf_str = JNU_NewStringPlatform(env, buf+(buf_len*i));
528 if (utf_str == NULL) {
529 delete[] buf;
530 return names;
531 }
532 env->SetObjectArrayElement(names, i, utf_str);
533 env->DeleteLocalRef(utf_str);
534 }
535 }
536 delete[] buf;
537 return names;
538
539 }
540
541
542 JNIEXPORT jobjectArray JNICALL
Java_sun_print_Win32PrintService_getAllMediaNames(JNIEnv * env,jobject peer,jstring printer,jstring port)543 Java_sun_print_Win32PrintService_getAllMediaNames(JNIEnv *env,
544 jobject peer,
545 jstring printer,
546 jstring port)
547 {
548 return getAllDCNames(env, peer, printer, port, DC_PAPERNAMES, PAPERNAME_LENGTH);
549 }
550
551
552 JNIEXPORT jobjectArray JNICALL
Java_sun_print_Win32PrintService_getAllMediaTrayNames(JNIEnv * env,jobject peer,jstring printer,jstring port)553 Java_sun_print_Win32PrintService_getAllMediaTrayNames(JNIEnv *env,
554 jobject peer,
555 jstring printer,
556 jstring port)
557 {
558 return getAllDCNames(env, peer, printer, port, DC_BINNAMES, TRAYNAME_LENGTH);
559 }
560
561
562 JNIEXPORT jint JNICALL
Java_sun_print_Win32PrintService_getCopiesSupported(JNIEnv * env,jobject peer,jstring printer,jstring port)563 Java_sun_print_Win32PrintService_getCopiesSupported(JNIEnv *env,
564 jobject peer,
565 jstring printer,
566 jstring port)
567 {
568 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
569 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
570
571 if (printerName == NULL || printerPort == NULL) {
572 if (printerName != NULL) {
573 JNU_ReleaseStringPlatformChars(env, printer, printerName);
574 }
575 if (printerPort != NULL) {
576 JNU_ReleaseStringPlatformChars(env, port, printerPort);
577 }
578 return 1;
579 }
580
581 SAVE_CONTROLWORD
582 int numCopies = ::DeviceCapabilities(printerName, printerPort,
583 DC_COPIES, NULL, NULL);
584 RESTORE_CONTROLWORD
585
586 if (numCopies == -1)
587 return 1; // default
588
589 JNU_ReleaseStringPlatformChars(env, printer, printerName);
590 JNU_ReleaseStringPlatformChars(env, port, printerPort);
591
592 return numCopies;
593 }
594
595
596 /*
597 PostScript Drivers return wrong support info for the following code:
598
599 DWORD dmFields = (::DeviceCapabilities(printerName,
600 NULL, DC_FIELDS, NULL, NULL)) ;
601
602 if ((dmFields & DM_YRESOLUTION) )
603 isSupported = true;
604
605 Returns not supported even if it supports resolution. Therefore, we use the
606 function _getAllResolutions.
607 */
608 JNIEXPORT jintArray JNICALL
Java_sun_print_Win32PrintService_getAllResolutions(JNIEnv * env,jobject peer,jstring printer,jstring port)609 Java_sun_print_Win32PrintService_getAllResolutions(JNIEnv *env,
610 jobject peer,
611 jstring printer,
612 jstring port)
613 {
614 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
615 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
616
617 if (printerName == NULL || printerPort == NULL) {
618 if (printerName != NULL) {
619 JNU_ReleaseStringPlatformChars(env, printer, printerName);
620 }
621 if (printerPort != NULL) {
622 JNU_ReleaseStringPlatformChars(env, port, printerPort);
623 }
624 return NULL;
625 }
626
627 SAVE_CONTROLWORD
628 int nResolutions = ::DeviceCapabilities(printerName, printerPort,
629 DC_ENUMRESOLUTIONS, NULL, NULL);
630 RESTORE_CONTROLWORD
631
632 jintArray resolutionArray = NULL;
633 if (nResolutions > 0) {
634 resolutionArray = env->NewIntArray(nResolutions*2);
635 if (resolutionArray != NULL) {
636 jint *jpcIndices = env->GetIntArrayElements(resolutionArray, NULL);
637 if (jpcIndices != NULL) {
638 jint *saveFormats = jpcIndices;
639 LPTSTR resBuf = NULL;
640 try {
641 resBuf = (LPTSTR)new char[nResolutions * sizeof(LONG) * 2];
642 } catch (std::bad_alloc&) {
643 resBuf = NULL;
644 }
645 if (resBuf != NULL) {
646 if (::DeviceCapabilities(printerName, printerPort,
647 DC_ENUMRESOLUTIONS, resBuf,
648 NULL) != -1) {
649 LONG *pResolution = (LONG *)resBuf;
650 for (int i = 0; i < nResolutions; i++) {
651 jpcIndices[i*2] = *pResolution++;
652 jpcIndices[i*2+1] = *pResolution++;
653 }
654 }
655 RESTORE_CONTROLWORD
656 delete[] resBuf;
657 }
658 env->ReleaseIntArrayElements(resolutionArray, saveFormats, 0);
659 }
660 }
661 }
662
663 JNU_ReleaseStringPlatformChars(env, printer, printerName);
664 JNU_ReleaseStringPlatformChars(env, printer, printerPort);
665 return resolutionArray;
666 }
667
668
IsDCPostscript(HDC hDC)669 static BOOL IsDCPostscript( HDC hDC )
670 {
671 int nEscapeCode;
672 CHAR szTechnology[MAX_PATH] = "";
673
674 // If it supports POSTSCRIPT_PASSTHROUGH, it must be PS.
675 nEscapeCode = POSTSCRIPT_PASSTHROUGH;
676 if( ::ExtEscape( hDC, QUERYESCSUPPORT, sizeof(int),
677 (LPCSTR)&nEscapeCode, 0, NULL ) > 0 )
678 return TRUE;
679
680 // If it doesn't support GETTECHNOLOGY, we won't be able to tell.
681 nEscapeCode = GETTECHNOLOGY;
682 if( ::ExtEscape( hDC, QUERYESCSUPPORT, sizeof(int),
683 (LPCSTR)&nEscapeCode, 0, NULL ) <= 0 )
684 return FALSE;
685
686 // Get the technology string and check if the word "postscript" is in it.
687 if( ::ExtEscape( hDC, GETTECHNOLOGY, 0, NULL, MAX_PATH,
688 (LPSTR)szTechnology ) <= 0 )
689 return FALSE;
690 _strupr_s(szTechnology, MAX_PATH);
691 if(!strstr( szTechnology, "POSTSCRIPT" ) == NULL )
692 return TRUE;
693
694 // The word "postscript" was not found and it didn't support
695 // POSTSCRIPT_PASSTHROUGH, so it's not a PS printer.
696 return FALSE;
697 }
698
699
700 JNIEXPORT jstring JNICALL
Java_sun_print_Win32PrintService_getPrinterPort(JNIEnv * env,jobject peer,jstring printer)701 Java_sun_print_Win32PrintService_getPrinterPort(JNIEnv *env,
702 jobject peer,
703 jstring printer)
704 {
705
706 if (printer == NULL) {
707 return NULL;
708 }
709
710 jstring jPort;
711 LPTSTR printerName = NULL, printerPort = TEXT("LPT1");
712 LPBYTE buffer = NULL;
713 DWORD cbBuf = 0;
714
715 try {
716 VERIFY(AwtPrintControl::FindPrinter(NULL, NULL, &cbBuf, NULL, NULL));
717 buffer = new BYTE[cbBuf];
718 AwtPrintControl::FindPrinter(printer, buffer, &cbBuf,
719 &printerName, &printerPort);
720 } catch (std::bad_alloc&) {
721 delete [] buffer;
722 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
723 return NULL;
724 }
725
726 if (printerPort == NULL) {
727 printerPort = TEXT("LPT1");
728 }
729 jPort = JNU_NewStringPlatform(env, printerPort);
730 delete [] buffer;
731 return jPort;
732
733 }
734
735
736 JNIEXPORT jint JNICALL
Java_sun_print_Win32PrintService_getCapabilities(JNIEnv * env,jobject peer,jstring printer,jstring port)737 Java_sun_print_Win32PrintService_getCapabilities(JNIEnv *env,
738 jobject peer,
739 jstring printer,
740 jstring port)
741 {
742 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
743 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
744
745 if (printerName == NULL || printerPort == NULL) {
746 if (printerName != NULL) {
747 JNU_ReleaseStringPlatformChars(env, printer, printerName);
748 }
749 if (printerPort != NULL) {
750 JNU_ReleaseStringPlatformChars(env, port, printerPort);
751 }
752 return NULL;
753 }
754
755 // 0x1000 is a flag to indicate that getCapabilities has already been called.
756 // 0x0001 is a flag for color support and supported is the default.
757 jint ret = 0x1001;
758 DWORD dmFields;
759
760 // get Duplex
761 SAVE_CONTROLWORD
762 DWORD isDuplex = (::DeviceCapabilities(printerName, printerPort,
763 DC_DUPLEX, NULL, NULL)) ;
764
765 /*
766 Check if duplexer is installed either physically or manually thru the
767 printer setting dialog by checking if DM_DUPLEX is set.
768 */
769 dmFields = (::DeviceCapabilities(printerName, printerPort,
770 DC_FIELDS, NULL, NULL)) ;
771
772 if ((dmFields & DM_DUPLEX) && isDuplex) {
773 ret |= 0x0002;
774 }
775
776 // get Collation
777 if ((dmFields & DM_COLLATE) ) {
778 ret |= 0x0004;
779 }
780
781 // get Print Quality
782 if ((dmFields & DM_PRINTQUALITY) ) {
783 ret |= 0x0008;
784 }
785
786 HDC pdc = CreateDC(TEXT("WINSPOOL"), printerName, NULL, NULL);
787 if (pdc != NULL) {
788 // get Color
789 int bpp = GetDeviceCaps(pdc, BITSPIXEL);
790 int nColors = GetDeviceCaps(pdc, NUMCOLORS);
791
792 if (!(dmFields & DM_COLOR) || ((bpp == 1)
793 && ((nColors == 2) || (nColors == 256)))) {
794 ret &= ~0x0001;
795 }
796
797 // check support for PostScript
798 if (IsDCPostscript(pdc)) {
799 ret |= 0x0010;
800 }
801
802 DeleteDC(pdc);
803 }
804
805 RESTORE_CONTROLWORD
806 JNU_ReleaseStringPlatformChars(env, printer, printerName);
807 JNU_ReleaseStringPlatformChars(env, printer, printerPort);
808 return ret;
809 }
810
811
812 #define GETDEFAULT_ERROR -50
813 #define NDEFAULT 9
814
815 JNIEXPORT jintArray JNICALL
Java_sun_print_Win32PrintService_getDefaultSettings(JNIEnv * env,jobject peer,jstring printer,jstring port)816 Java_sun_print_Win32PrintService_getDefaultSettings(JNIEnv *env,
817 jobject peer,
818 jstring printer,
819 jstring port)
820 {
821 HANDLE hPrinter;
822 LPDEVMODE pDevMode = NULL;
823
824 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
825 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
826
827 if (printerName == NULL || printerPort == NULL) {
828 if (printerName != NULL) {
829 JNU_ReleaseStringPlatformChars(env, printer, printerName);
830 }
831 if (printerPort != NULL) {
832 JNU_ReleaseStringPlatformChars(env, port, printerPort);
833 }
834 return NULL;
835 }
836
837 jint* defIndices = NULL;
838 jintArray defaultArray = env->NewIntArray(NDEFAULT);
839 if (defaultArray != NULL) {
840 defIndices = env->GetIntArrayElements(defaultArray, NULL);
841 }
842 if (defIndices == NULL) {
843 JNU_ReleaseStringPlatformChars(env, printer, printerName);
844 JNU_ReleaseStringPlatformChars(env, port, printerPort);
845 return NULL;
846 }
847
848 jint *saveFormats = defIndices;
849
850 for (int i=0; i < NDEFAULT; i++) {
851 defIndices[i] = GETDEFAULT_ERROR;
852 }
853
854 /* Start by opening the printer */
855 if (!::OpenPrinter(printerName, &hPrinter, NULL)) {
856 env->ReleaseIntArrayElements(defaultArray, saveFormats, 0);
857 JNU_ReleaseStringPlatformChars(env, printer, printerName);
858 JNU_ReleaseStringPlatformChars(env, port, printerPort);
859 return defaultArray;
860 }
861
862 if (!AwtPrintControl::getDevmode(hPrinter, printerName, &pDevMode)) {
863 /* if failure, cleanup and return failure */
864 if (pDevMode != NULL) {
865 ::GlobalFree(pDevMode);
866 }
867 ::ClosePrinter(hPrinter);
868 env->ReleaseIntArrayElements(defaultArray, saveFormats, 0);
869 JNU_ReleaseStringPlatformChars(env, printer, printerName);
870 JNU_ReleaseStringPlatformChars(env, port, printerPort);
871 return defaultArray;
872 }
873
874 /* Have seen one driver which reports a default paper id which is not
875 * one of their supported paper ids. If what is returned is not
876 * a supported paper, use one of the supported sizes instead.
877 *
878 */
879 if (pDevMode->dmFields & DM_PAPERSIZE) {
880 defIndices[0] = pDevMode->dmPaperSize;
881
882 SAVE_CONTROLWORD
883
884 int numSizes = ::DeviceCapabilities(printerName, printerPort,
885 DC_PAPERS, NULL, NULL);
886 if (numSizes > 0) {
887 LPTSTR papers;
888 try {
889 papers = (LPTSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, numSizes, sizeof(WORD));
890 } catch (const std::bad_alloc&) {
891 papers = NULL;
892 }
893
894 if (papers != NULL &&
895 ::DeviceCapabilities(printerName, printerPort,
896 DC_PAPERS, papers, NULL) != -1) {
897 int present = 0;
898 for (int i=0;i<numSizes;i++) {
899 if (papers[i] == pDevMode->dmPaperSize) {
900 present = 1;
901 }
902 }
903 if (!present) {
904 defIndices[0] = papers[0];
905 }
906 }
907 // If DeviceCapabilities fails, then also free paper allocation
908 if (papers != NULL) {
909 free((char*)papers);
910 }
911 }
912 RESTORE_CONTROLWORD
913 }
914
915 if (pDevMode->dmFields & DM_MEDIATYPE) {
916 defIndices[1] = pDevMode->dmMediaType;
917 }
918
919 /*
920 * For some printer like Brother HL-2240D series
921 * pDevMode->dmYResolution is not set in pDevMode->dmFields
922 * even though pDevMode->dmYResolution is populated
923 * via ::DocumentProperties API, so for this case
924 * we populate the resolution index in default array
925 */
926 if (pDevMode->dmFields & DM_YRESOLUTION || pDevMode->dmYResolution > 0) {
927 defIndices[2] = pDevMode->dmYResolution;
928 }
929
930 /*
931 * For some printer like Brother HL-2240D series
932 * pDevMode->dmPrintQuality is not set in pDevMode->dmFields
933 * even though pDevMode->dmPrintQuality is populated
934 * via ::DocumentProperties API, so for this case
935 * we populate the print quality index in default array
936 */
937 if (pDevMode->dmFields & DM_PRINTQUALITY || pDevMode->dmPrintQuality != 0) {
938 defIndices[3] = pDevMode->dmPrintQuality;
939 }
940
941 if (pDevMode->dmFields & DM_COPIES) {
942 defIndices[4] = pDevMode->dmCopies;
943 }
944
945 if (pDevMode->dmFields & DM_ORIENTATION) {
946 defIndices[5] = pDevMode->dmOrientation;
947 }
948
949 if (pDevMode->dmFields & DM_DUPLEX) {
950 defIndices[6] = pDevMode->dmDuplex;
951 }
952
953 if (pDevMode->dmFields & DM_COLLATE) {
954 defIndices[7] = pDevMode->dmCollate;
955 }
956
957 if (pDevMode->dmFields & DM_COLOR) {
958 defIndices[8] = pDevMode->dmColor;
959 }
960
961 GlobalFree(pDevMode);
962 ::ClosePrinter(hPrinter);
963
964 env->ReleaseIntArrayElements(defaultArray, saveFormats, 0);
965
966 JNU_ReleaseStringPlatformChars(env, printer, printerName);
967 JNU_ReleaseStringPlatformChars(env, port, printerPort);
968
969 return defaultArray;
970 }
971
972
973 JNIEXPORT jint JNICALL
Java_sun_print_Win32PrintService_getJobStatus(JNIEnv * env,jobject peer,jstring printer,jint type)974 Java_sun_print_Win32PrintService_getJobStatus(JNIEnv *env,
975 jobject peer,
976 jstring printer,
977 jint type)
978 {
979 HANDLE hPrinter;
980 DWORD cByteNeeded;
981 DWORD cByteUsed;
982 PRINTER_INFO_2 *pPrinterInfo = NULL;
983 int ret=0;
984
985 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
986 if (printerName == NULL) {
987 return -1;
988 }
989
990 // Start by opening the printer
991 if (!::OpenPrinter(printerName, &hPrinter, NULL)) {
992 JNU_ReleaseStringPlatformChars(env, printer, printerName);
993 return -1;
994 }
995
996 if (!::GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded)) {
997 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
998 ::ClosePrinter(hPrinter);
999 JNU_ReleaseStringPlatformChars(env, printer, printerName);
1000 return -1;
1001 }
1002 }
1003
1004 pPrinterInfo = (PRINTER_INFO_2 *)::GlobalAlloc(GPTR, cByteNeeded);
1005 if (!(pPrinterInfo)) {
1006 /* failure to allocate memory */
1007 ::ClosePrinter(hPrinter);
1008 JNU_ReleaseStringPlatformChars(env, printer, printerName);
1009 return -1;
1010 }
1011
1012 /* get the printer info */
1013 if (!::GetPrinter(hPrinter,
1014 2,
1015 (LPBYTE)pPrinterInfo,
1016 cByteNeeded,
1017 &cByteUsed))
1018 {
1019 /* failure to access the printer */
1020 ::GlobalFree(pPrinterInfo);
1021 pPrinterInfo = NULL;
1022 ::ClosePrinter(hPrinter);
1023 JNU_ReleaseStringPlatformChars(env, printer, printerName);
1024 return -1;
1025 }
1026
1027 if (type == GETJOBCOUNT) {
1028 ret = pPrinterInfo->cJobs;
1029 } else if (type == ACCEPTJOB) {
1030 if (pPrinterInfo->Status & PRINTER_STATUS_PENDING_DELETION) {
1031 ret = 0;
1032 }
1033 else {
1034 ret = 1;
1035 }
1036 }
1037
1038 ::GlobalFree(pPrinterInfo);
1039 ::ClosePrinter(hPrinter);
1040 JNU_ReleaseStringPlatformChars(env, printer, printerName);
1041 return ret;
1042 }
1043
1044
getIdOfLongField(JNIEnv * env,jobject self,const char * fieldName)1045 static jfieldID getIdOfLongField(JNIEnv *env, jobject self,
1046 const char *fieldName) {
1047 jclass myClass = env->GetObjectClass(self);
1048 jfieldID fieldId = env->GetFieldID(myClass, fieldName, "J");
1049 DASSERT(fieldId != 0);
1050 return fieldId;
1051 }
1052
1053
getHPrinter(JNIEnv * env,jobject self)1054 static inline HANDLE getHPrinter(JNIEnv *env, jobject self) {
1055 jfieldID fieldId = getIdOfLongField(env, self, HPRINTER_STR);
1056 if (fieldId == (jfieldID)0) {
1057 return (HANDLE)NULL;
1058 }
1059 return (HANDLE)(env->GetLongField(self, fieldId));
1060 }
1061
1062
1063 JNIEXPORT jboolean JNICALL
Java_sun_print_Win32PrintJob_startPrintRawData(JNIEnv * env,jobject peer,jstring printer,jstring jobname)1064 Java_sun_print_Win32PrintJob_startPrintRawData(JNIEnv *env,
1065 jobject peer,
1066 jstring printer,
1067 jstring jobname)
1068 {
1069 HANDLE hPrinter;
1070 DOC_INFO_1 DocInfo;
1071 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
1072 if (printerName == NULL) {
1073 return false;
1074 }
1075 DASSERT(jobname != NULL);
1076 LPTSTR lpJobName = (LPTSTR)JNU_GetStringPlatformChars(env, jobname, NULL);
1077 LPTSTR jname = _tcsdup(lpJobName);
1078 JNU_ReleaseStringPlatformChars(env, jobname, lpJobName);
1079
1080 // Start by opening the printer
1081 if (!::OpenPrinter(printerName, &hPrinter, NULL)) {
1082 JNU_ReleaseStringPlatformChars(env, printer, printerName);
1083 free((LPTSTR)jname);
1084 return false;
1085 }
1086
1087 JNU_ReleaseStringPlatformChars(env, printer, printerName);
1088
1089 // Fill in the structure with info about this "document."
1090 DocInfo.pDocName = jname;
1091 DocInfo.pOutputFile = NULL;
1092 DocInfo.pDatatype = TEXT("RAW");
1093
1094 // Inform the spooler the document is beginning.
1095 if( (::StartDocPrinter(hPrinter, 1, (LPBYTE)&DocInfo)) == 0 ) {
1096 ::ClosePrinter( hPrinter );
1097 free((LPTSTR)jname);
1098 return false;
1099 }
1100
1101 free((LPTSTR)jname);
1102
1103 // Start a page.
1104 if( ! ::StartPagePrinter( hPrinter ) ) {
1105 ::EndDocPrinter( hPrinter );
1106 ::ClosePrinter( hPrinter );
1107 return false;
1108 }
1109
1110 // store handle
1111 jfieldID fieldId = getIdOfLongField(env, peer, HPRINTER_STR);
1112 if (fieldId == (jfieldID)0) {
1113 return false;
1114 } else {
1115 env->SetLongField(peer, fieldId, reinterpret_cast<jlong>(hPrinter));
1116 return true;
1117 }
1118 }
1119
1120
1121 JNIEXPORT jboolean JNICALL
Java_sun_print_Win32PrintJob_printRawData(JNIEnv * env,jobject peer,jbyteArray dataArray,jint count)1122 Java_sun_print_Win32PrintJob_printRawData(JNIEnv *env,
1123 jobject peer,
1124 jbyteArray dataArray,
1125 jint count)
1126 {
1127 jboolean ret=true;
1128 jint dwBytesWritten;
1129 jbyte* data = NULL;
1130
1131 // retrieve handle
1132 HANDLE hPrinter = getHPrinter(env, peer);
1133 if (hPrinter == NULL) {
1134 return false;
1135 }
1136
1137 try {
1138 data=(jbyte *)env->GetPrimitiveArrayCritical(dataArray, 0);
1139 if (data == NULL) {
1140 return false;
1141 }
1142
1143 // Send the data to the printer.
1144 if( ! ::WritePrinter(hPrinter, data, count,(LPDWORD)&dwBytesWritten)) {
1145 env->ReleasePrimitiveArrayCritical(dataArray, data, 0);
1146 return false;
1147 }
1148
1149 // Check to see if correct number of bytes were written.
1150 if( dwBytesWritten != count ) {
1151 ret = false;
1152 }
1153
1154 } catch (...) {
1155 if (data != NULL) {
1156 env->ReleasePrimitiveArrayCritical(dataArray, data, 0);
1157 }
1158 JNU_ThrowInternalError(env, "Problem in Win32PrintJob_printRawData");
1159 return false;
1160 }
1161
1162 env->ReleasePrimitiveArrayCritical(dataArray, data, 0);
1163 return ret;
1164 }
1165
1166
1167 JNIEXPORT jboolean JNICALL
Java_sun_print_Win32PrintJob_endPrintRawData(JNIEnv * env,jobject peer)1168 Java_sun_print_Win32PrintJob_endPrintRawData(JNIEnv *env,
1169 jobject peer)
1170 {
1171 // retrieve handle
1172 HANDLE hPrinter = getHPrinter(env, peer);
1173 if (hPrinter == NULL) {
1174 return false;
1175 }
1176
1177 if ((::EndPagePrinter(hPrinter) != 0) &&
1178 (::EndDocPrinter(hPrinter) != 0) &&
1179 (::ClosePrinter(hPrinter) != 0)) {
1180 return true;
1181 } else {
1182 return false;
1183 }
1184 }
1185
1186 } /* extern "C" */
1187