Exemple #1
0
JNIEXPORT jintArray JNICALL Java_org_apache_harmony_x_print_GDIClient_getMediaIDs
(JNIEnv *env, jclass owner, jstring printerName) {
    const char *name = env->GetStringUTFChars(printerName, 0);
    jintArray result = NULL;
    
    PRINTER_INFO_2 *info = GetPrinterInfo(name);
    if (info != NULL) {
        int numPapersFirst = DeviceCapabilities(name, info->pPortName, DC_PAPERS, NULL, NULL);
        if (numPapersFirst > 0) {
            WORD *ids = new WORD[numPapersFirst];
            int numPapers = DeviceCapabilities(name, info->pPortName, DC_PAPERS, (LPSTR)ids, NULL);
            if (numPapers == numPapersFirst) {
                result = env->NewIntArray(numPapers);
                int *intIDs = new int[numPapers];
                for (int i = 0; i < numPapers; i++) {
                    intIDs[i] = (int)ids[i];
                }
                env->SetIntArrayRegion(result, 0, numPapers, (jint *)intIDs);
                delete[] intIDs;
            }
            delete[] ids;
        }
        free(info);
    }
    return result;
}
QWindowsPrintDevice::QWindowsPrintDevice(const QString &id)
    : QPlatformPrintDevice(id),
      m_hPrinter(0)
{
    // First do a fast lookup to see if printer exists, if it does then open it
    if (!id.isEmpty() && QWindowsPrintDevice::availablePrintDeviceIds().contains(id)) {
        if (OpenPrinter((LPWSTR)m_id.utf16(), &m_hPrinter, NULL)) {
            DWORD needed = 0;
            GetPrinter(m_hPrinter, 2, 0, 0, &needed);
            QScopedArrayPointer<BYTE> buffer(new BYTE[needed]);
            if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) {
                PPRINTER_INFO_2 info = reinterpret_cast<PPRINTER_INFO_2>(buffer.data());
                m_name = QString::fromWCharArray(info->pPrinterName);
                m_location = QString::fromWCharArray(info->pLocation);
                m_makeAndModel = QString::fromWCharArray(info->pDriverName); // TODO Check is not available elsewhere
                m_isRemote = info->Attributes & PRINTER_ATTRIBUTE_NETWORK;
            }
            m_supportsMultipleCopies = (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_COPIES, NULL, NULL) > 1);
            m_supportsCollateCopies = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_COLLATE, NULL, NULL);
            // Min/Max custom size is in tenths of a millimeter
            const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter);
            DWORD min = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_MINEXTENT, NULL, NULL);
            m_minimumPhysicalPageSize = QSize((LOWORD(min) / 10.0) * multiplier, (HIWORD(min) / 10.0) * multiplier);
            DWORD max = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_MAXEXTENT, NULL, NULL);
            m_maximumPhysicalPageSize = QSize((LOWORD(max) / 10.0) * multiplier, (HIWORD(max) / 10.0) * multiplier);
            m_supportsCustomPageSizes = (m_maximumPhysicalPageSize.width() > 0 && m_maximumPhysicalPageSize.height() > 0);
        }
    }
}
Exemple #3
0
JNIEXPORT jintArray JNICALL Java_org_apache_harmony_x_print_GDIClient_getResolutionsSupported
(JNIEnv *env, jclass owner, jstring printerName) {
    const char *name = env->GetStringUTFChars(printerName, 0);
    jintArray resolutions = NULL;
    
    PRINTER_INFO_2 *info = GetPrinterInfo(name);
    if (info != NULL) {
        int count = DeviceCapabilities(name, info->pPortName, DC_ENUMRESOLUTIONS, NULL, NULL);
        if (count > 0) {
            LONG *nativeArray = new LONG[count * 2];
            resolutions = env->NewIntArray(count * 2);
            if (DeviceCapabilities(name, info->pPortName, DC_ENUMRESOLUTIONS, (LPSTR)nativeArray, NULL) > 0) {
                jint *intArray = new jint[count * 2];
                for (int i = 0; i < count * 2; i++) {
                    intArray[i] = (jint)((int)nativeArray[i]);
                }
                env->SetIntArrayRegion(resolutions, 0, count * 2, intArray);     
                delete[] intArray;
            }
            delete[] nativeArray;
        }
        free(info);
    }
    return resolutions;
}
Exemple #4
0
JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_x_print_GDIClient_getMediaNames
(JNIEnv *env, jclass owner, jstring printerName) {
    const char *name = env->GetStringUTFChars(printerName, 0);
    jobjectArray result = NULL;
    
    PRINTER_INFO_2 *info = GetPrinterInfo(name);
    if (info != NULL) {
        int numNamesFirst = DeviceCapabilities(name, info->pPortName, DC_PAPERNAMES, NULL, NULL);
        if (numNamesFirst > 0) {
            char *buffer = new char[65 * numNamesFirst];
            int numNames = DeviceCapabilities(name, info->pPortName, DC_PAPERNAMES, (LPSTR)buffer, NULL);
            if (numNames == numNamesFirst) {
                jclass jstring_class = env->FindClass("java/lang/String");
                result = env->NewObjectArray(numNames, jstring_class, jstring());
                for (int i = 0; i < numNames; i++) {
                    char *name = buffer + i*64;
                    jstring jname = env->NewStringUTF(name); 
                    env->SetObjectArrayElement(result, i, jname);
                    env->DeleteLocalRef(jname);
                }
            }
            delete[] buffer;
        }
        free(info);
    }
    return result;
}
static void EnumeratePrinters() {
    str::Str<WCHAR> output;

    PRINTER_INFO_5 *info5Arr = nullptr;
    DWORD bufSize = 0, printersCount;
    bool fOk = EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, nullptr, 5, nullptr,
                            bufSize, &bufSize, &printersCount);
    if (fOk || GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
        info5Arr = (PRINTER_INFO_5 *)malloc(bufSize);
        fOk = EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, nullptr, 5,
                           (LPBYTE)info5Arr, bufSize, &bufSize, &printersCount);
    }
    if (!fOk || !info5Arr) {
        output.AppendFmt(L"Call to EnumPrinters failed with error %#x", GetLastError());
        MessageBox(nullptr, output.Get(), L"SumatraPDF - EnumeratePrinters", MB_OK | MB_ICONERROR);
        free(info5Arr);
        return;
    }
    ScopedMem<WCHAR> defName(GetDefaultPrinterName());
    for (DWORD i = 0; i < printersCount; i++) {
        const WCHAR *printerName = info5Arr[i].pPrinterName;
        const WCHAR *printerPort = info5Arr[i].pPortName;
        bool fDefault = str::Eq(defName, printerName);
        output.AppendFmt(L"%s (Port: %s, attributes: %#x%s)\n", printerName, printerPort,
                         info5Arr[i].Attributes, fDefault ? L", default" : L"");

        DWORD bins = DeviceCapabilities(printerName, printerPort, DC_BINS, nullptr, nullptr);
        DWORD binNames =
            DeviceCapabilities(printerName, printerPort, DC_BINNAMES, nullptr, nullptr);
        CrashIf(bins != binNames);
        if (0 == bins) {
            output.Append(L" - no paper bins available\n");
        } else if (bins == (DWORD)-1) {
            output.AppendFmt(L" - Call to DeviceCapabilities failed with error %#x\n",
                             GetLastError());
        } else {
            ScopedMem<WORD> binValues(AllocArray<WORD>(bins));
            DeviceCapabilities(printerName, printerPort, DC_BINS, (WCHAR *)binValues.Get(),
                               nullptr);
            ScopedMem<WCHAR> binNameValues(AllocArray<WCHAR>(24 * binNames));
            DeviceCapabilities(printerName, printerPort, DC_BINNAMES, binNameValues.Get(), nullptr);
            for (DWORD j = 0; j < bins; j++) {
                output.AppendFmt(L" - '%s' (%d)\n", binNameValues.Get() + 24 * j,
                                 binValues.Get()[j]);
            }
        }
    }
    free(info5Arr);
    MessageBox(nullptr, output.Get(), L"SumatraPDF - EnumeratePrinters",
               MB_OK | MB_ICONINFORMATION);
}
QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const
{
    const Q_D(QPrinterInfo);

    QList<QPrinter::PaperSize> paperSizes;
    if (isNull())
        return paperSizes;

    DWORD size = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->name.utf16()),
                                    NULL, DC_PAPERS, NULL, NULL);
    if ((int)size != -1) {
        wchar_t *papers = new wchar_t[size];
        size = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->name.utf16()),
                                  NULL, DC_PAPERS, papers, NULL);
        for (int c = 0; c < (int)size; ++c)
            paperSizes.append(mapDevmodePaperSize(papers[c]));
        delete [] papers;
    }

    return paperSizes;
}
Exemple #7
0
JNIEXPORT jint JNICALL Java_org_apache_harmony_x_print_GDIClient_getCopiesSupported
(JNIEnv *env, jclass owner, jstring printerName) {
    const char *name = env->GetStringUTFChars(printerName, 0);
    jint result = 0;
    
    PRINTER_INFO_2 *info = GetPrinterInfo(name);
    if (info != NULL) {
        result = DeviceCapabilities(name, info->pPortName, DC_COPIES, NULL, NULL);
        free(info);
    }
    return result;
}
void QWindowsPrintDevice::loadPageSizes() const
{
    // Get the number of paper sizes and check all 3 attributes have same count
    DWORD paperCount = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERNAMES, NULL, NULL);
    if (int(paperCount) > 0
        && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERSIZE, NULL, NULL) == paperCount
        && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERS, NULL, NULL) == paperCount) {

        QScopedArrayPointer<wchar_t> paperNames(new wchar_t[paperCount*64]);
        QScopedArrayPointer<POINT> winSizes(new POINT[paperCount*sizeof(POINT)]);
        QScopedArrayPointer<wchar_t> papers(new wchar_t[paperCount]);

        // Get the details and match the default paper size
        if (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERNAMES, paperNames.data(), NULL) == paperCount
            && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERSIZE, (wchar_t *)winSizes.data(), NULL) == paperCount
            && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERS, papers.data(), NULL) == paperCount) {

            // Returned size is in tenths of a millimeter
            const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter);
            for (int i = 0; i < int(paperCount); ++i) {
                QSize size = QSize(qRound((winSizes[i].x / 10.0) * multiplier), qRound((winSizes[i].y / 10.0) * multiplier));
                wchar_t *paper = paperNames.data() + (i * 64);
                QString name = QString::fromWCharArray(paper, qwcsnlen(paper, 64));
                m_pageSizes.append(createPageSize(papers[i], size, name));
            }

        }
    }

    m_havePageSizes = true;
}
Exemple #9
0
JNIEXPORT jint JNICALL Java_org_apache_harmony_x_print_GDIClient_getPagesPerMinuteColor
(JNIEnv *env, jclass owner, jstring printerName) {
    const char *name = env->GetStringUTFChars(printerName, 0);
    jint result = 0;
    
    PRINTER_INFO_2 *info = GetPrinterInfo(name);
    if (info != NULL) {
        info->pDevMode->dmColor = DMCOLOR_COLOR;
        result = DeviceCapabilities(name, info->pPortName, DC_PRINTRATEPPM, NULL, info->pDevMode);
        free(info);
    }
    return result;
}
static short GetPaperSourceByName(const WCHAR *name, LPDEVMODE devMode) {
    CrashIf(!(devMode->dmFields & DM_DEFAULTSOURCE));
    if (!(devMode->dmFields & DM_DEFAULTSOURCE))
        return devMode->dmDefaultSource;
    DWORD count = DeviceCapabilities(devMode->dmDeviceName, nullptr, DC_BINS, nullptr, nullptr);
    DWORD count2 =
        DeviceCapabilities(devMode->dmDeviceName, nullptr, DC_BINNAMES, nullptr, nullptr);
    if (count != count2 || 0 == count)
        return devMode->dmDefaultSource;
    // try to determine the paper bin number by name
    ScopedMem<WORD> bins(AllocArray<WORD>(count));
    ScopedMem<WCHAR> binNames(AllocArray<WCHAR>(24 * count + 1));
    DeviceCapabilities(devMode->dmDeviceName, nullptr, DC_BINS, (WCHAR *)bins.Get(), nullptr);
    DeviceCapabilities(devMode->dmDeviceName, nullptr, DC_BINNAMES, binNames.Get(), nullptr);
    for (DWORD i = 0; i < count; i++) {
        if (str::EqIS(binNames.Get() + 24 * i, name))
            return bins.Get()[i];
    }
    // alternatively allow indicating the paper bin directly by number
    if (str::Parse(L"%u%$", name, &count))
        return (short)count;
    return devMode->dmDefaultSource;
}
Exemple #11
0
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_GDIClient_getCollateSupported
(JNIEnv *env, jclass owner, jstring printerName) {
    const char *name = env->GetStringUTFChars(printerName, 0);
    jboolean result = JNI_FALSE;

    PRINTER_INFO_2 *info = GetPrinterInfo(name);
    if (info != NULL) {
        if (DeviceCapabilities(name, info->pPortName, DC_COLLATE, NULL, NULL) == 1) {
            result = JNI_TRUE;
        }
        free(info);
    }
    return result;
}
Exemple #12
0
JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_print_GDIClient_getOrientationSupported
(JNIEnv *env, jclass owner, jstring printerName) {
    const char *name = env->GetStringUTFChars(printerName, 0);
    jboolean result = JNI_FALSE;
    
    PRINTER_INFO_2 *info = GetPrinterInfo(name);
    if (info != NULL) {
        int orientation = DeviceCapabilities(name, info->pPortName, DC_ORIENTATION, NULL, NULL);
        if (orientation == 0 || orientation == 90 || orientation == 270) {
            result = JNI_TRUE;
        }
        free(info);
    }
    return result;
}
Exemple #13
0
JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_x_print_GDIClient_getMediaSizesSupported
(JNIEnv *env, jclass owner, jstring printerName) {
    const char *name = env->GetStringUTFChars(printerName, 0);
    jobjectArray result = NULL;
    
    PRINTER_INFO_2 *info = GetPrinterInfo(name);
    if (info != NULL) {
        int numSizes = DeviceCapabilities(name, info->pPortName, DC_PAPERSIZE, NULL, NULL);
        if (numSizes > 0) {
            POINT *sizes = new POINT[numSizes];
            int numSizes = DeviceCapabilities(name, info->pPortName, DC_PAPERSIZE, (LPSTR)sizes, NULL);
            if (numSizes > 0) {
                jclass IntArrayClass = env->FindClass("[I");
                result = env->NewObjectArray(numSizes, IntArrayClass, NULL);
                for (int i = 0; i < numSizes; i++) {
                    jintArray size = env->NewIntArray(2);
                    int *nativeArray = new int[2];
                    nativeArray[0] = sizes[i].x;
                    nativeArray[1] = sizes[i].y;
                    env->SetIntArrayRegion(size, 0, 2, (jint *)nativeArray);
                    env->SetObjectArrayElement(result, i, size);
                }
            }
        }

#ifdef PRINTING_DEBUG
        int count = DeviceCapabilities(name, info->pPortName, DC_PAPERS, NULL, NULL);
        if( count > 0 ) {
            printf("\n\n");
            WORD *papers = new WORD[count];
            count = DeviceCapabilities(name, info->pPortName, DC_PAPERS, (LPSTR)papers, NULL);
            printf("Found %d paper types.\n", count);
            for (int i = 0; i < count; i++) {
                printf("%d: %d\n", i+1, papers[i]);
            }
            delete [] papers;
        }
        
        int cnames = DeviceCapabilities(name, info->pPortName, DC_PAPERNAMES, NULL, NULL);
        if( cnames > 0 ) {
            printf("\n\n");
            char (*papernames)[64] = new char[cnames][64];
            cnames = DeviceCapabilities(name, info->pPortName, DC_PAPERNAMES, (LPSTR)papernames, NULL);
            printf("Found %d paper names.\n", cnames);
            for (int i = 0; i < cnames; i++) {
                printf("%d: %s\n", i+1, papernames[i]);
            }
            delete [] papernames;
        }
#endif /* PRINTING_DEBUG */
        free(info);
    }
    return result;
}
Exemple #14
0
WORD AwtPrintControl::getNearestMatchingPaper(LPTSTR printer, LPTSTR port,
                                      double origWid, double origHgt,
                                      double* newWid, double *newHgt) {
    const double epsilon = 0.50;
    const double tolerance = (1.0 * 72.0);  // # inches * 72
    int numPaperSizes = 0;
    WORD *papers = NULL;
    POINT *paperSizes = NULL;

    if ((printer== NULL) || (port == NULL)) {
        return 0;
    }

    SAVE_CONTROLWORD
    numPaperSizes = (int)DeviceCapabilities(printer, port, DC_PAPERSIZE,
                                              NULL, NULL);

    if (numPaperSizes > 0) {
        papers = (WORD*)safe_Malloc(sizeof(WORD) * numPaperSizes);
        paperSizes = (POINT *)safe_Malloc(sizeof(*paperSizes) *
                                          numPaperSizes);

        DWORD result1 = DeviceCapabilities(printer, port,
                                       DC_PAPERS, (LPTSTR) papers, NULL);

        DWORD result2 = DeviceCapabilities(printer, port,
                                       DC_PAPERSIZE, (LPTSTR) paperSizes,
                                       NULL);

        // REMIND: cache in papers and paperSizes
        if (result1 == -1 || result2 == -1 ) {
            free((LPTSTR) papers);
            papers = NULL;
            free((LPTSTR) paperSizes);
            paperSizes = NULL;
        }
    }
    RESTORE_CONTROLWORD

    double closestWid = 0.0;
    double closestHgt = 0.0;
    WORD   closestMatch = 0;

    if (paperSizes != NULL) {

      /* Paper sizes are in 0.1mm units. Convert to 1/72"
       * For each paper size, compute the difference from the paper size
       * passed in. Use a least-squares difference, so paper much different
       * in x or y should score poorly
       */
        double diffw = origWid;
        double diffh = origHgt;
        double least_square = diffw * diffw + diffh * diffh;
        double tmp_ls;
        double widpts, hgtpts;

        for (int i=0;i<numPaperSizes;i++) {
            widpts = paperSizes[i].x * LOMETRIC_TO_POINTS;
            hgtpts = paperSizes[i].y * LOMETRIC_TO_POINTS;

            if ((fabs(origWid - widpts) < epsilon) &&
                (fabs(origHgt - hgtpts) < epsilon)) {
                closestWid = origWid;
                closestHgt = origHgt;
                closestMatch = papers[i];
                break;
            }

            diffw = fabs(widpts - origWid);
            diffh = fabs(hgtpts - origHgt);
            tmp_ls = diffw * diffw + diffh * diffh;
            if ((diffw < tolerance) && (diffh < tolerance) &&
                (tmp_ls < least_square)) {
                least_square = tmp_ls;
                closestWid = widpts;
                closestHgt = hgtpts;
                closestMatch = papers[i];
            }
        }
    }

    if (closestWid > 0) {
        *newWid = closestWid;
    }
    if (closestHgt > 0) {
        *newHgt = closestHgt;
    }

    if (papers != NULL) {
        free((LPTSTR)papers);
    }

    if (paperSizes != NULL) {
        free((LPTSTR)paperSizes);
    }

    return closestMatch;
}
Exemple #15
0
/*
%F cdCreateCanvas para Impresora.
Usa a impressora default.
*/
static void cdcreatecanvas(cdCanvas* canvas, void *data)
{
  cdCtxCanvas* ctxcanvas;
  char *data_str = (char*) data;
  char docname[256] = "CD - Canvas Draw Document";
  DOCINFO di;
  HDC hDC;
  int dialog = 0, wtype;
  PRINTDLG pd;

  /* Inicializa parametros */
  if (data_str == NULL) 
    return;
  
  if (data_str[0] != 0)
  {
    char *ptr = strstr(data_str, "-d");

    if (ptr != NULL)
      dialog = 1;

    if (data_str[0] != '-')
    {
      strcpy(docname, data_str);

      if (dialog)
        docname[ptr - data_str - 1] = 0;
    }
  }
  
  ZeroMemory(&pd, sizeof(PRINTDLG));
  pd.lStructSize = sizeof(PRINTDLG);
  pd.nCopies = 1;

  if (dialog)
  {
    pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIES | PD_COLLATE | PD_NOPAGENUMS | PD_NOSELECTION;
    pd.hwndOwner = GetForegroundWindow();
  }
  else
  {
    pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
  }
  
  if (!PrintDlg(&pd))
  {
    if(pd.hDevMode) 
      GlobalFree(pd.hDevMode);
    if(pd.hDevNames) 
      GlobalFree(pd.hDevNames);
    return;
  }

  hDC = pd.hDC; 

  /* Inicializa documento */
  di.cbSize = sizeof(DOCINFO);
  di.lpszDocName = docname;
  di.lpszOutput = (LPTSTR) NULL;
  di.lpszDatatype = (LPTSTR) NULL; 
  di.fwType = 0; 

  StartDoc(hDC, &di);
  
  StartPage(hDC);
  
  wtype = CDW_EMF;
  
  /* Inicializa driver WIN32 */
  ctxcanvas = cdwCreateCanvas(canvas, NULL, hDC, wtype);
  
  canvas->w = GetDeviceCaps(hDC, HORZRES);
  canvas->h = GetDeviceCaps(hDC, VERTRES);
  canvas->w_mm = (double) GetDeviceCaps(hDC, HORZSIZE);
  canvas->h_mm = (double) GetDeviceCaps(hDC, VERTSIZE);
  canvas->bpp = GetDeviceCaps(hDC, BITSPIXEL);
  canvas->xres = canvas->w / canvas->w_mm;
  canvas->yres = canvas->h / canvas->h_mm;
  ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1;
  ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1;

  /* PDF Writer returns bpp=1, so we check if color is supported and overwrite this value */
  if (canvas->bpp==1 && pd.hDevNames)
  {
    unsigned char* devnames = (unsigned char*)GlobalLock(pd.hDevNames);
    DEVNAMES* dn = (DEVNAMES*)devnames;
    char* name = (char*)(devnames + dn->wDeviceOffset);
    char* port = (char*)(devnames + dn->wOutputOffset);

    if (DeviceCapabilities(name, port, DC_COLORDEVICE, NULL, NULL))
      canvas->bpp = 24;

    GlobalUnlock(pd.hDevNames);
  }

  if(pd.hDevMode) 
    GlobalFree(pd.hDevMode);
  if(pd.hDevNames) 
    GlobalFree(pd.hDevNames);
}
Exemple #16
0
/* Get Device Context for printer */
static int
win_pr2_getdc(gx_device_win_pr2 * wdev)
{
    char *device;
    char *devices;
    char *p;
    char driverbuf[512];
    char *driver;
    char *output;
    char *devcap;
    int devcapsize;
    int devmode_size;

    int i, n;
    POINT *pp;
    int paperindex;
    int paperwidth, paperheight;
    int orientation;
    int papersize;
    char papername[64];
    LPDEVMODE podevmode, pidevmode;
    HANDLE hprinter;

    /* first try to derive the printer name from -sOutputFile= */
    /* is printer if name prefixed by \\spool\ or by %printer% */
    if (is_spool(wdev->fname)) {
	device = wdev->fname + 8;	/* skip over \\spool\ */
	wdev->use_old_spool_name = true;
    } else if (strncmp("%printer%",wdev->fname,9) == 0) {
	device = wdev->fname + 9;	/* skip over %printer% */
	wdev->use_old_spool_name = false;
    } else {
	return FALSE;
    }

    /* now try to match the printer name against the [Devices] section */
    if ((devices = gs_malloc(wdev->memory, 4096, 1, "win_pr2_getdc")) == (char *)NULL)
	return FALSE;
    GetProfileString("Devices", NULL, "", devices, 4096);
    p = devices;
    while (*p) {
	if (stricmp(p, device) == 0)
	    break;
	p += strlen(p) + 1;
    }
    if (*p == '\0')
	p = NULL;
    gs_free(wdev->memory, devices, 4096, 1, "win_pr2_getdc");
    if (p == NULL)
	return FALSE;		/* doesn't match an available printer */

    /* the printer exists, get the remaining information from win.ini */
    GetProfileString("Devices", device, "", driverbuf, sizeof(driverbuf));
    driver = strtok(driverbuf, ",");
    output = strtok(NULL, ",");

    if (!OpenPrinter(device, &hprinter, NULL))
	return FALSE;
    devmode_size = DocumentProperties(NULL, hprinter, device, NULL, NULL, 0);
    if ((podevmode = gs_malloc(wdev->memory, devmode_size, 1, "win_pr2_getdc"))
	== (LPDEVMODE) NULL) {
	ClosePrinter(hprinter);
	return FALSE;
    }
    if ((pidevmode = gs_malloc(wdev->memory, devmode_size, 1, "win_pr2_getdc"))		== (LPDEVMODE) NULL) {
	gs_free(wdev->memory, podevmode, devmode_size, 1, "win_pr2_getdc");
	ClosePrinter(hprinter);
	return FALSE;
    }
    DocumentProperties(NULL, hprinter, device, podevmode, NULL, DM_OUT_BUFFER);

    /* now find out what paper sizes are available */
    devcapsize = DeviceCapabilities(device, output, DC_PAPERSIZE, NULL, NULL);
    devcapsize *= sizeof(POINT);
    if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
	return FALSE;
    n = DeviceCapabilities(device, output, DC_PAPERSIZE, devcap, NULL);
    paperwidth = (int)(wdev->MediaSize[0] * 254 / 72);
    paperheight = (int)(wdev->MediaSize[1] * 254 / 72);
    papername[0] = '\0';
    papersize = 0;
    paperindex = -1;
    orientation = 0;
    pp = (POINT *) devcap;
    for (i = 0; i < n; i++, pp++) {
	if ((pp->x < paperwidth + 20) && (pp->x > paperwidth - 20) &&
	    (pp->y < paperheight + 20) && (pp->y > paperheight - 20)) {
	    paperindex = i;
	    paperwidth = pp->x;
	    paperheight = pp->y;
	    orientation = DMORIENT_PORTRAIT;
	    break;
	}
    }
    if (paperindex < 0) {
	/* try again in landscape */
	pp = (POINT *) devcap;
	for (i = 0; i < n; i++, pp++) {
	    if ((pp->x < paperheight + 20) && (pp->x > paperheight - 20) &&
		(pp->y < paperwidth + 20) && (pp->y > paperwidth - 20)) {
		paperindex = i;
		paperwidth = pp->x;
		paperheight = pp->y;
		orientation = DMORIENT_LANDSCAPE;
		break;
	    }
	}
    }
    gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");
    
    /* get the dmPaperSize */
    devcapsize = DeviceCapabilities(device, output, DC_PAPERS, NULL, NULL);
    devcapsize *= sizeof(WORD);
    if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
	return FALSE;
    n = DeviceCapabilities(device, output, DC_PAPERS, devcap, NULL);
    if ((paperindex >= 0) && (paperindex < n))
	papersize = ((WORD *) devcap)[paperindex];
    gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");

    /* get the paper name */
    devcapsize = DeviceCapabilities(device, output, DC_PAPERNAMES, NULL, NULL);
    devcapsize *= 64;
    if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
	return FALSE;
    n = DeviceCapabilities(device, output, DC_PAPERNAMES, devcap, NULL);
    if ((paperindex >= 0) && (paperindex < n))
	strcpy(papername, devcap + paperindex * 64);
    gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");

    memcpy(pidevmode, podevmode, devmode_size);

    pidevmode->dmFields = 0;
    
    wdev->paper_name[0] = 0;

    if ( (wdev->user_paper)
      && (wdev->user_paper != papersize) ) {
	papersize = wdev->user_paper;
	paperheight = 0;
	paperwidth = 0;
	papername[0] = 0;
    }
    if (wdev->user_orient) {
	orientation = wdev->user_orient;
    }
    
    pidevmode->dmFields &= ~(DM_PAPERSIZE | DM_ORIENTATION | DM_COLOR | DM_PAPERLENGTH | DM_PAPERWIDTH | DM_DUPLEX);
    pidevmode->dmFields |= DM_DEFAULTSOURCE;
    pidevmode->dmDefaultSource = 0;
    
    if (orientation) {
	wdev->user_orient = orientation;
    }
    if (papersize) {
	wdev->user_paper = papersize;
	strcpy (wdev->paper_name, papername);
    }
    
    if (paperheight && paperwidth) {
	pidevmode->dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
	pidevmode->dmPaperWidth = paperwidth;
	pidevmode->dmPaperLength = paperheight;
        wdev->user_media_size[0] = paperwidth / 254.0 * 72.0;
	wdev->user_media_size[1] = paperheight / 254.0 * 72.0;
    }
    
    if (DeviceCapabilities(device, output, DC_DUPLEX, NULL, NULL)) {
	wdev->Duplex_set = 1;
    }
    
    win_pr2_update_win(wdev, pidevmode);
    
    /* merge the entries */
    DocumentProperties(NULL, hprinter, device, podevmode, pidevmode, DM_IN_BUFFER | DM_OUT_BUFFER);
    ClosePrinter(hprinter);
    
    /* now get a DC */
    wdev->hdcprn = CreateDC(driver, device, NULL, podevmode);
    
    if (wdev->win32_hdevmode == NULL)
	wdev->win32_hdevmode = GlobalAlloc(0, devmode_size);
    
    if (wdev->win32_hdevmode) {
	LPDEVMODE pdevmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
	if (pdevmode) {
	    memcpy(pdevmode, podevmode, devmode_size);
	    GlobalUnlock(wdev->win32_hdevmode);
	}
    }

    gs_free(wdev->memory, pidevmode, devmode_size, 1, "win_pr2_getdc");
    gs_free(wdev->memory, podevmode, devmode_size, 1, "win_pr2_getdc");

    if (wdev->hdcprn != (HDC) NULL)
	return TRUE;		/* success */

    /* fall back to prompting user */
    return FALSE;
}