2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
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)
13 /* INCLUDES *******************************************************************/
23 #include "bios/bios.h"
26 /* Extra PSDK/NDK Headers */
27 #include <ndk/obtypes.h>
29 /* PRIVATE VARIABLES **********************************************************/
31 /**/extern BYTE CurrentDrive
;/**/
33 /* DEFINES ********************************************************************/
36 #define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
37 #define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
39 /* PRIVATE FUNCTIONS **********************************************************/
41 static VOID WINAPI
DosSystemBop(LPWORD Stack
)
43 /* Get the Function Number and skip it */
44 BYTE FuncNum
= *(PBYTE
)SEG_OFF_TO_PTR(getCS(), getIP());
49 case 0x11: // Load the DOS kernel
51 BOOLEAN Success
= FALSE
;
53 ULONG ulDosKernelSize
= 0;
55 DPRINT1("You are loading Windows NT DOS!\n");
57 /* Open the DOS kernel file */
58 hDosKernel
= FileOpen("ntdos.sys", &ulDosKernelSize
);
60 /* If we failed, bail out */
61 if (hDosKernel
== NULL
) goto Quit
;
64 * Attempt to load the DOS kernel into memory.
65 * The segment where to load the DOS kernel is defined
66 * by the DOS BIOS and is found in DI:0000 .
68 Success
= FileLoadByHandle(hDosKernel
,
69 REAL_TO_PHYS(TO_LINEAR(getDI(), 0x0000)),
73 DPRINT1("Windows NT DOS loading %s at 0x%04X:0x%04X, size 0x%x ; GetLastError() = %u\n",
74 (Success
? "succeeded" : "failed"),
79 /* Close the DOS kernel file */
80 FileClose(hDosKernel
);
85 /* We failed everything, stop the VDM */
94 DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum
);
95 // setCF(1); // Disable, otherwise we enter an infinite loop
101 static VOID WINAPI
DosCmdInterpreterBop(LPWORD Stack
)
103 /* Get the Function Number and skip it */
104 BYTE FuncNum
= *(PBYTE
)SEG_OFF_TO_PTR(getCS(), getIP());
109 case 0x08: // Launch external command
111 #define CMDLINE_LENGTH 1024
116 LPSTR Command
= (LPSTR
)SEG_OFF_TO_PTR(getDS(), getSI());
117 LPSTR CmdPtr
= Command
;
118 CHAR CommandLine
[CMDLINE_LENGTH
] = "";
119 STARTUPINFOA StartupInfo
;
120 PROCESS_INFORMATION ProcessInformation
;
122 /* NULL-terminate the command line by removing the return carriage character */
123 while (*CmdPtr
&& *CmdPtr
!= '\r') CmdPtr
++;
126 DPRINT1("CMD Run Command '%s'\n", Command
);
128 /* Spawn a user-defined 32-bit command preprocessor */
130 /* Build the command line */
131 // FIXME: Use COMSPEC env var!!
132 strcpy(CommandLine
, "cmd.exe /c ");
133 strcat(CommandLine
, Command
);
135 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
136 ZeroMemory(&ProcessInformation
, sizeof(ProcessInformation
));
138 StartupInfo
.cb
= sizeof(StartupInfo
);
140 VidBiosDetachFromConsole();
142 Result
= CreateProcessA(NULL
,
151 &ProcessInformation
);
154 DPRINT1("Command '%s' launched successfully\n", Command
);
156 /* Wait for process termination */
157 WaitForSingleObject(ProcessInformation
.hProcess
, INFINITE
);
159 /* Get the exit code */
160 GetExitCodeProcess(ProcessInformation
.hProcess
, &dwExitCode
);
163 CloseHandle(ProcessInformation
.hThread
);
164 CloseHandle(ProcessInformation
.hProcess
);
168 DPRINT1("Failed when launched command '%s'\n");
169 dwExitCode
= GetLastError();
172 VidBiosAttachToConsole();
174 setAL((UCHAR
)dwExitCode
);
181 DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum
);
182 // setCF(1); // Disable, otherwise we enter an infinite loop
188 /* PUBLIC FUNCTIONS ***********************************************************/
190 BOOLEAN
DosInitialize(IN LPCSTR DosKernelFileName
)
192 /* Register the DOS BOPs */
193 RegisterBop(BOP_DOS
, DosSystemBop
);
194 RegisterBop(BOP_CMD
, DosCmdInterpreterBop
);
196 if (DosKernelFileName
)
200 ULONG ulDosBiosSize
= 0;
202 /* Open the DOS BIOS file */
203 hDosBios
= FileOpen(DosKernelFileName
, &ulDosBiosSize
);
205 /* If we failed, bail out */
206 if (hDosBios
== NULL
) return FALSE
;
208 /* Attempt to load the DOS BIOS into memory */
209 Success
= FileLoadByHandle(hDosBios
,
210 REAL_TO_PHYS(TO_LINEAR(0x0070, 0x0000)),
214 DPRINT1("DOS BIOS loading %s at 0x%04X:0x%04X, size 0x%x ; GetLastError() = %u\n",
215 (Success
? "succeeded" : "failed"),
220 /* Close the DOS BIOS file */
225 /* Position execution pointers and return */
236 Result
= DosBIOSInitialize();
237 DosMouseInitialize(); // FIXME: Should be done by the DOS BIOS
238 // Result &= DosKRNLInitialize();
244 /* PUBLIC EXPORTED APIS *******************************************************/
247 // demLFNGetCurrentDirectory
249 // demGetFileTimeByHandle_WOW
250 // demWOWLFNAllocateSearchHandle
251 // demWOWLFNCloseSearchHandle
253 // demWOWLFNGetSearchHandle
258 demClientErrorEx(IN HANDLE FileHandle
,
263 return GetLastError();
268 demFileDelete(IN LPCSTR FileName
)
270 if (DeleteFileA(FileName
)) SetLastError(ERROR_SUCCESS
);
272 return GetLastError();
277 demFileFindFirst(OUT PVOID lpFindFileData
,
281 BOOLEAN Success
= TRUE
;
282 WIN32_FIND_DATAA FindData
;
283 PDOS_FIND_FILE_BLOCK FindFileBlock
= (PDOS_FIND_FILE_BLOCK
)lpFindFileData
;
286 FindFileBlock
->DriveLetter
= CurrentDrive
+ 'A';
287 FindFileBlock
->AttribMask
= AttribMask
;
288 FindFileBlock
->SearchHandle
= FindFirstFileA(FileName
, &FindData
);
289 if (FindFileBlock
->SearchHandle
== INVALID_HANDLE_VALUE
) return GetLastError();
293 /* Check the attributes */
294 if (!((FindData
.dwFileAttributes
& (FILE_ATTRIBUTE_HIDDEN
|
295 FILE_ATTRIBUTE_SYSTEM
|
296 FILE_ATTRIBUTE_DIRECTORY
))
302 while ((Success
= FindNextFileA(FindFileBlock
->SearchHandle
, &FindData
)));
304 if (!Success
) return GetLastError();
306 FindFileBlock
->Attributes
= LOBYTE(FindData
.dwFileAttributes
);
307 FileTimeToDosDateTime(&FindData
.ftLastWriteTime
,
308 &FindFileBlock
->FileDate
,
309 &FindFileBlock
->FileTime
);
310 FindFileBlock
->FileSize
= FindData
.nFileSizeHigh
? 0xFFFFFFFF
311 : FindData
.nFileSizeLow
;
312 strcpy(FindFileBlock
->FileName
, FindData
.cAlternateFileName
);
314 return ERROR_SUCCESS
;
319 demFileFindNext(OUT PVOID lpFindFileData
)
321 WIN32_FIND_DATAA FindData
;
322 PDOS_FIND_FILE_BLOCK FindFileBlock
= (PDOS_FIND_FILE_BLOCK
)lpFindFileData
;
326 if (!FindNextFileA(FindFileBlock
->SearchHandle
, &FindData
))
327 return GetLastError();
329 /* Update the block */
330 FindFileBlock
->Attributes
= LOBYTE(FindData
.dwFileAttributes
);
331 FileTimeToDosDateTime(&FindData
.ftLastWriteTime
,
332 &FindFileBlock
->FileDate
,
333 &FindFileBlock
->FileTime
);
334 FindFileBlock
->FileSize
= FindData
.nFileSizeHigh
? 0xFFFFFFFF
335 : FindData
.nFileSizeLow
;
336 strcpy(FindFileBlock
->FileName
, FindData
.cAlternateFileName
);
338 while((FindData
.dwFileAttributes
& (FILE_ATTRIBUTE_HIDDEN
|
339 FILE_ATTRIBUTE_SYSTEM
|
340 FILE_ATTRIBUTE_DIRECTORY
))
341 & ~FindFileBlock
->AttribMask
);
343 return ERROR_SUCCESS
;
348 demGetPhysicalDriveType(IN UCHAR DriveNumber
)
351 return DOSDEVICE_DRIVE_UNKNOWN
;
356 demIsShortPathName(IN LPCSTR Path
,
365 demSetCurrentDirectoryGetDrive(IN LPCSTR CurrentDirectory
,
366 OUT PUCHAR DriveNumber
)
369 return ERROR_SUCCESS
;