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