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