1 /* 2 * Copyright (c) 2000, 2020, 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 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 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 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 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 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 190 Java_sun_print_PrintServiceLookupProvider_notifyFirstPrinterChange(JNIEnv *env, 191 jobject peer) { 192 HANDLE hPrinter; 193 LPTSTR printerName = NULL; // NULL indicates the local printer server 194 BOOL ret = OpenPrinter(printerName, &hPrinter, NULL); 195 if (!ret) { 196 return (jlong)-1; 197 } 198 199 // PRINTER_CHANGE_PRINTER = PRINTER_CHANGE_ADD_PRINTER | 200 // PRINTER_CHANGE_SET_PRINTER | 201 // PRINTER_CHANGE_DELETE_PRINTER | 202 // PRINTER_CHANGE_FAILED_CONNECTION_PRINTER 203 HANDLE chgObj = FindFirstPrinterChangeNotification(hPrinter, 204 PRINTER_CHANGE_PRINTER, 205 0, 206 NULL); 207 return (chgObj == INVALID_HANDLE_VALUE) ? (jlong)-1 : (jlong)chgObj; 208 } 209 210 211 212 JNIEXPORT void JNICALL 213 Java_sun_print_PrintServiceLookupProvider_notifyClosePrinterChange(JNIEnv *env, 214 jobject peer, 215 jlong chgObject) { 216 FindClosePrinterChangeNotification((HANDLE)chgObject); 217 } 218 219 220 JNIEXPORT jint JNICALL 221 Java_sun_print_PrintServiceLookupProvider_notifyPrinterChange(JNIEnv *env, 222 jobject peer, 223 jlong chgObject) { 224 DWORD dwChange; 225 226 DWORD ret = WaitForSingleObject((HANDLE)chgObject, INFINITE); 227 if (ret == WAIT_OBJECT_0) { 228 return(FindNextPrinterChangeNotification((HANDLE)chgObject, 229 &dwChange, NULL, NULL)); 230 } else { 231 return 0; 232 } 233 } 234 235 236 JNIEXPORT jfloatArray JNICALL 237 Java_sun_print_Win32PrintService_getMediaPrintableArea(JNIEnv *env, 238 jobject peer, 239 jstring printer, 240 jint papersize) 241 { 242 TRY; 243 244 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, 245 printer, NULL); 246 if (printerName == NULL) { 247 return NULL; 248 } 249 250 jfloatArray printableArray = NULL; 251 252 SAVE_CONTROLWORD 253 HDC pdc = CreateDC(TEXT("WINSPOOL"), printerName, NULL, NULL); 254 RESTORE_CONTROLWORD 255 if (pdc) { 256 HANDLE hPrinter; 257 /* Start by opening the printer */ 258 if (!::OpenPrinter(printerName, &hPrinter, NULL)) { 259 JNU_ReleaseStringPlatformChars(env, printer, printerName); 260 return printableArray; 261 } 262 263 PDEVMODE pDevMode; 264 265 if (!AwtPrintControl::getDevmode(hPrinter, printerName, &pDevMode)) { 266 /* if failure, cleanup and return failure */ 267 268 if (pDevMode != NULL) { 269 ::GlobalFree(pDevMode); 270 } 271 DeleteDC(pdc); 272 ::ClosePrinter(hPrinter); 273 JNU_ReleaseStringPlatformChars(env, printer, printerName); 274 return printableArray; 275 } 276 277 pDevMode->dmFields |= (DM_PAPERSIZE | DM_ORIENTATION); 278 pDevMode->dmPaperSize = (short)papersize; 279 pDevMode->dmOrientation = DMORIENT_PORTRAIT; 280 ::ResetDC(pdc, pDevMode); 281 RESTORE_CONTROLWORD 282 283 int left = GetDeviceCaps(pdc, PHYSICALOFFSETX); 284 int top = GetDeviceCaps(pdc, PHYSICALOFFSETY); 285 int width = GetDeviceCaps(pdc, HORZRES); 286 int height = GetDeviceCaps(pdc, VERTRES); 287 288 int resx = GetDeviceCaps(pdc, LOGPIXELSX); 289 int resy = GetDeviceCaps(pdc, LOGPIXELSY); 290 291 printableArray=env->NewFloatArray(4); 292 if (printableArray != NULL) { 293 jfloat *iPrintables = 294 env->GetFloatArrayElements(printableArray, NULL); 295 if (iPrintables != NULL) { 296 iPrintables[0] = (float)left/resx; 297 iPrintables[1] = (float)top/resy; 298 iPrintables[2] = (float)width/resx; 299 iPrintables[3] = (float)height/resy; 300 env->ReleaseFloatArrayElements(printableArray, iPrintables, 0); 301 } 302 } 303 GlobalFree(pDevMode); 304 DeleteDC(pdc); 305 } 306 307 JNU_ReleaseStringPlatformChars(env, printer, printerName); 308 309 return printableArray; 310 311 CATCH_BAD_ALLOC_RET(NULL); 312 } 313 314 jintArray getIDs(JNIEnv *env, jstring printer, jstring port, int dm_id) 315 { 316 317 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); 318 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); 319 320 if (printerName == NULL || printerPort == NULL) { 321 if (printerName != NULL) { 322 JNU_ReleaseStringPlatformChars(env, printer, printerName); 323 } 324 if (printerPort != NULL) { 325 JNU_ReleaseStringPlatformChars(env, port, printerPort); 326 } 327 return NULL; 328 } 329 330 SAVE_CONTROLWORD 331 int numIDs = ::DeviceCapabilities(printerName, printerPort, dm_id, 332 NULL, NULL); 333 RESTORE_CONTROLWORD 334 335 jintArray idArray = NULL; 336 if (numIDs > 0) { 337 idArray = env->NewIntArray(numIDs); 338 if (idArray != NULL) { 339 jint *jpcIndices = env->GetIntArrayElements(idArray, NULL); 340 if (jpcIndices != NULL) { 341 jint *saveFormats = jpcIndices; 342 LPTSTR buf = NULL; 343 try { 344 buf = (LPTSTR)new char[numIDs * sizeof(WORD)]; 345 } catch (std::bad_alloc&) { 346 buf = NULL; 347 } 348 if (buf != NULL) { 349 if (::DeviceCapabilities(printerName, printerPort, 350 dm_id, buf, NULL) != -1) { 351 WORD *id = (WORD *)buf; 352 for (int i = 0; i < numIDs; i++, id++) { 353 jpcIndices[i] = *id; 354 } 355 } 356 RESTORE_CONTROLWORD 357 delete[] buf; 358 } 359 env->ReleaseIntArrayElements(idArray, saveFormats, 0); 360 } 361 } 362 } 363 364 JNU_ReleaseStringPlatformChars(env, printer, printerName); 365 JNU_ReleaseStringPlatformChars(env, port, printerPort); 366 return idArray; 367 } 368 369 JNIEXPORT jintArray JNICALL 370 Java_sun_print_Win32PrintService_getAllMediaIDs(JNIEnv *env, 371 jobject peer, 372 jstring printer, 373 jstring port) 374 { 375 return getIDs(env, printer, port, DC_PAPERS); 376 } 377 378 379 JNIEXPORT jintArray JNICALL 380 Java_sun_print_Win32PrintService_getAllMediaTrays(JNIEnv *env, 381 jobject peer, 382 jstring printer, 383 jstring port) 384 { 385 return getIDs(env, printer, port, DC_BINS); 386 } 387 388 389 JNIEXPORT jintArray JNICALL 390 Java_sun_print_Win32PrintService_getAllMediaSizes(JNIEnv *env, 391 jobject peer, 392 jstring printer, 393 jstring port) 394 { 395 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); 396 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); 397 398 if (printerName == NULL || printerPort == NULL) { 399 if (printerName != NULL) { 400 JNU_ReleaseStringPlatformChars(env, printer, printerName); 401 } 402 if (printerPort != NULL) { 403 JNU_ReleaseStringPlatformChars(env, port, printerPort); 404 } 405 return NULL; 406 } 407 408 SAVE_CONTROLWORD 409 int nPapers = ::DeviceCapabilities(printerName, printerPort, DC_PAPERSIZE, 410 NULL, NULL) ; 411 RESTORE_CONTROLWORD 412 413 jintArray mediaArray = NULL; 414 jint *saveFormats = NULL; 415 416 if (nPapers > 0) { 417 mediaArray = env->NewIntArray(nPapers*2); 418 if (mediaArray != NULL) { 419 jint *jpcIndices = env->GetIntArrayElements(mediaArray, NULL); 420 if (jpcIndices != NULL) { 421 saveFormats = jpcIndices; 422 LPTSTR buf = NULL; 423 try { 424 buf = (LPTSTR)new char[nPapers * sizeof(POINT)]; 425 } catch (std::bad_alloc&) { 426 buf = NULL; 427 } 428 if (buf != NULL) { 429 if (::DeviceCapabilities(printerName, printerPort, 430 DC_PAPERSIZE, buf, NULL) != -1) { 431 POINT *pDim = (POINT *)buf; 432 for (int i = 0; i < nPapers; i++) { 433 jpcIndices[i*2] = (pDim+i)->x; 434 jpcIndices[i*2+1] = (pDim+i)->y; 435 } 436 } 437 RESTORE_CONTROLWORD 438 delete[] buf; 439 } 440 env->ReleaseIntArrayElements(mediaArray, saveFormats, 0); 441 saveFormats = NULL; 442 } 443 } 444 } 445 446 JNU_ReleaseStringPlatformChars(env, printer, printerName); 447 JNU_ReleaseStringPlatformChars(env, port, printerPort); 448 if (mediaArray != NULL && saveFormats != NULL) { 449 env->ReleaseIntArrayElements(mediaArray, saveFormats, 0); 450 } 451 return mediaArray; 452 453 } 454 455 456 jobjectArray getAllDCNames(JNIEnv *env, jobject peer, jstring printer, 457 jstring port, unsigned int dc_id, unsigned int buf_len) 458 { 459 460 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); 461 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); 462 463 if (printerName == NULL || printerPort == NULL) { 464 if (printerName != NULL) { 465 JNU_ReleaseStringPlatformChars(env, printer, printerName); 466 } 467 if (printerPort != NULL) { 468 JNU_ReleaseStringPlatformChars(env, port, printerPort); 469 } 470 return NULL; 471 } 472 473 jstring utf_str; 474 jobjectArray names = NULL; 475 LPTSTR buf = NULL; 476 SAVE_CONTROLWORD 477 int cReturned = ::DeviceCapabilities(printerName, printerPort, 478 dc_id, NULL, NULL); 479 RESTORE_CONTROLWORD 480 if (cReturned <= 0) { 481 JNU_ReleaseStringPlatformChars(env, printer, printerName); 482 JNU_ReleaseStringPlatformChars(env, port, printerPort); 483 return NULL; 484 } 485 486 try { 487 buf = (LPTSTR)new char[cReturned * buf_len * sizeof(TCHAR)]; 488 } catch (std::bad_alloc&) { 489 buf = NULL; 490 } 491 if (buf == NULL) { 492 JNU_ReleaseStringPlatformChars(env, printer, printerName); 493 JNU_ReleaseStringPlatformChars(env, port, printerPort); 494 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); 495 return NULL; 496 } 497 498 cReturned = ::DeviceCapabilities(printerName, printerPort, 499 dc_id, buf, NULL); 500 RESTORE_CONTROLWORD 501 502 JNU_ReleaseStringPlatformChars(env, printer, printerName); 503 JNU_ReleaseStringPlatformChars(env, port, printerPort); 504 505 if (cReturned > 0) { 506 jclass cls = env->FindClass("java/lang/String"); 507 if (cls != NULL) { 508 names = env->NewObjectArray(cReturned, cls, NULL); 509 } 510 if (names == NULL || cls == NULL) { 511 delete[] buf; 512 return names; 513 } 514 515 for (int i = 0; i < cReturned; i++) { 516 utf_str = JNU_NewStringPlatform(env, buf+(buf_len*i)); 517 if (utf_str == NULL) { 518 delete[] buf; 519 return names; 520 } 521 env->SetObjectArrayElement(names, i, utf_str); 522 env->DeleteLocalRef(utf_str); 523 } 524 } 525 delete[] buf; 526 return names; 527 528 } 529 530 531 JNIEXPORT jobjectArray JNICALL 532 Java_sun_print_Win32PrintService_getAllMediaNames(JNIEnv *env, 533 jobject peer, 534 jstring printer, 535 jstring port) 536 { 537 return getAllDCNames(env, peer, printer, port, DC_PAPERNAMES, PAPERNAME_LENGTH); 538 } 539 540 541 JNIEXPORT jobjectArray JNICALL 542 Java_sun_print_Win32PrintService_getAllMediaTrayNames(JNIEnv *env, 543 jobject peer, 544 jstring printer, 545 jstring port) 546 { 547 return getAllDCNames(env, peer, printer, port, DC_BINNAMES, TRAYNAME_LENGTH); 548 } 549 550 551 JNIEXPORT jint JNICALL 552 Java_sun_print_Win32PrintService_getCopiesSupported(JNIEnv *env, 553 jobject peer, 554 jstring printer, 555 jstring port) 556 { 557 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); 558 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); 559 560 if (printerName == NULL || printerPort == NULL) { 561 if (printerName != NULL) { 562 JNU_ReleaseStringPlatformChars(env, printer, printerName); 563 } 564 if (printerPort != NULL) { 565 JNU_ReleaseStringPlatformChars(env, port, printerPort); 566 } 567 return 1; 568 } 569 570 SAVE_CONTROLWORD 571 int numCopies = ::DeviceCapabilities(printerName, printerPort, 572 DC_COPIES, NULL, NULL); 573 RESTORE_CONTROLWORD 574 575 if (numCopies == -1) 576 return 1; // default 577 578 JNU_ReleaseStringPlatformChars(env, printer, printerName); 579 JNU_ReleaseStringPlatformChars(env, port, printerPort); 580 581 return numCopies; 582 } 583 584 585 /* 586 PostScript Drivers return wrong support info for the following code: 587 588 DWORD dmFields = (::DeviceCapabilities(printerName, 589 NULL, DC_FIELDS, NULL, NULL)) ; 590 591 if ((dmFields & DM_YRESOLUTION) ) 592 isSupported = true; 593 594 Returns not supported even if it supports resolution. Therefore, we use the 595 function _getAllResolutions. 596 */ 597 JNIEXPORT jintArray JNICALL 598 Java_sun_print_Win32PrintService_getAllResolutions(JNIEnv *env, 599 jobject peer, 600 jstring printer, 601 jstring port) 602 { 603 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); 604 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); 605 606 if (printerName == NULL || printerPort == NULL) { 607 if (printerName != NULL) { 608 JNU_ReleaseStringPlatformChars(env, printer, printerName); 609 } 610 if (printerPort != NULL) { 611 JNU_ReleaseStringPlatformChars(env, port, printerPort); 612 } 613 return NULL; 614 } 615 616 SAVE_CONTROLWORD 617 int nResolutions = ::DeviceCapabilities(printerName, printerPort, 618 DC_ENUMRESOLUTIONS, NULL, NULL); 619 RESTORE_CONTROLWORD 620 621 jintArray resolutionArray = NULL; 622 if (nResolutions > 0) { 623 resolutionArray = env->NewIntArray(nResolutions*2); 624 if (resolutionArray != NULL) { 625 jint *jpcIndices = env->GetIntArrayElements(resolutionArray, NULL); 626 if (jpcIndices != NULL) { 627 jint *saveFormats = jpcIndices; 628 LPTSTR resBuf = NULL; 629 try { 630 resBuf = (LPTSTR)new char[nResolutions * sizeof(LONG) * 2]; 631 } catch (std::bad_alloc&) { 632 resBuf = NULL; 633 } 634 if (resBuf != NULL) { 635 if (::DeviceCapabilities(printerName, printerPort, 636 DC_ENUMRESOLUTIONS, resBuf, 637 NULL) != -1) { 638 LONG *pResolution = (LONG *)resBuf; 639 for (int i = 0; i < nResolutions; i++) { 640 jpcIndices[i*2] = *pResolution++; 641 jpcIndices[i*2+1] = *pResolution++; 642 } 643 } 644 RESTORE_CONTROLWORD 645 delete[] resBuf; 646 } 647 env->ReleaseIntArrayElements(resolutionArray, saveFormats, 0); 648 } 649 } 650 } 651 652 JNU_ReleaseStringPlatformChars(env, printer, printerName); 653 JNU_ReleaseStringPlatformChars(env, port, printerPort); 654 return resolutionArray; 655 } 656 657 658 static BOOL IsDCPostscript( HDC hDC ) 659 { 660 int nEscapeCode; 661 CHAR szTechnology[MAX_PATH] = ""; 662 663 // If it supports POSTSCRIPT_PASSTHROUGH, it must be PS. 664 nEscapeCode = POSTSCRIPT_PASSTHROUGH; 665 if( ::ExtEscape( hDC, QUERYESCSUPPORT, sizeof(int), 666 (LPCSTR)&nEscapeCode, 0, NULL ) > 0 ) 667 return TRUE; 668 669 // If it doesn't support GETTECHNOLOGY, we won't be able to tell. 670 nEscapeCode = GETTECHNOLOGY; 671 if( ::ExtEscape( hDC, QUERYESCSUPPORT, sizeof(int), 672 (LPCSTR)&nEscapeCode, 0, NULL ) <= 0 ) 673 return FALSE; 674 675 // Get the technology string and check if the word "postscript" is in it. 676 if( ::ExtEscape( hDC, GETTECHNOLOGY, 0, NULL, MAX_PATH, 677 (LPSTR)szTechnology ) <= 0 ) 678 return FALSE; 679 _strupr_s(szTechnology, MAX_PATH); 680 if(!strstr( szTechnology, "POSTSCRIPT" ) == NULL ) 681 return TRUE; 682 683 // The word "postscript" was not found and it didn't support 684 // POSTSCRIPT_PASSTHROUGH, so it's not a PS printer. 685 return FALSE; 686 } 687 688 689 JNIEXPORT jstring JNICALL 690 Java_sun_print_Win32PrintService_getPrinterPort(JNIEnv *env, 691 jobject peer, 692 jstring printer) 693 { 694 695 if (printer == NULL) { 696 return NULL; 697 } 698 699 jstring jPort; 700 LPTSTR printerName = NULL, printerPort = TEXT("LPT1"); 701 LPBYTE buffer = NULL; 702 DWORD cbBuf = 0; 703 704 try { 705 VERIFY(AwtPrintControl::FindPrinter(NULL, NULL, &cbBuf, NULL, NULL)); 706 buffer = new BYTE[cbBuf]; 707 AwtPrintControl::FindPrinter(printer, buffer, &cbBuf, 708 &printerName, &printerPort); 709 } catch (std::bad_alloc&) { 710 delete [] buffer; 711 JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); 712 return NULL; 713 } 714 715 if (printerPort == NULL) { 716 printerPort = TEXT("LPT1"); 717 } 718 jPort = JNU_NewStringPlatform(env, printerPort); 719 delete [] buffer; 720 return jPort; 721 722 } 723 724 725 JNIEXPORT jint JNICALL 726 Java_sun_print_Win32PrintService_getCapabilities(JNIEnv *env, 727 jobject peer, 728 jstring printer, 729 jstring port) 730 { 731 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); 732 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); 733 734 if (printerName == NULL || printerPort == NULL) { 735 if (printerName != NULL) { 736 JNU_ReleaseStringPlatformChars(env, printer, printerName); 737 } 738 if (printerPort != NULL) { 739 JNU_ReleaseStringPlatformChars(env, port, printerPort); 740 } 741 return NULL; 742 } 743 744 // 0x1000 is a flag to indicate that getCapabilities has already been called. 745 // 0x0001 is a flag for color support and supported is the default. 746 jint ret = 0x1001; 747 DWORD dmFields; 748 749 // get Duplex 750 SAVE_CONTROLWORD 751 DWORD isDuplex = (::DeviceCapabilities(printerName, printerPort, 752 DC_DUPLEX, NULL, NULL)) ; 753 754 /* 755 Check if duplexer is installed either physically or manually thru the 756 printer setting dialog by checking if DM_DUPLEX is set. 757 */ 758 dmFields = (::DeviceCapabilities(printerName, printerPort, 759 DC_FIELDS, NULL, NULL)) ; 760 761 if ((dmFields & DM_DUPLEX) && isDuplex) { 762 ret |= 0x0002; 763 } 764 765 // get Collation 766 if ((dmFields & DM_COLLATE) ) { 767 ret |= 0x0004; 768 } 769 770 // get Print Quality 771 if ((dmFields & DM_PRINTQUALITY) ) { 772 ret |= 0x0008; 773 } 774 775 HDC pdc = CreateDC(TEXT("WINSPOOL"), printerName, NULL, NULL); 776 if (pdc != NULL) { 777 // get Color 778 int bpp = GetDeviceCaps(pdc, BITSPIXEL); 779 int nColors = GetDeviceCaps(pdc, NUMCOLORS); 780 781 if (!(dmFields & DM_COLOR) || ((bpp == 1) 782 && ((nColors == 2) || (nColors == 256)))) { 783 ret &= ~0x0001; 784 } 785 786 // check support for PostScript 787 if (IsDCPostscript(pdc)) { 788 ret |= 0x0010; 789 } 790 791 DeleteDC(pdc); 792 } 793 794 RESTORE_CONTROLWORD 795 JNU_ReleaseStringPlatformChars(env, printer, printerName); 796 JNU_ReleaseStringPlatformChars(env, port, printerPort); 797 return ret; 798 } 799 800 801 #define GETDEFAULT_ERROR -50 802 #define NDEFAULT 9 803 804 JNIEXPORT jintArray JNICALL 805 Java_sun_print_Win32PrintService_getDefaultSettings(JNIEnv *env, 806 jobject peer, 807 jstring printer, 808 jstring port) 809 { 810 HANDLE hPrinter; 811 LPDEVMODE pDevMode = NULL; 812 813 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); 814 LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL); 815 816 if (printerName == NULL || printerPort == NULL) { 817 if (printerName != NULL) { 818 JNU_ReleaseStringPlatformChars(env, printer, printerName); 819 } 820 if (printerPort != NULL) { 821 JNU_ReleaseStringPlatformChars(env, port, printerPort); 822 } 823 return NULL; 824 } 825 826 jint* defIndices = NULL; 827 jintArray defaultArray = env->NewIntArray(NDEFAULT); 828 if (defaultArray != NULL) { 829 defIndices = env->GetIntArrayElements(defaultArray, NULL); 830 } 831 if (defIndices == NULL) { 832 JNU_ReleaseStringPlatformChars(env, printer, printerName); 833 JNU_ReleaseStringPlatformChars(env, port, printerPort); 834 return NULL; 835 } 836 837 jint *saveFormats = defIndices; 838 839 for (int i=0; i < NDEFAULT; i++) { 840 defIndices[i] = GETDEFAULT_ERROR; 841 } 842 843 /* Start by opening the printer */ 844 if (!::OpenPrinter(printerName, &hPrinter, NULL)) { 845 env->ReleaseIntArrayElements(defaultArray, saveFormats, 0); 846 JNU_ReleaseStringPlatformChars(env, printer, printerName); 847 JNU_ReleaseStringPlatformChars(env, port, printerPort); 848 return defaultArray; 849 } 850 851 if (!AwtPrintControl::getDevmode(hPrinter, printerName, &pDevMode)) { 852 /* if failure, cleanup and return failure */ 853 if (pDevMode != NULL) { 854 ::GlobalFree(pDevMode); 855 } 856 ::ClosePrinter(hPrinter); 857 env->ReleaseIntArrayElements(defaultArray, saveFormats, 0); 858 JNU_ReleaseStringPlatformChars(env, printer, printerName); 859 JNU_ReleaseStringPlatformChars(env, port, printerPort); 860 return defaultArray; 861 } 862 863 /* Have seen one driver which reports a default paper id which is not 864 * one of their supported paper ids. If what is returned is not 865 * a supported paper, use one of the supported sizes instead. 866 * 867 */ 868 if (pDevMode->dmFields & DM_PAPERSIZE) { 869 defIndices[0] = pDevMode->dmPaperSize; 870 871 SAVE_CONTROLWORD 872 873 int numSizes = ::DeviceCapabilities(printerName, printerPort, 874 DC_PAPERS, NULL, NULL); 875 if (numSizes > 0) { 876 LPTSTR papers; 877 try { 878 papers = (LPTSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, numSizes, sizeof(WORD)); 879 } catch (const std::bad_alloc&) { 880 papers = NULL; 881 } 882 883 if (papers != NULL && 884 ::DeviceCapabilities(printerName, printerPort, 885 DC_PAPERS, papers, NULL) != -1) { 886 int present = 0; 887 for (int i=0;i<numSizes;i++) { 888 if (papers[i] == pDevMode->dmPaperSize) { 889 present = 1; 890 } 891 } 892 if (!present) { 893 defIndices[0] = papers[0]; 894 } 895 } 896 // If DeviceCapabilities fails, then also free paper allocation 897 if (papers != NULL) { 898 free((char*)papers); 899 } 900 } 901 RESTORE_CONTROLWORD 902 } 903 904 if (pDevMode->dmFields & DM_MEDIATYPE) { 905 defIndices[1] = pDevMode->dmMediaType; 906 } 907 908 /* 909 * For some printer like Brother HL-2240D series 910 * pDevMode->dmYResolution is not set in pDevMode->dmFields 911 * even though pDevMode->dmYResolution is populated 912 * via ::DocumentProperties API, so for this case 913 * we populate the resolution index in default array 914 */ 915 if (pDevMode->dmFields & DM_YRESOLUTION || pDevMode->dmYResolution > 0) { 916 defIndices[2] = pDevMode->dmYResolution; 917 } 918 919 /* 920 * For some printer like Brother HL-2240D series 921 * pDevMode->dmPrintQuality is not set in pDevMode->dmFields 922 * even though pDevMode->dmPrintQuality is populated 923 * via ::DocumentProperties API, so for this case 924 * we populate the print quality index in default array 925 */ 926 if (pDevMode->dmFields & DM_PRINTQUALITY || pDevMode->dmPrintQuality != 0) { 927 defIndices[3] = pDevMode->dmPrintQuality; 928 } 929 930 if (pDevMode->dmFields & DM_COPIES) { 931 defIndices[4] = pDevMode->dmCopies; 932 } 933 934 if (pDevMode->dmFields & DM_ORIENTATION) { 935 defIndices[5] = pDevMode->dmOrientation; 936 } 937 938 if (pDevMode->dmFields & DM_DUPLEX) { 939 defIndices[6] = pDevMode->dmDuplex; 940 } 941 942 if (pDevMode->dmFields & DM_COLLATE) { 943 defIndices[7] = pDevMode->dmCollate; 944 } 945 946 if (pDevMode->dmFields & DM_COLOR) { 947 defIndices[8] = pDevMode->dmColor; 948 } 949 950 GlobalFree(pDevMode); 951 ::ClosePrinter(hPrinter); 952 953 env->ReleaseIntArrayElements(defaultArray, saveFormats, 0); 954 955 JNU_ReleaseStringPlatformChars(env, printer, printerName); 956 JNU_ReleaseStringPlatformChars(env, port, printerPort); 957 958 return defaultArray; 959 } 960 961 962 JNIEXPORT jint JNICALL 963 Java_sun_print_Win32PrintService_getJobStatus(JNIEnv *env, 964 jobject peer, 965 jstring printer, 966 jint type) 967 { 968 HANDLE hPrinter; 969 DWORD cByteNeeded; 970 DWORD cByteUsed; 971 PRINTER_INFO_2 *pPrinterInfo = NULL; 972 int ret=0; 973 974 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); 975 if (printerName == NULL) { 976 return -1; 977 } 978 979 // Start by opening the printer 980 if (!::OpenPrinter(printerName, &hPrinter, NULL)) { 981 JNU_ReleaseStringPlatformChars(env, printer, printerName); 982 return -1; 983 } 984 985 if (!::GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded)) { 986 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { 987 ::ClosePrinter(hPrinter); 988 JNU_ReleaseStringPlatformChars(env, printer, printerName); 989 return -1; 990 } 991 } 992 993 pPrinterInfo = (PRINTER_INFO_2 *)::GlobalAlloc(GPTR, cByteNeeded); 994 if (!(pPrinterInfo)) { 995 /* failure to allocate memory */ 996 ::ClosePrinter(hPrinter); 997 JNU_ReleaseStringPlatformChars(env, printer, printerName); 998 return -1; 999 } 1000 1001 /* get the printer info */ 1002 if (!::GetPrinter(hPrinter, 1003 2, 1004 (LPBYTE)pPrinterInfo, 1005 cByteNeeded, 1006 &cByteUsed)) 1007 { 1008 /* failure to access the printer */ 1009 ::GlobalFree(pPrinterInfo); 1010 pPrinterInfo = NULL; 1011 ::ClosePrinter(hPrinter); 1012 JNU_ReleaseStringPlatformChars(env, printer, printerName); 1013 return -1; 1014 } 1015 1016 if (type == GETJOBCOUNT) { 1017 ret = pPrinterInfo->cJobs; 1018 } else if (type == ACCEPTJOB) { 1019 if (pPrinterInfo->Status & PRINTER_STATUS_PENDING_DELETION) { 1020 ret = 0; 1021 } 1022 else { 1023 ret = 1; 1024 } 1025 } 1026 1027 ::GlobalFree(pPrinterInfo); 1028 ::ClosePrinter(hPrinter); 1029 JNU_ReleaseStringPlatformChars(env, printer, printerName); 1030 return ret; 1031 } 1032 1033 1034 static jfieldID getIdOfLongField(JNIEnv *env, jobject self, 1035 const char *fieldName) { 1036 jclass myClass = env->GetObjectClass(self); 1037 jfieldID fieldId = env->GetFieldID(myClass, fieldName, "J"); 1038 DASSERT(fieldId != 0); 1039 return fieldId; 1040 } 1041 1042 1043 static inline HANDLE getHPrinter(JNIEnv *env, jobject self) { 1044 jfieldID fieldId = getIdOfLongField(env, self, HPRINTER_STR); 1045 if (fieldId == (jfieldID)0) { 1046 return (HANDLE)NULL; 1047 } 1048 return (HANDLE)(env->GetLongField(self, fieldId)); 1049 } 1050 1051 1052 JNIEXPORT jboolean JNICALL 1053 Java_sun_print_Win32PrintJob_startPrintRawData(JNIEnv *env, 1054 jobject peer, 1055 jstring printer, 1056 jstring jobname) 1057 { 1058 HANDLE hPrinter; 1059 DOC_INFO_1 DocInfo; 1060 LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL); 1061 if (printerName == NULL) { 1062 return false; 1063 } 1064 DASSERT(jobname != NULL); 1065 LPTSTR lpJobName = (LPTSTR)JNU_GetStringPlatformChars(env, jobname, NULL); 1066 LPTSTR jname = _tcsdup(lpJobName); 1067 JNU_ReleaseStringPlatformChars(env, jobname, lpJobName); 1068 1069 // Start by opening the printer 1070 if (!::OpenPrinter(printerName, &hPrinter, NULL)) { 1071 JNU_ReleaseStringPlatformChars(env, printer, printerName); 1072 free((LPTSTR)jname); 1073 return false; 1074 } 1075 1076 JNU_ReleaseStringPlatformChars(env, printer, printerName); 1077 1078 // Fill in the structure with info about this "document." 1079 DocInfo.pDocName = jname; 1080 DocInfo.pOutputFile = NULL; 1081 DocInfo.pDatatype = TEXT("RAW"); 1082 1083 // Inform the spooler the document is beginning. 1084 if( (::StartDocPrinter(hPrinter, 1, (LPBYTE)&DocInfo)) == 0 ) { 1085 ::ClosePrinter( hPrinter ); 1086 free((LPTSTR)jname); 1087 return false; 1088 } 1089 1090 free((LPTSTR)jname); 1091 1092 // Start a page. 1093 if( ! ::StartPagePrinter( hPrinter ) ) { 1094 ::EndDocPrinter( hPrinter ); 1095 ::ClosePrinter( hPrinter ); 1096 return false; 1097 } 1098 1099 // store handle 1100 jfieldID fieldId = getIdOfLongField(env, peer, HPRINTER_STR); 1101 if (fieldId == (jfieldID)0) { 1102 return false; 1103 } else { 1104 env->SetLongField(peer, fieldId, reinterpret_cast<jlong>(hPrinter)); 1105 return true; 1106 } 1107 } 1108 1109 1110 JNIEXPORT jboolean JNICALL 1111 Java_sun_print_Win32PrintJob_printRawData(JNIEnv *env, 1112 jobject peer, 1113 jbyteArray dataArray, 1114 jint count) 1115 { 1116 jboolean ret=true; 1117 jint dwBytesWritten; 1118 jbyte* data = NULL; 1119 1120 // retrieve handle 1121 HANDLE hPrinter = getHPrinter(env, peer); 1122 if (hPrinter == NULL) { 1123 return false; 1124 } 1125 1126 try { 1127 data=(jbyte *)env->GetPrimitiveArrayCritical(dataArray, 0); 1128 if (data == NULL) { 1129 return false; 1130 } 1131 1132 // Send the data to the printer. 1133 if( ! ::WritePrinter(hPrinter, data, count,(LPDWORD)&dwBytesWritten)) { 1134 env->ReleasePrimitiveArrayCritical(dataArray, data, 0); 1135 return false; 1136 } 1137 1138 // Check to see if correct number of bytes were written. 1139 if( dwBytesWritten != count ) { 1140 ret = false; 1141 } 1142 1143 } catch (...) { 1144 if (data != NULL) { 1145 env->ReleasePrimitiveArrayCritical(dataArray, data, 0); 1146 } 1147 JNU_ThrowInternalError(env, "Problem in Win32PrintJob_printRawData"); 1148 return false; 1149 } 1150 1151 env->ReleasePrimitiveArrayCritical(dataArray, data, 0); 1152 return ret; 1153 } 1154 1155 1156 JNIEXPORT jboolean JNICALL 1157 Java_sun_print_Win32PrintJob_endPrintRawData(JNIEnv *env, 1158 jobject peer) 1159 { 1160 // retrieve handle 1161 HANDLE hPrinter = getHPrinter(env, peer); 1162 if (hPrinter == NULL) { 1163 return false; 1164 } 1165 1166 if ((::EndPagePrinter(hPrinter) != 0) && 1167 (::EndDocPrinter(hPrinter) != 0) && 1168 (::ClosePrinter(hPrinter) != 0)) { 1169 return true; 1170 } else { 1171 return false; 1172 } 1173 } 1174 1175 } /* extern "C" */