home *** CD-ROM | disk | FTP | other *** search
- /*
- WIN32SRV Program
-
- (C) Copyright 1992 by
-
- John Richardson
- CompuServe 70541,672
- Internet jr@sni-usa.com
-
- This program may be used freely provided that this copyright is
- included in the source listings.
-
- Program to setup two pipes and pass them to a POSIX server
- process. The program then waits for requests from the POSIX
- server process and processes them making WIN32 calls.
- The results are passed back to the POSIX server process.
-
- This program allows a POSIX process to gain access to WIN32
- services that it normally can not. Examples would be the
- execution of a command such as the CL386 compiler, or
- sending communications requests to the WINSOCK API.
-
- Only requests that perform a system action or return an
- explicit value can be utilized. WIN32 requests that modify
- the state of the calling process (such as FileMapping() calls)
- do not have any effect upon the POSIX process.
-
- An explicit division of functionality of a UNIX program needs
- to be developed, in which the portions of the application
- that require WIN32 services will run in this server process,
- while portions that require the services of POSIX run in
- the POSIX process.
-
- The example given here is the implementation of the
- system() command that is calleable by the POSIX process.
-
- This could further be expanded to allow an X-Server running
- as a WIN32 process to process requests from an XLib that has
- been linked with a POSIX process.
-
- The Portion on creating a sub-process with re-directed Stdin
- and Stdout was taken from the Microsoft WIN32 programmers
- reference: Overviews, pages 67-71.
-
- The idea of passing Stdin and Stdout to a POSIX process to
- act as a communications channel is from Alistar Banks on the
- MSWIN32 developers conference on CompuServe.
- */
-
- #include <stdio.h>
- #include <windows.h>
- #include <io.h>
- #include <time.h>
- #include "win32psx.h"
-
-
- VOID ErrorExit(char *);
- VOID ServiceRequestLoop();
- VOID SendAckReply(int chan);
- VOID SendNackReply(int chan);
- int ReadStream(char *buf, int size);
- int WriteStream(char *buf, int size);
- int RunShellCmd(char *cmd_buf, int chan);
-
- HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
- hChildStdoutRd, hChildStdoutWr,
- hSaveStdin, hSaveStdout;
-
- main()
- {
- SECURITY_ATTRIBUTES pipe_attr;
- PROCESS_INFORMATION proc_info;
- static STARTUPINFO start_info = {
- sizeof(STARTUPINFO), /* cb */
- 0, 0, 0, /* LPSTR res,desk,title */
- 0, 0, /* X, Y */
- 80, 25, /* Xsize, Ysize */
- 80, 25,
- 0, /* Fill attribute */
- 0, /* dwFlags
- 0, /* dont show window */
- 0, /* reserved */
- 0 /* reserved */
- };
-
- /* Set the SECURITY_ATTRIBUTES so the pipe handles are inherited */
- pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
- pipe_attr.bInheritHandle = TRUE;
- pipe_attr.lpSecurityDescriptor = NULL;
-
- /* Save the Stdout Handle */
- DuplicateHandle(GetCurrentProcess(),
- GetStdHandle(STD_OUTPUT_HANDLE),
- GetCurrentProcess(), &hSaveStdout, 0,
- FALSE, /* Not inherited */
- DUPLICATE_SAME_ACCESS);
-
- if(!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &pipe_attr, 0))
- ErrorExit("Stdout pipe creation failed\n");
-
- if(!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr))
- ErrorExit("Redirecting Stdout Failed\n");
-
- DuplicateHandle(GetCurrentProcess(),
- GetStdHandle(STD_INPUT_HANDLE),
- GetCurrentProcess(), &hSaveStdin, 0,
- FALSE, /* Not inherited */
- DUPLICATE_SAME_ACCESS);
-
- if(!CreatePipe(&hChildStdinRd, &hChildStdinWr, &pipe_attr, 0))
- ErrorExit("Stdin pipe creation failed\n");
-
- if(!SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd))
- ErrorExit("Redirecting Stdin failed\n");
-
- DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
- GetCurrentProcess(), &hChildStdinWrDup, 0,
- FALSE, /* Not inherited */
- DUPLICATE_SAME_ACCESS);
-
- CloseHandle(hChildStdinWr);
-
- /* Now Create the Child Process */
-
- if (!CreateProcess(NULL,
- "psxagent.exe", /* name of POSIX server process */
- 0, /* no processes security attributes */
- 0, /* no thread security attributes */
- 1, /* inherit handles */
- 0, /* creation flags (inherit console, no detach */
- 0, /* inherit current environment block */
- 0, /* no new current directory */
- &start_info, /* Startup info */
- &proc_info) /* Process information */
- )
- ErrorExit("Create Process Failed\n");
-
- /* restore the Parents Stdin/Stdout Handles */
- if(!SetStdHandle(STD_INPUT_HANDLE, hSaveStdin))
- ErrorExit("Re-redirecting Stdin Failed\n");
-
- if(!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout))
- ErrorExit("Re-redirecting Stdout Failed\n");
-
- /*
- Close our version of childs write end of the pipe so that
- the childs close will be the last close of pipe. This is so that
- we will get the EOF properly when the child exits.
- */
- if(!CloseHandle(hChildStdoutWr))
- ErrorExit("Can't close pipe write end\n");
-
- /* parent process */
-
- ServiceRequestLoop();
-
- /* Close my pipe handles to tell the child that we are done */
- CloseHandle(hChildStdinWrDup);
- CloseHandle(hChildStdoutWr);
-
- /* Wait for the process */
- if(WaitForSingleObject(proc_info.hProcess, (unsigned int)-1) != 0)
- {
- printf("Error waiting for NT process %d\n",GetLastError());
- CloseHandle(proc_info.hThread);
- CloseHandle(proc_info.hProcess);
- return(1);
- }
-
- /* Close my child process handles */
- CloseHandle(proc_info.hThread);
- CloseHandle(proc_info.hProcess);
-
- return(1);
-
- }
-
- /*
- Service Requests from the POSIX program
-
- This can be expanded as required.
-
- The new client side requests can be added to rpcclt.c, while the server
- side is added here. Record the new RPC's in win32psx.h.
- */
-
- void ServiceRequestLoop()
- {
- struct Request_Header Hd;
- int numxfer;
- char buf[512];
-
- for(;;)
- {
- /* Get a request */
- numxfer = ReadStream((char *)&Hd, sizeof(struct Request_Header));
- if(Hd.rh_type == RPC_REQUEST)
- {
- switch(Hd.rh_request) {
-
- case RPC_NOOP:
- #ifdef DEBUG
- printf("WIN32: got RPC_NOOP request\n");
- #endif
- SendAckReply(Hd.rh_chan);
- break;
-
- case RPC_RUN_SHELL_CMD_SYNC:
- #ifdef DEBUG
- printf("WIN32: got RPC_RUN_SHELL_CMD_SYNC request :%s:\n",buf);
- #endif
- ReadStream(buf, Hd.rh_size);
- RunShellCmd(buf, Hd.rh_chan);
- #ifdef DEBUG
- printf("WIN32: Done running RPC_RUN_SHELL_CMD_SYNC\n");
- #endif
- break;
-
- default:
- SendNackReply(Hd.rh_chan);
- break;
- }
- }
- }
- }
-
- void SendAckReply(int chan)
- {
- struct Request_Header Hd;
-
- Hd.rh_type = RPC_REPLY;
- Hd.rh_hdrsize = sizeof(struct Request_Header);
- Hd.rh_size = 0;
- Hd.rh_chan = chan;
- Hd.rh_request = TRUE; /* Request is the RPC return code as well */
- WriteStream((char *)&Hd, sizeof(struct Request_Header));
- }
-
- void SendNackReply(int chan)
- {
- struct Request_Header Hd;
-
- Hd.rh_type = RPC_REPLY;
- Hd.rh_hdrsize = sizeof(struct Request_Header);
- Hd.rh_size = 0;
- Hd.rh_chan = chan;
- Hd.rh_request = FALSE; /* Request is the RPC return code as well */
- WriteStream((char *)&Hd, sizeof(struct Request_Header));
- }
-
- int RunShellCmd(char *cmd, int chan)
- {
- int exitstatus;
- struct Request_Header Hd;
- PROCESS_INFORMATION proc_info;
- static STARTUPINFO start_info = {
- sizeof(STARTUPINFO), /* cb */
- 0, 0, 0, /* LPSTR res,desk,title */
- 0, 0, /* X, Y */
- 80, 25, /* Xsize, Ysize */
- 80, 25,
- 0, /* Fill attribute */
- 0, /* dwFlags
- 0, /* dont show window */
- 0, /* reserved */
- 0 /* reserved */
- };
- /* Now Create the Child Process */
- if (!CreateProcess(NULL,
- cmd, /* command string from POSIX client process */
- 0, /* no processes security attributes */
- 0, /* no thread security attributes */
- 1, /* inherit handles */
- 0, /* creation flags (inherit console, no detach */
- 0, /* inherit current environment block */
- 0, /* no new current directory */
- &start_info, /* Startup info */
- &proc_info) /* Process information */
- )
- {
- SendNackReply(chan); /* Could not run the command */
- return(1);
- }
-
- /* Wait for the process */
- if(WaitForSingleObject(proc_info.hProcess, (unsigned int)-1) != 0)
- {
- printf("Error waiting for NT process %d\n",GetLastError());
- CloseHandle(proc_info.hThread);
- CloseHandle(proc_info.hProcess);
- SendNackReply(chan);
- return(1);
- }
-
- if(!GetExitCodeProcess(proc_info.hProcess, &exitstatus))
- {
- printf("Error %d getting exit status from NT process\n",GetLastError());
- SendNackReply(chan);
- return(1);
- }
-
- /* Close my child process handles */
- CloseHandle(proc_info.hThread);
- CloseHandle(proc_info.hProcess);
-
- Hd.rh_type = RPC_REPLY;
- Hd.rh_hdrsize = sizeof(struct Request_Header);
- Hd.rh_size = 4; /* Integer exit status from process */
- Hd.rh_chan = chan;
- Hd.rh_request = TRUE; /* Request is the RPC return code as well */
- WriteStream((char *)&Hd, sizeof(struct Request_Header));
- WriteStream((char *)&exitstatus, sizeof(int));
- return(0);
- }
-
- /*
- read data from the communications stream
- */
- int ReadStream(char *buf, int size)
- {
- int numxfer, error;
-
- if(!ReadFile(hChildStdoutRd, buf, size, &numxfer, 0))
- {
- error = GetLastError();
- if(error == ERROR_BROKEN_PIPE) /* Child exited */
- ExitProcess(1); /* Success */
- else
- {
- fprintf(stderr, "WIN32: Error reading Child Stdout, %d\n", GetLastError());
- ExitProcess(0);
- }
- }
- return(numxfer);
- }
-
- /*
- write data to the communications stream
- */
- int WriteStream(char *buf, int size)
- {
- int numxfer;
-
- if(!WriteFile(hChildStdinWrDup, buf, size, &numxfer, 0))
- {
- fprintf(stderr, "WIN32: Error writing Child Stdin, %d\n", GetLastError());
- ExitProcess(0);
- }
- return(numxfer);
- }
-
- VOID ErrorExit(char *message)
- {
- fprintf(stderr, message);
- ExitProcess(0);
- }
-