CLIENT.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:17k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples. 
  3. *       Copyright 1992 - 1997 Microsoft Corporation.
  4. *       All rights reserved. 
  5. *       This source code is only intended as a supplement to 
  6. *       Microsoft Development Tools and/or WinHelp documentation.
  7. *       See these sources for detailed information regarding the 
  8. *       Microsoft samples programs.
  9. ******************************************************************************/
  10. /*++
  11. Copyright 1992 - 1997 Microsoft Corporation
  12. Module Name:
  13.     Client.c
  14. Abstract:
  15.     The Client component of Remote. Connects to the remote
  16.     server using named pipes. It sends its stdin to
  17.     the server and output everything from server to
  18.     its stdout.
  19. Author:
  20.     Rajivendra Nath  2-Jan-1992
  21.     Dave Hart        Summer 1997   single-pipe operation
  22. Environment:
  23.     Console App. User mode.
  24. Revision History:
  25. --*/
  26. #include <windows.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <process.h>
  30. #include <io.h>
  31. #include <string.h>
  32. #include "Remote.h"
  33. BOOL fAsyncPipe = TRUE;    // need this so server has it TRUE
  34. HANDLE*
  35. EstablishSession(
  36.     char *server,
  37.     char *pipe
  38.     );
  39. DWORD
  40. WINAPI
  41. SendServerInp(
  42.     LPVOID pvParam
  43.     );
  44. BOOL
  45. FilterClientInp(
  46.     char *buff,
  47.     int count
  48.     );
  49. BOOL
  50. Mych(
  51.     DWORD ctrlT
  52.     );
  53. VOID
  54. SendMyInfo(
  55.     PHANDLE Pipes
  56.     );
  57. HANDLE MyStdInp;
  58. HANDLE MyStdOut;
  59. //
  60. // ReadPipe and WritePipe are referenced by multiple
  61. // threads so need to be volatile.
  62. //
  63. volatile HANDLE ReadPipe;
  64. volatile HANDLE WritePipe;
  65. CONSOLE_SCREEN_BUFFER_INFO csbi;
  66. char   MyEchoStr[30];
  67. BOOL   CmdSent;
  68. DWORD  LinesToSend=LINESTOSEND;
  69. VOID
  70. Client(
  71.     char* Server,
  72.     char* Pipe
  73.     )
  74. {
  75.     HANDLE *Connection;
  76.     DWORD  dwThreadID;
  77.     HANDLE hThread;
  78.     DWORD  cb;
  79.     OVERLAPPED ol;
  80.     char   rgchBuf[1024];
  81.     MyStdInp=GetStdHandle(STD_INPUT_HANDLE);
  82.     MyStdOut=GetStdHandle(STD_OUTPUT_HANDLE);
  83.     printf("**************************************n");
  84.     printf("***********     REMOTE    ************n");
  85.     printf("***********     CLIENT    ************n");
  86.     printf("**************************************n");
  87.     if ((Connection=EstablishSession(Server,Pipe))==NULL)
  88.         return;
  89.     ReadPipe=Connection[0];
  90.     WritePipe=Connection[1];
  91.     SetConsoleCtrlHandler((PHANDLER_ROUTINE)Mych,TRUE);
  92.     // Start Thread For Client --> Server Flow
  93.     hThread = (HANDLE)
  94.         _beginthreadex(
  95.             NULL,             // security
  96.             0,                // default stack size
  97.             SendServerInp,    // thread proc
  98.             NULL,             // parm
  99.             0,                // not suspended
  100.             &dwThreadID
  101.             );
  102.     if ( ! hThread)
  103.     {
  104.         Errormsg("REMOTE /C Could Not Create Thread.");
  105.         return;
  106.     }
  107.     ZeroMemory(&ol, sizeof(ol));
  108.     ol.hEvent =
  109.         CreateEvent(
  110.             NULL,      // security
  111.             TRUE,      // auto-reset
  112.             FALSE,     // initially nonsignaled
  113.             NULL       // unnamed
  114.             );
  115.     while (ReadFileSynch(ReadPipe, rgchBuf, sizeof rgchBuf, &cb, 0, &ol)) {
  116.         if (cb) {
  117.            if ( ! WriteFile(MyStdOut, rgchBuf, cb, &cb, NULL)) {
  118.                break;
  119.            }
  120.         }
  121.     }
  122.     CloseHandle(ol.hEvent);
  123.     printf("*** SESSION OVER ***");
  124.     fflush(stdout);
  125.     //
  126.     // Terminate the keyboard reading thread.
  127.     //
  128.     TerminateThread(hThread, 0);
  129.     CloseHandle(hThread);
  130.     CloseClientPipes();
  131.     printf("n");
  132.     fflush(stdout);
  133. }
  134. DWORD
  135. WINAPI
  136. SendServerInp(
  137.     LPVOID pvParam
  138.     )
  139. {
  140.     DWORD  dread,dwrote;
  141.     OVERLAPPED ol;
  142.     char buff[512];
  143.     UNREFERENCED_PARAMETER(pvParam);
  144.     ZeroMemory(&ol, sizeof(ol));
  145.     ol.hEvent =
  146.         CreateEvent(
  147.             NULL,      // security
  148.             TRUE,      // auto-reset
  149.             FALSE,     // initially nonsignaled
  150.             NULL       // unnamed
  151.             );
  152.     while(ReadFile(MyStdInp,buff,sizeof buff,&dread,NULL))
  153.     {
  154.         if (FilterClientInp(buff,dread))
  155.             continue;
  156.         if (!WriteFileSynch(WritePipe,buff,dread,&dwrote,0,&ol))
  157.             break;
  158.     }
  159.     return 0;
  160. }
  161. BOOL
  162. FilterClientInp(
  163.     char *buff,
  164.     int count
  165.     )
  166. {
  167.     if (count==0)
  168.         return(TRUE);
  169.     if (buff[0]==2)     // Adhoc screening of ^B so that i386kd/mipskd
  170.         return(TRUE);   // do not terminate.
  171.     if (buff[0]==COMMANDCHAR)
  172.     {
  173.         switch (buff[1])
  174.         {
  175.         case 'k':
  176.         case 'K':
  177.         case 'q':
  178.         case 'Q':
  179.               CloseClientPipes();
  180.               return(FALSE);
  181.         case 'h':
  182.         case 'H':
  183.               printf("%cM : Send Messagen",COMMANDCHAR);
  184.               printf("%cP : Show Popup on Servern",COMMANDCHAR);
  185.               printf("%cS : Status of Servern",COMMANDCHAR);
  186.               printf("%cQ : Quit clientn",COMMANDCHAR);
  187.               printf("%cH : This Helpn",COMMANDCHAR);
  188.               return(TRUE);
  189.         default:
  190.               return(FALSE);
  191.         }
  192.     }
  193.     return(FALSE);
  194. }
  195. BOOL
  196. Mych(
  197.    DWORD ctrlT
  198.    )
  199. {
  200.     char  c[2];
  201.     DWORD tmp;
  202.     OVERLAPPED ol;
  203.     c[0]=CTRLC;
  204.     if (ctrlT==CTRL_C_EVENT)
  205.     {
  206.         ZeroMemory(&ol, sizeof(ol));
  207.         ol.hEvent =
  208.             CreateEvent(
  209.                 NULL,      // security
  210.                 TRUE,      // auto-reset
  211.                 FALSE,     // initially nonsignaled
  212.                 NULL       // unnamed
  213.                 );
  214.         if (INVALID_HANDLE_VALUE != WritePipe &&
  215.             !WriteFileSynch(WritePipe,c,1,&tmp,0,&ol))
  216.         {
  217.             CloseHandle(ol.hEvent);
  218.             Errormsg("Error Sending ^c");
  219.             return(FALSE);
  220.         }
  221.         CloseHandle(ol.hEvent);
  222.         return(TRUE);
  223.     }
  224.     if ((ctrlT==CTRL_BREAK_EVENT)||
  225.         (ctrlT==CTRL_CLOSE_EVENT)||
  226.         (ctrlT==CTRL_LOGOFF_EVENT)||
  227.         (ctrlT==CTRL_SHUTDOWN_EVENT)
  228.        ) {
  229.        CloseClientPipes();
  230.     }
  231.     return(FALSE);
  232. }
  233. VOID
  234. CloseClientPipes(
  235.     VOID
  236.     )
  237. {
  238.     HANDLE WriteHandle, ReadHandle;
  239.     WriteHandle = (HANDLE) InterlockedExchange(
  240.         (LPLONG) &WritePipe,
  241.         (LONG)   INVALID_HANDLE_VALUE
  242.         );
  243.     if (INVALID_HANDLE_VALUE != WriteHandle) {
  244.         CloseHandle(WriteHandle);
  245.         ReadHandle = (HANDLE) InterlockedExchange(
  246.             (LPLONG) &ReadPipe,
  247.             (LONG)   INVALID_HANDLE_VALUE
  248.             );
  249.         if (INVALID_HANDLE_VALUE != ReadHandle &&
  250.             WriteHandle != ReadHandle) {
  251.             CloseHandle(ReadHandle);
  252.         }
  253.     }
  254. }
  255. VOID
  256. HandleConnectError(
  257.     char *server,
  258.     char *srvpipename
  259.     )
  260. {
  261.     DWORD Err = GetLastError();
  262.     char  msg[128];
  263.     Errormsg("*** Unable to Connect ***");
  264.     //
  265.     // Print a helpful message
  266.     //
  267.     switch(Err)
  268.     {
  269.         case ERROR_FILE_NOT_FOUND:
  270.             sprintf(msg,"invalid pipe name %s", srvpipename);
  271.             break;
  272.         case ERROR_BAD_NETPATH:
  273.             sprintf(msg,"\\%s not found", server);
  274.             break;
  275.         default:
  276.             FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|
  277.                            FORMAT_MESSAGE_IGNORE_INSERTS,
  278.                            NULL, Err, 0, msg, sizeof(msg), NULL);
  279.             break;
  280.     }
  281.     printf("Diagnosis: %sn",msg);
  282.     //
  283.     // If the machine exists but the pipe doesn't do an
  284.     // automatic remote /q to list pipes available on
  285.     // that machine.
  286.     //
  287.     if (ERROR_FILE_NOT_FOUND == Err) {
  288.         printf("nREMOTE /Q %sn", server);
  289.         fflush(stdout);
  290.         QueryRemotePipes(server);
  291.     }
  292. }
  293. HANDLE*
  294. EstablishSession(
  295.     char *server,
  296.     char *srvpipename
  297.     )
  298. {
  299.     extern BOOL bForceTwoPipes;
  300.     static HANDLE PipeH[2];
  301.     char   pipenameSrvIn[200];
  302.     char   pipenameSrvOut[200];
  303.     BOOL   fOldServer;
  304.     DWORD  dwError;
  305.     DWORD  RetryCount = 0;
  306.     //
  307.     // Since in single-pipe operation we'll be using the same
  308.     // pipe in two threads, we have to open the handles for
  309.     // overlapped operation, even though we always want
  310.     // synchronous operation.
  311.     //
  312.     sprintf(pipenameSrvIn ,SERVER_READ_PIPE ,server,srvpipename);
  313.     sprintf(pipenameSrvOut,SERVER_WRITE_PIPE,server,srvpipename);
  314.     if (bForceTwoPipes) {
  315.         dwError = ERROR_NOT_SUPPORTED;
  316.     } else {
  317.       RetrySrvBidi:
  318.         if (INVALID_HANDLE_VALUE ==
  319.                (PipeH[1] =
  320.                     CreateFile(
  321.                         pipenameSrvIn,
  322.                         GENERIC_READ | GENERIC_WRITE,
  323.                         0,
  324.                         NULL,
  325.                         OPEN_EXISTING,
  326.                         FILE_FLAG_OVERLAPPED,
  327.                         NULL
  328.                         ))) {
  329.             dwError = GetLastError();
  330.             if (ERROR_PIPE_BUSY == dwError) {
  331.                 printf( "All pipe instances busy, waiting for another...n");
  332.                 WaitNamedPipe(
  333.                     pipenameSrvIn,
  334.                     15000
  335.                     );
  336.                 if (RetryCount++ < 6) {
  337.                     goto RetrySrvBidi;
  338.                 }
  339.             }
  340.             if (ERROR_ACCESS_DENIED != dwError &&
  341.                 ERROR_NOT_SUPPORTED != dwError) {
  342.                 HandleConnectError(server, srvpipename);
  343.                 return NULL;
  344.             }
  345.         } else {
  346.             PipeH[0] = PipeH[1];
  347.             fAsyncPipe = TRUE;
  348.             printf("Connected...nn");
  349.             SendMyInfo(PipeH);
  350.             return PipeH;
  351.         }
  352.     }
  353.     //
  354.     // Old remote servers don't allow you to open the
  355.     // server IN pipe for READ access, so go down the
  356.     // old path, notably opening OUT first so the
  357.     // server knows we'll be using both pipes.  We'll
  358.     // also come down this path on Win95 because
  359.     // it doesn't allow you to open an overlapped
  360.     // pipe handle.  Or if remote /c mach pipe /2 is used.
  361.     //
  362.     fOldServer = (ERROR_ACCESS_DENIED == dwError);
  363.   RetrySrvOut:
  364.     if (INVALID_HANDLE_VALUE ==
  365.             (PipeH[0] =
  366.                 CreateFile(
  367.                     pipenameSrvOut,
  368.                     GENERIC_READ,
  369.                     0,
  370.                     NULL,
  371.                     OPEN_EXISTING,
  372.                     0,
  373.                     NULL
  374.                     ))) {
  375.         if (ERROR_PIPE_BUSY == GetLastError()) {
  376.             printf( "All OUT pipe instances busy, waiting for another...n");
  377.             WaitNamedPipe(
  378.                 pipenameSrvOut,
  379.                 32000              // server recycles abandoned
  380.                 );                 // OUT pipe after two minutes
  381.             if (RetryCount++ < 6) {
  382.                 goto RetrySrvOut;
  383.             }
  384.         }
  385.         HandleConnectError(server, srvpipename);
  386.         return NULL;
  387.     }
  388.   RetrySrvIn:
  389.     if (INVALID_HANDLE_VALUE ==
  390.            (PipeH[1] =
  391.                CreateFile(
  392.                     pipenameSrvIn,
  393.                     GENERIC_WRITE,
  394.                     0,
  395.                     NULL,
  396.                     OPEN_EXISTING,
  397.                     0,
  398.                     NULL
  399.                     ))) {
  400.         dwError = GetLastError();
  401.         if (ERROR_PIPE_BUSY == dwError) {
  402.             printf( "All IN pipe instances busy, waiting for another...n");
  403.             WaitNamedPipe(
  404.                 pipenameSrvIn,
  405.                 15000
  406.                 );
  407.             if (RetryCount++ < 6) {
  408.                 goto RetrySrvIn;
  409.            }
  410.         }
  411.         HandleConnectError(server, srvpipename);
  412.         return NULL;
  413.     }
  414.     fAsyncPipe = FALSE;
  415.     printf("Connected... %snn",
  416.            fOldServer
  417.                ? "to two-pipe remote server."
  418.                : "using two pipes."
  419.            );
  420.     SendMyInfo(PipeH);
  421.     return PipeH;
  422. }
  423. VOID
  424. SendMyInfo(
  425.     PHANDLE pipeH
  426.     )
  427. {
  428.     HANDLE rPipe=pipeH[0];
  429.     HANDLE wPipe=pipeH[1];
  430.     DWORD  hostlen;
  431.     WORD   BytesToSend=sizeof(SESSION_STARTUPINFO);
  432.     DWORD  tmp;
  433.     OVERLAPPED ol;
  434.     SESSION_STARTUPINFO ssi;
  435.     SESSION_STARTREPLY  ssr;
  436.     ol.hEvent =
  437.         CreateEvent(
  438.             NULL,      // security
  439.             TRUE,      // auto-reset
  440.             FALSE,     // initially nonsignaled
  441.             NULL       // unnamed
  442.             );
  443.     ssi.Size=BytesToSend;
  444.     ssi.Version=VERSION;
  445.     hostlen = sizeof(ssi.ClientName) / sizeof(ssi.ClientName[0]);
  446.     GetComputerName(ssi.ClientName, &hostlen);
  447.     ssi.LinesToSend=LinesToSend;
  448.     ssi.Flag=ClientToServerFlag;
  449.     {
  450.         DWORD NewCode=MAGICNUMBER;
  451.         char  Name[MAX_COMPUTERNAME_LENGTH+1];
  452.         strcpy(Name,(char *)ssi.ClientName);
  453.         memcpy(&Name[11],(char *)&NewCode,sizeof(NewCode));
  454.         //
  455.         // The server needs to know if we're doing single-pipe
  456.         // operation so it can complete the connection properly.
  457.         // So if we are, change the first byte of the first
  458.         // send (the computername, which is later superceded
  459.         // by the one in the SESSION_STARTUPINFO structure)
  460.         // to an illegal computername character, question mark.
  461.         //
  462.         if (wPipe == rPipe) {
  463.              Name[0] = '?';
  464.         }
  465.         WriteFileSynch(wPipe,(char *)Name,HOSTNAMELEN-1,&tmp,0,&ol);
  466.         ReadFileSynch(rPipe ,(char *)&ssr.MagicNumber,sizeof(ssr.MagicNumber),&tmp,0,&ol);
  467.         if (ssr.MagicNumber!=MAGICNUMBER)
  468.         {
  469.             SetLastError(ERROR_INVALID_PARAMETER);
  470.             ErrorExit("Pipe connected but server not recognized.n");
  471.         }
  472.         //Get Rest of the info-its not the old server
  473.         ReadFileSynch(
  474.             rPipe,
  475.             (char *)&ssr + sizeof(ssr.MagicNumber),
  476.             sizeof(ssr)-sizeof(ssr.MagicNumber),
  477.             &tmp,
  478.             0,
  479.             &ol
  480.             );
  481.     }
  482.     if (!WriteFileSynch(wPipe,(char *)&ssi,BytesToSend,&tmp,0,&ol))
  483.     {
  484.        Errormsg("INFO Send Error");
  485.     }
  486.     CloseHandle(ol.hEvent);
  487. }
  488. VOID
  489. QueryRemotePipes(
  490.     char* pszServer
  491.     )
  492. {
  493.     HANDLE hQPipe;
  494.     DWORD  dwRead;
  495.     DWORD  dwError;
  496.     char   fullname[400];
  497.     char*  msg;
  498.     int    msgLen;
  499.     if (pszServer[0] == '\' && pszServer[1] == '\') {
  500.         pszServer += 2;
  501.     }
  502.     printf("Querying server \\%sn", pszServer);
  503.     sprintf(fullname, QUERY_DEBUGGERS_PIPE, pszServer);
  504.         
  505.     //  
  506.     // Send request and display the query result
  507.     //                                                                                
  508.                                                                                    
  509.     hQPipe = CreateFile(fullname,
  510.         GENERIC_READ | GENERIC_WRITE,
  511.         0,
  512.         NULL,
  513.         OPEN_EXISTING,
  514.         FILE_ATTRIBUTE_NORMAL,
  515.         NULL);
  516.     
  517.     if(hQPipe == INVALID_HANDLE_VALUE) {
  518.         dwError = GetLastError();
  519.         if (ERROR_FILE_NOT_FOUND == dwError) {
  520.             printf("No Remote servers running on \\%sn", pszServer);
  521.         } else if (ERROR_BAD_NETPATH == dwError) {
  522.             printf("\\%s not found on the networkn", pszServer);
  523.         } else {
  524.             FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
  525.                            FORMAT_MESSAGE_IGNORE_INSERTS,
  526.                            NULL, dwError, 0,
  527.                            fullname, sizeof(fullname), NULL);
  528.             printf("Can't query server %s: %sn", pszServer, fullname);
  529.         }
  530.         return;
  531.     }                                                                                  
  532.     
  533.     //  Send Query Command
  534.     if(!WriteFile(hQPipe, "q", 1, &dwRead, NULL)
  535.         || (dwRead != 1))
  536.     {
  537.         printf("nError: Can't send commandn");
  538.         goto failure;
  539.     }
  540.     if(!ReadFile(hQPipe, 
  541.              &msgLen,
  542.              sizeof(int),      // read msg dimension
  543.              &dwRead,                                    
  544.              NULL) 
  545.         || (dwRead != sizeof(int)))
  546.     {
  547.         printf("nError: Can't read messagen");
  548.         goto failure;
  549.     }
  550.     if(!msgLen)
  551.     {
  552.         printf("nNo visible sessions on server %s", pszServer);
  553.         goto failure;
  554.     }
  555.     if(msgLen > 65535)        // error
  556.     {
  557.         printf("Error querying server %s, got %d for msg length, 65535 max.n",
  558.                pszServer,
  559.                msgLen
  560.                );
  561.         goto failure;
  562.     }
  563.     
  564.     if((msg = (char*)malloc(msgLen*sizeof(char))) == NULL)
  565.     {
  566.         printf("nOut of memoryn");
  567.         goto failure;    
  568.     }
  569.     ReadFile(hQPipe, 
  570.              msg,
  571.              msgLen * sizeof(char),      // read msg
  572.              &dwRead,                                    
  573.              NULL);                                                                
  574.     printf("nVisible sessions on server %s:nn", pszServer);
  575.     
  576.     printf("%sn", msg);
  577.     free(msg);
  578.  failure:
  579.     CloseHandle(hQPipe);
  580. }