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