[NTVDM]: Commit what I have in my local wc so far (and which is commitable & works):
[reactos.git] / reactos / subsystems / mvdm / ntvdm / dos / dos32krnl / bios.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: dos/dos32krnl/bios.c
5 * PURPOSE: DOS32 Bios
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #define NDEBUG
12
13 #include "ntvdm.h"
14 #include "emulator.h"
15 #include "int32.h"
16
17 #include "dos.h"
18 #include "dosfiles.h"
19 #include "memory.h"
20 #include "bios/bios.h"
21
22 // This is needed because on UNICODE this symbol is redirected to
23 // GetEnvironmentStringsW whereas on ANSI it corresponds to the real
24 // "ANSI" function (and GetEnvironmentStringsA is aliased to it).
25 #undef GetEnvironmentStrings
26
27 // Symmetrize the dumbness of the previous symbol: on UNICODE
28 // FreeEnvironmentStrings aliases to FreeEnvironmentStringsW but
29 // on "ANSI" FreeEnvironmentStrings aliases to FreeEnvironmentStringsA
30 #undef FreeEnvironmentStrings
31 #define FreeEnvironmentStrings FreeEnvironmentStringsA
32
33 /* PRIVATE VARIABLES **********************************************************/
34
35 // static BYTE CurrentDrive;
36 // static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH];
37
38 /* PRIVATE FUNCTIONS **********************************************************/
39
40 /* PUBLIC FUNCTIONS ***********************************************************/
41
42 CHAR DosReadCharacter(WORD FileHandle)
43 {
44 WORD BytesRead;
45
46 Sda->ByteBuffer = '\0';
47 DPRINT("DosReadCharacter\n");
48
49 /* Use the file reading function */
50 DosReadFile(FileHandle,
51 MAKELONG(DOS_DATA_OFFSET(Sda.ByteBuffer), DOS_DATA_SEGMENT),
52 1,
53 &BytesRead);
54
55 return Sda->ByteBuffer;
56 }
57
58 BOOLEAN DosCheckInput(VOID)
59 {
60 PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(DOS_INPUT_HANDLE);
61
62 if (Descriptor == NULL)
63 {
64 /* Invalid handle */
65 Sda->LastErrorCode = ERROR_INVALID_HANDLE; // ERROR_FILE_NOT_FOUND
66 return FALSE;
67 }
68
69 if (Descriptor->DeviceInfo & (1 << 7))
70 {
71 WORD Result;
72 PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer);
73
74 if (!Node->InputStatusRoutine) return FALSE;
75
76 Result = Node->InputStatusRoutine(Node);
77 return !(Result & DOS_DEVSTAT_BUSY);
78 }
79 else
80 {
81 DWORD FileSizeHigh;
82 DWORD FileSize = GetFileSize(Descriptor->Win32Handle, &FileSizeHigh);
83 LONG LocationHigh = 0;
84 DWORD Location = SetFilePointer(Descriptor->Win32Handle, 0, &LocationHigh, FILE_CURRENT);
85
86 return ((Location != FileSize) || (LocationHigh != FileSizeHigh));
87 }
88 }
89
90 VOID DosPrintCharacter(WORD FileHandle, CHAR Character)
91 {
92 WORD BytesWritten;
93
94 Sda->ByteBuffer = Character;
95
96 /* Use the file writing function */
97 DosWriteFile(FileHandle,
98 MAKELONG(DOS_DATA_OFFSET(Sda.ByteBuffer), DOS_DATA_SEGMENT),
99 1,
100 &BytesWritten);
101 }
102
103 BOOLEAN DosBuildSysEnvBlock(VOID)
104 {
105 LPSTR SourcePtr, Environment;
106 LPSTR DestPtr = (LPSTR)SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0);
107
108 /* Get the environment strings */
109 SourcePtr = Environment = GetEnvironmentStrings();
110 if (Environment == NULL) return FALSE;
111
112 /* Fill the DOS system environment block */
113 while (*SourcePtr)
114 {
115 /*
116 * - Ignore environment strings starting with a '=',
117 * they describe current directories.
118 * - Ignore also the WINDIR environment variable since
119 * DOS apps should ignore that we started from ReactOS.
120 * - Upper-case the environment names, not their values.
121 */
122 if (*SourcePtr != '=' && _strnicmp(SourcePtr, "WINDIR", 6) != 0)
123 {
124 PCHAR Delim = NULL;
125
126 /* Copy the environment string */
127 strcpy(DestPtr, SourcePtr);
128
129 /* Upper-case the environment name */
130 Delim = strchr(DestPtr, '='); // Find the '=' delimiter
131 if (Delim) *Delim = '\0'; // Temporarily replace it by NULL
132 _strupr(DestPtr); // Upper-case
133 if (Delim) *Delim = '='; // Restore the delimiter
134
135 DestPtr += strlen(SourcePtr);
136
137 /* NULL-terminate the environment string */
138 *(DestPtr++) = '\0';
139 }
140
141 /* Move to the next string */
142 SourcePtr += strlen(SourcePtr) + 1;
143 }
144 /* NULL-terminate the environment block */
145 *DestPtr = '\0';
146
147 /* Free the memory allocated for environment strings */
148 FreeEnvironmentStrings(Environment);
149
150 return TRUE;
151 }
152
153 BOOLEAN DosBIOSInitialize(VOID)
154 {
155 #if 0
156 UCHAR i;
157 CHAR CurrentDirectory[MAX_PATH];
158 CHAR DosDirectory[DOS_DIR_LENGTH];
159 LPSTR Path;
160
161 FILE *Stream;
162 WCHAR Buffer[256];
163 #endif
164
165 /* Set the data segment */
166 setDS(DOS_DATA_SEGMENT);
167
168 /* Initialize the DOS stack */
169 // Stack just before FIRST_MCB_SEGMENT and after SYSTEM_ENV_BLOCK
170 // FIXME: Add a block of fixed size for the stack in DOS_DATA instead!
171 setSS(0x0F00);
172 setSP(0x0FF0);
173 setBP(0x091E); // DOS base stack pointer relic value
174
175 /* Initialize memory management */
176 DosInitializeMemory();
177
178 /* Build the system master environment block (inherited by the shell) */
179 if (!DosBuildSysEnvBlock())
180 {
181 DPRINT1("An error occurred when setting up the system environment block.\n");
182 }
183
184
185 #if 0
186
187 /* Clear the current directory buffer */
188 RtlZeroMemory(CurrentDirectories, sizeof(CurrentDirectories));
189
190 /* Get the current directory */
191 if (!GetCurrentDirectoryA(MAX_PATH, CurrentDirectory))
192 {
193 // TODO: Use some kind of default path?
194 return FALSE;
195 }
196
197 /* Convert that to a DOS path */
198 if (!GetShortPathNameA(CurrentDirectory, DosDirectory, DOS_DIR_LENGTH))
199 {
200 // TODO: Use some kind of default path?
201 return FALSE;
202 }
203
204 /* Set the drive */
205 Sda->CurrentDrive = DosDirectory[0] - 'A';
206
207 /* Get the directory part of the path */
208 Path = strchr(DosDirectory, '\\');
209 if (Path != NULL)
210 {
211 /* Skip the backslash */
212 Path++;
213 }
214
215 /* Set the directory */
216 if (Path != NULL)
217 {
218 strncpy(CurrentDirectories[Sda->CurrentDrive], Path, DOS_DIR_LENGTH);
219 }
220
221 /* Read CONFIG.SYS */
222 Stream = _wfopen(DOS_CONFIG_PATH, L"r");
223 if (Stream != NULL)
224 {
225 while (fgetws(Buffer, ARRAYSIZE(Buffer), Stream))
226 {
227 // TODO: Parse the line
228 }
229 fclose(Stream);
230 }
231
232 #endif
233
234
235 /* Register the DOS 32-bit Interrupts */
236 // RegisterDosInt32(0x20, DosInt20h);
237
238 /* Initialize the DOS kernel */
239 return DosKRNLInitialize();
240 }
241
242 /* EOF */