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

  1. /*
  2.   WIN32SRV Program
  3.  
  4.   (C) Copyright 1992 by
  5.  
  6.       John Richardson
  7.       CompuServe 70541,672
  8.       Internet jr@sni-usa.com
  9.  
  10.       This program may be used freely provided that this copyright is
  11.       included in the source listings.
  12.  
  13.         Program to setup two pipes and pass them to a POSIX server
  14.         process. The program then waits for requests from the POSIX
  15.         server process and processes them making WIN32 calls.
  16.         The results are passed back to the POSIX server process.
  17.  
  18.         This program allows a POSIX process to gain access to WIN32
  19.         services that it normally can not. Examples would be the
  20.         execution of a command such as the CL386 compiler, or
  21.         sending communications requests to the WINSOCK API.
  22.  
  23.         Only requests that perform a system action or return an
  24.         explicit value can be utilized. WIN32 requests that modify
  25.         the state of the calling process (such as FileMapping() calls)
  26.         do not have any effect upon the POSIX process.
  27.  
  28.         An explicit division of functionality of a UNIX program needs
  29.         to be developed, in which the portions of the application
  30.         that require WIN32 services will run in this server process,
  31.         while portions that require the services of POSIX run in
  32.         the POSIX process.
  33.  
  34.         The example given here is the implementation of the
  35.         system() command that is calleable by the POSIX process.
  36.  
  37.         This could further be expanded to allow an X-Server running
  38.         as a WIN32 process to process requests from an XLib that has
  39.         been linked with a POSIX process.
  40.  
  41.         The Portion on creating a sub-process with re-directed Stdin
  42.         and Stdout was taken from the Microsoft WIN32 programmers
  43.         reference: Overviews, pages 67-71.
  44.  
  45.         The idea of passing Stdin and Stdout to a POSIX process to
  46.         act as a communications channel is from Alistar Banks on the
  47.         MSWIN32 developers conference on CompuServe.
  48. */
  49.  
  50. #include <stdio.h>
  51. #include <windows.h>
  52. #include <io.h>
  53. #include <time.h>
  54. #include "win32psx.h"
  55.  
  56.  
  57. VOID ErrorExit(char *);
  58. VOID ServiceRequestLoop();
  59. VOID SendAckReply(int chan);
  60. VOID SendNackReply(int chan);
  61. int  ReadStream(char *buf, int size);
  62. int  WriteStream(char *buf, int size);
  63. int  RunShellCmd(char *cmd_buf, int chan);
  64.  
  65. HANDLE    hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
  66.     hChildStdoutRd, hChildStdoutWr,
  67.     hSaveStdin, hSaveStdout;
  68.  
  69. main()
  70. {
  71.     SECURITY_ATTRIBUTES pipe_attr;
  72.     PROCESS_INFORMATION proc_info;
  73.     static STARTUPINFO start_info = {
  74.                        sizeof(STARTUPINFO), /* cb */
  75.                        0, 0, 0, /* LPSTR res,desk,title */
  76.                        0, 0, /* X, Y */
  77.                        80, 25, /* Xsize, Ysize */
  78.                        80, 25,
  79.                        0, /* Fill attribute */
  80.                        0, /* dwFlags
  81.                        0, /* dont show window */
  82.                        0, /* reserved */
  83.                        0 /* reserved */
  84.                     };
  85.  
  86.     /* Set the SECURITY_ATTRIBUTES so the pipe handles are inherited */
  87.     pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
  88.     pipe_attr.bInheritHandle = TRUE;
  89.     pipe_attr.lpSecurityDescriptor = NULL;
  90.  
  91.     /* Save the Stdout Handle */
  92.     DuplicateHandle(GetCurrentProcess(),
  93.         GetStdHandle(STD_OUTPUT_HANDLE),
  94.         GetCurrentProcess(), &hSaveStdout, 0,
  95.         FALSE,        /* Not inherited */
  96.         DUPLICATE_SAME_ACCESS);
  97.  
  98.         if(!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &pipe_attr, 0))
  99.         ErrorExit("Stdout pipe creation failed\n");
  100.  
  101.     if(!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr))
  102.         ErrorExit("Redirecting Stdout Failed\n");
  103.  
  104.     DuplicateHandle(GetCurrentProcess(),
  105.         GetStdHandle(STD_INPUT_HANDLE),
  106.         GetCurrentProcess(), &hSaveStdin, 0,
  107.         FALSE,        /* Not inherited */
  108.         DUPLICATE_SAME_ACCESS);
  109.  
  110.         if(!CreatePipe(&hChildStdinRd, &hChildStdinWr, &pipe_attr, 0))
  111.         ErrorExit("Stdin pipe creation failed\n");
  112.  
  113.     if(!SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd))
  114.         ErrorExit("Redirecting Stdin failed\n");
  115.  
  116.     DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
  117.         GetCurrentProcess(), &hChildStdinWrDup, 0,
  118.         FALSE,        /* Not inherited */
  119.         DUPLICATE_SAME_ACCESS);
  120.  
  121.     CloseHandle(hChildStdinWr);
  122.  
  123.     /* Now Create the Child Process */
  124.  
  125.     if (!CreateProcess(NULL,
  126.          "psxagent.exe", /* name of POSIX server process */
  127.          0, /* no processes security attributes */
  128.          0, /* no thread security attributes */
  129.          1, /* inherit handles */
  130.          0, /* creation flags (inherit console, no detach */
  131.          0, /* inherit current environment block */
  132.          0, /* no new current directory */
  133.          &start_info, /* Startup info */
  134.          &proc_info) /* Process information */
  135.         )
  136.         ErrorExit("Create Process Failed\n");
  137.  
  138.     /* restore the Parents Stdin/Stdout Handles */
  139.     if(!SetStdHandle(STD_INPUT_HANDLE, hSaveStdin))
  140.         ErrorExit("Re-redirecting Stdin Failed\n");
  141.  
  142.     if(!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout))
  143.         ErrorExit("Re-redirecting Stdout Failed\n");
  144.  
  145.     /* 
  146.            Close our version of childs write end of the pipe so that
  147.            the childs close will be the last close of pipe. This is so that
  148.            we will get the EOF properly when the child exits.
  149.         */
  150.         if(!CloseHandle(hChildStdoutWr))
  151.               ErrorExit("Can't close pipe write end\n");
  152.  
  153.     /* parent process */
  154.  
  155.     ServiceRequestLoop();
  156.  
  157.     /* Close my pipe handles to tell the child that we are done */
  158.     CloseHandle(hChildStdinWrDup);
  159.     CloseHandle(hChildStdoutWr);
  160.  
  161.     /* Wait for the process */
  162.     if(WaitForSingleObject(proc_info.hProcess, (unsigned int)-1) != 0)
  163.     {
  164.        printf("Error waiting for NT process %d\n",GetLastError());
  165.        CloseHandle(proc_info.hThread);
  166.        CloseHandle(proc_info.hProcess);
  167.        return(1);
  168.     }
  169.  
  170.     /* Close my child process handles */
  171.         CloseHandle(proc_info.hThread);
  172.         CloseHandle(proc_info.hProcess);
  173.  
  174.     return(1);
  175.  
  176. }
  177.  
  178. /*
  179.   Service Requests from the POSIX program
  180.  
  181.   This can be expanded as required.
  182.  
  183.   The new client side requests can be added to rpcclt.c, while the server
  184.   side is added here. Record the new RPC's in win32psx.h.
  185. */
  186.  
  187. void ServiceRequestLoop()
  188. {
  189.     struct Request_Header Hd;
  190.     int numxfer;
  191.     char buf[512];
  192.  
  193.     for(;;)
  194.     {
  195.           /* Get a request */
  196.           numxfer = ReadStream((char *)&Hd, sizeof(struct Request_Header));
  197.           if(Hd.rh_type == RPC_REQUEST)
  198.           {
  199.                 switch(Hd.rh_request) {
  200.  
  201.           case RPC_NOOP:
  202. #ifdef DEBUG
  203. printf("WIN32: got RPC_NOOP request\n");
  204. #endif
  205.                SendAckReply(Hd.rh_chan);
  206.                break;
  207.  
  208.           case RPC_RUN_SHELL_CMD_SYNC:
  209. #ifdef DEBUG
  210. printf("WIN32: got RPC_RUN_SHELL_CMD_SYNC request :%s:\n",buf);
  211. #endif
  212.                ReadStream(buf, Hd.rh_size);
  213.                RunShellCmd(buf, Hd.rh_chan);
  214. #ifdef DEBUG
  215. printf("WIN32: Done running RPC_RUN_SHELL_CMD_SYNC\n");
  216. #endif
  217.                break;
  218.  
  219.                   default:
  220.                SendNackReply(Hd.rh_chan);
  221.                break;
  222.                 }
  223.           }
  224.        }
  225. }
  226.  
  227. void SendAckReply(int chan)
  228. {
  229.   struct Request_Header Hd;
  230.  
  231.   Hd.rh_type = RPC_REPLY;
  232.   Hd.rh_hdrsize = sizeof(struct Request_Header);
  233.   Hd.rh_size = 0;
  234.   Hd.rh_chan = chan;
  235.   Hd.rh_request = TRUE; /* Request is the RPC return code as well */
  236.   WriteStream((char *)&Hd, sizeof(struct Request_Header));
  237. }
  238.  
  239. void SendNackReply(int chan)
  240. {
  241.   struct Request_Header Hd;
  242.  
  243.   Hd.rh_type = RPC_REPLY;
  244.   Hd.rh_hdrsize = sizeof(struct Request_Header);
  245.   Hd.rh_size = 0;
  246.   Hd.rh_chan = chan;
  247.   Hd.rh_request = FALSE; /* Request is the RPC return code as well */
  248.   WriteStream((char *)&Hd, sizeof(struct Request_Header));
  249. }
  250.  
  251. int RunShellCmd(char *cmd, int chan)
  252. {
  253.     int exitstatus;
  254.     struct Request_Header Hd;
  255.     PROCESS_INFORMATION proc_info;
  256.     static STARTUPINFO start_info = {
  257.                        sizeof(STARTUPINFO), /* cb */
  258.                        0, 0, 0, /* LPSTR res,desk,title */
  259.                        0, 0, /* X, Y */
  260.                        80, 25, /* Xsize, Ysize */
  261.                        80, 25,
  262.                        0, /* Fill attribute */
  263.                        0, /* dwFlags
  264.                        0, /* dont show window */
  265.                        0, /* reserved */
  266.                        0 /* reserved */
  267.                     };
  268.     /* Now Create the Child Process */
  269.     if (!CreateProcess(NULL,
  270.          cmd, /* command string from POSIX client process */
  271.          0, /* no processes security attributes */
  272.          0, /* no thread security attributes */
  273.          1, /* inherit handles */
  274.          0, /* creation flags (inherit console, no detach */
  275.          0, /* inherit current environment block */
  276.          0, /* no new current directory */
  277.          &start_info, /* Startup info */
  278.          &proc_info) /* Process information */
  279.         )
  280.     {
  281.         SendNackReply(chan); /* Could not run the command */
  282.         return(1);
  283.     }
  284.  
  285.     /* Wait for the process */
  286.     if(WaitForSingleObject(proc_info.hProcess, (unsigned int)-1) != 0)
  287.     {
  288.        printf("Error waiting for NT process %d\n",GetLastError());
  289.        CloseHandle(proc_info.hThread);
  290.        CloseHandle(proc_info.hProcess);
  291.        SendNackReply(chan);
  292.        return(1);
  293.     }
  294.  
  295.     if(!GetExitCodeProcess(proc_info.hProcess, &exitstatus))
  296.         {
  297.           printf("Error %d getting exit status from NT process\n",GetLastError());
  298.           SendNackReply(chan);
  299.       return(1);
  300.     }
  301.  
  302.     /* Close my child process handles */
  303.         CloseHandle(proc_info.hThread);
  304.         CloseHandle(proc_info.hProcess);
  305.  
  306.     Hd.rh_type = RPC_REPLY;
  307.     Hd.rh_hdrsize = sizeof(struct Request_Header);
  308.     Hd.rh_size = 4; /* Integer exit status from process */
  309.     Hd.rh_chan = chan;
  310.     Hd.rh_request = TRUE; /* Request is the RPC return code as well */
  311.     WriteStream((char *)&Hd, sizeof(struct Request_Header));
  312.     WriteStream((char *)&exitstatus, sizeof(int));
  313.     return(0);
  314. }
  315.  
  316. /*
  317.   read data from the communications stream
  318. */
  319. int ReadStream(char *buf, int size)
  320. {
  321.   int numxfer, error;
  322.  
  323.   if(!ReadFile(hChildStdoutRd, buf, size, &numxfer, 0))
  324.   {
  325.     error = GetLastError();
  326.     if(error == ERROR_BROKEN_PIPE) /* Child exited */
  327.       ExitProcess(1); /* Success */
  328.     else
  329.     {
  330.       fprintf(stderr, "WIN32: Error reading Child Stdout, %d\n", GetLastError());
  331.       ExitProcess(0);
  332.     }
  333.   }
  334.   return(numxfer);
  335. }
  336.  
  337. /*
  338.   write data to the communications stream
  339. */
  340. int WriteStream(char *buf, int size)
  341. {
  342.   int numxfer;
  343.  
  344.   if(!WriteFile(hChildStdinWrDup, buf, size, &numxfer, 0))
  345.   {
  346.     fprintf(stderr, "WIN32: Error writing Child Stdin, %d\n", GetLastError());
  347.     ExitProcess(0);
  348.   }
  349.   return(numxfer);
  350. }
  351.  
  352. VOID ErrorExit(char *message)
  353. {
  354.   fprintf(stderr, message);
  355.   ExitProcess(0);
  356. }
  357.