|
|
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.