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