ReactOS  0.4.14-dev-583-g2a1ba2c
dos.c File Reference
#include "ntvdm.h"
#include <debug.h>
#include "emulator.h"
#include "cpu/cpu.h"
#include "int32.h"
#include "dos.h"
#include "dos/dem.h"
#include "country.h"
#include "device.h"
#include "handle.h"
#include "dosfiles.h"
#include "memory.h"
#include "process.h"
#include "himem.h"
#include "bios/bios.h"
#include "io.h"
#include "hardware/ps2.h"
#include "emsdrv.h"
Include dependency graph for dos.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static BOOLEAN DosChangeDrive (BYTE Drive)
 
static BOOLEAN DosChangeDirectory (LPSTR Directory)
 
static BOOLEAN DosIsFileOnCdRom (VOID)
 
BOOLEAN DosControlBreak (VOID)
 
VOID WINAPI DosInt20h (LPWORD Stack)
 
VOID WINAPI DosInt21h (LPWORD Stack)
 
VOID WINAPI DosBreakInterrupt (LPWORD Stack)
 
VOID WINAPI DosAbsoluteRead (LPWORD Stack)
 
VOID WINAPI DosAbsoluteWrite (LPWORD Stack)
 
VOID WINAPI DosInt27h (LPWORD Stack)
 
VOID WINAPI DosIdle (LPWORD Stack)
 
VOID WINAPI DosFastConOut (LPWORD Stack)
 
VOID WINAPI DosInt2Ah (LPWORD Stack)
 
VOID WINAPI DosInt2Fh (LPWORD Stack)
 
BOOLEAN DosKRNLInitialize (VOID)
 

Variables

CALLBACK16 DosContext
 
PDOS_DATA DosData
 
PDOS_SYSVARS SysVars
 
PDOS_SDA Sda
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file dos.c.

Function Documentation

◆ DosAbsoluteRead()

VOID WINAPI DosAbsoluteRead ( LPWORD  Stack)

Definition at line 2021 of file dos.c.

2022 {
2023  /*
2024  * This call should leave the flags on the stack for some reason,
2025  * so move the stack by one word.
2026  * See: http://www.techhelpmanual.com/565-int_25h_26h__absolute_disk_read_write.html
2027  */
2028  Stack[STACK_INT_NUM] = Stack[STACK_IP];
2029  Stack[STACK_IP] = Stack[STACK_CS];
2030  Stack[STACK_CS] = Stack[STACK_FLAGS];
2031  setSP(LOWORD(getSP() - 2));
2032 
2033  // TODO: NOT IMPLEMENTED;
2034  UNIMPLEMENTED;
2035 
2036  /* General failure */
2037  setAX(0x800C);
2038  Stack[STACK_FLAGS - 1] |= EMULATOR_FLAG_CF;
2039 }
#define STACK_INT_NUM
Definition: int32.h:30
VOID WINAPI setAX(USHORT)
Definition: registers.c:121
#define EMULATOR_FLAG_CF
Definition: cpu.h:19
VOID WINAPI setSP(USHORT)
Definition: registers.c:351
#define STACK_FLAGS
Definition: int32.h:35
#define STACK_CS
Definition: int32.h:34
#define UNIMPLEMENTED
Definition: debug.h:114
USHORT WINAPI getSP(VOID)
Definition: registers.c:344
#define STACK_IP
Definition: int32.h:33
#define LOWORD(l)
Definition: pedump.c:82

Referenced by DosKRNLInitialize().

◆ DosAbsoluteWrite()

VOID WINAPI DosAbsoluteWrite ( LPWORD  Stack)

Definition at line 2041 of file dos.c.

2042 {
2043  /*
2044  * This call should leave the flags on the stack for some reason,
2045  * so move the stack by one word.
2046  * See: http://www.techhelpmanual.com/565-int_25h_26h__absolute_disk_read_write.html
2047  */
2048  Stack[STACK_INT_NUM] = Stack[STACK_IP];
2049  Stack[STACK_IP] = Stack[STACK_CS];
2050  Stack[STACK_CS] = Stack[STACK_FLAGS];
2051  setSP(LOWORD(getSP() - 2));
2052 
2053  // TODO: NOT IMPLEMENTED;
2054  UNIMPLEMENTED;
2055 
2056  /* General failure */
2057  setAX(0x800C);
2058  Stack[STACK_FLAGS - 1] |= EMULATOR_FLAG_CF;
2059 }
#define STACK_INT_NUM
Definition: int32.h:30
VOID WINAPI setAX(USHORT)
Definition: registers.c:121
#define EMULATOR_FLAG_CF
Definition: cpu.h:19
VOID WINAPI setSP(USHORT)
Definition: registers.c:351
#define STACK_FLAGS
Definition: int32.h:35
#define STACK_CS
Definition: int32.h:34
#define UNIMPLEMENTED
Definition: debug.h:114
USHORT WINAPI getSP(VOID)
Definition: registers.c:344
#define STACK_IP
Definition: int32.h:33
#define LOWORD(l)
Definition: pedump.c:82

Referenced by DosKRNLInitialize().

◆ DosBreakInterrupt()

VOID WINAPI DosBreakInterrupt ( LPWORD  Stack)

Definition at line 2015 of file dos.c.

2016 {
2017  /* Set CF to terminate the running process */
2018  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
2019 }
#define EMULATOR_FLAG_CF
Definition: cpu.h:19
#define STACK_FLAGS
Definition: int32.h:35

Referenced by DosKRNLInitialize().

◆ DosChangeDirectory()

static BOOLEAN DosChangeDirectory ( LPSTR  Directory)
static

Definition at line 78 of file dos.c.

79 {
80  BYTE DriveNumber;
82  LPSTR Path;
84  CHAR DosDirectory[DOS_DIR_LENGTH];
85 
86  /* Make sure the directory path is not too long */
88  {
90  return FALSE;
91  }
92 
93  /* Check whether the directory string is of format "X:..." */
94  if (strlen(Directory) >= 2 && Directory[1] == ':')
95  {
96  /* Get the drive number */
97  DriveNumber = RtlUpperChar(Directory[0]) - 'A';
98 
99  /* Make sure the drive exists */
100  if (DriveNumber >= SysVars->NumLocalDrives)
101  {
103  return FALSE;
104  }
105  }
106  else
107  {
108  /* Keep the current drive number */
109  DriveNumber = Sda->CurrentDrive;
110  }
111 
112  /* Get the file attributes */
114 
115  /* Make sure the path exists and is a directory */
118  {
120  return FALSE;
121  }
122 
123  /* Check if this is the current drive */
124  if (DriveNumber == Sda->CurrentDrive)
125  {
126  /* Change the directory */
128  {
130  return FALSE;
131  }
132  }
133 
134  /* Get the (possibly new) current directory (needed if we specified a relative directory) */
136  {
137  // TODO: Use some kind of default path?
138  return FALSE;
139  }
140 
141  /* Convert it to a DOS path */
142  if (!GetShortPathNameA(CurrentDirectory, DosDirectory, sizeof(DosDirectory)))
143  {
144  // TODO: Use some kind of default path?
145  return FALSE;
146  }
147 
148  /* Get the directory part of the path and set the current directory for the drive */
149  Path = strchr(DosDirectory, '\\');
150  if (Path != NULL)
151  {
152  Path++; // Skip the backslash
154  }
155  else
156  {
157  DosData->CurrentDirectories[DriveNumber][0] = '\0';
158  }
159 
160  /* Return success */
161  return TRUE;
162 }
WORD LastErrorCode
Definition: dos.h:151
#define DOS_DIR_LENGTH
Definition: dos.h:47
#define TRUE
Definition: types.h:120
WCHAR CurrentDirectory[1024]
Definition: chkdsk.c:74
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH]
Definition: dos.h:248
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
char CHAR
Definition: xmlstorage.h:175
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
char * LPSTR
Definition: xmlstorage.h:182
PDOS_DATA DosData
Definition: dos.c:45
BYTE CurrentDrive
Definition: dos.h:159
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:786
smooth NULL
Definition: ftsmooth.c:416
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
DWORD WINAPI GetShortPathNameA(IN LPCSTR lpszLongPath, OUT LPSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1751
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
NTSYSAPI CHAR NTAPI RtlUpperChar(CHAR Character)
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2205
unsigned char BYTE
Definition: mem.h:68
PDOS_SDA Sda
Definition: dos.c:48
BYTE NumLocalDrives
Definition: dos.h:88
_Must_inspect_result_ _In_ USHORT _In_ PHIDP_PREPARSED_DATA _Out_writes_to_ LengthAttributes PHIDP_EXTENDED_ATTRIBUTES Attributes
Definition: hidpi.h:348
PRTL_UNICODE_STRING_BUFFER Path
PDOS_SYSVARS SysVars
Definition: dos.c:47
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2145
char * strchr(const char *String, int ch)
Definition: utclib.c:501
base for all directory entries
Definition: entries.h:138
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define LOWORD(l)
Definition: pedump.c:82

Referenced by DosInt21h().

◆ DosChangeDrive()

static BOOLEAN DosChangeDrive ( BYTE  Drive)
static

Definition at line 52 of file dos.c.

53 {
54  CHAR DirectoryPath[DOS_CMDLINE_LENGTH + 1];
55 
56  /* Make sure the drive exists */
57  if (Drive >= SysVars->NumLocalDrives) return FALSE;
58 
59  RtlZeroMemory(DirectoryPath, sizeof(DirectoryPath));
60 
61  /* Find the path to the new current directory */
62  snprintf(DirectoryPath,
64  "%c:\\%s",
65  'A' + Drive,
67 
68  /* Change the current directory of the process */
69  if (!SetCurrentDirectoryA(DirectoryPath)) return FALSE;
70 
71  /* Set the current drive */
73 
74  /* Return success */
75  return TRUE;
76 }
#define TRUE
Definition: types.h:120
CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH]
Definition: dos.h:248
char CHAR
Definition: xmlstorage.h:175
#define snprintf
Definition: wintirpc.h:48
#define DOS_CMDLINE_LENGTH
Definition: process.h:13
PDOS_DATA DosData
Definition: dos.c:45
BYTE CurrentDrive
Definition: dos.h:159
PWCHAR Drive
Definition: chkdsk.c:73
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2205
PDOS_SDA Sda
Definition: dos.c:48
BYTE NumLocalDrives
Definition: dos.h:88
PDOS_SYSVARS SysVars
Definition: dos.c:47
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261

Referenced by DosInt21h().

◆ DosControlBreak()

BOOLEAN DosControlBreak ( VOID  )

Definition at line 181 of file dos.c.

182 {
183  setCF(0);
184 
185  /* Print an extra newline */
188 
189  /* Call interrupt 0x23 */
190  Int32Call(&DosContext, 0x23);
191 
192  if (getCF())
193  {
195  return TRUE;
196  }
197 
198  return FALSE;
199 }
#define DOS_OUTPUT_HANDLE
Definition: dos.h:43
WORD CurrentPsp
Definition: dos.h:156
#define TRUE
Definition: types.h:120
VOID Int32Call(IN PCALLBACK16 Context, IN BYTE IntNumber)
Definition: int32.c:151
VOID DosPrintCharacter(WORD FileHandle, CHAR Character)
Definition: bios.c:152
CALLBACK16 DosContext
Definition: dos.c:40
VOID WINAPI setCF(ULONG)
Definition: registers.c:573
PDOS_SDA Sda
Definition: dos.c:48
VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode, WORD KeepResident)
Definition: process.c:873
ULONG WINAPI getCF(VOID)
Definition: registers.c:566

Referenced by DosInt21h(), and DosReadLineBuffered().

◆ DosFastConOut()

VOID WINAPI DosFastConOut ( LPWORD  Stack)

Definition at line 2079 of file dos.c.

2080 {
2081  /*
2082  * This is the DOS 2+ Fast Console Output Interrupt.
2083  * The default handler under DOS 2.x and 3.x simply calls INT 10h/AH=0Eh.
2084  *
2085  * See Ralf Brown: http://www.ctyme.com/intr/rb-4124.htm
2086  * for more information.
2087  */
2088 
2089  /* Save AX and BX */
2090  USHORT AX = getAX();
2091  USHORT BX = getBX();
2092 
2093  /*
2094  * Set the parameters:
2095  * AL contains the character to print (already set),
2096  * BL contains the character attribute,
2097  * BH contains the video page to use.
2098  */
2100  setBH(Bda->VideoPage);
2101 
2102  /* Call the BIOS INT 10h, AH=0Eh "Teletype Output" */
2103  setAH(0x0E);
2105 
2106  /* Restore AX and BX */
2107  setBX(BX);
2108  setAX(AX);
2109 }
USHORT WINAPI getBX(VOID)
Definition: registers.c:170
BYTE VideoPage
Definition: bios.h:66
VOID WINAPI setBL(UCHAR)
Definition: registers.c:205
VOID WINAPI setAH(UCHAR)
Definition: registers.c:135
VOID WINAPI setAX(USHORT)
Definition: registers.c:121
VOID Int32Call(IN PCALLBACK16 Context, IN BYTE IntNumber)
Definition: int32.c:151
PBIOS_DATA_AREA Bda
Definition: bios.c:42
#define AX
Definition: i386-dis.c:415
#define BIOS_VIDEO_INTERRUPT
Definition: vidbios.h:15
CALLBACK16 DosContext
Definition: dos.c:40
#define DOS_CHAR_ATTRIBUTE
Definition: dos.h:49
USHORT WINAPI getAX(VOID)
Definition: registers.c:114
VOID WINAPI setBX(USHORT)
Definition: registers.c:177
VOID WINAPI setBH(UCHAR)
Definition: registers.c:191
unsigned short USHORT
Definition: pedump.c:61

Referenced by DosKRNLInitialize().

◆ DosIdle()

VOID WINAPI DosIdle ( LPWORD  Stack)

Definition at line 2070 of file dos.c.

2071 {
2072  /*
2073  * This will set the carry flag on the first call (to repeat the BOP),
2074  * and clear it in the next, so that exactly one HLT occurs.
2075  */
2076  setCF(!getCF());
2077 }
VOID WINAPI setCF(ULONG)
Definition: registers.c:573
ULONG WINAPI getCF(VOID)
Definition: registers.c:566

Referenced by DosKRNLInitialize().

◆ DosInt20h()

VOID WINAPI DosInt20h ( LPWORD  Stack)

Definition at line 201 of file dos.c.

202 {
203  /*
204  * This is the exit interrupt (alias to INT 21h, AH=00h).
205  * CS must be the PSP segment.
206  */
207  DosTerminateProcess(Stack[STACK_CS], 0, 0);
208 }
#define STACK_CS
Definition: int32.h:34
VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode, WORD KeepResident)
Definition: process.c:873

Referenced by DosKRNLInitialize().

◆ DosInt21h()

VOID WINAPI DosInt21h ( LPWORD  Stack)

Definition at line 210 of file dos.c.

211 {
212  BYTE Character;
213  SYSTEMTIME SystemTime;
214  PCHAR String;
215 
216  Sda->InDos++;
217 
218  /* Save the value of SS:SP on entry in the PSP */
219  SEGMENT_TO_PSP(Sda->CurrentPsp)->LastStack =
220  MAKELONG(getSP() + (STACK_FLAGS + 1) * 2, getSS());
221 
222  /* Check the value in the AH register */
223  switch (getAH())
224  {
225  /* Terminate Program */
226  case 0x00:
227  {
228  /* CS must be the PSP segment */
229  DosTerminateProcess(Stack[STACK_CS], 0, 0);
230  break;
231  }
232 
233  /* Read Character from STDIN with Echo */
234  case 0x01:
235  {
236  DPRINT("INT 21h, AH = 01h\n");
237 
238  Character = DosReadCharacter(DOS_INPUT_HANDLE, TRUE);
239  if (Character == 0x03 && DosControlBreak()) break;
240 
241  setAL(Character);
242  break;
243  }
244 
245  /* Write Character to STDOUT */
246  case 0x02:
247  {
248  // FIXME: Under DOS 2+, output handle may be redirected!!!!
249  Character = getDL();
251 
252  /*
253  * We return the output character (DOS 2.1+).
254  * Also, if we're going to output a TAB, then
255  * don't return a TAB but a SPACE instead.
256  * See Ralf Brown: http://www.ctyme.com/intr/rb-2554.htm
257  * for more information.
258  */
259  setAL(Character == '\t' ? ' ' : Character);
260  break;
261  }
262 
263  /* Read Character from STDAUX */
264  case 0x03:
265  {
266  // FIXME: Really read it from STDAUX!
267  DPRINT1("INT 16h, 03h: Read character from STDAUX is HALFPLEMENTED\n");
268  // setAL(DosReadCharacter());
269  break;
270  }
271 
272  /* Write Character to STDAUX */
273  case 0x04:
274  {
275  // FIXME: Really write it to STDAUX!
276  DPRINT1("INT 16h, 04h: Write character to STDAUX is HALFPLEMENTED\n");
277  // DosPrintCharacter(getDL());
278  break;
279  }
280 
281  /* Write Character to Printer */
282  case 0x05:
283  {
284  // FIXME: Really write it to printer!
285  DPRINT1("INT 16h, 05h: Write character to printer is HALFPLEMENTED -\n\n");
286  DPRINT1("0x%p\n", getDL());
287  DPRINT1("\n\n-----------\n\n");
288  break;
289  }
290 
291  /* Direct Console I/O */
292  case 0x06:
293  {
294  Character = getDL();
295 
296  // FIXME: Under DOS 2+, output handle may be redirected!!!!
297 
298  if (Character != 0xFF)
299  {
300  /* Output */
302 
303  /*
304  * We return the output character (DOS 2.1+).
305  * See Ralf Brown: http://www.ctyme.com/intr/rb-2558.htm
306  * for more information.
307  */
308  setAL(Character);
309  }
310  else
311  {
312  /* Input */
313  if (DosCheckInput())
314  {
315  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
317  }
318  else
319  {
320  /* No character available */
321  Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF;
322  setAL(0x00);
323  }
324  }
325 
326  break;
327  }
328 
329  /* Direct Character Input without Echo */
330  case 0x07:
331  {
332  DPRINT("Direct char input without echo\n");
334  break;
335  }
336 
337  /* Character Input without Echo */
338  case 0x08:
339  {
340  DPRINT("Char input without echo\n");
341 
343  if (Character == 0x03 && DosControlBreak()) break;
344 
345  setAL(Character);
346  break;
347  }
348 
349  /* Write String to STDOUT */
350  case 0x09:
351  {
353 
354  while (*String != '$')
355  {
357  String++;
358  }
359 
360  /*
361  * We return the terminating character (DOS 2.1+).
362  * See Ralf Brown: http://www.ctyme.com/intr/rb-2562.htm
363  * for more information.
364  */
365  setAL('$'); // *String
366  break;
367  }
368 
369  /* Read Buffered Input */
370  case 0x0A:
371  {
373 
374  DPRINT("Read Buffered Input\n");
375  if (InputBuffer->MaxLength == 0) break;
376 
377  /* Read from standard input */
381  InputBuffer->MaxLength
382  );
383 
384  break;
385  }
386 
387  /* Get STDIN Status */
388  case 0x0B:
389  {
390  setAL(DosCheckInput() ? 0xFF : 0x00);
391  break;
392  }
393 
394  /* Flush Buffer and Read STDIN */
395  case 0x0C:
396  {
397  BYTE InputFunction = getAL();
398 
399  /* Flush STDIN buffer */
401 
402  /*
403  * If the input function number contained in AL is valid, i.e.
404  * AL == 0x01 or 0x06 or 0x07 or 0x08 or 0x0A, call ourselves
405  * recursively with AL == AH.
406  */
407  if (InputFunction == 0x01 || InputFunction == 0x06 ||
408  InputFunction == 0x07 || InputFunction == 0x08 ||
409  InputFunction == 0x0A)
410  {
411  /* Call ourselves recursively */
412  setAH(InputFunction);
413  DosInt21h(Stack);
414  }
415  break;
416  }
417 
418  /* Disk Reset */
419  case 0x0D:
420  {
421  PDOS_PSP PspBlock = SEGMENT_TO_PSP(Sda->CurrentPsp);
422 
423  // TODO: Flush what's needed.
424  DPRINT1("INT 21h, 0Dh is UNIMPLEMENTED\n");
425 
426  /* Clear CF in DOS 6 only */
427  if (PspBlock->DosVersion == 0x0006)
428  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
429 
430  break;
431  }
432 
433  /* Set Default Drive */
434  case 0x0E:
435  {
438  break;
439  }
440 
441  /* NULL Function for CP/M Compatibility */
442  case 0x18:
443  {
444  /*
445  * This function corresponds to the CP/M BDOS function
446  * "get bit map of logged drives", which is meaningless
447  * under MS-DOS.
448  *
449  * For: PTS-DOS 6.51 & S/DOS 1.0 - EXTENDED RENAME FILE USING FCB
450  * See Ralf Brown: http://www.ctyme.com/intr/rb-2584.htm
451  * for more information.
452  */
453  setAL(0x00);
454  break;
455  }
456 
457  /* Get Default Drive */
458  case 0x19:
459  {
461  break;
462  }
463 
464  /* Set Disk Transfer Area */
465  case 0x1A:
466  {
468  break;
469  }
470 
471  /* NULL Function for CP/M Compatibility */
472  case 0x1D:
473  case 0x1E:
474  {
475  /*
476  * Function 0x1D corresponds to the CP/M BDOS function
477  * "get bit map of read-only drives", which is meaningless
478  * under MS-DOS.
479  * See Ralf Brown: http://www.ctyme.com/intr/rb-2592.htm
480  * for more information.
481  *
482  * Function 0x1E corresponds to the CP/M BDOS function
483  * "set file attributes", which was meaningless under MS-DOS 1.x.
484  * See Ralf Brown: http://www.ctyme.com/intr/rb-2593.htm
485  * for more information.
486  */
487  setAL(0x00);
488  break;
489  }
490 
491  /* NULL Function for CP/M Compatibility */
492  case 0x20:
493  {
494  /*
495  * This function corresponds to the CP/M BDOS function
496  * "get/set default user (sublibrary) number", which is meaningless
497  * under MS-DOS.
498  *
499  * For: S/DOS 1.0+ & PTS-DOS 6.51+ - GET OEM REVISION
500  * See Ralf Brown: http://www.ctyme.com/intr/rb-2596.htm
501  * for more information.
502  */
503  setAL(0x00);
504  break;
505  }
506 
507  /* Set Interrupt Vector */
508  case 0x25:
509  {
510  ULONG FarPointer = MAKELONG(getDX(), getDS());
511  DPRINT1("Setting interrupt 0x%02X to %04X:%04X ...\n",
512  getAL(), HIWORD(FarPointer), LOWORD(FarPointer));
513 
514  /* Write the new far pointer to the IDT */
515  ((PULONG)BaseAddress)[getAL()] = FarPointer;
516  break;
517  }
518 
519  /* Create New PSP */
520  case 0x26:
521  {
522  /* DOS 2+ assumes that the caller's CS is the segment of the PSP to copy */
523  DosClonePsp(getDX(), Stack[STACK_CS]);
524  break;
525  }
526 
527  /* Parse Filename into FCB */
528  case 0x29:
529  {
532  BYTE Options = getAL();
533  CHAR FillChar = ' ';
534  UINT i;
535 
536  if (FileName[1] == ':')
537  {
538  /* Set the drive number */
539  Fcb->DriveNumber = RtlUpperChar(FileName[0]) - 'A' + 1;
540 
541  /* Skip to the file name part */
542  FileName += 2;
543  }
544  else
545  {
546  /* No drive number specified */
547  if (Options & (1 << 1)) Fcb->DriveNumber = Sda->CurrentDrive + 1;
548  else Fcb->DriveNumber = 0;
549  }
550 
551  /* Parse the file name */
552  i = 0;
553  while ((*FileName > 0x20) && (i < 8))
554  {
555  if (*FileName == '.') break;
556  else if (*FileName == '*')
557  {
558  FillChar = '?';
559  break;
560  }
561 
562  Fcb->FileName[i++] = RtlUpperChar(*FileName++);
563  }
564 
565  /* Fill the whole field with blanks only if bit 2 is not set */
566  if ((FillChar != ' ') || (i != 0) || !(Options & (1 << 2)))
567  {
568  for (; i < 8; i++) Fcb->FileName[i] = FillChar;
569  }
570 
571  /* Skip to the extension part */
572  while (*FileName > 0x20 && *FileName != '.') FileName++;
573  if (*FileName == '.') FileName++;
574 
575  /* Now parse the extension */
576  i = 0;
577  FillChar = ' ';
578 
579  while ((*FileName > 0x20) && (i < 3))
580  {
581  if (*FileName == '*')
582  {
583  FillChar = '?';
584  break;
585  }
586 
587  Fcb->FileExt[i++] = RtlUpperChar(*FileName++);
588  }
589 
590  /* Fill the whole field with blanks only if bit 3 is not set */
591  if ((FillChar != ' ') || (i != 0) || !(Options & (1 << 3)))
592  {
593  for (; i < 3; i++) Fcb->FileExt[i] = FillChar;
594  }
595 
596  break;
597  }
598 
599  /* Get System Date */
600  case 0x2A:
601  {
602  GetLocalTime(&SystemTime);
603  setCX(SystemTime.wYear);
604  setDX(MAKEWORD(SystemTime.wDay, SystemTime.wMonth));
605  setAL(SystemTime.wDayOfWeek);
606  break;
607  }
608 
609  /* Set System Date */
610  case 0x2B:
611  {
612  GetLocalTime(&SystemTime);
613  SystemTime.wYear = getCX();
614  SystemTime.wMonth = getDH();
615  SystemTime.wDay = getDL();
616 
617  /* Return success or failure */
618  setAL(SetLocalTime(&SystemTime) ? 0x00 : 0xFF);
619  break;
620  }
621 
622  /* Get System Time */
623  case 0x2C:
624  {
625  GetLocalTime(&SystemTime);
626  setCX(MAKEWORD(SystemTime.wMinute, SystemTime.wHour));
627  setDX(MAKEWORD(SystemTime.wMilliseconds / 10, SystemTime.wSecond));
628  break;
629  }
630 
631  /* Set System Time */
632  case 0x2D:
633  {
634  GetLocalTime(&SystemTime);
635  SystemTime.wHour = getCH();
636  SystemTime.wMinute = getCL();
637  SystemTime.wSecond = getDH();
638  SystemTime.wMilliseconds = getDL() * 10; // In hundredths of seconds
639 
640  /* Return success or failure */
641  setAL(SetLocalTime(&SystemTime) ? 0x00 : 0xFF);
642  break;
643  }
644 
645  /* Get Disk Transfer Area */
646  case 0x2F:
647  {
650  break;
651  }
652 
653  /* Get DOS Version */
654  case 0x30:
655  {
656  PDOS_PSP PspBlock = SEGMENT_TO_PSP(Sda->CurrentPsp);
657 
658  /*
659  * DOS 2+ - GET DOS VERSION
660  * See Ralf Brown: http://www.ctyme.com/intr/rb-2711.htm
661  * for more information.
662  */
663 
664  if (LOBYTE(PspBlock->DosVersion) < 5 || getAL() == 0x00)
665  {
666  /*
667  * Return DOS OEM number:
668  * 0x00 for IBM PC-DOS
669  * 0x02 for packaged MS-DOS
670  * 0xFF for NT DOS
671  */
672  setBH(0xFF);
673  }
674 
675  if (LOBYTE(PspBlock->DosVersion) >= 5 && getAL() == 0x01)
676  {
677  /*
678  * Return version flag:
679  * 1 << 3 if DOS is in ROM,
680  * 0 (reserved) if not.
681  */
682  setBH(0x00);
683  }
684 
685  /* Return DOS 24-bit user serial number in BL:CX */
686  setBL(0x00);
687  setCX(0x0000);
688 
689  /*
690  * Return DOS version: Minor:Major in AH:AL
691  * The Windows NT DOS box returns version 5.00, subject to SETVER.
692  */
693  setAX(PspBlock->DosVersion);
694 
695  break;
696  }
697 
698  /* Terminate and Stay Resident */
699  case 0x31:
700  {
701  DPRINT1("Process going resident: %u paragraphs kept\n", getDX());
703  break;
704  }
705 
706  /* Extended functionalities */
707  case 0x33:
708  {
709  switch (getAL())
710  {
711  /*
712  * DOS 4+ - GET BOOT DRIVE
713  */
714  case 0x05:
715  {
717  break;
718  }
719 
720  /*
721  * DOS 5+ - GET TRUE VERSION NUMBER
722  * This function always returns the true version number, unlike
723  * AH=30h, whose return value may be changed with SETVER.
724  * See Ralf Brown: http://www.ctyme.com/intr/rb-2730.htm
725  * for more information.
726  */
727  case 0x06:
728  {
729  /*
730  * Return the true DOS version: Minor:Major in BH:BL
731  * The Windows NT DOS box returns BX=3205h (version 5.50).
732  */
734 
735  /* DOS revision 0 */
736  setDL(0x00);
737 
738  /* Unpatched DOS */
739  setDH(0x00);
740 
741  break;
742  }
743 
744  default: // goto Default;
745  {
746  DPRINT1("INT 21h, AH = %02Xh, subfunction AL = %02Xh NOT IMPLEMENTED\n",
747  getAH(), getAL());
748  }
749  }
750 
751  break;
752  }
753 
754  /* Get Address of InDOS flag */
755  case 0x34:
756  {
759  break;
760  }
761 
762  /* Get Interrupt Vector */
763  case 0x35:
764  {
765  ULONG FarPointer = ((PULONG)BaseAddress)[getAL()];
766 
767  /* Read the address from the IDT into ES:BX */
768  setES(HIWORD(FarPointer));
769  setBX(LOWORD(FarPointer));
770  break;
771  }
772 
773  /* Get Free Disk Space */
774  case 0x36:
775  {
776  CHAR RootPath[] = "?:\\";
777  DWORD SectorsPerCluster;
778  DWORD BytesPerSector;
779  DWORD NumberOfFreeClusters;
780  DWORD TotalNumberOfClusters;
781 
782  if (getDL() == 0x00)
783  RootPath[0] = 'A' + Sda->CurrentDrive;
784  else
785  RootPath[0] = 'A' + getDL() - 1;
786 
787  if (GetDiskFreeSpaceA(RootPath,
788  &SectorsPerCluster,
789  &BytesPerSector,
790  &NumberOfFreeClusters,
791  &TotalNumberOfClusters))
792  {
793  setAX(LOWORD(SectorsPerCluster));
794  setCX(LOWORD(BytesPerSector));
795  setBX(min(NumberOfFreeClusters, 0xFFFF));
796  setDX(min(TotalNumberOfClusters, 0xFFFF));
797  }
798  else
799  {
800  /* Error */
801  setAX(0xFFFF);
802  }
803 
804  break;
805  }
806 
807  /* SWITCH character - AVAILDEV */
808  case 0x37:
809  {
810  switch (getAL())
811  {
812  /*
813  * DOS 2+ - "SWITCHAR" - GET SWITCH CHARACTER
814  * This setting is ignored by MS-DOS 4.0+.
815  * MS-DOS 5+ always return AL=00h/DL=2Fh.
816  * See Ralf Brown: http://www.ctyme.com/intr/rb-2752.htm
817  * for more information.
818  */
819  case 0x00:
820  setDL('/');
821  setAL(0x00);
822  break;
823 
824  /*
825  * DOS 2+ - "SWITCHAR" - SET SWITCH CHARACTER
826  * This setting is ignored by MS-DOS 5+.
827  * See Ralf Brown: http://www.ctyme.com/intr/rb-2753.htm
828  * for more information.
829  */
830  case 0x01:
831  // getDL();
832  setAL(0xFF);
833  break;
834 
835  /*
836  * DOS 2.x and 3.3+ only - "AVAILDEV" - SPECIFY \DEV\ PREFIX USE
837  * See Ralf Brown: http://www.ctyme.com/intr/rb-2754.htm
838  * for more information.
839  */
840  case 0x02:
841  // setDL();
842  setAL(0xFF);
843  break;
844 
845  /*
846  * DOS 2.x and 3.3+ only - "AVAILDEV" - SPECIFY \DEV\ PREFIX USE
847  * See Ralf Brown: http://www.ctyme.com/intr/rb-2754.htm
848  * for more information.
849  */
850  case 0x03:
851  // getDL();
852  setAL(0xFF);
853  break;
854 
855  /* Invalid subfunction */
856  default:
857  setAL(0xFF);
858  break;
859  }
860 
861  break;
862  }
863 
864  /* Get/Set Country-dependent Information */
865  case 0x38:
866  {
867  WORD CountryId = getAL() < 0xFF ? getAL() : getBX();
868  WORD ErrorCode;
869 
870  ErrorCode = DosGetCountryInfo(&CountryId,
872 
873  if (ErrorCode == ERROR_SUCCESS)
874  {
875  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
876  setBX(CountryId);
877  }
878  else
879  {
880  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
881  setAX(ErrorCode);
882  }
883 
884  break;
885  }
886 
887  /* Create Directory */
888  case 0x39:
889  {
891 
893  {
894  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
895  }
896  else
897  {
898  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
900  }
901 
902  break;
903  }
904 
905  /* Remove Directory */
906  case 0x3A:
907  {
909 
911  {
912  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
913  }
914  else
915  {
916  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
918  }
919 
920  break;
921  }
922 
923  /* Set Current Directory */
924  case 0x3B:
925  {
927 
929  {
930  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
931  }
932  else
933  {
934  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
936  }
937 
938  break;
939  }
940 
941  /* Create or Truncate File */
942  case 0x3C:
943  {
948  getCX());
949 
950  if (ErrorCode == ERROR_SUCCESS)
951  {
952  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
953  setAX(FileHandle);
954  }
955  else
956  {
957  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
958  setAX(ErrorCode);
959  }
960 
961  break;
962  }
963 
964  /* Open File or Device */
965  case 0x3D:
966  {
968  BYTE AccessShareModes = getAL();
970  WORD ErrorCode = DosOpenFile(&FileHandle, FileName, AccessShareModes);
971 
972  /*
973  * Check if we failed because we attempted to open a file for write
974  * on a CDROM drive. In that situation, attempt to reopen for read
975  */
977  (AccessShareModes & 0x03) != 0 && DosIsFileOnCdRom())
978  {
980  }
981 
982  if (ErrorCode == ERROR_SUCCESS)
983  {
984  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
985  setAX(FileHandle);
986  }
987  else
988  {
989  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
990  setAX(ErrorCode);
991  }
992 
993  break;
994  }
995 
996  /* Close File or Device */
997  case 0x3E:
998  {
999  if (DosCloseHandle(getBX()))
1000  {
1001  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1002  }
1003  else
1004  {
1005  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1007  }
1008 
1009  break;
1010  }
1011 
1012  /* Read from File or Device */
1013  case 0x3F:
1014  {
1015  WORD BytesRead = 0;
1016  WORD ErrorCode;
1017 
1018  DPRINT("DosReadFile(0x%04X)\n", getBX());
1019 
1021  MAKELONG(getDX(), getDS()),
1022  getCX(),
1023  &BytesRead);
1024 
1025  if (ErrorCode == ERROR_SUCCESS)
1026  {
1027  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1028  setAX(BytesRead);
1029  }
1030  else if (ErrorCode != ERROR_NOT_READY)
1031  {
1032  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1033  setAX(ErrorCode);
1034  }
1035 
1036  break;
1037  }
1038 
1039  /* Write to File or Device */
1040  case 0x40:
1041  {
1042  WORD BytesWritten = 0;
1044  MAKELONG(getDX(), getDS()),
1045  getCX(),
1046  &BytesWritten);
1047 
1048  if (ErrorCode == ERROR_SUCCESS)
1049  {
1050  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1052  }
1053  else
1054  {
1055  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1056  setAX(ErrorCode);
1057  }
1058 
1059  break;
1060  }
1061 
1062  /* Delete File */
1063  case 0x41:
1064  {
1066 
1068  {
1069  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1070  /*
1071  * See Ralf Brown: http://www.ctyme.com/intr/rb-2797.htm
1072  * "AX destroyed (DOS 3.3) AL seems to be drive of deleted file."
1073  */
1074  setAL(RtlUpperChar(FileName[0]) - 'A');
1075  }
1076  else
1077  {
1078  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1079  setAX(GetLastError());
1080  }
1081 
1082  break;
1083  }
1084 
1085  /* Seek File */
1086  case 0x42:
1087  {
1088  DWORD NewLocation;
1090  MAKELONG(getDX(), getCX()),
1091  getAL(),
1092  &NewLocation);
1093 
1094  if (ErrorCode == ERROR_SUCCESS)
1095  {
1096  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1097 
1098  /* Return the new offset in DX:AX */
1099  setDX(HIWORD(NewLocation));
1100  setAX(LOWORD(NewLocation));
1101  }
1102  else
1103  {
1104  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1105  setAX(ErrorCode);
1106  }
1107 
1108  break;
1109  }
1110 
1111  /* Get/Set File Attributes */
1112  case 0x43:
1113  {
1114  DWORD Attributes;
1116 
1117  if (getAL() == 0x00)
1118  {
1119  /* Get the attributes */
1121 
1122  /* Check if it failed */
1124  {
1125  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1126  setAX(GetLastError());
1127  }
1128  else
1129  {
1130  /* Return the attributes that DOS can understand */
1131  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1132  setCX(Attributes & 0x00FF);
1133  }
1134  }
1135  else if (getAL() == 0x01)
1136  {
1137  /* Try to set the attributes */
1139  {
1140  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1141  }
1142  else
1143  {
1144  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1145  setAX(GetLastError());
1146  }
1147  }
1148  else
1149  {
1150  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1152  }
1153 
1154  break;
1155  }
1156 
1157  /* IOCTL */
1158  case 0x44:
1159  {
1160  WORD Length = getCX();
1161 
1163  {
1164  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1165  setAX(Length);
1166  }
1167  else
1168  {
1169  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1171  }
1172 
1173  break;
1174  }
1175 
1176  /* Duplicate Handle */
1177  case 0x45:
1178  {
1179  WORD NewHandle = DosDuplicateHandle(getBX());
1180 
1181  if (NewHandle != INVALID_DOS_HANDLE)
1182  {
1183  setAX(NewHandle);
1184  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1185  }
1186  else
1187  {
1188  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1190  }
1191 
1192  break;
1193  }
1194 
1195  /* Force Duplicate Handle */
1196  case 0x46:
1197  {
1199  {
1200  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1201  }
1202  else
1203  {
1204  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1206  }
1207 
1208  break;
1209  }
1210 
1211  /* Get Current Directory */
1212  case 0x47:
1213  {
1214  BYTE DriveNumber = getDL();
1216 
1217  /* Get the real drive number */
1218  if (DriveNumber == 0)
1219  {
1220  DriveNumber = Sda->CurrentDrive;
1221  }
1222  else
1223  {
1224  /* Decrement DriveNumber since it was 1-based */
1225  DriveNumber--;
1226  }
1227 
1228  if (DriveNumber < SysVars->NumLocalDrives)
1229  {
1230  /*
1231  * Copy the current directory into the target buffer.
1232  * It doesn't contain the drive letter and the backslash.
1233  */
1235  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1236  setAX(0x0100); // Undocumented, see Ralf Brown: http://www.ctyme.com/intr/rb-2933.htm
1237  }
1238  else
1239  {
1240  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1242  }
1243 
1244  break;
1245  }
1246 
1247  /* Allocate Memory */
1248  case 0x48:
1249  {
1250  WORD MaxAvailable = 0;
1251  WORD Segment = DosAllocateMemory(getBX(), &MaxAvailable);
1252 
1253  if (Segment != 0)
1254  {
1255  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1256  setAX(Segment);
1257  }
1258  else
1259  {
1260  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1262  setBX(MaxAvailable);
1263  }
1264 
1265  break;
1266  }
1267 
1268  /* Free Memory */
1269  case 0x49:
1270  {
1271  if (DosFreeMemory(getES()))
1272  {
1273  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1274  }
1275  else
1276  {
1277  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1279  }
1280 
1281  break;
1282  }
1283 
1284  /* Resize Memory Block */
1285  case 0x4A:
1286  {
1287  WORD Size;
1288 
1289  if (DosResizeMemory(getES(), getBX(), &Size))
1290  {
1291  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1292  }
1293  else
1294  {
1295  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1297  setBX(Size);
1298  }
1299 
1300  break;
1301  }
1302 
1303  /* Execute */
1304  case 0x4B:
1305  {
1306  BYTE OrgAL = getAL();
1307  LPSTR ProgramName = SEG_OFF_TO_PTR(getDS(), getDX());
1308  PDOS_EXEC_PARAM_BLOCK ParamBlock = SEG_OFF_TO_PTR(getES(), getBX());
1309  WORD ErrorCode;
1310 
1311  if (OrgAL <= DOS_LOAD_OVERLAY)
1312  {
1313  DOS_EXEC_TYPE LoadType = (DOS_EXEC_TYPE)OrgAL;
1314 
1315  if (LoadType == DOS_LOAD_AND_EXECUTE)
1316  {
1317  /* Create a new process */
1318  ErrorCode = DosCreateProcess(ProgramName,
1319  ParamBlock,
1320  MAKELONG(Stack[STACK_IP], Stack[STACK_CS]));
1321  }
1322  else
1323  {
1324  /* Just load an executable */
1325  ErrorCode = DosLoadExecutable(LoadType,
1326  ProgramName,
1327  ParamBlock,
1328  NULL,
1329  NULL,
1330  MAKELONG(Stack[STACK_IP], Stack[STACK_CS]));
1331  }
1332  }
1333  else if (OrgAL == 0x05)
1334  {
1335  // http://www.ctyme.com/intr/rb-2942.htm
1336  DPRINT1("Set execution state is UNIMPLEMENTED\n");
1338  }
1339  else
1340  {
1342  }
1343 
1344  if (ErrorCode == ERROR_SUCCESS)
1345  {
1346  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1347  }
1348  else
1349  {
1350  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1351  setAX(ErrorCode);
1352  }
1353 
1354  break;
1355  }
1356 
1357  /* Terminate with Return Code */
1358  case 0x4C:
1359  {
1361  break;
1362  }
1363 
1364  /* Get Return Code (ERRORLEVEL) */
1365  case 0x4D:
1366  {
1367  /*
1368  * According to Ralf Brown: http://www.ctyme.com/intr/rb-2976.htm
1369  * DosErrorLevel is cleared after being read by this function.
1370  */
1371  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1372  setAX(Sda->ErrorLevel);
1373  Sda->ErrorLevel = 0x0000; // Clear it
1374  break;
1375  }
1376 
1377  /* Find First File */
1378  case 0x4E:
1379  {
1381  SEG_OFF_TO_PTR(getDS(), getDX()),
1382  getCX());
1383 
1384  setAX(Result);
1385 
1386  if (Result == ERROR_SUCCESS)
1387  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1388  else
1389  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1390 
1391  break;
1392  }
1393 
1394  /* Find Next File */
1395  case 0x4F:
1396  {
1398 
1399  setAX(Result);
1400 
1401  if (Result == ERROR_SUCCESS)
1402  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1403  else
1404  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1405 
1406  break;
1407  }
1408 
1409  /* Internal - Set Current Process ID (Set PSP Address) */
1410  case 0x50:
1411  {
1413  break;
1414  }
1415 
1416  /* Internal - Get Current Process ID (Get PSP Address) */
1417  case 0x51:
1418  /* Get Current PSP Address */
1419  case 0x62:
1420  {
1421  /*
1422  * Undocumented AH=51h is identical to the documented AH=62h.
1423  * See Ralf Brown: http://www.ctyme.com/intr/rb-2982.htm
1424  * and http://www.ctyme.com/intr/rb-3140.htm
1425  * for more information.
1426  */
1427  setBX(Sda->CurrentPsp);
1428  break;
1429  }
1430 
1431  /* Internal - Get "List of lists" (SYSVARS) */
1432  case 0x52:
1433  {
1434  /*
1435  * On return, ES points at the DOS data segment (see also INT 2F/AX=1203h).
1436  * See Ralf Brown: http://www.ctyme.com/intr/rb-2983.htm
1437  * for more information.
1438  */
1439 
1440  /* Return the DOS "list of lists" in ES:BX */
1443  break;
1444  }
1445 
1446  /* Create Child PSP */
1447  case 0x55:
1448  {
1449  DosCreatePsp(getDX(), getSI());
1451  break;
1452  }
1453 
1454  /* Rename File */
1455  case 0x56:
1456  {
1457  LPSTR ExistingFileName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX());
1458  LPSTR NewFileName = (LPSTR)SEG_OFF_TO_PTR(getES(), getDI());
1459 
1460  /*
1461  * See Ralf Brown: http://www.ctyme.com/intr/rb-2990.htm
1462  * for more information.
1463  */
1464 
1465  if (MoveFileA(ExistingFileName, NewFileName))
1466  {
1467  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1468  }
1469  else
1470  {
1471  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1472  setAX(GetLastError());
1473  }
1474 
1475  break;
1476  }
1477 
1478  /* File Attributes */
1479  case 0x57:
1480  {
1481  switch (getAL())
1482  {
1483  /* Get File's last-written Date and Time */
1484  case 0x00:
1485  {
1487  FILETIME LastWriteTime;
1488  WORD FileDate, FileTime;
1489 
1490  if (Descriptor == NULL)
1491  {
1492  /* Invalid handle */
1493  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1494  // Sda->LastErrorCode = ERROR_INVALID_HANDLE;
1496  break;
1497  }
1498 
1499  if (Descriptor->DeviceInfo & FILE_INFO_DEVICE)
1500  {
1501  /* Invalid for devices */
1502  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1503  // setAX(ERROR_INVALID_FUNCTION);
1505  break;
1506  }
1507 
1508  /*
1509  * Retrieve the last-written Win32 date and time,
1510  * and convert it to DOS format.
1511  */
1512  if (!GetFileTime(Descriptor->Win32Handle,
1513  NULL, NULL, &LastWriteTime) ||
1514  !FileTimeToDosDateTime(&LastWriteTime,
1515  &FileDate, &FileTime))
1516  {
1517  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1518  setAX(GetLastError());
1519  break;
1520  }
1521 
1522  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1523  setCX(FileTime);
1524  setDX(FileDate);
1525  break;
1526  }
1527 
1528  /* Set File's last-written Date and Time */
1529  case 0x01:
1530  {
1532  FILETIME LastWriteTime;
1533  WORD FileDate = getDX();
1534  WORD FileTime = getCX();
1535 
1536  if (Descriptor == NULL)
1537  {
1538  /* Invalid handle */
1539  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1540  // Sda->LastErrorCode = ERROR_INVALID_HANDLE;
1542  break;
1543  }
1544 
1545  if (Descriptor->DeviceInfo & FILE_INFO_DEVICE)
1546  {
1547  /* Invalid for devices */
1548  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1549  // setAX(ERROR_INVALID_FUNCTION);
1551  break;
1552  }
1553 
1554  /*
1555  * Convert the new last-written DOS date and time
1556  * to Win32 format and set it.
1557  */
1558  if (!DosDateTimeToFileTime(FileDate, FileTime,
1559  &LastWriteTime) ||
1560  !SetFileTime(Descriptor->Win32Handle,
1561  NULL, NULL, &LastWriteTime))
1562  {
1563  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1564  setAX(GetLastError());
1565  break;
1566  }
1567 
1568  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1569  break;
1570  }
1571 
1572  default: // goto Default;
1573  {
1574  DPRINT1("INT 21h, AH = %02Xh, subfunction AL = %02Xh NOT IMPLEMENTED\n",
1575  getAH(), getAL());
1576  }
1577  }
1578 
1579  break;
1580  }
1581 
1582  /* Get/Set Memory Management Options */
1583  case 0x58:
1584  {
1585  switch (getAL())
1586  {
1587  /* Get allocation strategy */
1588  case 0x00:
1589  {
1590  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1592  break;
1593  }
1594 
1595  /* Set allocation strategy */
1596  case 0x01:
1597  {
1600  {
1601  /* Can't set both */
1602  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1604  break;
1605  }
1606 
1607  if ((getBL() & ~(DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW))
1609  {
1610  /* Invalid allocation strategy */
1611  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1613  break;
1614  }
1615 
1616  Sda->AllocStrategy = getBL();
1617  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1618  break;
1619  }
1620 
1621  /* Get UMB link state */
1622  case 0x02:
1623  {
1624  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1625  setAL(SysVars->UmbLinked ? 0x01 : 0x00);
1626  break;
1627  }
1628 
1629  /* Set UMB link state */
1630  case 0x03:
1631  {
1632  BOOLEAN Success;
1633 
1634  if (getBX())
1635  Success = DosLinkUmb();
1636  else
1637  Success = DosUnlinkUmb();
1638 
1639  if (Success)
1640  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1641  else
1642  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1643 
1644  break;
1645  }
1646 
1647  /* Invalid or unsupported function */
1648  default:
1649  {
1650  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1652  }
1653  }
1654 
1655  break;
1656  }
1657 
1658  /* Get Extended Error Information */
1659  case 0x59:
1660  {
1661  DPRINT1("INT 21h, AH = 59h, BX = %04Xh - Get Extended Error Information is UNIMPLEMENTED\n",
1662  getBX());
1663  break;
1664  }
1665 
1666  /* Create Temporary File */
1667  case 0x5A:
1668  {
1669  LPSTR PathName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX());
1670  LPSTR FileName = PathName; // The buffer for the path and the full file name is the same.
1671  UINT uRetVal;
1672  WORD FileHandle;
1673  WORD ErrorCode;
1674 
1675  /*
1676  * See Ralf Brown: http://www.ctyme.com/intr/rb-3014.htm
1677  * for more information.
1678  */
1679 
1680  // FIXME: Check for buffer validity?
1681  // It should be a ASCIIZ path ending with a '\' + 13 zero bytes
1682  // to receive the generated filename.
1683 
1684  /* First create the temporary file */
1685  uRetVal = GetTempFileNameA(PathName, NULL, 0, FileName);
1686  if (uRetVal == 0)
1687  {
1688  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1689  setAX(GetLastError());
1690  break;
1691  }
1692 
1693  /* Now try to open it in read/write access */
1695  if (ErrorCode == ERROR_SUCCESS)
1696  {
1697  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1698  setAX(FileHandle);
1699  }
1700  else
1701  {
1702  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1703  setAX(ErrorCode);
1704  }
1705 
1706  break;
1707  }
1708 
1709  /* Create New File */
1710  case 0x5B:
1711  {
1712  WORD FileHandle;
1715  CREATE_NEW,
1716  getCX());
1717 
1718  if (ErrorCode == ERROR_SUCCESS)
1719  {
1720  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1721  setAX(FileHandle);
1722  }
1723  else
1724  {
1725  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1726  setAX(ErrorCode);
1727  }
1728 
1729  break;
1730  }
1731 
1732  /* Lock/Unlock Region of File */
1733  case 0x5C:
1734  {
1735  if (getAL() == 0x00)
1736  {
1737  /* Lock region of file */
1738  if (DosLockFile(getBX(), MAKELONG(getDX(), getCX()), MAKELONG(getDI(), getSI())))
1739  {
1740  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1741  }
1742  else
1743  {
1744  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1746  }
1747  }
1748  else if (getAL() == 0x01)
1749  {
1750  /* Unlock region of file */
1751  if (DosUnlockFile(getBX(), MAKELONG(getDX(), getCX()), MAKELONG(getDI(), getSI())))
1752  {
1753  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1754  }
1755  else
1756  {
1757  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1759  }
1760  }
1761  else
1762  {
1763  /* Invalid subfunction */
1764  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1766  }
1767 
1768  break;
1769  }
1770 
1771  /* Canonicalize File Name or Path */
1772  case 0x60:
1773  {
1774  /*
1775  * See Ralf Brown: http://www.ctyme.com/intr/rb-3137.htm
1776  * for more information.
1777  */
1778 
1779  /*
1780  * We suppose that the DOS app gave to us a valid
1781  * 128-byte long buffer for the canonicalized name.
1782  */
1783  DWORD dwRetVal = GetFullPathNameA(SEG_OFF_TO_PTR(getDS(), getSI()),
1784  128,
1785  SEG_OFF_TO_PTR(getES(), getDI()),
1786  NULL);
1787  if (dwRetVal == 0)
1788  {
1789  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1790  setAX(GetLastError());
1791  }
1792  else
1793  {
1794  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1795  setAX(0x0000);
1796  }
1797 
1798  // FIXME: Convert the full path name into short version.
1799  // We cannot reliably use GetShortPathName, because it fails
1800  // if the path name given doesn't exist. However this DOS
1801  // function AH=60h should be able to work even for non-existing
1802  // path and file names.
1803 
1804  break;
1805  }
1806 
1807  /* Miscellaneous Internal Functions */
1808  case 0x5D:
1809  {
1810  switch (getAL())
1811  {
1812  /* Get Swappable Data Area */
1813  case 0x06:
1814  {
1817  setCX(sizeof(DOS_SDA));
1818  setDX(FIELD_OFFSET(DOS_SDA, LastAX));
1819 
1820  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1821  break;
1822  }
1823 
1824  default: // goto Default;
1825  {
1826  DPRINT1("INT 21h, AH = %02Xh, subfunction AL = %02Xh NOT IMPLEMENTED\n",
1827  getAH(), getAL());
1828  }
1829  }
1830 
1831  break;
1832  }
1833 
1834  /* Extended Country Information */
1835  case 0x65:
1836  {
1837  switch (getAL())
1838  {
1839  case 0x01: case 0x02: case 0x03:
1840  case 0x04: case 0x05: case 0x06:
1841  case 0x07:
1842  {
1843  WORD BufferSize = getCX();
1844  WORD ErrorCode;
1846  getBX(),
1847  getDX(),
1849  &BufferSize);
1850  if (ErrorCode == ERROR_SUCCESS)
1851  {
1852  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1853  setCX(BufferSize);
1854  }
1855  else
1856  {
1857  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1858  setAX(ErrorCode);
1859  }
1860 
1861  break;
1862  }
1863 
1864  /* Country-dependent Character Capitalization -- Character */
1865  case 0x20:
1866  /* Country-dependent Filename Capitalization -- Character */
1867  case 0xA0:
1868  {
1869  setDL(DosToUpper(getDL()));
1870  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1871  // setAX(ERROR_SUCCESS);
1872  break;
1873  }
1874 
1875  /* Country-dependent Character Capitalization -- Counted ASCII String */
1876  case 0x21:
1877  /* Country-dependent Filename Capitalization -- Counted ASCII String */
1878  case 0xA1:
1879  {
1880  PCHAR Str = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX());
1881  // FIXME: Check for NULL ptr!!
1882  DosToUpperStrN(Str, Str, getCX());
1883  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1884  // setAX(ERROR_SUCCESS);
1885  break;
1886  }
1887 
1888  /* Country-dependent Character Capitalization -- ASCIIZ String */
1889  case 0x22:
1890  /* Country-dependent Filename Capitalization -- ASCIIZ String */
1891  case 0xA2:
1892  {
1893  PSTR Str = (PSTR)SEG_OFF_TO_PTR(getDS(), getDX());
1894  // FIXME: Check for NULL ptr!!
1895  DosToUpperStrZ(Str, Str);
1896  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1897  // setAX(ERROR_SUCCESS);
1898  break;
1899  }
1900 
1901  /* Determine if Character represents YES/NO Response */
1902  case 0x23:
1903  {
1905  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1906  break;
1907  }
1908 
1909  default: // goto Default;
1910  {
1911  DPRINT1("INT 21h, AH = %02Xh, subfunction AL = %02Xh NOT IMPLEMENTED\n",
1912  getAH(), getAL());
1913  }
1914  }
1915 
1916  break;
1917  }
1918 
1919  /* Set Handle Count */
1920  case 0x67:
1921  {
1922  if (!DosResizeHandleTable(getBX()))
1923  {
1924  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1926  }
1927  else Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1928 
1929  break;
1930  }
1931 
1932  /* Commit File */
1933  case 0x68:
1934  case 0x6A:
1935  {
1936  /*
1937  * Function 6Ah is identical to function 68h,
1938  * and sets AH to 68h if success.
1939  * See Ralf Brown: http://www.ctyme.com/intr/rb-3176.htm
1940  * for more information.
1941  */
1942  setAH(0x68);
1943 
1944  if (DosFlushFileBuffers(getBX()))
1945  {
1946  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1947  }
1948  else
1949  {
1950  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1951  setAX(GetLastError());
1952  }
1953 
1954  break;
1955  }
1956 
1957  /* Extended Open/Create */
1958  case 0x6C:
1959  {
1960  WORD FileHandle;
1961  WORD CreationStatus;
1962  WORD ErrorCode;
1963 
1964  /* Check for AL == 00 */
1965  if (getAL() != 0x00)
1966  {
1967  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1969  break;
1970  }
1971 
1972  /*
1973  * See Ralf Brown: http://www.ctyme.com/intr/rb-3179.htm
1974  * for the full detailed description.
1975  *
1976  * WARNING: BH contains some extended flags that are NOT SUPPORTED.
1977  */
1978 
1980  &CreationStatus,
1982  getBL(),
1983  getDL(),
1984  getCX());
1985 
1986  if (ErrorCode == ERROR_SUCCESS)
1987  {
1988  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
1989  setCX(CreationStatus);
1990  setAX(FileHandle);
1991  }
1992  else
1993  {
1994  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
1995  setAX(ErrorCode);
1996  }
1997 
1998  break;
1999  }
2000 
2001  /* Unsupported */
2002  default: // Default:
2003  {
2004  DPRINT1("DOS Function INT 21h, AH = %02Xh, AL = %02Xh NOT IMPLEMENTED!\n",
2005  getAH(), getAL());
2006 
2007  setAL(0); // Some functions expect AL to be 0 when it's not supported.
2008  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
2009  }
2010  }
2011 
2012  Sda->InDos--;
2013 }
WORD LastErrorCode
Definition: dos.h:151
signed char * PCHAR
Definition: retypes.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define DOS_DATA_OFFSET(x)
Definition: dos.h:35
BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable)
Definition: memory.c:289
WORD DosDuplicateHandle(WORD DosHandle)
Definition: handle.c:256
#define DOS_OUTPUT_HANDLE
Definition: dos.h:43
USHORT WINAPI getBX(VOID)
Definition: registers.c:170
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ FLT_IO_OPERATION_FLAGS _Out_opt_ PULONG BytesWritten
Definition: fltkernel.h:1293
#define DOS_DIR_LENGTH
Definition: dos.h:47
WORD CurrentPsp
Definition: dos.h:156
#define TRUE
Definition: types.h:120
#define INVALID_DOS_HANDLE
Definition: dos.h:41
BOOLEAN DosLinkUmb(VOID)
Definition: memory.c:446
WORD DosCreateProcess(IN LPCSTR ProgramName, IN PDOS_EXEC_PARAM_BLOCK Parameters, IN DWORD ReturnAddress OPTIONAL)
Definition: process.c:783
#define DOS_INPUT_HANDLE
Definition: dos.h:42
#define DOS_ALLOC_HIGH
Definition: memory.h:17
VOID WINAPI setBL(UCHAR)
Definition: registers.c:205
VOID DosToUpperStrZ(PSTR DestStr, PSTR SrcStr)
Definition: country.c:230
WORD DosReadFile(WORD FileHandle, DWORD Buffer, WORD Count, LPWORD BytesRead)
Definition: dosfiles.c:768
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
UCHAR WINAPI getCL(VOID)
Definition: registers.c:256
BOOL DosFlushFileBuffers(WORD FileHandle)
Definition: dosfiles.c:1056
#define ERROR_SUCCESS
Definition: deptool.c:10
USHORT WINAPI getSI(VOID)
Definition: registers.c:404
VOID DosToUpperStrN(PCHAR DestStr, PCHAR SrcStr, WORD Length)
Definition: country.c:224
BYTE ErrorMode
Definition: dos.h:147
#define LOBYTE(W)
Definition: jmemdos.c:487
WORD wMonth
Definition: winbase.h:878
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
USHORT WINAPI getCX(VOID)
Definition: registers.c:228
#define MAKEWORD(a, b)
Definition: typedefs.h:247
DOS_EXEC_TYPE
Definition: process.h:18
VOID WINAPI setAH(UCHAR)
Definition: registers.c:135
BYTE InDos
Definition: dos.h:148
static BOOLEAN DosChangeDirectory(LPSTR Directory)
Definition: dos.c:78
CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH]
Definition: dos.h:248
WORD wDayOfWeek
Definition: winbase.h:879
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
VOID WINAPI setAX(USHORT)
Definition: registers.c:121
char CHAR
Definition: xmlstorage.h:175
VOID WINAPI setDS(USHORT)
Definition: registers.c:515
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
BOOLEAN DosFreeMemory(WORD BlockData)
Definition: memory.c:418
VOID WINAPI DosInt21h(LPWORD Stack)
Definition: dos.c:210
BOOL WINAPI MoveFileA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName)
Definition: move.c:1077
VOID WINAPI setAL(UCHAR)
Definition: registers.c:149
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
UCHAR WINAPI getAH(VOID)
Definition: registers.c:128
static WCHAR String[]
Definition: stringtable.c:55
UCHAR WINAPI getAL(VOID)
Definition: registers.c:142
char * LPSTR
Definition: xmlstorage.h:182
UCHAR WINAPI getDH(VOID)
Definition: registers.c:300
DWORD WINAPI demFileFindNext(OUT PVOID lpFindFileData)
Definition: dem.c:1465
enum OPTION_FLAGS Options
Definition: stats.c:44
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
UCHAR WINAPI getDL(VOID)
Definition: registers.c:314
CHAR InputBuffer[80]
Definition: conmgr.c:33
PDOS_DATA DosData
Definition: dos.c:45
BOOL WINAPI SetFileTime(IN HANDLE hFile, CONST FILETIME *lpCreationTime OPTIONAL, CONST FILETIME *lpLastAccessTime OPTIONAL, CONST FILETIME *lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:1098
#define EMULATOR_FLAG_CF
Definition: cpu.h:19
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:992
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
VOID WINAPI setES(USHORT)
Definition: registers.c:529
HANDLE FileHandle
Definition: stats.c:38
WORD wYear
Definition: winbase.h:877
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BYTE CurrentDrive
Definition: dos.h:159
BOOLEAN DosCheckInput(VOID)
Definition: bios.c:120
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
#define EMULATOR_FLAG_ZF
Definition: cpu.h:22
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:786
VOID DosPrintCharacter(WORD FileHandle, CHAR Character)
Definition: bios.c:152
VOID WINAPI setSI(USHORT)
Definition: registers.c:411
static BOOLEAN DosChangeDrive(BYTE Drive)
Definition: dos.c:52
WORD wMinute
Definition: winbase.h:882
#define MAKELONG(a, b)
Definition: typedefs.h:248
unsigned char BOOLEAN
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
smooth NULL
Definition: ftsmooth.c:416
DWORD WINAPI demFileFindFirst(OUT PVOID lpFindFileData, IN LPCSTR FileName, IN WORD AttribMask)
Definition: dem.c:1411
#define ERROR_NOT_READY
Definition: winerror.h:124
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable)
Definition: memory.c:136
void DPRINT(...)
Definition: polytest.cpp:61
BOOL WINAPI SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:926
Definition: bufpool.h:45
#define FAR_POINTER(x)
Definition: emulator.h:31
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:286
#define STACK_FLAGS
Definition: int32.h:35
VOID DosSetProcessContext(WORD Segment)
Definition: process.c:321
const char * LPCSTR
Definition: xmlstorage.h:183
CHAR DosToUpper(CHAR Char)
Definition: country.c:218
BOOLEAN DosControlBreak(VOID)
Definition: dos.c:181
PDOS_FILE_DESCRIPTOR DosGetHandleFileDescriptor(WORD DosHandle)
Definition: dosfiles.c:173
struct _DOS_INPUT_BUFFER * PDOS_INPUT_BUFFER
_Inout_ PVOID Segment
Definition: exfuncs.h:893
BOOLEAN DosResizeHandleTable(WORD NewSize)
Definition: handle.c:118
#define PCHAR
Definition: match.c:90
#define DOS_DATA_SEGMENT
Definition: dos.h:33
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
Definition: dos.h:53
WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset)
Definition: dosfiles.c:1001
#define FILE_INFO_DEVICE
Definition: dosfiles.h:16
BOOL WINAPI DosDateTimeToFileTime(IN WORD wFatDate, IN WORD wFatTime, OUT LPFILETIME lpFileTime)
Definition: time.c:75
struct _DOS_FCB * PDOS_FCB
USHORT WINAPI getES(VOID)
Definition: registers.c:522
BOOLEAN DosUnlinkUmb(VOID)
Definition: memory.c:492
#define BufferSize
Definition: classpnp.h:419
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
WORD wSecond
Definition: winbase.h:883
NTSYSAPI CHAR NTAPI RtlUpperChar(CHAR Character)
VOID WINAPI setDX(USHORT)
Definition: registers.c:293
WORD wMilliseconds
Definition: winbase.h:884
#define DOS_ALLOC_HIGH_LOW
Definition: memory.h:18
VOID DosCreatePsp(WORD Segment, WORD ProgramSize)
Definition: process.c:270
WORD DosGetCountryInfo(IN OUT PWORD CountryId, OUT PDOS_COUNTRY_INFO CountryInfo)
Definition: country.c:77
CHAR DosReadCharacter(WORD FileHandle, BOOLEAN Echo)
Definition: bios.c:85
static BOOLEAN DosIsFileOnCdRom(VOID)
Definition: dos.c:164
#define ERROR_INVALID_DRIVE
Definition: winerror.h:118
USHORT WINAPI getDX(VOID)
Definition: registers.c:286
unsigned char BYTE
Definition: mem.h:68
VOID DosClonePsp(WORD DestSegment, WORD SourceSegment)
Definition: process.c:243
PDOS_SDA Sda
Definition: dos.c:48
WORD DosGetCountryInfoEx(IN BYTE InfoId, IN WORD CodePage, IN WORD CountryId, OUT PDOS_COUNTRY_INFO_2 CountryInfo, IN OUT PWORD BufferSize)
Definition: country.c:141
#define STACK_CS
Definition: int32.h:34
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define NTDOS_VERSION
Definition: dos.h:25
BYTE UmbLinked
Definition: dos.h:100
VOID WINAPI setBX(USHORT)
Definition: registers.c:177
WORD ErrorLevel
Definition: dos.h:158
VOID WINAPI setBH(UCHAR)
Definition: registers.c:191
BYTE NumLocalDrives
Definition: dos.h:88
WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessShareModes)
Definition: dosfiles.c:521
WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, DWORD CreationDisposition, WORD Attributes)
Definition: dosfiles.c:442
DWORD DiskTransferArea
Definition: dos.h:155
BOOLEAN DosLockFile(WORD DosHandle, DWORD Offset, DWORD Size)
Definition: dosfiles.c:1082
WORD wDay
Definition: winbase.h:880
BOOL WINAPI FileTimeToDosDateTime(IN CONST FILETIME *lpFileTime, OUT LPWORD lpFatDate, OUT LPWORD lpFatTime)
Definition: time.c:37
VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode, WORD KeepResident)
Definition: process.c:873
BOOLEAN DosDeviceIoControl(WORD FileHandle, BYTE ControlCode, DWORD Buffer, PWORD Length)
Definition: dosfiles.c:1185
#define CREATE_ALWAYS
Definition: disk.h:72
WORD DosCreateFileEx(LPWORD Handle, LPWORD CreationStatus, LPCSTR FilePath, BYTE AccessShareModes, WORD CreateActionFlags, WORD Attributes)
Definition: dosfiles.c:181
_Must_inspect_result_ _In_ USHORT _In_ PHIDP_PREPARSED_DATA _Out_writes_to_ LengthAttributes PHIDP_EXTENDED_ATTRIBUTES Attributes
Definition: hidpi.h:348
UCHAR WINAPI getBL(VOID)
Definition: registers.c:198
USHORT WINAPI getDI(VOID)
Definition: registers.c:434
VOID WINAPI setDL(UCHAR)
Definition: registers.c:321
PDOS_SYSVARS SysVars
Definition: dos.c:47
signed char * PSTR
Definition: retypes.h:7
WORD wHour
Definition: winbase.h:881
BOOL WINAPI RemoveDirectoryA(IN LPCSTR lpPathName)
Definition: dir.c:714
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
BYTE DosReadLineBuffered(WORD FileHandle, DWORD Buffer, BYTE MaxSize)
Definition: dosfiles.c:674
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
VOID WINAPI setCX(USHORT)
Definition: registers.c:235
DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType, IN LPCSTR ExecutablePath, IN PDOS_EXEC_PARAM_BLOCK Parameters, IN LPCSTR CommandLine OPTIONAL, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL)
Definition: process.c:695
#define DPRINT1
Definition: precomp.h:8
UCHAR WINAPI getCH(VOID)
Definition: registers.c:242
WORD DosWriteFile(WORD FileHandle, DWORD Buffer, WORD Count, LPWORD BytesWritten)
Definition: dosfiles.c:915
DWORD WINAPI demFileDelete(IN LPCSTR FileName)
Definition: dem.c:1402
USHORT WINAPI getDS(VOID)
Definition: registers.c:508
BYTE BootDrive
Definition: dos.h:96
WORD DosVersion
Definition: process.h:43
#define HIWORD(l)
Definition: typedefs.h:246
unsigned int ULONG
Definition: retypes.h:1
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:92
BOOL WINAPI GetDiskFreeSpaceA(IN LPCSTR lpRootPathName, OUT LPDWORD lpSectorsPerCluster, OUT LPDWORD lpBytesPerSector, OUT LPDWORD lpNumberOfFreeClusters, OUT LPDWORD lpTotalNumberOfClusters)
Definition: disk.c:142
#define CREATE_NEW
Definition: disk.h:69
BOOLEAN DosForceDuplicateHandle(WORD OldHandle, WORD NewHandle)
Definition: handle.c:269
USHORT WINAPI getSP(VOID)
Definition: registers.c:344
BYTE AllocStrategy
Definition: dos.h:143
_In_ PFCB Fcb
Definition: cdprocs.h:151
Definition: dos.h:139
BOOLEAN DosCloseHandle(WORD DosHandle)
Definition: handle.c:311
BOOL WINAPI SetLocalTime(IN CONST SYSTEMTIME *lpSystemTime)
Definition: time.c:356
#define STACK_IP
Definition: int32.h:33
WORD DosIfCharYesNo(WORD Char)
Definition: country.c:204
#define LOWORD(l)
Definition: pedump.c:82
BOOL WINAPI GetFileTime(IN HANDLE hFile, OUT LPFILETIME lpCreationTime OPTIONAL, OUT LPFILETIME lpLastAccessTime OPTIONAL, OUT LPFILETIME lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:1046
UINT WINAPI GetTempFileNameA(IN LPCSTR lpPathName, IN LPCSTR lpPrefixString, IN UINT uUnique, OUT LPSTR lpTempFileName)
Definition: filename.c:26
BOOLEAN DosUnlockFile(WORD DosHandle, DWORD Offset, DWORD Size)
Definition: dosfiles.c:1105
DWORD FirstDpb
Definition: dos.h:80
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ FLT_IO_OPERATION_FLAGS _Out_opt_ PULONG BytesRead
Definition: fltkernel.h:1255
VOID WINAPI setDH(UCHAR)
Definition: registers.c:307
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966

Referenced by DosKRNLInitialize().

◆ DosInt27h()

VOID WINAPI DosInt27h ( LPWORD  Stack)

Definition at line 2061 of file dos.c.

2062 {
2063  WORD KeepResident = (getDX() + 0x0F) >> 4;
2064 
2065  /* Terminate and Stay Resident. CS must be the PSP segment. */
2066  DPRINT1("Process going resident: %u paragraphs kept\n", KeepResident);
2067  DosTerminateProcess(Stack[STACK_CS], 0, KeepResident);
2068 }
unsigned short WORD
Definition: ntddk_ex.h:93
USHORT WINAPI getDX(VOID)
Definition: registers.c:286
#define STACK_CS
Definition: int32.h:34
VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode, WORD KeepResident)
Definition: process.c:873
#define DPRINT1
Definition: precomp.h:8

Referenced by DosKRNLInitialize().

◆ DosInt2Ah()

VOID WINAPI DosInt2Ah ( LPWORD  Stack)

Definition at line 2111 of file dos.c.

2112 {
2113  DPRINT1("INT 2Ah, AX=%4xh called\n", getAX());
2114 }
USHORT WINAPI getAX(VOID)
Definition: registers.c:114
#define DPRINT1
Definition: precomp.h:8

Referenced by DosKRNLInitialize().

◆ DosInt2Fh()

VOID WINAPI DosInt2Fh ( LPWORD  Stack)

Definition at line 2116 of file dos.c.

2117 {
2118  switch (getAH())
2119  {
2120  /* DOS 3+ Internal Utility Functions */
2121  case 0x12:
2122  {
2123  DPRINT1("INT 2Fh, AX=%4xh DOS Internal Utility Function called\n", getAX());
2124 
2125  switch (getAL())
2126  {
2127  /* Installation Check */
2128  case 0x00:
2129  {
2130  setAL(0xFF);
2131  break;
2132  }
2133 
2134  /* Get DOS Data Segment */
2135  case 0x03:
2136  {
2138  break;
2139  }
2140 
2141  /* Compare FAR Pointers */
2142  case 0x14:
2143  {
2144  PVOID PointerFromFarPointer1 = SEG_OFF_TO_PTR(getDS(), getSI());
2145  PVOID PointerFromFarPointer2 = SEG_OFF_TO_PTR(getES(), getDI());
2146  BOOLEAN AreEqual = (PointerFromFarPointer1 == PointerFromFarPointer2);
2147 
2148  if (AreEqual)
2149  {
2150  Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF;
2151  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
2152  }
2153  else
2154  {
2155  Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
2156  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
2157  }
2158  break;
2159  }
2160 
2161  /* Set DOS Version Number to return */
2162  case 0x2F:
2163  {
2164  WORD DosVersion = getDX();
2165 
2166  // Special case: return the true DOS version when DX=00h
2167  if (DosVersion == 0x0000)
2169  else
2170  DosData->DosVersion = DosVersion;
2171 
2172  break;
2173  }
2174  }
2175 
2176  break;
2177  }
2178 
2179  /* Set Disk Interrupt Handler */
2180  case 0x13:
2181  {
2182  /* Save the old values of PrevInt13 and RomBiosInt13 */
2183  ULONG OldInt13 = BiosData->PrevInt13;
2184  ULONG OldBiosInt13 = BiosData->RomBiosInt13;
2185 
2186  /* Set PrevInt13 and RomBiosInt13 to their new values */
2189 
2190  /* Return in DS:DX the old value of PrevInt13 */
2191  setDS(HIWORD(OldInt13));
2192  setDX(LOWORD(OldInt13));
2193 
2194  /* Return in DS:DX the old value of RomBiosInt13 */
2195  setES(HIWORD(OldBiosInt13));
2196  setBX(LOWORD(OldBiosInt13));
2197 
2198  break;
2199  }
2200 
2201  /* Mostly Windows 2.x/3.x/9x support */
2202  case 0x16:
2203  {
2204  /*
2205  * AL=80h is DOS/Windows/DPMI "Release Current Virtual Machine Time-slice"
2206  * Just do nothing in this case.
2207  */
2208  if (getAL() != 0x80) goto Default;
2209  break;
2210  }
2211 
2212  /* Extended Memory Specification */
2213  case 0x43:
2214  {
2216  if (!XmsGetDriverEntry(&DriverEntry)) break;
2217 
2218  switch (getAL())
2219  {
2220  /* Installation Check */
2221  case 0x00:
2222  {
2223  /* The driver is loaded */
2224  setAL(0x80);
2225  break;
2226  }
2227 
2228  /* Get Driver Address */
2229  case 0x10:
2230  {
2233  break;
2234  }
2235 
2236  default:
2237  DPRINT1("Unknown DOS XMS Function: INT 2Fh, AH = 43h, AL = %02Xh\n", getAL());
2238  break;
2239  }
2240 
2241  break;
2242  }
2243 
2244  default: Default:
2245  {
2246  DPRINT1("DOS Internal System Function INT 2Fh, AH = %02Xh, AL = %02Xh NOT IMPLEMENTED!\n",
2247  getAH(), getAL());
2248  Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
2249  }
2250  }
2251 }
USHORT WINAPI getBX(VOID)
Definition: registers.c:170
USHORT WINAPI getSI(VOID)
Definition: registers.c:404
VOID WINAPI setDS(USHORT)
Definition: registers.c:515
VOID WINAPI setAL(UCHAR)
Definition: registers.c:149
UCHAR WINAPI getAH(VOID)
Definition: registers.c:128
UCHAR WINAPI getAL(VOID)
Definition: registers.c:142
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
PDOS_DATA DosData
Definition: dos.c:45
#define EMULATOR_FLAG_CF
Definition: cpu.h:19
VOID WINAPI setES(USHORT)
Definition: registers.c:529
#define EMULATOR_FLAG_ZF
Definition: cpu.h:22
BOOLEAN XmsGetDriverEntry(PDWORD Pointer)
Definition: himem.c:789
#define DOS_VERSION
Definition: dos.h:24
#define MAKELONG(a, b)
Definition: typedefs.h:248
unsigned char BOOLEAN
#define STACK_FLAGS
Definition: int32.h:35
#define DOS_DATA_SEGMENT
Definition: dos.h:33
USHORT WINAPI getES(VOID)
Definition: registers.c:522
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
VOID WINAPI setDX(USHORT)
Definition: registers.c:293
USHORT WINAPI getDX(VOID)
Definition: registers.c:286
USHORT WINAPI getAX(VOID)
Definition: registers.c:114
VOID WINAPI setBX(USHORT)
Definition: registers.c:177
DWORD PrevInt13
Definition: dos.h:287
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
USHORT WINAPI getDI(VOID)
Definition: registers.c:434
#define DPRINT1
Definition: precomp.h:8
USHORT WINAPI getDS(VOID)
Definition: registers.c:508
#define HIWORD(l)
Definition: typedefs.h:246
unsigned int ULONG
Definition: retypes.h:1
WORD DosVersion
Definition: dos.h:246
#define LOWORD(l)
Definition: pedump.c:82
DWORD RomBiosInt13
Definition: dos.h:286
PBIOS_DATA BiosData
Definition: bios.c:42

Referenced by DosKRNLInitialize().

◆ DosIsFileOnCdRom()

static BOOLEAN DosIsFileOnCdRom ( VOID  )
static

Definition at line 164 of file dos.c.

165 {
166  UINT DriveType;
167  CHAR RootPathName[4];
168 
169  /* Construct a simple <letter>:\ string to get drive type */
170  RootPathName[0] = Sda->CurrentDrive + 'A';
171  RootPathName[1] = ':';
172  RootPathName[2] = '\\';
173  RootPathName[3] = ANSI_NULL;
174 
175  DriveType = GetDriveTypeA(RootPathName);
176  return (DriveType == DRIVE_CDROM);
177 }
UINT WINAPI GetDriveTypeA(IN LPCSTR lpRootPathName)
Definition: disk.c:468
char CHAR
Definition: xmlstorage.h:175
UINT DriveType
BYTE CurrentDrive
Definition: dos.h:159
#define ANSI_NULL
PDOS_SDA Sda
Definition: dos.c:48
#define DRIVE_CDROM
Definition: winbase.h:251
unsigned int UINT
Definition: ndis.h:50

Referenced by DosInt21h().

◆ DosKRNLInitialize()

BOOLEAN DosKRNLInitialize ( VOID  )

Definition at line 2253 of file dos.c.

2254 {
2255  UCHAR i;
2256  PDOS_SFT Sft;
2257  LPSTR Path;
2258  BOOLEAN Success = TRUE;
2259  DWORD dwRet;
2261  CHAR DosDirectory[DOS_DIR_LENGTH];
2262 
2263  static const BYTE NullDriverRoutine[] =
2264  {
2265  /* Strategy routine entry */
2266  0x26, // mov [Request.Status], DOS_DEVSTAT_DONE
2267  0xC7,
2268  0x47,
2272 
2273  /* Interrupt routine entry */
2274  0xCB, // retf
2275  };
2276 
2277  /* Set the data segment */
2279 
2280  /* Initialize the global DOS data area */
2282  RtlZeroMemory(DosData, sizeof(*DosData));
2283 
2284  /* Initialize the DOS stack */
2286  setSP(DOS_DATA_OFFSET(DosStack) + sizeof(DosData->DosStack) - sizeof(WORD));
2287 
2288  /* Initialize the list of lists */
2289  SysVars = &DosData->SysVars;
2290  RtlZeroMemory(SysVars, sizeof(*SysVars));
2292  SysVars->CurrentDirs = MAKELONG(DOS_DATA_OFFSET(CurrentDirectories),
2294  /*
2295  * The last drive can be redefined with the LASTDRIVE command.
2296  * At the moment, set the real maximum possible, 'Z'.
2297  */
2298  SysVars->NumLocalDrives = 'Z' - 'A' + 1; // See #define NUM_DRIVES in dos.h
2299 
2300  /* The boot drive is initialized to the %SYSTEMDRIVE% value */
2301  // NOTE: Using the NtSystemRoot system variable might be OS-specific...
2302  SysVars->BootDrive = RtlUpcaseUnicodeChar(SharedUserData->NtSystemRoot[0]) - 'A' + 1;
2303 
2304  /* Initialize the NUL device driver */
2305  SysVars->NullDevice.Link = 0xFFFFFFFF;
2307  // Offset from within the DOS data segment
2308  SysVars->NullDevice.StrategyRoutine = DOS_DATA_OFFSET(NullDriverRoutine);
2309  // Hardcoded to the RETF inside StrategyRoutine
2312  sizeof(SysVars->NullDevice.DeviceName),
2313  ' ');
2316  NullDriverRoutine,
2317  sizeof(NullDriverRoutine));
2318 
2319  /* Default DOS version to report */
2321 
2322  /* Initialize the swappable data area */
2323  Sda = &DosData->Sda;
2324  RtlZeroMemory(Sda, sizeof(*Sda));
2325 
2326  /* Get the current directory and convert it to a DOS path */
2328  if (dwRet == 0)
2329  {
2330  Success = FALSE;
2331  DPRINT1("GetCurrentDirectoryA failed (Error: %u)\n", GetLastError());
2332  }
2333  else if (dwRet > sizeof(CurrentDirectory))
2334  {
2335  Success = FALSE;
2336  DPRINT1("Current directory too long (%d > MAX_PATH) for GetCurrentDirectoryA\n", dwRet);
2337  }
2338 
2339  if (Success)
2340  {
2341  dwRet = GetShortPathNameA(CurrentDirectory, DosDirectory, sizeof(DosDirectory));
2342  if (dwRet == 0)
2343  {
2344  Success = FALSE;
2345  DPRINT1("GetShortPathNameA failed (Error: %u)\n", GetLastError());
2346  }
2347  else if (dwRet > sizeof(DosDirectory))
2348  {
2349  Success = FALSE;
2350  DPRINT1("Short path too long (%d > DOS_DIR_LENGTH) for GetShortPathNameA\n", dwRet);
2351  }
2352  }
2353 
2354  if (!Success)
2355  {
2356  /* We failed, use the boot drive instead */
2357  DosDirectory[0] = SysVars->BootDrive + 'A' - 1;
2358  DosDirectory[1] = ':';
2359  DosDirectory[2] = '\\';
2360  DosDirectory[3] = '\0';
2361  }
2362 
2363  /* Set the current drive */
2364  Sda->CurrentDrive = RtlUpperChar(DosDirectory[0]) - 'A';
2365 
2366  /* Get the directory part of the path and set the current directory */
2367  Path = strchr(DosDirectory, '\\');
2368  if (Path != NULL)
2369  {
2370  Path++; // Skip the backslash
2372  }
2373  else
2374  {
2376  }
2377 
2378  /* Set the current PSP to the system PSP */
2380 
2381  /* Initialize the SFT */
2383  Sft->Link = 0xFFFFFFFF;
2385 
2386  for (i = 0; i < Sft->NumDescriptors; i++)
2387  {
2388  /* Clear the file descriptor entry */
2390  }
2391 
2392  /* Initialize memory management */
2394 
2395  /* Initialize the callback context */
2397 
2398  /* Register the DOS 32-bit Interrupts */
2399  RegisterDosInt32(0x20, DosInt20h );
2400  RegisterDosInt32(0x21, DosInt21h );
2401 // RegisterDosInt32(0x22, DosInt22h ); // Termination
2402  RegisterDosInt32(0x23, DosBreakInterrupt); // Ctrl-C / Ctrl-Break
2403 // RegisterDosInt32(0x24, DosInt24h ); // Critical Error
2404  RegisterDosInt32(0x25, DosAbsoluteRead ); // Absolute Disk Read
2405  RegisterDosInt32(0x26, DosAbsoluteWrite ); // Absolute Disk Write
2406  RegisterDosInt32(0x27, DosInt27h ); // Terminate and Stay Resident
2407  RegisterDosInt32(0x28, DosIdle ); // DOS Idle Interrupt
2408  RegisterDosInt32(0x29, DosFastConOut ); // DOS 2+ Fast Console Output
2409  RegisterDosInt32(0x2F, DosInt2Fh ); // Multiplex Interrupt
2410 
2411  /* Unimplemented DOS interrupts */
2412  RegisterDosInt32(0x2A, DosInt2Ah); // DOS Critical Sections / Network
2413 // RegisterDosInt32(0x2E, NULL); // COMMAND.COM "Reload Transient"
2414 // COMMAND.COM adds support for INT 2Fh, AX=AE00h and AE01h "Installable Command - Installation Check & Execute"
2415 // COMMAND.COM adds support for INT 2Fh, AX=5500h "COMMAND.COM Interface"
2416 
2417  /* Reserved DOS interrupts */
2418  RegisterDosInt32(0x2B, NULL);
2419  RegisterDosInt32(0x2C, NULL);
2420  RegisterDosInt32(0x2D, NULL);
2421 
2422  /* Initialize country data */
2424 
2425  /* Load the CON driver */
2426  ConDrvInitialize();
2427 
2428  /* Load the XMS driver (HIMEM) */
2429  XmsInitialize();
2430 
2431  /* Load the EMS driver */
2433  {
2434  DosDisplayMessage("Could not initialize EMS. EMS will not be available.\n"
2435  "Page frame segment or number of EMS pages invalid.\n");
2436  }
2437 
2438  /* Finally initialize the UMBs */
2439  DosInitializeUmb();
2440 
2441  return TRUE;
2442 }
#define DOS_DATA_OFFSET(x)
Definition: dos.h:35
VOID DosInitializeMemory(VOID)
Definition: memory.c:665
#define DOS_DIR_LENGTH
Definition: dos.h:47
WORD CurrentPsp
Definition: dos.h:156
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
VOID WINAPI DosFastConOut(LPWORD Stack)
Definition: dos.c:2079
DWORD Link
Definition: device.h:110
#define LOBYTE(W)
Definition: jmemdos.c:487
CHAR DeviceName[MAX_DEVICE_NAME]
Definition: device.h:117
WCHAR CurrentDirectory[1024]
Definition: chkdsk.c:74
VOID WINAPI DosInt2Fh(LPWORD Stack)
Definition: dos.c:2116
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH]
Definition: dos.h:248
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
VOID InitializeContext(IN PCALLBACK16 Context, IN USHORT Segment, IN USHORT Offset)
Definition: callback.c:60
char CHAR
Definition: xmlstorage.h:175
VOID WINAPI setDS(USHORT)
Definition: registers.c:515
DOS_DRIVER NullDevice
Definition: dos.h:89
VOID WINAPI DosInt20h(LPWORD Stack)
Definition: dos.c:201
BYTE DosStack[384]
Definition: dos.h:250
#define HIBYTE(W)
Definition: jmemdos.c:486
VOID WINAPI DosInt21h(LPWORD Stack)
Definition: dos.c:210
DOS_FILE_DESCRIPTOR FileDescriptors[ANYSIZE_ARRAY]
Definition: dosfiles.h:68
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define EMS_SEGMENT
Definition: emsdrv.h:16
char * LPSTR
Definition: xmlstorage.h:182
#define DosDisplayMessage(Format,...)
Definition: dem.h:37
VOID DosInitializeUmb(VOID)
Definition: memory.c:582
NTSYSAPI WCHAR NTAPI RtlUpcaseUnicodeChar(WCHAR Source)
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
#define EMS_TOTAL_PAGES
Definition: emsdrv.h:24
#define RegisterDosInt32(IntNumber, IntHandler)
Definition: dos.h:305
DOS_SDA Sda
Definition: dos.h:247
PDOS_DATA DosData
Definition: dos.c:45
VOID WINAPI DosInt2Ah(LPWORD Stack)
Definition: dos.c:2111
VOID WINAPI DosIdle(LPWORD Stack)
Definition: dos.c:2070
VOID WINAPI setSP(USHORT)
Definition: registers.c:351
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DOS_CODE_SEGMENT
Definition: dos.h:32
BYTE CurrentDrive
Definition: dos.h:159
VOID WINAPI DosAbsoluteWrite(LPWORD Stack)
Definition: dos.c:2041
WORD InterruptRoutine
Definition: device.h:113
#define DOS_VERSION
Definition: dos.h:24
VOID WINAPI setSS(USHORT)
Definition: registers.c:501
CALLBACK16 DosContext
Definition: dos.c:40
#define DOS_SFT_SIZE
Definition: dos.h:46
#define MAKELONG(a, b)
Definition: typedefs.h:248
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define FAR_POINTER(x)
Definition: emulator.h:31
DWORD CurrentDirs
Definition: dos.h:85
BOOLEAN DosCountryInitialize(VOID)
Definition: country.c:236
#define DOS_DATA_SEGMENT
Definition: dos.h:33
BOOLEAN EmsDrvInitialize(USHORT Segment, ULONG TotalPages)
Definition: emsdrv.c:767
DWORD WINAPI GetShortPathNameA(IN LPCSTR lpszLongPath, OUT LPSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1751
#define MAX_PATH
Definition: compat.h:26
unsigned short WORD
Definition: ntddk_ex.h:93
VOID WINAPI DosInt27h(LPWORD Stack)
Definition: dos.c:2061
unsigned long DWORD
Definition: ntddk_ex.h:95
struct _DOS_DATA * PDOS_DATA
VOID ConDrvInitialize(VOID)
Definition: condrv.c:132
NTSYSAPI CHAR NTAPI RtlUpperChar(CHAR Character)
#define SharedUserData
unsigned char UCHAR
Definition: xmlstorage.h:181
#define DOS_DEVATTR_NUL
Definition: device.h:23
VOID WINAPI DosBreakInterrupt(LPWORD Stack)
Definition: dos.c:2015
unsigned char BYTE
Definition: mem.h:68
PDOS_SDA Sda
Definition: dos.c:48
VOID WINAPI DosAbsoluteRead(LPWORD Stack)
Definition: dos.c:2021
BYTE NullDriverRoutine[7]
Definition: dos.h:245
#define DOS_DEVSTAT_DONE
Definition: device.h:49
BYTE NumLocalDrives
Definition: dos.h:88
struct _DOS_SFT * PDOS_SFT
Status
Definition: gdiplustypes.h:24
WORD DeviceAttributes
Definition: device.h:111
#define DOS_DEVATTR_CHARACTER
Definition: device.h:29
PRTL_UNICODE_STRING_BUFFER Path
WORD NumDescriptors
Definition: dosfiles.h:67
DOS_SYSVARS SysVars
Definition: dos.h:244
PDOS_SYSVARS SysVars
Definition: dos.c:47
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2145
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
#define SYSTEM_PSP
Definition: dos.h:39
DWORD FirstSft
Definition: dos.h:81
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define DPRINT1
Definition: precomp.h:8
BYTE BootDrive
Definition: dos.h:96
VOID XmsInitialize(VOID)
Definition: himem.c:796
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
WORD DosVersion
Definition: dos.h:246
WORD StrategyRoutine
Definition: device.h:112
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
DWORD Link
Definition: dosfiles.h:66

Referenced by DosBIOSInitialize().

Variable Documentation

◆ DosContext

◆ DosData

◆ Sda

◆ SysVars