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 */
95 DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum
);
96 // setCF(1); // Disable, otherwise we enter an infinite loop
102 static VOID WINAPI
DosCmdInterpreterBop(LPWORD Stack
)
104 /* Get the Function Number and skip it */
105 BYTE FuncNum
= *(PBYTE
)SEG_OFF_TO_PTR(getCS(), getIP());
110 case 0x08: // Launch external command
112 #define CMDLINE_LENGTH 1024
117 LPSTR Command
= (LPSTR
)SEG_OFF_TO_PTR(getDS(), getSI());
118 LPSTR CmdPtr
= Command
;
119 CHAR CommandLine
[CMDLINE_LENGTH
] = "";
120 STARTUPINFOA StartupInfo
;
121 PROCESS_INFORMATION ProcessInformation
;
123 /* NULL-terminate the command line by removing the return carriage character */
124 while (*CmdPtr
&& *CmdPtr
!= '\r') CmdPtr
++;
127 DPRINT1("CMD Run Command '%s'\n", Command
);
129 /* Spawn a user-defined 32-bit command preprocessor */
131 /* Build the command line */
132 // FIXME: Use COMSPEC env var!!
133 strcpy(CommandLine
, "cmd.exe /c ");
134 strcat(CommandLine
, Command
);
136 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
137 ZeroMemory(&ProcessInformation
, sizeof(ProcessInformation
));
139 StartupInfo
.cb
= sizeof(StartupInfo
);
141 VidBiosDetachFromConsole();
143 Result
= CreateProcessA(NULL
,
152 &ProcessInformation
);
155 DPRINT1("Command '%s' launched successfully\n", Command
);
157 /* Wait for process termination */
158 WaitForSingleObject(ProcessInformation
.hProcess
, INFINITE
);
160 /* Get the exit code */
161 GetExitCodeProcess(ProcessInformation
.hProcess
, &dwExitCode
);
164 CloseHandle(ProcessInformation
.hThread
);
165 CloseHandle(ProcessInformation
.hProcess
);
169 DPRINT1("Failed when launched command '%s'\n");
170 dwExitCode
= GetLastError();
173 VidBiosAttachToConsole();
175 setAL((UCHAR
)dwExitCode
);
182 DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum
);
183 // setCF(1); // Disable, otherwise we enter an infinite loop
189 /* PUBLIC FUNCTIONS ***********************************************************/
191 BOOLEAN
DosInitialize(IN LPCSTR DosKernelFileName
)
193 /* Register the DOS BOPs */
194 RegisterBop(BOP_DOS
, DosSystemBop
);
195 RegisterBop(BOP_CMD
, DosCmdInterpreterBop
);
197 if (DosKernelFileName
)
201 ULONG ulDosBiosSize
= 0;
203 /* Open the DOS BIOS file */
204 hDosBios
= FileOpen(DosKernelFileName
, &ulDosBiosSize
);
206 /* If we failed, bail out */
207 if (hDosBios
== NULL
) return FALSE
;
209 /* Attempt to load the DOS BIOS into memory */
210 Success
= FileLoadByHandle(hDosBios
,
211 REAL_TO_PHYS(TO_LINEAR(0x0070, 0x0000)),
215 DPRINT1("DOS BIOS loading %s at 0x%04X:0x%04X, size 0x%x ; GetLastError() = %u\n",
216 (Success
? "succeeded" : "failed"),
221 /* Close the DOS BIOS file */
226 /* Position execution pointers and return */
237 Result
= DosBIOSInitialize();
238 DosMouseInitialize(); // FIXME: Should be done by the DOS BIOS
239 // Result &= DosKRNLInitialize();
245 /* PUBLIC EXPORTED APIS *******************************************************/
248 // demLFNGetCurrentDirectory
250 // demGetFileTimeByHandle_WOW
251 // demWOWLFNAllocateSearchHandle
252 // demWOWLFNCloseSearchHandle
254 // demWOWLFNGetSearchHandle
259 demClientErrorEx(IN HANDLE FileHandle
,
264 return GetLastError();
269 demFileDelete(IN LPCSTR FileName
)
271 if (DeleteFileA(FileName
)) SetLastError(ERROR_SUCCESS
);
273 return GetLastError();
278 demFileFindFirst(OUT PVOID lpFindFileData
,
282 BOOLEAN Success
= TRUE
;
283 WIN32_FIND_DATAA FindData
;
284 PDOS_FIND_FILE_BLOCK FindFileBlock
= (PDOS_FIND_FILE_BLOCK
)lpFindFileData
;
287 FindFileBlock
->DriveLetter
= CurrentDrive
+ 'A';
288 FindFileBlock
->AttribMask
= AttribMask
;
289 FindFileBlock
->SearchHandle
= FindFirstFileA(FileName
, &FindData
);
290 if (FindFileBlock
->SearchHandle
== INVALID_HANDLE_VALUE
) return GetLastError();
294 /* Check the attributes */
295 if (!((FindData
.dwFileAttributes
& (FILE_ATTRIBUTE_HIDDEN
|
296 FILE_ATTRIBUTE_SYSTEM
|
297 FILE_ATTRIBUTE_DIRECTORY
))
303 while ((Success
= FindNextFileA(FindFileBlock
->SearchHandle
, &FindData
)));
305 if (!Success
) return GetLastError();
307 FindFileBlock
->Attributes
= LOBYTE(FindData
.dwFileAttributes
);
308 FileTimeToDosDateTime(&FindData
.ftLastWriteTime
,
309 &FindFileBlock
->FileDate
,
310 &FindFileBlock
->FileTime
);
311 FindFileBlock
->FileSize
= FindData
.nFileSizeHigh
? 0xFFFFFFFF
312 : FindData
.nFileSizeLow
;
313 strcpy(FindFileBlock
->FileName
, FindData
.cAlternateFileName
);
315 return ERROR_SUCCESS
;
320 demFileFindNext(OUT PVOID lpFindFileData
)
322 WIN32_FIND_DATAA FindData
;
323 PDOS_FIND_FILE_BLOCK FindFileBlock
= (PDOS_FIND_FILE_BLOCK
)lpFindFileData
;
327 if (!FindNextFileA(FindFileBlock
->SearchHandle
, &FindData
))
328 return GetLastError();
330 /* Update the block */
331 FindFileBlock
->Attributes
= LOBYTE(FindData
.dwFileAttributes
);
332 FileTimeToDosDateTime(&FindData
.ftLastWriteTime
,
333 &FindFileBlock
->FileDate
,
334 &FindFileBlock
->FileTime
);
335 FindFileBlock
->FileSize
= FindData
.nFileSizeHigh
? 0xFFFFFFFF
336 : FindData
.nFileSizeLow
;
337 strcpy(FindFileBlock
->FileName
, FindData
.cAlternateFileName
);
339 while((FindData
.dwFileAttributes
& (FILE_ATTRIBUTE_HIDDEN
|
340 FILE_ATTRIBUTE_SYSTEM
|
341 FILE_ATTRIBUTE_DIRECTORY
))
342 & ~FindFileBlock
->AttribMask
);
344 return ERROR_SUCCESS
;
349 demGetPhysicalDriveType(IN UCHAR DriveNumber
)
352 return DOSDEVICE_DRIVE_UNKNOWN
;
357 demIsShortPathName(IN LPCSTR Path
,
366 demSetCurrentDirectoryGetDrive(IN LPCSTR CurrentDirectory
,
367 OUT PUCHAR DriveNumber
)
370 return ERROR_SUCCESS
;