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