/******************* pipedriver.c: Sample program using SwiftView "pipe" data file input. Stdin and anonymous pipes are supported, on unix or windows. This code may be freely used/adapted without copyright restriction. *******************/ #include /* Comment this line out for unix build: */ #define OS_WIN #ifdef OS_WIN #include #endif #define BUFLEN 5031 unsigned char buffer[BUFLEN]; #ifdef OS_WIN /**************************************************************** * FUNCTION: Get the specified (non-default) string value from the registry. * * RETURNS: NULL on failure or value does not exist (error message printed * except for does not exist). Buf is empty if * the value does not exist. Else pointer to string. * Return value is buf. ****************************************************************/ char *GetRegStringVal(HKEY section, /* e.g. HKEY_LOCAL_MACHINE */ char *keyname, /* subkey */ char *valname, /* value name */ char *buf, /* buffer to fill */ int size) /* size of buf */ { int ret; HKEY hKey; int bufsz = size; if (!buf) return NULL; /* Return empty on any error/non-existence */ *buf = '\0'; if ((ret = RegOpenKeyEx(section, keyname, 0, KEY_QUERY_VALUE, &hKey)) != ERROR_SUCCESS) { return NULL; } ret = RegQueryValueEx(hKey, valname, NULL, NULL, (LPBYTE)buf, (LPDWORD)&size); RegCloseKey(hKey); if (ret == ERROR_SUCCESS) return buf; return NULL; } /**************************************************************** * FUNCTION: Get the local default SwiftView program directory. * Do not use App Paths - we want to avoid networked drives * for our temporary dir. * * RETURNS: pointer to static buffer with path, always succeeds. ****************************************************************/ char *u_getDefaultSviewDir(void) { static char buf[MAX_PATH+1] = { '\0' }; if (buf[0]) return buf; // Place in the official Program Files directory. if (GetRegStringVal(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", "ProgramFilesDir", buf, MAX_PATH+1)) #define DEFAULT_SVIEWDIR "C:\\Program Files\\SwiftView" #define DEFAULT_SVIEWLOC "\\SwiftView" strcat(buf, DEFAULT_SVIEWLOC); else /* Desparate hardcoded default path */ strcpy(buf, DEFAULT_SVIEWDIR); return buf; } /**************************************************************** * FUNCTION: Get the SwiftView program directory from the registry. * Use App Paths if it exists (post-install), else * return the standard install location. * * RETURNS: pointer to static buffer with path, always succeeds. ****************************************************************/ char *u_getSviewDir(void) { static char buf[MAX_PATH+1] = { '\0' }; if (buf[0]) return buf; #define SWIFTVIEW_HKEY \ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\sview.exe" /* We only write one Path element */ if (GetRegStringVal(HKEY_LOCAL_MACHINE, SWIFTVIEW_HKEY, "Path", buf, MAX_PATH+1)) return buf; // Not installed, put in the official Program Files directory. return u_getDefaultSviewDir(); } #endif /* OS_WIN */ /* OK, now for the "main event": */ main(argc, argv) int argc; char **argv; { int rtn; FILE *in; int i, ret; #ifdef OS_WIN HANDLE SviewRead; HANDLE hPWrite = NULL; /* Pipe write handle */ HANDLE hPWriteDup; SECURITY_ATTRIBUTES sa; STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInfo; #define ARGBUFLEN 80 char argbuf[ARGBUFLEN]; char buf1[MAX_PATH+ARGBUFLEN+1]; char buf[MAX_PATH+ARGBUFLEN+1]; DWORD dwBytesWritten; #else FILE *out; #endif if (argc < 3) { #ifdef OS_WIN fprintf(stderr, "Usage: %s icscmds infiles...\n", argv[0]); #define INFILEARG 2 #else fprintf(stderr, "Usage: %s icscmds outfile infiles...\n", argv[0]); #define OUTFILEARG 2 #define INFILEARG 3 #endif /* OS_WIN */ exit(1); } #ifdef OS_WIN /* Initialize security attributes structure to allow handles to be inherited by child process */ sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; /* The only other field, unused */ CreatePipe(&SviewRead, &hPWrite, &sa, 0); /* Test default system-assigned buffer size */ if (!hPWrite) { fprintf(stderr, "Could not create a pipe to sview"); exit(1); } // MSDN sez you MUST not allow your end of the pipe to be inherited. // Why? Apparently, the reader won't detect a Close otherwise, and will hang. // Create noninheritable read handle and close the inheritable read // handle. if (!DuplicateHandle(GetCurrentProcess(), hPWrite, GetCurrentProcess(), &hPWriteDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) { fprintf(stderr, "Could not duplicate our end of pipe to sview"); exit(1); } CloseHandle(hPWrite); hPWrite = hPWriteDup; memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); StartupInfo.wShowWindow = SW_HIDE; StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; /* Using GetStdHandle in sview conflicted with its use in the XES 8830 print driver (and HP 970, etc). In case this is a problem, we use the pipe://handle method. */ /* #define USESTDIN */ #ifdef USESTDIN StartupInfo.hStdInput = SviewRead; #else StartupInfo.hStdInput = NULL; #endif StartupInfo.hStdOutput = NULL; #ifdef USESTDIN sprintf(argbuf, " -v1 -uAWRPH -lsdonotuse -c\"ldoc pipe://-|%s\"", argv[1]); #else sprintf(argbuf, " -v1 -uAWRPH -lsdonotuse -c\"ldoc pipe://%d|%s\"", (int)SviewRead, argv[1]); #endif strcpy(buf1, ".\\sview.exe"); strcat(buf1, argbuf); /* OEM dll customers that install a licensed sview.exe must get it from current directory e.g. for CD installation, else they will collide with the standard, unlicensed installation. */ if (!CreateProcess(NULL, buf1, NULL, NULL, TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)) { /* If SwiftView program directory is registered, try it, else use $PATH. */ buf1[0] = '\0'; if (u_getSviewDir()) { /* Stupid windows - must quote a full argv[0] path that contains spaces or it gets passed wrong to sview and the copyright notice pops up. */ strcpy(buf1, "\""); strcat(buf1, u_getSviewDir()); strcat(buf1, "\\sview.exe\""); strcat(buf1, argbuf); } /* One, maybe two customers had this CreateProcess fail on win95 (not NT) when the process file arg was sviewpath. */ if (!buf1[0] || !CreateProcess(NULL, buf1, NULL, NULL, TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)) { /* non-plugin only gets sview.exe from $PATH */ strcpy(buf, "sview.exe"); strcat(buf, argbuf); if (!CreateProcess(NULL, buf, NULL, NULL, TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)) { char *path = getenv("PATH"); /* Don't display args */ *(strchr(buf, ' ')) = '\0'; if (buf1[0]) { *(strchr(buf1+strlen(u_getSviewDir()), ' ')) = '\0'; fprintf(stderr, /*TRANSLATE*/"Could not start %s, or %s from $PATH=%s", buf1, buf, path); } else fprintf(stderr, /*TRANSLATE*/"Could not start %s from $PATH=%s", buf, path); goto CLEANUP; } } } #else /* unix */ out = fopen(argv[OUTFILEARG], "w+b"); if (!out) { fprintf(stderr, "can't open %s\n", argv[OUTFILEARG]); goto CLEANUP; } #endif /* OS_WIN */ i = INFILEARG; while (i < argc) { if (!(in = fopen(argv[i], "rb"))) { fprintf(stderr, "can't open %s\n", argv[i]); goto CLEANUP; } while ((rtn = fread(buffer, 1, BUFLEN, in)) > 0) { #ifdef OS_WIN if (!WriteFile(hPWrite, buffer, rtn, &dwBytesWritten, NULL) || (dwBytesWritten < (DWORD)rtn)) #else if (fwrite(buffer, 1, rtn, out) != rtn) #endif { #ifdef OS_WIN fprintf(stderr, "can't write pipe\n"); #else fprintf(stderr, "can't write %s\n", argv[i]); #endif goto CLEANUP; } } fclose(in); i++; } ret = 0; goto OK; CLEANUP: ret = 1; OK: #ifdef OS_WIN CloseHandle(SviewRead); CloseHandle(hPWrite); #else if (out) fclose(out); #endif exit (ret); }