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