|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.