Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/gs/src/gp_mswin.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1992, 2000-2003 artofcode LLC.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gp_mswin.c,v 1.25 2005/03/04 21:58:55 ghostgum Exp $ */
18
/*
19
 * Microsoft Windows platform support for Ghostscript.
20
 *
21
 * Original version by Russell Lang and Maurice Castro with help from
22
 * Programming Windows, 2nd Ed., Charles Petzold, Microsoft Press;
23
 * initially created from gp_dosfb.c and gp_itbc.c 5th June 1992.
24
 */
25
 
26
/* Modified for Win32 & Microsoft C/C++ 8.0 32-Bit, 26.Okt.1994 */
27
/* by Friedrich Nowak                                           */
28
 
29
/* Original EXE and GSview specific code removed */
30
/* DLL version must now be used under MS-Windows */
31
/* Russell Lang 16 March 1996 */
32
 
33
#include "stdio_.h"
34
#include "string_.h"
35
#include "memory_.h"
36
#include "pipe_.h"
37
#include <stdlib.h>
38
#include <stdarg.h>
39
#include "ctype_.h"
40
#include <io.h>
41
#include "malloc_.h"
42
#include <fcntl.h>
43
#include <signal.h>
44
#include "gx.h"
45
#include "gp.h"
46
#include "gpcheck.h"
47
#include "gpmisc.h"
48
#include "gserrors.h"
49
#include "gsexit.h"
50
 
51
#include "windows_.h"
52
#include <shellapi.h>
53
#include <winspool.h>
54
#include "gp_mswin.h"
55
 
56
/* Library routines not declared in a standard header */
57
extern char *getenv(const char *);
58
 
59
/* limits */
60
#define MAXSTR 255
61
 
62
/* GLOBAL VARIABLE that needs to be removed */
63
char win_prntmp[MAXSTR];	/* filename of PRN temporary file */
64
 
65
/* GLOBAL VARIABLES - initialised at DLL load time */
66
HINSTANCE phInstance;
67
BOOL is_win32s = FALSE;
68
 
69
const LPSTR szAppName = "Ghostscript";
70
private int is_printer(const char *name);
71
 
72
 
73
/* ====== Generic platform procedures ====== */
74
 
75
/* ------ Initialization/termination (from gp_itbc.c) ------ */
76
 
77
/* Do platform-dependent initialization. */
78
void
79
gp_init(void)
80
{
81
}
82
 
83
/* Do platform-dependent cleanup. */
84
void
85
gp_exit(int exit_status, int code)
86
{
87
}
88
 
89
/* Exit the program. */
90
void
91
gp_do_exit(int exit_status)
92
{
93
    exit(exit_status);
94
}
95
 
96
/* ------ Persistent data cache ------*/
97
 
98
/* insert a buffer under a (type, key) pair */
99
int gp_cache_insert(int type, byte *key, int keylen, void *buffer, int buflen)
100
{
101
    /* not yet implemented */
102
    return 0;
103
}
104
 
105
/* look up a (type, key) in the cache */
106
int gp_cache_query(int type, byte* key, int keylen, void **buffer,
107
    gp_cache_alloc alloc, void *userdata)
108
{
109
    /* not yet implemented */
110
    return -1;
111
}
112
 
113
/* ------ Printer accessing ------ */
114
 
115
/* Forward references */
116
private int gp_printfile(const char *, const char *);
117
 
118
/* Open a connection to a printer.  A null file name means use the */
119
/* standard printer connected to the machine, if any. */
120
/* Return NULL if the connection could not be opened. */
121
FILE *
122
gp_open_printer(char fname[gp_file_name_sizeof], int binary_mode)
123
{
124
    if (is_printer(fname)) {
125
	FILE *pfile;
126
 
127
	/* Open a scratch file, which we will send to the */
128
	/* actual printer in gp_close_printer. */
129
	pfile = gp_open_scratch_file(gp_scratch_file_name_prefix,
130
				     win_prntmp, "wb");
131
	return pfile;
132
    } else if (fname[0] == '|') 	/* pipe */
133
	return popen(fname + 1, (binary_mode ? "wb" : "w"));
134
    else
135
	return fopen(fname, (binary_mode ? "wb" : "w"));
136
}
137
 
138
/* Close the connection to the printer. */
139
void
140
gp_close_printer(FILE * pfile, const char *fname)
141
{
142
    fclose(pfile);
143
    if (!is_printer(fname))
144
	return;			/* a file, not a printer */
145
 
146
    gp_printfile(win_prntmp, fname);
147
    unlink(win_prntmp);
148
}
149
 
150
 
151
/* Dialog box to select printer port */
152
DLGRETURN CALLBACK
153
SpoolDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
154
{
155
    LPSTR entry;
156
 
157
    switch (message) {
158
	case WM_INITDIALOG:
159
	    entry = (LPSTR) lParam;
160
	    while (*entry) {
161
		SendDlgItemMessage(hDlg, SPOOL_PORT, LB_ADDSTRING, 0, (LPARAM) entry);
162
		entry += lstrlen(entry) + 1;
163
	    }
164
	    SendDlgItemMessage(hDlg, SPOOL_PORT, LB_SETCURSEL, 0, (LPARAM) 0);
165
	    return TRUE;
166
	case WM_COMMAND:
167
	    switch (LOWORD(wParam)) {
168
		case SPOOL_PORT:
169
		    if (HIWORD(wParam) == LBN_DBLCLK)
170
			PostMessage(hDlg, WM_COMMAND, IDOK, 0L);
171
		    return FALSE;
172
		case IDOK:
173
		    EndDialog(hDlg, 1 + (int)SendDlgItemMessage(hDlg, SPOOL_PORT, LB_GETCURSEL, 0, 0L));
174
		    return TRUE;
175
		case IDCANCEL:
176
		    EndDialog(hDlg, 0);
177
		    return TRUE;
178
	    }
179
    }
180
    return FALSE;
181
}
182
 
183
/* return TRUE if queue looks like a valid printer name */
184
int
185
is_spool(const char *queue)
186
{
187
    char *prefix = "\\\\spool";	/* 7 characters long */
188
    int i;
189
 
190
    for (i = 0; i < 7; i++) {
191
	if (prefix[i] == '\\') {
192
	    if ((*queue != '\\') && (*queue != '/'))
193
		return FALSE;
194
	} else if (tolower(*queue) != prefix[i])
195
	    return FALSE;
196
	queue++;
197
    }
198
    if (*queue && (*queue != '\\') && (*queue != '/'))
199
	return FALSE;
200
    return TRUE;
201
}
202
 
203
 
204
private int
205
is_printer(const char *name)
206
{
207
    char buf[128];
208
 
209
    /* is printer if no name given */
210
    if (strlen(name) == 0)
211
	return TRUE;
212
 
213
    /*  is printer if name appears in win.ini [ports] section */
214
    GetProfileString("ports", name, "XYZ", buf, sizeof(buf));
215
    if (strlen(name) == 0 || strcmp(buf, "XYZ"))
216
	return TRUE;
217
 
218
    /* is printer if name prefixed by \\spool\ */
219
    if (is_spool(name))
220
	return TRUE;
221
 
222
    return FALSE;
223
}
224
 
225
 
226
/******************************************************************/
227
/* Print File to port or queue */
228
/* port==NULL means prompt for port or queue with dialog box */
229
 
230
/* This is messy because Microsoft changed the spooler interface */
231
/* between Windows 3.1 and Windows 95/NT */
232
/* and didn't provide the spooler interface in Win32s */
233
 
234
/* Win95, WinNT: Use OpenPrinter, WritePrinter etc. */
235
private int gp_printfile_win32(const char *filename, char *port);
236
 
237
/* Win32s: Pass to Win16 spooler via gs16spl.exe */
238
private int gp_printfile_gs16spl(const char *filename, const char *port);
239
 
240
/*
241
 * Valid values for pmport are:
242
 *   ""
243
 *      action: WinNT and Win95 use default queue, Win32s prompts for port
244
 *   "LPT1:" (or other port that appears in win.ini [ports]
245
 *      action: start gs16spl.exe to print to the port
246
 *   "\\spool\printer name"
247
 *      action: send to printer using WritePrinter (WinNT and Win95).
248
 *      action: translate to port name using win.ini [Devices]
249
 *              then use gs16spl.exe (Win32s).
250
 *   "\\spool"
251
 *      action: prompt for queue name then send to printer using 
252
 *              WritePrinter (WinNT and Win95).
253
 *      action: prompt for port then use gs16spl.exe (Win32s).
254
 */
255
/* Print File */
256
private int
257
gp_printfile(const char *filename, const char *pmport)
258
{
259
    /* treat WinNT and Win95 differently to Win32s */
260
    if (!is_win32s) {
261
	if (strlen(pmport) == 0) {	/* get default printer */
262
	    char buf[256];
263
	    char *p;
264
 
265
	    /* WinNT stores default printer in registry and win.ini */
266
	    /* Win95 stores default printer in win.ini */
267
	    GetProfileString("windows", "device", "", buf, sizeof(buf));
268
	    if ((p = strchr(buf, ',')) != NULL)
269
		*p = '\0';
270
	    return gp_printfile_win32(filename, buf);
271
	} else if (is_spool(pmport)) {
272
	    if (strlen(pmport) >= 8)
273
		return gp_printfile_win32(filename, (char *)pmport + 8);
274
	    else
275
		return gp_printfile_win32(filename, (char *)NULL);
276
	} else
277
	    return gp_printfile_gs16spl(filename, pmport);
278
    } else {
279
	/* Win32s */
280
	if (is_spool(pmport)) {
281
	    if (strlen(pmport) >= 8) {
282
		/* extract port name from win.ini */
283
		char driverbuf[256];
284
		char *output;
285
 
286
		GetProfileString("Devices", pmport + 8, "", driverbuf, sizeof(driverbuf));
287
		strtok(driverbuf, ",");
288
		output = strtok(NULL, ",");
289
		return gp_printfile_gs16spl(filename, output);
290
	    } else
291
		return gp_printfile_gs16spl(filename, (char *)NULL);
292
	} else
293
	    return gp_printfile_gs16spl(filename, pmport);
294
    }
295
}
296
 
297
#define PRINT_BUF_SIZE 16384u
298
#define PORT_BUF_SIZE 4096
299
 
300
char *
301
get_queues(void)
302
{
303
    int i;
304
    DWORD count, needed;
305
    PRINTER_INFO_1 *prinfo;
306
    char *enumbuffer;
307
    char *buffer;
308
    char *p;
309
 
310
    /* enumerate all available printers */
311
    EnumPrinters(PRINTER_ENUM_CONNECTIONS | PRINTER_ENUM_LOCAL, NULL, 1, NULL, 0, &needed, &count);
312
    if (needed == 0) {
313
	/* no printers */
314
	enumbuffer = malloc(4);
315
	if (enumbuffer == (char *)NULL)
316
	    return NULL;
317
	memset(enumbuffer, 0, 4);
318
	return enumbuffer;
319
    }
320
    enumbuffer = malloc(needed);
321
    if (enumbuffer == (char *)NULL)
322
	return NULL;
323
    if (!EnumPrinters(PRINTER_ENUM_CONNECTIONS | PRINTER_ENUM_LOCAL, NULL, 1, (LPBYTE) enumbuffer, needed, &needed, &count)) {
324
	char buf[256];
325
 
326
	free(enumbuffer);
327
	sprintf(buf, "EnumPrinters() failed, error code = %d", GetLastError());
328
	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
329
	return NULL;
330
    }
331
    prinfo = (PRINTER_INFO_1 *) enumbuffer;
332
    if ((buffer = malloc(PORT_BUF_SIZE)) == (char *)NULL) {
333
	free(enumbuffer);
334
	return NULL;
335
    }
336
    /* copy printer names to single buffer */
337
    p = buffer;
338
    for (i = 0; i < count; i++) {
339
	if (strlen(prinfo[i].pName) + 1 < (PORT_BUF_SIZE - (p - buffer))) {
340
	    strcpy(p, prinfo[i].pName);
341
	    p += strlen(p) + 1;
342
	}
343
    }
344
    *p = '\0';			/* double null at end */
345
    free(enumbuffer);
346
    return buffer;
347
}
348
 
349
 
350
char *
351
get_ports(void)
352
{
353
    char *buffer;
354
 
355
    if (!is_win32s)
356
	return get_queues();
357
 
358
    if ((buffer = malloc(PORT_BUF_SIZE)) == (char *)NULL)
359
	return NULL;
360
    GetProfileString("ports", NULL, "", buffer, PORT_BUF_SIZE);
361
    return buffer;
362
}
363
 
364
/* return TRUE if queuename available */
365
/* return FALSE if cancelled or error */
366
/* if queue non-NULL, use as suggested queue */
367
BOOL
368
get_queuename(char *portname, const char *queue)
369
{
370
    char *buffer;
371
    char *p;
372
    int i, iport;
373
 
374
    buffer = get_queues();
375
    if (buffer == NULL)
376
	return FALSE;
377
    if ((queue == (char *)NULL) || (strlen(queue) == 0)) {
378
	/* select a queue */
379
	iport = DialogBoxParam(phInstance, "QueueDlgBox", (HWND) NULL, SpoolDlgProc, (LPARAM) buffer);
380
	if (!iport) {
381
	    free(buffer);
382
	    return FALSE;
383
	}
384
	p = buffer;
385
	for (i = 1; i < iport && strlen(p) != 0; i++)
386
	    p += lstrlen(p) + 1;
387
	/* prepend \\spool\ which is used by Ghostscript to distinguish */
388
	/* real files from queues */
389
	strcpy(portname, "\\\\spool\\");
390
	strcat(portname, p);
391
    } else {
392
	strcpy(portname, "\\\\spool\\");
393
	strcat(portname, queue);
394
    }
395
 
396
    free(buffer);
397
    return TRUE;
398
}
399
 
400
/* return TRUE if portname available */
401
/* return FALSE if cancelled or error */
402
/* if port non-NULL, use as suggested port */
403
BOOL
404
get_portname(char *portname, const char *port)
405
{
406
    char *buffer;
407
    char *p;
408
    int i, iport;
409
    char filename[MAXSTR];
410
 
411
    buffer = get_ports();
412
    if (buffer == NULL)
413
	return FALSE;
414
    if ((port == (char *)NULL) || (strlen(port) == 0)) {
415
	if (buffer == (char *)NULL)
416
	    return FALSE;
417
	/* select a port */
418
	iport = DialogBoxParam(phInstance, "SpoolDlgBox", (HWND) NULL, SpoolDlgProc, (LPARAM) buffer);
419
	if (!iport) {
420
	    free(buffer);
421
	    return FALSE;
422
	}
423
	p = buffer;
424
	for (i = 1; i < iport && strlen(p) != 0; i++)
425
	    p += lstrlen(p) + 1;
426
	strcpy(portname, p);
427
    } else
428
	strcpy(portname, port);
429
 
430
    if (strlen(portname) == 0)
431
	return FALSE;
432
    if (strcmp(portname, "FILE:") == 0) {
433
	OPENFILENAME ofn;
434
 
435
	filename[0] = '\0';
436
	memset(&ofn, 0, sizeof(OPENFILENAME));
437
	ofn.lStructSize = sizeof(OPENFILENAME);
438
	ofn.hwndOwner = (HWND) NULL;
439
	ofn.lpstrFile = filename;
440
	ofn.nMaxFile = sizeof(filename);
441
	ofn.Flags = OFN_PATHMUSTEXIST;
442
	if (!GetSaveFileName(&ofn)) {
443
	    free(buffer);
444
	    return FALSE;
445
	}
446
	strcpy(portname, filename);
447
    }
448
    free(buffer);
449
    return TRUE;
450
}
451
 
452
 
453
/* True Win32 method, using OpenPrinter, WritePrinter etc. */
454
private int
455
gp_printfile_win32(const char *filename, char *port)
456
{
457
    DWORD count;
458
    char *buffer;
459
    char portname[MAXSTR];
460
    FILE *f;
461
    HANDLE printer;
462
    DOC_INFO_1 di;
463
    DWORD written;
464
 
465
    if (!get_queuename(portname, port))
466
	return FALSE;
467
    port = portname + 8;	/* skip over \\spool\ */
468
 
469
    if ((buffer = malloc(PRINT_BUF_SIZE)) == (char *)NULL)
470
	return FALSE;
471
 
472
    if ((f = fopen(filename, "rb")) == (FILE *) NULL) {
473
	free(buffer);
474
	return FALSE;
475
    }
476
    /* open a printer */
477
    if (!OpenPrinter(port, &printer, NULL)) {
478
	char buf[256];
479
 
480
	sprintf(buf, "OpenPrinter() failed for \042%s\042, error code = %d", port, GetLastError());
481
	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
482
	free(buffer);
483
	return FALSE;
484
    }
485
    /* from here until ClosePrinter, should AbortPrinter on error */
486
 
487
    di.pDocName = szAppName;
488
    di.pOutputFile = NULL;
489
    di.pDatatype = "RAW";	/* for available types see EnumPrintProcessorDatatypes */
490
    if (!StartDocPrinter(printer, 1, (LPBYTE) & di)) {
491
	char buf[256];
492
 
493
	sprintf(buf, "StartDocPrinter() failed, error code = %d", GetLastError());
494
	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
495
	AbortPrinter(printer);
496
	free(buffer);
497
	return FALSE;
498
    }
499
    /* copy file to printer */
500
    while ((count = fread(buffer, 1, PRINT_BUF_SIZE, f)) != 0) {
501
	if (!WritePrinter(printer, (LPVOID) buffer, count, &written)) {
502
	    free(buffer);
503
	    fclose(f);
504
	    AbortPrinter(printer);
505
	    return FALSE;
506
	}
507
    }
508
    fclose(f);
509
    free(buffer);
510
 
511
    if (!EndDocPrinter(printer)) {
512
	char buf[256];
513
 
514
	sprintf(buf, "EndDocPrinter() failed, error code = %d", GetLastError());
515
	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
516
	AbortPrinter(printer);
517
	return FALSE;
518
    }
519
    if (!ClosePrinter(printer)) {
520
	char buf[256];
521
 
522
	sprintf(buf, "ClosePrinter() failed, error code = %d", GetLastError());
523
	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
524
	return FALSE;
525
    }
526
    return TRUE;
527
}
528
 
529
 
530
/* Start a 16-bit application gs16spl.exe to print a file */
531
/* Intended for Win32s where 16-bit spooler functions are not available */
532
/* and Win32 spooler functions are not implemented. */
533
int
534
gp_printfile_gs16spl(const char *filename, const char *port)
535
{
536
/* Get printer port list from win.ini */
537
    char portname[MAXSTR];
538
    HINSTANCE hinst;
539
    char command[MAXSTR];
540
    char *p;
541
    HWND hwndspl;
542
 
543
    if (!get_portname(portname, port))
544
	return FALSE;
545
 
546
    /* get path to EXE - same as DLL */
547
    GetModuleFileName(phInstance, command, sizeof(command));
548
    if ((p = strrchr(command, '\\')) != (char *)NULL)
549
	p++;
550
    else
551
	p = command;
552
    *p = '\0';
553
    sprintf(command + strlen(command), "gs16spl.exe %s %s",
554
	    portname, filename);
555
 
556
    hinst = (HINSTANCE) WinExec(command, SW_SHOWNORMAL);
557
    if (hinst < (HINSTANCE) HINSTANCE_ERROR) {
558
	char buf[MAXSTR];
559
 
560
	sprintf(buf, "Can't run: %s", command);
561
	MessageBox((HWND) NULL, buf, szAppName, MB_OK | MB_ICONSTOP);
562
	return FALSE;
563
    }
564
    hwndspl = FindWindow(NULL, "GS Win32s/Win16 spooler");
565
 
566
    while (IsWindow(hwndspl)) {
567
	gp_check_interrupts(NULL);
568
    }
569
 
570
    return 0;
571
}
572
 
573
 
574
/******************************************************************/
575
/* MS Windows has popen and pclose in stdio.h, but under different names.
576
 * Unfortunately MSVC5 and 6 have a broken implementation of _popen, 
577
 * so we use own.  Our implementation only supports mode "wb".
578
 */
579
FILE *mswin_popen(const char *cmd, const char *mode)
580
{
581
    SECURITY_ATTRIBUTES saAttr;
582
    STARTUPINFO siStartInfo;
583
    PROCESS_INFORMATION piProcInfo;
584
    HANDLE hPipeTemp = INVALID_HANDLE_VALUE;
585
    HANDLE hChildStdinRd = INVALID_HANDLE_VALUE;
586
    HANDLE hChildStdinWr = INVALID_HANDLE_VALUE;
587
    HANDLE hChildStdoutWr = INVALID_HANDLE_VALUE;
588
    HANDLE hChildStderrWr = INVALID_HANDLE_VALUE;
589
    HANDLE hProcess = GetCurrentProcess();
590
    int handle = 0;
591
    char *command = NULL;
592
    FILE *pipe = NULL;
593
 
594
    if (strcmp(mode, "wb") != 0)
595
	return NULL;
596
 
597
    /* Set the bInheritHandle flag so pipe handles are inherited. */
598
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
599
    saAttr.bInheritHandle = TRUE;
600
    saAttr.lpSecurityDescriptor = NULL;
601
 
602
    /* Create anonymous inheritable pipes for STDIN for child. 
603
     * First create a noninheritable duplicate handle of our end of 
604
     * the pipe, then close the inheritable handle.
605
     */
606
    if (handle == 0)
607
        if (!CreatePipe(&hChildStdinRd, &hPipeTemp, &saAttr, 0))
608
	    handle = -1;
609
    if (handle == 0) {
610
	if (!DuplicateHandle(hProcess, hPipeTemp, 
611
	    hProcess, &hChildStdinWr, 0, FALSE /* not inherited */,
612
	    DUPLICATE_SAME_ACCESS))
613
	    handle = -1;
614
        CloseHandle(hPipeTemp);
615
    }
616
    /* Create inheritable duplicate handles for our stdout/err */
617
    if (handle == 0)
618
	if (!DuplicateHandle(hProcess, GetStdHandle(STD_OUTPUT_HANDLE),
619
	    hProcess, &hChildStdoutWr, 0, TRUE /* inherited */,
620
	    DUPLICATE_SAME_ACCESS))
621
	    handle = -1;
622
    if (handle == 0)
623
        if (!DuplicateHandle(hProcess, GetStdHandle(STD_ERROR_HANDLE),
624
            hProcess, &hChildStderrWr, 0, TRUE /* inherited */, 
625
	    DUPLICATE_SAME_ACCESS))
626
	    handle = -1;
627
 
628
    /* Set up members of STARTUPINFO structure. */
629
    memset(&siStartInfo, 0, sizeof(STARTUPINFO));
630
    siStartInfo.cb = sizeof(STARTUPINFO);
631
    siStartInfo.dwFlags = STARTF_USESTDHANDLES;
632
    siStartInfo.hStdInput = hChildStdinRd;
633
    siStartInfo.hStdOutput = hChildStdoutWr;
634
    siStartInfo.hStdError = hChildStderrWr;
635
 
636
    if (handle == 0) {
637
	command = (char *)malloc(strlen(cmd)+1);
638
	if (command)
639
	    strcpy(command, cmd);
640
	else
641
	    handle = -1;
642
    }
643
 
644
    if (handle == 0)
645
	if (!CreateProcess(NULL,
646
	    command,  	   /* command line                       */
647
	    NULL,          /* process security attributes        */
648
	    NULL,          /* primary thread security attributes */
649
	    TRUE,          /* handles are inherited              */
650
	    0,             /* creation flags                     */
651
	    NULL,          /* environment                        */
652
	    NULL,          /* use parent's current directory     */
653
	    &siStartInfo,  /* STARTUPINFO pointer                */
654
	    &piProcInfo))  /* receives PROCESS_INFORMATION  */ 
655
	{
656
	    handle = -1;
657
	}
658
	else {
659
	    CloseHandle(piProcInfo.hProcess);
660
	    CloseHandle(piProcInfo.hThread);
661
	    handle = _open_osfhandle((long)hChildStdinWr, 0);
662
	}
663
 
664
    if (hChildStdinRd != INVALID_HANDLE_VALUE)
665
	CloseHandle(hChildStdinRd);	/* close our copy */
666
    if (hChildStdoutWr != INVALID_HANDLE_VALUE)
667
	CloseHandle(hChildStdoutWr);	/* close our copy */
668
    if (hChildStderrWr != INVALID_HANDLE_VALUE)
669
	CloseHandle(hChildStderrWr);	/* close our copy */
670
    if (command)
671
	free(command);
672
 
673
    if (handle < 0) {
674
	if (hChildStdinWr != INVALID_HANDLE_VALUE)
675
	    CloseHandle(hChildStdinWr);
676
    }
677
    else {
678
	pipe = _fdopen(handle, "wb");
679
	if (pipe == NULL)
680
	    _close(handle);
681
    }
682
    return pipe;
683
}
684
 
685
 
686
/* ------ File naming and accessing ------ */
687
 
688
/* Create and open a scratch file with a given name prefix. */
689
/* Write the actual file name at fname. */
690
FILE *
691
gp_open_scratch_file(const char *prefix, char *fname, const char *mode)
692
{
693
    UINT n;
694
    DWORD l;
695
    HANDLE hfile = INVALID_HANDLE_VALUE;
696
    int fd = -1;
697
    FILE *f = NULL;
698
    char sTempDir[_MAX_PATH];
699
    char sTempFileName[_MAX_PATH];
700
 
701
    memset(fname, 0, gp_file_name_sizeof);
702
    if (!gp_file_name_is_absolute(prefix, strlen(prefix))) {
703
	int plen = sizeof(sTempDir);
704
 
705
	if (gp_gettmpdir(sTempDir, &plen) != 0)
706
	    l = GetTempPath(sizeof(sTempDir), sTempDir);
707
	else
708
	    l = strlen(sTempDir);
709
    } else {
710
	strncpy(sTempDir, prefix, sizeof(sTempDir));
711
	prefix = "";
712
	l = strlen(sTempDir);
713
    }
714
    /* Fix the trailing terminator so GetTempFileName doesn't get confused */
715
    if (sTempDir[l-1] == '/')
716
	sTempDir[l-1] = '\\';		/* What Windoze prefers */
717
 
718
    if (l <= sizeof(sTempDir)) {
719
	n = GetTempFileName(sTempDir, prefix, 0, sTempFileName);
720
	if (n == 0) {
721
	    /* If 'prefix' is not a directory, it is a path prefix. */
722
	    int l = strlen(sTempDir), i;
723
 
724
	    for (i = l - 1; i > 0; i--) {
725
		uint slen = gs_file_name_check_separator(sTempDir + i, l, sTempDir + l);
726
 
727
		if (slen > 0) {
728
		    sTempDir[i] = 0;   
729
		    i += slen;
730
		    break;
731
		}
732
	    }
733
	    if (i > 0)
734
		n = GetTempFileName(sTempDir, sTempDir + i, 0, sTempFileName);
735
	}
736
	if (n != 0) {
737
	    hfile = CreateFile(sTempFileName, 
738
		GENERIC_READ | GENERIC_WRITE | DELETE,
739
		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
740
		FILE_ATTRIBUTE_NORMAL /* | FILE_FLAG_DELETE_ON_CLOSE */, 
741
		NULL);
742
	    /*
743
	     * Can't apply FILE_FLAG_DELETE_ON_CLOSE due to 
744
	     * the logics of clist_fclose. Also note that
745
	     * gdev_prn_render_pages requires multiple temporary files
746
	     * to exist simultaneousely, so that keeping all them opened
747
	     * may exceed available CRTL file handles.
748
	     */
749
	}
750
    }
751
    if (hfile != INVALID_HANDLE_VALUE) {
752
	/* Associate a C file handle with an OS file handle. */
753
	fd = _open_osfhandle((long)hfile, 0);
754
	if (fd == -1)
755
	    CloseHandle(hfile);
756
	else {
757
	    /* Associate a C file stream with C file handle. */
758
	    f = fdopen(fd, mode);
759
	    if (f == NULL)
760
		_close(fd);
761
	}
762
    }
763
    if (f != NULL) {
764
	if ((strlen(sTempFileName) < gp_file_name_sizeof))
765
	    strncpy(fname, sTempFileName, gp_file_name_sizeof - 1);
766
	else {
767
	    /* The file name is too long. */
768
	    fclose(f);
769
	    f = NULL;
770
	}
771
    }
772
    if (f == NULL)
773
	eprintf1("**** Could not open temporary file '%s'\n", fname);
774
    return f;
775
}
776
 
777
/* Open a file with the given name, as a stream of uninterpreted bytes. */
778
FILE *
779
gp_fopen(const char *fname, const char *mode)
780
{
781
    return fopen(fname, mode);
782
}
783
 
784
/* ------ Font enumeration ------ */
785
 
786
 /* This is used to query the native os for a list of font names and
787
  * corresponding paths. The general idea is to save the hassle of
788
  * building a custom fontmap file.
789
  */
790
 
791
void *gp_enumerate_fonts_init(gs_memory_t *mem)
792
{
793
    return NULL;
794
}
795
 
796
int gp_enumerate_fonts_next(void *enum_state, char **fontname, char **path)
797
{
798
    return 0;
799
}
800
 
801
void gp_enumerate_fonts_free(void *enum_state)
802
{
803
}