Annotation of mstools/samples/sdktools/rshell/client/rcmd.c, revision 1.1.1.1

1.1       root        1: /****************************** Module Header ******************************\
                      2: * Module Name: rsh.c
                      3: *
                      4: * Copyright (c) 1991, Microsoft Corporation
                      5: *
                      6: * Remote shell NT client main module
                      7: *
                      8: * History:
                      9: * 05-20-92 Davidc       Created.
                     10: \***************************************************************************/
                     11: 
                     12: #define UNICODE
                     13: 
                     14: #include <windows.h>
                     15: 
                     16: #include <stdio.h>
                     17: #include <stdarg.h>
                     18: #include <assert.h>
                     19: 
                     20: #define PIPE_NAME   TEXT("%hs\\pipe\\rshell")
                     21: #define BUFFER_SIZE 1000
                     22: 
                     23: 
                     24: // #define DEBUG
                     25: 
                     26: #ifdef DEBUG
                     27: #define Dbgprintf DbgPrint
                     28: #else
                     29: #define Dbgprintf
                     30: #endif
                     31: 
                     32: 
                     33: //
                     34: // The pipe handle is global so we can use it from the
                     35: // Ctrl-C handler routine.
                     36: //
                     37: 
                     38: static HANDLE PipeHandle = NULL;
                     39: 
                     40: 
                     41: 
                     42: //
                     43: // Private prototypes
                     44: //
                     45: 
                     46: DWORD
                     47: ReadThreadProc(
                     48:     LPVOID Parameter
                     49:     );
                     50: 
                     51: DWORD
                     52: WriteThreadProc(
                     53:     LPVOID Parameter
                     54:     );
                     55: 
                     56: BOOL
                     57: CtrlHandler(
                     58:     DWORD CtrlType
                     59:     );
                     60: 
                     61: int Myprintf (
                     62:     const char *format,
                     63:     ...
                     64:     );
                     65: 
                     66: 
                     67: 
                     68: 
                     69: /***************************************************************************\
                     70: * FUNCTION: Main
                     71: *
                     72: * PURPOSE:  Main entry point.
                     73: *
                     74: * RETURNS:  0 on success, 1 on failure
                     75: *
                     76: * HISTORY:
                     77: *
                     78: *   07-10-92 Davidc       Created.
                     79: *
                     80: \***************************************************************************/
                     81: 
                     82: int
                     83: _CRTAPI1 main(
                     84:     int argc,
                     85:     char **argv
                     86:     )
                     87: {
                     88:     SECURITY_ATTRIBUTES SecurityAttributes;
                     89:     HANDLE StdInputHandle;
                     90:     HANDLE StdOutputHandle;
                     91:     HANDLE StdErrorHandle;
                     92:     WCHAR  PipeName[MAX_PATH];
                     93:     LPSTR  ServerName;
                     94:     HANDLE ReadThreadHandle;
                     95:     HANDLE WriteThreadHandle;
                     96:     DWORD ThreadId;
                     97:     HANDLE HandleArray[2];
                     98: 
                     99:     //
                    100:     // Install a handler for Ctrl-C
                    101:     //
                    102: 
                    103:     if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) &CtrlHandler, TRUE)) {
                    104:         Myprintf("Failed to install control-C handler, error = %d\n", GetLastError());
                    105:         return(1);
                    106:     }
                    107: 
                    108: 
                    109:     //
                    110:     // Check usage
                    111:     //
                    112: 
                    113:     if (argc < 2) {
                    114:         Myprintf("Usage: rcmd server_name\n");
                    115:         Myprintf("Note : server name should include leading '\\\\'s\n");
                    116:         return(1);
                    117:     }
                    118: 
                    119: 
                    120:     //
                    121:     // Calculate the pipe name
                    122:     //
                    123: 
                    124:     if (argc > 1) {
                    125:         ServerName = argv[1];
                    126:     } else {
                    127:         ServerName = "\\\\.";
                    128:     }
                    129: 
                    130:     wsprintf(PipeName, PIPE_NAME, ServerName);
                    131: 
                    132: 
                    133:     //
                    134:     // Store away our normal i/o handles
                    135:     //
                    136: 
                    137:     StdInputHandle = GetStdHandle(STD_INPUT_HANDLE);
                    138:     assert(StdInputHandle != (HANDLE)0xffffffff);
                    139:     StdOutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
                    140:     assert(StdOutputHandle != (HANDLE)0xffffffff);
                    141:     StdErrorHandle = GetStdHandle(STD_ERROR_HANDLE);
                    142:     assert(StdErrorHandle != (HANDLE)0xffffffff);
                    143: 
                    144: 
                    145:     //
                    146:     // Open the named pipe
                    147:     //
                    148: 
                    149:     SecurityAttributes.nLength = sizeof(SecurityAttributes);
                    150:     SecurityAttributes.lpSecurityDescriptor = NULL; // Use default SD
                    151:     SecurityAttributes.bInheritHandle = FALSE;
                    152: 
                    153:     PipeHandle = CreateFile( PipeName,
                    154:                              GENERIC_READ | GENERIC_WRITE,
                    155:                              0,                         // No sharing
                    156:                              &SecurityAttributes,
                    157:                              OPEN_EXISTING,
                    158:                              FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                    159:                              NULL                       // Template file
                    160:                            );
                    161: 
                    162:     if (PipeHandle == (HANDLE)0xffffffff ) {
                    163:         Dbgprintf("Failed to open named pipe, error = %d\n", GetLastError());
                    164:         Myprintf("Failed to connect to <%s>, error = %d\n", ServerName, GetLastError());
                    165:         return(1);
                    166:     }
                    167: 
                    168:     Myprintf("Connected to %s\n\n", ServerName);
                    169: 
                    170:     //
                    171:     // Exec 2 threads - 1 copies data from stdin to pipe, the other
                    172:     // copies data from the pipe to stdout.
                    173:     //
                    174: 
                    175:     ReadThreadHandle = CreateThread(
                    176:                         NULL,                       // Default security
                    177:                         0,                          // Default Stack size
                    178:                         (LPTHREAD_START_ROUTINE) ReadThreadProc,
                    179:                         (PVOID)PipeHandle,
                    180:                         0,
                    181:                         &ThreadId);
                    182: 
                    183:     if (ReadThreadHandle == NULL) {
                    184:         Myprintf("Failed to create read thread, error = %ld\n", GetLastError());
                    185:         return(1);
                    186:     }
                    187: 
                    188: 
                    189:     //
                    190:     // Create the write thread
                    191:     //
                    192: 
                    193:     WriteThreadHandle = CreateThread(
                    194:                         NULL,                       // Default security
                    195:                         0,                          // Default Stack size
                    196:                         (LPTHREAD_START_ROUTINE) WriteThreadProc,
                    197:                         (PVOID)PipeHandle,
                    198:                         0,
                    199:                         &ThreadId);
                    200: 
                    201:     if (WriteThreadHandle == NULL) {
                    202:         Myprintf("Failed to create write thread, error = %ld\n", GetLastError());
                    203:         TerminateThread(ReadThreadHandle, 0);
                    204:         CloseHandle(ReadThreadHandle);
                    205:         return(1);
                    206:     }
                    207: 
                    208: 
                    209: 
                    210:     //
                    211:     // Wait for either thread to finish
                    212:     //
                    213: 
                    214:     HandleArray[0] = ReadThreadHandle;
                    215:     HandleArray[1] = WriteThreadHandle;
                    216: 
                    217:     WaitForMultipleObjects(
                    218:                             2,
                    219:                             HandleArray,
                    220:                             FALSE,              // Wait for either to finish
                    221:                             0xffffffff
                    222:                            );                   // Wait forever
                    223: 
                    224:     Dbgprintf("Read or write thread terminated\n");
                    225: 
                    226:     //
                    227:     // Terminate and close both threads
                    228:     //
                    229: 
                    230:     TerminateThread(ReadThreadHandle, 0);
                    231:     CloseHandle(ReadThreadHandle);
                    232:     TerminateThread(WriteThreadHandle, 0);
                    233:     CloseHandle(WriteThreadHandle);
                    234: 
                    235: 
                    236:     //
                    237:     // Close our pipe handle
                    238:     //
                    239: 
                    240:     CloseHandle(PipeHandle);
                    241:     PipeHandle = NULL;
                    242: 
                    243: 
                    244:     Myprintf("\nDisconnected from %s\n", ServerName);
                    245: 
                    246:     return(0);
                    247: }
                    248: 
                    249: 
                    250: /***************************************************************************\
                    251: * FUNCTION: ReadPipe
                    252: *
                    253: * PURPOSE:  Implements an overlapped read such that read and write operations
                    254: *           to the same pipe handle don't deadlock.
                    255: *
                    256: * RETURNS:  TRUE on success, FALSE on failure (GetLastError() has error)
                    257: *
                    258: * HISTORY:
                    259: *
                    260: *   05-27-92 Davidc       Created.
                    261: *
                    262: \***************************************************************************/
                    263: 
                    264: BOOL
                    265: ReadPipe(
                    266:     HANDLE PipeHandle,
                    267:     LPVOID lpBuffer,
                    268:     DWORD nNumberOfBytesToRead,
                    269:     LPDWORD lpNumberOfBytesRead
                    270:     )
                    271: {
                    272:     DWORD Result;
                    273:     OVERLAPPED Overlapped;
                    274:     HANDLE  EventHandle;
                    275:     DWORD Error;
                    276: 
                    277:     //
                    278:     // Create an event for the overlapped operation
                    279:     //
                    280: 
                    281:     EventHandle = CreateEvent(
                    282:                               NULL,         // no security
                    283:                               TRUE,         // Manual reset
                    284:                               FALSE,        // Initial state
                    285:                               NULL          // Name
                    286:                              );
                    287:     if (EventHandle == NULL) {
                    288:         Myprintf("ReadPipe failed to create event, error = %d\n", GetLastError());
                    289:         return(FALSE);
                    290:     }
                    291: 
                    292:     Overlapped.hEvent = EventHandle;
                    293: 
                    294:     Result = ReadFile(
                    295:                       PipeHandle,
                    296:                       lpBuffer,
                    297:                       nNumberOfBytesToRead,
                    298:                       lpNumberOfBytesRead,
                    299:                       &Overlapped
                    300:                      );
                    301:     if (Result) {
                    302: 
                    303:         //
                    304:         // Success without waiting - it's too easy !
                    305:         //
                    306: 
                    307:         CloseHandle(EventHandle);
                    308: 
                    309:     } else {
                    310: 
                    311:         //
                    312:         // Read failed, if it's overlapped io, go wait for it
                    313:         //
                    314: 
                    315:         Error = GetLastError();
                    316: 
                    317:         if (Error != ERROR_IO_PENDING) {
                    318:             Dbgprintf("ReadPipe: ReadFile failed, error = %d\n", Error);
                    319:             CloseHandle(EventHandle);
                    320:             return(FALSE);
                    321:         }
                    322: 
                    323:         //
                    324:         // Wait for the I/O to complete
                    325:         //
                    326: 
                    327:         Result = WaitForSingleObject(EventHandle, (DWORD)-1);
                    328:         if (Result != 0) {
                    329:             Dbgprintf("ReadPipe: event wait failed, result = %d, last error = %d\n", Result, GetLastError());
                    330:             CloseHandle(EventHandle);
                    331:             return(FALSE);
                    332:         }
                    333: 
                    334:         //
                    335:         // Go get the I/O result
                    336:         //
                    337: 
                    338:         Result = GetOverlappedResult( PipeHandle,
                    339:                                       &Overlapped,
                    340:                                       lpNumberOfBytesRead,
                    341:                                       FALSE
                    342:                                     );
                    343:         //
                    344:         // We're finished with the event handle
                    345:         //
                    346: 
                    347:         CloseHandle(EventHandle);
                    348: 
                    349:         //
                    350:         // Check result of GetOverlappedResult
                    351:         //
                    352: 
                    353:         if (!Result) {
                    354:             Dbgprintf("ReadPipe: GetOverlappedResult failed, error = %d\n", GetLastError());
                    355:             return(FALSE);
                    356:         }
                    357:     }
                    358: 
                    359:     return(TRUE);
                    360: }
                    361: 
                    362: 
                    363: /***************************************************************************\
                    364: * FUNCTION: WritePipe
                    365: *
                    366: * PURPOSE:  Implements an overlapped write such that read and write operations
                    367: *           to the same pipe handle don't deadlock.
                    368: *
                    369: * RETURNS:  TRUE on success, FALSE on failure (GetLastError() has error)
                    370: *
                    371: * HISTORY:
                    372: *
                    373: *   05-27-92 Davidc       Created.
                    374: *
                    375: \***************************************************************************/
                    376: 
                    377: BOOL
                    378: WritePipe(
                    379:     HANDLE PipeHandle,
                    380:     CONST VOID *lpBuffer,
                    381:     DWORD nNumberOfBytesToWrite,
                    382:     LPDWORD lpNumberOfBytesWritten
                    383:     )
                    384: {
                    385:     DWORD Result;
                    386:     OVERLAPPED Overlapped;
                    387:     HANDLE  EventHandle;
                    388:     DWORD Error;
                    389: 
                    390:     //
                    391:     // Create an event for the overlapped operation
                    392:     //
                    393: 
                    394:     EventHandle = CreateEvent(
                    395:                               NULL,         // no security
                    396:                               TRUE,         // Manual reset
                    397:                               FALSE,        // Initial state
                    398:                               NULL          // Name
                    399:                              );
                    400:     if (EventHandle == NULL) {
                    401:         Myprintf("WritePipe failed to create event, error = %d\n", GetLastError());
                    402:         return(FALSE);
                    403:     }
                    404: 
                    405:     Overlapped.hEvent = EventHandle;
                    406: 
                    407:     Result = WriteFile(
                    408:                       PipeHandle,
                    409:                       lpBuffer,
                    410:                       nNumberOfBytesToWrite,
                    411:                       lpNumberOfBytesWritten,
                    412:                       &Overlapped
                    413:                      );
                    414:     if (Result) {
                    415: 
                    416:         //
                    417:         // Success without waiting - it's too easy !
                    418:         //
                    419: 
                    420:         CloseHandle(EventHandle);
                    421: 
                    422:     } else {
                    423: 
                    424:         //
                    425:         // Write failed, if it's overlapped io, go wait for it
                    426:         //
                    427: 
                    428:         Error = GetLastError();
                    429: 
                    430:         if (Error != ERROR_IO_PENDING) {
                    431:             Dbgprintf("WritePipe: WriteFile failed, error = %d\n", Error);
                    432:             CloseHandle(EventHandle);
                    433:             return(FALSE);
                    434:         }
                    435: 
                    436:         //
                    437:         // Wait for the I/O to complete
                    438:         //
                    439: 
                    440:         Result = WaitForSingleObject(EventHandle, (DWORD)-1);
                    441:         if (Result != 0) {
                    442:             Dbgprintf("WritePipe: event wait failed, result = %d, last error = %d\n", Result, GetLastError());
                    443:             CloseHandle(EventHandle);
                    444:             return(FALSE);
                    445:         }
                    446: 
                    447:         //
                    448:         // Go get the I/O result
                    449:         //
                    450: 
                    451:         Result = GetOverlappedResult( PipeHandle,
                    452:                                       &Overlapped,
                    453:                                       lpNumberOfBytesWritten,
                    454:                                       FALSE
                    455:                                     );
                    456:         //
                    457:         // We're finished with the event handle
                    458:         //
                    459: 
                    460:         CloseHandle(EventHandle);
                    461: 
                    462:         //
                    463:         // Check result of GetOverlappedResult
                    464:         //
                    465: 
                    466:         if (!Result) {
                    467:             Dbgprintf("WritePipe: GetOverlappedResult failed, error = %d\n", GetLastError());
                    468:             return(FALSE);
                    469:         }
                    470:     }
                    471: 
                    472:     return(TRUE);
                    473: }
                    474: 
                    475: 
                    476: /***************************************************************************\
                    477: * FUNCTION: ReadThreadProc
                    478: *
                    479: * PURPOSE:  The read thread procedure. Reads from pipe and writes to STD_OUT
                    480: *
                    481: * RETURNS:  Nothing
                    482: *
                    483: * HISTORY:
                    484: *
                    485: *   05-21-92 Davidc       Created.
                    486: *
                    487: \***************************************************************************/
                    488: 
                    489: DWORD
                    490: ReadThreadProc(
                    491:     LPVOID Parameter
                    492:     )
                    493: {
                    494:     HANDLE  PipeHandle = Parameter;
                    495:     BYTE    Buffer[BUFFER_SIZE];
                    496:     DWORD   BytesRead;
                    497:     DWORD   BytesWritten;
                    498: 
                    499:     while (ReadPipe(
                    500:                     PipeHandle,
                    501:                     Buffer,
                    502:                     sizeof(Buffer),
                    503:                     &BytesRead
                    504:                    )) {
                    505: 
                    506:         if (!WriteFile(
                    507:                     (HANDLE)STD_OUTPUT_HANDLE,
                    508:                     Buffer,
                    509:                     BytesRead,
                    510:                     &BytesWritten,
                    511:                     NULL
                    512:                  )) {
                    513: 
                    514:             Dbgprintf("ReadThreadProc, writefile failed\n");
                    515:             Myprintf("ReadThreadProc, writefile failed\n");
                    516:             break;
                    517:         }
                    518:     }
                    519: 
                    520:     Dbgprintf("ReadThreadProc exitted, error = %ld\n", GetLastError());
                    521: 
                    522:     ExitThread((DWORD)0);
                    523: 
                    524:     assert(FALSE); // Should never get here
                    525: 
                    526:     return(0);
                    527: }
                    528: 
                    529: 
                    530: /***************************************************************************\
                    531: * FUNCTION: WriteThreadProc
                    532: *
                    533: * PURPOSE:  The write thread procedure. Reads from STD_INPUT and writes to pipe
                    534: *
                    535: * RETURNS:  Nothing
                    536: *
                    537: * HISTORY:
                    538: *
                    539: *   05-21-92 Davidc       Created.
                    540: *
                    541: \***************************************************************************/
                    542: 
                    543: DWORD
                    544: WriteThreadProc(
                    545:     LPVOID Parameter
                    546:     )
                    547: {
                    548:     HANDLE PipeHandle = Parameter;
                    549:     BYTE    Buffer[BUFFER_SIZE];
                    550:     DWORD   BytesRead;
                    551:     DWORD   BytesWritten;
                    552: 
                    553:     while (ReadFile(
                    554:                     (HANDLE)STD_INPUT_HANDLE,
                    555:                     Buffer,
                    556:                     sizeof(Buffer),
                    557:                     &BytesRead,
                    558:                     NULL
                    559:                    )) {
                    560: 
                    561:         if (!WritePipe(
                    562:                     PipeHandle,
                    563:                     Buffer,
                    564:                     BytesRead,
                    565:                     &BytesWritten
                    566:                  )) {
                    567:             Dbgprintf("WriteThreadProc, writefile failed\n");
                    568:             break;
                    569:         }
                    570:     }
                    571: 
                    572:     Dbgprintf("WriteThreadProc exitted, error = %ld\n", GetLastError());
                    573: 
                    574:     ExitThread((DWORD)0);
                    575: 
                    576:     assert(FALSE); // Should never get here
                    577: 
                    578:     return(0);
                    579: }
                    580: 
                    581: 
                    582: /***************************************************************************\
                    583: * FUNCTION: CtrlHandler
                    584: *
                    585: * PURPOSE:  Handles console event notifications.
                    586: *
                    587: * RETURNS:  TRUE if the event has been handled, otherwise FALSE.
                    588: *
                    589: * HISTORY:
                    590: *
                    591: *   05-21-92 Davidc       Created.
                    592: *
                    593: \***************************************************************************/
                    594: 
                    595: BOOL
                    596: CtrlHandler(
                    597:     DWORD CtrlType
                    598:     )
                    599: {
                    600:     //
                    601:     // We'll handle Ctrl-C events
                    602:     //
                    603: 
                    604:     if (CtrlType == CTRL_C_EVENT) {
                    605: 
                    606:         if (PipeHandle != NULL) {
                    607: 
                    608:             //
                    609:             // Send a Ctrl-C to the server, don't care if it fails
                    610:             //
                    611: 
                    612:             CHAR    CtrlC = '\003';
                    613:             DWORD   BytesWritten;
                    614: 
                    615:             WriteFile(PipeHandle,
                    616:                       &CtrlC,
                    617:                       sizeof(CtrlC),
                    618:                       &BytesWritten,
                    619:                       NULL
                    620:                      );
                    621:         }
                    622: 
                    623:         //
                    624:         // We handled the event
                    625:         //
                    626: 
                    627:         return(TRUE);
                    628:     }
                    629: 
                    630:     //
                    631:     // Deal with all other events as normal
                    632:     //
                    633: 
                    634:     return (FALSE);
                    635: }
                    636: 
                    637: 
                    638: /***************************************************************************\
                    639: * FUNCTION: MyPrintf
                    640: *
                    641: * PURPOSE:  Printf that uses low-level io.
                    642: *
                    643: * HISTORY:
                    644: *
                    645: *   07-15-92 Davidc       Created.
                    646: *
                    647: \***************************************************************************/
                    648: 
                    649: int Myprintf (
                    650:     const char *format,
                    651:     ...
                    652:     )
                    653: {
                    654:     CHAR Buffer[MAX_PATH];
                    655:     va_list argpointer;
                    656:     int Result;
                    657:     DWORD BytesWritten;
                    658: 
                    659:     va_start(argpointer, format);
                    660: 
                    661:     Result = vsprintf(Buffer, format, argpointer);
                    662: 
                    663:     if (!WriteFile((HANDLE)STD_OUTPUT_HANDLE, Buffer, Result, &BytesWritten, NULL)) {
                    664:         Dbgprintf("Myprintf : Write file to stdout failed, error = %d\n", GetLastError());
                    665:         Result = 0;
                    666:     }
                    667: 
                    668:     va_end(argpointer);
                    669: 
                    670:     return(Result);
                    671: }
                    672: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.