xref: /plan9/sys/src/cmd/gs/src/gp_mswin.c (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
1*3ff48bf5SDavid du Colombier /* Copyright (C) 1992, 2000 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*3ff48bf5SDavid du Colombier   This file is part of AFPL Ghostscript.
47dd7cddfSDavid du Colombier 
5*3ff48bf5SDavid du Colombier   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
6*3ff48bf5SDavid du Colombier   distributor accepts any responsibility for the consequences of using it, or
7*3ff48bf5SDavid du Colombier   for whether it serves any particular purpose or works at all, unless he or
8*3ff48bf5SDavid du Colombier   she says so in writing.  Refer to the Aladdin Free Public License (the
9*3ff48bf5SDavid du Colombier   "License") for full details.
107dd7cddfSDavid du Colombier 
11*3ff48bf5SDavid du Colombier   Every copy of AFPL Ghostscript must include a copy of the License, normally
12*3ff48bf5SDavid du Colombier   in a plain ASCII text file named PUBLIC.  The License grants you the right
13*3ff48bf5SDavid du Colombier   to copy, modify and redistribute AFPL Ghostscript, but only under certain
14*3ff48bf5SDavid du Colombier   conditions described in the License.  Among other things, the License
15*3ff48bf5SDavid du Colombier   requires that the copyright notice and this notice be preserved on all
16*3ff48bf5SDavid du Colombier   copies.
177dd7cddfSDavid du Colombier */
187dd7cddfSDavid du Colombier 
19*3ff48bf5SDavid du Colombier /*$Id: gp_mswin.c,v 1.7 2001/09/22 07:07:02 ghostgum Exp $ */
207dd7cddfSDavid du Colombier /*
21*3ff48bf5SDavid du Colombier  * Microsoft Windows platform support for Ghostscript.
227dd7cddfSDavid du Colombier  *
237dd7cddfSDavid du Colombier  * Original version by Russell Lang and Maurice Castro with help from
247dd7cddfSDavid du Colombier  * Programming Windows, 2nd Ed., Charles Petzold, Microsoft Press;
257dd7cddfSDavid du Colombier  * initially created from gp_dosfb.c and gp_itbc.c 5th June 1992.
267dd7cddfSDavid du Colombier  */
277dd7cddfSDavid du Colombier 
287dd7cddfSDavid du Colombier /* Modified for Win32 & Microsoft C/C++ 8.0 32-Bit, 26.Okt.1994 */
297dd7cddfSDavid du Colombier /* by Friedrich Nowak                                           */
307dd7cddfSDavid du Colombier 
317dd7cddfSDavid du Colombier /* Original EXE and GSview specific code removed */
327dd7cddfSDavid du Colombier /* DLL version must now be used under MS-Windows */
337dd7cddfSDavid du Colombier /* Russell Lang 16 March 1996 */
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier #include "stdio_.h"
367dd7cddfSDavid du Colombier #include "string_.h"
377dd7cddfSDavid du Colombier #include "memory_.h"
387dd7cddfSDavid du Colombier #include <stdlib.h>
397dd7cddfSDavid du Colombier #include <stdarg.h>
407dd7cddfSDavid du Colombier #include "ctype_.h"
417dd7cddfSDavid du Colombier #include "dos_.h"
427dd7cddfSDavid du Colombier #include <io.h>
437dd7cddfSDavid du Colombier #include "malloc_.h"
447dd7cddfSDavid du Colombier #include <fcntl.h>
457dd7cddfSDavid du Colombier #include <signal.h>
467dd7cddfSDavid du Colombier #include "gx.h"
477dd7cddfSDavid du Colombier #include "gp.h"
487dd7cddfSDavid du Colombier #include "gpcheck.h"
49*3ff48bf5SDavid du Colombier #include "gpmisc.h"
507dd7cddfSDavid du Colombier #include "gserrors.h"
517dd7cddfSDavid du Colombier #include "gsexit.h"
527dd7cddfSDavid du Colombier 
537dd7cddfSDavid du Colombier #include "windows_.h"
547dd7cddfSDavid du Colombier #include <shellapi.h>
557dd7cddfSDavid du Colombier #include <winspool.h>
567dd7cddfSDavid du Colombier #include "gp_mswin.h"
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier /* Library routines not declared in a standard header */
597dd7cddfSDavid du Colombier extern char *getenv(P1(const char *));
607dd7cddfSDavid du Colombier 
617dd7cddfSDavid du Colombier /* limits */
627dd7cddfSDavid du Colombier #define MAXSTR 255
637dd7cddfSDavid du Colombier 
64*3ff48bf5SDavid du Colombier /* GLOBAL VARIABLE that needs to be removed */
65*3ff48bf5SDavid du Colombier char win_prntmp[MAXSTR];	/* filename of PRN temporary file */
66*3ff48bf5SDavid du Colombier 
67*3ff48bf5SDavid du Colombier /* GLOBAL VARIABLES - initialised at DLL load time */
687dd7cddfSDavid du Colombier HINSTANCE phInstance;
69*3ff48bf5SDavid du Colombier BOOL is_win32s = FALSE;
707dd7cddfSDavid du Colombier 
717dd7cddfSDavid du Colombier const LPSTR szAppName = "Ghostscript";
727dd7cddfSDavid du Colombier private int is_printer(const char *name);
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier 
757dd7cddfSDavid du Colombier /* ====== Generic platform procedures ====== */
767dd7cddfSDavid du Colombier 
777dd7cddfSDavid du Colombier /* ------ Initialization/termination (from gp_itbc.c) ------ */
787dd7cddfSDavid du Colombier 
797dd7cddfSDavid du Colombier /* Do platform-dependent initialization. */
807dd7cddfSDavid du Colombier void
817dd7cddfSDavid du Colombier gp_init(void)
827dd7cddfSDavid du Colombier {
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier 
857dd7cddfSDavid du Colombier /* Do platform-dependent cleanup. */
867dd7cddfSDavid du Colombier void
877dd7cddfSDavid du Colombier gp_exit(int exit_status, int code)
887dd7cddfSDavid du Colombier {
897dd7cddfSDavid du Colombier }
907dd7cddfSDavid du Colombier 
917dd7cddfSDavid du Colombier /* Exit the program. */
927dd7cddfSDavid du Colombier void
937dd7cddfSDavid du Colombier gp_do_exit(int exit_status)
947dd7cddfSDavid du Colombier {
957dd7cddfSDavid du Colombier }
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier /* ------ Printer accessing ------ */
987dd7cddfSDavid du Colombier 
997dd7cddfSDavid du Colombier /* Forward references */
1007dd7cddfSDavid du Colombier private int gp_printfile(P2(const char *, const char *));
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier /* Open a connection to a printer.  A null file name means use the */
1037dd7cddfSDavid du Colombier /* standard printer connected to the machine, if any. */
1047dd7cddfSDavid du Colombier /* Return NULL if the connection could not be opened. */
1057dd7cddfSDavid du Colombier FILE *
1067dd7cddfSDavid du Colombier gp_open_printer(char fname[gp_file_name_sizeof], int binary_mode)
1077dd7cddfSDavid du Colombier {
1087dd7cddfSDavid du Colombier     if (is_printer(fname)) {
1097dd7cddfSDavid du Colombier 	FILE *pfile;
1107dd7cddfSDavid du Colombier 
1117dd7cddfSDavid du Colombier 	/* Open a scratch file, which we will send to the */
1127dd7cddfSDavid du Colombier 	/* actual printer in gp_close_printer. */
1137dd7cddfSDavid du Colombier 	pfile = gp_open_scratch_file(gp_scratch_file_name_prefix,
1147dd7cddfSDavid du Colombier 				     win_prntmp, "wb");
1157dd7cddfSDavid du Colombier 	return pfile;
1167dd7cddfSDavid du Colombier     } else
1177dd7cddfSDavid du Colombier 	return fopen(fname, (binary_mode ? "wb" : "w"));
1187dd7cddfSDavid du Colombier }
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier /* Close the connection to the printer. */
1217dd7cddfSDavid du Colombier void
1227dd7cddfSDavid du Colombier gp_close_printer(FILE * pfile, const char *fname)
1237dd7cddfSDavid du Colombier {
1247dd7cddfSDavid du Colombier     fclose(pfile);
1257dd7cddfSDavid du Colombier     if (!is_printer(fname))
1267dd7cddfSDavid du Colombier 	return;			/* a file, not a printer */
1277dd7cddfSDavid du Colombier 
1287dd7cddfSDavid du Colombier     gp_printfile(win_prntmp, fname);
1297dd7cddfSDavid du Colombier     unlink(win_prntmp);
1307dd7cddfSDavid du Colombier }
1317dd7cddfSDavid du Colombier 
1327dd7cddfSDavid du Colombier 
1337dd7cddfSDavid du Colombier /* Dialog box to select printer port */
134*3ff48bf5SDavid du Colombier BOOL CALLBACK
1357dd7cddfSDavid du Colombier SpoolDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1367dd7cddfSDavid du Colombier {
1377dd7cddfSDavid du Colombier     LPSTR entry;
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier     switch (message) {
1407dd7cddfSDavid du Colombier 	case WM_INITDIALOG:
1417dd7cddfSDavid du Colombier 	    entry = (LPSTR) lParam;
1427dd7cddfSDavid du Colombier 	    while (*entry) {
1437dd7cddfSDavid du Colombier 		SendDlgItemMessage(hDlg, SPOOL_PORT, LB_ADDSTRING, 0, (LPARAM) entry);
1447dd7cddfSDavid du Colombier 		entry += lstrlen(entry) + 1;
1457dd7cddfSDavid du Colombier 	    }
1467dd7cddfSDavid du Colombier 	    SendDlgItemMessage(hDlg, SPOOL_PORT, LB_SETCURSEL, 0, (LPARAM) 0);
1477dd7cddfSDavid du Colombier 	    return TRUE;
1487dd7cddfSDavid du Colombier 	case WM_COMMAND:
1497dd7cddfSDavid du Colombier 	    switch (LOWORD(wParam)) {
1507dd7cddfSDavid du Colombier 		case SPOOL_PORT:
151*3ff48bf5SDavid du Colombier 		    if (HIWORD(wParam) == LBN_DBLCLK)
1527dd7cddfSDavid du Colombier 			PostMessage(hDlg, WM_COMMAND, IDOK, 0L);
1537dd7cddfSDavid du Colombier 		    return FALSE;
1547dd7cddfSDavid du Colombier 		case IDOK:
1557dd7cddfSDavid du Colombier 		    EndDialog(hDlg, 1 + (int)SendDlgItemMessage(hDlg, SPOOL_PORT, LB_GETCURSEL, 0, 0L));
1567dd7cddfSDavid du Colombier 		    return TRUE;
1577dd7cddfSDavid du Colombier 		case IDCANCEL:
1587dd7cddfSDavid du Colombier 		    EndDialog(hDlg, 0);
1597dd7cddfSDavid du Colombier 		    return TRUE;
1607dd7cddfSDavid du Colombier 	    }
1617dd7cddfSDavid du Colombier     }
1627dd7cddfSDavid du Colombier     return FALSE;
1637dd7cddfSDavid du Colombier }
1647dd7cddfSDavid du Colombier 
1657dd7cddfSDavid du Colombier /* return TRUE if queue looks like a valid printer name */
1667dd7cddfSDavid du Colombier int
1677dd7cddfSDavid du Colombier is_spool(const char *queue)
1687dd7cddfSDavid du Colombier {
1697dd7cddfSDavid du Colombier     char *prefix = "\\\\spool";	/* 7 characters long */
1707dd7cddfSDavid du Colombier     int i;
1717dd7cddfSDavid du Colombier 
1727dd7cddfSDavid du Colombier     for (i = 0; i < 7; i++) {
1737dd7cddfSDavid du Colombier 	if (prefix[i] == '\\') {
1747dd7cddfSDavid du Colombier 	    if ((*queue != '\\') && (*queue != '/'))
1757dd7cddfSDavid du Colombier 		return FALSE;
1767dd7cddfSDavid du Colombier 	} else if (tolower(*queue) != prefix[i])
1777dd7cddfSDavid du Colombier 	    return FALSE;
1787dd7cddfSDavid du Colombier 	queue++;
1797dd7cddfSDavid du Colombier     }
1807dd7cddfSDavid du Colombier     if (*queue && (*queue != '\\') && (*queue != '/'))
1817dd7cddfSDavid du Colombier 	return FALSE;
1827dd7cddfSDavid du Colombier     return TRUE;
1837dd7cddfSDavid du Colombier }
1847dd7cddfSDavid du Colombier 
1857dd7cddfSDavid du Colombier 
1867dd7cddfSDavid du Colombier private int
1877dd7cddfSDavid du Colombier is_printer(const char *name)
1887dd7cddfSDavid du Colombier {
1897dd7cddfSDavid du Colombier     char buf[128];
1907dd7cddfSDavid du Colombier 
1917dd7cddfSDavid du Colombier     /* is printer if no name given */
1927dd7cddfSDavid du Colombier     if (strlen(name) == 0)
1937dd7cddfSDavid du Colombier 	return TRUE;
1947dd7cddfSDavid du Colombier 
1957dd7cddfSDavid du Colombier     /*  is printer if name appears in win.ini [ports] section */
1967dd7cddfSDavid du Colombier     GetProfileString("ports", name, "XYZ", buf, sizeof(buf));
1977dd7cddfSDavid du Colombier     if (strlen(name) == 0 || strcmp(buf, "XYZ"))
1987dd7cddfSDavid du Colombier 	return TRUE;
1997dd7cddfSDavid du Colombier 
2007dd7cddfSDavid du Colombier     /* is printer if name prefixed by \\spool\ */
2017dd7cddfSDavid du Colombier     if (is_spool(name))
2027dd7cddfSDavid du Colombier 	return TRUE;
2037dd7cddfSDavid du Colombier 
2047dd7cddfSDavid du Colombier     return FALSE;
2057dd7cddfSDavid du Colombier }
2067dd7cddfSDavid du Colombier 
2077dd7cddfSDavid du Colombier 
2087dd7cddfSDavid du Colombier /******************************************************************/
2097dd7cddfSDavid du Colombier /* Print File to port or queue */
2107dd7cddfSDavid du Colombier /* port==NULL means prompt for port or queue with dialog box */
2117dd7cddfSDavid du Colombier 
2127dd7cddfSDavid du Colombier /* This is messy because Microsoft changed the spooler interface */
213*3ff48bf5SDavid du Colombier /* between Windows 3.1 and Windows 95/NT */
2147dd7cddfSDavid du Colombier /* and didn't provide the spooler interface in Win32s */
2157dd7cddfSDavid du Colombier 
2167dd7cddfSDavid du Colombier /* Win95, WinNT: Use OpenPrinter, WritePrinter etc. */
2177dd7cddfSDavid du Colombier private int gp_printfile_win32(const char *filename, char *port);
2187dd7cddfSDavid du Colombier 
2197dd7cddfSDavid du Colombier /* Win32s: Pass to Win16 spooler via gs16spl.exe */
2207dd7cddfSDavid du Colombier private int gp_printfile_gs16spl(const char *filename, const char *port);
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier /*
2237dd7cddfSDavid du Colombier  * Valid values for pmport are:
2247dd7cddfSDavid du Colombier  *   ""
2257dd7cddfSDavid du Colombier  *      action: WinNT and Win95 use default queue, Win32s prompts for port
2267dd7cddfSDavid du Colombier  *   "LPT1:" (or other port that appears in win.ini [ports]
2277dd7cddfSDavid du Colombier  *      action: start gs16spl.exe to print to the port
2287dd7cddfSDavid du Colombier  *   "\\spool\printer name"
2297dd7cddfSDavid du Colombier  *      action: send to printer using WritePrinter (WinNT and Win95).
2307dd7cddfSDavid du Colombier  *      action: translate to port name using win.ini [Devices]
2317dd7cddfSDavid du Colombier  *              then use gs16spl.exe (Win32s).
2327dd7cddfSDavid du Colombier  *   "\\spool"
2337dd7cddfSDavid du Colombier  *      action: prompt for queue name then send to printer using
2347dd7cddfSDavid du Colombier  *              WritePrinter (WinNT and Win95).
2357dd7cddfSDavid du Colombier  *      action: prompt for port then use gs16spl.exe (Win32s).
2367dd7cddfSDavid du Colombier  */
2377dd7cddfSDavid du Colombier /* Print File */
2387dd7cddfSDavid du Colombier private int
2397dd7cddfSDavid du Colombier gp_printfile(const char *filename, const char *pmport)
2407dd7cddfSDavid du Colombier {
2417dd7cddfSDavid du Colombier     /* treat WinNT and Win95 differently to Win32s */
2427dd7cddfSDavid du Colombier     if (!is_win32s) {
2437dd7cddfSDavid du Colombier 	if (strlen(pmport) == 0) {	/* get default printer */
2447dd7cddfSDavid du Colombier 	    char buf[256];
2457dd7cddfSDavid du Colombier 	    char *p;
2467dd7cddfSDavid du Colombier 
2477dd7cddfSDavid du Colombier 	    /* WinNT stores default printer in registry and win.ini */
2487dd7cddfSDavid du Colombier 	    /* Win95 stores default printer in win.ini */
2497dd7cddfSDavid du Colombier 	    GetProfileString("windows", "device", "", buf, sizeof(buf));
2507dd7cddfSDavid du Colombier 	    if ((p = strchr(buf, ',')) != NULL)
2517dd7cddfSDavid du Colombier 		*p = '\0';
2527dd7cddfSDavid du Colombier 	    return gp_printfile_win32(filename, buf);
2537dd7cddfSDavid du Colombier 	} else if (is_spool(pmport)) {
2547dd7cddfSDavid du Colombier 	    if (strlen(pmport) >= 8)
2557dd7cddfSDavid du Colombier 		return gp_printfile_win32(filename, (char *)pmport + 8);
2567dd7cddfSDavid du Colombier 	    else
2577dd7cddfSDavid du Colombier 		return gp_printfile_win32(filename, (char *)NULL);
2587dd7cddfSDavid du Colombier 	} else
2597dd7cddfSDavid du Colombier 	    return gp_printfile_gs16spl(filename, pmport);
2607dd7cddfSDavid du Colombier     } else {
2617dd7cddfSDavid du Colombier 	/* Win32s */
2627dd7cddfSDavid du Colombier 	if (is_spool(pmport)) {
2637dd7cddfSDavid du Colombier 	    if (strlen(pmport) >= 8) {
2647dd7cddfSDavid du Colombier 		/* extract port name from win.ini */
2657dd7cddfSDavid du Colombier 		char driverbuf[256];
2667dd7cddfSDavid du Colombier 		char *output;
2677dd7cddfSDavid du Colombier 
2687dd7cddfSDavid du Colombier 		GetProfileString("Devices", pmport + 8, "", driverbuf, sizeof(driverbuf));
2697dd7cddfSDavid du Colombier 		strtok(driverbuf, ",");
2707dd7cddfSDavid du Colombier 		output = strtok(NULL, ",");
2717dd7cddfSDavid du Colombier 		return gp_printfile_gs16spl(filename, output);
2727dd7cddfSDavid du Colombier 	    } else
2737dd7cddfSDavid du Colombier 		return gp_printfile_gs16spl(filename, (char *)NULL);
2747dd7cddfSDavid du Colombier 	} else
2757dd7cddfSDavid du Colombier 	    return gp_printfile_gs16spl(filename, pmport);
2767dd7cddfSDavid du Colombier     }
2777dd7cddfSDavid du Colombier }
2787dd7cddfSDavid du Colombier 
2797dd7cddfSDavid du Colombier #define PRINT_BUF_SIZE 16384u
2807dd7cddfSDavid du Colombier #define PORT_BUF_SIZE 4096
2817dd7cddfSDavid du Colombier 
2827dd7cddfSDavid du Colombier char *
2837dd7cddfSDavid du Colombier get_queues(void)
2847dd7cddfSDavid du Colombier {
2857dd7cddfSDavid du Colombier     int i;
2867dd7cddfSDavid du Colombier     DWORD count, needed;
2877dd7cddfSDavid du Colombier     PRINTER_INFO_1 *prinfo;
2887dd7cddfSDavid du Colombier     char *enumbuffer;
2897dd7cddfSDavid du Colombier     char *buffer;
2907dd7cddfSDavid du Colombier     char *p;
2917dd7cddfSDavid du Colombier 
2927dd7cddfSDavid du Colombier     /* enumerate all available printers */
2937dd7cddfSDavid du Colombier     EnumPrinters(PRINTER_ENUM_CONNECTIONS | PRINTER_ENUM_LOCAL, NULL, 1, NULL, 0, &needed, &count);
2947dd7cddfSDavid du Colombier     if (needed == 0) {
2957dd7cddfSDavid du Colombier 	/* no printers */
2967dd7cddfSDavid du Colombier 	enumbuffer = malloc(4);
2977dd7cddfSDavid du Colombier 	if (enumbuffer == (char *)NULL)
2987dd7cddfSDavid du Colombier 	    return NULL;
2997dd7cddfSDavid du Colombier 	memset(enumbuffer, 0, 4);
3007dd7cddfSDavid du Colombier 	return enumbuffer;
3017dd7cddfSDavid du Colombier     }
3027dd7cddfSDavid du Colombier     enumbuffer = malloc(needed);
3037dd7cddfSDavid du Colombier     if (enumbuffer == (char *)NULL)
3047dd7cddfSDavid du Colombier 	return NULL;
3057dd7cddfSDavid du Colombier     if (!EnumPrinters(PRINTER_ENUM_CONNECTIONS | PRINTER_ENUM_LOCAL, NULL, 1, (LPBYTE) enumbuffer, needed, &needed, &count)) {
3067dd7cddfSDavid du Colombier 	char buf[256];
3077dd7cddfSDavid du Colombier 
3087dd7cddfSDavid du Colombier 	free(enumbuffer);
3097dd7cddfSDavid du Colombier 	sprintf(buf, "EnumPrinters() failed, error code = %d", GetLastError());
3107dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
3117dd7cddfSDavid du Colombier 	return NULL;
3127dd7cddfSDavid du Colombier     }
3137dd7cddfSDavid du Colombier     prinfo = (PRINTER_INFO_1 *) enumbuffer;
3147dd7cddfSDavid du Colombier     if ((buffer = malloc(PORT_BUF_SIZE)) == (char *)NULL) {
3157dd7cddfSDavid du Colombier 	free(enumbuffer);
3167dd7cddfSDavid du Colombier 	return NULL;
3177dd7cddfSDavid du Colombier     }
3187dd7cddfSDavid du Colombier     /* copy printer names to single buffer */
3197dd7cddfSDavid du Colombier     p = buffer;
3207dd7cddfSDavid du Colombier     for (i = 0; i < count; i++) {
3217dd7cddfSDavid du Colombier 	if (strlen(prinfo[i].pName) + 1 < (PORT_BUF_SIZE - (p - buffer))) {
3227dd7cddfSDavid du Colombier 	    strcpy(p, prinfo[i].pName);
3237dd7cddfSDavid du Colombier 	    p += strlen(p) + 1;
3247dd7cddfSDavid du Colombier 	}
3257dd7cddfSDavid du Colombier     }
3267dd7cddfSDavid du Colombier     *p = '\0';			/* double null at end */
3277dd7cddfSDavid du Colombier     free(enumbuffer);
3287dd7cddfSDavid du Colombier     return buffer;
3297dd7cddfSDavid du Colombier }
3307dd7cddfSDavid du Colombier 
3317dd7cddfSDavid du Colombier 
3327dd7cddfSDavid du Colombier char *
3337dd7cddfSDavid du Colombier get_ports(void)
3347dd7cddfSDavid du Colombier {
3357dd7cddfSDavid du Colombier     char *buffer;
3367dd7cddfSDavid du Colombier 
3377dd7cddfSDavid du Colombier     if (!is_win32s)
3387dd7cddfSDavid du Colombier 	return get_queues();
3397dd7cddfSDavid du Colombier 
3407dd7cddfSDavid du Colombier     if ((buffer = malloc(PORT_BUF_SIZE)) == (char *)NULL)
3417dd7cddfSDavid du Colombier 	return NULL;
3427dd7cddfSDavid du Colombier     GetProfileString("ports", NULL, "", buffer, PORT_BUF_SIZE);
3437dd7cddfSDavid du Colombier     return buffer;
3447dd7cddfSDavid du Colombier }
3457dd7cddfSDavid du Colombier 
3467dd7cddfSDavid du Colombier /* return TRUE if queuename available */
3477dd7cddfSDavid du Colombier /* return FALSE if cancelled or error */
3487dd7cddfSDavid du Colombier /* if queue non-NULL, use as suggested queue */
3497dd7cddfSDavid du Colombier BOOL
3507dd7cddfSDavid du Colombier get_queuename(char *portname, const char *queue)
3517dd7cddfSDavid du Colombier {
3527dd7cddfSDavid du Colombier     char *buffer;
3537dd7cddfSDavid du Colombier     char *p;
3547dd7cddfSDavid du Colombier     int i, iport;
3557dd7cddfSDavid du Colombier 
3567dd7cddfSDavid du Colombier     buffer = get_queues();
3577dd7cddfSDavid du Colombier     if (buffer == NULL)
3587dd7cddfSDavid du Colombier 	return FALSE;
3597dd7cddfSDavid du Colombier     if ((queue == (char *)NULL) || (strlen(queue) == 0)) {
3607dd7cddfSDavid du Colombier 	/* select a queue */
3617dd7cddfSDavid du Colombier 	iport = DialogBoxParam(phInstance, "QueueDlgBox", (HWND) NULL, SpoolDlgProc, (LPARAM) buffer);
3627dd7cddfSDavid du Colombier 	if (!iport) {
3637dd7cddfSDavid du Colombier 	    free(buffer);
3647dd7cddfSDavid du Colombier 	    return FALSE;
3657dd7cddfSDavid du Colombier 	}
3667dd7cddfSDavid du Colombier 	p = buffer;
3677dd7cddfSDavid du Colombier 	for (i = 1; i < iport && strlen(p) != 0; i++)
3687dd7cddfSDavid du Colombier 	    p += lstrlen(p) + 1;
3697dd7cddfSDavid du Colombier 	/* prepend \\spool\ which is used by Ghostscript to distinguish */
3707dd7cddfSDavid du Colombier 	/* real files from queues */
3717dd7cddfSDavid du Colombier 	strcpy(portname, "\\\\spool\\");
3727dd7cddfSDavid du Colombier 	strcat(portname, p);
3737dd7cddfSDavid du Colombier     } else {
3747dd7cddfSDavid du Colombier 	strcpy(portname, "\\\\spool\\");
3757dd7cddfSDavid du Colombier 	strcat(portname, queue);
3767dd7cddfSDavid du Colombier     }
3777dd7cddfSDavid du Colombier 
3787dd7cddfSDavid du Colombier     free(buffer);
3797dd7cddfSDavid du Colombier     return TRUE;
3807dd7cddfSDavid du Colombier }
3817dd7cddfSDavid du Colombier 
3827dd7cddfSDavid du Colombier /* return TRUE if portname available */
3837dd7cddfSDavid du Colombier /* return FALSE if cancelled or error */
3847dd7cddfSDavid du Colombier /* if port non-NULL, use as suggested port */
3857dd7cddfSDavid du Colombier BOOL
3867dd7cddfSDavid du Colombier get_portname(char *portname, const char *port)
3877dd7cddfSDavid du Colombier {
3887dd7cddfSDavid du Colombier     char *buffer;
3897dd7cddfSDavid du Colombier     char *p;
3907dd7cddfSDavid du Colombier     int i, iport;
3917dd7cddfSDavid du Colombier     char filename[MAXSTR];
3927dd7cddfSDavid du Colombier 
3937dd7cddfSDavid du Colombier     buffer = get_ports();
3947dd7cddfSDavid du Colombier     if (buffer == NULL)
3957dd7cddfSDavid du Colombier 	return FALSE;
3967dd7cddfSDavid du Colombier     if ((port == (char *)NULL) || (strlen(port) == 0)) {
3977dd7cddfSDavid du Colombier 	if (buffer == (char *)NULL)
3987dd7cddfSDavid du Colombier 	    return FALSE;
3997dd7cddfSDavid du Colombier 	/* select a port */
4007dd7cddfSDavid du Colombier 	iport = DialogBoxParam(phInstance, "SpoolDlgBox", (HWND) NULL, SpoolDlgProc, (LPARAM) buffer);
4017dd7cddfSDavid du Colombier 	if (!iport) {
4027dd7cddfSDavid du Colombier 	    free(buffer);
4037dd7cddfSDavid du Colombier 	    return FALSE;
4047dd7cddfSDavid du Colombier 	}
4057dd7cddfSDavid du Colombier 	p = buffer;
4067dd7cddfSDavid du Colombier 	for (i = 1; i < iport && strlen(p) != 0; i++)
4077dd7cddfSDavid du Colombier 	    p += lstrlen(p) + 1;
4087dd7cddfSDavid du Colombier 	strcpy(portname, p);
4097dd7cddfSDavid du Colombier     } else
4107dd7cddfSDavid du Colombier 	strcpy(portname, port);
4117dd7cddfSDavid du Colombier 
4127dd7cddfSDavid du Colombier     if (strlen(portname) == 0)
4137dd7cddfSDavid du Colombier 	return FALSE;
4147dd7cddfSDavid du Colombier     if (strcmp(portname, "FILE:") == 0) {
4157dd7cddfSDavid du Colombier 	OPENFILENAME ofn;
4167dd7cddfSDavid du Colombier 
4177dd7cddfSDavid du Colombier 	filename[0] = '\0';
4187dd7cddfSDavid du Colombier 	memset(&ofn, 0, sizeof(OPENFILENAME));
4197dd7cddfSDavid du Colombier 	ofn.lStructSize = sizeof(OPENFILENAME);
4207dd7cddfSDavid du Colombier 	ofn.hwndOwner = (HWND) NULL;
4217dd7cddfSDavid du Colombier 	ofn.lpstrFile = filename;
4227dd7cddfSDavid du Colombier 	ofn.nMaxFile = sizeof(filename);
4237dd7cddfSDavid du Colombier 	ofn.Flags = OFN_PATHMUSTEXIST;
4247dd7cddfSDavid du Colombier 	if (!GetSaveFileName(&ofn)) {
4257dd7cddfSDavid du Colombier 	    free(buffer);
4267dd7cddfSDavid du Colombier 	    return FALSE;
4277dd7cddfSDavid du Colombier 	}
4287dd7cddfSDavid du Colombier 	strcpy(portname, filename);
4297dd7cddfSDavid du Colombier     }
4307dd7cddfSDavid du Colombier     free(buffer);
4317dd7cddfSDavid du Colombier     return TRUE;
4327dd7cddfSDavid du Colombier }
4337dd7cddfSDavid du Colombier 
4347dd7cddfSDavid du Colombier 
4357dd7cddfSDavid du Colombier /* True Win32 method, using OpenPrinter, WritePrinter etc. */
4367dd7cddfSDavid du Colombier private int
4377dd7cddfSDavid du Colombier gp_printfile_win32(const char *filename, char *port)
4387dd7cddfSDavid du Colombier {
4397dd7cddfSDavid du Colombier     DWORD count;
4407dd7cddfSDavid du Colombier     char *buffer;
4417dd7cddfSDavid du Colombier     char portname[MAXSTR];
4427dd7cddfSDavid du Colombier     FILE *f;
4437dd7cddfSDavid du Colombier     HANDLE printer;
4447dd7cddfSDavid du Colombier     DOC_INFO_1 di;
4457dd7cddfSDavid du Colombier     DWORD written;
4467dd7cddfSDavid du Colombier 
4477dd7cddfSDavid du Colombier     if (!get_queuename(portname, port))
4487dd7cddfSDavid du Colombier 	return FALSE;
4497dd7cddfSDavid du Colombier     port = portname + 8;	/* skip over \\spool\ */
4507dd7cddfSDavid du Colombier 
4517dd7cddfSDavid du Colombier     if ((buffer = malloc(PRINT_BUF_SIZE)) == (char *)NULL)
4527dd7cddfSDavid du Colombier 	return FALSE;
4537dd7cddfSDavid du Colombier 
4547dd7cddfSDavid du Colombier     if ((f = fopen(filename, "rb")) == (FILE *) NULL) {
4557dd7cddfSDavid du Colombier 	free(buffer);
4567dd7cddfSDavid du Colombier 	return FALSE;
4577dd7cddfSDavid du Colombier     }
4587dd7cddfSDavid du Colombier     /* open a printer */
4597dd7cddfSDavid du Colombier     if (!OpenPrinter(port, &printer, NULL)) {
4607dd7cddfSDavid du Colombier 	char buf[256];
4617dd7cddfSDavid du Colombier 
4627dd7cddfSDavid du Colombier 	sprintf(buf, "OpenPrinter() failed for \042%s\042, error code = %d", port, GetLastError());
4637dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
4647dd7cddfSDavid du Colombier 	free(buffer);
4657dd7cddfSDavid du Colombier 	return FALSE;
4667dd7cddfSDavid du Colombier     }
4677dd7cddfSDavid du Colombier     /* from here until ClosePrinter, should AbortPrinter on error */
4687dd7cddfSDavid du Colombier 
4697dd7cddfSDavid du Colombier     di.pDocName = szAppName;
4707dd7cddfSDavid du Colombier     di.pOutputFile = NULL;
4717dd7cddfSDavid du Colombier     di.pDatatype = "RAW";	/* for available types see EnumPrintProcessorDatatypes */
4727dd7cddfSDavid du Colombier     if (!StartDocPrinter(printer, 1, (LPBYTE) & di)) {
4737dd7cddfSDavid du Colombier 	char buf[256];
4747dd7cddfSDavid du Colombier 
4757dd7cddfSDavid du Colombier 	sprintf(buf, "StartDocPrinter() failed, error code = %d", GetLastError());
4767dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
4777dd7cddfSDavid du Colombier 	AbortPrinter(printer);
4787dd7cddfSDavid du Colombier 	free(buffer);
4797dd7cddfSDavid du Colombier 	return FALSE;
4807dd7cddfSDavid du Colombier     }
4817dd7cddfSDavid du Colombier     /* copy file to printer */
4827dd7cddfSDavid du Colombier     while ((count = fread(buffer, 1, PRINT_BUF_SIZE, f)) != 0) {
4837dd7cddfSDavid du Colombier 	if (!WritePrinter(printer, (LPVOID) buffer, count, &written)) {
4847dd7cddfSDavid du Colombier 	    free(buffer);
4857dd7cddfSDavid du Colombier 	    fclose(f);
4867dd7cddfSDavid du Colombier 	    AbortPrinter(printer);
4877dd7cddfSDavid du Colombier 	    return FALSE;
4887dd7cddfSDavid du Colombier 	}
4897dd7cddfSDavid du Colombier     }
4907dd7cddfSDavid du Colombier     fclose(f);
4917dd7cddfSDavid du Colombier     free(buffer);
4927dd7cddfSDavid du Colombier 
4937dd7cddfSDavid du Colombier     if (!EndDocPrinter(printer)) {
4947dd7cddfSDavid du Colombier 	char buf[256];
4957dd7cddfSDavid du Colombier 
4967dd7cddfSDavid du Colombier 	sprintf(buf, "EndDocPrinter() failed, error code = %d", GetLastError());
4977dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
4987dd7cddfSDavid du Colombier 	AbortPrinter(printer);
4997dd7cddfSDavid du Colombier 	return FALSE;
5007dd7cddfSDavid du Colombier     }
5017dd7cddfSDavid du Colombier     if (!ClosePrinter(printer)) {
5027dd7cddfSDavid du Colombier 	char buf[256];
5037dd7cddfSDavid du Colombier 
5047dd7cddfSDavid du Colombier 	sprintf(buf, "ClosePrinter() failed, error code = %d", GetLastError());
5057dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
5067dd7cddfSDavid du Colombier 	return FALSE;
5077dd7cddfSDavid du Colombier     }
5087dd7cddfSDavid du Colombier     return TRUE;
5097dd7cddfSDavid du Colombier }
5107dd7cddfSDavid du Colombier 
5117dd7cddfSDavid du Colombier 
5127dd7cddfSDavid du Colombier /* Start a 16-bit application gs16spl.exe to print a file */
5137dd7cddfSDavid du Colombier /* Intended for Win32s where 16-bit spooler functions are not available */
5147dd7cddfSDavid du Colombier /* and Win32 spooler functions are not implemented. */
5157dd7cddfSDavid du Colombier int
5167dd7cddfSDavid du Colombier gp_printfile_gs16spl(const char *filename, const char *port)
5177dd7cddfSDavid du Colombier {
5187dd7cddfSDavid du Colombier /* Get printer port list from win.ini */
5197dd7cddfSDavid du Colombier     char portname[MAXSTR];
5207dd7cddfSDavid du Colombier     HINSTANCE hinst;
5217dd7cddfSDavid du Colombier     char command[MAXSTR];
5227dd7cddfSDavid du Colombier     char *p;
5237dd7cddfSDavid du Colombier     HWND hwndspl;
5247dd7cddfSDavid du Colombier 
5257dd7cddfSDavid du Colombier     if (!get_portname(portname, port))
5267dd7cddfSDavid du Colombier 	return FALSE;
5277dd7cddfSDavid du Colombier 
5287dd7cddfSDavid du Colombier     /* get path to EXE - same as DLL */
5297dd7cddfSDavid du Colombier     GetModuleFileName(phInstance, command, sizeof(command));
5307dd7cddfSDavid du Colombier     if ((p = strrchr(command, '\\')) != (char *)NULL)
5317dd7cddfSDavid du Colombier 	p++;
5327dd7cddfSDavid du Colombier     else
5337dd7cddfSDavid du Colombier 	p = command;
5347dd7cddfSDavid du Colombier     *p = '\0';
5357dd7cddfSDavid du Colombier     sprintf(command + strlen(command), "gs16spl.exe %s %s",
5367dd7cddfSDavid du Colombier 	    portname, filename);
5377dd7cddfSDavid du Colombier 
5387dd7cddfSDavid du Colombier     hinst = (HINSTANCE) WinExec(command, SW_SHOWNORMAL);
5397dd7cddfSDavid du Colombier     if (hinst < (HINSTANCE) HINSTANCE_ERROR) {
5407dd7cddfSDavid du Colombier 	char buf[MAXSTR];
5417dd7cddfSDavid du Colombier 
5427dd7cddfSDavid du Colombier 	sprintf(buf, "Can't run: %s", command);
5437dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
5447dd7cddfSDavid du Colombier 	return FALSE;
5457dd7cddfSDavid du Colombier     }
5467dd7cddfSDavid du Colombier     hwndspl = FindWindow(NULL, "GS Win32s/Win16 spooler");
5477dd7cddfSDavid du Colombier 
5487dd7cddfSDavid du Colombier     while (IsWindow(hwndspl)) {
5497dd7cddfSDavid du Colombier 	gp_check_interrupts();
5507dd7cddfSDavid du Colombier     }
5517dd7cddfSDavid du Colombier 
5527dd7cddfSDavid du Colombier     return 0;
5537dd7cddfSDavid du Colombier }
5547dd7cddfSDavid du Colombier 
5557dd7cddfSDavid du Colombier 
5567dd7cddfSDavid du Colombier 
5577dd7cddfSDavid du Colombier 
5587dd7cddfSDavid du Colombier /* ------ File naming and accessing ------ */
5597dd7cddfSDavid du Colombier 
5607dd7cddfSDavid du Colombier /* Create and open a scratch file with a given name prefix. */
5617dd7cddfSDavid du Colombier /* Write the actual file name at fname. */
5627dd7cddfSDavid du Colombier FILE *
5637dd7cddfSDavid du Colombier gp_open_scratch_file(const char *prefix, char *fname, const char *mode)
5647dd7cddfSDavid du Colombier {	/* The -7 is for XXXXXX plus a possible final \. */
565*3ff48bf5SDavid du Colombier     int prefix_length = strlen(prefix);
566*3ff48bf5SDavid du Colombier     int len = gp_file_name_sizeof - prefix_length - 7;
5677dd7cddfSDavid du Colombier 
568*3ff48bf5SDavid du Colombier     if (gp_file_name_is_absolute(prefix, prefix_length) ||
569*3ff48bf5SDavid du Colombier 	gp_gettmpdir(fname, &len) != 0
570*3ff48bf5SDavid du Colombier 	)
5717dd7cddfSDavid du Colombier 	*fname = 0;
5727dd7cddfSDavid du Colombier     else {
5737dd7cddfSDavid du Colombier 	char *temp;
5747dd7cddfSDavid du Colombier 
5757dd7cddfSDavid du Colombier 	/* Prevent X's in path from being converted by mktemp. */
5767dd7cddfSDavid du Colombier 	for (temp = fname; *temp; temp++)
5777dd7cddfSDavid du Colombier 	    *temp = tolower(*temp);
5787dd7cddfSDavid du Colombier 	if (strlen(fname) && (fname[strlen(fname) - 1] != '\\'))
5797dd7cddfSDavid du Colombier 	    strcat(fname, "\\");
5807dd7cddfSDavid du Colombier     }
581*3ff48bf5SDavid du Colombier     if (strlen(fname) + prefix_length + 7 >= gp_file_name_sizeof)
582*3ff48bf5SDavid du Colombier 	return 0;		/* file name too long */
5837dd7cddfSDavid du Colombier     strcat(fname, prefix);
5847dd7cddfSDavid du Colombier     strcat(fname, "XXXXXX");
5857dd7cddfSDavid du Colombier     mktemp(fname);
586*3ff48bf5SDavid du Colombier     return gp_fopentemp(fname, mode);
5877dd7cddfSDavid du Colombier }
5887dd7cddfSDavid du Colombier 
5897dd7cddfSDavid du Colombier /* Open a file with the given name, as a stream of uninterpreted bytes. */
5907dd7cddfSDavid du Colombier FILE *
5917dd7cddfSDavid du Colombier gp_fopen(const char *fname, const char *mode)
5927dd7cddfSDavid du Colombier {
5937dd7cddfSDavid du Colombier     return fopen(fname, mode);
5947dd7cddfSDavid du Colombier }
595*3ff48bf5SDavid du Colombier 
596