|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1992 Microsoft Corporation
4:
5: Module Name:
6:
7: Server.c
8:
9: Abstract:
10:
11: The server component of Remote. It spawns a child process
12: and redirects the stdin/stdout/stderr of child to itself.
13: Waits for connections from clients - passing the
14: output of child process to client and the input from clients
15: to child process.
16:
17: Author:
18:
19: Rajivendra Nath (rajnath) 2-Jan-1992
20:
21: Environment:
22:
23: Console App. User mode.
24:
25: Revision History:
26:
27: --*/
28:
29: #include <windows.h>
30: #include <stdio.h>
31: #include <stdlib.h>
32: #include <io.h>
33: #include <string.h>
34: #include "Remote.h"
35:
36: #define MAX_SESSION 10
37:
38: #define COMMANDFORMAT "%c%-15s [%-15s %d:%d]\n%c"
39: #define LOCALNAME "Local"
40: #define LOCALCLIENT(x) (strcmp((char *)(x->Name),LOCALNAME)==0)
41: #define RemoteInfo(prt,flg) {if (!(flg&&0x80000000)) prt;}
42:
43: #define CMDSTRING(OutBuff,InpBuff,Client,sTime) \
44: { \
45: /* int xxlen; */ \
46: sprintf \
47: ( \
48: &OutBuff[0],COMMANDFORMAT,\
49: BEGINMARK,InpBuff, \
50: Client->Name,sTime.wHour, \
51: sTime.wMinute,ENDMARK \
52: ); \
53: } \
54:
55: #define BUFFSIZE 256
56:
57: SESSION_TYPE ClientList[MAX_SESSION];
58:
59: HANDLE ChildStdInp; //Server Writes to it
60: HANDLE ChildStdOut; //Server Reads from it
61: HANDLE ChildStdErr; //Server Reads from it
62:
63: HANDLE SaveFile; //File containing all that was
64: //output by child process.
65: //Each connection opens a handle to this file
66: //and is sent through PipeWriteH.
67:
68: char SaveFileName[64]; //Name of above file - all new sessions need
69: HANDLE ChldProc; //Handle to the Child Process
70: HANDLE ListenThreadH; //Handle to the thread listening for connections
71: //from Remote Clients.
72:
73: HANDLE
74: ForkChildProcess( // Creates a new process
75: char *cmd, // Redirects its stdin,stdout
76: PHANDLE in, // and stderr - returns the
77: PHANDLE out, // corresponding pipe ends. Using currently
78: PHANDLE err
79: );
80:
81: HANDLE
82: OldForkChildProcess( //Same as above except different
83: char *cmd, //method for redirection. Not Used.
84: PHANDLE in,
85: PHANDLE out,
86: PHANDLE err
87: );
88:
89: DWORD
90: ListenForSession( //THREAD:Listens for new connections and
91: char* pipe //spawns of new seesions - Updates the
92: ); //Status in Client DataStructure. Seperate Thread.
93:
94: DWORD
95: NewSession( //Manages the session with a client.
96: SESSION_TYPE* Client
97: );
98:
99: DWORD //2 THREAD:Each reads either
100: GetChldOutput( //StdOut or StdErr of child and
101: HANDLE rhandle //writes to SaveFile. Seperate Thread.
102: );
103:
104: DWORD
105: TransferFileToClient( //X THREADS:Reads the save
106: SESSION_TYPE* Client //file and sendsoutput to a client. Seperate Thread
107: );
108:
109:
110: DWORD
111: GetClientInput( //Times X THREADS:Gets input from Child pipe
112: SESSION_TYPE* Client //and sends to childs StdIn. Seperate Thread.
113: );
114:
115:
116: BOOL
117: FilterCommand( //Filters input from client
118: SESSION_TYPE *cl, //for commands intended for REMOTE
119: char *buff,
120: int dread
121: );
122:
123: DWORD // Manages the IO with user
124: LocalSession( // For the remote server. Seperate Thread.
125: PVOID noarg
126: );
127:
128: DWORD // Manages the IO with Remote Client.
129: RemoteSession(
130: SESSION_TYPE* Client
131: );
132:
133: BOOL // Ctrl-C handler
134: SrvCtrlHand(
135: DWORD event
136: );
137:
138: VOID // @s command to remote
139: SendStatus(
140: HANDLE hClientPipe
141: );
142:
143: DWORD // @p command to remote
144: ShowPopup(
145: char *mssg
146: );
147:
148: VOID // Removes the command begin and end markers
149: RemoveInpMark( // from the save file.
150: char* Buff,
151: DWORD Size
152: );
153:
154: VOID // Cleans up the session
155: CloseClient( // once it ends.
156: SESSION_TYPE *Client
157: );
158: // Initialises the Client datastructs
159: VOID
160: InitClientList(
161: );
162:
163:
164: /*************************************************************/
165: /* The main entry point for the Server End of Remote */
166: /*************************************************************/
167: VOID
168: Server(
169: char* ChildCmd,
170: char* PipeName
171: )
172: {
173: DWORD ThreadID ;
174: HANDLE WaitH[3];
175: DWORD WaitObj;
176: char tmpdir[32];
177:
178: WRITEF((VBuff,"**************************************\n"));
179: WRITEF((VBuff,"*********** REMOTE ************\n"));
180: WRITEF((VBuff,"*********** SERVER ************\n"));
181: WRITEF((VBuff,"**************************************\n"));
182: WRITEF((VBuff,"To Connect: Remote /C %s %s\n\n",HostName,PipeName));
183:
184: InitClientList();
185:
186: //
187: //Start the command as a child process
188: //
189:
190: ChldProc=ForkChildProcess(ChildCmd,&ChildStdInp,&ChildStdOut,&ChildStdErr);
191:
192: //
193: //Create a tempfile for storing Child process output.
194: //
195: {
196: DWORD size=sizeof(tmpdir);
197: if (
198: (GetEnvironmentVariable("TMP" ,tmpdir,size)==0)&&
199: (GetEnvironmentVariable("TEMP",tmpdir,size)==0)
200: )
201: {
202: sprintf(tmpdir,"%s",".");
203: }
204: if (!GetTempFileName(tmpdir,"REMOTE",0,SaveFileName))
205: GetTempFileName(".","REMOTE",0,SaveFileName);
206: }
207:
208:
209: if ((SaveFile=CreateFile
210: (
211: (LPCTSTR)SaveFileName, /* address of name of the file */
212: GENERIC_READ|GENERIC_WRITE, /* access (read/write) mode */
213: FILE_SHARE_READ|FILE_SHARE_WRITE,/* share mode */
214: (LPSECURITY_ATTRIBUTES)NULL, /* security descriptor */
215: CREATE_ALWAYS, /* how to create */
216: FILE_ATTRIBUTE_NORMAL, /* File Attribute */
217: (HANDLE)NULL)
218: )==NULL)
219: {
220: TerminateProcess(ChldProc,0);
221: ErrorExit("Could not Create Output File");
222: }
223:
224:
225: //
226: //Start 2 threads to save the output from stdout and stderr of cmd to savefile.
227: //
228:
229: if ((WaitH[0]=CreateThread
230: (
231: (LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
232: (DWORD)0, // Use same stack size.
233: (LPTHREAD_START_ROUTINE)GetChldOutput, // Thread procedure.
234: (LPVOID)ChildStdErr, // Parameter to pass.
235: (DWORD)0, // Run immediately.
236: (LPDWORD)&ThreadID)
237: )==NULL)
238: {
239:
240: TerminateProcess(ChldProc,0);
241: ErrorExit("Failed to Create GetGhldOutput#1 Thread");
242: }
243:
244:
245: if ((WaitH[1]=CreateThread
246: (
247: (LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
248: (DWORD)0, // Use same stack size.
249: (LPTHREAD_START_ROUTINE)GetChldOutput, // Thread procedure.
250: (LPVOID)ChildStdOut, // Parameter to pass.
251: (DWORD)0, // Run immediately.
252: (LPDWORD)&ThreadID)
253: )==NULL)
254: {
255:
256: TerminateProcess(ChldProc,0);
257: ErrorExit("Failed to Create GetGhldOutput#2 Thread");
258: }
259:
260:
261: //
262: //Start Thread to listen for new Connections
263: //
264:
265: if ((ListenThreadH=CreateThread
266: (
267: (LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
268: (DWORD)0, // Use same stack size.
269: (LPTHREAD_START_ROUTINE)ListenForSession, // Thread procedure.
270: (LPVOID)PipeName, // Parameter to pass.
271: (DWORD)0, // Run immediately.
272: (LPDWORD)&ThreadID)
273: )==NULL)
274: {
275:
276: TerminateProcess(ChldProc,0);
277: ErrorExit("Failed To Create ListenForSession Thread");
278:
279: }
280:
281: //
282: //Start Local Thread
283: //
284:
285: if ((ClientList[0].hThread=CreateThread
286: (
287: (LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
288: (DWORD)0, // Use same stack size.
289: (LPTHREAD_START_ROUTINE)LocalSession, // Thread procedure.
290: (LPVOID)NULL, // Parameter to pass.
291: (DWORD)0, // Run immediately.
292: (LPDWORD)&ThreadID)
293: )==NULL)
294: {
295:
296: TerminateProcess(ChldProc,0);
297: ErrorExit("Failed To Create ListenForSession Thread");
298:
299: }
300:
301: SetConsoleCtrlHandler((PHANDLER_ROUTINE)SrvCtrlHand,TRUE);
302:
303: WaitH[2]=ChldProc;
304:
305: //
306: // Wait until the child process terminates
307: // or local IO thread terminates
308: // or IO with child process ends
309: //
310:
311: WaitObj=WaitForMultipleObjects(3,WaitH,FALSE,INFINITE);
312:
313: switch (WaitObj-WAIT_OBJECT_0)
314: {
315: case 0: // Error Writing to savefile
316: case 1:
317: TerminateProcess(ChldProc,0);
318: break;
319: case 2: // Child Proc Terminated
320: break;
321:
322: default: // Out of Some Resource
323: printf("Out of Resource Error %d..Terminating\n",GetLastError());
324: break;
325:
326: }
327:
328: TerminateThread(ListenThreadH,0);
329:
330: CloseHandle(ChildStdInp);
331: CloseHandle(ChildStdOut);
332: CloseHandle(ChildStdErr);
333:
334: WRITEF((VBuff,"\nRemote:Parent exiting. Child(%s) dead..\n",ChildCmd));
335:
336: CloseHandle(SaveFile);
337:
338: {
339: int i;
340: for (i=0;i<MAX_SESSION;i++)
341: CloseClient(&ClientList[i]);
342: }
343:
344: if (!DeleteFile(SaveFileName))
345: WRITEF((VBuff,"Temp File %s not deleted..\n",SaveFileName));
346:
347: return;
348: }
349: /*************************************************************/
350: /* Creates the child process and redirects its std.IO handles*/
351: /*************************************************************/
352: HANDLE
353: ForkChildProcess( // Creates a new process
354: char *cmd, // Redirects its stdin,stdout
355: PHANDLE inH, // and stderr - returns the
356: PHANDLE outH, // corresponding pipe ends.
357: PHANDLE errH
358: )
359: {
360: SECURITY_ATTRIBUTES lsa;
361: STARTUPINFO si;
362: PROCESS_INFORMATION pi;
363:
364: HANDLE ChildIn;
365: HANDLE ChildOut;
366: HANDLE ChildErr;
367:
368: lsa.nLength=sizeof(SECURITY_ATTRIBUTES);
369: lsa.lpSecurityDescriptor=NULL;
370: lsa.bInheritHandle=TRUE;
371:
372: //
373: //Create Parent_Write to ChildStdIn Pipe
374: //
375:
376: if (!CreatePipe(&ChildIn,inH,&lsa,0))
377: ErrorExit("Could Not Create Parent-->Child Pipe");
378:
379: //
380: //Create ChildStdOut to Parent_Read pipe
381: //
382:
383: if (!CreatePipe(outH,&ChildOut,&lsa,0))
384: ErrorExit("Could Not Create Child-->Parent Pipe");
385:
386: //
387: //Create ChildStdOut to Parent_Read pipe
388: //
389:
390: if (!CreatePipe(errH,&ChildErr,&lsa,0))
391: ErrorExit("Could Not Create Child-->Parent Pipe");
392:
393: //
394: // Lets Redirect Console StdHandles - easy enough
395: //
396:
397:
398: si.cb=sizeof(STARTUPINFO);
399: si.lpReserved=NULL;
400: si.lpTitle=NULL;
401: si.lpDesktop=NULL;
402: si.dwX=si.dwY=si.dwYSize=si.dwXSize=0;
403: si.dwFlags=STARTF_USESTDHANDLES;
404: si.hStdInput =ChildIn;
405: si.hStdOutput=ChildOut;
406: si.hStdError =ChildErr;
407: si.wShowWindow=SW_SHOW;
408: si.lpReserved2=NULL;
409: si.cbReserved2=0;
410:
411: //
412: //Create Child Process
413: //
414:
415: if (!CreateProcess
416: (
417: NULL,
418: cmd,
419: NULL,
420: NULL,
421: TRUE,
422: NORMAL_PRIORITY_CLASS,
423: NULL,
424: NULL,
425: &si,
426: &pi)
427: )
428: {
429: if (GetLastError()==2)
430: WRITEF((VBuff,"Executable %s not found\n",cmd));
431: ErrorExit("Could Not Create Child Process");
432: }
433:
434: //
435: //Close unneccesary Handles and Restore the crt handles
436: //
437:
438: CloseHandle(ChildIn);
439: CloseHandle(ChildOut);
440: CloseHandle(ChildErr);
441:
442: return(pi.hProcess);
443: }
444: /*************************************************************/
445: /* Same as above but uses different method of IO redir. */
446: /* Not used now */
447: /*************************************************************/
448: HANDLE
449: OldForkChildProcess(
450: char *cmd,
451: PHANDLE inH,
452: PHANDLE outH,
453: PHANDLE errH
454: )
455: {
456: SECURITY_ATTRIBUTES lsa;
457: STARTUPINFO si;
458: PROCESS_INFORMATION pi;
459:
460: HANDLE OldStdIn =GetStdHandle(STD_INPUT_HANDLE);
461: HANDLE OldStdOut=GetStdHandle(STD_OUTPUT_HANDLE);
462: HANDLE OldStdErr=GetStdHandle(STD_ERROR_HANDLE);
463:
464: HANDLE ChildStdIn;
465: HANDLE ChildStdOut;
466: HANDLE ChildStdErr;
467:
468: lsa.nLength=sizeof(SECURITY_ATTRIBUTES);
469: lsa.lpSecurityDescriptor=NULL;
470: lsa.bInheritHandle=TRUE;
471:
472: //Create Parent_Write to ChildStdIn Pipe
473: if (!CreatePipe(&ChildStdIn,inH,&lsa,0))
474: ErrorExit("Could Not Create Parent-->Child Pipe");
475:
476: //Create ChildStdOut to Parent_Read pipe
477: if (!CreatePipe(outH,&ChildStdOut,&lsa,0))
478: ErrorExit("Could Not Create Child-->Parent Pipe");
479:
480: //Create ChildStdOut to Parent_Read pipe
481: if (!CreatePipe(errH,&ChildStdErr,&lsa,0))
482: ErrorExit("Could Not Create Child-->Parent Pipe");
483:
484: //Make ChildStdIn and Out as standard handles and get it inherited by child
485: if (!SetStdHandle(STD_INPUT_HANDLE,ChildStdIn))
486: ErrorExit("Could not change StdIn");
487:
488: if (!SetStdHandle(STD_OUTPUT_HANDLE,ChildStdOut))
489: ErrorExit("Could Not change StdOut");
490:
491: if (!SetStdHandle(STD_ERROR_HANDLE,ChildStdErr))
492: ErrorExit("Could Not change StdErr");
493:
494: si.cb=sizeof(STARTUPINFO);
495: si.lpReserved=NULL;
496: si.lpTitle=NULL;
497: si.lpDesktop=NULL;
498: si.dwX=si.dwY=si.dwYSize=si.dwXSize=si.dwFlags=0L;
499: si.wShowWindow=SW_SHOW;
500: si.lpReserved2=NULL;
501: si.cbReserved2=0;
502:
503: //Create Child Process
504: if (!CreateProcess
505: (
506: NULL,
507: cmd,
508: NULL,
509: NULL,
510: TRUE,
511: NORMAL_PRIORITY_CLASS,
512: NULL,
513: NULL,
514: &si,
515: &pi)
516: )
517: {
518: ErrorExit("Could Not Create Child Process");
519: }
520:
521: //reset StdIn StdOut
522: if (!SetStdHandle(STD_INPUT_HANDLE,OldStdIn))
523: {
524: TerminateProcess(pi.hProcess,1);
525: ErrorExit("Could not RESET StdIn");
526: }
527:
528: if (!SetStdHandle(STD_OUTPUT_HANDLE,OldStdOut))
529: {
530: TerminateProcess(pi.hProcess,1);
531: ErrorExit("Could not RESET StdIn");
532: }
533:
534: if (!SetStdHandle(STD_ERROR_HANDLE,OldStdErr))
535: {
536: TerminateProcess(pi.hProcess,1);
537: ErrorExit("Could not RESET StdIn");
538: }
539:
540: //Close unneccesary Handles
541: CloseHandle(ChildStdIn);
542: CloseHandle(ChildStdOut);
543: CloseHandle(ChildStdErr);
544:
545: return(pi.hProcess);
546: }
547: /*************************************************************/
548: /* Listens for sessions from Clients and creates a new thread*/
549: /* for each client */
550: /*************************************************************/
551:
552: DWORD
553: ListenForSession(
554: char* pipename
555: )
556: {
557: int i;
558: DWORD ThreadID;
559: HANDLE PipeH[2];
560: SECURITY_DESCRIPTOR SecurityDescriptor;
561: HANDLE TokenHandle;
562: TOKEN_DEFAULT_DACL DefaultDacl;
563: SECURITY_ATTRIBUTES lsa;
564:
565: char fullnameIn[BUFFSIZE];
566: char fullnameOut[BUFFSIZE];
567:
568: sprintf(fullnameIn,SERVER_READ_PIPE ,".",pipename);
569: sprintf(fullnameOut,SERVER_WRITE_PIPE,".",pipename);
570:
571: //
572: // Initialize the security descriptor that we're going to
573: // use.
574: //
575:
576: InitializeSecurityDescriptor
577: (
578: &SecurityDescriptor,
579: SECURITY_DESCRIPTOR_REVISION
580: );
581:
582: (VOID) SetSecurityDescriptorDacl
583: (
584: &SecurityDescriptor,
585: TRUE,
586: NULL,
587: FALSE
588: );
589:
590: DefaultDacl.DefaultDacl = NULL;
591:
592: if (OpenProcessToken
593: (
594: GetCurrentProcess(),
595: TOKEN_ADJUST_DEFAULT,
596: &TokenHandle
597: ))
598: {
599:
600: //
601: // Remove the default DACL on the token
602: //
603:
604: SetTokenInformation
605: (
606: TokenHandle,
607: TokenDefaultDacl,
608: &DefaultDacl,
609: sizeof( TOKEN_DEFAULT_DACL )
610: );
611:
612: }
613:
614: lsa.nLength=sizeof(SECURITY_ATTRIBUTES);
615: lsa.lpSecurityDescriptor=&SecurityDescriptor;
616: lsa.bInheritHandle=TRUE;
617:
618: while(TRUE)
619: {
620: //
621: // Create New pipe instances for each connection
622: //
623:
624: PipeH[0]=CreateNamedPipe
625: (
626: fullnameIn ,
627: PIPE_ACCESS_INBOUND ,
628: PIPE_TYPE_BYTE,
629: PIPE_UNLIMITED_INSTANCES,
630: 0,0,0,&lsa
631: );
632:
633: PipeH[1]=CreateNamedPipe
634: (
635: fullnameOut,
636: PIPE_ACCESS_OUTBOUND,
637: PIPE_TYPE_BYTE,
638: PIPE_UNLIMITED_INSTANCES,
639: 0,0,0,&lsa
640: );
641:
642: if (!ConnectNamedPipe(PipeH[0],NULL))
643: {
644: if (GetLastError()!=ERROR_PIPE_CONNECTED)
645: {
646: CloseHandle(PipeH[0]);
647: CloseHandle(PipeH[1]);
648: continue;
649: }
650:
651: }
652:
653: if (!ConnectNamedPipe(PipeH[1],NULL))
654: {
655: if (GetLastError()!=ERROR_PIPE_CONNECTED)
656: {
657: CloseHandle(PipeH[0]);
658: CloseHandle(PipeH[1]);
659: continue;
660: }
661: }
662:
663: //
664: //Look For a Free Slot & if not- then terminate connection
665: //
666:
667: for (i=1;i<MAX_SESSION;i++)
668: {
669: //
670: // Locate a Free Client block
671: //
672: if (!ClientList[i].Active)
673: break;
674: }
675:
676: if (i<MAX_SESSION)
677: {
678: //
679: // Initialize the Client
680: //
681: ClientList[i].PipeReadH=PipeH[0];
682: ClientList[i].PipeWriteH=PipeH[1];
683: ClientList[i].Active=TRUE;
684: ClientList[i].SendOutput=TRUE;
685: ClientList[i].CommandRcvd=FALSE;
686:
687: }
688: else
689: {
690: WRITEF((VBuff,"Remote:Closing New Session - No more slots\n"));
691: CloseHandle(PipeH[0]);
692: CloseHandle(PipeH[1]);
693: continue;
694: }
695:
696: //
697: //start new thread for this connection
698: //
699:
700: if((ClientList[i].hThread=CreateThread
701: (
702: (LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
703: (DWORD)0, // Use same stack size.
704: (LPTHREAD_START_ROUTINE)RemoteSession, // Thread procedure.
705: (LPVOID)&ClientList[i], // Parameter to pass.
706: (DWORD)0, // Run immediately.
707: (LPDWORD)&ThreadID)
708: )==NULL)
709: {
710: CloseClient(&ClientList[i]);
711: continue;
712: }
713: }
714: return(0);
715: }
716: /*************************************************************/
717: /* Manages the Session with a Client - Creates a thread for */
718: /* Inputs from the client and a thread for sending outputs to*/
719: /* the client. Could have just as easily done with 1 thread */
720: /* using Asyn IO. */
721: /*************************************************************/
722: DWORD
723: RemoteSession(
724: SESSION_TYPE *MyClient
725: )
726: {
727: DWORD ReadCnt;
728: SESSION_STARTUPINFO ssi;
729: char *headerbuff;
730: char msg[BUFFSIZE];
731: DWORD tmp;
732: SESSION_STARTREPLY ssr;
733: SYSTEMTIME st;
734:
735: GetLocalTime(&st);
736: memset((char *)&ssi,0,sizeof(ssi));
737:
738: //
739: // Open a new handle to the save file ...
740: // contains the saved output from the child process
741: // and the commands already given to it.
742: //
743:
744: if ((MyClient->rSaveFile=CreateFile
745: (
746: SaveFileName,
747: GENERIC_READ|GENERIC_WRITE,
748: FILE_SHARE_READ|FILE_SHARE_WRITE,
749: NULL,OPEN_EXISTING,
750: FILE_ATTRIBUTE_NORMAL,NULL)
751: )==NULL)
752:
753: {
754: CloseClient(MyClient);
755: return(1);
756: }
757:
758: //
759: // Exchange Remote Information with Client.
760: //
761:
762: {
763:
764: DWORD reply=0;
765:
766: ReadFixBytes(MyClient->PipeReadH,(char *)MyClient->Name,HOSTNAMELEN-1,0);
767:
768: //
769: //Last four Bytes contains a code
770: //
771:
772: memcpy((char *)&reply,(char *)&(MyClient->Name[11]),4);
773:
774: if (reply!=MAGICNUMBER)
775: {
776: //
777: // Unknown client
778: //
779: CloseClient(MyClient);
780: return(1);
781: }
782:
783: ssr.MagicNumber=MAGICNUMBER;
784: ssr.Size=sizeof(ssr);
785: ssr.FileSize=GetFileSize( MyClient->rSaveFile, &tmp );
786:
787: WriteFile(MyClient->PipeWriteH,(char *)&ssr,sizeof(ssr),&tmp,NULL);
788: }
789:
790: if (ReadFixBytes(MyClient->PipeReadH,(char *)&(ssi.Size),sizeof(ssi.Size),0)!=0)
791: {
792: CloseClient(MyClient);
793: return(1);
794: }
795:
796: if (ssi.Size>1024) //Sanity Check
797: {
798: sprintf(msg,"%s","Server:Unknown Header..Terminating session\n");
799: WriteFile(MyClient->PipeWriteH,msg,strlen(msg),&tmp,NULL);
800: CloseClient(MyClient);
801: return(1);
802: }
803:
804: if ((headerbuff=(char *)calloc(ssi.Size,1))==NULL)
805: {
806: sprintf(msg,"%s","Server:Not Enough Memory..Terminating session\n");
807: WriteFile(MyClient->PipeWriteH,msg,strlen(msg),&tmp,NULL);
808: CloseClient(MyClient);
809: return(1);
810: }
811:
812: ReadCnt=ssi.Size-sizeof(ssi.Size);
813: if (ReadFixBytes(MyClient->PipeReadH,(char *)headerbuff,ReadCnt,0)!=0)
814: {
815: CloseClient(MyClient);
816: return(1);
817: }
818:
819: memcpy((char *)&ssi+sizeof(ssi.Size),headerbuff,sizeof(ssi)-sizeof(ssi.Size));
820: free(headerbuff);
821:
822: /* Version */
823: if (ssi.Version!=VERSION)
824: {
825: sprintf(msg,"Remote Warning:Server Version=%d Client Version=%d\n",VERSION,ssi.Version);
826: WriteFile(MyClient->PipeWriteH,msg,strlen(msg),&tmp,NULL);
827:
828: }
829:
830: /* Name */
831: {
832: memcpy(MyClient->Name,ssi.ClientName,15);
833: MyClient->Name[14]=0;
834:
835: }
836:
837: /* Lines */
838: if (ssi.LinesToSend!=-1)
839: {
840: long PosFromEnd=ssi.LinesToSend*CHARS_PER_LINE;
841: DWORD BytesToSend=MINIMUM((DWORD)PosFromEnd,ssr.FileSize);
842: DWORD BytesRead;
843: char *buff=(char *)calloc(BytesToSend+1,1);
844:
845: if (ssr.FileSize > (DWORD)PosFromEnd)
846: {
847: SetFilePointer(
848: MyClient->rSaveFile,
849: -PosFromEnd,
850: (PLONG)NULL,
851: FILE_END
852: );
853: }
854:
855: if (buff!=NULL)
856: {
857: if (!ReadFile(MyClient->rSaveFile,buff,BytesToSend,&BytesRead,NULL))
858: {
859: CloseClient(MyClient);
860: return(1);
861: }
862:
863: //
864: // Don't want the markers to be part of the output display
865: // at the client end.
866: //
867: RemoveInpMark(buff,BytesRead);
868: if (!WriteFile(MyClient->PipeWriteH,buff,BytesRead,&tmp,NULL))
869: {
870: CloseClient(MyClient);
871: return(1);
872: }
873: }
874: free(buff);
875:
876: }
877:
878: RemoteInfo(printf("\n**Remote:Connected To %s [%02d:%02d]\n",MyClient->Name,st.wHour,st.wMinute),ssi.Flag);
879:
880: //
881: // Start off the new session.
882: //
883: NewSession(MyClient);
884:
885: RemoteInfo(printf("\n**Remote:Disconnected From %s [%02d:%02d]\n",MyClient->Name,st.wHour,st.wMinute),ssi.Flag);
886: CloseClient(MyClient);
887: return(0);
888: }
889: /*************************************************************/
890: DWORD
891: NewSession(
892: SESSION_TYPE* MyClient
893: )
894: {
895: DWORD ThreadId;
896: HANDLE rwThread[3];
897:
898: MyClient->MoreData=CreateEvent
899: (
900: (LPSECURITY_ATTRIBUTES) NULL,/* address of security attributes */
901: FALSE, /* flag for manual-reset event */
902: TRUE, /* flag for initial state */
903: NULL /* address of event-object name */
904: );
905:
906: if ((rwThread[0]=CreateThread
907: (
908: (LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
909: (DWORD)0, // Use same stack size.
910: (LPTHREAD_START_ROUTINE)GetClientInput, // Thread procedure.
911: (LPVOID)MyClient, // Parameter to pass.
912: (DWORD)0, // Run immediately.
913: (LPDWORD)&ThreadId)
914: )==NULL)
915: {
916: return(GetLastError());
917: }
918:
919:
920: if ((rwThread[1]=CreateThread
921: (
922: (LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
923: (DWORD)0, // Use same stack size.
924: (LPTHREAD_START_ROUTINE)TransferFileToClient, // Thread procedure.
925: (LPVOID)MyClient, // Parameter to pass.
926: (DWORD)0, // Run immediately.
927: (LPDWORD)&ThreadId)
928: )==NULL)
929: {
930: CloseHandle(rwThread[0]);
931: return(GetLastError());
932: }
933:
934: rwThread[2]=ChldProc;
935:
936: //
937: // Wait for either the Input or Output thread
938: // to terminate and then close the session.
939: //
940:
941: WaitForMultipleObjects(3, rwThread,FALSE, INFINITE);
942:
943: TerminateThread(rwThread[0],1);
944: TerminateThread(rwThread[1],1);
945:
946: CloseHandle(rwThread[0]);
947: CloseHandle(rwThread[0]);
948:
949: return(0);
950: }
951:
952: /*************************************************************/
953: /* Saves the output from the child process into the savefile */
954: /* All the remote client thread and local client thread */
955: /* open a seperate handle to this and output its content */
956: /* sequentially. */
957: /*************************************************************/
958: DWORD
959: GetChldOutput(
960: HANDLE readH
961: )
962: {
963: char buff[BUFFSIZE];
964: DWORD dread;
965: DWORD tmp;
966:
967:
968: while(ReadFile(readH,buff,BUFFSIZE-1,&dread,NULL))
969: {
970: buff[dread]='\0';
971:
972: if (!WriteFile(SaveFile,buff,dread,&tmp,NULL))
973: {
974: return(1);
975: }
976:
977: //
978: // Signal Reader Thread that more data is available
979: //
980: {
981: int i;
982: for (i=0;i<MAX_SESSION;i++)
983: {
984: if (ClientList[i].Active)
985: {
986: SetEvent(ClientList[i].MoreData);
987: }
988: }
989: }
990: }
991: return(1);
992: }
993: /*************************************************************/
994: /* A thread for each client connection and one for local IO */
995: /* Reads the contents of Save file and sends it to client for*/
996: /* display. */
997: /*************************************************************/
998: DWORD
999: TransferFileToClient(
1000: SESSION_TYPE *MyClient
1001: )
1002: {
1003:
1004: char buffin[BUFFSIZE],buffout[BUFFSIZE],cmdbuff[BUFFSIZE];
1005: DWORD tmp;
1006: DWORD dread=0,dwrite=0;
1007: BOOL incmd=FALSE;
1008: DWORD cmdP=0;
1009: DWORD i;
1010: char MyEchoStr[30];
1011:
1012: sprintf(MyEchoStr,"[%-15s",MyClient->Name);
1013:
1014: while(ReadFile(MyClient->rSaveFile,buffin,BUFFSIZE-1,&dread,NULL))
1015: {
1016: if (dread==0)
1017: {
1018: //
1019: // Event is set by GetChldOutput() func. to signal
1020: // More data is available in save file.
1021: //
1022: WaitForSingleObject(MyClient->MoreData,INFINITE);
1023: continue;
1024: }
1025: dwrite=0;
1026:
1027: //
1028: // This is all to insure that the commands entered
1029: // by clients are not echoed back to them.
1030: // A Beginmark and an Endmark is placed around commands
1031: // sent to the child process from some client.
1032: //
1033:
1034: for(i=0;i<dread;i++)
1035: {
1036: if (incmd)
1037: {
1038: if ((buffin[i]==ENDMARK)||(cmdP==BUFFSIZE-1))
1039: {
1040: incmd=FALSE;
1041: cmdbuff[cmdP]=0;
1042: if ((strstr(cmdbuff,MyEchoStr)==NULL)||
1043: (!MyClient->CommandRcvd))
1044: {
1045: if (!WriteFile(
1046: MyClient->PipeWriteH,
1047: cmdbuff,cmdP,&tmp,NULL))
1048: {
1049: return(1);
1050: }
1051: }
1052: cmdP=0;
1053: }
1054: else
1055: {
1056: cmdbuff[cmdP++]=buffin[i];
1057: }
1058: }
1059: else
1060: {
1061:
1062: if (buffin[i]==BEGINMARK)
1063: {
1064: if (dwrite!=0)
1065: {
1066: if (!WriteFile(
1067: MyClient->PipeWriteH,
1068: buffout,dwrite,&tmp,NULL))
1069: {
1070: return(1);
1071: }
1072: dwrite=0;
1073: }
1074: incmd=TRUE;
1075: continue;
1076: }
1077: else
1078: {
1079: buffout[dwrite++]=buffin[i];
1080: }
1081: }
1082: }
1083:
1084: if (dwrite!=0)
1085: {
1086: if (!WriteFile(
1087: MyClient->PipeWriteH,
1088: buffout,dwrite,&tmp,NULL))
1089: {
1090: return(0);
1091: }
1092: }
1093: }
1094: return(1);
1095: }
1096:
1097: /*************************************************************/
1098: /* Commands from the clients are sent to the child process */
1099: /* and also saved in the SaveFile with Begin and End markers */
1100: /* around them to seperate them from the output from child */
1101: /* process. */
1102: /*************************************************************/
1103: DWORD
1104: GetClientInput(
1105: SESSION_TYPE *MyClient
1106: )
1107: {
1108: char buff[BUFFSIZE];
1109: DWORD tmp,dread;
1110:
1111: while(ReadFile(MyClient->PipeReadH,buff,BUFFSIZE,&dread,NULL))
1112: {
1113: buff[dread]=0;
1114: MyClient->CommandRcvd=TRUE;
1115:
1116: if (FilterCommand(MyClient,buff,dread))
1117: continue;
1118:
1119:
1120: if (!WriteFile(ChildStdInp,buff,dread,&tmp,NULL))
1121: {
1122: ExitThread(0);
1123: }
1124: }
1125: return(1);
1126: }
1127:
1128: /*************************************************************/
1129: /* If a client command is intended for the Remote server - */
1130: /* those beginning with COMMANDCHAR (are not intended */
1131: /* for the child process) - they are executed here */
1132: /* and the output sent to the client. */
1133: /*************************************************************/
1134: BOOL
1135: FilterCommand(
1136: SESSION_TYPE *cl,
1137: char *buff,
1138: int dread
1139: )
1140: {
1141: SYSTEMTIME st;
1142: char inp_buff[4096];
1143: char tmpchar;
1144: char ch[3];
1145: DWORD tmp;
1146: int len;
1147: DWORD ThreadID; //Useless
1148:
1149: if (dread==0)
1150: return(FALSE);
1151:
1152: buff[dread]=0;
1153:
1154: GetLocalTime(&st);
1155:
1156:
1157: if (buff[0]==COMMANDCHAR)
1158: {
1159: switch(buff[1])
1160: {
1161: case 'o':
1162: case 'O':
1163: cl->SendOutput=!cl->SendOutput;
1164: break;
1165:
1166: case 'k':
1167: case 'K':
1168: TerminateProcess(ChldProc,1);
1169: break;
1170:
1171: case 's':
1172: case 'S':
1173: SendStatus(cl->PipeWriteH);
1174: break;
1175:
1176: case 'p':
1177: case 'P':
1178: {
1179: char *mssg=(char *)calloc(4096,1); //Free it in called Proc
1180: char *ack="Remote:Popup Shown..\n";
1181:
1182: if (mssg==NULL)
1183: break;
1184:
1185: sprintf(mssg,"From %s [%d:%d]\n\n%s\n",cl->Name,st.wHour,st.wMinute,&buff[2]);
1186: CreateThread(
1187: (LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
1188: (DWORD)0, // Use same stack size.
1189: (LPTHREAD_START_ROUTINE)ShowPopup, // Thread procedure.
1190: (LPVOID)mssg, // Parameter to pass.
1191: (DWORD)0, // Run immediately.
1192: (LPDWORD)&ThreadID
1193: );
1194: WriteFile(cl->PipeWriteH,ack,strlen(ack),&tmp,NULL);
1195: break;
1196: }
1197:
1198: case 'm':
1199: case 'M':
1200: buff[dread-2]=0;
1201: CMDSTRING(inp_buff,buff,cl,st);
1202: len=strlen(inp_buff);
1203: WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
1204: break;
1205:
1206: case '@':
1207: buff[dread-2]=0;
1208: CMDSTRING(inp_buff,&buff[1],cl,st);
1209: len=strlen(inp_buff);
1210: WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
1211: //
1212: // Remove the first @ sign
1213: //
1214: MoveMemory(buff,&buff[1],dread-1);
1215: buff[dread-1]=' ';
1216: return(FALSE); //Send it it to the chile process
1217: break;
1218:
1219:
1220: default :
1221: sprintf(inp_buff,"%s","** Unknown Command **\n");
1222: WriteFile(cl->PipeWriteH,inp_buff,strlen(inp_buff),&tmp,NULL);
1223:
1224: case 'h':
1225: case 'H':
1226: sprintf(inp_buff,"%cM: To Send Message\n",COMMANDCHAR);
1227: WriteFile(cl->PipeWriteH,inp_buff,strlen(inp_buff),&tmp,NULL);
1228: sprintf(inp_buff,"%cP: To Generate popup\n",COMMANDCHAR);
1229: WriteFile(cl->PipeWriteH,inp_buff,strlen(inp_buff),&tmp,NULL);
1230: sprintf(inp_buff,"%cK: To kill the server\n",COMMANDCHAR);
1231: WriteFile(cl->PipeWriteH,inp_buff,strlen(inp_buff),&tmp,NULL);
1232: sprintf(inp_buff,"%cH: This Help\n",COMMANDCHAR);
1233: WriteFile(cl->PipeWriteH,inp_buff,strlen(inp_buff),&tmp,NULL);
1234: break;
1235: }
1236: return(TRUE);
1237: }
1238:
1239:
1240: if ((buff[0]<26))
1241: {
1242: BOOL ret=FALSE;
1243:
1244: sprintf(ch,"^%c",buff[0]+64);
1245: CMDSTRING(inp_buff,ch,cl,st);
1246: len=strlen(inp_buff);
1247:
1248: if (buff[0]==CTRLC)
1249: {
1250: cl->CommandRcvd=FALSE;
1251: GenerateConsoleCtrlEvent(CTRL_C_EVENT,0);
1252: ret=TRUE; //Already sent to child
1253: }
1254:
1255: WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
1256: return(ret); //FALSE:send it to child StdIn
1257: }
1258:
1259: tmpchar=buff[dread-2]; //must be 13;but just incase
1260: buff[dread-2]=0;
1261: CMDSTRING(inp_buff,buff,cl,st);
1262: buff[dread-2]=tmpchar;
1263: len=strlen(inp_buff);
1264: WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
1265: return(FALSE);
1266: }
1267: /*************************************************************/
1268: VOID
1269: SendStatus(
1270: HANDLE hClientPipe
1271: )
1272: {
1273: char buff[1024];
1274: int i;
1275: DWORD tmp;
1276: char *env=(char *)GetEnvironmentStrings();
1277: DWORD ver=GetVersion();
1278:
1279: sprintf(buff,"Command = %s\n",ChildCmd);
1280: WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
1281:
1282: sprintf(buff,"Server = %s PIPE=%s\n",HostName,PipeName);
1283: WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
1284:
1285: sprintf(buff,"Build = %d \n",((WORD *)&ver)[1]);
1286: WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
1287:
1288: for (i=1;i<MAX_SESSION;i++)
1289: {
1290: if (ClientList[i].Active)
1291: {
1292: sprintf(buff,"ACTIVE SESSION=%s\n",ClientList[i].Name);
1293: WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
1294: }
1295: }
1296:
1297: sprintf(buff,"====================\n",Server,PipeName);
1298: WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
1299:
1300: sprintf(buff,"ENVIRONMENT VARIABLES\n",Server,PipeName);
1301: WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
1302:
1303: sprintf(buff,"====================\n",Server,PipeName);
1304: WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
1305:
1306:
1307: try
1308: {
1309: while (*env!=0)
1310: {
1311: sprintf(buff,"%s\n",env);
1312: WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
1313:
1314: while(*(env++)!=0);
1315: }
1316: }
1317: except(EXCEPTION_EXECUTE_HANDLER)
1318: {
1319: sprintf(buff,"Exception Generated Getting Environment Block\n",env);
1320: WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
1321:
1322: }
1323:
1324: sprintf(buff,"====================\n",Server,PipeName);
1325: WriteFile(hClientPipe,buff,strlen(buff),&tmp,NULL);
1326: return;
1327: }
1328: /*************************************************************/
1329: DWORD
1330: ShowPopup(
1331: char *mssg
1332: )
1333: {
1334: MessageBox(GetActiveWindow(),mssg,"***REMOTE***",MB_OK|MB_SETFOREGROUND);
1335: free(mssg);
1336: return(0);
1337:
1338: }
1339: /*************************************************************/
1340: BOOL SrvCtrlHand(
1341: DWORD event
1342: )
1343: {
1344: if (event==CTRL_BREAK_EVENT)
1345: {
1346: TerminateProcess(ChldProc,1);
1347: }
1348: return(TRUE);
1349: }
1350: /*************************************************************/
1351:
1352: DWORD LocalSession(PVOID noarg)
1353: {
1354: //Local is ClientList[0]
1355: char *name=(char *)ClientList[0].Name;
1356:
1357: strcpy(name,LOCALNAME);
1358: if ((ClientList[0].rSaveFile=CreateFile(SaveFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL))==NULL)
1359: {
1360: WRITEF((VBuff,"Remote:Cannot open ReadHandle to Savefile:%d\n",GetLastError()));
1361: ClientList[0].Active=FALSE;
1362: return(1);
1363:
1364: }
1365:
1366: ClientList[0].PipeReadH=GetStdHandle(STD_INPUT_HANDLE);
1367: ClientList[0].PipeWriteH=GetStdHandle(STD_OUTPUT_HANDLE);
1368: ClientList[0].SendOutput=TRUE;
1369: ClientList[0].Active=TRUE;
1370: NewSession(&ClientList[0]);
1371: CloseClient(&ClientList[0]);
1372: return(0);
1373: }
1374:
1375: VOID
1376: CloseClient(
1377: SESSION_TYPE *Client
1378: )
1379: {
1380: ZeroMemory(Client->Name,HOSTNAMELEN);
1381:
1382: if (Client->PipeReadH!=INVALID_HANDLE_VALUE)
1383: {
1384: CloseHandle(Client->PipeReadH);
1385: Client->PipeReadH=INVALID_HANDLE_VALUE;
1386: }
1387:
1388: if (Client->PipeWriteH!=INVALID_HANDLE_VALUE)
1389: {
1390: CloseHandle(Client->PipeWriteH);
1391: Client->PipeWriteH=INVALID_HANDLE_VALUE;
1392: }
1393:
1394: if (Client->rSaveFile!=INVALID_HANDLE_VALUE)
1395: {
1396: CloseHandle(Client->rSaveFile);
1397: Client->rSaveFile=INVALID_HANDLE_VALUE;
1398: }
1399: if (Client->MoreData!=NULL)
1400: {
1401: CloseHandle(Client->MoreData);
1402: Client->MoreData=NULL;
1403: }
1404:
1405: Client->Active=FALSE; //Keep it last else synch problem.
1406: return;
1407: }
1408:
1409: VOID
1410: InitClientList(
1411: )
1412: {
1413: int i;
1414: for (i=0;i<MAX_SESSION;i++)
1415: {
1416: ZeroMemory(ClientList[i].Name,HOSTNAMELEN);
1417: ClientList[i].PipeReadH=INVALID_HANDLE_VALUE;
1418: ClientList[i].PipeWriteH=INVALID_HANDLE_VALUE;
1419: ClientList[i].rSaveFile=INVALID_HANDLE_VALUE;
1420: ClientList[i].MoreData=NULL;
1421: ClientList[i].Active=FALSE;
1422: ClientList[i].CommandRcvd=FALSE;
1423: ClientList[i].SendOutput=FALSE;
1424: ClientList[i].hThread=NULL;
1425: }
1426: return;
1427: }
1428:
1429:
1430:
1431: VOID
1432: RemoveInpMark(
1433: char* Buff,
1434: DWORD Size
1435: )
1436:
1437: {
1438: DWORD i;
1439: for (i=0;i<Size;i++)
1440: {
1441: switch (Buff[i])
1442: {
1443: case BEGINMARK:
1444: Buff[i]=' ';
1445: break;
1446:
1447: case ENDMARK:
1448: if (i<2)
1449: {
1450: Buff[i]= ' ';
1451: }
1452: else
1453: {
1454: Buff[i] =Buff[i-1];
1455: Buff[i-1]=Buff[i-2];
1456: Buff[i-2]=' ';
1457: }
1458: break;
1459:
1460: default:
1461: break;
1462: }
1463: }
1464: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.