b7f01790735a136cc8ab0f65abfbc2adfc5f53b7
[reactos.git] / subsystems / ntvdm / dos / dem.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: dem.c
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)
11 */
12
13 /* INCLUDES *******************************************************************/
14
15 #define NDEBUG
16
17 #include "emulator.h"
18
19 #include "dem.h"
20 #include "bop.h"
21
22 /* Extra PSDK/NDK Headers */
23 #include <ndk/obtypes.h>
24
25 /* PRIVATE VARIABLES **********************************************************/
26
27 /**/extern BYTE CurrentDrive;/**/
28
29 /* DEFINES ********************************************************************/
30
31 /* BOP Identifiers */
32 #define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
33 #define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
34
35 /* PRIVATE FUNCTIONS **********************************************************/
36
37 static VOID WINAPI DosSystemBop(LPWORD Stack)
38 {
39 /* Get the Function Number and skip it */
40 BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
41 setIP(getIP() + 1);
42
43 DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum);
44 }
45
46 static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
47 {
48 /* Get the Function Number and skip it */
49 BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
50 setIP(getIP() + 1);
51
52 switch (FuncNum)
53 {
54 case 0x08: // Launch external command
55 {
56 #define CMDLINE_LENGTH 1024
57
58 BOOL Result;
59 DWORD dwExitCode;
60
61 LPSTR Command = (LPSTR)SEG_OFF_TO_PTR(getDS(), getSI());
62 LPSTR CmdPtr = Command;
63 CHAR CommandLine[CMDLINE_LENGTH] = "";
64 STARTUPINFOA StartupInfo;
65 PROCESS_INFORMATION ProcessInformation;
66
67 /* Remove return carriage character */
68 while (*CmdPtr != '\r') CmdPtr++;
69 *CmdPtr = '\0';
70
71 DPRINT1("CMD Run Command '%s'\n", Command);
72
73 /* Spawn a user-defined 32-bit command preprocessor */
74
75 /* Build the command line */
76 // FIXME: Use COMSPEC env var!!
77 strcpy(CommandLine, "cmd.exe /c ");
78 strcat(CommandLine, Command);
79
80 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
81 ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
82
83 StartupInfo.cb = sizeof(StartupInfo);
84
85 DosPrintCharacter('\n');
86
87 Result = CreateProcessA(NULL,
88 CommandLine,
89 NULL,
90 NULL,
91 TRUE,
92 0,
93 NULL,
94 NULL,
95 &StartupInfo,
96 &ProcessInformation);
97 if (Result)
98 {
99 DPRINT1("Command '%s' launched successfully\n", Command);
100
101 /* Wait for process termination */
102 WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
103
104 /* Get the exit code */
105 GetExitCodeProcess(ProcessInformation.hProcess, &dwExitCode);
106
107 /* Close handles */
108 CloseHandle(ProcessInformation.hThread);
109 CloseHandle(ProcessInformation.hProcess);
110 }
111 else
112 {
113 DPRINT1("Failed when launched command '%s'\n");
114 dwExitCode = GetLastError();
115 }
116
117 DosPrintCharacter('\n');
118
119 setAL((UCHAR)dwExitCode);
120
121 break;
122 }
123
124 default:
125 {
126 DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum);
127 // setCF(1); // Disable, otherwise we enter an infinite loop
128 break;
129 }
130 }
131 }
132
133 /* PUBLIC FUNCTIONS ***********************************************************/
134
135 BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames)
136 {
137 /* Register the DOS BOPs */
138 RegisterBop(BOP_DOS, DosSystemBop );
139 RegisterBop(BOP_CMD, DosCmdInterpreterBop);
140
141 if (DosKernelFileNames)
142 {
143 DisplayMessage(L"NTVDM: Loading DOS kernel from external files is currently unsupported");
144 return FALSE;
145 }
146 else
147 {
148 BOOLEAN Result;
149
150 Result = DosBIOSInitialize();
151 // Result &= DosKRNLInitialize();
152
153 return Result;
154 }
155 }
156
157 /* PUBLIC EXPORTED APIS *******************************************************/
158
159 // demLFNCleanup
160 // demLFNGetCurrentDirectory
161
162 // demGetFileTimeByHandle_WOW
163 // demWOWLFNAllocateSearchHandle
164 // demWOWLFNCloseSearchHandle
165 // demWOWLFNEntry
166 // demWOWLFNGetSearchHandle
167 // demWOWLFNInit
168
169 DWORD
170 WINAPI
171 demClientErrorEx(IN HANDLE FileHandle,
172 IN CHAR Unknown,
173 IN BOOL Flag)
174 {
175 UNIMPLEMENTED;
176 return GetLastError();
177 }
178
179 DWORD
180 WINAPI
181 demFileDelete(IN LPCSTR FileName)
182 {
183 if (DeleteFileA(FileName)) SetLastError(ERROR_SUCCESS);
184
185 return GetLastError();
186 }
187
188 DWORD
189 WINAPI
190 demFileFindFirst(OUT PVOID lpFindFileData,
191 IN LPCSTR FileName,
192 IN WORD AttribMask)
193 {
194 BOOLEAN Success = TRUE;
195 WIN32_FIND_DATAA FindData;
196 PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)lpFindFileData;
197
198 /* Fill the block */
199 FindFileBlock->DriveLetter = CurrentDrive + 'A';
200 FindFileBlock->AttribMask = AttribMask;
201 FindFileBlock->SearchHandle = FindFirstFileA(FileName, &FindData);
202 if (FindFileBlock->SearchHandle == INVALID_HANDLE_VALUE) return GetLastError();
203
204 do
205 {
206 /* Check the attributes */
207 if (!((FindData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN |
208 FILE_ATTRIBUTE_SYSTEM |
209 FILE_ATTRIBUTE_DIRECTORY))
210 & ~AttribMask))
211 {
212 break;
213 }
214 }
215 while ((Success = FindNextFileA(FindFileBlock->SearchHandle, &FindData)));
216
217 if (!Success) return GetLastError();
218
219 FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes);
220 FileTimeToDosDateTime(&FindData.ftLastWriteTime,
221 &FindFileBlock->FileDate,
222 &FindFileBlock->FileTime);
223 FindFileBlock->FileSize = FindData.nFileSizeHigh ? 0xFFFFFFFF
224 : FindData.nFileSizeLow;
225 strcpy(FindFileBlock->FileName, FindData.cAlternateFileName);
226
227 return ERROR_SUCCESS;
228 }
229
230 DWORD
231 WINAPI
232 demFileFindNext(OUT PVOID lpFindFileData)
233 {
234 WIN32_FIND_DATAA FindData;
235 PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)lpFindFileData;
236
237 do
238 {
239 if (!FindNextFileA(FindFileBlock->SearchHandle, &FindData))
240 return GetLastError();
241
242 /* Update the block */
243 FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes);
244 FileTimeToDosDateTime(&FindData.ftLastWriteTime,
245 &FindFileBlock->FileDate,
246 &FindFileBlock->FileTime);
247 FindFileBlock->FileSize = FindData.nFileSizeHigh ? 0xFFFFFFFF
248 : FindData.nFileSizeLow;
249 strcpy(FindFileBlock->FileName, FindData.cAlternateFileName);
250 }
251 while((FindData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN |
252 FILE_ATTRIBUTE_SYSTEM |
253 FILE_ATTRIBUTE_DIRECTORY))
254 & ~FindFileBlock->AttribMask);
255
256 return ERROR_SUCCESS;
257 }
258
259 UCHAR
260 WINAPI
261 demGetPhysicalDriveType(IN UCHAR DriveNumber)
262 {
263 UNIMPLEMENTED;
264 return DOSDEVICE_DRIVE_UNKNOWN;
265 }
266
267 BOOL
268 WINAPI
269 demIsShortPathName(IN LPCSTR Path,
270 IN BOOL Unknown)
271 {
272 UNIMPLEMENTED;
273 return FALSE;
274 }
275
276 DWORD
277 WINAPI
278 demSetCurrentDirectoryGetDrive(IN LPCSTR CurrentDirectory,
279 OUT PUCHAR DriveNumber)
280 {
281 UNIMPLEMENTED;
282 return ERROR_SUCCESS;
283 }
284
285 /* EOF */