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