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