xref: /plan9/sys/src/cmd/gs/src/gp_mswin.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1*593dc095SDavid du Colombier /* Copyright (C) 1992, 2000-2003 artofcode LLC.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gp_mswin.c,v 1.25 2005/03/04 21:58:55 ghostgum Exp $ */
187dd7cddfSDavid du Colombier /*
193ff48bf5SDavid du Colombier  * Microsoft Windows platform support for Ghostscript.
207dd7cddfSDavid du Colombier  *
217dd7cddfSDavid du Colombier  * Original version by Russell Lang and Maurice Castro with help from
227dd7cddfSDavid du Colombier  * Programming Windows, 2nd Ed., Charles Petzold, Microsoft Press;
237dd7cddfSDavid du Colombier  * initially created from gp_dosfb.c and gp_itbc.c 5th June 1992.
247dd7cddfSDavid du Colombier  */
257dd7cddfSDavid du Colombier 
267dd7cddfSDavid du Colombier /* Modified for Win32 & Microsoft C/C++ 8.0 32-Bit, 26.Okt.1994 */
277dd7cddfSDavid du Colombier /* by Friedrich Nowak                                           */
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier /* Original EXE and GSview specific code removed */
307dd7cddfSDavid du Colombier /* DLL version must now be used under MS-Windows */
317dd7cddfSDavid du Colombier /* Russell Lang 16 March 1996 */
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier #include "stdio_.h"
347dd7cddfSDavid du Colombier #include "string_.h"
357dd7cddfSDavid du Colombier #include "memory_.h"
36*593dc095SDavid du Colombier #include "pipe_.h"
377dd7cddfSDavid du Colombier #include <stdlib.h>
387dd7cddfSDavid du Colombier #include <stdarg.h>
397dd7cddfSDavid du Colombier #include "ctype_.h"
407dd7cddfSDavid du Colombier #include <io.h>
417dd7cddfSDavid du Colombier #include "malloc_.h"
427dd7cddfSDavid du Colombier #include <fcntl.h>
437dd7cddfSDavid du Colombier #include <signal.h>
447dd7cddfSDavid du Colombier #include "gx.h"
457dd7cddfSDavid du Colombier #include "gp.h"
467dd7cddfSDavid du Colombier #include "gpcheck.h"
473ff48bf5SDavid du Colombier #include "gpmisc.h"
487dd7cddfSDavid du Colombier #include "gserrors.h"
497dd7cddfSDavid du Colombier #include "gsexit.h"
507dd7cddfSDavid du Colombier 
517dd7cddfSDavid du Colombier #include "windows_.h"
527dd7cddfSDavid du Colombier #include <shellapi.h>
537dd7cddfSDavid du Colombier #include <winspool.h>
547dd7cddfSDavid du Colombier #include "gp_mswin.h"
557dd7cddfSDavid du Colombier 
567dd7cddfSDavid du Colombier /* Library routines not declared in a standard header */
57*593dc095SDavid du Colombier extern char *getenv(const char *);
587dd7cddfSDavid du Colombier 
597dd7cddfSDavid du Colombier /* limits */
607dd7cddfSDavid du Colombier #define MAXSTR 255
617dd7cddfSDavid du Colombier 
623ff48bf5SDavid du Colombier /* GLOBAL VARIABLE that needs to be removed */
633ff48bf5SDavid du Colombier char win_prntmp[MAXSTR];	/* filename of PRN temporary file */
643ff48bf5SDavid du Colombier 
653ff48bf5SDavid du Colombier /* GLOBAL VARIABLES - initialised at DLL load time */
667dd7cddfSDavid du Colombier HINSTANCE phInstance;
673ff48bf5SDavid du Colombier BOOL is_win32s = FALSE;
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier const LPSTR szAppName = "Ghostscript";
707dd7cddfSDavid du Colombier private int is_printer(const char *name);
717dd7cddfSDavid du Colombier 
727dd7cddfSDavid du Colombier 
737dd7cddfSDavid du Colombier /* ====== Generic platform procedures ====== */
747dd7cddfSDavid du Colombier 
757dd7cddfSDavid du Colombier /* ------ Initialization/termination (from gp_itbc.c) ------ */
767dd7cddfSDavid du Colombier 
777dd7cddfSDavid du Colombier /* Do platform-dependent initialization. */
787dd7cddfSDavid du Colombier void
gp_init(void)797dd7cddfSDavid du Colombier gp_init(void)
807dd7cddfSDavid du Colombier {
817dd7cddfSDavid du Colombier }
827dd7cddfSDavid du Colombier 
837dd7cddfSDavid du Colombier /* Do platform-dependent cleanup. */
847dd7cddfSDavid du Colombier void
gp_exit(int exit_status,int code)857dd7cddfSDavid du Colombier gp_exit(int exit_status, int code)
867dd7cddfSDavid du Colombier {
877dd7cddfSDavid du Colombier }
887dd7cddfSDavid du Colombier 
897dd7cddfSDavid du Colombier /* Exit the program. */
907dd7cddfSDavid du Colombier void
gp_do_exit(int exit_status)917dd7cddfSDavid du Colombier gp_do_exit(int exit_status)
927dd7cddfSDavid du Colombier {
93*593dc095SDavid du Colombier     exit(exit_status);
94*593dc095SDavid du Colombier }
95*593dc095SDavid du Colombier 
96*593dc095SDavid du Colombier /* ------ Persistent data cache ------*/
97*593dc095SDavid du Colombier 
98*593dc095SDavid du Colombier /* insert a buffer under a (type, key) pair */
gp_cache_insert(int type,byte * key,int keylen,void * buffer,int buflen)99*593dc095SDavid du Colombier int gp_cache_insert(int type, byte *key, int keylen, void *buffer, int buflen)
100*593dc095SDavid du Colombier {
101*593dc095SDavid du Colombier     /* not yet implemented */
102*593dc095SDavid du Colombier     return 0;
103*593dc095SDavid du Colombier }
104*593dc095SDavid du Colombier 
105*593dc095SDavid du Colombier /* look up a (type, key) in the cache */
gp_cache_query(int type,byte * key,int keylen,void ** buffer,gp_cache_alloc alloc,void * userdata)106*593dc095SDavid du Colombier int gp_cache_query(int type, byte* key, int keylen, void **buffer,
107*593dc095SDavid du Colombier     gp_cache_alloc alloc, void *userdata)
108*593dc095SDavid du Colombier {
109*593dc095SDavid du Colombier     /* not yet implemented */
110*593dc095SDavid du Colombier     return -1;
1117dd7cddfSDavid du Colombier }
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier /* ------ Printer accessing ------ */
1147dd7cddfSDavid du Colombier 
1157dd7cddfSDavid du Colombier /* Forward references */
116*593dc095SDavid du Colombier private int gp_printfile(const char *, const char *);
1177dd7cddfSDavid du Colombier 
1187dd7cddfSDavid du Colombier /* Open a connection to a printer.  A null file name means use the */
1197dd7cddfSDavid du Colombier /* standard printer connected to the machine, if any. */
1207dd7cddfSDavid du Colombier /* Return NULL if the connection could not be opened. */
1217dd7cddfSDavid du Colombier FILE *
gp_open_printer(char fname[gp_file_name_sizeof],int binary_mode)1227dd7cddfSDavid du Colombier gp_open_printer(char fname[gp_file_name_sizeof], int binary_mode)
1237dd7cddfSDavid du Colombier {
1247dd7cddfSDavid du Colombier     if (is_printer(fname)) {
1257dd7cddfSDavid du Colombier 	FILE *pfile;
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier 	/* Open a scratch file, which we will send to the */
1287dd7cddfSDavid du Colombier 	/* actual printer in gp_close_printer. */
1297dd7cddfSDavid du Colombier 	pfile = gp_open_scratch_file(gp_scratch_file_name_prefix,
1307dd7cddfSDavid du Colombier 				     win_prntmp, "wb");
1317dd7cddfSDavid du Colombier 	return pfile;
132*593dc095SDavid du Colombier     } else if (fname[0] == '|') 	/* pipe */
133*593dc095SDavid du Colombier 	return popen(fname + 1, (binary_mode ? "wb" : "w"));
134*593dc095SDavid du Colombier     else
1357dd7cddfSDavid du Colombier 	return fopen(fname, (binary_mode ? "wb" : "w"));
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier /* Close the connection to the printer. */
1397dd7cddfSDavid du Colombier void
gp_close_printer(FILE * pfile,const char * fname)1407dd7cddfSDavid du Colombier gp_close_printer(FILE * pfile, const char *fname)
1417dd7cddfSDavid du Colombier {
1427dd7cddfSDavid du Colombier     fclose(pfile);
1437dd7cddfSDavid du Colombier     if (!is_printer(fname))
1447dd7cddfSDavid du Colombier 	return;			/* a file, not a printer */
1457dd7cddfSDavid du Colombier 
1467dd7cddfSDavid du Colombier     gp_printfile(win_prntmp, fname);
1477dd7cddfSDavid du Colombier     unlink(win_prntmp);
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier 
1517dd7cddfSDavid du Colombier /* Dialog box to select printer port */
152*593dc095SDavid du Colombier DLGRETURN CALLBACK
SpoolDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)1537dd7cddfSDavid du Colombier SpoolDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1547dd7cddfSDavid du Colombier {
1557dd7cddfSDavid du Colombier     LPSTR entry;
1567dd7cddfSDavid du Colombier 
1577dd7cddfSDavid du Colombier     switch (message) {
1587dd7cddfSDavid du Colombier 	case WM_INITDIALOG:
1597dd7cddfSDavid du Colombier 	    entry = (LPSTR) lParam;
1607dd7cddfSDavid du Colombier 	    while (*entry) {
1617dd7cddfSDavid du Colombier 		SendDlgItemMessage(hDlg, SPOOL_PORT, LB_ADDSTRING, 0, (LPARAM) entry);
1627dd7cddfSDavid du Colombier 		entry += lstrlen(entry) + 1;
1637dd7cddfSDavid du Colombier 	    }
1647dd7cddfSDavid du Colombier 	    SendDlgItemMessage(hDlg, SPOOL_PORT, LB_SETCURSEL, 0, (LPARAM) 0);
1657dd7cddfSDavid du Colombier 	    return TRUE;
1667dd7cddfSDavid du Colombier 	case WM_COMMAND:
1677dd7cddfSDavid du Colombier 	    switch (LOWORD(wParam)) {
1687dd7cddfSDavid du Colombier 		case SPOOL_PORT:
1693ff48bf5SDavid du Colombier 		    if (HIWORD(wParam) == LBN_DBLCLK)
1707dd7cddfSDavid du Colombier 			PostMessage(hDlg, WM_COMMAND, IDOK, 0L);
1717dd7cddfSDavid du Colombier 		    return FALSE;
1727dd7cddfSDavid du Colombier 		case IDOK:
1737dd7cddfSDavid du Colombier 		    EndDialog(hDlg, 1 + (int)SendDlgItemMessage(hDlg, SPOOL_PORT, LB_GETCURSEL, 0, 0L));
1747dd7cddfSDavid du Colombier 		    return TRUE;
1757dd7cddfSDavid du Colombier 		case IDCANCEL:
1767dd7cddfSDavid du Colombier 		    EndDialog(hDlg, 0);
1777dd7cddfSDavid du Colombier 		    return TRUE;
1787dd7cddfSDavid du Colombier 	    }
1797dd7cddfSDavid du Colombier     }
1807dd7cddfSDavid du Colombier     return FALSE;
1817dd7cddfSDavid du Colombier }
1827dd7cddfSDavid du Colombier 
1837dd7cddfSDavid du Colombier /* return TRUE if queue looks like a valid printer name */
1847dd7cddfSDavid du Colombier int
is_spool(const char * queue)1857dd7cddfSDavid du Colombier is_spool(const char *queue)
1867dd7cddfSDavid du Colombier {
1877dd7cddfSDavid du Colombier     char *prefix = "\\\\spool";	/* 7 characters long */
1887dd7cddfSDavid du Colombier     int i;
1897dd7cddfSDavid du Colombier 
1907dd7cddfSDavid du Colombier     for (i = 0; i < 7; i++) {
1917dd7cddfSDavid du Colombier 	if (prefix[i] == '\\') {
1927dd7cddfSDavid du Colombier 	    if ((*queue != '\\') && (*queue != '/'))
1937dd7cddfSDavid du Colombier 		return FALSE;
1947dd7cddfSDavid du Colombier 	} else if (tolower(*queue) != prefix[i])
1957dd7cddfSDavid du Colombier 	    return FALSE;
1967dd7cddfSDavid du Colombier 	queue++;
1977dd7cddfSDavid du Colombier     }
1987dd7cddfSDavid du Colombier     if (*queue && (*queue != '\\') && (*queue != '/'))
1997dd7cddfSDavid du Colombier 	return FALSE;
2007dd7cddfSDavid du Colombier     return TRUE;
2017dd7cddfSDavid du Colombier }
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier 
2047dd7cddfSDavid du Colombier private int
is_printer(const char * name)2057dd7cddfSDavid du Colombier is_printer(const char *name)
2067dd7cddfSDavid du Colombier {
2077dd7cddfSDavid du Colombier     char buf[128];
2087dd7cddfSDavid du Colombier 
2097dd7cddfSDavid du Colombier     /* is printer if no name given */
2107dd7cddfSDavid du Colombier     if (strlen(name) == 0)
2117dd7cddfSDavid du Colombier 	return TRUE;
2127dd7cddfSDavid du Colombier 
2137dd7cddfSDavid du Colombier     /*  is printer if name appears in win.ini [ports] section */
2147dd7cddfSDavid du Colombier     GetProfileString("ports", name, "XYZ", buf, sizeof(buf));
2157dd7cddfSDavid du Colombier     if (strlen(name) == 0 || strcmp(buf, "XYZ"))
2167dd7cddfSDavid du Colombier 	return TRUE;
2177dd7cddfSDavid du Colombier 
2187dd7cddfSDavid du Colombier     /* is printer if name prefixed by \\spool\ */
2197dd7cddfSDavid du Colombier     if (is_spool(name))
2207dd7cddfSDavid du Colombier 	return TRUE;
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier     return FALSE;
2237dd7cddfSDavid du Colombier }
2247dd7cddfSDavid du Colombier 
2257dd7cddfSDavid du Colombier 
2267dd7cddfSDavid du Colombier /******************************************************************/
2277dd7cddfSDavid du Colombier /* Print File to port or queue */
2287dd7cddfSDavid du Colombier /* port==NULL means prompt for port or queue with dialog box */
2297dd7cddfSDavid du Colombier 
2307dd7cddfSDavid du Colombier /* This is messy because Microsoft changed the spooler interface */
2313ff48bf5SDavid du Colombier /* between Windows 3.1 and Windows 95/NT */
2327dd7cddfSDavid du Colombier /* and didn't provide the spooler interface in Win32s */
2337dd7cddfSDavid du Colombier 
2347dd7cddfSDavid du Colombier /* Win95, WinNT: Use OpenPrinter, WritePrinter etc. */
2357dd7cddfSDavid du Colombier private int gp_printfile_win32(const char *filename, char *port);
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier /* Win32s: Pass to Win16 spooler via gs16spl.exe */
2387dd7cddfSDavid du Colombier private int gp_printfile_gs16spl(const char *filename, const char *port);
2397dd7cddfSDavid du Colombier 
2407dd7cddfSDavid du Colombier /*
2417dd7cddfSDavid du Colombier  * Valid values for pmport are:
2427dd7cddfSDavid du Colombier  *   ""
2437dd7cddfSDavid du Colombier  *      action: WinNT and Win95 use default queue, Win32s prompts for port
2447dd7cddfSDavid du Colombier  *   "LPT1:" (or other port that appears in win.ini [ports]
2457dd7cddfSDavid du Colombier  *      action: start gs16spl.exe to print to the port
2467dd7cddfSDavid du Colombier  *   "\\spool\printer name"
2477dd7cddfSDavid du Colombier  *      action: send to printer using WritePrinter (WinNT and Win95).
2487dd7cddfSDavid du Colombier  *      action: translate to port name using win.ini [Devices]
2497dd7cddfSDavid du Colombier  *              then use gs16spl.exe (Win32s).
2507dd7cddfSDavid du Colombier  *   "\\spool"
2517dd7cddfSDavid du Colombier  *      action: prompt for queue name then send to printer using
2527dd7cddfSDavid du Colombier  *              WritePrinter (WinNT and Win95).
2537dd7cddfSDavid du Colombier  *      action: prompt for port then use gs16spl.exe (Win32s).
2547dd7cddfSDavid du Colombier  */
2557dd7cddfSDavid du Colombier /* Print File */
2567dd7cddfSDavid du Colombier private int
gp_printfile(const char * filename,const char * pmport)2577dd7cddfSDavid du Colombier gp_printfile(const char *filename, const char *pmport)
2587dd7cddfSDavid du Colombier {
2597dd7cddfSDavid du Colombier     /* treat WinNT and Win95 differently to Win32s */
2607dd7cddfSDavid du Colombier     if (!is_win32s) {
2617dd7cddfSDavid du Colombier 	if (strlen(pmport) == 0) {	/* get default printer */
2627dd7cddfSDavid du Colombier 	    char buf[256];
2637dd7cddfSDavid du Colombier 	    char *p;
2647dd7cddfSDavid du Colombier 
2657dd7cddfSDavid du Colombier 	    /* WinNT stores default printer in registry and win.ini */
2667dd7cddfSDavid du Colombier 	    /* Win95 stores default printer in win.ini */
2677dd7cddfSDavid du Colombier 	    GetProfileString("windows", "device", "", buf, sizeof(buf));
2687dd7cddfSDavid du Colombier 	    if ((p = strchr(buf, ',')) != NULL)
2697dd7cddfSDavid du Colombier 		*p = '\0';
2707dd7cddfSDavid du Colombier 	    return gp_printfile_win32(filename, buf);
2717dd7cddfSDavid du Colombier 	} else if (is_spool(pmport)) {
2727dd7cddfSDavid du Colombier 	    if (strlen(pmport) >= 8)
2737dd7cddfSDavid du Colombier 		return gp_printfile_win32(filename, (char *)pmport + 8);
2747dd7cddfSDavid du Colombier 	    else
2757dd7cddfSDavid du Colombier 		return gp_printfile_win32(filename, (char *)NULL);
2767dd7cddfSDavid du Colombier 	} else
2777dd7cddfSDavid du Colombier 	    return gp_printfile_gs16spl(filename, pmport);
2787dd7cddfSDavid du Colombier     } else {
2797dd7cddfSDavid du Colombier 	/* Win32s */
2807dd7cddfSDavid du Colombier 	if (is_spool(pmport)) {
2817dd7cddfSDavid du Colombier 	    if (strlen(pmport) >= 8) {
2827dd7cddfSDavid du Colombier 		/* extract port name from win.ini */
2837dd7cddfSDavid du Colombier 		char driverbuf[256];
2847dd7cddfSDavid du Colombier 		char *output;
2857dd7cddfSDavid du Colombier 
2867dd7cddfSDavid du Colombier 		GetProfileString("Devices", pmport + 8, "", driverbuf, sizeof(driverbuf));
2877dd7cddfSDavid du Colombier 		strtok(driverbuf, ",");
2887dd7cddfSDavid du Colombier 		output = strtok(NULL, ",");
2897dd7cddfSDavid du Colombier 		return gp_printfile_gs16spl(filename, output);
2907dd7cddfSDavid du Colombier 	    } else
2917dd7cddfSDavid du Colombier 		return gp_printfile_gs16spl(filename, (char *)NULL);
2927dd7cddfSDavid du Colombier 	} else
2937dd7cddfSDavid du Colombier 	    return gp_printfile_gs16spl(filename, pmport);
2947dd7cddfSDavid du Colombier     }
2957dd7cddfSDavid du Colombier }
2967dd7cddfSDavid du Colombier 
2977dd7cddfSDavid du Colombier #define PRINT_BUF_SIZE 16384u
2987dd7cddfSDavid du Colombier #define PORT_BUF_SIZE 4096
2997dd7cddfSDavid du Colombier 
3007dd7cddfSDavid du Colombier char *
get_queues(void)3017dd7cddfSDavid du Colombier get_queues(void)
3027dd7cddfSDavid du Colombier {
3037dd7cddfSDavid du Colombier     int i;
3047dd7cddfSDavid du Colombier     DWORD count, needed;
3057dd7cddfSDavid du Colombier     PRINTER_INFO_1 *prinfo;
3067dd7cddfSDavid du Colombier     char *enumbuffer;
3077dd7cddfSDavid du Colombier     char *buffer;
3087dd7cddfSDavid du Colombier     char *p;
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier     /* enumerate all available printers */
3117dd7cddfSDavid du Colombier     EnumPrinters(PRINTER_ENUM_CONNECTIONS | PRINTER_ENUM_LOCAL, NULL, 1, NULL, 0, &needed, &count);
3127dd7cddfSDavid du Colombier     if (needed == 0) {
3137dd7cddfSDavid du Colombier 	/* no printers */
3147dd7cddfSDavid du Colombier 	enumbuffer = malloc(4);
3157dd7cddfSDavid du Colombier 	if (enumbuffer == (char *)NULL)
3167dd7cddfSDavid du Colombier 	    return NULL;
3177dd7cddfSDavid du Colombier 	memset(enumbuffer, 0, 4);
3187dd7cddfSDavid du Colombier 	return enumbuffer;
3197dd7cddfSDavid du Colombier     }
3207dd7cddfSDavid du Colombier     enumbuffer = malloc(needed);
3217dd7cddfSDavid du Colombier     if (enumbuffer == (char *)NULL)
3227dd7cddfSDavid du Colombier 	return NULL;
3237dd7cddfSDavid du Colombier     if (!EnumPrinters(PRINTER_ENUM_CONNECTIONS | PRINTER_ENUM_LOCAL, NULL, 1, (LPBYTE) enumbuffer, needed, &needed, &count)) {
3247dd7cddfSDavid du Colombier 	char buf[256];
3257dd7cddfSDavid du Colombier 
3267dd7cddfSDavid du Colombier 	free(enumbuffer);
3277dd7cddfSDavid du Colombier 	sprintf(buf, "EnumPrinters() failed, error code = %d", GetLastError());
3287dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
3297dd7cddfSDavid du Colombier 	return NULL;
3307dd7cddfSDavid du Colombier     }
3317dd7cddfSDavid du Colombier     prinfo = (PRINTER_INFO_1 *) enumbuffer;
3327dd7cddfSDavid du Colombier     if ((buffer = malloc(PORT_BUF_SIZE)) == (char *)NULL) {
3337dd7cddfSDavid du Colombier 	free(enumbuffer);
3347dd7cddfSDavid du Colombier 	return NULL;
3357dd7cddfSDavid du Colombier     }
3367dd7cddfSDavid du Colombier     /* copy printer names to single buffer */
3377dd7cddfSDavid du Colombier     p = buffer;
3387dd7cddfSDavid du Colombier     for (i = 0; i < count; i++) {
3397dd7cddfSDavid du Colombier 	if (strlen(prinfo[i].pName) + 1 < (PORT_BUF_SIZE - (p - buffer))) {
3407dd7cddfSDavid du Colombier 	    strcpy(p, prinfo[i].pName);
3417dd7cddfSDavid du Colombier 	    p += strlen(p) + 1;
3427dd7cddfSDavid du Colombier 	}
3437dd7cddfSDavid du Colombier     }
3447dd7cddfSDavid du Colombier     *p = '\0';			/* double null at end */
3457dd7cddfSDavid du Colombier     free(enumbuffer);
3467dd7cddfSDavid du Colombier     return buffer;
3477dd7cddfSDavid du Colombier }
3487dd7cddfSDavid du Colombier 
3497dd7cddfSDavid du Colombier 
3507dd7cddfSDavid du Colombier char *
get_ports(void)3517dd7cddfSDavid du Colombier get_ports(void)
3527dd7cddfSDavid du Colombier {
3537dd7cddfSDavid du Colombier     char *buffer;
3547dd7cddfSDavid du Colombier 
3557dd7cddfSDavid du Colombier     if (!is_win32s)
3567dd7cddfSDavid du Colombier 	return get_queues();
3577dd7cddfSDavid du Colombier 
3587dd7cddfSDavid du Colombier     if ((buffer = malloc(PORT_BUF_SIZE)) == (char *)NULL)
3597dd7cddfSDavid du Colombier 	return NULL;
3607dd7cddfSDavid du Colombier     GetProfileString("ports", NULL, "", buffer, PORT_BUF_SIZE);
3617dd7cddfSDavid du Colombier     return buffer;
3627dd7cddfSDavid du Colombier }
3637dd7cddfSDavid du Colombier 
3647dd7cddfSDavid du Colombier /* return TRUE if queuename available */
3657dd7cddfSDavid du Colombier /* return FALSE if cancelled or error */
3667dd7cddfSDavid du Colombier /* if queue non-NULL, use as suggested queue */
3677dd7cddfSDavid du Colombier BOOL
get_queuename(char * portname,const char * queue)3687dd7cddfSDavid du Colombier get_queuename(char *portname, const char *queue)
3697dd7cddfSDavid du Colombier {
3707dd7cddfSDavid du Colombier     char *buffer;
3717dd7cddfSDavid du Colombier     char *p;
3727dd7cddfSDavid du Colombier     int i, iport;
3737dd7cddfSDavid du Colombier 
3747dd7cddfSDavid du Colombier     buffer = get_queues();
3757dd7cddfSDavid du Colombier     if (buffer == NULL)
3767dd7cddfSDavid du Colombier 	return FALSE;
3777dd7cddfSDavid du Colombier     if ((queue == (char *)NULL) || (strlen(queue) == 0)) {
3787dd7cddfSDavid du Colombier 	/* select a queue */
3797dd7cddfSDavid du Colombier 	iport = DialogBoxParam(phInstance, "QueueDlgBox", (HWND) NULL, SpoolDlgProc, (LPARAM) buffer);
3807dd7cddfSDavid du Colombier 	if (!iport) {
3817dd7cddfSDavid du Colombier 	    free(buffer);
3827dd7cddfSDavid du Colombier 	    return FALSE;
3837dd7cddfSDavid du Colombier 	}
3847dd7cddfSDavid du Colombier 	p = buffer;
3857dd7cddfSDavid du Colombier 	for (i = 1; i < iport && strlen(p) != 0; i++)
3867dd7cddfSDavid du Colombier 	    p += lstrlen(p) + 1;
3877dd7cddfSDavid du Colombier 	/* prepend \\spool\ which is used by Ghostscript to distinguish */
3887dd7cddfSDavid du Colombier 	/* real files from queues */
3897dd7cddfSDavid du Colombier 	strcpy(portname, "\\\\spool\\");
3907dd7cddfSDavid du Colombier 	strcat(portname, p);
3917dd7cddfSDavid du Colombier     } else {
3927dd7cddfSDavid du Colombier 	strcpy(portname, "\\\\spool\\");
3937dd7cddfSDavid du Colombier 	strcat(portname, queue);
3947dd7cddfSDavid du Colombier     }
3957dd7cddfSDavid du Colombier 
3967dd7cddfSDavid du Colombier     free(buffer);
3977dd7cddfSDavid du Colombier     return TRUE;
3987dd7cddfSDavid du Colombier }
3997dd7cddfSDavid du Colombier 
4007dd7cddfSDavid du Colombier /* return TRUE if portname available */
4017dd7cddfSDavid du Colombier /* return FALSE if cancelled or error */
4027dd7cddfSDavid du Colombier /* if port non-NULL, use as suggested port */
4037dd7cddfSDavid du Colombier BOOL
get_portname(char * portname,const char * port)4047dd7cddfSDavid du Colombier get_portname(char *portname, const char *port)
4057dd7cddfSDavid du Colombier {
4067dd7cddfSDavid du Colombier     char *buffer;
4077dd7cddfSDavid du Colombier     char *p;
4087dd7cddfSDavid du Colombier     int i, iport;
4097dd7cddfSDavid du Colombier     char filename[MAXSTR];
4107dd7cddfSDavid du Colombier 
4117dd7cddfSDavid du Colombier     buffer = get_ports();
4127dd7cddfSDavid du Colombier     if (buffer == NULL)
4137dd7cddfSDavid du Colombier 	return FALSE;
4147dd7cddfSDavid du Colombier     if ((port == (char *)NULL) || (strlen(port) == 0)) {
4157dd7cddfSDavid du Colombier 	if (buffer == (char *)NULL)
4167dd7cddfSDavid du Colombier 	    return FALSE;
4177dd7cddfSDavid du Colombier 	/* select a port */
4187dd7cddfSDavid du Colombier 	iport = DialogBoxParam(phInstance, "SpoolDlgBox", (HWND) NULL, SpoolDlgProc, (LPARAM) buffer);
4197dd7cddfSDavid du Colombier 	if (!iport) {
4207dd7cddfSDavid du Colombier 	    free(buffer);
4217dd7cddfSDavid du Colombier 	    return FALSE;
4227dd7cddfSDavid du Colombier 	}
4237dd7cddfSDavid du Colombier 	p = buffer;
4247dd7cddfSDavid du Colombier 	for (i = 1; i < iport && strlen(p) != 0; i++)
4257dd7cddfSDavid du Colombier 	    p += lstrlen(p) + 1;
4267dd7cddfSDavid du Colombier 	strcpy(portname, p);
4277dd7cddfSDavid du Colombier     } else
4287dd7cddfSDavid du Colombier 	strcpy(portname, port);
4297dd7cddfSDavid du Colombier 
4307dd7cddfSDavid du Colombier     if (strlen(portname) == 0)
4317dd7cddfSDavid du Colombier 	return FALSE;
4327dd7cddfSDavid du Colombier     if (strcmp(portname, "FILE:") == 0) {
4337dd7cddfSDavid du Colombier 	OPENFILENAME ofn;
4347dd7cddfSDavid du Colombier 
4357dd7cddfSDavid du Colombier 	filename[0] = '\0';
4367dd7cddfSDavid du Colombier 	memset(&ofn, 0, sizeof(OPENFILENAME));
4377dd7cddfSDavid du Colombier 	ofn.lStructSize = sizeof(OPENFILENAME);
4387dd7cddfSDavid du Colombier 	ofn.hwndOwner = (HWND) NULL;
4397dd7cddfSDavid du Colombier 	ofn.lpstrFile = filename;
4407dd7cddfSDavid du Colombier 	ofn.nMaxFile = sizeof(filename);
4417dd7cddfSDavid du Colombier 	ofn.Flags = OFN_PATHMUSTEXIST;
4427dd7cddfSDavid du Colombier 	if (!GetSaveFileName(&ofn)) {
4437dd7cddfSDavid du Colombier 	    free(buffer);
4447dd7cddfSDavid du Colombier 	    return FALSE;
4457dd7cddfSDavid du Colombier 	}
4467dd7cddfSDavid du Colombier 	strcpy(portname, filename);
4477dd7cddfSDavid du Colombier     }
4487dd7cddfSDavid du Colombier     free(buffer);
4497dd7cddfSDavid du Colombier     return TRUE;
4507dd7cddfSDavid du Colombier }
4517dd7cddfSDavid du Colombier 
4527dd7cddfSDavid du Colombier 
4537dd7cddfSDavid du Colombier /* True Win32 method, using OpenPrinter, WritePrinter etc. */
4547dd7cddfSDavid du Colombier private int
gp_printfile_win32(const char * filename,char * port)4557dd7cddfSDavid du Colombier gp_printfile_win32(const char *filename, char *port)
4567dd7cddfSDavid du Colombier {
4577dd7cddfSDavid du Colombier     DWORD count;
4587dd7cddfSDavid du Colombier     char *buffer;
4597dd7cddfSDavid du Colombier     char portname[MAXSTR];
4607dd7cddfSDavid du Colombier     FILE *f;
4617dd7cddfSDavid du Colombier     HANDLE printer;
4627dd7cddfSDavid du Colombier     DOC_INFO_1 di;
4637dd7cddfSDavid du Colombier     DWORD written;
4647dd7cddfSDavid du Colombier 
4657dd7cddfSDavid du Colombier     if (!get_queuename(portname, port))
4667dd7cddfSDavid du Colombier 	return FALSE;
4677dd7cddfSDavid du Colombier     port = portname + 8;	/* skip over \\spool\ */
4687dd7cddfSDavid du Colombier 
4697dd7cddfSDavid du Colombier     if ((buffer = malloc(PRINT_BUF_SIZE)) == (char *)NULL)
4707dd7cddfSDavid du Colombier 	return FALSE;
4717dd7cddfSDavid du Colombier 
4727dd7cddfSDavid du Colombier     if ((f = fopen(filename, "rb")) == (FILE *) NULL) {
4737dd7cddfSDavid du Colombier 	free(buffer);
4747dd7cddfSDavid du Colombier 	return FALSE;
4757dd7cddfSDavid du Colombier     }
4767dd7cddfSDavid du Colombier     /* open a printer */
4777dd7cddfSDavid du Colombier     if (!OpenPrinter(port, &printer, NULL)) {
4787dd7cddfSDavid du Colombier 	char buf[256];
4797dd7cddfSDavid du Colombier 
4807dd7cddfSDavid du Colombier 	sprintf(buf, "OpenPrinter() failed for \042%s\042, error code = %d", port, GetLastError());
4817dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
4827dd7cddfSDavid du Colombier 	free(buffer);
4837dd7cddfSDavid du Colombier 	return FALSE;
4847dd7cddfSDavid du Colombier     }
4857dd7cddfSDavid du Colombier     /* from here until ClosePrinter, should AbortPrinter on error */
4867dd7cddfSDavid du Colombier 
4877dd7cddfSDavid du Colombier     di.pDocName = szAppName;
4887dd7cddfSDavid du Colombier     di.pOutputFile = NULL;
4897dd7cddfSDavid du Colombier     di.pDatatype = "RAW";	/* for available types see EnumPrintProcessorDatatypes */
4907dd7cddfSDavid du Colombier     if (!StartDocPrinter(printer, 1, (LPBYTE) & di)) {
4917dd7cddfSDavid du Colombier 	char buf[256];
4927dd7cddfSDavid du Colombier 
4937dd7cddfSDavid du Colombier 	sprintf(buf, "StartDocPrinter() failed, error code = %d", GetLastError());
4947dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
4957dd7cddfSDavid du Colombier 	AbortPrinter(printer);
4967dd7cddfSDavid du Colombier 	free(buffer);
4977dd7cddfSDavid du Colombier 	return FALSE;
4987dd7cddfSDavid du Colombier     }
4997dd7cddfSDavid du Colombier     /* copy file to printer */
5007dd7cddfSDavid du Colombier     while ((count = fread(buffer, 1, PRINT_BUF_SIZE, f)) != 0) {
5017dd7cddfSDavid du Colombier 	if (!WritePrinter(printer, (LPVOID) buffer, count, &written)) {
5027dd7cddfSDavid du Colombier 	    free(buffer);
5037dd7cddfSDavid du Colombier 	    fclose(f);
5047dd7cddfSDavid du Colombier 	    AbortPrinter(printer);
5057dd7cddfSDavid du Colombier 	    return FALSE;
5067dd7cddfSDavid du Colombier 	}
5077dd7cddfSDavid du Colombier     }
5087dd7cddfSDavid du Colombier     fclose(f);
5097dd7cddfSDavid du Colombier     free(buffer);
5107dd7cddfSDavid du Colombier 
5117dd7cddfSDavid du Colombier     if (!EndDocPrinter(printer)) {
5127dd7cddfSDavid du Colombier 	char buf[256];
5137dd7cddfSDavid du Colombier 
5147dd7cddfSDavid du Colombier 	sprintf(buf, "EndDocPrinter() failed, error code = %d", GetLastError());
5157dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
5167dd7cddfSDavid du Colombier 	AbortPrinter(printer);
5177dd7cddfSDavid du Colombier 	return FALSE;
5187dd7cddfSDavid du Colombier     }
5197dd7cddfSDavid du Colombier     if (!ClosePrinter(printer)) {
5207dd7cddfSDavid du Colombier 	char buf[256];
5217dd7cddfSDavid du Colombier 
5227dd7cddfSDavid du Colombier 	sprintf(buf, "ClosePrinter() failed, error code = %d", GetLastError());
5237dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
5247dd7cddfSDavid du Colombier 	return FALSE;
5257dd7cddfSDavid du Colombier     }
5267dd7cddfSDavid du Colombier     return TRUE;
5277dd7cddfSDavid du Colombier }
5287dd7cddfSDavid du Colombier 
5297dd7cddfSDavid du Colombier 
5307dd7cddfSDavid du Colombier /* Start a 16-bit application gs16spl.exe to print a file */
5317dd7cddfSDavid du Colombier /* Intended for Win32s where 16-bit spooler functions are not available */
5327dd7cddfSDavid du Colombier /* and Win32 spooler functions are not implemented. */
5337dd7cddfSDavid du Colombier int
gp_printfile_gs16spl(const char * filename,const char * port)5347dd7cddfSDavid du Colombier gp_printfile_gs16spl(const char *filename, const char *port)
5357dd7cddfSDavid du Colombier {
5367dd7cddfSDavid du Colombier /* Get printer port list from win.ini */
5377dd7cddfSDavid du Colombier     char portname[MAXSTR];
5387dd7cddfSDavid du Colombier     HINSTANCE hinst;
5397dd7cddfSDavid du Colombier     char command[MAXSTR];
5407dd7cddfSDavid du Colombier     char *p;
5417dd7cddfSDavid du Colombier     HWND hwndspl;
5427dd7cddfSDavid du Colombier 
5437dd7cddfSDavid du Colombier     if (!get_portname(portname, port))
5447dd7cddfSDavid du Colombier 	return FALSE;
5457dd7cddfSDavid du Colombier 
5467dd7cddfSDavid du Colombier     /* get path to EXE - same as DLL */
5477dd7cddfSDavid du Colombier     GetModuleFileName(phInstance, command, sizeof(command));
5487dd7cddfSDavid du Colombier     if ((p = strrchr(command, '\\')) != (char *)NULL)
5497dd7cddfSDavid du Colombier 	p++;
5507dd7cddfSDavid du Colombier     else
5517dd7cddfSDavid du Colombier 	p = command;
5527dd7cddfSDavid du Colombier     *p = '\0';
5537dd7cddfSDavid du Colombier     sprintf(command + strlen(command), "gs16spl.exe %s %s",
5547dd7cddfSDavid du Colombier 	    portname, filename);
5557dd7cddfSDavid du Colombier 
5567dd7cddfSDavid du Colombier     hinst = (HINSTANCE) WinExec(command, SW_SHOWNORMAL);
5577dd7cddfSDavid du Colombier     if (hinst < (HINSTANCE) HINSTANCE_ERROR) {
5587dd7cddfSDavid du Colombier 	char buf[MAXSTR];
5597dd7cddfSDavid du Colombier 
5607dd7cddfSDavid du Colombier 	sprintf(buf, "Can't run: %s", command);
5617dd7cddfSDavid du Colombier 	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
5627dd7cddfSDavid du Colombier 	return FALSE;
5637dd7cddfSDavid du Colombier     }
5647dd7cddfSDavid du Colombier     hwndspl = FindWindow(NULL, "GS Win32s/Win16 spooler");
5657dd7cddfSDavid du Colombier 
5667dd7cddfSDavid du Colombier     while (IsWindow(hwndspl)) {
567*593dc095SDavid du Colombier 	gp_check_interrupts(NULL);
5687dd7cddfSDavid du Colombier     }
5697dd7cddfSDavid du Colombier 
5707dd7cddfSDavid du Colombier     return 0;
5717dd7cddfSDavid du Colombier }
5727dd7cddfSDavid du Colombier 
5737dd7cddfSDavid du Colombier 
574*593dc095SDavid du Colombier /******************************************************************/
575*593dc095SDavid du Colombier /* MS Windows has popen and pclose in stdio.h, but under different names.
576*593dc095SDavid du Colombier  * Unfortunately MSVC5 and 6 have a broken implementation of _popen,
577*593dc095SDavid du Colombier  * so we use own.  Our implementation only supports mode "wb".
578*593dc095SDavid du Colombier  */
mswin_popen(const char * cmd,const char * mode)579*593dc095SDavid du Colombier FILE *mswin_popen(const char *cmd, const char *mode)
580*593dc095SDavid du Colombier {
581*593dc095SDavid du Colombier     SECURITY_ATTRIBUTES saAttr;
582*593dc095SDavid du Colombier     STARTUPINFO siStartInfo;
583*593dc095SDavid du Colombier     PROCESS_INFORMATION piProcInfo;
584*593dc095SDavid du Colombier     HANDLE hPipeTemp = INVALID_HANDLE_VALUE;
585*593dc095SDavid du Colombier     HANDLE hChildStdinRd = INVALID_HANDLE_VALUE;
586*593dc095SDavid du Colombier     HANDLE hChildStdinWr = INVALID_HANDLE_VALUE;
587*593dc095SDavid du Colombier     HANDLE hChildStdoutWr = INVALID_HANDLE_VALUE;
588*593dc095SDavid du Colombier     HANDLE hChildStderrWr = INVALID_HANDLE_VALUE;
589*593dc095SDavid du Colombier     HANDLE hProcess = GetCurrentProcess();
590*593dc095SDavid du Colombier     int handle = 0;
591*593dc095SDavid du Colombier     char *command = NULL;
592*593dc095SDavid du Colombier     FILE *pipe = NULL;
593*593dc095SDavid du Colombier 
594*593dc095SDavid du Colombier     if (strcmp(mode, "wb") != 0)
595*593dc095SDavid du Colombier 	return NULL;
596*593dc095SDavid du Colombier 
597*593dc095SDavid du Colombier     /* Set the bInheritHandle flag so pipe handles are inherited. */
598*593dc095SDavid du Colombier     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
599*593dc095SDavid du Colombier     saAttr.bInheritHandle = TRUE;
600*593dc095SDavid du Colombier     saAttr.lpSecurityDescriptor = NULL;
601*593dc095SDavid du Colombier 
602*593dc095SDavid du Colombier     /* Create anonymous inheritable pipes for STDIN for child.
603*593dc095SDavid du Colombier      * First create a noninheritable duplicate handle of our end of
604*593dc095SDavid du Colombier      * the pipe, then close the inheritable handle.
605*593dc095SDavid du Colombier      */
606*593dc095SDavid du Colombier     if (handle == 0)
607*593dc095SDavid du Colombier         if (!CreatePipe(&hChildStdinRd, &hPipeTemp, &saAttr, 0))
608*593dc095SDavid du Colombier 	    handle = -1;
609*593dc095SDavid du Colombier     if (handle == 0) {
610*593dc095SDavid du Colombier 	if (!DuplicateHandle(hProcess, hPipeTemp,
611*593dc095SDavid du Colombier 	    hProcess, &hChildStdinWr, 0, FALSE /* not inherited */,
612*593dc095SDavid du Colombier 	    DUPLICATE_SAME_ACCESS))
613*593dc095SDavid du Colombier 	    handle = -1;
614*593dc095SDavid du Colombier         CloseHandle(hPipeTemp);
615*593dc095SDavid du Colombier     }
616*593dc095SDavid du Colombier     /* Create inheritable duplicate handles for our stdout/err */
617*593dc095SDavid du Colombier     if (handle == 0)
618*593dc095SDavid du Colombier 	if (!DuplicateHandle(hProcess, GetStdHandle(STD_OUTPUT_HANDLE),
619*593dc095SDavid du Colombier 	    hProcess, &hChildStdoutWr, 0, TRUE /* inherited */,
620*593dc095SDavid du Colombier 	    DUPLICATE_SAME_ACCESS))
621*593dc095SDavid du Colombier 	    handle = -1;
622*593dc095SDavid du Colombier     if (handle == 0)
623*593dc095SDavid du Colombier         if (!DuplicateHandle(hProcess, GetStdHandle(STD_ERROR_HANDLE),
624*593dc095SDavid du Colombier             hProcess, &hChildStderrWr, 0, TRUE /* inherited */,
625*593dc095SDavid du Colombier 	    DUPLICATE_SAME_ACCESS))
626*593dc095SDavid du Colombier 	    handle = -1;
627*593dc095SDavid du Colombier 
628*593dc095SDavid du Colombier     /* Set up members of STARTUPINFO structure. */
629*593dc095SDavid du Colombier     memset(&siStartInfo, 0, sizeof(STARTUPINFO));
630*593dc095SDavid du Colombier     siStartInfo.cb = sizeof(STARTUPINFO);
631*593dc095SDavid du Colombier     siStartInfo.dwFlags = STARTF_USESTDHANDLES;
632*593dc095SDavid du Colombier     siStartInfo.hStdInput = hChildStdinRd;
633*593dc095SDavid du Colombier     siStartInfo.hStdOutput = hChildStdoutWr;
634*593dc095SDavid du Colombier     siStartInfo.hStdError = hChildStderrWr;
635*593dc095SDavid du Colombier 
636*593dc095SDavid du Colombier     if (handle == 0) {
637*593dc095SDavid du Colombier 	command = (char *)malloc(strlen(cmd)+1);
638*593dc095SDavid du Colombier 	if (command)
639*593dc095SDavid du Colombier 	    strcpy(command, cmd);
640*593dc095SDavid du Colombier 	else
641*593dc095SDavid du Colombier 	    handle = -1;
642*593dc095SDavid du Colombier     }
643*593dc095SDavid du Colombier 
644*593dc095SDavid du Colombier     if (handle == 0)
645*593dc095SDavid du Colombier 	if (!CreateProcess(NULL,
646*593dc095SDavid du Colombier 	    command,  	   /* command line                       */
647*593dc095SDavid du Colombier 	    NULL,          /* process security attributes        */
648*593dc095SDavid du Colombier 	    NULL,          /* primary thread security attributes */
649*593dc095SDavid du Colombier 	    TRUE,          /* handles are inherited              */
650*593dc095SDavid du Colombier 	    0,             /* creation flags                     */
651*593dc095SDavid du Colombier 	    NULL,          /* environment                        */
652*593dc095SDavid du Colombier 	    NULL,          /* use parent's current directory     */
653*593dc095SDavid du Colombier 	    &siStartInfo,  /* STARTUPINFO pointer                */
654*593dc095SDavid du Colombier 	    &piProcInfo))  /* receives PROCESS_INFORMATION  */
655*593dc095SDavid du Colombier 	{
656*593dc095SDavid du Colombier 	    handle = -1;
657*593dc095SDavid du Colombier 	}
658*593dc095SDavid du Colombier 	else {
659*593dc095SDavid du Colombier 	    CloseHandle(piProcInfo.hProcess);
660*593dc095SDavid du Colombier 	    CloseHandle(piProcInfo.hThread);
661*593dc095SDavid du Colombier 	    handle = _open_osfhandle((long)hChildStdinWr, 0);
662*593dc095SDavid du Colombier 	}
663*593dc095SDavid du Colombier 
664*593dc095SDavid du Colombier     if (hChildStdinRd != INVALID_HANDLE_VALUE)
665*593dc095SDavid du Colombier 	CloseHandle(hChildStdinRd);	/* close our copy */
666*593dc095SDavid du Colombier     if (hChildStdoutWr != INVALID_HANDLE_VALUE)
667*593dc095SDavid du Colombier 	CloseHandle(hChildStdoutWr);	/* close our copy */
668*593dc095SDavid du Colombier     if (hChildStderrWr != INVALID_HANDLE_VALUE)
669*593dc095SDavid du Colombier 	CloseHandle(hChildStderrWr);	/* close our copy */
670*593dc095SDavid du Colombier     if (command)
671*593dc095SDavid du Colombier 	free(command);
672*593dc095SDavid du Colombier 
673*593dc095SDavid du Colombier     if (handle < 0) {
674*593dc095SDavid du Colombier 	if (hChildStdinWr != INVALID_HANDLE_VALUE)
675*593dc095SDavid du Colombier 	    CloseHandle(hChildStdinWr);
676*593dc095SDavid du Colombier     }
677*593dc095SDavid du Colombier     else {
678*593dc095SDavid du Colombier 	pipe = _fdopen(handle, "wb");
679*593dc095SDavid du Colombier 	if (pipe == NULL)
680*593dc095SDavid du Colombier 	    _close(handle);
681*593dc095SDavid du Colombier     }
682*593dc095SDavid du Colombier     return pipe;
683*593dc095SDavid du Colombier }
6847dd7cddfSDavid du Colombier 
6857dd7cddfSDavid du Colombier 
6867dd7cddfSDavid du Colombier /* ------ File naming and accessing ------ */
6877dd7cddfSDavid du Colombier 
6887dd7cddfSDavid du Colombier /* Create and open a scratch file with a given name prefix. */
6897dd7cddfSDavid du Colombier /* Write the actual file name at fname. */
6907dd7cddfSDavid du Colombier FILE *
gp_open_scratch_file(const char * prefix,char * fname,const char * mode)6917dd7cddfSDavid du Colombier gp_open_scratch_file(const char *prefix, char *fname, const char *mode)
692*593dc095SDavid du Colombier {
693*593dc095SDavid du Colombier     UINT n;
694*593dc095SDavid du Colombier     DWORD l;
695*593dc095SDavid du Colombier     HANDLE hfile = INVALID_HANDLE_VALUE;
696*593dc095SDavid du Colombier     int fd = -1;
697*593dc095SDavid du Colombier     FILE *f = NULL;
698*593dc095SDavid du Colombier     char sTempDir[_MAX_PATH];
699*593dc095SDavid du Colombier     char sTempFileName[_MAX_PATH];
7007dd7cddfSDavid du Colombier 
701*593dc095SDavid du Colombier     memset(fname, 0, gp_file_name_sizeof);
702*593dc095SDavid du Colombier     if (!gp_file_name_is_absolute(prefix, strlen(prefix))) {
703*593dc095SDavid du Colombier 	int plen = sizeof(sTempDir);
7047dd7cddfSDavid du Colombier 
705*593dc095SDavid du Colombier 	if (gp_gettmpdir(sTempDir, &plen) != 0)
706*593dc095SDavid du Colombier 	    l = GetTempPath(sizeof(sTempDir), sTempDir);
707*593dc095SDavid du Colombier 	else
708*593dc095SDavid du Colombier 	    l = strlen(sTempDir);
709*593dc095SDavid du Colombier     } else {
710*593dc095SDavid du Colombier 	strncpy(sTempDir, prefix, sizeof(sTempDir));
711*593dc095SDavid du Colombier 	prefix = "";
712*593dc095SDavid du Colombier 	l = strlen(sTempDir);
7137dd7cddfSDavid du Colombier     }
714*593dc095SDavid du Colombier     /* Fix the trailing terminator so GetTempFileName doesn't get confused */
715*593dc095SDavid du Colombier     if (sTempDir[l-1] == '/')
716*593dc095SDavid du Colombier 	sTempDir[l-1] = '\\';		/* What Windoze prefers */
717*593dc095SDavid du Colombier 
718*593dc095SDavid du Colombier     if (l <= sizeof(sTempDir)) {
719*593dc095SDavid du Colombier 	n = GetTempFileName(sTempDir, prefix, 0, sTempFileName);
720*593dc095SDavid du Colombier 	if (n == 0) {
721*593dc095SDavid du Colombier 	    /* If 'prefix' is not a directory, it is a path prefix. */
722*593dc095SDavid du Colombier 	    int l = strlen(sTempDir), i;
723*593dc095SDavid du Colombier 
724*593dc095SDavid du Colombier 	    for (i = l - 1; i > 0; i--) {
725*593dc095SDavid du Colombier 		uint slen = gs_file_name_check_separator(sTempDir + i, l, sTempDir + l);
726*593dc095SDavid du Colombier 
727*593dc095SDavid du Colombier 		if (slen > 0) {
728*593dc095SDavid du Colombier 		    sTempDir[i] = 0;
729*593dc095SDavid du Colombier 		    i += slen;
730*593dc095SDavid du Colombier 		    break;
731*593dc095SDavid du Colombier 		}
732*593dc095SDavid du Colombier 	    }
733*593dc095SDavid du Colombier 	    if (i > 0)
734*593dc095SDavid du Colombier 		n = GetTempFileName(sTempDir, sTempDir + i, 0, sTempFileName);
735*593dc095SDavid du Colombier 	}
736*593dc095SDavid du Colombier 	if (n != 0) {
737*593dc095SDavid du Colombier 	    hfile = CreateFile(sTempFileName,
738*593dc095SDavid du Colombier 		GENERIC_READ | GENERIC_WRITE | DELETE,
739*593dc095SDavid du Colombier 		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
740*593dc095SDavid du Colombier 		FILE_ATTRIBUTE_NORMAL /* | FILE_FLAG_DELETE_ON_CLOSE */,
741*593dc095SDavid du Colombier 		NULL);
742*593dc095SDavid du Colombier 	    /*
743*593dc095SDavid du Colombier 	     * Can't apply FILE_FLAG_DELETE_ON_CLOSE due to
744*593dc095SDavid du Colombier 	     * the logics of clist_fclose. Also note that
745*593dc095SDavid du Colombier 	     * gdev_prn_render_pages requires multiple temporary files
746*593dc095SDavid du Colombier 	     * to exist simultaneousely, so that keeping all them opened
747*593dc095SDavid du Colombier 	     * may exceed available CRTL file handles.
748*593dc095SDavid du Colombier 	     */
749*593dc095SDavid du Colombier 	}
750*593dc095SDavid du Colombier     }
751*593dc095SDavid du Colombier     if (hfile != INVALID_HANDLE_VALUE) {
752*593dc095SDavid du Colombier 	/* Associate a C file handle with an OS file handle. */
753*593dc095SDavid du Colombier 	fd = _open_osfhandle((long)hfile, 0);
754*593dc095SDavid du Colombier 	if (fd == -1)
755*593dc095SDavid du Colombier 	    CloseHandle(hfile);
756*593dc095SDavid du Colombier 	else {
757*593dc095SDavid du Colombier 	    /* Associate a C file stream with C file handle. */
758*593dc095SDavid du Colombier 	    f = fdopen(fd, mode);
759*593dc095SDavid du Colombier 	    if (f == NULL)
760*593dc095SDavid du Colombier 		_close(fd);
761*593dc095SDavid du Colombier 	}
762*593dc095SDavid du Colombier     }
763*593dc095SDavid du Colombier     if (f != NULL) {
764*593dc095SDavid du Colombier 	if ((strlen(sTempFileName) < gp_file_name_sizeof))
765*593dc095SDavid du Colombier 	    strncpy(fname, sTempFileName, gp_file_name_sizeof - 1);
766*593dc095SDavid du Colombier 	else {
767*593dc095SDavid du Colombier 	    /* The file name is too long. */
768*593dc095SDavid du Colombier 	    fclose(f);
769*593dc095SDavid du Colombier 	    f = NULL;
770*593dc095SDavid du Colombier 	}
771*593dc095SDavid du Colombier     }
772*593dc095SDavid du Colombier     if (f == NULL)
773*593dc095SDavid du Colombier 	eprintf1("**** Could not open temporary file '%s'\n", fname);
774*593dc095SDavid du Colombier     return f;
7757dd7cddfSDavid du Colombier }
7767dd7cddfSDavid du Colombier 
7777dd7cddfSDavid du Colombier /* Open a file with the given name, as a stream of uninterpreted bytes. */
7787dd7cddfSDavid du Colombier FILE *
gp_fopen(const char * fname,const char * mode)7797dd7cddfSDavid du Colombier gp_fopen(const char *fname, const char *mode)
7807dd7cddfSDavid du Colombier {
7817dd7cddfSDavid du Colombier     return fopen(fname, mode);
7827dd7cddfSDavid du Colombier }
7833ff48bf5SDavid du Colombier 
784*593dc095SDavid du Colombier /* ------ Font enumeration ------ */
785*593dc095SDavid du Colombier 
786*593dc095SDavid du Colombier  /* This is used to query the native os for a list of font names and
787*593dc095SDavid du Colombier   * corresponding paths. The general idea is to save the hassle of
788*593dc095SDavid du Colombier   * building a custom fontmap file.
789*593dc095SDavid du Colombier   */
790*593dc095SDavid du Colombier 
gp_enumerate_fonts_init(gs_memory_t * mem)791*593dc095SDavid du Colombier void *gp_enumerate_fonts_init(gs_memory_t *mem)
792*593dc095SDavid du Colombier {
793*593dc095SDavid du Colombier     return NULL;
794*593dc095SDavid du Colombier }
795*593dc095SDavid du Colombier 
gp_enumerate_fonts_next(void * enum_state,char ** fontname,char ** path)796*593dc095SDavid du Colombier int gp_enumerate_fonts_next(void *enum_state, char **fontname, char **path)
797*593dc095SDavid du Colombier {
798*593dc095SDavid du Colombier     return 0;
799*593dc095SDavid du Colombier }
800*593dc095SDavid du Colombier 
gp_enumerate_fonts_free(void * enum_state)801*593dc095SDavid du Colombier void gp_enumerate_fonts_free(void *enum_state)
802*593dc095SDavid du Colombier {
803*593dc095SDavid du Colombier }
804