blob: 5d24aaf9c4fd3a96011127405a2ecaf2ace85f1e [file] [log] [blame]
/*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "awt.h"
#include "stdhdrs.h"
#include <commdlg.h>
#include <winspool.h>
#include <limits.h>
#include <float.h>
#include "awt_Toolkit.h"
#include "awt_PrintControl.h"
/* values for parameter "type" of XXX_getJobStatus() */
#define GETJOBCOUNT 1
#define ACCEPTJOB 2
static const char *HPRINTER_STR = "hPrintJob";
/* constants for DeviceCapability buffer lengths */
#define PAPERNAME_LENGTH 64
#define TRAYNAME_LENGTH 24
static BOOL IsSupportedLevel(HANDLE hPrinter, DWORD dwLevel) {
BOOL isSupported = FALSE;
DWORD cbBuf = 0;
LPBYTE pPrinter = NULL;
DASSERT(hPrinter != NULL);
VERIFY(::GetPrinter(hPrinter, dwLevel, NULL, 0, &cbBuf) == 0);
if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
pPrinter = new BYTE[cbBuf];
if (::GetPrinter(hPrinter, dwLevel, pPrinter, cbBuf, &cbBuf)) {
isSupported = TRUE;
}
delete[] pPrinter;
}
return isSupported;
}
extern "C" {
JNIEXPORT jstring JNICALL
Java_sun_print_Win32PrintServiceLookup_getDefaultPrinterName(JNIEnv *env,
jobject peer)
{
TRY;
TCHAR cBuffer[250];
OSVERSIONINFO osv;
PRINTER_INFO_2 *ppi2 = NULL;
DWORD dwNeeded = 0;
DWORD dwReturned = 0;
LPTSTR pPrinterName = NULL;
jstring jPrinterName;
// What version of Windows are you running?
osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osv);
// If Windows 2000, XP, Vista
if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT) {
// Retrieve the default string from Win.ini (the registry).
// String will be in form "printername,drivername,portname".
if (GetProfileString(TEXT("windows"), TEXT("device"), TEXT(",,,"),
cBuffer, 250) <= 0) {
return NULL;
}
// Copy printer name into passed-in buffer...
int index = 0;
int len = lstrlen(cBuffer);
while ((index < len) && cBuffer[index] != _T(',')) {
index++;
}
if (index==0) {
return NULL;
}
pPrinterName = (LPTSTR)GlobalAlloc(GPTR, (index+1)*sizeof(TCHAR));
lstrcpyn(pPrinterName, cBuffer, index+1);
jPrinterName = JNU_NewStringPlatform(env, pPrinterName);
GlobalFree(pPrinterName);
return jPrinterName;
} else {
return NULL;
}
CATCH_BAD_ALLOC_RET(NULL);
}
JNIEXPORT jobjectArray JNICALL
Java_sun_print_Win32PrintServiceLookup_getAllPrinterNames(JNIEnv *env,
jobject peer)
{
TRY;
DWORD cbNeeded = 0;
DWORD cReturned = 0;
LPBYTE pPrinterEnum = NULL;
jstring utf_str;
jclass clazz = env->FindClass("java/lang/String");
jobjectArray nameArray;
try {
::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
NULL, 4, NULL, 0, &cbNeeded, &cReturned);
pPrinterEnum = new BYTE[cbNeeded];
::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
NULL, 4, pPrinterEnum, cbNeeded, &cbNeeded,
&cReturned);
if (cReturned > 0) {
nameArray = env->NewObjectArray(cReturned, clazz, NULL);
if (nameArray == NULL) {
throw std::bad_alloc();
}
} else {
nameArray = NULL;
}
for (DWORD i = 0; i < cReturned; i++) {
PRINTER_INFO_4 *info4 = (PRINTER_INFO_4 *)
(pPrinterEnum + i * sizeof(PRINTER_INFO_4));
utf_str = JNU_NewStringPlatform(env, info4->pPrinterName);
if (utf_str == NULL) {
throw std::bad_alloc();
}
env->SetObjectArrayElement(nameArray, i, utf_str);
env->DeleteLocalRef(utf_str);
}
} catch (std::bad_alloc&) {
delete [] pPrinterEnum;
throw;
}
delete [] pPrinterEnum;
return nameArray;
CATCH_BAD_ALLOC_RET(NULL);
}
JNIEXPORT jlong JNICALL
Java_sun_print_Win32PrintServiceLookup_notifyFirstPrinterChange(JNIEnv *env,
jobject peer,
jstring printer) {
HANDLE hPrinter;
LPTSTR printerName = NULL;
if (printer != NULL) {
printerName = (LPTSTR)JNU_GetStringPlatformChars(env,
printer,
NULL);
JNU_ReleaseStringPlatformChars(env, printer, printerName);
}
// printerName - "Win NT/2K/XP: If NULL, it indicates the local printer
// server" - MSDN. Win9x : OpenPrinter returns 0.
BOOL ret = OpenPrinter(printerName, &hPrinter, NULL);
if (!ret) {
return (jlong)-1;
}
// PRINTER_CHANGE_PRINTER = PRINTER_CHANGE_ADD_PRINTER |
// PRINTER_CHANGE_SET_PRINTER |
// PRINTER_CHANGE_DELETE_PRINTER |
// PRINTER_CHANGE_FAILED_CONNECTION_PRINTER
HANDLE chgObj = FindFirstPrinterChangeNotification(hPrinter,
PRINTER_CHANGE_PRINTER,
0,
NULL);
return (chgObj == INVALID_HANDLE_VALUE) ? (jlong)-1 : (jlong)chgObj;
}
JNIEXPORT void JNICALL
Java_sun_print_Win32PrintServiceLookup_notifyClosePrinterChange(JNIEnv *env,
jobject peer,
jlong chgObject) {
FindClosePrinterChangeNotification((HANDLE)chgObject);
}
JNIEXPORT jint JNICALL
Java_sun_print_Win32PrintServiceLookup_notifyPrinterChange(JNIEnv *env,
jobject peer,
jlong chgObject) {
DWORD dwChange;
DWORD ret = WaitForSingleObject((HANDLE)chgObject, INFINITE);
if (ret == WAIT_OBJECT_0) {
return(FindNextPrinterChangeNotification((HANDLE)chgObject,
&dwChange, NULL, NULL));
} else {
return 0;
}
}
JNIEXPORT jfloatArray JNICALL
Java_sun_print_Win32PrintService_getMediaPrintableArea(JNIEnv *env,
jobject peer,
jstring printer,
jint papersize)
{
TRY;
LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env,
printer, NULL);
jfloatArray printableArray = NULL;
SAVE_CONTROLWORD
HDC pdc = CreateDC(TEXT("WINSPOOL"), printerName, NULL, NULL);
RESTORE_CONTROLWORD
if (pdc) {
HANDLE hPrinter;
/* Start by opening the printer */
if (!::OpenPrinter(printerName, &hPrinter, NULL)) {
JNU_ReleaseStringPlatformChars(env, printer, printerName);
return printableArray;
}
PDEVMODE pDevMode;
if (!AwtPrintControl::getDevmode(hPrinter, printerName, &pDevMode)) {
/* if failure, cleanup and return failure */
if (pDevMode != NULL) {
::GlobalFree(pDevMode);
}
::ClosePrinter(hPrinter);
JNU_ReleaseStringPlatformChars(env, printer, printerName);
return printableArray;
}
pDevMode->dmFields |= (DM_PAPERSIZE | DM_ORIENTATION);
pDevMode->dmPaperSize = (short)papersize;
pDevMode->dmOrientation = DMORIENT_PORTRAIT;
::ResetDC(pdc, pDevMode);
RESTORE_CONTROLWORD
int left = GetDeviceCaps(pdc, PHYSICALOFFSETX);
int top = GetDeviceCaps(pdc, PHYSICALOFFSETY);
int width = GetDeviceCaps(pdc, HORZRES);
int height = GetDeviceCaps(pdc, VERTRES);
int resx = GetDeviceCaps(pdc, LOGPIXELSX);
int resy = GetDeviceCaps(pdc, LOGPIXELSY);
printableArray=env->NewFloatArray(4);
if (printableArray == NULL) {
throw std::bad_alloc();
}
jboolean isCopy;
jfloat *iPrintables = env->GetFloatArrayElements(printableArray,
&isCopy),
*savePrintables = iPrintables;
iPrintables[0] = (float)left/resx;
iPrintables[1] = (float)top/resy;
iPrintables[2] = (float)width/resx;
iPrintables[3] = (float)height/resy;
env->ReleaseFloatArrayElements(printableArray, savePrintables, 0);
GlobalFree(pDevMode);
}
DeleteDC(pdc);
JNU_ReleaseStringPlatformChars(env, printer, printerName);
return printableArray;
CATCH_BAD_ALLOC_RET(NULL);
}
JNIEXPORT jintArray JNICALL
Java_sun_print_Win32PrintService_getAllMediaIDs(JNIEnv *env,
jobject peer,
jstring printer,
jstring port)
{
TRY;
LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
jintArray mediasizeArray = NULL;
SAVE_CONTROLWORD
int numSizes = ::DeviceCapabilities(printerName, printerPort,
DC_PAPERS, NULL, NULL);
RESTORE_CONTROLWORD
if (numSizes > 0) {
mediasizeArray = env->NewIntArray(numSizes);
if (mediasizeArray == NULL) {
throw std::bad_alloc();
}
jboolean isCopy;
jint *jpcIndices = env->GetIntArrayElements(mediasizeArray,
&isCopy), *saveFormats = jpcIndices;
LPTSTR papersBuf = (LPTSTR)new char[numSizes * sizeof(WORD)];
if (::DeviceCapabilities(printerName, printerPort,
DC_PAPERS, papersBuf, NULL) != -1) {
RESTORE_CONTROLWORD
WORD *pDmPaperSize = (WORD *)papersBuf;
for (int i = 0; i < numSizes; i++, pDmPaperSize++) {
jpcIndices[i] = *pDmPaperSize;
}
}
delete[] papersBuf;
env->ReleaseIntArrayElements(mediasizeArray, saveFormats, 0);
}
JNU_ReleaseStringPlatformChars(env, printer, printerName);
JNU_ReleaseStringPlatformChars(env, port, printerPort);
return mediasizeArray;
CATCH_BAD_ALLOC_RET(NULL);
}
JNIEXPORT jintArray JNICALL
Java_sun_print_Win32PrintService_getAllMediaTrays(JNIEnv *env,
jobject peer,
jstring printer,
jstring port)
{
TRY;
LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env,
printer, NULL);
LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
jintArray mediaTrayArray = NULL;
SAVE_CONTROLWORD
int nBins = ::DeviceCapabilities(printerName, printerPort,
DC_BINS, NULL, NULL) ;
RESTORE_CONTROLWORD
if (nBins > 0) {
mediaTrayArray = env->NewIntArray(nBins);
if (mediaTrayArray == NULL) {
throw std::bad_alloc();
}
jboolean isCopy;
jint *jpcIndices = env->GetIntArrayElements(mediaTrayArray,
&isCopy), *saveFormats = jpcIndices;
LPTSTR buf = (LPTSTR)new char[nBins * sizeof(WORD)];
if (::DeviceCapabilities(printerName, printerPort,
DC_BINS, buf, NULL) != -1) {
RESTORE_CONTROLWORD
WORD *pBins = (WORD *)buf;
for (int i = 0; i < nBins; i++) {
jpcIndices[i] = *(pBins+i);
}
}
delete[] buf;
env->ReleaseIntArrayElements(mediaTrayArray, saveFormats, 0);
}
JNU_ReleaseStringPlatformChars(env, printer, printerName);
JNU_ReleaseStringPlatformChars(env, port, printerPort);
return mediaTrayArray;
CATCH_BAD_ALLOC_RET(NULL);
}
JNIEXPORT jintArray JNICALL
Java_sun_print_Win32PrintService_getAllMediaSizes(JNIEnv *env,
jobject peer,
jstring printer,
jstring port)
{
TRY;
LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env,
printer, NULL);
LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
jintArray mediaArray = NULL;
SAVE_CONTROLWORD
int nPapers = ::DeviceCapabilities(printerName, printerPort,
DC_PAPERSIZE, NULL, NULL) ;
RESTORE_CONTROLWORD
if (nPapers > 0) {
mediaArray = env->NewIntArray(nPapers*2);
if (mediaArray == NULL) {
throw std::bad_alloc();
}
jboolean isCopy;
jint *jpcIndices = env->GetIntArrayElements(mediaArray,
&isCopy), *saveFormats = jpcIndices;
LPTSTR buf = (LPTSTR)new char[nPapers * sizeof(POINT)]; // array of POINTs
if (::DeviceCapabilities(printerName, printerPort,
DC_PAPERSIZE, buf, NULL) != -1) {
POINT *pDim = (POINT *)buf;
for (int i = 0; i < nPapers; i++) {
jpcIndices[i*2] = (pDim+i)->x;
jpcIndices[i*2+1] = (pDim+i)->y;
}
}
RESTORE_CONTROLWORD
delete[] buf;
env->ReleaseIntArrayElements(mediaArray, saveFormats, 0);
}
JNU_ReleaseStringPlatformChars(env, printer, printerName);
JNU_ReleaseStringPlatformChars(env, port, printerPort);
return mediaArray;
CATCH_BAD_ALLOC_RET(NULL);
}
jobjectArray getAllDCNames(JNIEnv *env, jobject peer, jstring printer,
jstring port, unsigned int dc_id, unsigned int buf_len)
{
TRY;
LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env,
printer, NULL);
LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
jstring utf_str;
jclass cls = env->FindClass("java/lang/String");
jobjectArray names= NULL;
LPTSTR buf = NULL;
SAVE_CONTROLWORD
int cReturned = ::DeviceCapabilities(printerName, printerPort,
dc_id, NULL, NULL);
RESTORE_CONTROLWORD
if (cReturned > 0) {
buf = (LPTSTR)new char[cReturned * buf_len * sizeof(TCHAR)];
if (buf == NULL) {
throw std::bad_alloc();
}
cReturned = ::DeviceCapabilities(printerName, printerPort,
dc_id, buf, NULL);
RESTORE_CONTROLWORD
if (cReturned > 0) {
names = env->NewObjectArray(cReturned, cls, NULL);
if (names == NULL) {
throw std::bad_alloc();
}
for (int i = 0; i < cReturned; i++) {
utf_str = JNU_NewStringPlatform(env, buf+(buf_len*i));
if (utf_str == NULL) {
throw std::bad_alloc();
}
env->SetObjectArrayElement(names, i, utf_str);
env->DeleteLocalRef(utf_str);
}
}
delete[] buf;
}
return names;
CATCH_BAD_ALLOC_RET(NULL);
}
JNIEXPORT jobjectArray JNICALL
Java_sun_print_Win32PrintService_getAllMediaNames(JNIEnv *env,
jobject peer,
jstring printer,
jstring port)
{
return getAllDCNames(env, peer, printer, port, DC_PAPERNAMES, PAPERNAME_LENGTH);
}
JNIEXPORT jobjectArray JNICALL
Java_sun_print_Win32PrintService_getAllMediaTrayNames(JNIEnv *env,
jobject peer,
jstring printer,
jstring port)
{
return getAllDCNames(env, peer, printer, port, DC_BINNAMES, TRAYNAME_LENGTH);
}
JNIEXPORT jint JNICALL
Java_sun_print_Win32PrintService_getCopiesSupported(JNIEnv *env,
jobject peer,
jstring printer,
jstring port)
{
LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
SAVE_CONTROLWORD
int numCopies = ::DeviceCapabilities(printerName, printerPort,
DC_COPIES, NULL, NULL);
RESTORE_CONTROLWORD
if (numCopies == -1)
return 1; // default
JNU_ReleaseStringPlatformChars(env, printer, printerName);
JNU_ReleaseStringPlatformChars(env, port, printerPort);
return numCopies;
}
/*
PostScript Drivers return wrong support info for the following code:
DWORD dmFields = (::DeviceCapabilities(printerName,
NULL, DC_FIELDS, NULL, NULL)) ;
if ((dmFields & DM_YRESOLUTION) )
isSupported = true;
Returns not supported even if it supports resolution. Therefore, we use the
function _getAllResolutions.
*/
JNIEXPORT jintArray JNICALL
Java_sun_print_Win32PrintService_getAllResolutions(JNIEnv *env,
jobject peer,
jstring printer,
jstring port)
{
TRY;
LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
jintArray resolutionArray = NULL;
SAVE_CONTROLWORD
int nResolutions = ::DeviceCapabilities(printerName, printerPort,
DC_ENUMRESOLUTIONS, NULL, NULL);
RESTORE_CONTROLWORD
if (nResolutions > 0) {
resolutionArray = env->NewIntArray(nResolutions*2);
if (resolutionArray == NULL) {
throw std::bad_alloc();
}
jboolean isCopy;
jint *jpcIndices = env->GetIntArrayElements(resolutionArray,
&isCopy), *saveFormats = jpcIndices;
LPTSTR resBuf = (LPTSTR)new char[nResolutions * sizeof(LONG) * 2]; // pairs of long
if (::DeviceCapabilities(printerName, printerPort,
DC_ENUMRESOLUTIONS, resBuf, NULL) != -1) {
LONG *pResolution = (LONG *)resBuf;
for (int i = 0; i < nResolutions; i++) {
jpcIndices[i*2] = *pResolution++;
jpcIndices[i*2+1] = *pResolution++;
}
}
RESTORE_CONTROLWORD
delete[] resBuf;
env->ReleaseIntArrayElements(resolutionArray, saveFormats, 0);
}
JNU_ReleaseStringPlatformChars(env, printer, printerName);
JNU_ReleaseStringPlatformChars(env, printer, printerPort);
return resolutionArray;
CATCH_BAD_ALLOC_RET(NULL);
}
static BOOL IsDCPostscript( HDC hDC )
{
int nEscapeCode;
CHAR szTechnology[MAX_PATH] = "";
// If it supports POSTSCRIPT_PASSTHROUGH, it must be PS.
nEscapeCode = POSTSCRIPT_PASSTHROUGH;
if( ::ExtEscape( hDC, QUERYESCSUPPORT, sizeof(int),
(LPCSTR)&nEscapeCode, 0, NULL ) > 0 )
return TRUE;
// If it doesn't support GETTECHNOLOGY, we won't be able to tell.
nEscapeCode = GETTECHNOLOGY;
if( ::ExtEscape( hDC, QUERYESCSUPPORT, sizeof(int),
(LPCSTR)&nEscapeCode, 0, NULL ) <= 0 )
return FALSE;
// Get the technology string and check if the word "postscript" is in it.
if( ::ExtEscape( hDC, GETTECHNOLOGY, 0, NULL, MAX_PATH,
(LPSTR)szTechnology ) <= 0 )
return FALSE;
strupr( szTechnology );
if(!strstr( szTechnology, "POSTSCRIPT" ) == NULL )
return TRUE;
// The word "postscript" was not found and it didn't support
// POSTSCRIPT_PASSTHROUGH, so it's not a PS printer.
return FALSE;
}
JNIEXPORT jstring JNICALL
Java_sun_print_Win32PrintService_getPrinterPort(JNIEnv *env,
jobject peer,
jstring printer)
{
if (printer == NULL) {
return NULL;
}
jstring jPort;
LPTSTR printerName = NULL, printerPort = TEXT("LPT1");
LPBYTE buffer = NULL;
DWORD cbBuf = 0;
try {
VERIFY(AwtPrintControl::FindPrinter(NULL, NULL, &cbBuf, NULL, NULL));
buffer = new BYTE[cbBuf];
AwtPrintControl::FindPrinter(printer, buffer, &cbBuf,
&printerName, &printerPort);
} catch (std::bad_alloc&) {
delete [] buffer;
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
}
if (printerPort == NULL) {
printerPort = TEXT("LPT1");
}
jPort = JNU_NewStringPlatform(env, printerPort);
delete [] buffer;
return jPort;
}
JNIEXPORT jint JNICALL
Java_sun_print_Win32PrintService_getCapabilities(JNIEnv *env,
jobject peer,
jstring printer,
jstring port)
{
LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
// 0x1000 is a flag to indicate that getCapabilities has already been called.
// 0x0001 is a flag for color support and supported is the default.
jint ret = 0x1001;
DWORD dmFields;
// get Duplex
SAVE_CONTROLWORD
DWORD isDuplex = (::DeviceCapabilities(printerName, printerPort,
DC_DUPLEX, NULL, NULL)) ;
/*
Check if duplexer is installed either physically or manually thru the
printer setting dialog by checking if DM_DUPLEX is set.
*/
dmFields = (::DeviceCapabilities(printerName, printerPort,
DC_FIELDS, NULL, NULL)) ;
if ((dmFields & DM_DUPLEX) && isDuplex) {
ret |= 0x0002;
}
// get Collation
if ((dmFields & DM_COLLATE) ) {
ret |= 0x0004;
}
// get Print Quality
if ((dmFields & DM_PRINTQUALITY) ) {
ret |= 0x0008;
}
HDC pdc = CreateDC(TEXT("WINSPOOL"), printerName, NULL, NULL);
if (pdc != NULL) {
// get Color
int bpp = GetDeviceCaps(pdc, BITSPIXEL);
int nColors = GetDeviceCaps(pdc, NUMCOLORS);
if (!(dmFields & DM_COLOR) || ((bpp == 1)
&& ((nColors == 2) || (nColors == 256)))) {
ret &= ~0x0001;
}
// check support for PostScript
if (IsDCPostscript(pdc)) {
ret |= 0x0010;
}
DeleteDC(pdc);
}
RESTORE_CONTROLWORD
JNU_ReleaseStringPlatformChars(env, printer, printerName);
JNU_ReleaseStringPlatformChars(env, printer, printerPort);
return ret;
}
#define GETDEFAULT_ERROR -50
#define NDEFAULT 8
JNIEXPORT jintArray JNICALL
Java_sun_print_Win32PrintService_getDefaultSettings(JNIEnv *env,
jobject peer,
jstring printer,
jstring port)
{
HANDLE hPrinter;
LPDEVMODE pDevMode = NULL;
TRY;
LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
LPTSTR printerPort = (LPTSTR)JNU_GetStringPlatformChars(env, port, NULL);
jintArray defaultArray = env->NewIntArray(NDEFAULT);
if (defaultArray == NULL) {
throw std::bad_alloc();
}
jboolean isCopy;
jint *defIndices = env->GetIntArrayElements(defaultArray,
&isCopy), *saveFormats = defIndices;
for (int i=0; i<NDEFAULT; i++) {
defIndices[i]=GETDEFAULT_ERROR;
}
/* Start by opening the printer */
if (!::OpenPrinter(printerName, &hPrinter, NULL)) {
env->ReleaseIntArrayElements(defaultArray, saveFormats, 0);
JNU_ReleaseStringPlatformChars(env, printer, printerName);
return defaultArray;
}
if (!AwtPrintControl::getDevmode(hPrinter, printerName, &pDevMode)) {
/* if failure, cleanup and return failure */
if (pDevMode != NULL) {
::GlobalFree(pDevMode);
}
::ClosePrinter(hPrinter);
env->ReleaseIntArrayElements(defaultArray, saveFormats, 0);
JNU_ReleaseStringPlatformChars(env, printer, printerName);
return defaultArray;
}
/* Have seen one driver which reports a default paper id which is not
* one of their supported paper ids. If what is returned is not
* a supported paper, use one of the supported sizes instead.
*
*/
if (pDevMode->dmFields & DM_PAPERSIZE) {
defIndices[0] = pDevMode->dmPaperSize;
SAVE_CONTROLWORD
int numSizes = ::DeviceCapabilities(printerName, printerPort,
DC_PAPERS, NULL, NULL);
if (numSizes > 0) {
LPTSTR papers = (LPTSTR)safe_Malloc(numSizes * sizeof(WORD));
if (papers != NULL &&
::DeviceCapabilities(printerName, printerPort,
DC_PAPERS, papers, NULL) != -1) {
int present = 0;
for (int i=0;i<numSizes;i++) {
if (papers[i] == pDevMode->dmPaperSize) {
present = 1;
}
}
if (!present) {
defIndices[0] = papers[0];
}
if (papers != NULL) {
free((char*)papers);
}
}
}
RESTORE_CONTROLWORD
}
if (pDevMode->dmFields & DM_MEDIATYPE) {
defIndices[1] = pDevMode->dmMediaType;
}
if (pDevMode->dmFields & DM_YRESOLUTION) {
defIndices[2] = pDevMode->dmYResolution;
}
if (pDevMode->dmFields & DM_PRINTQUALITY) {
defIndices[3] = pDevMode->dmPrintQuality;
}
if (pDevMode->dmFields & DM_COPIES) {
defIndices[4] = pDevMode->dmCopies;
}
if (pDevMode->dmFields & DM_ORIENTATION) {
defIndices[5] = pDevMode->dmOrientation;
}
if (pDevMode->dmFields & DM_DUPLEX) {
defIndices[6] = pDevMode->dmDuplex;
}
if (pDevMode->dmFields & DM_COLLATE) {
defIndices[7] = pDevMode->dmCollate;
}
GlobalFree(pDevMode);
::ClosePrinter(hPrinter);
env->ReleaseIntArrayElements(defaultArray, saveFormats, 0);
JNU_ReleaseStringPlatformChars(env, printer, printerName);
JNU_ReleaseStringPlatformChars(env, port, printerPort);
return defaultArray;
CATCH_BAD_ALLOC_RET(NULL);
}
JNIEXPORT jint JNICALL
Java_sun_print_Win32PrintService_getJobStatus(JNIEnv *env,
jobject peer,
jstring printer,
jint type)
{
HANDLE hPrinter;
DWORD cByteNeeded;
DWORD cByteUsed;
PRINTER_INFO_2 *pPrinterInfo = NULL;
int ret=0;
LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
// Start by opening the printer
if (!::OpenPrinter(printerName, &hPrinter, NULL)) {
JNU_ReleaseStringPlatformChars(env, printer, printerName);
return -1;
}
if (!::GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded)) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
::ClosePrinter(hPrinter);
JNU_ReleaseStringPlatformChars(env, printer, printerName);
return -1;
}
}
pPrinterInfo = (PRINTER_INFO_2 *)::GlobalAlloc(GPTR, cByteNeeded);
if (!(pPrinterInfo)) {
/* failure to allocate memory */
::ClosePrinter(hPrinter);
JNU_ReleaseStringPlatformChars(env, printer, printerName);
return -1;
}
/* get the printer info */
if (!::GetPrinter(hPrinter,
2,
(LPBYTE)pPrinterInfo,
cByteNeeded,
&cByteUsed))
{
/* failure to access the printer */
::GlobalFree(pPrinterInfo);
pPrinterInfo = NULL;
::ClosePrinter(hPrinter);
JNU_ReleaseStringPlatformChars(env, printer, printerName);
return -1;
}
if (type == GETJOBCOUNT) {
ret = pPrinterInfo->cJobs;
} else if (type == ACCEPTJOB) {
if (pPrinterInfo->Status &
(PRINTER_STATUS_ERROR |
PRINTER_STATUS_NOT_AVAILABLE |
PRINTER_STATUS_NO_TONER |
PRINTER_STATUS_OUT_OF_MEMORY |
PRINTER_STATUS_OFFLINE |
PRINTER_STATUS_USER_INTERVENTION |
PRINTER_STATUS_DOOR_OPEN)) {
ret = 0;
}
else {
ret = 1;
}
}
::GlobalFree(pPrinterInfo);
::ClosePrinter(hPrinter);
JNU_ReleaseStringPlatformChars(env, printer, printerName);
return ret;
}
static jfieldID getIdOfLongField(JNIEnv *env, jobject self,
const char *fieldName) {
jclass myClass = env->GetObjectClass(self);
jfieldID fieldId = env->GetFieldID(myClass, fieldName, "J");
DASSERT(fieldId != 0);
return fieldId;
}
static inline HANDLE getHPrinter(JNIEnv *env, jobject self) {
jfieldID fieldId = getIdOfLongField(env, self, HPRINTER_STR);
return (HANDLE)(env->GetLongField(self, fieldId));
}
JNIEXPORT jboolean JNICALL
Java_sun_print_Win32PrintJob_startPrintRawData(JNIEnv *env,
jobject peer,
jstring printer,
jstring jobname)
{
HANDLE hPrinter;
DOC_INFO_1 DocInfo;
LPTSTR printerName = (LPTSTR)JNU_GetStringPlatformChars(env, printer, NULL);
DASSERT(jobname != NULL);
LPTSTR lpJobName = (LPTSTR)JNU_GetStringPlatformChars(env, jobname, NULL);
LPTSTR jname = _tcsdup(lpJobName);
JNU_ReleaseStringPlatformChars(env, jobname, lpJobName);
// Start by opening the printer
if (!::OpenPrinter(printerName, &hPrinter, NULL)) {
JNU_ReleaseStringPlatformChars(env, printer, printerName);
free((LPTSTR)jname);
return false;
}
JNU_ReleaseStringPlatformChars(env, printer, printerName);
// Fill in the structure with info about this "document."
DocInfo.pDocName = jname;
DocInfo.pOutputFile = NULL;
DocInfo.pDatatype = TEXT("RAW");
// Inform the spooler the document is beginning.
if( (::StartDocPrinter(hPrinter, 1, (LPBYTE)&DocInfo)) == 0 ) {
::ClosePrinter( hPrinter );
free((LPTSTR)jname);
return false;
}
free((LPTSTR)jname);
// Start a page.
if( ! ::StartPagePrinter( hPrinter ) ) {
::EndDocPrinter( hPrinter );
::ClosePrinter( hPrinter );
return false;
}
// store handle
jfieldID fieldId = getIdOfLongField(env, peer, HPRINTER_STR);
env->SetLongField(peer, fieldId, reinterpret_cast<jlong>(hPrinter));
return true;
}
JNIEXPORT jboolean JNICALL
Java_sun_print_Win32PrintJob_printRawData(JNIEnv *env,
jobject peer,
jbyteArray dataArray,
jint count)
{
jboolean ret=true;
jint dwBytesWritten;
jbyte* data = NULL;
// retrieve handle
HANDLE hPrinter = getHPrinter(env, peer);
if (hPrinter == NULL) {
return false;
}
try {
data=(jbyte *)env->GetPrimitiveArrayCritical(dataArray, 0);
// Send the data to the printer.
if( ! ::WritePrinter(hPrinter, data, count,(LPDWORD)&dwBytesWritten)) {
env->ReleasePrimitiveArrayCritical(dataArray, data, 0);
return false;
}
// Check to see if correct number of bytes were written.
if( dwBytesWritten != count ) {
ret = false;
}
} catch (...) {
if (data != NULL) {
env->ReleasePrimitiveArrayCritical(dataArray, data, 0);
}
JNU_ThrowInternalError(env, "Problem in Win32PrintJob_printRawData");
return false;
}
env->ReleasePrimitiveArrayCritical(dataArray, data, 0);
return ret;
}
JNIEXPORT jboolean JNICALL
Java_sun_print_Win32PrintJob_endPrintRawData(JNIEnv *env,
jobject peer)
{
// retrieve handle
HANDLE hPrinter = getHPrinter(env, peer);
if (hPrinter == NULL) {
return false;
}
if ((::EndPagePrinter(hPrinter) != 0) &&
(::EndDocPrinter(hPrinter) != 0) &&
(::ClosePrinter(hPrinter) != 0)) {
return true;
} else {
return false;
}
}
} /* extern "C" */