home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / remote / server.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  45KB  |  1,630 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1992-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. /*++
  13.  
  14. Module Name:
  15.  
  16.     Server.c
  17.  
  18. Abstract:
  19.  
  20.     The server component of Remote. It spawns a child process
  21.     and redirects the stdin/stdout/stderr of child to itself.
  22.     Waits for connections from clients - passing the
  23.     output of child process to client and the input from clients
  24.     to child process.
  25.  
  26. Author:
  27.  
  28.     Rajivendra Nath (rajnath) 2-Jan-1992
  29.  
  30. Environment:
  31.  
  32.     Console App. User mode.
  33.  
  34. Revision History:
  35.  
  36. --*/
  37.  
  38. #include <windows.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <io.h>
  42. #include <string.h>
  43. #include "Remote.h"
  44.  
  45. #define MAX_SESSION   10
  46.  
  47. #define COMMANDFORMAT       "%c%-15s    [%-15s %d:%d]\n%c"
  48. #define LOCALNAME           "Local"
  49. #define LOCALCLIENT(x)      (strcmp((char *)(x->Name),LOCALNAME)==0)
  50. #define RemoteInfo(prt,flg) {if (!(flg&&0x80000000)) prt;}
  51.  
  52. #define CMDSTRING(OutBuff,InpBuff,Client,sTime) \
  53.         {                                \
  54.             /* int xxlen; */             \
  55.             sprintf                      \
  56.             (                            \
  57.                &OutBuff[0],COMMANDFORMAT,\
  58.                BEGINMARK,InpBuff,        \
  59.                Client->Name,sTime.wHour, \
  60.                sTime.wMinute,ENDMARK     \
  61.             );                           \
  62.          }                               \
  63.  
  64. #define BUFFSIZE      256
  65.  
  66. SESSION_TYPE ClientList[MAX_SESSION];
  67.  
  68. HANDLE  ChildStdInp;     //Server Writes to  it
  69. HANDLE  ChildStdOut;     //Server Reads from it
  70. HANDLE  ChildStdErr;     //Server Reads from it
  71.  
  72. HANDLE  SaveFile;       //File containing all that was
  73.                         //output by child process.
  74.                         //Each connection opens a handle to this file
  75.                         //and is sent through PipeWriteH.
  76.  
  77. char    SaveFileName[64]; //Name of above file - all new sessions need
  78. HANDLE  ChldProc;         //Handle to the Child Process
  79. HANDLE  ListenThreadH;    //Handle to the thread listening for connections
  80.                           //from Remote Clients.
  81.  
  82. char    *UserName;        // User/Group who can connect to this server.
  83.                           // Obtained from /U option. If NULL all access.
  84.  
  85. HANDLE
  86. ForkChildProcess(          // Creates a new process
  87.     char *cmd,             // Redirects its stdin,stdout
  88.     PHANDLE in,            // and stderr - returns the
  89.     PHANDLE out,           // corresponding pipe ends. Using currently
  90.     PHANDLE err
  91.     );
  92.  
  93. HANDLE
  94. OldForkChildProcess(       //Same as above except different
  95.     char *cmd,             //method for redirection. Not Used.
  96.     PHANDLE in,
  97.     PHANDLE out,
  98.     PHANDLE err
  99.     );
  100.  
  101. DWORD
  102. ListenForSession(          //THREAD:Listens for new connections and
  103.     char* pipe             //spawns of new seesions - Updates the
  104.     );                     //Status in Client DataStructure. Seperate Thread.
  105.  
  106. BOOL
  107. CreateMySecurityDescriptor(                    //
  108.     PSECURITY_DESCRIPTOR pSecurityDescriptor,  // Creates a security descriptor
  109.     char *Owner                                // with discretionary access for
  110.     );                                         // access for Owner.
  111.  
  112.  
  113. DWORD
  114. NewSession(                //Manages the session with a client.
  115.     SESSION_TYPE* Client
  116.     );
  117.  
  118. DWORD                      //2 THREAD:Each reads either
  119. GetChldOutput(             //StdOut or StdErr of child and
  120.     HANDLE rhandle         //writes to SaveFile. Seperate Thread.
  121.     );
  122.  
  123. DWORD
  124. TransferFileToClient(      //X THREADS:Reads the save
  125.     SESSION_TYPE* Client   //file and sendsoutput to a client. Seperate Thread
  126.     );
  127.  
  128.  
  129. DWORD
  130. GetClientInput(            //Times X THREADS:Gets input from Child pipe
  131.     SESSION_TYPE* Client   //and sends to childs StdIn. Seperate Thread.
  132.     );
  133.  
  134.  
  135. BOOL
  136. FilterCommand(             //Filters input from client
  137.     SESSION_TYPE *cl,      //for commands intended for REMOTE
  138.     char *buff,
  139.     int dread
  140.     );
  141.  
  142. DWORD                      // Manages the IO with user
  143. LocalSession(              // For the remote server. Seperate Thread.
  144.     PVOID noarg
  145.     );
  146.  
  147. DWORD                      // Manages the IO with Remote Client.
  148. RemoteSession(
  149.     SESSION_TYPE* Client
  150.     );
  151.  
  152. BOOL                       // Ctrl-C handler
  153. SrvCtrlHand(
  154.     DWORD event
  155.     );
  156.  
  157. VOID                       // @s command to remote
  158. SendStatus(
  159.     HANDLE hClientPipe
  160.     );
  161.  
  162. DWORD                      // @p command to remote
  163. ShowPopup(
  164.     char *mssg
  165.     );
  166.  
  167. VOID                       // Removes the command begin and end markers
  168. RemoveInpMark(             // from the save file.
  169.     char* Buff,
  170.     DWORD Size
  171.     );
  172.  
  173. VOID                       // Cleans up the session
  174. CloseClient(               // once it ends.
  175.     SESSION_TYPE *Client
  176.     );
  177.                            // Initialises the Client datastructs
  178. VOID
  179. InitClientList(
  180.     );
  181.  
  182.  
  183. /*************************************************************/
  184. /* The main entry point for the Server End of Remote         */
  185. /*************************************************************/
  186. VOID
  187. Server(                    
  188.     char* ChildCmd,
  189.     char* PipeName
  190.     )
  191. {
  192.     DWORD  ThreadID ;
  193.     HANDLE WaitH[3];
  194.     DWORD  WaitObj;
  195.     char   tmpdir[32];
  196.  
  197.     WRITEF((VBuff,"**************************************\n"));
  198.     WRITEF((VBuff,"***********     REMOTE    ************\n"));
  199.     WRITEF((VBuff,"***********     SERVER    ************\n"));
  200.     WRITEF((VBuff,"**************************************\n"));
  201.     WRITEF((VBuff,"To Connect: Remote /C %s %s\n\n",HostName,PipeName));
  202.  
  203.     InitClientList();
  204.  
  205.     //
  206.     //Start the command as a child process
  207.     //
  208.  
  209.     ChldProc=ForkChildProcess(ChildCmd,&ChildStdInp,&ChildStdOut,&ChildStdErr);
  210.  
  211.     //
  212.     //Create a tempfile for storing Child process output.
  213.     //
  214.     {
  215.          DWORD size=sizeof(tmpdir);
  216.          if (
  217.              (GetEnvironmentVariable("TMP" ,tmpdir,size)==0)&&
  218.              (GetEnvironmentVariable("TEMP",tmpdir,size)==0)
  219.             )
  220.          {
  221.             sprintf(tmpdir,"%s",".");
  222.          }
  223.          if (!GetTempFileName(tmpdir,"REMOTE",0,SaveFileName))
  224.             GetTempFileName(".","REMOTE",0,SaveFileName);
  225.     }
  226.  
  227.  
  228.     if ((SaveFile=CreateFile
  229.                   (
  230.                      (LPCTSTR)SaveFileName,           /* address of name of the file  */
  231.                      GENERIC_READ|GENERIC_WRITE,      /* access (read/write) mode */
  232.                      FILE_SHARE_READ|FILE_SHARE_WRITE,/* share mode   */
  233.                      (LPSECURITY_ATTRIBUTES)NULL,     /* security descriptor  */
  234.                      CREATE_ALWAYS,                   /* how to create    */
  235.                      FILE_ATTRIBUTE_NORMAL,           /* File Attribute */
  236.                      (HANDLE)NULL)
  237.                   )==NULL)
  238.     {
  239.         TerminateProcess(ChldProc,0);
  240.         ErrorExit("Could not Create Output File");
  241.     }
  242.  
  243.  
  244.     //
  245.     //Start 2 threads to save the output from stdout and stderr of cmd to savefile.
  246.     //
  247.  
  248.     if ((WaitH[0]=CreateThread
  249.                   (
  250.                      (LPSECURITY_ATTRIBUTES)NULL,           // No security attributes.
  251.                      (DWORD)0,                              // Use same stack size.
  252.                      (LPTHREAD_START_ROUTINE)GetChldOutput, // Thread procedure.
  253.                      (LPVOID)ChildStdErr,                   // Parameter to pass.
  254.                      (DWORD)0,                              // Run immediately.
  255.                      (LPDWORD)&ThreadID)
  256.                    )==NULL)
  257.     {
  258.  
  259.         TerminateProcess(ChldProc,0);
  260.         ErrorExit("Failed to Create GetGhldOutput#1 Thread");
  261.     }
  262.  
  263.  
  264.     if ((WaitH[1]=CreateThread
  265.                   (
  266.                      (LPSECURITY_ATTRIBUTES)NULL,           // No security attributes.
  267.                      (DWORD)0,                              // Use same stack size.
  268.                      (LPTHREAD_START_ROUTINE)GetChldOutput, // Thread procedure.
  269.                      (LPVOID)ChildStdOut,                   // Parameter to pass.
  270.                      (DWORD)0,                              // Run immediately.
  271.                      (LPDWORD)&ThreadID)
  272.                   )==NULL)
  273.     {
  274.  
  275.         TerminateProcess(ChldProc,0);
  276.         ErrorExit("Failed to Create GetGhldOutput#2 Thread");
  277.     }
  278.  
  279.  
  280.     //
  281.     //Start Thread to listen for new Connections
  282.     //
  283.  
  284.     if ((ListenThreadH=CreateThread
  285.                        (
  286.                          (LPSECURITY_ATTRIBUTES)NULL,        // No security attributes.
  287.                          (DWORD)0,                           // Use same stack size.
  288.                          (LPTHREAD_START_ROUTINE)ListenForSession, // Thread procedure.
  289.                          (LPVOID)PipeName,                   // Parameter to pass.
  290.                          (DWORD)0,                           // Run immediately.
  291.                          (LPDWORD)&ThreadID)
  292.                        )==NULL)
  293.     {
  294.  
  295.         TerminateProcess(ChldProc,0);
  296.         ErrorExit("Failed To Create ListenForSession Thread");
  297.  
  298.     }
  299.  
  300.     //
  301.     //Start Local Thread
  302.     //
  303.  
  304.     if ((ClientList[0].hThread=CreateThread
  305.                                (
  306.                                     (LPSECURITY_ATTRIBUTES)NULL,        // No security attributes.
  307.                                     (DWORD)0,                           // Use same stack size.
  308.                                     (LPTHREAD_START_ROUTINE)LocalSession, // Thread procedure.
  309.                                     (LPVOID)NULL,                       // Parameter to pass.
  310.                                     (DWORD)0,                           // Run immediately.
  311.                                     (LPDWORD)&ThreadID)
  312.                                )==NULL)
  313.     {
  314.  
  315.         TerminateProcess(ChldProc,0);
  316.         ErrorExit("Failed To Create ListenForSession Thread");
  317.  
  318.     }
  319.  
  320.     SetConsoleCtrlHandler((PHANDLER_ROUTINE)SrvCtrlHand,TRUE);
  321.  
  322.     WaitH[2]=ChldProc;
  323.  
  324.     //
  325.     // Wait until the child process terminates
  326.     // or local IO thread terminates
  327.     // or IO with child process ends
  328.     //
  329.  
  330.     WaitObj=WaitForMultipleObjects(3,WaitH,FALSE,INFINITE);
  331.  
  332.     switch (WaitObj-WAIT_OBJECT_0)
  333.     {
  334.         case 0:      // Error Writing to savefile
  335.         case 1:
  336.             TerminateProcess(ChldProc,0);
  337.             break;
  338.         case 2:      // Child Proc Terminated
  339.             break;
  340.  
  341.         default:     // Out of Some Resource
  342.             printf("Out of Resource Error %d..Terminating\n",GetLastError());
  343.             break;
  344.  
  345.     }
  346.  
  347.     TerminateThread(ListenThreadH,0);
  348.  
  349.     CloseHandle(ChildStdInp);
  350.     CloseHandle(ChildStdOut);
  351.     CloseHandle(ChildStdErr);
  352.  
  353.     WRITEF((VBuff,"\nRemote:Parent exiting. Child(%s) dead..\n",ChildCmd));
  354.  
  355.     CloseHandle(SaveFile);
  356.  
  357.     {
  358.         int i;
  359.         for (i=0;i<MAX_SESSION;i++)
  360.             CloseClient(&ClientList[i]);
  361.     }
  362.  
  363.     if (!DeleteFile(SaveFileName))
  364.           WRITEF((VBuff,"Temp File %s not deleted..\n",SaveFileName));
  365.  
  366.     return;
  367. }
  368. /*************************************************************/
  369. /* Creates the child process and redirects its std.IO handles*/
  370. /*************************************************************/
  371. HANDLE
  372. ForkChildProcess(          // Creates a new process
  373.     char *cmd,             // Redirects its stdin,stdout
  374.     PHANDLE inH,           // and stderr - returns the
  375.     PHANDLE outH,          // corresponding pipe ends.
  376.     PHANDLE errH
  377.     )
  378. {
  379.     SECURITY_ATTRIBUTES lsa;
  380.     STARTUPINFO         si;
  381.     PROCESS_INFORMATION pi;
  382.  
  383.     HANDLE ChildIn;
  384.     HANDLE ChildOut;
  385.     HANDLE ChildErr;
  386.  
  387.     lsa.nLength=sizeof(SECURITY_ATTRIBUTES);
  388.     lsa.lpSecurityDescriptor=NULL;
  389.     lsa.bInheritHandle=TRUE;
  390.  
  391.     //
  392.     //Create Parent_Write to ChildStdIn Pipe
  393.     //
  394.  
  395.     if (!CreatePipe(&ChildIn,inH,&lsa,0))
  396.         ErrorExit("Could Not Create Parent-->Child Pipe");
  397.  
  398.     //
  399.     //Create ChildStdOut to Parent_Read pipe
  400.     //
  401.  
  402.     if (!CreatePipe(outH,&ChildOut,&lsa,0))
  403.         ErrorExit("Could Not Create Child-->Parent Pipe");
  404.  
  405.     //
  406.     //Create ChildStdOut to Parent_Read pipe
  407.     //
  408.  
  409.     if (!CreatePipe(errH,&ChildErr,&lsa,0))
  410.         ErrorExit("Could Not Create Child-->Parent Pipe");
  411.  
  412.     //
  413.     // Lets Redirect Console StdHandles - easy enough
  414.     //
  415.  
  416.  
  417.     si.cb=sizeof(STARTUPINFO);
  418.     si.lpReserved=NULL;
  419.     si.lpTitle=NULL;
  420.     si.lpDesktop=NULL;
  421.     si.dwX=si.dwY=si.dwYSize=si.dwXSize=0;
  422.     si.dwFlags=STARTF_USESTDHANDLES;
  423.     si.hStdInput =ChildIn;
  424.     si.hStdOutput=ChildOut;
  425.     si.hStdError =ChildErr;
  426.     si.wShowWindow=SW_SHOW;
  427.     si.lpReserved2=NULL;
  428.     si.cbReserved2=0;
  429.  
  430.     //
  431.     //Create Child Process
  432.     //
  433.  
  434.     if (!CreateProcess
  435.          (
  436.             NULL,
  437.             cmd,
  438.             NULL,
  439.             NULL,
  440.             TRUE,
  441.             NORMAL_PRIORITY_CLASS,
  442.             NULL,
  443.             NULL,
  444.             &si,
  445.             &pi)
  446.          )
  447.     {
  448.         if (GetLastError()==2)
  449.             WRITEF((VBuff,"Executable %s not found\n",cmd));
  450.         ErrorExit("Could Not Create Child Process");
  451.     }
  452.  
  453.     //
  454.     //Close unneccesary Handles and Restore the crt handles
  455.     //
  456.  
  457.     CloseHandle(ChildIn);
  458.     CloseHandle(ChildOut);
  459.     CloseHandle(ChildErr);
  460.  
  461.     return(pi.hProcess);
  462. }
  463. /*************************************************************/
  464. /* Same as above but uses different method of IO redir.      */
  465. /* Not used now                                              */
  466. /*************************************************************/
  467. HANDLE
  468. OldForkChildProcess(
  469.     char *cmd,
  470.     PHANDLE inH,
  471.     PHANDLE outH,
  472.     PHANDLE errH
  473.     )
  474. {
  475.     SECURITY_ATTRIBUTES lsa;
  476.     STARTUPINFO         si;
  477.     PROCESS_INFORMATION pi;
  478.  
  479.     HANDLE OldStdIn =GetStdHandle(STD_INPUT_HANDLE);
  480.     HANDLE OldStdOut=GetStdHandle(STD_OUTPUT_HANDLE);
  481.     HANDLE OldStdErr=GetStdHandle(STD_ERROR_HANDLE);
  482.  
  483.     HANDLE ChildStdIn;
  484.     HANDLE ChildStdOut;
  485.     HANDLE ChildStdErr;
  486.  
  487.     lsa.nLength=sizeof(SECURITY_ATTRIBUTES);
  488.     lsa.lpSecurityDescriptor=NULL;
  489.     lsa.bInheritHandle=TRUE;
  490.  
  491.     //Create Parent_Write to ChildStdIn Pipe
  492.     if (!CreatePipe(&ChildStdIn,inH,&lsa,0))
  493.         ErrorExit("Could Not Create Parent-->Child Pipe");
  494.  
  495.     //Create ChildStdOut to Parent_Read pipe
  496.     if (!CreatePipe(outH,&ChildStdOut,&lsa,0))
  497.         ErrorExit("Could Not Create Child-->Parent Pipe");
  498.  
  499.     //Create ChildStdOut to Parent_Read pipe
  500.     if (!CreatePipe(errH,&ChildStdErr,&lsa,0))
  501.         ErrorExit("Could Not Create Child-->Parent Pipe");
  502.  
  503.     //Make ChildStdIn and Out as standard handles and get it inherited by child
  504.     if (!SetStdHandle(STD_INPUT_HANDLE,ChildStdIn))
  505.         ErrorExit("Could not change StdIn");
  506.  
  507.     if (!SetStdHandle(STD_OUTPUT_HANDLE,ChildStdOut))
  508.         ErrorExit("Could Not change StdOut");
  509.  
  510.     if (!SetStdHandle(STD_ERROR_HANDLE,ChildStdErr))
  511.         ErrorExit("Could Not change StdErr");
  512.  
  513.     si.cb=sizeof(STARTUPINFO);
  514.     si.lpReserved=NULL;
  515.     si.lpTitle=NULL;
  516.     si.lpDesktop=NULL;
  517.     si.dwX=si.dwY=si.dwYSize=si.dwXSize=si.dwFlags=0L;
  518.     si.wShowWindow=SW_SHOW;
  519.     si.lpReserved2=NULL;
  520.     si.cbReserved2=0;
  521.  
  522.     //Create Child Process
  523.     if (!CreateProcess
  524.          (
  525.             NULL,
  526.             cmd,
  527.             NULL,
  528.             NULL,
  529.             TRUE,
  530.             NORMAL_PRIORITY_CLASS,
  531.             NULL,
  532.             NULL,
  533.             &si,
  534.             &pi)
  535.          )
  536.     {
  537.         ErrorExit("Could Not Create Child Process");
  538.     }
  539.  
  540.     //reset StdIn StdOut
  541.     if (!SetStdHandle(STD_INPUT_HANDLE,OldStdIn))
  542.     {
  543.         TerminateProcess(pi.hProcess,1);
  544.         ErrorExit("Could not RESET StdIn");
  545.     }
  546.  
  547.     if (!SetStdHandle(STD_OUTPUT_HANDLE,OldStdOut))
  548.     {
  549.         TerminateProcess(pi.hProcess,1);
  550.         ErrorExit("Could not RESET StdIn");
  551.     }
  552.  
  553.     if (!SetStdHandle(STD_ERROR_HANDLE,OldStdErr))
  554.     {
  555.         TerminateProcess(pi.hProcess,1);
  556.         ErrorExit("Could not RESET StdIn");
  557.     }
  558.  
  559.     //Close unneccesary Handles
  560.     CloseHandle(ChildStdIn);
  561.     CloseHandle(ChildStdOut);
  562.     CloseHandle(ChildStdErr);
  563.  
  564.     return(pi.hProcess);
  565. }
  566.  
  567. /*************************************************************/
  568. /* Listens for sessions from Clients and creates a new thread*/
  569. /* for each client                                           */
  570. /*************************************************************/
  571.  
  572. DWORD
  573. ListenForSession(
  574.    char* pipename
  575.    )
  576. {
  577.     int    i;
  578.     DWORD  ThreadID;
  579.     HANDLE PipeH[2];
  580.     SECURITY_DESCRIPTOR SecurityDescriptor;
  581.     HANDLE TokenHandle;
  582.     TOKEN_DEFAULT_DACL DefaultDacl;
  583.     SECURITY_ATTRIBUTES lsa;
  584.  
  585.     char   fullnameIn[BUFFSIZE];
  586.     char   fullnameOut[BUFFSIZE];
  587.  
  588.     sprintf(fullnameIn,SERVER_READ_PIPE  ,".",pipename);
  589.     sprintf(fullnameOut,SERVER_WRITE_PIPE,".",pipename);
  590.  
  591.  
  592.     DefaultDacl.DefaultDacl = NULL;
  593.  
  594.     if (OpenProcessToken
  595.         (
  596.             GetCurrentProcess(),
  597.             TOKEN_ADJUST_DEFAULT,
  598.             &TokenHandle
  599.         ))
  600.     {
  601.  
  602.         //
  603.         // Remove the default DACL on the token
  604.         //
  605.  
  606.         SetTokenInformation
  607.         (
  608.             TokenHandle,
  609.             TokenDefaultDacl,
  610.             &DefaultDacl,
  611.             sizeof( TOKEN_DEFAULT_DACL )
  612.         );
  613.  
  614.     }
  615.  
  616.  
  617.     if (CreateMySecurityDescriptor(&SecurityDescriptor,UserName)==FALSE)
  618.     {
  619.         Errormsg("Remote:Could not set security for user");
  620.     }
  621.  
  622.     lsa.nLength=sizeof(SECURITY_ATTRIBUTES);
  623.     lsa.lpSecurityDescriptor=&SecurityDescriptor;
  624.     lsa.bInheritHandle=TRUE;
  625.  
  626.     while(TRUE)
  627.     {
  628.         //
  629.         // Create New pipe instances for each connection
  630.         //
  631.  
  632.         PipeH[0]=CreateNamedPipe
  633.                  (
  634.                     fullnameIn ,
  635.                     PIPE_ACCESS_INBOUND ,
  636.                     PIPE_TYPE_BYTE,
  637.                     PIPE_UNLIMITED_INSTANCES,
  638.                     0,0,0,&lsa
  639.                  );
  640.  
  641.         PipeH[1]=CreateNamedPipe
  642.                  (
  643.                     fullnameOut,
  644.                     PIPE_ACCESS_OUTBOUND,
  645.                     PIPE_TYPE_BYTE,
  646.                     PIPE_UNLIMITED_INSTANCES,
  647.                     0,0,0,&lsa
  648.                  );
  649.  
  650.         if (!ConnectNamedPipe(PipeH[0],NULL))
  651.         {
  652.             if (GetLastError()!=ERROR_PIPE_CONNECTED)
  653.             {
  654.                 CloseHandle(PipeH[0]);
  655.                 CloseHandle(PipeH[1]);
  656.                 continue;
  657.             }
  658.  
  659.         }
  660.  
  661.         if (!ConnectNamedPipe(PipeH[1],NULL))
  662.         {
  663.             if (GetLastError()!=ERROR_PIPE_CONNECTED)
  664.             {
  665.                 CloseHandle(PipeH[0]);
  666.                 CloseHandle(PipeH[1]);
  667.                 continue;
  668.             }
  669.         }
  670.  
  671.         //
  672.         //Look For a Free Slot & if not- then terminate connection
  673.         //
  674.  
  675.         for (i=1;i<MAX_SESSION;i++)
  676.         {
  677.             //
  678.             // Locate a Free Client block
  679.             //
  680.             if (!ClientList[i].Active)
  681.                 break;
  682.         }
  683.  
  684.         if (i<MAX_SESSION)
  685.         {
  686.             //
  687.             // Initialize the Client
  688.             //
  689.             ClientList[i].PipeReadH=PipeH[0];
  690.             ClientList[i].PipeWriteH=PipeH[1];
  691.             ClientList[i].Active=TRUE;
  692.             ClientList[i].SendOutput=TRUE;
  693.             ClientList[i].CommandRcvd=FALSE;
  694.  
  695.         }
  696.         else
  697.         {
  698.             WRITEF((VBuff,"Remote:Closing New Session - No more slots\n"));
  699.             CloseHandle(PipeH[0]);
  700.             CloseHandle(PipeH[1]);
  701.             continue;
  702.         }
  703.  
  704.         //
  705.         //start new thread for this connection
  706.         //
  707.  
  708.         if((ClientList[i].hThread=CreateThread
  709.             (
  710.                  (LPSECURITY_ATTRIBUTES)NULL,        // No security attributes.
  711.                  (DWORD)0,                           // Use same stack size.
  712.                  (LPTHREAD_START_ROUTINE)RemoteSession, // Thread procedure.
  713.                  (LPVOID)&ClientList[i],             // Parameter to pass.
  714.                  (DWORD)0,                           // Run immediately.
  715.                  (LPDWORD)&ThreadID)
  716.             )==NULL)
  717.         {
  718.             CloseClient(&ClientList[i]);
  719.             continue;
  720.         }
  721.     }
  722.     return(0);
  723. }
  724.  
  725. /*************************************************************/
  726. /* Creates a security descriptor with the discrtionry access */
  727. /* for the account specified in the /U switch  if any        */
  728. /*************************************************************/
  729.  
  730. BOOL
  731. CreateMySecurityDescriptor(
  732.     PSECURITY_DESCRIPTOR pSecurityDescriptor,
  733.     char *Owner
  734.     )
  735. {
  736.     PSID pOwnerSid;
  737.     PACL pAcl;
  738.     BOOL Ret=FALSE;
  739.  
  740.     //
  741.     // Initialize the Security Descriptor struct.
  742.     //
  743.  
  744.  
  745.     InitializeSecurityDescriptor
  746.     (
  747.         pSecurityDescriptor,
  748.         SECURITY_DESCRIPTOR_REVISION
  749.     );
  750.  
  751.     if (Owner==NULL)
  752.     {
  753.         //
  754.         // No security required.
  755.         //
  756.  
  757.         SetSecurityDescriptorDacl
  758.         (
  759.                pSecurityDescriptor,
  760.                TRUE,
  761.                NULL,
  762.                FALSE
  763.         );
  764.  
  765.         return TRUE;
  766.     }
  767.  
  768.     {
  769.         //
  770.         // Get the SID for the account/Group
  771.         //
  772.  
  773.         DWORD len1=1024,len2=1024;
  774.         char RefDomain[1024];
  775.         SID_NAME_USE snu=0;        //don't care
  776.  
  777.         if ((pOwnerSid=(PSID)calloc(len1,1))==NULL)
  778.             return FALSE;
  779.  
  780.  
  781.         Ret=
  782.         LookupAccountName
  783.         (
  784.             NULL,
  785.             Owner,
  786.             pOwnerSid,
  787.             &len1,
  788.             RefDomain,
  789.             &len2,
  790.             &snu
  791.         );
  792.  
  793.         if (!Ret)
  794.         {
  795.             free(pOwnerSid);
  796.             return FALSE;
  797.         }
  798.  
  799.     }
  800.  
  801.     {
  802.  
  803.         //
  804.         // Create the access control list with access for
  805.         // the SID obtained above.
  806.         //
  807.  
  808.         DWORD aclsize=sizeof(ACL)+
  809.                       sizeof(ACCESS_ALLOWED_ACE)+
  810.                       GetLengthSid(pOwnerSid)-
  811.                       sizeof(DWORD);
  812.  
  813.         if ((pAcl=(PACL)calloc(1,aclsize))==NULL)
  814.         {
  815.             free(pOwnerSid);
  816.             return FALSE;
  817.         }
  818.  
  819.         //
  820.         // Initialize the acl buffer
  821.         //
  822.  
  823.         Ret=
  824.         InitializeAcl
  825.         (
  826.             pAcl,
  827.             aclsize,
  828.             ACL_REVISION
  829.         );
  830.  
  831.         if (!Ret)
  832.         {
  833.             free(pOwnerSid);
  834.             free(pAcl);
  835.             return FALSE;
  836.         }
  837.  
  838.         //
  839.         // Add the sid to the access allowed part in ACL
  840.         //
  841.  
  842.         Ret=
  843.         AddAccessAllowedAce
  844.         (
  845.             pAcl,
  846.             ACL_REVISION,
  847.             GENERIC_ALL,
  848.             pOwnerSid
  849.         );
  850.  
  851.         if (!Ret)
  852.         {
  853.             free(pOwnerSid);
  854.             free(pAcl);
  855.             return FALSE;
  856.         }
  857.     }
  858.  
  859.     //
  860.     // Add the created ACL to the discreationary control list
  861.     //
  862.  
  863.     Ret=
  864.     SetSecurityDescriptorDacl
  865.     (
  866.         pSecurityDescriptor,
  867.         TRUE,
  868.         pAcl,
  869.         FALSE
  870.     );
  871.  
  872.     if (!Ret)
  873.     {
  874.         free(pOwnerSid);
  875.         free(pAcl);
  876.         return FALSE;
  877.     }
  878.     return TRUE;
  879. }
  880.  
  881. /*************************************************************/
  882. /* Manages the Session with a Client - Creates a thread for  */
  883. /* Inputs from the client and a thread for sending outputs to*/
  884. /* the client. Could have just as easily done with 1 thread  */
  885. /* using Asyn IO.                                            */
  886. /*************************************************************/
  887. DWORD
  888. RemoteSession(
  889.     SESSION_TYPE         *MyClient
  890.     )
  891. {
  892.     DWORD                ReadCnt;
  893.     SESSION_STARTUPINFO  ssi;
  894.     char                 *headerbuff;
  895.     char                 msg[BUFFSIZE];
  896.     DWORD                tmp;
  897.     SESSION_STARTREPLY   ssr;
  898.     SYSTEMTIME           st;
  899.  
  900.     GetLocalTime(&st);
  901.     memset((char *)&ssi,0,sizeof(ssi));
  902.  
  903.     //
  904.     // Open a new handle to the save file ...
  905.     // contains the saved output from the child process
  906.     // and the commands already given to it.
  907.     //
  908.  
  909.     if ((MyClient->rSaveFile=CreateFile
  910.         (
  911.             SaveFileName,
  912.             GENERIC_READ|GENERIC_WRITE,
  913.             FILE_SHARE_READ|FILE_SHARE_WRITE,
  914.             NULL,OPEN_EXISTING,
  915.             FILE_ATTRIBUTE_NORMAL,NULL)
  916.         )==NULL)
  917.  
  918.     {
  919.         CloseClient(MyClient);
  920.         return(1);
  921.     }
  922.  
  923.     //
  924.     // Exchange Remote Information with Client.
  925.     //
  926.  
  927.     {
  928.  
  929.         DWORD reply=0;
  930.  
  931.         ReadFixBytes(MyClient->PipeReadH,(char *)MyClient->Name,HOSTNAMELEN-1,0);
  932.  
  933.         //
  934.         //Last four Bytes contains a code
  935.         //
  936.  
  937.         memcpy((char *)&reply,(char *)&(MyClient->Name[11]),4);
  938.  
  939.         if (reply!=MAGICNUMBER)
  940.         {
  941.             //
  942.             // Unknown client
  943.             //
  944.             CloseClient(MyClient);
  945.             return(1);
  946.         }
  947.  
  948.         ssr.MagicNumber=MAGICNUMBER;
  949.         ssr.Size=sizeof(ssr);
  950.         ssr.FileSize=GetFileSize( MyClient->rSaveFile, &tmp );
  951.  
  952.         WriteFile(MyClient->PipeWriteH,(char *)&ssr,sizeof(ssr),&tmp,NULL);
  953.     }
  954.  
  955.     if (ReadFixBytes(MyClient->PipeReadH,(char *)&(ssi.Size),sizeof(ssi.Size),0)!=0)
  956.     {
  957.         CloseClient(MyClient);
  958.         return(1);
  959.     }
  960.  
  961.     if (ssi.Size>1024)      //Sanity Check
  962.     {
  963.         sprintf(msg,"%s","Server:Unknown Header..Terminating session\n");
  964.         WriteFile(MyClient->PipeWriteH,msg,strlen(msg),&tmp,NULL);
  965.         CloseClient(MyClient);
  966.         return(1);
  967.     }
  968.  
  969.     if ((headerbuff=(char *)calloc(ssi.Size,1))==NULL)
  970.     {
  971.         sprintf(msg,"%s","Server:Not Enough Memory..Terminating session\n");
  972.         WriteFile(MyClient->PipeWriteH,msg,strlen(msg),&tmp,NULL);
  973.         CloseClient(MyClient);
  974.         return(1);
  975.     }
  976.  
  977.     ReadCnt=ssi.Size-sizeof(ssi.Size);
  978.     if (ReadFixBytes(MyClient->PipeReadH,(char *)headerbuff,ReadCnt,0)!=0)
  979.     {
  980.         CloseClient(MyClient);
  981.         return(1);
  982.     }
  983.  
  984.     memcpy((char *)&ssi+sizeof(ssi.Size),headerbuff,sizeof(ssi)-sizeof(ssi.Size));
  985.     free(headerbuff);
  986.  
  987.     /* Version  */
  988.     if (ssi.Version!=VERSION)
  989.     {
  990.          sprintf(msg,"Remote Warning:Server Version=%d Client Version=%d\n",VERSION,ssi.Version);
  991.          WriteFile(MyClient->PipeWriteH,msg,strlen(msg),&tmp,NULL);
  992.  
  993.     }
  994.  
  995.     /* Name  */
  996.     {
  997.         memcpy(MyClient->Name,ssi.ClientName,15);
  998.         MyClient->Name[14]=0;
  999.  
  1000.     }
  1001.  
  1002.     /* Lines  */
  1003.     if (ssi.LinesToSend!=-1)
  1004.     {
  1005.         long  PosFromEnd=ssi.LinesToSend*CHARS_PER_LINE;
  1006.         DWORD BytesToSend=MINIMUM((DWORD)PosFromEnd,ssr.FileSize);
  1007.         DWORD BytesRead;
  1008.         char  *buff=(char *)calloc(BytesToSend+1,1);
  1009.  
  1010.         if (ssr.FileSize > (DWORD)PosFromEnd)
  1011.         {
  1012.             SetFilePointer(
  1013.                             MyClient->rSaveFile,
  1014.                             -PosFromEnd,
  1015.                             (PLONG)NULL,
  1016.                             FILE_END
  1017.                           );
  1018.         }
  1019.  
  1020.         if (buff!=NULL)
  1021.         {
  1022.             if (!ReadFile(MyClient->rSaveFile,buff,BytesToSend,&BytesRead,NULL))
  1023.             {
  1024.                 CloseClient(MyClient);
  1025.                 return(1);
  1026.             }
  1027.  
  1028.             //
  1029.             // Don't want the markers to be part of the output display
  1030.             // at the client end.
  1031.             //
  1032.             RemoveInpMark(buff,BytesRead);
  1033.             if (!WriteFile(MyClient->PipeWriteH,buff,BytesRead,&tmp,NULL))
  1034.             {
  1035.                 CloseClient(MyClient);
  1036.                 return(1);
  1037.             }
  1038.         }
  1039.         free(buff);
  1040.  
  1041.     }
  1042.  
  1043.     RemoteInfo(printf("\n**Remote:Connected To %s [%02d:%02d]\n",MyClient->Name,st.wHour,st.wMinute),ssi.Flag);
  1044.  
  1045.     //
  1046.     // Start off the new session.
  1047.     //
  1048.     NewSession(MyClient);
  1049.  
  1050.     RemoteInfo(printf("\n**Remote:Disconnected From %s [%02d:%02d]\n",MyClient->Name,st.wHour,st.wMinute),ssi.Flag);
  1051.     CloseClient(MyClient);
  1052.     return(0);
  1053. }
  1054. /*************************************************************/
  1055. DWORD
  1056. NewSession(
  1057.     SESSION_TYPE* MyClient
  1058.     )
  1059. {
  1060.     DWORD        ThreadId;
  1061.     HANDLE       rwThread[3];
  1062.  
  1063.     MyClient->MoreData=CreateEvent
  1064.     (
  1065.         (LPSECURITY_ATTRIBUTES) NULL,/* address of security attributes    */
  1066.         FALSE,                         /* flag for manual-reset event    */
  1067.         TRUE,                         /* flag for initial state    */
  1068.         NULL                         /* address of event-object name    */
  1069.     );
  1070.  
  1071.     if ((rwThread[0]=CreateThread
  1072.          (
  1073.             (LPSECURITY_ATTRIBUTES)NULL,         // No security attributes.
  1074.             (DWORD)0,                            // Use same stack size.
  1075.             (LPTHREAD_START_ROUTINE)GetClientInput, // Thread procedure.
  1076.             (LPVOID)MyClient,                    // Parameter to pass.
  1077.             (DWORD)0,                            // Run immediately.
  1078.             (LPDWORD)&ThreadId)
  1079.          )==NULL)
  1080.     {
  1081.         return(GetLastError());
  1082.     }
  1083.  
  1084.  
  1085.     if ((rwThread[1]=CreateThread
  1086.          (
  1087.             (LPSECURITY_ATTRIBUTES)NULL,        // No security attributes.
  1088.             (DWORD)0,                           // Use same stack size.
  1089.             (LPTHREAD_START_ROUTINE)TransferFileToClient, // Thread procedure.
  1090.             (LPVOID)MyClient,                    // Parameter to pass.
  1091.             (DWORD)0,                           // Run immediately.
  1092.             (LPDWORD)&ThreadId)
  1093.          )==NULL)
  1094.     {
  1095.         CloseHandle(rwThread[0]);
  1096.         return(GetLastError());
  1097.     }
  1098.  
  1099.     rwThread[2]=ChldProc;
  1100.  
  1101.     //
  1102.     // Wait for either the Input or Output thread
  1103.     // to terminate and then close the session.
  1104.     //
  1105.  
  1106.     WaitForMultipleObjects(3, rwThread,FALSE, INFINITE);
  1107.  
  1108.     TerminateThread(rwThread[0],1);
  1109.     TerminateThread(rwThread[1],1);
  1110.  
  1111.     CloseHandle(rwThread[0]);
  1112.     CloseHandle(rwThread[0]);
  1113.  
  1114.     return(0);
  1115. }
  1116.  
  1117. /*************************************************************/
  1118. /* Saves the output from the child process into the savefile */
  1119. /* All the remote client thread and local client thread      */
  1120. /* open a seperate handle to this and output its content     */
  1121. /* sequentially.                                             */
  1122. /*************************************************************/
  1123. DWORD
  1124. GetChldOutput(
  1125.     HANDLE readH
  1126.     )
  1127. {
  1128.     char  buff[BUFFSIZE];
  1129.     DWORD dread;
  1130.     DWORD tmp;
  1131.  
  1132.  
  1133.     while(ReadFile(readH,buff,BUFFSIZE-1,&dread,NULL))
  1134.     {
  1135.         buff[dread]='\0';
  1136.  
  1137.         if (!WriteFile(SaveFile,buff,dread,&tmp,NULL))
  1138.         {
  1139.             return(1);
  1140.         }
  1141.  
  1142.         //
  1143.         // Signal Reader Thread that more data is available
  1144.         //
  1145.         {
  1146.             int i;
  1147.             for (i=0;i<MAX_SESSION;i++)
  1148.             {
  1149.                 if (ClientList[i].Active)
  1150.                 {
  1151.                     SetEvent(ClientList[i].MoreData);
  1152.                 }
  1153.             }
  1154.         }
  1155.     }
  1156.     return(1);
  1157. }
  1158. /*************************************************************/
  1159. /* A thread for each client connection and one for local IO  */
  1160. /* Reads the contents of Save file and sends it to client for*/
  1161. /* display.                                                  */
  1162. /*************************************************************/
  1163. DWORD
  1164. TransferFileToClient(
  1165.     SESSION_TYPE *MyClient
  1166.     )
  1167. {
  1168.  
  1169.     char   buffin[BUFFSIZE],buffout[BUFFSIZE],cmdbuff[BUFFSIZE];
  1170.     DWORD  tmp;
  1171.     DWORD  dread=0,dwrite=0;
  1172.     BOOL   incmd=FALSE;
  1173.     DWORD  cmdP=0;
  1174.     DWORD  i;
  1175.     char   MyEchoStr[30];
  1176.  
  1177.     sprintf(MyEchoStr,"[%-15s",MyClient->Name);
  1178.  
  1179.     while(ReadFile(MyClient->rSaveFile,buffin,BUFFSIZE-1,&dread,NULL))
  1180.     {
  1181.         if (dread==0)
  1182.         {
  1183.             //
  1184.             // Event is set by GetChldOutput() func. to signal
  1185.             // More data is available in save file.
  1186.             //
  1187.             WaitForSingleObject(MyClient->MoreData,INFINITE);
  1188.             continue;
  1189.         }
  1190.         dwrite=0;
  1191.  
  1192.         //
  1193.         // This is all to insure that the commands entered
  1194.         // by clients are not echoed back to them.
  1195.         // A Beginmark and an Endmark is placed around commands
  1196.         // sent to the child process from some client.
  1197.         //
  1198.  
  1199.         for(i=0;i<dread;i++)
  1200.         {
  1201.             if (incmd)
  1202.             {
  1203.                 if ((buffin[i]==ENDMARK)||(cmdP==BUFFSIZE-1))
  1204.                 {
  1205.                     incmd=FALSE;
  1206.                     cmdbuff[cmdP]=0;
  1207.                     if ((strstr(cmdbuff,MyEchoStr)==NULL)||
  1208.                         (!MyClient->CommandRcvd))
  1209.                     {
  1210.                         if (!WriteFile(
  1211.                             MyClient->PipeWriteH,
  1212.                             cmdbuff,cmdP,&tmp,NULL))
  1213.                         {
  1214.                             return(1);
  1215.                         }
  1216.                     }
  1217.                     cmdP=0;
  1218.                 }
  1219.                 else
  1220.                 {
  1221.                     cmdbuff[cmdP++]=buffin[i];
  1222.                 }
  1223.             }
  1224.             else
  1225.             {
  1226.  
  1227.                 if (buffin[i]==BEGINMARK)
  1228.                 {
  1229.                     if (dwrite!=0)
  1230.                     {
  1231.                         if (!WriteFile(
  1232.                             MyClient->PipeWriteH,
  1233.                             buffout,dwrite,&tmp,NULL))
  1234.                         {
  1235.                             return(1);
  1236.                         }
  1237.                         dwrite=0;
  1238.                     }
  1239.                     incmd=TRUE;
  1240.                     continue;
  1241.                 }
  1242.                 else
  1243.                 {
  1244.                     buffout[dwrite++]=buffin[i];
  1245.                 }
  1246.             }
  1247.         }
  1248.  
  1249.         if (dwrite!=0)
  1250.         {
  1251.             if (!WriteFile(
  1252.                 MyClient->PipeWriteH,
  1253.                 buffout,dwrite,&tmp,NULL))
  1254.             {
  1255.                 return(0);
  1256.             }
  1257.         }
  1258.     }
  1259.     return(1);
  1260. }
  1261.  
  1262. /*************************************************************/
  1263. /* Commands from the clients are sent to the child process   */
  1264. /* and also saved in the SaveFile with Begin and End markers */
  1265. /* around them to seperate them from the output from child   */
  1266. /* process.                                                  */
  1267. /*************************************************************/
  1268. DWORD
  1269. GetClientInput(
  1270.     SESSION_TYPE *MyClient
  1271.     )
  1272. {
  1273.     char buff[BUFFSIZE];
  1274.     DWORD tmp,dread;
  1275.  
  1276.     while(ReadFile(MyClient->PipeReadH,buff,BUFFSIZE,&dread,NULL))
  1277.     {
  1278.         buff[dread]=0;
  1279.         MyClient->CommandRcvd=TRUE;
  1280.  
  1281.         if (FilterCommand(MyClient,buff,dread))
  1282.             continue;
  1283.  
  1284.  
  1285.         if (!WriteFile(ChildStdInp,buff,dread,&tmp,NULL))
  1286.         {
  1287.             ExitThread(0);
  1288.         }
  1289.     }
  1290.     return(1);
  1291. }
  1292.  
  1293. /*************************************************************/
  1294. /* If a client command is intended for the Remote server -   */
  1295. /* those beginning with COMMANDCHAR (are not intended        */
  1296. /* for the child process) - they are executed here           */
  1297. /* and the output sent to the client.                        */
  1298. /*************************************************************/
  1299. BOOL
  1300. FilterCommand(
  1301.     SESSION_TYPE *cl,
  1302.     char *buff,
  1303.     int dread
  1304.     )
  1305. {
  1306.     SYSTEMTIME st;
  1307.     char       inp_buff[4096];
  1308.     char       tmpchar;
  1309.     char       ch[3];
  1310.     DWORD      tmp;
  1311.     int        len;
  1312.     DWORD      ThreadID; //Useless
  1313.  
  1314.     if (dread==0)
  1315.         return(FALSE);
  1316.  
  1317.     buff[dread]=0;
  1318.  
  1319.     GetLocalTime(&st);
  1320.  
  1321.  
  1322.     if (buff[0]==COMMANDCHAR)
  1323.     {
  1324.         switch(buff[1])
  1325.         {
  1326.             case 'o':
  1327.             case 'O':
  1328.                 cl->SendOutput=!cl->SendOutput;
  1329.                 break;
  1330.  
  1331.             case 'k':
  1332.             case 'K':
  1333.                 TerminateProcess(ChldProc,1);
  1334.                 break;
  1335.  
  1336.             case 's':
  1337.             case 'S':
  1338.                  SendStatus(cl->PipeWriteH);
  1339.                  break;
  1340.  
  1341.             case 'p':
  1342.             case 'P':
  1343.                 {
  1344.                     char  *mssg=(char *)calloc(4096,1); //Free it in called Proc
  1345.                     char  *ack="Remote:Popup Shown..\n";
  1346.  
  1347.                     if (mssg==NULL)
  1348.                         break;
  1349.  
  1350.                     sprintf(mssg,"From %s [%d:%d]\n\n%s\n",cl->Name,st.wHour,st.wMinute,&buff[2]);
  1351.                     CreateThread(
  1352.                           (LPSECURITY_ATTRIBUTES)NULL,         // No security attributes.
  1353.                           (DWORD)0,              // Use same stack size.
  1354.                           (LPTHREAD_START_ROUTINE)ShowPopup, // Thread procedure.
  1355.                           (LPVOID)mssg,          // Parameter to pass.
  1356.                           (DWORD)0,              // Run immediately.
  1357.                           (LPDWORD)&ThreadID
  1358.                          );
  1359.                     WriteFile(cl->PipeWriteH,ack,strlen(ack),&tmp,NULL);
  1360.                     break;
  1361.                  }
  1362.  
  1363.             case 'm':
  1364.             case 'M':
  1365.                 buff[dread-2]=0;
  1366.                 CMDSTRING(inp_buff,buff,cl,st);
  1367.                 len=strlen(inp_buff);
  1368.                 WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
  1369.                 break;
  1370.  
  1371.             case '@':
  1372.                 buff[dread-2]=0;
  1373.                 CMDSTRING(inp_buff,&buff[1],cl,st);
  1374.                 len=strlen(inp_buff);
  1375.                 WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
  1376.                 //
  1377.                 // Remove the first @ sign
  1378.                 //
  1379.                 MoveMemory(buff,&buff[1],dread-1);
  1380.                 buff[dread-1]=' ';
  1381.                 return(FALSE); //Send it it to the chile process
  1382.                 break;
  1383.  
  1384.  
  1385.             default :
  1386.                 sprintf(inp_buff,"%s","** Unknown Command **\n");
  1387.                 WriteFile(cl->PipeWriteH,inp_buff,strlen(inp_buff),&tmp,NULL);
  1388.  
  1389.             case 'h':
  1390.             case 'H':
  1391.                  sprintf(inp_buff,"%cM: To Send Message\n",COMMANDCHAR);
  1392.                  WriteFile(cl->PipeWriteH,inp_buff,strlen(inp_buff),&tmp,NULL);
  1393.                  sprintf(inp_buff,"%cP: To Generate popup\n",COMMANDCHAR);
  1394.                  WriteFile(cl->PipeWriteH,inp_buff,strlen(inp_buff),&tmp,NULL);
  1395.                  sprintf(inp_buff,"%cK: To kill the server\n",COMMANDCHAR);
  1396.                  WriteFile(cl->PipeWriteH,inp_buff,strlen(inp_buff),&tmp,NULL);
  1397.                  sprintf(inp_buff,"%cH: This Help\n",COMMANDCHAR);
  1398.                  WriteFile(cl->PipeWriteH,inp_buff,strlen(inp_buff),&tmp,NULL);
  1399.                  break;
  1400.         }
  1401.         return(TRUE);
  1402.     }
  1403.  
  1404.  
  1405.     if ((buff[0]<26))
  1406.     {
  1407.         BOOL ret=FALSE;
  1408.  
  1409.         sprintf(ch,"^%c",buff[0]+64);
  1410.         CMDSTRING(inp_buff,ch,cl,st);
  1411.         len=strlen(inp_buff);
  1412.  
  1413.         if (buff[0]==CTRLC)
  1414.         {
  1415.             cl->CommandRcvd=FALSE;
  1416.             GenerateConsoleCtrlEvent(CTRL_C_EVENT,0);
  1417.             ret=TRUE; //Already sent to child
  1418.         }
  1419.  
  1420.         WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
  1421.         return(ret); //FALSE:send it to child StdIn
  1422.     }
  1423.  
  1424.     tmpchar=buff[dread-2]; //must be 13;but just incase
  1425.     buff[dread-2]=0;
  1426.     CMDSTRING(inp_buff,buff,cl,st);
  1427.     buff[dread-2]=tmpchar;
  1428.     len=strlen(inp_buff);
  1429.     WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
  1430.     return(FALSE);
  1431. }
  1432. /*************************************************************/
  1433. VOID
  1434. SendStatus(
  1435.     HANDLE hClientPipe
  1436.     )
  1437. {
  1438.     char  buff[1024];
  1439.     int   i;
  1440.     DWORD tmp;
  1441.     char  *env=(char *)GetEnvironmentStrings();
  1442.     DWORD ver=GetVersion();
  1443.  
  1444.     sprintf(buff,"Command = %s\n",ChildCmd);
  1445.     WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
  1446.  
  1447.     sprintf(buff,"Server = %s PIPE=%s\n",HostName,PipeName);
  1448.     WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
  1449.  
  1450.     sprintf(buff,"Build = %d \n",((WORD *)&ver)[1]);
  1451.     WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
  1452.  
  1453.     for (i=1;i<MAX_SESSION;i++)
  1454.     {
  1455.         if (ClientList[i].Active)
  1456.         {
  1457.             sprintf(buff,"ACTIVE SESSION=%s\n",ClientList[i].Name);
  1458.             WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
  1459.         }
  1460.     }
  1461.  
  1462.     sprintf(buff,"====================\n",Server,PipeName);
  1463.     WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
  1464.  
  1465.     sprintf(buff,"ENVIRONMENT VARIABLES\n",Server,PipeName);
  1466.     WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
  1467.  
  1468.     sprintf(buff,"====================\n",Server,PipeName);
  1469.     WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
  1470.  
  1471.  
  1472.     try
  1473.     {
  1474.         while (*env!=0)
  1475.         {
  1476.             sprintf(buff,"%s\n",env);
  1477.             WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
  1478.  
  1479.             while(*(env++)!=0);
  1480.         }
  1481.     }
  1482.     except(EXCEPTION_EXECUTE_HANDLER)
  1483.     {
  1484.         sprintf(buff,"Exception Generated Getting Environment Block\n",env);
  1485.         WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
  1486.  
  1487.     }
  1488.  
  1489.     sprintf(buff,"====================\n",Server,PipeName);
  1490.     WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
  1491.     return;
  1492. }
  1493. /*************************************************************/
  1494. DWORD
  1495. ShowPopup(
  1496.     char *mssg
  1497.     )
  1498. {
  1499.     MessageBox(GetActiveWindow(),mssg,"***REMOTE***",MB_OK|MB_SETFOREGROUND);
  1500.     free(mssg);
  1501.     return(0);
  1502.  
  1503. }
  1504. /*************************************************************/
  1505. BOOL SrvCtrlHand(
  1506.     DWORD event
  1507.     )
  1508. {
  1509.     if (event==CTRL_BREAK_EVENT)
  1510.     {
  1511.         TerminateProcess(ChldProc,1);
  1512.     }
  1513.     return(TRUE);
  1514. }
  1515. /*************************************************************/
  1516.  
  1517. DWORD   LocalSession(PVOID noarg)
  1518. {
  1519.     //Local is ClientList[0]
  1520.     char *name=(char *)ClientList[0].Name;
  1521.  
  1522.     strcpy(name,LOCALNAME);
  1523.     if ((ClientList[0].rSaveFile=CreateFile(SaveFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL))==NULL)
  1524.     {
  1525.         WRITEF((VBuff,"Remote:Cannot open ReadHandle to Savefile:%d\n",GetLastError()));
  1526.         ClientList[0].Active=FALSE;
  1527.         return(1);
  1528.  
  1529.     }
  1530.  
  1531.     ClientList[0].PipeReadH=GetStdHandle(STD_INPUT_HANDLE);
  1532.     ClientList[0].PipeWriteH=GetStdHandle(STD_OUTPUT_HANDLE);
  1533.     ClientList[0].SendOutput=TRUE;
  1534.     ClientList[0].Active=TRUE;
  1535.     NewSession(&ClientList[0]);
  1536.     CloseClient(&ClientList[0]);
  1537.     return(0);
  1538. }
  1539.  
  1540. VOID
  1541. CloseClient(
  1542.     SESSION_TYPE *Client
  1543.     )
  1544. {
  1545.     ZeroMemory(Client->Name,HOSTNAMELEN);
  1546.  
  1547.     if (Client->PipeReadH!=INVALID_HANDLE_VALUE)
  1548.     {
  1549.         CloseHandle(Client->PipeReadH);
  1550.         Client->PipeReadH=INVALID_HANDLE_VALUE;
  1551.     }
  1552.  
  1553.     if (Client->PipeWriteH!=INVALID_HANDLE_VALUE)
  1554.     {
  1555.         CloseHandle(Client->PipeWriteH);
  1556.         Client->PipeWriteH=INVALID_HANDLE_VALUE;
  1557.     }
  1558.  
  1559.     if (Client->rSaveFile!=INVALID_HANDLE_VALUE)
  1560.     {
  1561.         CloseHandle(Client->rSaveFile);
  1562.         Client->rSaveFile=INVALID_HANDLE_VALUE;
  1563.     }
  1564.     if (Client->MoreData!=NULL)
  1565.     {
  1566.         CloseHandle(Client->MoreData);
  1567.         Client->MoreData=NULL;
  1568.     }
  1569.  
  1570.     Client->Active=FALSE; //Keep it last else synch problem.
  1571.     return;
  1572. }
  1573.  
  1574. VOID
  1575. InitClientList(
  1576.     )
  1577. {
  1578.     int i;
  1579.     for (i=0;i<MAX_SESSION;i++)
  1580.     {
  1581.         ZeroMemory(ClientList[i].Name,HOSTNAMELEN);
  1582.         ClientList[i].PipeReadH=INVALID_HANDLE_VALUE;
  1583.         ClientList[i].PipeWriteH=INVALID_HANDLE_VALUE;
  1584.         ClientList[i].rSaveFile=INVALID_HANDLE_VALUE;
  1585.         ClientList[i].MoreData=NULL;
  1586.         ClientList[i].Active=FALSE;
  1587.         ClientList[i].CommandRcvd=FALSE;
  1588.         ClientList[i].SendOutput=FALSE;
  1589.         ClientList[i].hThread=NULL;
  1590.     }
  1591.     return;
  1592. }
  1593.  
  1594.  
  1595.  
  1596. VOID
  1597. RemoveInpMark(
  1598.     char* Buff,
  1599.     DWORD Size
  1600.     )
  1601.  
  1602. {
  1603.     DWORD i;
  1604.     for (i=0;i<Size;i++)
  1605.     {
  1606.         switch (Buff[i])
  1607.         {
  1608.         case BEGINMARK:
  1609.             Buff[i]=' ';
  1610.             break;
  1611.  
  1612.         case ENDMARK:
  1613.             if (i<2)
  1614.             {
  1615.                 Buff[i]= ' ';
  1616.             }
  1617.             else
  1618.             {
  1619.                 Buff[i]  =Buff[i-1];
  1620.                 Buff[i-1]=Buff[i-2];
  1621.                 Buff[i-2]=' ';
  1622.             }
  1623.             break;
  1624.  
  1625.         default:
  1626.            break;
  1627.        }
  1628.     }
  1629. }
  1630.