home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
WindowsWare 2 the Maxx
/
winmaxx.zip
/
winmaxx
/
WIN_NT
/
PSXRPC.ZIP
/
WIN32SRV.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-20
|
10KB
|
357 lines
/*
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);
}