2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: subsys/ntvdm/ntvdm->c
5 * PURPOSE: Virtual DOS Machine
6 * PROGRAMMER: Robert Dickenson (robd@mok.lvcm.com)
11 /* INCLUDES *****************************************************************/
14 #define WIN32_NO_STATUS
26 /* GLOBALS ******************************************************************/
29 /* FUNCTIONS *****************************************************************/
31 void PrintString(char* fmt
,...)
37 vsprintf(buffer
, fmt
, ap
);
40 OutputDebugStringA(buffer
);
57 SetVDMCurrentDirectories
69 typedef struct tag_VDM_CONFIG
{
75 //device=%SystemRoot%\system32\himem.sys
77 } VDM_CONFIG
, *PVDM_CONFIG
;
79 typedef struct tag_VDM_AUTOEXEC
{
81 //lh %SystemRoot%\system32\mscdexnt.exe
82 //lh %SystemRoot%\system32\redir
83 //lh %SystemRoot%\system32\dosx
84 } VDM_AUTOEXEC
, *PVDM_AUTOEXEC
;
86 typedef struct tag_VDM_CONTROL_BLOCK
{
90 VDM_AUTOEXEC vdmAutoexec
;
91 PROCESS_INFORMATION ProcessInformation
;
92 CHAR CommandLine
[MAX_PATH
];
93 CHAR CurrentDirectory
[MAX_PATH
];
95 } VDM_CONTROL_BLOCK
, *PVDM_CONTROL_BLOCK
;
99 StartVDM(PVDM_CONTROL_BLOCK vdm
)
102 STARTUPINFOA StartupInfo
;
104 StartupInfo
.cb
= sizeof(StartupInfo
);
105 StartupInfo
.lpReserved
= NULL
;
106 StartupInfo
.lpDesktop
= NULL
;
107 StartupInfo
.lpTitle
= NULL
;
108 StartupInfo
.dwFlags
= 0;
109 StartupInfo
.cbReserved2
= 0;
110 StartupInfo
.lpReserved2
= 0;
112 Result
= CreateProcessA(vdm
->CommandLine
,
121 &vdm
->ProcessInformation
);
123 PrintString("VDM: Failed to execute target process\n");
126 WaitForSingleObject(vdm
->ProcessInformation
.hProcess
, INFINITE
);
127 CloseHandle(vdm
->ProcessInformation
.hProcess
);
128 CloseHandle(vdm
->ProcessInformation
.hThread
);
133 ShutdownVDM(PVDM_CONTROL_BLOCK vdm
)
140 BOOL
ReadConfigForVDM(PVDM_CONTROL_BLOCK vdm
)
146 hFile
= CreateFileW(L
"\\system32\\config.nt",
150 OPEN_ALWAYS
/*OPEN_EXISTING*/,
151 FILE_ATTRIBUTE_NORMAL
,
153 dwError
= GetLastError();
154 if (hFile
== INVALID_HANDLE_VALUE
) {
155 // error with file path or system problem?
158 // we just created a new file, perhaps we should set/write some defaults?
160 if (dwError
== ERROR_ALREADY_EXISTS
) {
161 // read the line entries and cache in some struct...
166 hFile
= CreateFileW(L
"\\system32\\autoexec.nt",
171 FILE_ATTRIBUTE_NORMAL
,
173 dwError
= GetLastError();
174 if (hFile
== INVALID_HANDLE_VALUE
) {
175 // error with file path or system problem?
178 // we just created a new file, perhaps we should set/write some defaults?
180 if (dwError
== ERROR_ALREADY_EXISTS
) {
181 // read the line entries and cache in some struct...
190 LoadConfigDriversForVDM(PVDM_CONFIG vdmConfig
)
198 SetConfigOptionsForVDM(PVDM_AUTOEXEC vdmAutoexec
)
206 CreateVDM(PVDM_CONTROL_BLOCK vdm
)
208 // BOOL result = TRUE;
213 GlobalMemoryStatus(&stat
);
214 if (stat
.dwLength
!= sizeof(MEMORYSTATUS
)) {
215 printf("WARNING: GlobalMemoryStatus() returned unknown structure version, size %ld, expected %d.\n", stat
.dwLength
, sizeof(stat
));
217 printf("Memory Load: %ld percent in use.\n", stat
.dwMemoryLoad
);
218 printf("\t%ld total bytes physical memory.\n", stat
.dwTotalPhys
);
219 printf("\t%ld available physical memory.\n", stat
.dwAvailPhys
);
220 printf("\t%ld total bytes paging file.\n", stat
.dwTotalPageFile
);
221 printf("\t%ld available paging file.\n", stat
.dwAvailPageFile
);
222 printf("\t%lx total bytes virtual memory.\n", stat
.dwTotalVirtual
);
223 printf("\t%lx available bytes virtual memory.\n", stat
.dwAvailVirtual
);
225 #define OUT_OF_HEADROOM 90
226 if (stat
.dwMemoryLoad
> OUT_OF_HEADROOM
) {
227 DPRINT("VDM: system resources deemed to low to start VDM.\n");
235 vdm
->hHeap
= HeapCreate(0, inf
.dwAllocationGranularity
, 0);
236 if (vdm
->hHeap
== NULL
) {
237 DPRINT("VDM: failed to create heap.\n");
241 #define DEFAULT_VDM_IMAGE_SIZE 2000000
242 vdm
->ImageMem
= HeapAlloc(vdm
->hHeap
, 0, DEFAULT_VDM_IMAGE_SIZE
);
243 if (vdm
->ImageMem
== NULL
) {
244 DPRINT("VDM: failed to allocate image memory from heap %x.\n", vdm
->hHeap
);
245 HeapDestroy(vdm
->hHeap
);
253 DestroyVDM(PVDM_CONTROL_BLOCK vdm
)
257 if (vdm
->ImageMem
!= NULL
) {
258 if (HeapFree(vdm
->hHeap
, 0, vdm
->ImageMem
) != FALSE
) {
259 DPRINT("VDM: failed to free memory from heap %x.\n", vdm
->hHeap
);
262 vdm
->ImageMem
= NULL
;
264 if (vdm
->hHeap
!= NULL
) {
265 if (!HeapDestroy(vdm
->hHeap
)) {
266 DPRINT("VDM: failed to destroy heap %x.\n", vdm
->hHeap
);
275 WinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPSTR lpCmdLine
, int nShowCmd
)
277 VDM_CONTROL_BLOCK VdmCB
;
280 BOOL vdmStarted
= FALSE
;
282 WCHAR WelcomeMsg
[RC_STRING_MAX_SIZE
];
283 WCHAR PromptMsg
[RC_STRING_MAX_SIZE
];
284 CHAR InputBuffer
[255];
286 LoadStringW( GetModuleHandle(NULL
), STRING_WelcomeMsg
, WelcomeMsg
,sizeof(WelcomeMsg
) / sizeof(WelcomeMsg
[0]));
287 LoadStringW( GetModuleHandle(NULL
), STRING_PromptMsg
, PromptMsg
,sizeof(PromptMsg
) / sizeof(PromptMsg
[0]));
290 SetConsoleTitleW(L
"ntvdm");
292 WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE
),
293 WelcomeMsg
, lstrlenW(WelcomeMsg
), // wcslen(WelcomeMsg),
296 if (!CreateVDM(&VdmCB
)) {
297 DPRINT("VDM: failed to create VDM.\n");
302 ReadConfigForVDM(&VdmCB
);
304 if (!LoadConfigDriversForVDM(&(VdmCB
.vdmConfig
))) {
305 DPRINT("VDM: failed to load configuration drivers.\n");
309 if (!SetConfigOptionsForVDM(&(VdmCB
.vdmAutoexec
))) {
310 DPRINT("VDM: failed to set configuration options.\n");
315 GetSystemDirectoryA(VdmCB
.CommandLine
, MAX_PATH
);
316 strcat(VdmCB
.CommandLine
, "\\hello.exe");
317 GetWindowsDirectoryA(VdmCB
.CurrentDirectory
, MAX_PATH
);
320 WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE
),
321 PromptMsg
, lstrlenW(PromptMsg
), // wcslen(PromptMsg),
325 ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE
),
328 if (++i
>= (sizeof(InputBuffer
) - 1)) {
331 } while (InputBuffer
[i
- 1] != '\n');
332 InputBuffer
[i
- 1] = '\0';
334 if (InputBuffer
[0] == 'r' || InputBuffer
[0] == 'R') {
336 if (StartVDM(&VdmCB
)) {
339 DPRINT("VDM: failed to start.\n");
342 DPRINT("VDM: already started.\n");
345 if (InputBuffer
[0] == 's' || InputBuffer
[0] == 'S') {
347 if (ShutdownVDM(&VdmCB
)) {
350 DPRINT("VDM: failed to shutdown.\n");
353 DPRINT("VDM: not started.\n");
356 if (InputBuffer
[0] == 'q' || InputBuffer
[0] == 'Q') {
361 if (!ShutdownVDM(&VdmCB
)) {
362 DPRINT("VDM: failed to cleanly shutdown VDM.\n");
367 if (!DestroyVDM(&VdmCB
)) {
368 DPRINT("VDM: failed to cleanly destroy VDM.\n");