Annotation of mstools/samples/sdktools/rshell/client/rcmd.c, revision 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.