1 /* $Id: ntvdm.c,v 1.4 2003/11/14 17:13:32 weiden Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: subsys/ntvdm/ntvdm->c
6 * PURPOSE: Virtual DOS Machine
7 * PROGRAMMER: Robert Dickenson (robd@mok.lvcm.com)
12 /* INCLUDES *****************************************************************/
22 /* GLOBALS ******************************************************************/
25 /* FUNCTIONS *****************************************************************/
27 void PrintString(char* fmt
,...)
33 vsprintf(buffer
, fmt
, ap
);
36 OutputDebugStringA(buffer
);
53 SetVDMCurrentDirectories
65 typedef struct tag_VDM_CONFIG
{
71 //device=%SystemRoot%\system32\himem.sys
73 } VDM_CONFIG
, *PVDM_CONFIG
;
75 typedef struct tag_VDM_AUTOEXEC
{
77 //lh %SystemRoot%\system32\mscdexnt.exe
78 //lh %SystemRoot%\system32\redir
79 //lh %SystemRoot%\system32\dosx
80 } VDM_AUTOEXEC
, *PVDM_AUTOEXEC
;
82 typedef struct tag_VDM_CONTROL_BLOCK
{
86 VDM_AUTOEXEC vdmAutoexec
;
87 PROCESS_INFORMATION ProcessInformation
;
88 CHAR CommandLine
[MAX_PATH
];
89 CHAR CurrentDirectory
[MAX_PATH
];
91 } VDM_CONTROL_BLOCK
, *PVDM_CONTROL_BLOCK
;
95 StartVDM(PVDM_CONTROL_BLOCK vdm
)
98 STARTUPINFOA StartupInfo
;
100 StartupInfo
.cb
= sizeof(StartupInfo
);
101 StartupInfo
.lpReserved
= NULL
;
102 StartupInfo
.lpDesktop
= NULL
;
103 StartupInfo
.lpTitle
= NULL
;
104 StartupInfo
.dwFlags
= 0;
105 StartupInfo
.cbReserved2
= 0;
106 StartupInfo
.lpReserved2
= 0;
108 Result
= CreateProcessA(vdm
->CommandLine
,
117 &vdm
->ProcessInformation
);
119 PrintString("VDM: Failed to execute target process\n");
122 WaitForSingleObject(vdm
->ProcessInformation
.hProcess
, INFINITE
);
123 CloseHandle(vdm
->ProcessInformation
.hProcess
);
124 CloseHandle(vdm
->ProcessInformation
.hThread
);
129 ShutdownVDM(PVDM_CONTROL_BLOCK vdm
)
136 BOOL
ReadConfigForVDM(PVDM_CONTROL_BLOCK vdm
)
142 hFile
= CreateFileW(L
"\\system32\\config.nt",
146 OPEN_ALWAYS
/*OPEN_EXISTING*/,
147 FILE_ATTRIBUTE_NORMAL
,
149 dwError
= GetLastError();
150 if (hFile
== INVALID_HANDLE_VALUE
) {
151 // error with file path or system problem?
154 // we just created a new file, perhaps we should set/write some defaults?
156 if (dwError
== ERROR_ALREADY_EXISTS
) {
157 // read the line entries and cache in some struct...
162 hFile
= CreateFileW(L
"\\system32\\autoexec.nt",
167 FILE_ATTRIBUTE_NORMAL
,
169 dwError
= GetLastError();
170 if (hFile
== INVALID_HANDLE_VALUE
) {
171 // error with file path or system problem?
174 // we just created a new file, perhaps we should set/write some defaults?
176 if (dwError
== ERROR_ALREADY_EXISTS
) {
177 // read the line entries and cache in some struct...
186 LoadConfigDriversForVDM(PVDM_CONFIG vdmConfig
)
194 SetConfigOptionsForVDM(PVDM_AUTOEXEC vdmAutoexec
)
202 CreateVDM(PVDM_CONTROL_BLOCK vdm
)
204 // BOOL result = TRUE;
208 GlobalMemoryStatus(&stat
);
209 if (stat
.dwLength
!= sizeof(MEMORYSTATUS
)) {
210 printf("WARNING: GlobalMemoryStatus() returned unknown structure version, size %ld, expected %d.\n", stat
.dwLength
, sizeof(stat
));
212 printf("Memory Load: %ld percent in use.\n", stat
.dwMemoryLoad
);
213 printf("\t%ld total bytes physical memory.\n", stat
.dwTotalPhys
);
214 printf("\t%ld available physical memory.\n", stat
.dwAvailPhys
);
215 printf("\t%ld total bytes paging file.\n", stat
.dwTotalPageFile
);
216 printf("\t%ld available paging file.\n", stat
.dwAvailPageFile
);
217 printf("\t%lx total bytes virtual memory.\n", stat
.dwTotalVirtual
);
218 printf("\t%lx available bytes virtual memory.\n", stat
.dwAvailVirtual
);
220 #define OUT_OF_HEADROOM 90
221 if (stat
.dwMemoryLoad
> OUT_OF_HEADROOM
) {
222 DPRINT("VDM: system resources deemed to low to start VDM.\n");
229 vdm
->hHeap
= HeapCreate(0, inf
.dwAllocationGranularity
, 0);
230 if (vdm
->hHeap
== NULL
) {
231 DPRINT("VDM: failed to create heap.\n");
235 #define DEFAULT_VDM_IMAGE_SIZE 2000000
236 vdm
->ImageMem
= HeapAlloc(vdm
->hHeap
, 0, DEFAULT_VDM_IMAGE_SIZE
);
237 if (vdm
->ImageMem
== NULL
) {
238 DPRINT("VDM: failed to allocate image memory from heap %x.\n", vdm
->hHeap
);
239 HeapDestroy(vdm
->hHeap
);
247 DestroyVDM(PVDM_CONTROL_BLOCK vdm
)
251 if (vdm
->ImageMem
!= NULL
) {
252 if (HeapFree(vdm
->hHeap
, 0, vdm
->ImageMem
) != FALSE
) {
253 DPRINT("VDM: failed to free memory from heap %x.\n", vdm
->hHeap
);
256 vdm
->ImageMem
= NULL
;
258 if (vdm
->hHeap
!= NULL
) {
259 if (!HeapDestroy(vdm
->hHeap
)) {
260 DPRINT("VDM: failed to destroy heap %x.\n", vdm
->hHeap
);
269 WinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPSTR lpCmdLine
, int nShowCmd
)
271 VDM_CONTROL_BLOCK VdmCB
;
274 BOOL vdmStarted
= FALSE
;
276 WCHAR WelcomeMsg
[] = L
"ReactOS Virtual DOS Machine support.\n";
277 WCHAR PromptMsg
[] = L
"Type r<cr> to run, s<cr> to shutdown or q<cr> to quit now.";
278 CHAR InputBuffer
[255];
281 SetConsoleTitleW(L
"ntvdm");
283 WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE
),
284 WelcomeMsg
, lstrlenW(WelcomeMsg
), // wcslen(WelcomeMsg),
287 if (!CreateVDM(&VdmCB
)) {
288 DPRINT("VDM: failed to create VDM.\n");
293 ReadConfigForVDM(&VdmCB
);
295 if (!LoadConfigDriversForVDM(&(VdmCB
.vdmConfig
))) {
296 DPRINT("VDM: failed to load configuration drivers.\n");
300 if (!SetConfigOptionsForVDM(&(VdmCB
.vdmAutoexec
))) {
301 DPRINT("VDM: failed to set configuration options.\n");
306 GetSystemDirectoryA(VdmCB
.CommandLine
, MAX_PATH
);
307 strcat(VdmCB
.CommandLine
, "\\hello.exe");
308 GetWindowsDirectoryA(VdmCB
.CurrentDirectory
, MAX_PATH
);
311 WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE
),
312 PromptMsg
, lstrlenW(PromptMsg
), // wcslen(PromptMsg),
316 ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE
),
319 if (++i
>= (sizeof(InputBuffer
) - 1)) {
322 } while (InputBuffer
[i
- 1] != '\n');
323 InputBuffer
[i
- 1] = '\0';
325 if (InputBuffer
[0] == 'r' || InputBuffer
[0] == 'R') {
327 if (StartVDM(&VdmCB
)) {
330 DPRINT("VDM: failed to start.\n");
333 DPRINT("VDM: already started.\n");
336 if (InputBuffer
[0] == 's' || InputBuffer
[0] == 'S') {
338 if (ShutdownVDM(&VdmCB
)) {
341 DPRINT("VDM: failed to shutdown.\n");
344 DPRINT("VDM: not started.\n");
347 if (InputBuffer
[0] == 'q' || InputBuffer
[0] == 'Q') {
352 if (!ShutdownVDM(&VdmCB
)) {
353 DPRINT("VDM: failed to cleanly shutdown VDM.\n");
358 if (!DestroyVDM(&VdmCB
)) {
359 DPRINT("VDM: failed to cleanly destroy VDM.\n");