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 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 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 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 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 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 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 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 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 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 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 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 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 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, port, printerPort); 665 return resolutionArray; 666 } 667 668 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 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 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, port, printerPort); 808 return ret; 809 } 810 811 812 #define GETDEFAULT_ERROR -50 813 #define NDEFAULT 9 814 815 JNIEXPORT jintArray JNICALL 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 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 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 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 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 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 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" */