Back to index

radiance  4R0+20100331
Defines | Functions | Variables
win_process.c File Reference
#include "copyright.h"
#include <stdio.h>
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include "rterror.h"
#include "rtio.h"
#include "rtprocess.h"

Go to the source code of this file.

Defines

#define STRICT

Functions

int win_nice (int inc)
BOOL SafeTerminateProcess (HANDLE hProcess, UINT uExitCode)
static int start_process (SUBPROC *proc, char *cmdstr)
static int wordncopy (char *dest, char *src, int dlen, int insert_space, int force_dq)
static char * quoted_cmdline (char *cmdpath, char *sl[])
int open_process (SUBPROC *proc, char *av[])
int win_kill (RT_PID pid, int sig)
int close_process (SUBPROC *proc)

Variables

static char RCSid [] = "$Id: win_process.c,v 3.6 2005/09/19 11:30:10 schorsch Exp $"

Define Documentation

#define STRICT

Definition at line 14 of file win_process.c.


Function Documentation

int close_process ( SUBPROC proc)

Definition at line 317 of file win_process.c.

                             {
       int icres, ocres;
       DWORD pid;

       ocres = close(proc->w);
       icres = close(proc->r);
       pid = proc->pid;
       if(ocres != 0 || icres != 0) {
              /* something went wrong: enforce infanticide */
              /* other than that, it looks like we want to ignore errors here */
              if (proc->running) {
                     win_kill(pid, 0);
              }
       }
       proc->running = 0;
       return 0; /* XXX we need to figure out more here... */
}

Here is the call graph for this function:

Here is the caller graph for this function:

int open_process ( SUBPROC proc,
char *  av[] 
)

Definition at line 277 of file win_process.c.

{
       char *cmdpath;
       char *cmdstr;

       proc->running = 0;
       cmdpath = getpath(av[0], getenv("PATH"), X_OK);
       cmdstr = quoted_cmdline(cmdpath, av+1);
       if (cmdstr == NULL) { return 0; }
       return start_process(proc, cmdstr);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* quoted_cmdline ( char *  cmdpath,
char *  sl[] 
) [static]

Definition at line 241 of file win_process.c.

{
       static char *cmdstr;
       static int clen;
       char *newcs;
       int newlen, pos, res, i;

       newlen = strlen(cmdpath) + 3; /* allow two quotes plus the final \0 */
       for (i = 0; sl[i] != NULL; i++) {
              newlen += strlen(sl[i]) + 3; /* allow two quotes and a space */
       }
       if (cmdstr == NULL) {
              cmdstr = (char *) malloc(newlen);
              if (cmdstr == NULL) return NULL;
       } else if (newlen > clen) {
              newcs = (char *) realloc(cmdstr, newlen);
              if (newcs == NULL) return NULL;
              cmdstr = newcs;
       }
       clen = newlen;
       pos = wordncopy(cmdstr, cmdpath, clen, 0, 1);
       if (pos < 0) return NULL;
       for (i = 0; sl[i] != NULL; i++) {
              res = wordncopy(cmdstr + pos, sl[i], clen - pos, 1, 1);
              if (res < 0) return NULL;
              pos += res;
       }
       return cmdstr;
}

Here is the call graph for this function:

Here is the caller graph for this function:

BOOL SafeTerminateProcess ( HANDLE  hProcess,
UINT  uExitCode 
)

Definition at line 42 of file win_process.c.

{
       DWORD dwTID, dwCode, dwErr = 0;
       HANDLE hProcessDup = INVALID_HANDLE_VALUE;
       HANDLE hRT = NULL;
       HINSTANCE hKernel = GetModuleHandle("Kernel32");
       BOOL bSuccess = FALSE;

       BOOL bDup = DuplicateHandle(GetCurrentProcess(), 
                     hProcess, 
                     GetCurrentProcess(), 
                     &hProcessDup, 
                     PROCESS_ALL_ACCESS, 
                     FALSE, 
                     0);
       /* Detect the special case where the process is already dead... */
       if ( GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) && 
                     (dwCode == STILL_ACTIVE) ) {
              FARPROC pfnExitProc;
              pfnExitProc = GetProcAddress(hKernel, "ExitProcess");
              hRT = CreateRemoteThread((bDup) ? hProcessDup : hProcess, 
                            NULL, 
                            0, 
                            (LPTHREAD_START_ROUTINE)pfnExitProc,
                            (PVOID)uExitCode, 0, &dwTID);
              if ( hRT == NULL ) dwErr = GetLastError();
       } else {
              dwErr = ERROR_PROCESS_ABORTED;
       }
       if ( hRT ) {
              /* Must wait process to terminate to guarantee that it has exited... */
              WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE);
              CloseHandle(hRT);
              bSuccess = TRUE;
       }
       if ( bDup ) CloseHandle(hProcessDup);
       if ( !bSuccess ) SetLastError(dwErr);
       return bSuccess;
}

Here is the caller graph for this function:

static int start_process ( SUBPROC proc,
char *  cmdstr 
) [static]

Definition at line 85 of file win_process.c.

{
       BOOL res;
       int Pflags = 0;
       SECURITY_ATTRIBUTES SAttrs;
       STARTUPINFO SInfo;
       PROCESS_INFORMATION PInfo;
       /* welcome to the world of resource handles */
       HANDLE hToChildRead = NULL;
       HANDLE hToChildWrite = NULL;
       HANDLE hFromChildRead = NULL;
       HANDLE hFromChildWrite = NULL;
       HANDLE hRead = NULL, hWrite = NULL;
       HANDLE hStdIn, hStdOut, hStdErr;
       HANDLE hCurProc;

       /* get process and standard stream handles */
       hCurProc = GetCurrentProcess();
       hStdIn = GetStdHandle(STD_INPUT_HANDLE);
       hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
       hStdErr = GetStdHandle(STD_ERROR_HANDLE);
       
       /* the remote pipe handles must be inheritable */
       SAttrs.bInheritHandle = 1;
       SAttrs.lpSecurityDescriptor = NULL;
       SAttrs.nLength = sizeof(SECURITY_ATTRIBUTES);

       /* make pipe, assign to stdout */
       /* we'll check for errors after CreateProcess()...*/
       res = CreatePipe(&hFromChildRead, &hFromChildWrite, &SAttrs, 0);
       res = SetStdHandle(STD_OUTPUT_HANDLE, hFromChildWrite);
       /* create non-inheritable dup of local end */
       res = DuplicateHandle(hCurProc, hFromChildRead, hCurProc, &hRead,
                     0, FALSE, DUPLICATE_SAME_ACCESS);
       CloseHandle(hFromChildRead); hFromChildRead = NULL;

       res = CreatePipe(&hToChildRead, &hToChildWrite, &SAttrs, 0);
       res = SetStdHandle(STD_INPUT_HANDLE, hToChildRead);
       res = DuplicateHandle(hCurProc, hToChildWrite, hCurProc, &hWrite,
                     0, FALSE, DUPLICATE_SAME_ACCESS);
       CloseHandle(hToChildWrite); hToChildWrite = NULL;

       CloseHandle(hCurProc); hCurProc = NULL;

       /* do some bookkeeping for Windows... */
       SInfo.cb = sizeof(STARTUPINFO);
       SInfo.lpReserved = NULL;
       SInfo.lpDesktop = NULL;
       SInfo.lpTitle = NULL;
       SInfo.cbReserved2 = 0;
       SInfo.lpReserved2 = NULL;
       /* don't open a console automatically, pass handles */
       SInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
       SInfo.wShowWindow = SW_HIDE;
       SInfo.hStdInput = hToChildRead;
       SInfo.hStdOutput = hFromChildWrite;
       SInfo.hStdError = hStdErr; /* reuse original stderr */
       
       res = CreateProcess(NULL, /* command name */
              cmdstr, /* full command line */
              NULL,    /* default process attributes */
              NULL,    /* default security attributes */
              1,       /* inherit handles (pass doesn't work reliably) */
              Pflags,  /* process flags */
              NULL,    /* no new environment */
              NULL,    /* stay in current directory */
              &SInfo,
              &PInfo
              );
       /* reset stdin/stdout in any case */
       SetStdHandle(STD_OUTPUT_HANDLE, hStdOut);
       SetStdHandle(STD_INPUT_HANDLE, hStdIn);
       /* Oops... */
       if(res == 0) {
              char es[128];
              _snprintf(es, sizeof(es),
                            "Error creating process (%d)\n", GetLastError());
              eputs(es);
              goto error;
       }
       /* close stuff we don't need */
       CloseHandle(PInfo.hThread);
       CloseHandle(hFromChildWrite); hFromChildWrite = NULL;
       CloseHandle(hToChildRead); hToChildRead = NULL;
       /* get the file descriptors */
       proc->r = _open_osfhandle((long)hRead, _O_RDONLY);
       proc->w = _open_osfhandle((long)hWrite, _O_APPEND);
       proc->pid = PInfo.dwProcessId;
       proc->running = 1;
       CloseHandle(hCurProc);
       /* Windows doesn't tell us the actual buffer size */
       return PIPE_BUF;

error: /* cleanup */
       if(PInfo.hThread) CloseHandle(PInfo.hThread);
       if(hToChildRead) CloseHandle(hToChildRead);
       if(hToChildWrite) CloseHandle(hToChildWrite);
       if(hFromChildRead) CloseHandle(hFromChildRead);
       if(hFromChildWrite) CloseHandle(hFromChildWrite);
       if(hRead) CloseHandle(hRead);
       if(hWrite) CloseHandle(hWrite);
       if(hCurProc) CloseHandle(hCurProc);
       proc->running = 0;
       return 0;
       /* There... Are we happy now? */
}

Here is the call graph for this function:

Here is the caller graph for this function:

int win_kill ( RT_PID  pid,
int  sig 
)

Definition at line 290 of file win_process.c.

{
       HANDLE hProc;

       hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid);
       /*  it looks like we want to ignore errors here */
       if(hProc != NULL) {
#ifdef OBSOLETE_WINDOWS
#define KILL_TIMEOUT 10 * 1000 /* milliseconds */
              /* it might have some windows open... */
              EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM)pid);
              if(WaitForSingleObject(hProc, KILL_TIMEOUT)!=WAIT_OBJECT_0) {
                     /* No way to avoid dangling DLLs here. */
                     TerminateProcess(hProc, 0);
              }
#else
              SafeTerminateProcess(hProc, 0);
#endif
              /* WaitForSingleObject(hProc, 0); */
              /* not much use to wait on Windows */
              CloseHandle(hProc);
       }
       return 0; /* XXX we need to figure out more here... */
}

Here is the call graph for this function:

Here is the caller graph for this function:

int win_nice ( int  inc)

Definition at line 25 of file win_process.c.

{
       /* We don't have much granularity available: IDLE_PRIORITY_CLASS
          will run whenever no other higher priority process is running */
       if (inc > 0) {
              return (int)!SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
       }
       return 0;
}
static int wordncopy ( char *  dest,
char *  src,
int  dlen,
int  insert_space,
int  force_dq 
) [static]

Definition at line 194 of file win_process.c.

{
       int slen;
       int pos = 0;

       slen = strlen(src);
       if (insert_space) {
              if (1 >= dlen) return -1;
              dest[pos++] = ' ';
       }
       if (strpbrk(src, " \f\n\r\t\v")) {
              if (force_dq && src[0] == '\'' && src[slen-1] == '\'') {
                     if (slen + pos + 1 > dlen) return -1;
                     dest[pos++] = '"';
                     strncpy(dest + pos, src + 1, slen -2);
                     pos += slen - 2;
                     dest[pos++] = '"';
              } else if (src[0] == '"' && src[slen-1] == '"') {
                     if (slen + pos + 1 > dlen) return -1;
                     strncpy(dest + pos, src, slen);
                     pos += slen;
              } else {
                     if (slen + pos + 3 > dlen) return -1;
                     dest[pos++] = '"';
                     strncpy(dest + pos, src, slen);
                     pos += slen;
                     dest[pos++] = '"';
              }
       } else {
              if (slen + pos + 1 > dlen) return -1;
              strncpy(dest + pos, src, slen);
              pos += slen;
       }
       dest[pos] = '\0';
       return pos;
}      

Here is the caller graph for this function:


Variable Documentation

char RCSid[] = "$Id: win_process.c,v 3.6 2005/09/19 11:30:10 schorsch Exp $" [static]

Definition at line 2 of file win_process.c.