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.

442 lines
9.8 KiB

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <malloc.h>
  6. #include <ctype.h>
  7. #include "demexp.h"
  8. #include "softpc.h"
  9. #include <cmdsvc.h>
  10. #include <xmssvc.h>
  11. #include <dbgexp.h>
  12. #include "xwincon.h"
  13. #include "fun.h"
  14. #include <conapi.h>
  15. #define VDM_VIRTUAL_INTERRUPTS 0x00000200L
  16. extern CONTEXT IntelRegisters;
  17. VOID DumpIntelRegs();
  18. VOID ParseSwitches( int, char**);
  19. VOID usage();
  20. BOOL ConInit (VOID);
  21. extern VOID VDMCtrlCHandler(ULONG);
  22. INT flOptions;
  23. HANDLE OutputHandle;
  24. HANDLE InputHandle;
  25. HANDLE SCSCreateEvent;
  26. char *EmDirectory;
  27. BOOL scaffMin = FALSE;
  28. BOOL scaffWow = FALSE;
  29. BOOL VDMForWOW = FALSE;
  30. CHAR BootLetter;
  31. void main (argc, argv)
  32. int argc;
  33. char *argv[];
  34. {
  35. PSZ psz,pszNULL;
  36. HANDLE hfile;
  37. DWORD BytesRead;
  38. int i;
  39. PCHAR FileAddress;
  40. BOOL IsFirst;
  41. int temp_argc = argc;
  42. char **temp_argv = argv;
  43. // DebugBreak();
  44. if(SetConsoleCtrlHandler((PHANDLER_ROUTINE)VDMCtrlCHandler,TRUE)
  45. == FALSE) {
  46. VDprint(
  47. VDP_LEVEL_INFO,
  48. ("CtrlC Handler Could'nt be installed\n")
  49. );
  50. }
  51. // Tell the console that we want the last event (i.e when the
  52. // window is just to be destroyed.
  53. SetLastConsoleEventActive();
  54. // Check if the VDM Is for WOW
  55. while (--temp_argc > 0) {
  56. psz = *++temp_argv;
  57. if (*psz == '-' || *psz == '/') {
  58. psz++;
  59. if(tolower(*psz) == 'w'){
  60. VDMForWOW = TRUE;
  61. break;
  62. }
  63. }
  64. }
  65. // This following API is required for recovery purposes. This
  66. // tells the basesrv that VDM has hooked ctrlc event. After
  67. // this it will always get the termination notification. If
  68. // the window is killed before we hook ctrl-c then basesrv
  69. // will know that data structures for this VDM has to be
  70. // freed. This should be the first call to base.dll.
  71. VDMOperationStarted (VDMForWOW);
  72. EmDirectory = NULL;
  73. // Hide the cmd window of WOWVDM
  74. if(VDMForWOW)
  75. VDMConsoleOperation((DWORD)VDM_HIDE_WINDOW);
  76. ParseSwitches( argc, argv );
  77. IsFirst = GetNextVDMCommand(NULL);
  78. for (i = 0; i < argc; i++) {
  79. VDprint(
  80. VDP_LEVEL_INFO,
  81. ("%s\n", argv[i])
  82. );
  83. }
  84. VDbreak(VDB_LEVEL_INFO);
  85. if (EmDirectory == NULL) {
  86. usage();
  87. TerminateVDM();
  88. }
  89. // Sudeepb 26-Dec-1991 Temporary code to make
  90. // the life easy for WOW's internal users such that they dont have
  91. // to change the config.sys as per their setup.
  92. FixConfigFile (EmDirectory,IsFirst);
  93. pszNULL = strchr(EmDirectory,'\0');
  94. psz = EmDirectory;
  95. while(*psz == ' ' || *psz == '\t')
  96. psz++;
  97. BootLetter = *psz;
  98. host_cpu_init();
  99. sas_init(1024L * 1024L + 64L * 1024L);
  100. // Initialize ROM support
  101. BiosInit(argc, argv);
  102. // Initialize console support
  103. if (!ConInit()) {
  104. VDprint(
  105. VDP_LEVEL_ERROR,
  106. ("SoftPC: error initializing console\n")
  107. );
  108. TerminateVDM();
  109. }
  110. // Initialize WOW
  111. CMDInit (argc,argv);
  112. // Initialize DOSEm
  113. if(!DemInit (argc,argv,EmDirectory)) {
  114. VDprint(
  115. VDP_LEVEL_ERROR,
  116. ("SoftPC: error initializing DOSEm\n")
  117. );
  118. TerminateVDM();
  119. }
  120. // Initialize XMS
  121. if(!XMSInit (argc,argv)) {
  122. VDprint(
  123. VDP_LEVEL_ERROR,
  124. ("SoftPC: error initializing XMS\n")
  125. );
  126. TerminateVDM();
  127. }
  128. // Initialize DBG
  129. if(!DBGInit (argc,argv)) {
  130. VDprint(
  131. VDP_LEVEL_ERROR,
  132. ("SoftPC: error initializing DBG\n")
  133. );
  134. TerminateVDM();
  135. }
  136. // Prepare to load ntio.sys
  137. strcat (EmDirectory,"\\ntio.sys");
  138. hfile = CreateFile(EmDirectory,
  139. GENERIC_READ,
  140. FILE_SHARE_READ,
  141. NULL,
  142. OPEN_EXISTING,
  143. FILE_ATTRIBUTE_NORMAL,
  144. NULL );
  145. if (hfile == (HANDLE)0xffffffff) {
  146. VDprint(
  147. VDP_LEVEL_ERROR,
  148. ("SoftPC: could not open file %s. Error %d\n",
  149. EmDirectory,
  150. GetLastError())
  151. );
  152. TerminateVDM();
  153. }
  154. FileAddress = (PCHAR)0x700;
  155. BytesRead = 1;
  156. while (BytesRead) {
  157. if (!ReadFile(hfile, FileAddress, 16384, &BytesRead, NULL)) {
  158. VDprint(
  159. VDP_LEVEL_ERROR,
  160. ("SoftPC: read failure on file %s. Error %d\n",
  161. EmDirectory,
  162. GetLastError())
  163. );
  164. TerminateVDM();
  165. }
  166. VDprint(VDP_LEVEL_INFO,
  167. ("SoftPC: read a block of file %s\n",
  168. EmDirectory)
  169. );
  170. FileAddress = (PCHAR)FileAddress + BytesRead;
  171. }
  172. VDprint(VDP_LEVEL_WARNING,
  173. ("SoftPC: using Emulation file %s\n",
  174. EmDirectory)
  175. );
  176. VDbreak(VDB_LEVEL_INFO);
  177. CloseHandle (hfile);
  178. // restore the emulation directory
  179. *pszNULL = 0;
  180. IntelRegisters.Eip = 0x0;
  181. IntelRegisters.SegCs = 0x70;
  182. IntelRegisters.EFlags = VDM_VIRTUAL_INTERRUPTS;
  183. host_simulate();
  184. if (IntelRegisters.EFlags & VDM_VIRTUAL_INTERRUPTS) {
  185. VDprint(VDP_LEVEL_INFO, ("Virtual ints enabled\n"));
  186. } else {
  187. VDprint(VDP_LEVEL_INFO, ("Virtual ints disabled\n"));
  188. }
  189. DumpIntelRegs();
  190. }
  191. #define MAX_CONFIG_SIZE 1024
  192. VOID FixConfigFile (pszBin86Dir,IsFirstVDM)
  193. PSZ pszBin86Dir;
  194. BOOL IsFirstVDM;
  195. {
  196. // Temporary code. To be thrown out once we have full configuration
  197. // and installation.
  198. CHAR ConfigFile[]="?:\\config.vdm";
  199. CHAR Buffer [MAX_CONFIG_SIZE];
  200. DWORD len,i;
  201. DWORD BytesRead,BytesWritten;
  202. HANDLE hfile;
  203. if (IsFirstVDM == FALSE)
  204. return;
  205. ConfigFile[0] = *pszBin86Dir;
  206. hfile = CreateFile( ConfigFile,
  207. GENERIC_WRITE | GENERIC_READ,
  208. FILE_SHARE_READ,
  209. NULL,
  210. OPEN_EXISTING,
  211. FILE_ATTRIBUTE_NORMAL,
  212. NULL );
  213. if (hfile == (HANDLE)0xffffffff) {
  214. DbgPrint ("config.vdm is'nt found on the root drive of yout NT trre\n");
  215. return;
  216. }
  217. if (!ReadFile(hfile, Buffer, MAX_CONFIG_SIZE, &BytesRead, NULL)){
  218. DbgPrint ("config.vdm could'nt be read\n, %x\n",GetLastError ());
  219. CloseHandle (hfile);
  220. return;
  221. }
  222. if (BytesRead == MAX_CONFIG_SIZE) {
  223. DbgPrint ("config.vdm is too big, could'nt perform macro substitution\n");
  224. CloseHandle (hfile);
  225. return;
  226. }
  227. SetFilePointer (hfile,
  228. 0,
  229. NULL,
  230. FILE_BEGIN);
  231. len = strlen (pszBin86Dir);
  232. for (i=0; i < BytesRead; i++) {
  233. if (Buffer [i] != '@'){
  234. WriteFile (hfile,
  235. &Buffer[i],
  236. 1,
  237. &BytesWritten,
  238. NULL);
  239. }
  240. else {
  241. WriteFile (hfile,
  242. pszBin86Dir,
  243. len,
  244. &BytesWritten,
  245. NULL);
  246. }
  247. }
  248. CloseHandle (hfile);
  249. return;
  250. }
  251. VOID DumpIntelRegs()
  252. {
  253. VDprint(VDP_LEVEL_ERROR,("EAX = %lx\n",IntelRegisters.Eax));
  254. VDprint(VDP_LEVEL_ERROR,("Ebx = %lx\n",IntelRegisters.Ebx));
  255. VDprint(VDP_LEVEL_ERROR,("Ecx = %lx\n",IntelRegisters.Ecx));
  256. VDprint(VDP_LEVEL_ERROR,("Edx = %lx\n",IntelRegisters.Edx));
  257. VDprint(VDP_LEVEL_ERROR,("Esi = %lx\n",IntelRegisters.Esi));
  258. VDprint(VDP_LEVEL_ERROR,("Edi = %lx\n",IntelRegisters.Edi));
  259. VDprint(VDP_LEVEL_ERROR,("Ebp = %lx\n",IntelRegisters.Ebp));
  260. VDprint(VDP_LEVEL_ERROR,("SegDs = %lx\n",IntelRegisters.SegDs));
  261. VDprint(VDP_LEVEL_ERROR,("SegEs = %lx\n",IntelRegisters.SegEs));
  262. VDprint(VDP_LEVEL_ERROR,("SegFs = %lx\n",IntelRegisters.SegFs));
  263. VDprint(VDP_LEVEL_ERROR,("SegGs = %lx\n",IntelRegisters.SegGs));
  264. VDprint(VDP_LEVEL_ERROR,("EFlags = %lx\n",IntelRegisters.EFlags));
  265. VDprint(VDP_LEVEL_ERROR,("SS:Esp = %lx:",IntelRegisters.SegSs));
  266. VDprint(VDP_LEVEL_ERROR,("%lx\n",IntelRegisters.Esp));
  267. VDprint(VDP_LEVEL_ERROR,("CS:Eip = %lx:",IntelRegisters.SegCs));
  268. VDprint(VDP_LEVEL_ERROR,("%lx\n",IntelRegisters.Eip));
  269. }
  270. VOID ParseSwitches(
  271. int argc,
  272. char **argv
  273. )
  274. {
  275. int i;
  276. for (i = 1; i < argc; i++){
  277. if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
  278. switch (argv[i][1]) {
  279. case 's' :
  280. case 'S' :
  281. sscanf(&argv[i][2], "%x", &VdmDebugLevel);
  282. VDprint(
  283. VDP_LEVEL_WARNING,
  284. ("VdmDebugLevel = %x\n",
  285. VdmDebugLevel)
  286. );
  287. break;
  288. case 'f' :
  289. case 'F' :
  290. // Note this memory is freed by DEM.
  291. if((EmDirectory = (PCHAR)malloc (strlen (&argv[i][2]) +
  292. 1 +
  293. sizeof("\\ntdos.sys") +
  294. 1
  295. )) == NULL){
  296. DbgPrint("SoftPC: Not Enough Memory \n");
  297. TerminateVDM();
  298. }
  299. strcpy(EmDirectory,&argv[i][2]);
  300. break;
  301. case 't' :
  302. case 'T' :
  303. flOptions |= OPT_TERMINAL;
  304. break;
  305. case 'm' :
  306. case 'M' :
  307. scaffMin = TRUE;
  308. break;
  309. case 'w' :
  310. case 'W' :
  311. scaffWow = TRUE;
  312. }
  313. } else {
  314. break;
  315. }
  316. }
  317. }
  318. VOID usage()
  319. {
  320. DbgPrint("SoftPC Usage: softpc -F<emulation file> [-D#] [<drive>:=<virtual disk>] [dos command line]\n");
  321. }
  322. VOID TerminateVDM(void)
  323. {
  324. if(VDMForWOW)
  325. // Kill everything for WOW VDM
  326. ExitVDM(VDMForWOW,(ULONG)-1);
  327. else
  328. ExitVDM(FALSE,0);
  329. ExitProcess (0);
  330. }
  331. DWORD SCSConsoleThread(LPVOID lp)
  332. {
  333. SetEvent(SCSCreateEvent);
  334. BiosKbdReadLoop();
  335. return TRUE;
  336. }
  337. BOOL ConInit (VOID)
  338. {
  339. DWORD SCSThreadId;
  340. HANDLE InputThread;
  341. OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
  342. InputHandle = GetStdHandle(STD_INPUT_HANDLE);
  343. SCSCreateEvent = CreateEvent( NULL, TRUE, FALSE,NULL );
  344. InputThread = CreateThread(
  345. (LPSECURITY_ATTRIBUTES)0,
  346. 8192,
  347. (LPTHREAD_START_ROUTINE)SCSConsoleThread,
  348. (LPVOID)0,
  349. STANDARD_RIGHTS_REQUIRED,
  350. &SCSThreadId
  351. );
  352. WaitForSingleObject(SCSCreateEvent, -1);
  353. CloseHandle(SCSCreateEvent);
  354. return TRUE;
  355. }