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