ReactOS  0.4.14-dev-604-gcfdd483
dem.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: GPL - See COPYING in the top level directory
3  * PROJECT: ReactOS Virtual DOS Machine
4  * FILE: subsystems/mvdm/ntvdm/dos/dem.c
5  * PURPOSE: DOS 32-bit Emulation Support Library -
6  * This library is used by the built-in NTVDM DOS32 and by
7  * the NT 16-bit DOS in Windows (via BOPs). It also exposes
8  * exported functions that can be used by VDDs.
9  * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
10  * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
11  */
12 
13 /* INCLUDES *******************************************************************/
14 
15 #include "ntvdm.h"
16 
17 #define NDEBUG
18 #include <debug.h>
19 
20 #include "emulator.h"
21 #include <isvbop.h>
22 
23 #include "utils.h"
24 
25 #include "dem.h"
26 #include "dos/dos32krnl/device.h"
27 #include "dos/dos32krnl/memory.h"
28 #include "dos/dos32krnl/process.h"
29 #include "cpu/bop.h"
30 #include "cpu/cpu.h"
31 
32 #include "bios/bios.h"
33 #include "mouse32.h"
34 
35 #include "vddsup.h"
36 
37 /*
38  * EXPERIMENTAL!
39  * Activate this line if you want to have COMMAND.COM completely external.
40  */
41 // #define COMSPEC_FULLY_EXTERNAL
42 
43 /* PRIVATE VARIABLES **********************************************************/
44 
45 /* PRIVATE FUNCTIONS **********************************************************/
46 
47 /* PUBLIC VARIABLES ***********************************************************/
48 
49 /* PUBLIC FUNCTIONS ***********************************************************/
50 
51 
52 /******************************************************************************\
53 |** DOS DEM Kernel helpers **|
54 \******************************************************************************/
55 
56 
58 {
59  /* Save AX and BX */
60  USHORT AX = getAX();
61  USHORT BX = getBX();
62 
63  /*
64  * Set the parameters:
65  * AL contains the character to print,
66  * BL contains the character attribute,
67  * BH contains the video page to use.
68  */
69  setAL(Character);
72 
73  /* Call the BIOS INT 10h, AH=0Eh "Teletype Output" */
74  setAH(0x0E);
76 
77  /* Restore AX and BX */
78  setBX(BX);
79  setAX(AX);
80 }
81 
83 {
85 }
86 
87 
89 {
91  LPCSTR DosKernelFileName = "ntdos.sys";
92  HANDLE hDosKernel;
93  ULONG ulDosKernelSize = 0;
94 
95  DPRINT1("You are loading Windows NT DOS!\n");
96 
97  /* Open the DOS kernel file */
98  hDosKernel = FileOpen(DosKernelFileName, &ulDosKernelSize);
99  if (hDosKernel == NULL) goto Quit;
100 
101  /*
102  * Attempt to load the DOS kernel into memory.
103  * The segment where to load the DOS kernel is defined
104  * by the DOS BIOS and is found in DI:0000 .
105  */
106  Success = FileLoadByHandle(hDosKernel,
107  REAL_TO_PHYS(TO_LINEAR(getDI(), 0x0000)),
108  ulDosKernelSize,
109  &ulDosKernelSize);
110 
111  DPRINT1("Windows NT DOS file '%s' loading %s at %04X:%04X, size 0x%X (Error: %u).\n",
112  DosKernelFileName,
113  (Success ? "succeeded" : "failed"),
114  getDI(), 0x0000,
115  ulDosKernelSize,
116  GetLastError());
117 
118  /* Close the DOS kernel file */
119  FileClose(hDosKernel);
120 
121 Quit:
122  if (!Success)
123  {
124  /* We failed everything, stop the VDM */
125  BiosDisplayMessage("Windows NT DOS kernel file '%s' loading failed (Error: %u). The VDM will shut down.\n",
126  DosKernelFileName, GetLastError());
128  return;
129  }
130 }
131 
133 {
134  /* Get the Function Number and skip it */
135  BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
136  setIP(getIP() + 1);
137 
138  switch (FuncNum)
139  {
140  /* Load the DOS kernel */
141  case 0x11:
142  {
144  break;
145  }
146 
147  /* Call 32-bit Driver Strategy Routine */
148  case BOP_DRV_STRATEGY:
149  {
151  break;
152  }
153 
154  /* Call 32-bit Driver Interrupt Routine */
155  case BOP_DRV_INTERRUPT:
156  {
158  break;
159  }
160 
161  default:
162  {
163  DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum);
164  // setCF(1); // Disable, otherwise we enter an infinite loop
165  break;
166  }
167  }
168 }
169 
170 
171 
172 
173 /******************************************************************************\
174 |** DOS Command Process management **|
175 \******************************************************************************/
176 
177 
178 #ifndef STANDALONE
179 static ULONG SessionId = 0;
180 
181 /*
182  * 16-bit Command Interpreter information for DOS reentry
183  */
184 typedef struct _COMSPEC_INFO
185 {
191 
194 
195 // FIXME: Should we need list locking?
197 
198 static PCOMSPEC_INFO
200 {
201  PLIST_ENTRY Pointer;
202  PCOMSPEC_INFO ComSpecInfo;
203 
204  for (Pointer = ComSpecInfoList.Flink; Pointer != &ComSpecInfoList; Pointer = Pointer->Flink)
205  {
206  ComSpecInfo = CONTAINING_RECORD(Pointer, COMSPEC_INFO, Entry);
207  if (ComSpecInfo->ComSpecPsp == Psp) return ComSpecInfo;
208  }
209 
210  return NULL;
211 }
212 
213 static VOID
215 {
216  InsertHeadList(&ComSpecInfoList, &ComSpecInfo->Entry);
217 }
218 
219 static VOID
221 {
222  RemoveEntryList(&ComSpecInfo->Entry);
223  if (ComSpecInfo != &RootCmd)
224  RtlFreeHeap(RtlGetProcessHeap(), 0, ComSpecInfo);
225 }
226 #endif
227 
229 {
230  /* Attach to the console */
231  ConsoleAttach();
233 }
234 
236 {
237  /* Detach from the console */
239  ConsoleDetach();
240 }
241 
242 /*
243  * Data for the next DOS command to run
244  */
245 #ifndef STANDALONE
249 #endif
250 static BOOLEAN First = TRUE;
251 static CHAR CmdLine[MAX_PATH] = ""; // DOS_CMDLINE_LENGTH
252 static CHAR AppName[MAX_PATH] = "";
253 #ifndef STANDALONE
254 static CHAR PifFile[MAX_PATH] = "";
256 static CHAR Desktop[MAX_PATH] = "";
257 static CHAR Title[MAX_PATH] = "";
258 static ULONG EnvSize = 256;
259 static PVOID Env = NULL;
260 #endif
261 
262 #pragma pack(push, 2)
263 
264 /*
265  * This structure is compatible with Windows NT DOS
266  */
267 typedef struct _NEXT_CMD
268 {
286 } NEXT_CMD, *PNEXT_CMD;
287 
288 #pragma pack(pop)
289 
291 {
292 #ifndef STANDALONE
293  PCOMSPEC_INFO ComSpecInfo;
294 #endif
295  SIZE_T CmdLen;
296  PNEXT_CMD DataStruct = (PNEXT_CMD)SEG_OFF_TO_PTR(getDS(), getDX());
297 
298  DPRINT1("CmdStartProcess -- DS:DX = %04X:%04X (DataStruct = 0x%p)\n",
299  getDS(), getDX(), DataStruct);
300 
301  /* Pause the VM */
302  EmulatorPause();
303 
304 #ifndef STANDALONE
305  /* Check whether we need to shell out now in case we were started by a 32-bit app */
306  ComSpecInfo = FindComSpecInfoByPsp(Sda->CurrentPsp);
307  if (ComSpecInfo && ComSpecInfo->Terminated)
308  {
309  RemoveComSpecInfo(ComSpecInfo);
310 
311  DPRINT1("Exit DOS from start-app BOP\n");
312  setCF(1);
313  goto Quit;
314  }
315 
316  /* Clear the structure */
318 
319  /* Initialize the structure members */
323  CommandInfo.CmdLen = sizeof(CmdLine);
325  CommandInfo.AppLen = sizeof(AppName);
327  CommandInfo.PifLen = sizeof(PifFile);
331  CommandInfo.DesktopLen = sizeof(Desktop);
333  CommandInfo.TitleLen = sizeof(Title);
334  CommandInfo.Env = Env;
336 
338 
339 Command:
340 
342  Repeat = FALSE;
343 
344  /* Get the VDM command information */
345  DPRINT1("Calling GetNextVDMCommand in CmdStartProcess: wait for new VDM task...\n");
347  {
348  DPRINT1("CmdStartProcess - GetNextVDMCommand failed, retrying... last error = %d\n", GetLastError());
349  if (CommandInfo.EnvLen > EnvSize)
350  {
351  /* Expand the environment size */
353  CommandInfo.Env = Env = RtlReAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Env, EnvSize);
354 
355  /* Repeat the request */
356  Repeat = TRUE;
357  goto Command;
358  }
359 
360  /* Shouldn't happen */
361  DisplayMessage(L"An unrecoverable failure happened from start-app BOP; exiting DOS.");
362  setCF(1);
363  goto Quit;
364  }
365 
366  // FIXME: What happens if some other 32-bit app is killed while we are waiting there??
367 
368  DPRINT1("CmdStartProcess - GetNextVDMCommand succeeded, start app...\n");
369 
370 #else
371 
372  if (!First)
373  {
374  DPRINT1("Exit DOS from start-app BOP\n");
375  setCF(1);
376  goto Quit;
377  }
378 
379 #endif
380 
381  /* Compute the command line length, not counting the terminating "\r\n" */
382  CmdLen = strlen(CmdLine);
383  if (CmdLen >= 2 && CmdLine[CmdLen - 2] == '\r')
384  CmdLen -= 2;
385 
386  DPRINT1("Starting '%s' ('%.*s')...\n", AppName, CmdLen, CmdLine);
387 
388  /* Start the process */
389  // FIXME: Merge 'Env' with the master environment SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0)
390  // FIXME: Environment
391  RtlCopyMemory(SEG_OFF_TO_PTR(DataStruct->AppNameSeg, DataStruct->AppNameOff), AppName, MAX_PATH);
392  *(PBYTE)(SEG_OFF_TO_PTR(DataStruct->CmdLineSeg, DataStruct->CmdLineOff)) = (BYTE)CmdLen;
394 
395 #ifndef STANDALONE
396  /* Update console title if we run in a separate console */
397  if (SessionId != 0)
399 #endif
400 
401  First = FALSE;
402  setCF(0);
403 
404  DPRINT1("App started!\n");
405 
406 Quit:
407  /* Resume the VM */
408  EmulatorResume();
409 }
410 
412 {
413  DWORD Result;
414 
415  // TODO: improve: this code has strong similarities
416  // with the 'default' case of DosCreateProcess.
417 
419  CHAR CmdLine[sizeof("cmd.exe /c ") + DOS_CMDLINE_LENGTH + 1] = "";
420  LPSTR CmdLinePtr;
421  SIZE_T CmdLineLen;
422 
423  /* Spawn a user-defined 32-bit command preprocessor */
424 
425  // FIXME: Use COMSPEC env var!!
426  CmdLinePtr = CmdLine;
427  strcpy(CmdLinePtr, "cmd.exe /c ");
428  CmdLinePtr += strlen(CmdLinePtr);
429 
430  /* Build a Win32-compatible command-line */
431  CmdLineLen = min(strlen(Command), sizeof(CmdLine) - strlen(CmdLinePtr) - 1);
432  RtlCopyMemory(CmdLinePtr, Command, CmdLineLen);
433  CmdLinePtr[CmdLineLen] = '\0';
434 
435  /* Remove any trailing return carriage character and NULL-terminate the command line */
436  while (*CmdLinePtr && *CmdLinePtr != '\r' && *CmdLinePtr != '\n') CmdLinePtr++;
437  *CmdLinePtr = '\0';
438 
439  DPRINT1("CMD Run Command '%s' ('%s')\n", Command, CmdLine);
440 
441  /*
442  * No need to prepare the stack for DosStartComSpec since we won't start it.
443  */
445  SEG_OFF_TO_PTR(getES(), 0) /*Environment*/,
446  MAKELONG(getIP(), getCS()) /*ReturnAddress*/,
447  FALSE);
448  if (Result != ERROR_SUCCESS)
449  {
450  DosDisplayMessage("Failed to start command '%s' ('%s'). Error: %u\n", Command, CmdLine, Result);
451  setCF(0);
452  setAL((UCHAR)Result);
453  }
454  else
455  {
456  DosDisplayMessage("Command '%s' ('%s') started successfully.\n", Command, CmdLine);
457 #ifndef STANDALONE
458  setCF(Repeat); // Set CF if we need to start a 16-bit process
459 #else
460  setCF(0);
461 #endif
462  }
463 }
464 
466 {
467  DWORD Result;
468 
469  // TODO: improve: this code has strong similarities with the
470  // 'default' case of DosCreateProcess and with the 'case 0x08'.
471 
472  CHAR CmdLine[sizeof("cmd.exe") + 1] = "";
473 
474  /* Spawn a user-defined 32-bit command preprocessor */
475 
476  // FIXME: Use COMSPEC env var!!
477  strcpy(CmdLine, "cmd.exe");
478 
479  DPRINT1("CMD Run 32-bit Command Interpreter '%s'\n", CmdLine);
480 
481  /*
482  * No need to prepare the stack for DosStartComSpec since we won't start it.
483  */
485  SEG_OFF_TO_PTR(getES(), 0) /*Environment*/,
486  MAKELONG(getIP(), getCS()) /*ReturnAddress*/,
487  FALSE);
488  if (Result != ERROR_SUCCESS)
489  {
490  DosDisplayMessage("Failed to start 32-bit Command Interpreter '%s'. Error: %u\n", CmdLine, Result);
491  setCF(0);
492  setAL((UCHAR)Result);
493  }
494  else
495  {
496  DosDisplayMessage("32-bit Command Interpreter '%s' started successfully.\n", CmdLine);
497 #ifndef STANDALONE
498  setCF(Repeat); // Set CF if we need to start a 16-bit process
499 #else
500  setCF(0);
501 #endif
502  }
503 }
504 
506 {
507 #ifndef STANDALONE
508  BOOL Success;
509  PCOMSPEC_INFO ComSpecInfo;
511 #endif
512 
513  /* Pause the VM */
514  EmulatorPause();
515 
516 #ifndef STANDALONE
517  /*
518  * Check whether we need to shell out now in case we were started by a 32-bit app,
519  * or we were started alone along with the root 32-bit app.
520  */
521  ComSpecInfo = FindComSpecInfoByPsp(Sda->CurrentPsp);
522  if ((ComSpecInfo && ComSpecInfo->Terminated) ||
523  (ComSpecInfo == &RootCmd && SessionId != 0))
524  {
525  RemoveComSpecInfo(ComSpecInfo);
526 #endif
527  DPRINT1("Exit DOS from ExitCode (prologue)!\n");
528  setCF(0);
529  goto Quit;
530 #ifndef STANDALONE
531  }
532 
533  /* Clear the VDM structure */
535 
536 Retry:
537  /* Update the VDM state of the task */
538  // CommandInfo.TaskId = SessionId;
541  DPRINT1("Calling GetNextVDMCommand 32bit end of VDM task\n");
543  DPRINT1("GetNextVDMCommand 32bit end of VDM task success = %s, last error = %d\n", Success ? "true" : "false", GetLastError());
544 
545  /*
546  * Check whether we were awaited because the 32-bit process was stopped,
547  * or because it started a new DOS application.
548  */
549  if (CommandInfo.CmdLen != 0 || CommandInfo.AppLen != 0 || CommandInfo.PifLen != 0)
550  {
551  DPRINT1("GetNextVDMCommand end-of-app, this is for a new VDM task - CmdLen = %d, AppLen = %d, PifLen = %d\n",
553 
554  /* Repeat the request */
555  Repeat = TRUE;
556  setCF(1);
557  }
558  else
559  {
560  DPRINT1("GetNextVDMCommand end-of-app, the app stopped\n");
561 
562  /* Check whether we need to shell out now in case we were started by a 32-bit app */
563  ComSpecInfo = FindComSpecInfoByPsp(Sda->CurrentPsp);
564  if (!ComSpecInfo || !ComSpecInfo->Terminated)
565  {
566  DPRINT1("Not our 32-bit app, retrying...\n");
567  goto Retry;
568  }
569 
570  ASSERT(ComSpecInfo->Terminated == TRUE);
571 
572  /* Record found, remove it and exit now */
573  RemoveComSpecInfo(ComSpecInfo);
574 
575  DPRINT1("Exit DOS from ExitCode wait!\n");
576  setCF(0);
577  }
578 #endif
579 
580  // FIXME: Use the retrieved exit code as the value of our exit code
581  // when COMMAND.COM will shell-out ??
582 
583 Quit:
584  /* Resume the VM */
585  EmulatorResume();
586 }
587 
589 {
590  /* Get the Function Number and skip it */
591  BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
592  setIP(getIP() + 1);
593 
594  switch (FuncNum)
595  {
596  /* Kill the VDM */
597  case 0x00:
598  {
599  /* Stop the VDM */
601  return;
602  }
603 
604  /*
605  * Get a new app to start
606  *
607  * Input
608  * DS:DX : Data block.
609  *
610  * Output
611  * CF : 0: Success; 1: Failure.
612  */
613  case 0x01:
614  {
615  CmdStartProcess();
616  break;
617  }
618 
619  /*
620  * Check binary format
621  *
622  * Input
623  * DS:DX : Program to check.
624  *
625  * Output
626  * CF : 0: Success; 1: Failure.
627  * AX : Error code.
628  */
629  case 0x07:
630  {
631  DWORD BinaryType;
632  LPSTR ProgramName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX());
633 
634  if (!GetBinaryTypeA(ProgramName, &BinaryType))
635  {
636  /* An error happened, bail out */
637  setCF(1);
639  break;
640  }
641 
642  // FIXME: We only support DOS binaries for now...
643  ASSERT(BinaryType == SCS_DOS_BINARY);
644  if (BinaryType != SCS_DOS_BINARY)
645  {
646  /* An error happened, bail out */
647  setCF(1);
649  break;
650  }
651 
652  /* Return success: DOS application */
653  setCF(0);
654  break;
655  }
656 
657  /*
658  * Start an external command
659  *
660  * Input
661  * DS:SI : Command to start.
662  * ES : Environment block segment.
663  * AL : Current drive number.
664  * AH : 0: Directly start the command;
665  * 1: Use "cmd.exe /c" to start the command.
666  *
667  * Output
668  * CF : 0: Shell-out; 1: Continue.
669  * AL : Error/Exit code.
670  */
671  case 0x08:
672  {
674  break;
675  }
676 
677  /*
678  * Start the default 32-bit command interpreter (COMSPEC)
679  *
680  * Input
681  * ES : Environment block segment.
682  * AL : Current drive number.
683  *
684  * Output
685  * CF : 0: Shell-out; 1: Continue.
686  * AL : Error/Exit code.
687  */
688  case 0x0A:
689  {
691  break;
692  }
693 
694  /*
695  * Set exit code
696  *
697  * Input
698  * DX : Exit code
699  *
700  * Output
701  * CF : 0: Shell-out; 1: Continue.
702  */
703  case 0x0B:
704  {
705  CmdSetExitCode();
706  break;
707  }
708 
709  /*
710  * Get start information
711  *
712  * Output
713  * AL : 0 (resp. 1): Started from (resp. without) an existing console.
714  */
715  case 0x10:
716  {
717 #ifndef STANDALONE
718  /*
719  * When a new instance of our (internal) COMMAND.COM is started,
720  * we check whether we need to run a 32-bit COMSPEC. This goes by
721  * checking whether we were started in a new console (no parent
722  * console process) or from an existing one.
723  *
724  * However COMMAND.COM can also be started in the case where a
725  * 32-bit process (started by a 16-bit parent) wants to start a new
726  * 16-bit process: to ensure DOS reentry we need to start a new
727  * instance of COMMAND.COM. On Windows the COMMAND.COM is started
728  * just before the 32-bit process (in fact, it is this COMMAND.COM
729  * which starts the 32-bit process via an undocumented command-line
730  * switch '/z', which syntax is:
731  * COMMAND.COM /z\bAPPNAME.EXE
732  * notice the '\b' character inserted in-between. Then COMMAND.COM
733  * issues a BOP_CMD 08h with AH=00h to start the process).
734  *
735  * Instead, we do the reverse, i.e. we start the 32-bit process,
736  * and *only* if needed, i.e. if this process wants to start a
737  * new 16-bit process, we start our COMMAND.COM.
738  *
739  * The problem we then face is that our COMMAND.COM will possibly
740  * want to start a new COMSPEC, however we do not want this.
741  * The chosen solution is to flag this case -- done with the 'Reentry'
742  * boolean -- so that COMMAND.COM will not attempt to start COMSPEC
743  * but instead will directly try to start the 16-bit process.
744  */
745  // setAL(SessionId != 0);
746  setAL((SessionId != 0) && !Reentry);
747  /* Reset 'Reentry' */
748  Reentry = FALSE;
749 #else
750  setAL(0);
751 #endif
752  break;
753  }
754 
755  default:
756  {
757  DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum);
758  // setCF(1); // Disable, otherwise we enter an infinite loop
759  break;
760  }
761  }
762 }
763 
764 #ifndef COMSPEC_FULLY_EXTERNAL
765 /*
766  * Internal COMMAND.COM binary data in the CommandCom array.
767  */
768 #include "command_com.h"
769 #endif
770 
771 static
774  IN DWORD ReturnAddress OPTIONAL,
775  OUT PWORD ComSpecPsp OPTIONAL)
776 {
777  /*
778  * BOOLEAN Permanent
779  * TRUE to simulate the /P switch of command.com: starts AUTOEXEC.BAT/NT
780  * and makes the interpreter permanent (cannot exit).
781  */
782 
783  DWORD Result;
784 
785  if (ComSpecPsp) *ComSpecPsp = 0;
786 
787  Result =
788 #ifndef COMSPEC_FULLY_EXTERNAL
790  CommandCom,
791  sizeof(CommandCom),
792  "COMMAND.COM",
793 #else
795 #ifndef STANDALONE // FIXME: Those values are hardcoded paths on my local test machines!!
796  "C:\\CMDCMD.COM",
797 #else
798  "H:\\DOS_tests\\CMDCMD.COM",
799 #endif // STANDALONE
800 #endif // COMSPEC_FULLY_EXTERNAL
801  NULL,
802  Permanent ? "/P" : "",
803  Environment ? Environment : "", // FIXME: Default environment!
804  ReturnAddress);
805  if (Result != ERROR_SUCCESS) return Result;
806 
807  /* TODO: Read AUTOEXEC.NT/BAT */
808 
809  /* Retrieve the PSP of the COMSPEC (current PSP set by DosLoadExecutable) */
810  if (ComSpecPsp) *ComSpecPsp = Sda->CurrentPsp;
811 
812  return Result;
813 }
814 
815 typedef struct _DOS_START_PROC32
816 {
820 #ifndef STANDALONE
823 #endif
825 
826 static DWORD
827 WINAPI
829 {
830  BOOL Success;
831  PROCESS_INFORMATION ProcessInfo;
832  STARTUPINFOA StartupInfo;
833  DWORD dwExitCode;
835 #ifndef STANDALONE
837  PCOMSPEC_INFO ComSpecInfo = DosStartProc32->ComSpecInfo;
838 #endif
839 
840  /* Set up the VDM, startup and process info structures */
841 #ifndef STANDALONE
843 #endif
844  RtlZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
845  RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
846  StartupInfo.cb = sizeof(StartupInfo);
847 
848  // FIXME: Build suitable 32-bit environment!!
849 
850 #ifndef STANDALONE
851  /*
852  * Wait for signaling a new VDM task and increment the VDM re-entry count so
853  * that we can handle 16-bit apps that may be possibly started by the 32-bit app.
854  */
856  DPRINT1("Calling GetNextVDMCommand reenter++\n");
858  DPRINT1("GetNextVDMCommand reenter++ success = %s, last error = %d\n", Success ? "true" : "false", GetLastError());
859  ++ReentrancyCount;
860 #endif
861 
862  /* Start the process */
863  Success = CreateProcessA(NULL, // ProgramName,
864  DosStartProc32->CommandLine,
865  NULL,
866  NULL,
867  TRUE, // Inherit handles
869  DosStartProc32->Environment,
870  NULL, // lpCurrentDirectory, see "START" command in cmd.exe
871  &StartupInfo,
872  &ProcessInfo);
873 
874 #ifndef STANDALONE
875  /* Signal our caller the process was started */
876  SetEvent(DosStartProc32->hEvent);
877  // After this point, 'DosStartProc32' is not valid anymore.
878 #endif
879 
880  if (Success)
881  {
882  /* Resume the process */
883  ResumeThread(ProcessInfo.hThread);
884 
885  /* Wait for the process to finish running and retrieve its exit code */
886  WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
887  GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
888 
889  /* Close the handles */
890  CloseHandle(ProcessInfo.hThread);
891  CloseHandle(ProcessInfo.hProcess);
892  }
893  else
894  {
895  dwExitCode = GetLastError();
896  }
897 
898 #ifndef STANDALONE
899  ASSERT(ComSpecInfo);
900  ComSpecInfo->Terminated = TRUE;
901  ComSpecInfo->dwExitCode = dwExitCode;
902 
903  /* Decrement the VDM re-entry count */
905  DPRINT1("Calling GetNextVDMCommand reenter--\n");
907  DPRINT1("GetNextVDMCommand reenter-- success = %s, last error = %d\n", Success ? "true" : "false", GetLastError());
908  --ReentrancyCount;
909 
910  return 0;
911 #else
912  return dwExitCode;
913 #endif
914 }
915 
917  IN LPCSTR CommandLine,
919  IN DWORD ReturnAddress OPTIONAL,
920  IN BOOLEAN StartComSpec)
921 {
923  HANDLE CommandThread;
924  DOS_START_PROC32 DosStartProc32;
925 #ifndef STANDALONE
926  BOOL Success;
928 #endif
929 
930  DosStartProc32.ExecutablePath = (LPSTR)ExecutablePath;
931  DosStartProc32.CommandLine = (LPSTR)CommandLine;
932  DosStartProc32.Environment = (LPSTR)Environment;
933 
934 #ifndef STANDALONE
935  DosStartProc32.ComSpecInfo =
936  RtlAllocateHeap(RtlGetProcessHeap(),
938  sizeof(*DosStartProc32.ComSpecInfo));
939  ASSERT(DosStartProc32.ComSpecInfo);
940 
941  DosStartProc32.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
942  ASSERT(DosStartProc32.hEvent);
943 #endif
944 
945  /* Pause the VM and detach from the console */
946  EmulatorPause();
948 
949  /* Start the 32-bit process via another thread */
950  CommandThread = CreateThread(NULL, 0, &CommandThreadProc, &DosStartProc32, 0, NULL);
951  if (CommandThread == NULL)
952  {
953  DisplayMessage(L"FATAL: Failed to create the command processing thread: %d", GetLastError());
954  Result = GetLastError();
955  goto Quit;
956  }
957 
958 #ifndef STANDALONE
959  /* Close the thread handle */
960  CloseHandle(CommandThread);
961 
962  /* Wait for the process to be ready to start */
963  WaitForSingleObject(DosStartProc32.hEvent, INFINITE);
964 
965  /* Wait for any potential new DOS app started by the 32-bit process */
967 
968 Retry:
970  DPRINT1("Calling GetNextVDMCommand 32bit for possible new VDM task...\n");
972  DPRINT1("GetNextVDMCommand 32bit awaited, success = %s, last error = %d\n", Success ? "true" : "false", GetLastError());
973 
974  /*
975  * Check whether we were awaited because the 32-bit process was stopped,
976  * or because it started a new DOS application.
977  */
978  if (CommandInfo.CmdLen != 0 || CommandInfo.AppLen != 0 || CommandInfo.PifLen != 0)
979  {
980  DPRINT1("GetNextVDMCommand 32bit, this is for a new VDM task - CmdLen = %d, AppLen = %d, PifLen = %d\n",
982 
983  /* Repeat the request */
984  Repeat = TRUE;
985 
986  /*
987  * Set 'Reentry' to TRUE or FALSE depending on whether we are going
988  * to reenter with a new COMMAND.COM. See the comment for:
989  * BOP_CMD 0x10 'Get start information'
990  * (dem.c!DosCmdInterpreterBop) for more details.
991  */
992  Reentry = StartComSpec;
993 
994  /* If needed, start a new command interpreter to handle the possible incoming DOS commands */
995  if (StartComSpec)
996  {
997  //
998  // DosStartProcess32 was only called by DosCreateProcess, called from INT 21h,
999  // so the caller stack is already prepared for running a new DOS program
1000  // (Flags, CS and IP, and the extra interrupt number, are already pushed).
1001  //
1002  Result = DosStartComSpec(FALSE, Environment, ReturnAddress,
1003  &DosStartProc32.ComSpecInfo->ComSpecPsp);
1004  if (Result != ERROR_SUCCESS)
1005  {
1006  DosDisplayMessage("Failed to start a new Command Interpreter (Error: %u).\n", Result);
1007  goto Quit;
1008  }
1009  }
1010  else
1011  {
1012  /* Retrieve the PSP of the COMSPEC (current PSP set by DosLoadExecutable) */
1013  DosStartProc32.ComSpecInfo->ComSpecPsp = Sda->CurrentPsp;
1015  }
1016 
1017  /* Insert the new entry in the list; it will be freed when needed by COMMAND.COM */
1018  InsertComSpecInfo(DosStartProc32.ComSpecInfo);
1019  }
1020  else
1021  {
1022  DPRINT1("GetNextVDMCommand 32bit, 32-bit app stopped\n");
1023 
1024  /* Check whether this was our 32-bit app which was killed */
1025  if (!DosStartProc32.ComSpecInfo->Terminated)
1026  {
1027  DPRINT1("Not our 32-bit app, retrying...\n");
1028  goto Retry;
1029  }
1030 
1031  Result = DosStartProc32.ComSpecInfo->dwExitCode;
1032 
1033  /* Delete the entry */
1034  RtlFreeHeap(RtlGetProcessHeap(), 0, DosStartProc32.ComSpecInfo);
1035  }
1036 #else
1037  /* Wait for the thread to finish */
1038  WaitForSingleObject(CommandThread, INFINITE);
1039  GetExitCodeThread(CommandThread, &Result);
1040 
1041  /* Close the thread handle */
1042  CloseHandle(CommandThread);
1043 
1044  DPRINT1("32-bit app stopped\n");
1045 #endif
1046 
1047 Quit:
1048 #ifndef STANDALONE
1049  CloseHandle(DosStartProc32.hEvent);
1050 #endif
1051 
1052  /* Attach to the console and resume the VM */
1054  EmulatorResume();
1055 
1056  return Result;
1057 }
1058 
1059 
1060 
1061 
1062 /******************************************************************************\
1063 |** DOS Bootloader emulation, Startup and Shutdown **|
1064 \******************************************************************************/
1065 
1066 
1067 //
1068 // This function (equivalent of the DOS bootsector) is called by the bootstrap
1069 // loader *BEFORE* jumping at 0000:7C00. What we should do is to write at 0000:7C00
1070 // a BOP call that calls DosInitialize back. Then the bootstrap loader jumps at
1071 // 0000:7C00, our BOP gets called and then we can initialize the 32-bit part of the DOS.
1072 //
1073 
1074 /* 16-bit bootstrap code at 0000:7C00 */
1075 /* Of course, this is not in real bootsector format, because we don't care about it for now */
1076 static BYTE Bootsector1[] =
1077 {
1079 };
1080 /* This portion of code is run if we failed to load the DOS */
1081 // NOTE: This may also be done by the BIOS32.
1082 static BYTE Bootsector2[] =
1083 {
1085 };
1086 
1087 static VOID WINAPI DosInitialize(LPWORD Stack);
1088 
1090 {
1091  /* We write the bootsector at 0000:7C00 */
1092  ULONG_PTR StartAddress = (ULONG_PTR)SEG_OFF_TO_PTR(0x0000, 0x7C00);
1093  ULONG_PTR Address = StartAddress;
1094  CHAR DosKernelFileName[] = ""; // No DOS BIOS file name, therefore we will load DOS32
1095 
1096  DPRINT("DosBootsectorInitialize\n");
1097 
1098  /* Write the "bootsector" */
1100  Address += sizeof(Bootsector1);
1101  RtlCopyMemory((PVOID)Address, DosKernelFileName, sizeof(DosKernelFileName));
1102  Address += sizeof(DosKernelFileName);
1104  Address += sizeof(Bootsector2);
1105 
1106  /* Initialize the callback context */
1107  InitializeContext(&DosContext, 0x0000,
1108  (ULONG_PTR)MEM_ALIGN_UP(0x7C00 + Address - StartAddress, sizeof(WORD)));
1109 
1110  /* Register the DOS Loading BOP */
1112 }
1113 
1114 
1115 //
1116 // This function is called by the DOS bootsector in case we load DOS32.
1117 // It sets up the DOS32 start code then jumps to 0070:0000.
1118 //
1119 
1120 /* 16-bit startup code for DOS32 at 0070:0000 */
1121 static BYTE Startup[] =
1122 {
1125 };
1126 
1127 static VOID WINAPI DosStart(LPWORD Stack);
1128 
1130 {
1131  /* Get the DOS BIOS file name (NULL-terminated) */
1132  // FIXME: Isn't it possible to use some DS:SI instead??
1133  LPCSTR DosBiosFileName = (LPCSTR)SEG_OFF_TO_PTR(getCS(), getIP());
1134  setIP(getIP() + strlen(DosBiosFileName) + 1); // Skip it
1135 
1136  DPRINT("DosInitialize('%s')\n", DosBiosFileName);
1137 
1138  /*
1139  * We succeeded, deregister the DOS Loading BOP
1140  * so that no app will be able to call us back.
1141  */
1143 
1144  /* Register the DOS BOPs */
1147 
1148  if (DosBiosFileName[0] != '\0')
1149  {
1150  BOOLEAN Success = FALSE;
1151  HANDLE hDosBios;
1152  ULONG ulDosBiosSize = 0;
1153 
1154  /* Open the DOS BIOS file */
1155  hDosBios = FileOpen(DosBiosFileName, &ulDosBiosSize);
1156  if (hDosBios == NULL) goto Quit;
1157 
1158  /* Attempt to load the DOS BIOS into memory */
1159  Success = FileLoadByHandle(hDosBios,
1160  REAL_TO_PHYS(TO_LINEAR(0x0070, 0x0000)),
1161  ulDosBiosSize,
1162  &ulDosBiosSize);
1163 
1164  DPRINT1("DOS BIOS file '%s' loading %s at %04X:%04X, size 0x%X (Error: %u).\n",
1165  DosBiosFileName,
1166  (Success ? "succeeded" : "failed"),
1167  0x0070, 0x0000,
1168  ulDosBiosSize,
1169  GetLastError());
1170 
1171  /* Close the DOS BIOS file */
1172  FileClose(hDosBios);
1173 
1174 Quit:
1175  if (!Success)
1176  {
1177  BiosDisplayMessage("DOS BIOS file '%s' loading failed (Error: %u). The VDM will shut down.\n",
1178  DosBiosFileName, GetLastError());
1179  return;
1180  }
1181  }
1182  else
1183  {
1184  /* Load the 16-bit startup code for DOS32 and register its Starting BOP */
1185  RtlCopyMemory(SEG_OFF_TO_PTR(0x0070, 0x0000), Startup, sizeof(Startup));
1186 
1187  // This is the equivalent of BOP_LOAD_DOS, function 0x11 "Load the DOS kernel"
1188  // for the Windows NT DOS.
1190  }
1191 
1192  /* Position execution pointers for DOS startup and return */
1193  setCS(0x0070);
1194  setIP(0x0000);
1195 }
1196 
1198 {
1199  BOOLEAN Success;
1200  DWORD Result;
1201 #ifndef STANDALONE
1202  INT i;
1203 #endif
1204 
1205  DPRINT("DosStart\n");
1206 
1207  /*
1208  * We succeeded, deregister the DOS Starting BOP
1209  * so that no app will be able to call us back.
1210  */
1212 
1213  /* Initialize the callback context */
1215 
1217 // Success &= DosKRNLInitialize();
1218  if (!Success)
1219  {
1220  BiosDisplayMessage("DOS32 loading failed (Error: %u). The VDM will shut down.\n", GetLastError());
1222  return;
1223  }
1224 
1225  /* Load the mouse driver */
1227 
1228 #ifndef STANDALONE
1229 
1230  /* Parse the command line arguments */
1231  for (i = 1; i < NtVdmArgc; i++)
1232  {
1233  if (wcsncmp(NtVdmArgv[i], L"-i", 2) == 0)
1234  {
1235  /* This is the session ID (hex format) */
1236  SessionId = wcstoul(NtVdmArgv[i] + 2, NULL, 16);
1237  }
1238  }
1239 
1240  /* Initialize Win32-VDM environment */
1241  Env = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
1242  if (Env == NULL)
1243  {
1244  DosDisplayMessage("Failed to initialize the global environment (Error: %u). The VDM will shut down.\n", GetLastError());
1246  return;
1247  }
1248 
1249  /* Clear the structure */
1251 
1252  /* Get the initial information */
1256 
1257 #else
1258 
1259  /* Retrieve the command to start */
1260  if (NtVdmArgc >= 2)
1261  {
1262  WideCharToMultiByte(CP_ACP, 0, NtVdmArgv[1], -1, AppName, sizeof(AppName), NULL, NULL);
1263 
1264  if (NtVdmArgc >= 3)
1265  WideCharToMultiByte(CP_ACP, 0, NtVdmArgv[2], -1, CmdLine, sizeof(CmdLine), NULL, NULL);
1266  else
1267  strcpy(CmdLine, "");
1268  }
1269  else
1270  {
1271  DosDisplayMessage("Invalid DOS command line\n");
1273  return;
1274  }
1275 
1276 #endif
1277 
1278  /*
1279  * At this point, CS:IP points to the DOS BIOS exit code. If the
1280  * root command interpreter fails to start (or if it exits), DOS
1281  * exits and the VDM terminates.
1282  */
1283 
1284  /* Start the root command interpreter */
1285  // TODO: Really interpret the 'SHELL=' line of CONFIG.NT, and use it!
1286 
1287  /*
1288  * Prepare the stack for DosStartComSpec:
1289  * push Flags, CS and IP, and an extra WORD.
1290  */
1291  setSP(getSP() - sizeof(WORD));
1292  *((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = (WORD)getEFLAGS();
1293  setSP(getSP() - sizeof(WORD));
1294  *((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = getCS();
1295  setSP(getSP() - sizeof(WORD));
1296  *((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = getIP();
1297  setSP(getSP() - sizeof(WORD));
1298 
1300  MAKELONG(getIP(), getCS()),
1301 #ifndef STANDALONE
1303 #else
1304  NULL
1305 #endif
1306  );
1307  if (Result != ERROR_SUCCESS)
1308  {
1309  /* Unprepare the stack for DosStartComSpec */
1310  setSP(getSP() + 4*sizeof(WORD));
1311 
1312  DosDisplayMessage("Failed to start the Command Interpreter (Error: %u). The VDM will shut down.\n", Result);
1314  return;
1315  }
1316 
1317 #ifndef STANDALONE
1320 #endif
1321 
1322 
1323  /* Attach to the console and resume the VM */
1325  EmulatorResume();
1326 
1327 
1328  return;
1329 }
1330 
1332 {
1333  /*
1334  * Immediate = TRUE: Immediate shutdown;
1335  * FALSE: Delayed shutdown (notification).
1336  */
1337 
1338 #ifndef STANDALONE
1339  if (Immediate)
1340  {
1341  ExitVDM(FALSE, 0);
1342  return TRUE;
1343  }
1344  else
1345  {
1346 // HACK!
1347 extern HANDLE VdmTaskEvent; // see emulator.c
1348 
1349  /*
1350  * Signal the root COMMAND.COM that it should terminate
1351  * when it checks for a new command.
1352  */
1354 
1355  /* If the list is already empty, or just contains only one element, bail out */
1356  // FIXME: Question: if the list has only one element, is it ALWAYS RootCmd ??
1357  // FIXME: The following is hackish.
1358  if ((IsListEmpty(&ComSpecInfoList) ||
1361  ReentrancyCount == 0 &&
1363  {
1364  /* Nothing runs, so exit immediately */
1365  ExitVDM(FALSE, 0);
1366  return TRUE;
1367  }
1368 
1369  return FALSE;
1370  }
1371 #else
1372  UNREFERENCED_PARAMETER(Immediate);
1373  return TRUE;
1374 #endif
1375 }
1376 
1377 
1378 /* PUBLIC EXPORTED APIS *******************************************************/
1379 
1380 // demLFNCleanup
1381 // demLFNGetCurrentDirectory
1382 
1383 // demGetFileTimeByHandle_WOW
1384 // demWOWLFNAllocateSearchHandle
1385 // demWOWLFNCloseSearchHandle
1386 // demWOWLFNEntry
1387 // demWOWLFNGetSearchHandle
1388 // demWOWLFNInit
1389 
1390 DWORD
1391 WINAPI
1393  IN CHAR Unknown,
1394  IN BOOL Flag)
1395 {
1396  UNIMPLEMENTED;
1397  return GetLastError();
1398 }
1399 
1400 DWORD
1401 WINAPI
1403 {
1405 
1406  return GetLastError();
1407 }
1408 
1409 DWORD
1410 WINAPI
1411 demFileFindFirst(OUT PVOID lpFindFileData,
1412  IN LPCSTR FileName,
1413  IN WORD AttribMask)
1414 {
1415  BOOLEAN Success = TRUE;
1416  WIN32_FIND_DATAA FindData;
1417  HANDLE SearchHandle;
1418  PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)lpFindFileData;
1419 
1420  /* Start a search */
1421  SearchHandle = FindFirstFileA(FileName, &FindData);
1422  if (SearchHandle == INVALID_HANDLE_VALUE) return GetLastError();
1423 
1424  do
1425  {
1426  /* Check the attributes and retry as long as we haven't found a matching file */
1427  if (!((FindData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN |
1430  & ~AttribMask))
1431  {
1432  break;
1433  }
1434  }
1435  while ((Success = FindNextFileA(SearchHandle, &FindData)));
1436 
1437  /* If we failed at some point, close the search and return an error */
1438  if (!Success)
1439  {
1440  FindClose(SearchHandle);
1441  return GetLastError();
1442  }
1443 
1444  /* Fill the block */
1445  FindFileBlock->DriveLetter = DosData->Sda.CurrentDrive + 'A';
1446  FindFileBlock->AttribMask = AttribMask;
1447  FindFileBlock->SearchHandle = SearchHandle;
1448  FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes);
1449  FileTimeToDosDateTime(&FindData.ftLastWriteTime,
1450  &FindFileBlock->FileDate,
1451  &FindFileBlock->FileTime);
1452  FindFileBlock->FileSize = FindData.nFileSizeHigh ? 0xFFFFFFFF
1453  : FindData.nFileSizeLow;
1454  /* Build a short path name */
1455  if (*FindData.cAlternateFileName)
1456  strncpy(FindFileBlock->FileName, FindData.cAlternateFileName, sizeof(FindFileBlock->FileName));
1457  else
1458  GetShortPathNameA(FindData.cFileName, FindFileBlock->FileName, sizeof(FindFileBlock->FileName));
1459 
1460  return ERROR_SUCCESS;
1461 }
1462 
1463 DWORD
1464 WINAPI
1465 demFileFindNext(OUT PVOID lpFindFileData)
1466 {
1467  WIN32_FIND_DATAA FindData;
1468  PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)lpFindFileData;
1469 
1470  do
1471  {
1472  /* Continue searching as long as we haven't found a matching file */
1473 
1474  /* If we failed at some point, close the search and return an error */
1475  if (!FindNextFileA(FindFileBlock->SearchHandle, &FindData))
1476  {
1477  FindClose(FindFileBlock->SearchHandle);
1478  return GetLastError();
1479  }
1480  }
1481  while ((FindData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN |
1484  & ~FindFileBlock->AttribMask);
1485 
1486  /* Update the block */
1487  FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes);
1488  FileTimeToDosDateTime(&FindData.ftLastWriteTime,
1489  &FindFileBlock->FileDate,
1490  &FindFileBlock->FileTime);
1491  FindFileBlock->FileSize = FindData.nFileSizeHigh ? 0xFFFFFFFF
1492  : FindData.nFileSizeLow;
1493  /* Build a short path name */
1494  if (*FindData.cAlternateFileName)
1495  strncpy(FindFileBlock->FileName, FindData.cAlternateFileName, sizeof(FindFileBlock->FileName));
1496  else
1497  GetShortPathNameA(FindData.cFileName, FindFileBlock->FileName, sizeof(FindFileBlock->FileName));
1498 
1499  return ERROR_SUCCESS;
1500 }
1501 
1502 UCHAR
1503 WINAPI
1505 {
1506  UNIMPLEMENTED;
1507  return DOSDEVICE_DRIVE_UNKNOWN;
1508 }
1509 
1510 BOOL
1511 WINAPI
1513  IN BOOL Unknown)
1514 {
1515  UNIMPLEMENTED;
1516  return FALSE;
1517 }
1518 
1519 DWORD
1520 WINAPI
1522  OUT PUCHAR DriveNumber)
1523 {
1524  UNIMPLEMENTED;
1525  return ERROR_SUCCESS;
1526 }
1527 
1528 /* EOF */
static BYTE Startup[]
Definition: dem.c:1121
HANDLE hEvent
Definition: dem.c:822
USHORT Unknown4
Definition: dem.c:281
LPSTR Desktop
Definition: vdm.h:84
static PCOMSPEC_INFO FindComSpecInfoByPsp(WORD Psp)
Definition: dem.c:199
#define DOS_OUTPUT_HANDLE
Definition: dos.h:43
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:45
#define IN
Definition: typedefs.h:38
ULONG Unknown2
Definition: dem.c:278
INT NtVdmArgc
Definition: ntvdm.c:28
VOID WINAPI setIP(USHORT)
Definition: registers.c:471
USHORT WINAPI getBX(VOID)
Definition: registers.c:170
WORD CurrentPsp
Definition: dos.h:156
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define BOP_START_DOS
Definition: dem.h:24
#define CloseHandle
Definition: compat.h:406
BYTE VideoPage
Definition: bios.h:66
VOID WINAPI setBL(UCHAR)
Definition: registers.c:205
ULONG DesktopLen
Definition: vdm.h:85
ULONG ExitCode
Definition: vdm.h:72
VOID DosCharPrint(CHAR Character)
Definition: dem.c:82
#define ERROR_SUCCESS
Definition: deptool.c:10
USHORT WINAPI getSI(VOID)
Definition: registers.c:404
#define WideCharToMultiByte
Definition: compat.h:101
WORD ComSpecPsp
Definition: dem.c:188
#define LOBYTE(W)
Definition: jmemdos.c:487
HANDLE SearchHandle
Definition: dos.h:128
LPSTR CmdLine
Definition: vdm.h:77
static VDM_COMMAND_INFO CommandInfo
Definition: dem.c:246
static VOID InsertComSpecInfo(PCOMSPEC_INFO ComSpecInfo)
Definition: dem.c:214
WCHAR CurrentDirectory[1024]
Definition: chkdsk.c:74
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
DWORD WINAPI demClientErrorEx(IN HANDLE FileHandle, IN CHAR Unknown, IN BOOL Flag)
Definition: dem.c:1392
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
VOID VidBiosAttachToConsole(VOID)
Definition: vidbios.c:3907
USHORT Unknown1
Definition: dem.c:277
VOID WINAPI setAH(UCHAR)
Definition: registers.c:135
#define BIOS_CODE_SEGMENT
Definition: dos.h:30
#define SYSTEM_ENV_BLOCK
Definition: dos.h:37
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define BOP_DRV_STRATEGY
Definition: device.h:18
VOID RegisterBop(BYTE BopCode, EMULATOR_BOP_PROC BopHandler)
Definition: bop.c:29
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1168
#define CP_ACP
Definition: compat.h:99
Definition: dem.c:267
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
unsigned char * PUCHAR
Definition: retypes.h:3
VOID WINAPI setAX(USHORT)
Definition: registers.c:121
VOID InitializeContext(IN PCALLBACK16 Context, IN USHORT Segment, IN USHORT Offset)
Definition: callback.c:60
char CHAR
Definition: xmlstorage.h:175
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
static VOID RemoveComSpecInfo(PCOMSPEC_INFO ComSpecInfo)
Definition: dem.c:220
VOID Int32Call(IN PCALLBACK16 Context, IN BYTE IntNumber)
Definition: int32.c:151
#define HIBYTE(W)
Definition: jmemdos.c:486
static CHAR CmdLine[MAX_PATH]
Definition: dem.c:251
static CHAR AppName[MAX_PATH]
Definition: dem.c:252
#define BOP_UNSIMULATE
Definition: isvbop.h:31
BOOLEAN DosShutdown(BOOLEAN Immediate)
Definition: dem.c:1331
#define DOS_CMDLINE_LENGTH
Definition: process.h:13
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
VOID WINAPI setAL(UCHAR)
Definition: registers.c:149
PBIOS_DATA_AREA Bda
Definition: bios.c:42
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static COMSPEC_INFO RootCmd
Definition: dem.c:192
USHORT PifLen
Definition: vdm.h:92
#define AX
Definition: i386-dis.c:415
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
DWORD dwExitCode
Definition: dem.c:187
#define CREATE_DEFAULT_ERROR_MODE
Definition: winbase.h:194
static VOID DemLoadNTDOSKernel(VOID)
Definition: dem.c:88
HANDLE VdmTaskEvent
Definition: emulator.c:51
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
Definition: shell.h:41
_In_ PVOID Parameter
Definition: ldrtypes.h:241
BOOL WINAPI FindNextFileA(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAA lpFindFileData)
Definition: find.c:336
VOID FileClose(IN HANDLE FileHandle)
Definition: utils.c:21
USHORT CmdLen
Definition: vdm.h:90
VOID WINAPI ExitVDM(BOOL IsWow, ULONG iWowTask)
Definition: vdm.c:1384
char * LPSTR
Definition: xmlstorage.h:182
#define DosDisplayMessage(Format,...)
Definition: dem.h:37
#define DEFAULT_ATTRIBUTE
Definition: vidbios.h:21
DWORD WINAPI demFileFindNext(OUT PVOID lpFindFileData)
Definition: dem.c:1465
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2561
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
int32_t INT
Definition: typedefs.h:56
#define STANDALONE
Definition: testlist.c:3
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
LIST_ENTRY Entry
Definition: dem.c:186
static VOID WINAPI DosInitialize(LPWORD Stack)
Definition: dem.c:1129
static VOID DosProcessConsoleAttach(VOID)
Definition: dem.c:228
DOS_SDA Sda
Definition: dos.h:247
#define BIOS_VIDEO_INTERRUPT
Definition: vidbios.h:15
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
VOID Dem_BiosCharPrint(CHAR Character)
Definition: dem.c:57
PDOS_DATA DosData
Definition: dos.c:45
struct _DOS_START_PROC32 DOS_START_PROC32
UCHAR Attributes
Definition: dos.h:131
uint32_t ULONG_PTR
Definition: typedefs.h:63
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
static LIST_ENTRY ComSpecInfoList
Definition: dem.c:196
USHORT CurDirectoryLen
Definition: vdm.h:93
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:540
static ULONG EnvSize
Definition: dem.c:258
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HANDLE FileHandle
Definition: stats.c:38
VOID WINAPI setSP(USHORT)
Definition: registers.c:351
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define CREATE_SUSPENDED
Definition: winbase.h:178
#define SCS_DOS_BINARY
Definition: winbase.h:235
BYTE CurrentDrive
Definition: dos.h:159
ULONG WINAPI getEFLAGS(VOID)
Definition: registers.c:680
unsigned int BOOL
Definition: ntddk_ex.h:94
PCOMSPEC_INFO ComSpecInfo
Definition: dem.c:821
USHORT Unknown3
Definition: dem.c:280
VOID DosPrintCharacter(WORD FileHandle, CHAR Character)
Definition: bios.c:152
#define BOP_DOS
Definition: dem.h:25
CALLBACK16 DosContext
Definition: dos.c:40
#define BOP_DRV_INTERRUPT
Definition: device.h:19
VOID WINAPI setCF(ULONG)
Definition: registers.c:573
#define DOSDEVICE_DRIVE_UNKNOWN
Definition: obtypes.h:163
#define REAL_TO_PHYS(ptr)
Definition: emulator.h:33
#define VDM_GET_FIRST_COMMAND
Definition: vdm.h:61
#define MAKELONG(a, b)
Definition: typedefs.h:248
unsigned char BOOLEAN
#define ERROR_BAD_EXE_FORMAT
Definition: winerror.h:251
DWORD FileSize
Definition: dos.h:134
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
#define BOP_CMD
Definition: dem.h:26
smooth NULL
Definition: ftsmooth.c:416
DWORD WINAPI demFileFindFirst(OUT PVOID lpFindFileData, IN LPCSTR FileName, IN WORD AttribMask)
Definition: dem.c:1411
static WCHAR Address[46]
Definition: ping.c:68
#define VDM_FLAG_RETRY
Definition: vdm.h:56
LPSTR ExecutablePath
Definition: dem.c:817
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
WCHAR ** NtVdmArgv
Definition: ntvdm.c:29
#define VDM_FLAG_DOS
Definition: vdm.h:55
IN PSCSI_REQUEST_BLOCK IN OUT NTSTATUS IN OUT BOOLEAN * Retry
Definition: class2.h:49
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
void DPRINT(...)
Definition: polytest.cpp:61
USHORT VDMState
Definition: vdm.h:94
#define VDM_DEC_REENTER_COUNT
Definition: vdm.h:58
USHORT Flags
Definition: dem.c:285
const char * LPCSTR
Definition: xmlstorage.h:183
VOID VidBiosDetachFromConsole(VOID)
Definition: vidbios.c:3920
VOID DeviceStrategyBop(VOID)
Definition: device.c:430
static CHAR Desktop[MAX_PATH]
Definition: dem.c:256
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define VDM_FLAG_NESTED_TASK
Definition: vdm.h:59
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
static DWORD WINAPI CommandThreadProc(LPVOID Parameter)
Definition: dem.c:828
#define BOP_LOAD_DOS
Definition: dem.h:23
static VOID DosProcessConsoleDetach(VOID)
Definition: dem.c:235
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
struct _DOS_START_PROC32 * PDOS_START_PROC32
WORD * PWORD
Definition: pedump.c:67
static BYTE Bootsector2[]
Definition: dem.c:1082
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
USHORT NumDrives
Definition: dem.c:272
LPSTR CurDirectory
Definition: vdm.h:80
DWORD cb
Definition: winbase.h:803
struct _NEXT_CMD NEXT_CMD
struct _DOS_FIND_FILE_BLOCK * PDOS_FIND_FILE_BLOCK
static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
Definition: dem.c:588
BOOLEAN DosBIOSInitialize(VOID)
Definition: bios.c:221
USHORT WINAPI getES(VOID)
Definition: registers.c:522
struct Command Command
USHORT CmdLineSeg
Definition: dem.c:273
USHORT WINAPI getIP(VOID)
Definition: registers.c:464
BOOL ConsoleAttach(VOID)
Definition: console.c:398
UCHAR AttribMask
Definition: dos.h:126
VOID ConsoleDetach(VOID)
Definition: console.c:424
LPSTR PifFile
Definition: vdm.h:79
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4742
DWORD WINAPI GetShortPathNameA(IN LPCSTR lpszLongPath, OUT LPSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1751
BOOLEAN Terminated
Definition: dem.c:189
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:6
USHORT AppLen
Definition: vdm.h:91
Definition: xml2sdb.h:79
unsigned short WORD
Definition: ntddk_ex.h:93
static PVOID Env
Definition: dem.c:259
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:417
LPSTR Env
Definition: vdm.h:81
VOID DeviceInterruptBop(VOID)
Definition: device.c:436
UCHAR WINAPI demGetPhysicalDriveType(IN UCHAR DriveNumber)
Definition: dem.c:1504
_Check_return_ _CRTIMP int __cdecl wcsncmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
#define WAIT_TIMEOUT
Definition: dderror.h:14
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
USHORT Unknown0
Definition: dem.c:275
#define TO_LINEAR(seg, off)
Definition: emulator.h:22
unsigned char UCHAR
Definition: xmlstorage.h:181
static DWORD DosStartComSpec(IN BOOLEAN Permanent, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL, OUT PWORD ComSpecPsp OPTIONAL)
Definition: dem.c:772
BOOL WINAPI GetBinaryTypeA(IN LPCSTR lpApplicationName, OUT LPDWORD lpBinaryType)
Definition: vdm.c:1327
VOID EmulatorPause(VOID)
Definition: emulator.c:487
static VOID CmdStartExternalCommand(VOID)
Definition: dem.c:411
static VOID CmdSetExitCode(VOID)
Definition: dem.c:505
static const WCHAR L[]
Definition: oid.c:1250
USHORT WINAPI getDX(VOID)
Definition: registers.c:286
USHORT WINAPI getAX(VOID)
Definition: registers.c:114
unsigned char BYTE
Definition: mem.h:68
DWORD DosStartProcess32(IN LPCSTR ExecutablePath, IN LPCSTR CommandLine, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL, IN BOOLEAN StartComSpec)
Definition: dem.c:916
PDOS_SDA Sda
Definition: dos.c:48
BOOLEAN DosMouseInitialize(VOID)
Definition: mouse32.c:1260
Definition: typedefs.h:117
static BOOLEAN Repeat
Definition: dem.c:247
struct _COMSPEC_INFO * PCOMSPEC_INFO
VOID EmulatorTerminate(VOID)
Definition: emulator.c:503
static CHAR PifFile[MAX_PATH]
Definition: dem.c:254
static VOID WINAPI DosStart(LPWORD Stack)
Definition: dem.c:1197
VOID WINAPI setBX(USHORT)
Definition: registers.c:177
ULONG EnvLen
Definition: vdm.h:82
HANDLE FileOpen(IN PCSTR FileName, OUT PULONG FileSize OPTIONAL)
Definition: utils.c:27
VOID WINAPI setBH(UCHAR)
Definition: registers.c:191
static VOID WINAPI DosSystemBop(LPWORD Stack)
Definition: dem.c:132
uint16_t * LPWORD
Definition: typedefs.h:54
VOID WINAPI setCS(USHORT)
Definition: registers.c:487
static CHAR Title[MAX_PATH]
Definition: dem.c:257
ULONG_PTR SIZE_T
Definition: typedefs.h:78
BOOL WINAPI FileTimeToDosDateTime(IN CONST FILETIME *lpFileTime, OUT LPWORD lpFatDate, OUT LPWORD lpFatTime)
Definition: time.c:37
PRTL_UNICODE_STRING_BUFFER Path
BOOL WINAPI demIsShortPathName(IN LPCSTR Path, IN BOOL Unknown)
Definition: dem.c:1512
DWORD WINAPI demSetCurrentDirectoryGetDrive(IN LPCSTR CurrentDirectory, OUT PUCHAR DriveNumber)
Definition: dem.c:1521
static BOOLEAN Reentry
Definition: dem.c:248
#define MEM_ALIGN_UP(ptr, align)
Definition: emulator.h:20
unsigned short USHORT
Definition: pedump.c:61
static ULONG SessionId
Definition: dem.c:179
USHORT CodePage
Definition: dem.c:279
DWORD DosLoadExecutableInternal(IN DOS_EXEC_TYPE LoadType, IN LPBYTE ExeBuffer, IN DWORD ExeBufferSize, IN LPCSTR ExePath, IN PDOS_EXEC_PARAM_BLOCK Parameters, IN LPCSTR CommandLine OPTIONAL, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL)
Definition: process.c:327
#define EMULATOR_BOP
Definition: bop.h:16
static VOID CmdStartComSpec32(VOID)
Definition: dem.c:465
USHORT WINAPI getDI(VOID)
Definition: registers.c:434
static BOOLEAN First
Definition: dem.c:250
LPSTR AppName
Definition: vdm.h:78
LPSTR CommandLine
Definition: dem.c:818
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define min(a, b)
Definition: monoChain.cc:55
static CHAR CurDirectory[MAX_PATH]
Definition: dem.c:255
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
USHORT AppNameOff
Definition: dem.c:283
USHORT ExitCode
Definition: dem.c:276
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleTitleA(LPCSTR lpConsoleTitle)
Definition: console.c:2304
DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType, IN LPCSTR ExecutablePath, IN PDOS_EXEC_PARAM_BLOCK Parameters, IN LPCSTR CommandLine OPTIONAL, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL)
Definition: process.c:695
CHAR FileName[13]
Definition: dos.h:135
#define DPRINT1
Definition: precomp.h:8
LPSTR Title
Definition: vdm.h:86
static VOID CmdStartProcess(VOID)
Definition: dem.c:290
DWORD WINAPI demFileDelete(IN LPCSTR FileName)
Definition: dem.c:1402
VOID EmulatorResume(VOID)
Definition: emulator.c:495
#define VDM_INC_REENTER_COUNT
Definition: vdm.h:57
static DWORD ReentrancyCount
Definition: dem.c:193
USHORT WINAPI getDS(VOID)
Definition: registers.c:508
#define OUT
Definition: typedefs.h:39
USHORT EnvBlockSeg
Definition: dem.c:269
USHORT CmdLineOff
Definition: dem.c:274
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:566
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
unsigned int ULONG
Definition: retypes.h:1
#define VDM_FLAG_FIRST_TASK
Definition: vdm.h:53
#define UNIMPLEMENTED
Definition: debug.h:114
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
BOOLEAN FileLoadByHandle(IN HANDLE FileHandle, IN PVOID Location, IN ULONG FileSize, OUT PULONG BytesRead)
Definition: utils.c:69
#define ULONG_PTR
Definition: config.h:101
struct _COMSPEC_INFO COMSPEC_INFO
USHORT WINAPI getSP(VOID)
Definition: registers.c:344
BOOL WINAPI GetNextVDMCommand(PVDM_COMMAND_INFO CommandData)
Definition: vdm.c:1412
USHORT CurDrive
Definition: dem.c:271
ULONG TitleLen
Definition: vdm.h:87
void DisplayMessage(BOOL bConsole, BOOL bSilent, LPCTSTR lpMessage, LPCTSTR lpTitle, UINT uType)
Definition: regsvr32.c:239
#define INFINITE
Definition: serial.h:102
static BYTE Bootsector1[]
Definition: dem.c:1076
USHORT AppNameSeg
Definition: dem.c:282
USHORT WINAPI getCS(VOID)
Definition: registers.c:480
BYTE * PBYTE
Definition: pedump.c:66
struct _NEXT_CMD * PNEXT_CMD
HANDLE WINAPI FindFirstFileA(IN LPCSTR lpFileName, OUT LPWIN32_FIND_DATAA lpFindFileData)
Definition: find.c:263
#define LOWORD(l)
Definition: pedump.c:82
ULONG TaskId
Definition: vdm.h:70
base of all file and directory entries
Definition: entries.h:82
USHORT EnvBlockLen
Definition: dem.c:270
CHAR DriveLetter
Definition: dos.h:124
#define VDM_FLAG_DONT_WAIT
Definition: vdm.h:60
VOID DosBootsectorInitialize(VOID)
Definition: dem.c:1089
USHORT AppNameLen
Definition: dem.c:284
LPSTR Environment OPTIONAL
Definition: dem.c:819
#define BiosDisplayMessage(Format,...)
Definition: dem.h:33
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68