/* Filename : vdmdebug.c Author : D.A.Bartlett Purpose : Provide a debug window for softpc */ /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Include files */ #include "windows.h" #include "stdio.h" #include "stdlib.h" /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::: Internal macros */ #define UNREFERENCED_FORMAL_PARAMETER(x) (x) #define RDNS_OK (0) #define RDNS_ERROR (1) #define RDNS_INPUT_REQUEST (2) #define DEFAULT_PIPE_NAME "\\\\.\\pipe\\softpc" #define DEFAULT_EVENT_NAME "YodaEvent" #define DEFAULT_LOG_FILE "\\vdmdebug.log" /*:::::::::::::::::::::::::::::::::::::::::::: Internal function protocols */ BOOL GetSendInput(HANDLE pipe, CHAR *LastPrint); int ReadDisplayNxtString(HANDLE pipe, CHAR *Buf, INT BufSize, DWORD *error); BOOL CntrlHandler(ULONG CtrlType); VOID DebugShell(CHAR *LastPrint, CHAR *Command); /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Static globals */ HANDLE YodaEvent; FILE *LogHandle; /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */ __cdecl main(int argc, char *argv[]) { HANDLE pipe; // Handle of pipe char *pipeName; // Pipe name char *eventName; // Yoda event object name CHAR buffer[500]; // Buffer to read pipe data into CHAR OrgConsoleTitle[250]; // Orginal console title BOOL PipeConnected; DWORD ReadError; // Error returned from ReadFile UNREFERENCED_FORMAL_PARAMETER(argc); UNREFERENCED_FORMAL_PARAMETER(argv); /*:::::::::::::::::::::::::::::::::::::::::::::::::: Display copyright */ printf("Softpc Debugging shell\n"); printf("Copyright Insignia Solutions 1991, 1992\n\n"); /*::::::::::::::::::::::::::::::::::::::::: Register Control-C handler */ if(!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CntrlHandler,TRUE)) { /*.......................................... Failed to create pipe */ printf("Failed to register a Control-C handler, error (%d)\n", GetLastError()); return(-1); } /*:::::::::::::::::::::::::: Validate environment and input parameters */ if((pipeName = getenv("PIPE")) == NULL) pipeName = DEFAULT_PIPE_NAME; /*::::::::::::::::::::::::::::::::::::: Attempt to create a named pipe */ if((pipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_WRITE_THROUGH, PIPE_WAIT | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE, 2, 1024, 1024, 0, NULL)) == (HANDLE) -1) { /*.......................................... Failed to create pipe */ printf("Failed to create pipe (%s), error (%d)\n", pipeName, GetLastError()); return(-1); } else printf("Successfully created communications pipe (%s)\n\n",pipeName); /*::::::::::::::::::::::::::::::::::::::::: Get Yoda event object name */ if((eventName = getenv("EVENT")) == NULL) eventName = DEFAULT_EVENT_NAME; /*::::::::::::::::::::::::::::::::::::::::::: Create YODA event object */ if((YodaEvent = CreateEvent(NULL,TRUE,FALSE,eventName))==NULL) { /*.......................................... Failed to create pipe */ printf("Failed to create yoda event (%s), error (%d)\n", eventName, GetLastError()); return(-1); } else printf("Successfully created Yoda event object (%s)\n\n",eventName); printf("Use Control-C to break into Yoda\n\n"); /*:::::::::::::::::::::::::::::::::::::::::::::::: Setup console title */ GetConsoleTitle(OrgConsoleTitle, sizeof(OrgConsoleTitle)); SetConsoleTitle("Softpc Debugger"); /*:::::::::::::::::::::::::: Wait for a process to connect to the pipe */ while(1) { ResetEvent(YodaEvent); printf("Waiting for ntvdm to connect............\n\n"); if(!ConnectNamedPipe(pipe,NULL)) { printf("ConnectNamedPipe failed (%d)\n",GetLastError()); SetConsoleTitle(OrgConsoleTitle); return(-1); } printf("Softpc connected successfully to debug shell....\n\n"); PipeConnected = TRUE; /*::::::::::::::::::::::::::::: Read data from pipe and display it */ while(PipeConnected) { /*........................................ Read data from pipe */ switch(ReadDisplayNxtString(pipe,buffer,sizeof(buffer),&ReadError)) { /*..................................... Handle read errors */ case RDNS_ERROR : if(ReadError == ERROR_BROKEN_PIPE) { printf("\nError Pipe broken\n\n"); DisconnectNamedPipe(pipe); PipeConnected = FALSE; } else printf("ReadFile failed (%d)\n",ReadError); break; /*................................... Handle input request */ case RDNS_INPUT_REQUEST : GetSendInput(pipe,buffer); break; } } } /* End of connect loop */ } /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ /*::::::::::::::::::::: Get input from console :::::::::::::::::::::::::::::*/ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ BOOL GetSendInput(HANDLE pipe, CHAR *LastPrint) { char buffer[500]; // Input buffer char bufsizstr[2]; // Buffer size string int bufsize; DWORD BytesWritten; /*::::::::::::::::: Get string from the console, remove new line marker */ while(1) { gets(buffer); // Get input from prompt if(*buffer != '!') break; // Enter debug shell ? DebugShell(LastPrint, buffer); // Entry vdmdebug shell } if((bufsize = strlen(buffer)) == 0) { bufsize = 1; buffer[0] = ' '; buffer[1] = 0; } /*::::::::::::::::::::::::::::: Construct and send buffer size string ! */ bufsizstr[0] = (char) (bufsize%256); bufsizstr[1] = (char) (bufsize/256); if(!WriteFile(pipe, bufsizstr, 2, &BytesWritten, NULL)) { printf("\n\nError writing to pipe (%d)\n",GetLastError()); return(FALSE); } /*:::::::::::::::::::::::::::::::::::::::::::::::: Write string to pipe */ if(!WriteFile(pipe, buffer, bufsize, &BytesWritten, NULL)) { printf("\n\nError writing to pipe (%d)\n",GetLastError()); return(FALSE); } return(TRUE); } /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ /*:::::::::::::::::::: Read and display next string ::::::::::::::::::::::::*/ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ int ReadDisplayNxtString(HANDLE pipe, CHAR *Buf, INT BufSize, DWORD *error) { DWORD RtnError = 0; // Error return by function int NxtStringSize; // Size of next string to read DWORD BytesRead; /*:::::::::::::::::::::::::::::::::::::::::: Wait for size of next size */ if(!ReadFile(pipe, Buf, 2, &BytesRead, NULL)) { *error = GetLastError(); return(RDNS_ERROR); } /*::::::::::::::::::::::::::::: Have we just received and input request */ if(Buf[0] == (char) 0xff && Buf[1] == (char) 0xff) return(RDNS_INPUT_REQUEST); /*:::::::::: Calculate and validate the size of the next string to read */ NxtStringSize = (Buf[0]&0xff) + ((Buf[1]&0xff)*256); if(NxtStringSize >= BufSize) { printf("\nWARNING : BUFFER OVERFLOW(%x,%x -> %d \n\n", Buf[0]&0xff,Buf[1]&0xff,NxtStringSize); } /*:::::::::::::::::::::::::::::::::::::::::::::::::::: Read next string */ if(!ReadFile(pipe, Buf, NxtStringSize, &BytesRead, NULL)) { *error = GetLastError(); return(RDNS_ERROR); } /*:::::::::::::::::::::::::::::::::::::::::::::::::::::: Display string */ Buf[BytesRead] = 0; printf("%s",Buf); return(RDNS_OK); } /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ /*:::::::::::::::::::::::::: Control-C handler :::::::::::::::::::::::::::::*/ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ BOOL CntrlHandler(ULONG CtrlType) { BOOL rtn = FALSE; // Default return event not handled /*:::::::::::::::::::::::::::::::::::::::::::: Process control C event */ if(CtrlType == CTRL_C_EVENT) { if(YodaEvent) { SetEvent(YodaEvent); Beep(0x100,1000); } rtn = TRUE; // Tell call the control event has been handled */ } return(rtn); } /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ /*:::::::::::::::::::::::::: Enter Debug Shell :::::::::::::::::::::::::::::*/ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ VOID DebugShell(CHAR *LastPrint, CHAR *Command) { switch(Command[1]) { // Open log file case 'o' : case 'O' : if((LogHandle = fopen(DEFAULT_LOG_FILE,"rw")) == NULL) printf("\nVDMDEBUG : Unable to open log file (%s)\n",DEFAULT_LOG_FILE); else printf("\nVDMDEBUG : Opened log file (%s)\n",DEFAULT_LOG_FILE); break; // Close log file if(LogHandle == NULL) printf("\nVDMDEBUG : Log file not open\n"); else { fclose(LogHandle); printf("\nVDMDEBUG : Closed log file (%s)\n",DEFAULT_LOG_FILE); } break; default: printf("\nVDMDEBUG : Unrecognised Command\n"); break; } printf("%s",LastPrint); // Print out orginal prompt }