Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
8.8 KiB

  1. /*
  2. Filename : vdmdebug.c
  3. Author : D.A.Bartlett
  4. Purpose : Provide a debug window for softpc
  5. */
  6. /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Include files */
  7. #include "windows.h"
  8. #include "stdio.h"
  9. #include "stdlib.h"
  10. /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::: Internal macros */
  11. #define UNREFERENCED_FORMAL_PARAMETER(x) (x)
  12. #define RDNS_OK (0)
  13. #define RDNS_ERROR (1)
  14. #define RDNS_INPUT_REQUEST (2)
  15. #define DEFAULT_PIPE_NAME "\\\\.\\pipe\\softpc"
  16. #define DEFAULT_EVENT_NAME "YodaEvent"
  17. #define DEFAULT_LOG_FILE "\\vdmdebug.log"
  18. /*:::::::::::::::::::::::::::::::::::::::::::: Internal function protocols */
  19. BOOL GetSendInput(HANDLE pipe, CHAR *LastPrint);
  20. int ReadDisplayNxtString(HANDLE pipe, CHAR *Buf, INT BufSize, DWORD *error);
  21. BOOL CntrlHandler(ULONG CtrlType);
  22. VOID DebugShell(CHAR *LastPrint, CHAR *Command);
  23. /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Static globals */
  24. HANDLE YodaEvent;
  25. FILE *LogHandle;
  26. /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */
  27. __cdecl main(int argc, char *argv[])
  28. {
  29. HANDLE pipe; // Handle of pipe
  30. char *pipeName; // Pipe name
  31. char *eventName; // Yoda event object name
  32. CHAR buffer[500]; // Buffer to read pipe data into
  33. CHAR OrgConsoleTitle[250]; // Orginal console title
  34. BOOL PipeConnected;
  35. DWORD ReadError; // Error returned from ReadFile
  36. UNREFERENCED_FORMAL_PARAMETER(argc);
  37. UNREFERENCED_FORMAL_PARAMETER(argv);
  38. /*:::::::::::::::::::::::::::::::::::::::::::::::::: Display copyright */
  39. printf("Softpc Debugging shell\n");
  40. printf("Copyright Insignia Solutions 1991, 1992\n\n");
  41. /*::::::::::::::::::::::::::::::::::::::::: Register Control-C handler */
  42. if(!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CntrlHandler,TRUE))
  43. {
  44. /*.......................................... Failed to create pipe */
  45. printf("Failed to register a Control-C handler, error (%d)\n",
  46. GetLastError());
  47. return(-1);
  48. }
  49. /*:::::::::::::::::::::::::: Validate environment and input parameters */
  50. if((pipeName = getenv("PIPE")) == NULL)
  51. pipeName = DEFAULT_PIPE_NAME;
  52. /*::::::::::::::::::::::::::::::::::::: Attempt to create a named pipe */
  53. if((pipe = CreateNamedPipe(pipeName,
  54. PIPE_ACCESS_DUPLEX | FILE_FLAG_WRITE_THROUGH,
  55. PIPE_WAIT | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE,
  56. 2, 1024, 1024, 0, NULL)) == (HANDLE) -1)
  57. {
  58. /*.......................................... Failed to create pipe */
  59. printf("Failed to create pipe (%s), error (%d)\n", pipeName,
  60. GetLastError());
  61. return(-1);
  62. }
  63. else
  64. printf("Successfully created communications pipe (%s)\n\n",pipeName);
  65. /*::::::::::::::::::::::::::::::::::::::::: Get Yoda event object name */
  66. if((eventName = getenv("EVENT")) == NULL)
  67. eventName = DEFAULT_EVENT_NAME;
  68. /*::::::::::::::::::::::::::::::::::::::::::: Create YODA event object */
  69. if((YodaEvent = CreateEvent(NULL,TRUE,FALSE,eventName))==NULL)
  70. {
  71. /*.......................................... Failed to create pipe */
  72. printf("Failed to create yoda event (%s), error (%d)\n", eventName,
  73. GetLastError());
  74. return(-1);
  75. }
  76. else
  77. printf("Successfully created Yoda event object (%s)\n\n",eventName);
  78. printf("Use Control-C to break into Yoda\n\n");
  79. /*:::::::::::::::::::::::::::::::::::::::::::::::: Setup console title */
  80. GetConsoleTitle(OrgConsoleTitle, sizeof(OrgConsoleTitle));
  81. SetConsoleTitle("Softpc Debugger");
  82. /*:::::::::::::::::::::::::: Wait for a process to connect to the pipe */
  83. while(1)
  84. {
  85. ResetEvent(YodaEvent);
  86. printf("Waiting for ntvdm to connect............\n\n");
  87. if(!ConnectNamedPipe(pipe,NULL))
  88. {
  89. printf("ConnectNamedPipe failed (%d)\n",GetLastError());
  90. SetConsoleTitle(OrgConsoleTitle);
  91. return(-1);
  92. }
  93. printf("Softpc connected successfully to debug shell....\n\n");
  94. PipeConnected = TRUE;
  95. /*::::::::::::::::::::::::::::: Read data from pipe and display it */
  96. while(PipeConnected)
  97. {
  98. /*........................................ Read data from pipe */
  99. switch(ReadDisplayNxtString(pipe,buffer,sizeof(buffer),&ReadError))
  100. {
  101. /*..................................... Handle read errors */
  102. case RDNS_ERROR :
  103. if(ReadError == ERROR_BROKEN_PIPE)
  104. {
  105. printf("\nError Pipe broken\n\n");
  106. DisconnectNamedPipe(pipe);
  107. PipeConnected = FALSE;
  108. }
  109. else
  110. printf("ReadFile failed (%d)\n",ReadError);
  111. break;
  112. /*................................... Handle input request */
  113. case RDNS_INPUT_REQUEST :
  114. GetSendInput(pipe,buffer);
  115. break;
  116. }
  117. }
  118. } /* End of connect loop */
  119. }
  120. /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
  121. /*::::::::::::::::::::: Get input from console :::::::::::::::::::::::::::::*/
  122. /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
  123. BOOL GetSendInput(HANDLE pipe, CHAR *LastPrint)
  124. {
  125. char buffer[500]; // Input buffer
  126. char bufsizstr[2]; // Buffer size string
  127. int bufsize;
  128. DWORD BytesWritten;
  129. /*::::::::::::::::: Get string from the console, remove new line marker */
  130. while(1)
  131. {
  132. gets(buffer); // Get input from prompt
  133. if(*buffer != '!') break; // Enter debug shell ?
  134. DebugShell(LastPrint, buffer); // Entry vdmdebug shell
  135. }
  136. if((bufsize = strlen(buffer)) == 0)
  137. {
  138. bufsize = 1;
  139. buffer[0] = ' ';
  140. buffer[1] = 0;
  141. }
  142. /*::::::::::::::::::::::::::::: Construct and send buffer size string ! */
  143. bufsizstr[0] = (char) (bufsize%256);
  144. bufsizstr[1] = (char) (bufsize/256);
  145. if(!WriteFile(pipe, bufsizstr, 2, &BytesWritten, NULL))
  146. {
  147. printf("\n\nError writing to pipe (%d)\n",GetLastError());
  148. return(FALSE);
  149. }
  150. /*:::::::::::::::::::::::::::::::::::::::::::::::: Write string to pipe */
  151. if(!WriteFile(pipe, buffer, bufsize, &BytesWritten, NULL))
  152. {
  153. printf("\n\nError writing to pipe (%d)\n",GetLastError());
  154. return(FALSE);
  155. }
  156. return(TRUE);
  157. }
  158. /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
  159. /*:::::::::::::::::::: Read and display next string ::::::::::::::::::::::::*/
  160. /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
  161. int ReadDisplayNxtString(HANDLE pipe, CHAR *Buf, INT BufSize, DWORD *error)
  162. {
  163. DWORD RtnError = 0; // Error return by function
  164. int NxtStringSize; // Size of next string to read
  165. DWORD BytesRead;
  166. /*:::::::::::::::::::::::::::::::::::::::::: Wait for size of next size */
  167. if(!ReadFile(pipe, Buf, 2, &BytesRead, NULL))
  168. {
  169. *error = GetLastError();
  170. return(RDNS_ERROR);
  171. }
  172. /*::::::::::::::::::::::::::::: Have we just received and input request */
  173. if(Buf[0] == (char) 0xff && Buf[1] == (char) 0xff)
  174. return(RDNS_INPUT_REQUEST);
  175. /*:::::::::: Calculate and validate the size of the next string to read */
  176. NxtStringSize = (Buf[0]&0xff) + ((Buf[1]&0xff)*256);
  177. if(NxtStringSize >= BufSize)
  178. {
  179. printf("\nWARNING : BUFFER OVERFLOW(%x,%x -> %d \n\n",
  180. Buf[0]&0xff,Buf[1]&0xff,NxtStringSize);
  181. }
  182. /*:::::::::::::::::::::::::::::::::::::::::::::::::::: Read next string */
  183. if(!ReadFile(pipe, Buf, NxtStringSize, &BytesRead, NULL))
  184. {
  185. *error = GetLastError();
  186. return(RDNS_ERROR);
  187. }
  188. /*:::::::::::::::::::::::::::::::::::::::::::::::::::::: Display string */
  189. Buf[BytesRead] = 0;
  190. printf("%s",Buf);
  191. return(RDNS_OK);
  192. }
  193. /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
  194. /*:::::::::::::::::::::::::: Control-C handler :::::::::::::::::::::::::::::*/
  195. /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
  196. BOOL CntrlHandler(ULONG CtrlType)
  197. {
  198. BOOL rtn = FALSE; // Default return event not handled
  199. /*:::::::::::::::::::::::::::::::::::::::::::: Process control C event */
  200. if(CtrlType == CTRL_C_EVENT)
  201. {
  202. if(YodaEvent)
  203. {
  204. SetEvent(YodaEvent);
  205. Beep(0x100,1000);
  206. }
  207. rtn = TRUE; // Tell call the control event has been handled */
  208. }
  209. return(rtn);
  210. }
  211. /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
  212. /*:::::::::::::::::::::::::: Enter Debug Shell :::::::::::::::::::::::::::::*/
  213. /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
  214. VOID DebugShell(CHAR *LastPrint, CHAR *Command)
  215. {
  216. switch(Command[1])
  217. {
  218. // Open log file
  219. case 'o' :
  220. case 'O' :
  221. if((LogHandle = fopen(DEFAULT_LOG_FILE,"rw")) == NULL)
  222. printf("\nVDMDEBUG : Unable to open log file (%s)\n",DEFAULT_LOG_FILE);
  223. else
  224. printf("\nVDMDEBUG : Opened log file (%s)\n",DEFAULT_LOG_FILE);
  225. break;
  226. // Close log file
  227. if(LogHandle == NULL)
  228. printf("\nVDMDEBUG : Log file not open\n");
  229. else
  230. {
  231. fclose(LogHandle);
  232. printf("\nVDMDEBUG : Closed log file (%s)\n",DEFAULT_LOG_FILE);
  233. }
  234. break;
  235. default:
  236. printf("\nVDMDEBUG : Unrecognised Command\n");
  237. break;
  238. }
  239. printf("%s",LastPrint); // Print out orginal prompt
  240. }