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