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 /* Extra PSDK/NDK Headers */
24 #include <ndk/obtypes.h>
26 /* PRIVATE VARIABLES **********************************************************/
28 /**/extern BYTE CurrentDrive
;/**/
30 /* DEFINES ********************************************************************/
33 #define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
34 #define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
36 /* PRIVATE FUNCTIONS **********************************************************/
38 static VOID WINAPI
DosSystemBop(LPWORD Stack
)
40 /* Get the Function Number and skip it */
41 BYTE FuncNum
= *(PBYTE
)SEG_OFF_TO_PTR(getCS(), getIP());
46 case 0x11: // Load the DOS kernel
50 ULONG ulDosKernelSize
= 0;
52 DPRINT1("You are loading Windows NT DOS!\n");
54 /* Open the DOS kernel file */
55 hDosKernel
= FileOpen("ntdos.sys", &ulDosKernelSize
);
57 /* If we failed, bail out */
58 if (hDosKernel
== NULL
) goto Quit
;
61 * Attempt to load the DOS kernel into memory.
62 * The segment where to load the DOS kernel is defined
63 * by the DOS BIOS and is found in DI:0000 .
65 Success
= FileLoadByHandle(hDosKernel
,
66 REAL_TO_PHYS(TO_LINEAR(getDI(), 0x0000)),
69 DPRINT1("DOS loading %s ; GetLastError() = %u\n", Success
? "succeeded" : "failed", GetLastError());
71 /* Close the DOS kernel file */
72 FileClose(hDosKernel
);
77 /* We failed everything, stop the VDM */
87 DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum
);
88 // setCF(1); // Disable, otherwise we enter an infinite loop
94 static VOID WINAPI
DosCmdInterpreterBop(LPWORD Stack
)
96 /* Get the Function Number and skip it */
97 BYTE FuncNum
= *(PBYTE
)SEG_OFF_TO_PTR(getCS(), getIP());
102 case 0x08: // Launch external command
104 #define CMDLINE_LENGTH 1024
109 LPSTR Command
= (LPSTR
)SEG_OFF_TO_PTR(getDS(), getSI());
110 LPSTR CmdPtr
= Command
;
111 CHAR CommandLine
[CMDLINE_LENGTH
] = "";
112 STARTUPINFOA StartupInfo
;
113 PROCESS_INFORMATION ProcessInformation
;
115 /* Remove return carriage character */
116 while (*CmdPtr
!= '\r') CmdPtr
++;
119 DPRINT1("CMD Run Command '%s'\n", Command
);
121 /* Spawn a user-defined 32-bit command preprocessor */
123 /* Build the command line */
124 // FIXME: Use COMSPEC env var!!
125 strcpy(CommandLine
, "cmd.exe /c ");
126 strcat(CommandLine
, Command
);
128 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
129 ZeroMemory(&ProcessInformation
, sizeof(ProcessInformation
));
131 StartupInfo
.cb
= sizeof(StartupInfo
);
133 DosPrintCharacter('\n');
135 Result
= CreateProcessA(NULL
,
144 &ProcessInformation
);
147 DPRINT1("Command '%s' launched successfully\n", Command
);
149 /* Wait for process termination */
150 WaitForSingleObject(ProcessInformation
.hProcess
, INFINITE
);
152 /* Get the exit code */
153 GetExitCodeProcess(ProcessInformation
.hProcess
, &dwExitCode
);
156 CloseHandle(ProcessInformation
.hThread
);
157 CloseHandle(ProcessInformation
.hProcess
);
161 DPRINT1("Failed when launched command '%s'\n");
162 dwExitCode
= GetLastError();
165 DosPrintCharacter('\n');
167 setAL((UCHAR
)dwExitCode
);
174 DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum
);
175 // setCF(1); // Disable, otherwise we enter an infinite loop
181 /* PUBLIC FUNCTIONS ***********************************************************/
183 BOOLEAN
DosInitialize(IN LPCSTR DosKernelFileName
)
185 /* Register the DOS BOPs */
186 RegisterBop(BOP_DOS
, DosSystemBop
);
187 RegisterBop(BOP_CMD
, DosCmdInterpreterBop
);
189 if (DosKernelFileName
)
193 ULONG ulDosBiosSize
= 0;
195 /* Open the DOS BIOS file */
196 hDosBios
= FileOpen(DosKernelFileName
, &ulDosBiosSize
);
198 /* If we failed, bail out */
199 if (hDosBios
== NULL
) return FALSE
;
201 /* Attempt to load the DOS BIOS into memory */
202 Success
= FileLoadByHandle(hDosBios
,
203 REAL_TO_PHYS(TO_LINEAR(0x0070, 0x0000)),
206 DPRINT1("DOS BIOS loading %s ; GetLastError() = %u\n", Success
? "succeeded" : "failed", GetLastError());
208 /* Close the DOS BIOS file */
213 /* Position execution pointers and return */
224 Result
= DosBIOSInitialize();
225 // Result &= DosKRNLInitialize();
231 /* PUBLIC EXPORTED APIS *******************************************************/
234 // demLFNGetCurrentDirectory
236 // demGetFileTimeByHandle_WOW
237 // demWOWLFNAllocateSearchHandle
238 // demWOWLFNCloseSearchHandle
240 // demWOWLFNGetSearchHandle
245 demClientErrorEx(IN HANDLE FileHandle
,
250 return GetLastError();
255 demFileDelete(IN LPCSTR FileName
)
257 if (DeleteFileA(FileName
)) SetLastError(ERROR_SUCCESS
);
259 return GetLastError();
264 demFileFindFirst(OUT PVOID lpFindFileData
,
268 BOOLEAN Success
= TRUE
;
269 WIN32_FIND_DATAA FindData
;
270 PDOS_FIND_FILE_BLOCK FindFileBlock
= (PDOS_FIND_FILE_BLOCK
)lpFindFileData
;
273 FindFileBlock
->DriveLetter
= CurrentDrive
+ 'A';
274 FindFileBlock
->AttribMask
= AttribMask
;
275 FindFileBlock
->SearchHandle
= FindFirstFileA(FileName
, &FindData
);
276 if (FindFileBlock
->SearchHandle
== INVALID_HANDLE_VALUE
) return GetLastError();
280 /* Check the attributes */
281 if (!((FindData
.dwFileAttributes
& (FILE_ATTRIBUTE_HIDDEN
|
282 FILE_ATTRIBUTE_SYSTEM
|
283 FILE_ATTRIBUTE_DIRECTORY
))
289 while ((Success
= FindNextFileA(FindFileBlock
->SearchHandle
, &FindData
)));
291 if (!Success
) return GetLastError();
293 FindFileBlock
->Attributes
= LOBYTE(FindData
.dwFileAttributes
);
294 FileTimeToDosDateTime(&FindData
.ftLastWriteTime
,
295 &FindFileBlock
->FileDate
,
296 &FindFileBlock
->FileTime
);
297 FindFileBlock
->FileSize
= FindData
.nFileSizeHigh
? 0xFFFFFFFF
298 : FindData
.nFileSizeLow
;
299 strcpy(FindFileBlock
->FileName
, FindData
.cAlternateFileName
);
301 return ERROR_SUCCESS
;
306 demFileFindNext(OUT PVOID lpFindFileData
)
308 WIN32_FIND_DATAA FindData
;
309 PDOS_FIND_FILE_BLOCK FindFileBlock
= (PDOS_FIND_FILE_BLOCK
)lpFindFileData
;
313 if (!FindNextFileA(FindFileBlock
->SearchHandle
, &FindData
))
314 return GetLastError();
316 /* Update the block */
317 FindFileBlock
->Attributes
= LOBYTE(FindData
.dwFileAttributes
);
318 FileTimeToDosDateTime(&FindData
.ftLastWriteTime
,
319 &FindFileBlock
->FileDate
,
320 &FindFileBlock
->FileTime
);
321 FindFileBlock
->FileSize
= FindData
.nFileSizeHigh
? 0xFFFFFFFF
322 : FindData
.nFileSizeLow
;
323 strcpy(FindFileBlock
->FileName
, FindData
.cAlternateFileName
);
325 while((FindData
.dwFileAttributes
& (FILE_ATTRIBUTE_HIDDEN
|
326 FILE_ATTRIBUTE_SYSTEM
|
327 FILE_ATTRIBUTE_DIRECTORY
))
328 & ~FindFileBlock
->AttribMask
);
330 return ERROR_SUCCESS
;
335 demGetPhysicalDriveType(IN UCHAR DriveNumber
)
338 return DOSDEVICE_DRIVE_UNKNOWN
;
343 demIsShortPathName(IN LPCSTR Path
,
352 demSetCurrentDirectoryGetDrive(IN LPCSTR CurrentDirectory
,
353 OUT PUCHAR DriveNumber
)
356 return ERROR_SUCCESS
;