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