ReactOS 0.4.15-dev-7958-gcd0bb1a
dem.c File Reference
#include "ntvdm.h"
#include <debug.h>
#include "emulator.h"
#include <isvbop.h>
#include "utils.h"
#include "dem.h"
#include "dos/dos32krnl/device.h"
#include "dos/dos32krnl/memory.h"
#include "dos/dos32krnl/process.h"
#include "cpu/bop.h"
#include "cpu/cpu.h"
#include "bios/bios.h"
#include "mouse32.h"
#include "vddsup.h"
#include "command_com.h"
Include dependency graph for dem.c:

Go to the source code of this file.

Classes

struct  _COMSPEC_INFO
 
struct  _NEXT_CMD
 
struct  _DOS_START_PROC32
 

Macros

#define NDEBUG
 

Typedefs

typedef struct _COMSPEC_INFO COMSPEC_INFO
 
typedef struct _COMSPEC_INFOPCOMSPEC_INFO
 
typedef struct _NEXT_CMD NEXT_CMD
 
typedef struct _NEXT_CMDPNEXT_CMD
 
typedef struct _DOS_START_PROC32 DOS_START_PROC32
 
typedef struct _DOS_START_PROC32PDOS_START_PROC32
 

Functions

VOID Dem_BiosCharPrint (CHAR Character)
 
VOID DosCharPrint (CHAR Character)
 
static VOID DemLoadNTDOSKernel (VOID)
 
static VOID WINAPI DosSystemBop (LPWORD Stack)
 
static PCOMSPEC_INFO FindComSpecInfoByPsp (WORD Psp)
 
static VOID InsertComSpecInfo (PCOMSPEC_INFO ComSpecInfo)
 
static VOID RemoveComSpecInfo (PCOMSPEC_INFO ComSpecInfo)
 
static VOID DosProcessConsoleAttach (VOID)
 
static VOID DosProcessConsoleDetach (VOID)
 
static VOID CmdStartProcess (VOID)
 
static VOID CmdStartExternalCommand (VOID)
 
static VOID CmdStartComSpec32 (VOID)
 
static VOID CmdSetExitCode (VOID)
 
static VOID WINAPI DosCmdInterpreterBop (LPWORD Stack)
 
static DWORD DosStartComSpec (IN BOOLEAN Permanent, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL, OUT PWORD ComSpecPsp OPTIONAL)
 
static DWORD WINAPI CommandThreadProc (LPVOID Parameter)
 
DWORD DosStartProcess32 (IN LPCSTR ExecutablePath, IN LPCSTR CommandLine, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL, IN BOOLEAN StartComSpec)
 
static VOID WINAPI DosInitialize (LPWORD Stack)
 
VOID DosBootsectorInitialize (VOID)
 
static VOID WINAPI DosStart (LPWORD Stack)
 
BOOLEAN DosShutdown (BOOLEAN Immediate)
 
DWORD WINAPI demClientErrorEx (IN HANDLE FileHandle, IN CHAR Unknown, IN BOOL Flag)
 
DWORD WINAPI demFileDelete (IN LPCSTR FileName)
 
static BOOLEAN dempIsFileMatch (_Inout_ PWIN32_FIND_DATAA FindData, _In_ WORD AttribMask, _Out_ PCSTR *ShortName)
 Helper for demFileFindFirst() and demFileFindNext(). Returns TRUE if a file matches the DOS attributes and has a 8.3 file name.
 
demFileFindFirst

Implementation of the DOS INT 21h, AH=4Eh "Find First File" function.

Starts enumerating files that match the given file search specification and whose attributes are at most those specified by the mask. This means in particular that "normal files", i.e. files with no attributes set, are always enumerated along those matching the requested attributes.

Parameters
[out]pFindFileDataPointer to the DTA (Disk Transfer Area) filled with FindFirst data block.
[in]FileNameFile search specification (may include path and wildcards).
[in]AttribMaskMask of file attributes. Includes files with a given attribute bit set if the corresponding bit is set to 1 in the mask. Excludes files with a given attribute bit set if the corresponding bit is set to 0 in the mask. Supported file attributes: FA_NORMAL 0x0000 FA_READONLY 0x0001 (ignored) FA_HIDDEN 0x0002 FA_SYSTEM 0x0004 FA_VOLID 0x0008 (not currently supported) FA_LABEL FA_DIRECTORY 0x0010 FA_ARCHIVE 0x0020 (ignored) FA_DEVICE 0x0040 (ignored)
Returns
ERROR_SUCCESS on success (found match), or a last error (match not found).
See also
demFileFindNext()
DWORD WINAPI demFileFindFirst (_Out_ PVOID pFindFileData, _In_ PCSTR FileName, _In_ WORD AttribMask)
 
demFileFindNext

Implementation of the DOS INT 21h, AH=4Fh "Find Next File" function.

Continues enumerating files, with the same file search specification and attributes as those given to the first demFileFindFirst() call.

Parameters
[in,out]pFindFileDataPointer to the DTA (Disk Transfer Area) filled with FindFirst data block.
Returns
ERROR_SUCCESS on success (found match), or a last error (match not found).
See also
demFileFindFirst()
DWORD WINAPI demFileFindNext (_Inout_ PVOID pFindFileData)
 
UCHAR WINAPI demGetPhysicalDriveType (IN UCHAR DriveNumber)
 
BOOL WINAPI demIsShortPathName (IN LPCSTR Path, IN BOOL Unknown)
 
DWORD WINAPI demSetCurrentDirectoryGetDrive (IN LPCSTR CurrentDirectory, OUT PUCHAR DriveNumber)
 

Variables

static ULONG SessionId = 0
 
static COMSPEC_INFO RootCmd
 
static DWORD ReentrancyCount = 0
 
static LIST_ENTRY ComSpecInfoList = { &ComSpecInfoList, &ComSpecInfoList }
 
static VDM_COMMAND_INFO CommandInfo
 
static BOOLEAN Repeat = FALSE
 
static BOOLEAN Reentry = FALSE
 
static BOOLEAN First = TRUE
 
static CHAR CmdLine [MAX_PATH] = ""
 
static CHAR AppName [MAX_PATH] = ""
 
static CHAR PifFile [MAX_PATH] = ""
 
static CHAR CurDirectory [MAX_PATH] = ""
 
static CHAR Desktop [MAX_PATH] = ""
 
static CHAR Title [MAX_PATH] = ""
 
static ULONG EnvSize = 256
 
static PVOID Env = NULL
 
static BYTE Bootsector1 []
 
static BYTE Bootsector2 []
 
static BYTE Startup []
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 17 of file dem.c.

Typedef Documentation

◆ COMSPEC_INFO

◆ DOS_START_PROC32

◆ NEXT_CMD

◆ PCOMSPEC_INFO

◆ PDOS_START_PROC32

◆ PNEXT_CMD

Function Documentation

◆ CmdSetExitCode()

static VOID CmdSetExitCode ( VOID  )
static

Definition at line 505 of file dem.c.

506{
507#ifndef STANDALONE
509 PCOMSPEC_INFO ComSpecInfo;
511#endif
512
513 /* Pause the VM */
515
516#ifndef STANDALONE
517 /*
518 * Check whether we need to shell out now in case we were started by a 32-bit app,
519 * or we were started alone along with the root 32-bit app.
520 */
521 ComSpecInfo = FindComSpecInfoByPsp(Sda->CurrentPsp);
522 if ((ComSpecInfo && ComSpecInfo->Terminated) ||
523 (ComSpecInfo == &RootCmd && SessionId != 0))
524 {
525 RemoveComSpecInfo(ComSpecInfo);
526#endif
527 DPRINT1("Exit DOS from ExitCode (prologue)!\n");
528 setCF(0);
529 goto Quit;
530#ifndef STANDALONE
531 }
532
533 /* Clear the VDM structure */
535
536Retry:
537 /* Update the VDM state of the task */
538 // CommandInfo.TaskId = SessionId;
541 DPRINT1("Calling GetNextVDMCommand 32bit end of VDM task\n");
543 DPRINT1("GetNextVDMCommand 32bit end of VDM task success = %s, last error = %d\n", Success ? "true" : "false", GetLastError());
544
545 /*
546 * Check whether we were awaited because the 32-bit process was stopped,
547 * or because it started a new DOS application.
548 */
549 if (CommandInfo.CmdLen != 0 || CommandInfo.AppLen != 0 || CommandInfo.PifLen != 0)
550 {
551 DPRINT1("GetNextVDMCommand end-of-app, this is for a new VDM task - CmdLen = %d, AppLen = %d, PifLen = %d\n",
553
554 /* Repeat the request */
555 Repeat = TRUE;
556 setCF(1);
557 }
558 else
559 {
560 DPRINT1("GetNextVDMCommand end-of-app, the app stopped\n");
561
562 /* Check whether we need to shell out now in case we were started by a 32-bit app */
563 ComSpecInfo = FindComSpecInfoByPsp(Sda->CurrentPsp);
564 if (!ComSpecInfo || !ComSpecInfo->Terminated)
565 {
566 DPRINT1("Not our 32-bit app, retrying...\n");
567 goto Retry;
568 }
569
570 ASSERT(ComSpecInfo->Terminated == TRUE);
571
572 /* Record found, remove it and exit now */
573 RemoveComSpecInfo(ComSpecInfo);
574
575 DPRINT1("Exit DOS from ExitCode wait!\n");
576 setCF(0);
577 }
578#endif
579
580 // FIXME: Use the retrieved exit code as the value of our exit code
581 // when COMMAND.COM will shell-out ??
582
583Quit:
584 /* Resume the VM */
586}
#define DPRINT1
Definition: precomp.h:8
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
static COMSPEC_INFO RootCmd
Definition: dem.c:192
static ULONG SessionId
Definition: dem.c:179
static VOID RemoveComSpecInfo(PCOMSPEC_INFO ComSpecInfo)
Definition: dem.c:220
static PCOMSPEC_INFO FindComSpecInfoByPsp(WORD Psp)
Definition: dem.c:199
static BOOLEAN Repeat
Definition: dem.c:247
static VDM_COMMAND_INFO CommandInfo
Definition: dem.c:246
#define TRUE
Definition: types.h:120
BOOL WINAPI GetNextVDMCommand(PVDM_COMMAND_INFO CommandData)
Definition: vdm.c:1420
PDOS_SDA Sda
Definition: dos.c:48
VOID EmulatorResume(VOID)
Definition: emulator.c:495
VOID EmulatorPause(VOID)
Definition: emulator.c:487
@ Success
Definition: eventcreate.c:712
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ASSERT(a)
Definition: mode.c:44
#define VDM_FLAG_DONT_WAIT
Definition: vdm.h:60
USHORT AppLen
Definition: vdm.h:91
USHORT CmdLen
Definition: vdm.h:90
USHORT PifLen
Definition: vdm.h:92
USHORT VDMState
Definition: vdm.h:94
ULONG ExitCode
Definition: vdm.h:72
BOOLEAN Terminated
Definition: dem.c:189
WORD CurrentPsp
Definition: dos.h:165
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
VOID WINAPI setCF(ULONG)
Definition: registers.c:573
USHORT WINAPI getDX(VOID)
Definition: registers.c:286
DWORD WINAPI GetLastError(void)
Definition: except.c:1042

Referenced by DosCmdInterpreterBop().

◆ CmdStartComSpec32()

static VOID CmdStartComSpec32 ( VOID  )
static

Definition at line 465 of file dem.c.

466{
468
469 // TODO: improve: this code has strong similarities with the
470 // 'default' case of DosCreateProcess and with the 'case 0x08'.
471
472 CHAR CmdLine[sizeof("cmd.exe") + 1] = "";
473
474 /* Spawn a user-defined 32-bit command preprocessor */
475
476 // FIXME: Use COMSPEC env var!!
477 strcpy(CmdLine, "cmd.exe");
478
479 DPRINT1("CMD Run 32-bit Command Interpreter '%s'\n", CmdLine);
480
481 /*
482 * No need to prepare the stack for DosStartComSpec since we won't start it.
483 */
485 SEG_OFF_TO_PTR(getES(), 0) /*Environment*/,
486 MAKELONG(getIP(), getCS()) /*ReturnAddress*/,
487 FALSE);
488 if (Result != ERROR_SUCCESS)
489 {
490 DosDisplayMessage("Failed to start 32-bit Command Interpreter '%s'. Error: %u\n", CmdLine, Result);
491 setCF(0);
493 }
494 else
495 {
496 DosDisplayMessage("32-bit Command Interpreter '%s' started successfully.\n", CmdLine);
497#ifndef STANDALONE
498 setCF(Repeat); // Set CF if we need to start a 16-bit process
499#else
500 setCF(0);
501#endif
502 }
503}
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
static CHAR CmdLine[MAX_PATH]
Definition: dem.c:251
DWORD DosStartProcess32(IN LPCSTR ExecutablePath, IN LPCSTR CommandLine, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL, IN BOOLEAN StartComSpec)
Definition: dem.c:916
#define DosDisplayMessage(Format,...)
Definition: dem.h:38
#define ERROR_SUCCESS
Definition: deptool.c:10
#define FALSE
Definition: types.h:117
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:32
unsigned long DWORD
Definition: ntddk_ex.h:95
#define MAKELONG(a, b)
Definition: typedefs.h:249
USHORT WINAPI getIP(VOID)
Definition: registers.c:464
VOID WINAPI setAL(UCHAR)
Definition: registers.c:149
USHORT WINAPI getES(VOID)
Definition: registers.c:522
USHORT WINAPI getCS(VOID)
Definition: registers.c:480
_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:409
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175

Referenced by DosCmdInterpreterBop().

◆ CmdStartExternalCommand()

static VOID CmdStartExternalCommand ( VOID  )
static

Definition at line 411 of file dem.c.

412{
414
415 // TODO: improve: this code has strong similarities
416 // with the 'default' case of DosCreateProcess.
417
419 CHAR CmdLine[sizeof("cmd.exe /c ") + DOS_CMDLINE_LENGTH + 1] = "";
420 LPSTR CmdLinePtr;
421 SIZE_T CmdLineLen;
422
423 /* Spawn a user-defined 32-bit command preprocessor */
424
425 // FIXME: Use COMSPEC env var!!
426 CmdLinePtr = CmdLine;
427 strcpy(CmdLinePtr, "cmd.exe /c ");
428 CmdLinePtr += strlen(CmdLinePtr);
429
430 /* Build a Win32-compatible command-line */
431 CmdLineLen = min(strlen(Command), sizeof(CmdLine) - strlen(CmdLinePtr) - 1);
432 RtlCopyMemory(CmdLinePtr, Command, CmdLineLen);
433 CmdLinePtr[CmdLineLen] = '\0';
434
435 /* Remove any trailing return carriage character and NULL-terminate the command line */
436 while (*CmdLinePtr && *CmdLinePtr != '\r' && *CmdLinePtr != '\n') CmdLinePtr++;
437 *CmdLinePtr = '\0';
438
439 DPRINT1("CMD Run Command '%s' ('%s')\n", Command, CmdLine);
440
441 /*
442 * No need to prepare the stack for DosStartComSpec since we won't start it.
443 */
445 SEG_OFF_TO_PTR(getES(), 0) /*Environment*/,
446 MAKELONG(getIP(), getCS()) /*ReturnAddress*/,
447 FALSE);
448 if (Result != ERROR_SUCCESS)
449 {
450 DosDisplayMessage("Failed to start command '%s' ('%s'). Error: %u\n", Command, CmdLine, Result);
451 setCF(0);
453 }
454 else
455 {
456 DosDisplayMessage("Command '%s' ('%s') started successfully.\n", Command, CmdLine);
457#ifndef STANDALONE
458 setCF(Repeat); // Set CF if we need to start a 16-bit process
459#else
460 setCF(0);
461#endif
462 }
463}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define min(a, b)
Definition: monoChain.cc:55
Definition: shell.h:41
#define DOS_CMDLINE_LENGTH
Definition: process.h:13
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
USHORT WINAPI getDS(VOID)
Definition: registers.c:508
USHORT WINAPI getSI(VOID)
Definition: registers.c:404
char * LPSTR
Definition: xmlstorage.h:182

Referenced by DosCmdInterpreterBop().

◆ CmdStartProcess()

static VOID CmdStartProcess ( VOID  )
static

Definition at line 290 of file dem.c.

291{
292#ifndef STANDALONE
293 PCOMSPEC_INFO ComSpecInfo;
294#endif
295 SIZE_T CmdLen;
296 PNEXT_CMD DataStruct = (PNEXT_CMD)SEG_OFF_TO_PTR(getDS(), getDX());
297
298 DPRINT1("CmdStartProcess -- DS:DX = %04X:%04X (DataStruct = 0x%p)\n",
299 getDS(), getDX(), DataStruct);
300
301 /* Pause the VM */
303
304#ifndef STANDALONE
305 /* Check whether we need to shell out now in case we were started by a 32-bit app */
306 ComSpecInfo = FindComSpecInfoByPsp(Sda->CurrentPsp);
307 if (ComSpecInfo && ComSpecInfo->Terminated)
308 {
309 RemoveComSpecInfo(ComSpecInfo);
310
311 DPRINT1("Exit DOS from start-app BOP\n");
312 setCF(1);
313 goto Quit;
314 }
315
316 /* Clear the structure */
318
319 /* Initialize the structure members */
323 CommandInfo.CmdLen = sizeof(CmdLine);
325 CommandInfo.AppLen = sizeof(AppName);
327 CommandInfo.PifLen = sizeof(PifFile);
333 CommandInfo.TitleLen = sizeof(Title);
336
338
339Command:
340
342 Repeat = FALSE;
343
344 /* Get the VDM command information */
345 DPRINT1("Calling GetNextVDMCommand in CmdStartProcess: wait for new VDM task...\n");
347 {
348 DPRINT1("CmdStartProcess - GetNextVDMCommand failed, retrying... last error = %d\n", GetLastError());
350 {
351 /* Expand the environment size */
353 CommandInfo.Env = Env = RtlReAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Env, EnvSize);
354
355 /* Repeat the request */
356 Repeat = TRUE;
357 goto Command;
358 }
359
360 /* Shouldn't happen */
361 DisplayMessage(L"An unrecoverable failure happened from start-app BOP; exiting DOS.");
362 setCF(1);
363 goto Quit;
364 }
365
366 // FIXME: What happens if some other 32-bit app is killed while we are waiting there??
367
368 DPRINT1("CmdStartProcess - GetNextVDMCommand succeeded, start app...\n");
369
370#else
371
372 if (!First)
373 {
374 DPRINT1("Exit DOS from start-app BOP\n");
375 setCF(1);
376 goto Quit;
377 }
378
379#endif
380
381 /* Compute the command line length, not counting the terminating "\r\n" */
382 CmdLen = strlen(CmdLine);
383 if (CmdLen >= 2 && CmdLine[CmdLen - 2] == '\r')
384 CmdLen -= 2;
385
386 DPRINT1("Starting '%s' ('%.*s')...\n", AppName, CmdLen, CmdLine);
387
388 /* Start the process */
389 // FIXME: Merge 'Env' with the master environment SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0)
390 // FIXME: Environment
392 *(PBYTE)(SEG_OFF_TO_PTR(DataStruct->CmdLineSeg, DataStruct->CmdLineOff)) = (BYTE)CmdLen;
394
395#ifndef STANDALONE
396 /* Update console title if we run in a separate console */
397 if (SessionId != 0)
399#endif
400
401 First = FALSE;
402 setCF(0);
403
404 DPRINT1("App started!\n");
405
406Quit:
407 /* Resume the VM */
409}
static CHAR CurDirectory[MAX_PATH]
Definition: dem.c:255
struct _NEXT_CMD * PNEXT_CMD
static CHAR Desktop[MAX_PATH]
Definition: dem.c:256
static CHAR Title[MAX_PATH]
Definition: dem.c:257
static CHAR AppName[MAX_PATH]
Definition: dem.c:252
static PVOID Env
Definition: dem.c:259
static BOOLEAN First
Definition: dem.c:250
static CHAR PifFile[MAX_PATH]
Definition: dem.c:254
static ULONG EnvSize
Definition: dem.c:258
#define MAX_PATH
Definition: compat.h:34
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleTitleA(LPCSTR lpConsoleTitle)
Definition: console.c:2302
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2667
#define L(x)
Definition: ntvdm.h:50
BYTE * PBYTE
Definition: pedump.c:66
void DisplayMessage(BOOL bConsole, BOOL bSilent, LPCTSTR lpMessage, LPCTSTR lpTitle, UINT uType)
Definition: regsvr32.c:239
#define VDM_FLAG_RETRY
Definition: vdm.h:56
#define VDM_FLAG_DOS
Definition: vdm.h:55
#define VDM_FLAG_FIRST_TASK
Definition: vdm.h:53
LPSTR CmdLine
Definition: vdm.h:77
LPSTR CurDirectory
Definition: vdm.h:80
LPSTR Title
Definition: vdm.h:86
LPSTR Desktop
Definition: vdm.h:84
LPSTR Env
Definition: vdm.h:81
ULONG TitleLen
Definition: vdm.h:87
USHORT CurDirectoryLen
Definition: vdm.h:93
LPSTR PifFile
Definition: vdm.h:79
LPSTR AppName
Definition: vdm.h:78
ULONG TaskId
Definition: vdm.h:70
ULONG DesktopLen
Definition: vdm.h:85
ULONG EnvLen
Definition: vdm.h:82
Definition: dem.c:268
USHORT AppNameSeg
Definition: dem.c:282
USHORT AppNameOff
Definition: dem.c:283
USHORT CmdLineSeg
Definition: dem.c:273
USHORT CmdLineOff
Definition: dem.c:274
unsigned char BYTE
Definition: xxhash.c:193

Referenced by DosCmdInterpreterBop().

◆ CommandThreadProc()

static DWORD WINAPI CommandThreadProc ( LPVOID  Parameter)
static

Definition at line 828 of file dem.c.

829{
831 PROCESS_INFORMATION ProcessInfo;
832 STARTUPINFOA StartupInfo;
833 DWORD dwExitCode;
835#ifndef STANDALONE
837 PCOMSPEC_INFO ComSpecInfo = DosStartProc32->ComSpecInfo;
838#endif
839
840 /* Set up the VDM, startup and process info structures */
841#ifndef STANDALONE
843#endif
844 RtlZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
845 RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
846 StartupInfo.cb = sizeof(StartupInfo);
847
848 // FIXME: Build suitable 32-bit environment!!
849
850#ifndef STANDALONE
851 /*
852 * Wait for signaling a new VDM task and increment the VDM re-entry count so
853 * that we can handle 16-bit apps that may be possibly started by the 32-bit app.
854 */
856 DPRINT1("Calling GetNextVDMCommand reenter++\n");
858 DPRINT1("GetNextVDMCommand reenter++ success = %s, last error = %d\n", Success ? "true" : "false", GetLastError());
860#endif
861
862 /* Start the process */
863 Success = CreateProcessA(NULL, // ProgramName,
864 DosStartProc32->CommandLine,
865 NULL,
866 NULL,
867 TRUE, // Inherit handles
869 DosStartProc32->Environment,
870 NULL, // lpCurrentDirectory, see "START" command in cmd.exe
871 &StartupInfo,
872 &ProcessInfo);
873
874#ifndef STANDALONE
875 /* Signal our caller the process was started */
876 SetEvent(DosStartProc32->hEvent);
877 // After this point, 'DosStartProc32' is not valid anymore.
878#endif
879
880 if (Success)
881 {
882 /* Resume the process */
883 ResumeThread(ProcessInfo.hThread);
884
885 /* Wait for the process to finish running and retrieve its exit code */
887 GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
888
889 /* Close the handles */
890 CloseHandle(ProcessInfo.hThread);
891 CloseHandle(ProcessInfo.hProcess);
892 }
893 else
894 {
895 dwExitCode = GetLastError();
896 }
897
898#ifndef STANDALONE
899 ASSERT(ComSpecInfo);
900 ComSpecInfo->Terminated = TRUE;
901 ComSpecInfo->dwExitCode = dwExitCode;
902
903 /* Decrement the VDM re-entry count */
905 DPRINT1("Calling GetNextVDMCommand reenter--\n");
907 DPRINT1("GetNextVDMCommand reenter-- success = %s, last error = %d\n", Success ? "true" : "false", GetLastError());
909
910 return 0;
911#else
912 return dwExitCode;
913#endif
914}
static DWORD ReentrancyCount
Definition: dem.c:193
struct _DOS_START_PROC32 * PDOS_START_PROC32
#define NULL
Definition: types.h:112
#define CloseHandle
Definition: compat.h:739
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1168
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4741
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
#define INFINITE
Definition: serial.h:102
#define VDM_INC_REENTER_COUNT
Definition: vdm.h:57
#define VDM_DEC_REENTER_COUNT
Definition: vdm.h:58
DWORD dwExitCode
Definition: dem.c:187
LPSTR CommandLine
Definition: dem.c:818
HANDLE hEvent
Definition: dem.c:822
PCOMSPEC_INFO ComSpecInfo
Definition: dem.c:821
DWORD cb
Definition: winbase.h:831
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
#define CREATE_DEFAULT_ERROR_MODE
Definition: winbase.h:194
#define CREATE_SUSPENDED
Definition: winbase.h:178
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323

Referenced by DosStartProcess32().

◆ Dem_BiosCharPrint()

VOID Dem_BiosCharPrint ( CHAR  Character)

Definition at line 57 of file dem.c.

58{
59 /* Save AX and BX */
60 USHORT AX = getAX();
61 USHORT BX = getBX();
62
63 /*
64 * Set the parameters:
65 * AL contains the character to print,
66 * BL contains the character attribute,
67 * BH contains the video page to use.
68 */
69 setAL(Character);
72
73 /* Call the BIOS INT 10h, AH=0Eh "Teletype Output" */
74 setAH(0x0E);
76
77 /* Restore AX and BX */
78 setBX(BX);
79 setAX(AX);
80}
CALLBACK16 DosContext
Definition: dos.c:40
#define AX
Definition: i386-dis.c:424
VOID Int32Call(IN PCALLBACK16 Context, IN BYTE IntNumber)
Definition: int32.c:151
unsigned short USHORT
Definition: pedump.c:61
BYTE VideoPage
Definition: bios.h:66
PBIOS_DATA_AREA Bda
Definition: bios.c:42
VOID WINAPI setBX(USHORT)
Definition: registers.c:177
USHORT WINAPI getBX(VOID)
Definition: registers.c:170
VOID WINAPI setAH(UCHAR)
Definition: registers.c:135
VOID WINAPI setBL(UCHAR)
Definition: registers.c:205
USHORT WINAPI getAX(VOID)
Definition: registers.c:114
VOID WINAPI setBH(UCHAR)
Definition: registers.c:191
VOID WINAPI setAX(USHORT)
Definition: registers.c:121
#define DEFAULT_ATTRIBUTE
Definition: vidbios.h:21
#define BIOS_VIDEO_INTERRUPT
Definition: vidbios.h:15

◆ demClientErrorEx()

DWORD WINAPI demClientErrorEx ( IN HANDLE  FileHandle,
IN CHAR  Unknown,
IN BOOL  Flag 
)

Definition at line 1392 of file dem.c.

1395{
1397 return GetLastError();
1398}
#define UNIMPLEMENTED
Definition: debug.h:115

◆ demFileDelete()

DWORD WINAPI demFileDelete ( IN LPCSTR  FileName)

Definition at line 1402 of file dem.c.

1403{
1405
1406 return GetLastError();
1407}
#define SetLastError(x)
Definition: compat.h:752
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24

Referenced by DosInt21h().

◆ demFileFindFirst()

DWORD WINAPI demFileFindFirst ( _Out_ PVOID  pFindFileData,
_In_ PCSTR  FileName,
_In_ WORD  AttribMask 
)

Definition at line 1515 of file dem.c.

1519{
1520 PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)pFindFileData;
1521 HANDLE SearchHandle;
1522 WIN32_FIND_DATAA FindData;
1524
1525 /* Reset the private block fields */
1526 RtlZeroMemory(FindFileBlock, RTL_SIZEOF_THROUGH_FIELD(DOS_FIND_FILE_BLOCK, SearchHandle));
1527
1528 // TODO: Handle FA_VOLID for volume label.
1529 if (AttribMask & FA_VOLID)
1530 {
1531 DPRINT1("demFileFindFirst: Volume label attribute is UNIMPLEMENTED!\n");
1532 AttribMask &= ~FA_VOLID; // Remove it for the time being...
1533 }
1534
1535 /* Filter out the ignored attributes */
1536 AttribMask &= ~(FA_DEVICE | FA_ARCHIVE | FA_READONLY);
1537
1538 /* Start a search */
1539 SearchHandle = FindFirstFileA(FileName, &FindData);
1540 if (SearchHandle == INVALID_HANDLE_VALUE)
1541 return GetLastError();
1542
1543 /* Check the attributes and retry as long as we haven't found a matching file */
1544 while (!dempIsFileMatch(&FindData, AttribMask, &ShortName))
1545 {
1546 /* Continue searching. If we fail at some point,
1547 * stop the search and return an error. */
1548 if (!FindNextFileA(SearchHandle, &FindData))
1549 {
1550 FindClose(SearchHandle);
1551 return GetLastError();
1552 }
1553 }
1554
1555 /* Fill the block */
1556 FindFileBlock->DriveLetter = DosData->Sda.CurrentDrive + 'A';
1557 strncpy(FindFileBlock->Pattern, FileName, _countof(FindFileBlock->Pattern));
1558 FindFileBlock->AttribMask = AttribMask;
1559 FindFileBlock->SearchHandle = SearchHandle;
1560 FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes);
1561 FileTimeToDosDateTime(&FindData.ftLastWriteTime,
1562 &FindFileBlock->FileDate,
1563 &FindFileBlock->FileTime);
1564 FindFileBlock->FileSize = FindData.nFileSizeHigh ? MAXDWORD
1565 : FindData.nFileSizeLow;
1566
1567 /* Copy the NULL-terminated short file name */
1568 RtlStringCchCopyA(FindFileBlock->FileName,
1569 _countof(FindFileBlock->FileName),
1570 ShortName);
1571
1572 return ERROR_SUCCESS;
1573}
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
static BOOLEAN dempIsFileMatch(_Inout_ PWIN32_FIND_DATAA FindData, _In_ WORD AttribMask, _Out_ PCSTR *ShortName)
Helper for demFileFindFirst() and demFileFindNext(). Returns TRUE if a file matches the DOS attribute...
Definition: dem.c:1414
#define FA_VOLID
Definition: dem.h:73
#define FA_DEVICE
Definition: dem.h:77
#define FA_ARCHIVE
Definition: dem.h:76
#define FA_READONLY
Definition: dem.h:70
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
HANDLE WINAPI FindFirstFileA(IN LPCSTR lpFileName, OUT LPWIN32_FIND_DATAA lpFindFileData)
Definition: find.c:263
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FindNextFileA(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAA lpFindFileData)
Definition: find.c:336
BOOL WINAPI FileTimeToDosDateTime(IN CONST FILETIME *lpFileTime, OUT LPWORD lpFatDate, OUT LPWORD lpFatTime)
Definition: time.c:37
PDOS_DATA DosData
Definition: dos.c:45
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING ShortName
Definition: fatprocs.h:1306
#define LOBYTE(W)
Definition: jmemdos.c:487
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
#define MAXDWORD
NTSTRSAFEAPI RtlStringCchCopyA(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:110
#define _countof(array)
Definition: sndvol32.h:68
DOS_SDA Sda
Definition: dos.h:256
HANDLE SearchHandle
Definition: dos.h:137
_Null_terminated_ CHAR FileName[13]
Definition: dos.h:144
UCHAR AttribMask
Definition: dos.h:135
CHAR DriveLetter
Definition: dos.h:133
UCHAR Attributes
Definition: dos.h:140
CHAR Pattern[11]
Definition: dos.h:134
DWORD FileSize
Definition: dos.h:143
BYTE CurrentDrive
Definition: dos.h:168
struct _DOS_FIND_FILE_BLOCK * PDOS_FIND_FILE_BLOCK
const char * PCSTR
Definition: typedefs.h:52

Referenced by DosInt21h().

◆ demFileFindNext()

DWORD WINAPI demFileFindNext ( _Inout_ PVOID  pFindFileData)

Definition at line 1592 of file dem.c.

1594{
1595 PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)pFindFileData;
1596 HANDLE SearchHandle = FindFileBlock->SearchHandle;
1597 WIN32_FIND_DATAA FindData;
1599
1600 do
1601 {
1602 /* Continue searching. If we fail at some point,
1603 * stop the search and return an error. */
1604 if (!FindNextFileA(SearchHandle, &FindData))
1605 {
1606 FindClose(SearchHandle);
1607
1608 /* Reset the private block fields */
1609 RtlZeroMemory(FindFileBlock, RTL_SIZEOF_THROUGH_FIELD(DOS_FIND_FILE_BLOCK, SearchHandle));
1610 return GetLastError();
1611 }
1612 }
1613 /* Check the attributes and retry as long as we haven't found a matching file */
1614 while (!dempIsFileMatch(&FindData, FindFileBlock->AttribMask, &ShortName));
1615
1616 /* Update the block */
1617 FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes);
1618 FileTimeToDosDateTime(&FindData.ftLastWriteTime,
1619 &FindFileBlock->FileDate,
1620 &FindFileBlock->FileTime);
1621 FindFileBlock->FileSize = FindData.nFileSizeHigh ? MAXDWORD
1622 : FindData.nFileSizeLow;
1623
1624 /* Copy the NULL-terminated short file name */
1625 RtlStringCchCopyA(FindFileBlock->FileName,
1626 _countof(FindFileBlock->FileName),
1627 ShortName);
1628
1629 return ERROR_SUCCESS;
1630}

Referenced by DosInt21h().

◆ demGetPhysicalDriveType()

UCHAR WINAPI demGetPhysicalDriveType ( IN UCHAR  DriveNumber)

Definition at line 1634 of file dem.c.

1635{
1638}
#define DOSDEVICE_DRIVE_UNKNOWN
Definition: obtypes.h:163

◆ demIsShortPathName()

BOOL WINAPI demIsShortPathName ( IN LPCSTR  Path,
IN BOOL  Unknown 
)

Definition at line 1642 of file dem.c.

1644{
1646 return FALSE;
1647}

◆ DemLoadNTDOSKernel()

static VOID DemLoadNTDOSKernel ( VOID  )
static

Definition at line 88 of file dem.c.

89{
91 LPCSTR DosKernelFileName = "ntdos.sys";
92 HANDLE hDosKernel;
93 ULONG ulDosKernelSize = 0;
94
95 DPRINT1("You are loading Windows NT DOS!\n");
96
97 /* Open the DOS kernel file */
98 hDosKernel = FileOpen(DosKernelFileName, &ulDosKernelSize);
99 if (hDosKernel == NULL) goto Quit;
100
101 /*
102 * Attempt to load the DOS kernel into memory.
103 * The segment where to load the DOS kernel is defined
104 * by the DOS BIOS and is found in DI:0000 .
105 */
106 Success = FileLoadByHandle(hDosKernel,
107 REAL_TO_PHYS(TO_LINEAR(getDI(), 0x0000)),
108 ulDosKernelSize,
109 &ulDosKernelSize);
110
111 DPRINT1("Windows NT DOS file '%s' loading %s at %04X:%04X, size 0x%X (Error: %u).\n",
112 DosKernelFileName,
113 (Success ? "succeeded" : "failed"),
114 getDI(), 0x0000,
115 ulDosKernelSize,
116 GetLastError());
117
118 /* Close the DOS kernel file */
119 FileClose(hDosKernel);
120
121Quit:
122 if (!Success)
123 {
124 /* We failed everything, stop the VDM */
125 BiosDisplayMessage("Windows NT DOS kernel file '%s' loading failed (Error: %u). The VDM will shut down.\n",
126 DosKernelFileName, GetLastError());
128 return;
129 }
130}
unsigned char BOOLEAN
#define BiosDisplayMessage(Format,...)
Definition: dem.h:34
VOID EmulatorTerminate(VOID)
Definition: emulator.c:503
#define TO_LINEAR(seg, off)
Definition: emulator.h:26
#define REAL_TO_PHYS(ptr)
Definition: emulator.h:37
HANDLE FileOpen(IN PCSTR FileName, OUT PULONG FileSize OPTIONAL)
Definition: utils.c:27
VOID FileClose(IN HANDLE FileHandle)
Definition: utils.c:21
BOOLEAN FileLoadByHandle(IN HANDLE FileHandle, IN PVOID Location, IN ULONG FileSize, OUT PULONG BytesRead)
Definition: utils.c:69
uint32_t ULONG
Definition: typedefs.h:59
USHORT WINAPI getDI(VOID)
Definition: registers.c:434
const char * LPCSTR
Definition: xmlstorage.h:183

Referenced by DosSystemBop().

◆ dempIsFileMatch()

static BOOLEAN dempIsFileMatch ( _Inout_ PWIN32_FIND_DATAA  FindData,
_In_ WORD  AttribMask,
_Out_ PCSTR ShortName 
)
static

Helper for demFileFindFirst() and demFileFindNext(). Returns TRUE if a file matches the DOS attributes and has a 8.3 file name.

Definition at line 1414 of file dem.c.

1418{
1419 /* Convert in place the attributes to DOS format */
1420 FindData->dwFileAttributes = NT_TO_DOS_FA(FindData->dwFileAttributes);
1421
1422 /* Check the attributes */
1423 if ((FindData->dwFileAttributes & (FA_HIDDEN | FA_SYSTEM | FA_DIRECTORY))
1424 & ~AttribMask)
1425 {
1426 return FALSE;
1427 }
1428
1429 /* Check whether the file has a 8.3 file name */
1430 if (*FindData->cAlternateFileName)
1431 {
1432 /* Use the available one */
1433 *ShortName = FindData->cAlternateFileName;
1434 return TRUE;
1435 }
1436 else
1437 {
1438 /*
1439 * Verify whether the original long name is actually a valid
1440 * 8.3 file name. Note that we cannot use GetShortPathName()
1441 * since the latter works on full paths, that we do not always have.
1442 */
1443 BOOLEAN IsNameLegal, SpacesInName;
1444 WCHAR FileNameBufferU[_countof(FindData->cFileName) + 1];
1445 UNICODE_STRING FileNameU;
1447
1448 RtlInitAnsiString(&FileNameA, FindData->cFileName);
1449 RtlInitEmptyUnicodeString(&FileNameU, FileNameBufferU, sizeof(FileNameBufferU));
1451
1452 IsNameLegal = RtlIsNameLegalDOS8Dot3(&FileNameU,
1453 NULL, // (lpOemName ? &AnsiName : NULL),
1454 &SpacesInName);
1455
1456 if (!IsNameLegal || SpacesInName)
1457 {
1458 /* This is an error situation */
1459 DPRINT1("'%.*s' is %s 8.3 filename %s spaces\n",
1460 _countof(FindData->cFileName), FindData->cFileName,
1461 (IsNameLegal ? "a valid" : "an invalid"), (SpacesInName ? "with" : "without"));
1462 }
1463
1464 if (IsNameLegal && !SpacesInName)
1465 {
1466 /* We can use the original name */
1467 *ShortName = FindData->cFileName;
1468 return TRUE;
1469 }
1470 }
1471
1472 DPRINT1("No short 8.3 filename available for '%.*s'\n",
1473 _countof(FindData->cFileName), FindData->cFileName);
1474
1475 return FALSE;
1476}
static const CHAR FileNameA[]
#define FA_SYSTEM
Definition: dem.h:72
#define FA_DIRECTORY
Definition: dem.h:75
#define FA_HIDDEN
Definition: dem.h:71
#define NT_TO_DOS_FA(Attrs)
Convert Win32/NT file attributes to DOS format.
Definition: dem.h:82
BOOLEAN NTAPI RtlIsNameLegalDOS8Dot3(_In_ PUNICODE_STRING Name, _Inout_opt_ POEM_STRING OemName, _Inout_opt_ PBOOLEAN NameContainsSpaces)
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by demFileFindFirst(), and demFileFindNext().

◆ demSetCurrentDirectoryGetDrive()

DWORD WINAPI demSetCurrentDirectoryGetDrive ( IN LPCSTR  CurrentDirectory,
OUT PUCHAR  DriveNumber 
)

Definition at line 1651 of file dem.c.

1653{
1655 return ERROR_SUCCESS;
1656}

◆ DosBootsectorInitialize()

VOID DosBootsectorInitialize ( VOID  )

Definition at line 1089 of file dem.c.

1090{
1091 /* We write the bootsector at 0000:7C00 */
1092 ULONG_PTR StartAddress = (ULONG_PTR)SEG_OFF_TO_PTR(0x0000, 0x7C00);
1093 ULONG_PTR Address = StartAddress;
1094 CHAR DosKernelFileName[] = ""; // No DOS BIOS file name, therefore we will load DOS32
1095
1096 DPRINT("DosBootsectorInitialize\n");
1097
1098 /* Write the "bootsector" */
1100 Address += sizeof(Bootsector1);
1101 RtlCopyMemory((PVOID)Address, DosKernelFileName, sizeof(DosKernelFileName));
1102 Address += sizeof(DosKernelFileName);
1104 Address += sizeof(Bootsector2);
1105
1106 /* Initialize the callback context */
1108 (ULONG_PTR)MEM_ALIGN_UP(0x7C00 + Address - StartAddress, sizeof(WORD)));
1109
1110 /* Register the DOS Loading BOP */
1112}
VOID RegisterBop(BYTE BopCode, EMULATOR_BOP_PROC BopHandler)
Definition: bop.c:29
static VOID WINAPI DosInitialize(LPWORD Stack)
Definition: dem.c:1129
static BYTE Bootsector2[]
Definition: dem.c:1082
static BYTE Bootsector1[]
Definition: dem.c:1076
#define BOP_LOAD_DOS
Definition: dem.h:24
#define ULONG_PTR
Definition: config.h:101
#define MEM_ALIGN_UP(ptr, align)
Definition: emulator.h:24
unsigned short WORD
Definition: ntddk_ex.h:93
static WCHAR Address[46]
Definition: ping.c:68
#define DPRINT
Definition: sndvol32.h:71
VOID InitializeContext(IN PCALLBACK16 Context, IN USHORT Segment, IN USHORT Offset)
Definition: callback.c:60
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by BiosBootstrapLoader().

◆ DosCharPrint()

VOID DosCharPrint ( CHAR  Character)

Definition at line 82 of file dem.c.

83{
85}
VOID DosPrintCharacter(WORD FileHandle, CHAR Character)
Definition: bios.c:152
#define DOS_OUTPUT_HANDLE
Definition: dos.h:43

◆ DosCmdInterpreterBop()

static VOID WINAPI DosCmdInterpreterBop ( LPWORD  Stack)
static

Definition at line 588 of file dem.c.

589{
590 /* Get the Function Number and skip it */
591 BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
592 setIP(getIP() + 1);
593
594 switch (FuncNum)
595 {
596 /* Kill the VDM */
597 case 0x00:
598 {
599 /* Stop the VDM */
601 return;
602 }
603
604 /*
605 * Get a new app to start
606 *
607 * Input
608 * DS:DX : Data block.
609 *
610 * Output
611 * CF : 0: Success; 1: Failure.
612 */
613 case 0x01:
614 {
616 break;
617 }
618
619 /*
620 * Check binary format
621 *
622 * Input
623 * DS:DX : Program to check.
624 *
625 * Output
626 * CF : 0: Success; 1: Failure.
627 * AX : Error code.
628 */
629 case 0x07:
630 {
631 DWORD BinaryType;
632 LPSTR ProgramName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX());
633
634 if (!GetBinaryTypeA(ProgramName, &BinaryType))
635 {
636 /* An error happened, bail out */
637 setCF(1);
639 break;
640 }
641
642 // FIXME: We only support DOS binaries for now...
643 ASSERT(BinaryType == SCS_DOS_BINARY);
644 if (BinaryType != SCS_DOS_BINARY)
645 {
646 /* An error happened, bail out */
647 setCF(1);
649 break;
650 }
651
652 /* Return success: DOS application */
653 setCF(0);
654 break;
655 }
656
657 /*
658 * Start an external command
659 *
660 * Input
661 * DS:SI : Command to start.
662 * ES : Environment block segment.
663 * AL : Current drive number.
664 * AH : 0: Directly start the command;
665 * 1: Use "cmd.exe /c" to start the command.
666 *
667 * Output
668 * CF : 0: Shell-out; 1: Continue.
669 * AL : Error/Exit code.
670 */
671 case 0x08:
672 {
674 break;
675 }
676
677 /*
678 * Start the default 32-bit command interpreter (COMSPEC)
679 *
680 * Input
681 * ES : Environment block segment.
682 * AL : Current drive number.
683 *
684 * Output
685 * CF : 0: Shell-out; 1: Continue.
686 * AL : Error/Exit code.
687 */
688 case 0x0A:
689 {
691 break;
692 }
693
694 /*
695 * Set exit code
696 *
697 * Input
698 * DX : Exit code
699 *
700 * Output
701 * CF : 0: Shell-out; 1: Continue.
702 */
703 case 0x0B:
704 {
706 break;
707 }
708
709 /*
710 * Get start information
711 *
712 * Output
713 * AL : 0 (resp. 1): Started from (resp. without) an existing console.
714 */
715 case 0x10:
716 {
717#ifndef STANDALONE
718 /*
719 * When a new instance of our (internal) COMMAND.COM is started,
720 * we check whether we need to run a 32-bit COMSPEC. This goes by
721 * checking whether we were started in a new console (no parent
722 * console process) or from an existing one.
723 *
724 * However COMMAND.COM can also be started in the case where a
725 * 32-bit process (started by a 16-bit parent) wants to start a new
726 * 16-bit process: to ensure DOS reentry we need to start a new
727 * instance of COMMAND.COM. On Windows the COMMAND.COM is started
728 * just before the 32-bit process (in fact, it is this COMMAND.COM
729 * which starts the 32-bit process via an undocumented command-line
730 * switch '/z', which syntax is:
731 * COMMAND.COM /z\bAPPNAME.EXE
732 * notice the '\b' character inserted in-between. Then COMMAND.COM
733 * issues a BOP_CMD 08h with AH=00h to start the process).
734 *
735 * Instead, we do the reverse, i.e. we start the 32-bit process,
736 * and *only* if needed, i.e. if this process wants to start a
737 * new 16-bit process, we start our COMMAND.COM.
738 *
739 * The problem we then face is that our COMMAND.COM will possibly
740 * want to start a new COMSPEC, however we do not want this.
741 * The chosen solution is to flag this case -- done with the 'Reentry'
742 * boolean -- so that COMMAND.COM will not attempt to start COMSPEC
743 * but instead will directly try to start the 16-bit process.
744 */
745 // setAL(SessionId != 0);
746 setAL((SessionId != 0) && !Reentry);
747 /* Reset 'Reentry' */
748 Reentry = FALSE;
749#else
750 setAL(0);
751#endif
752 break;
753 }
754
755 default:
756 {
757 DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum);
758 // setCF(1); // Disable, otherwise we enter an infinite loop
759 break;
760 }
761 }
762}
static VOID CmdStartProcess(VOID)
Definition: dem.c:290
static VOID CmdSetExitCode(VOID)
Definition: dem.c:505
static BOOLEAN Reentry
Definition: dem.c:248
static VOID CmdStartExternalCommand(VOID)
Definition: dem.c:411
static VOID CmdStartComSpec32(VOID)
Definition: dem.c:465
BOOL WINAPI GetBinaryTypeA(IN LPCSTR lpApplicationName, OUT LPDWORD lpBinaryType)
Definition: vdm.c:1335
#define LOWORD(l)
Definition: pedump.c:82
VOID WINAPI setIP(USHORT)
Definition: registers.c:471
#define SCS_DOS_BINARY
Definition: winbase.h:238
#define ERROR_BAD_EXE_FORMAT
Definition: winerror.h:251

Referenced by DosInitialize().

◆ DosInitialize()

static VOID WINAPI DosInitialize ( LPWORD  Stack)
static

Definition at line 1129 of file dem.c.

1130{
1131 /* Get the DOS BIOS file name (NULL-terminated) */
1132 // FIXME: Isn't it possible to use some DS:SI instead??
1133 LPCSTR DosBiosFileName = (LPCSTR)SEG_OFF_TO_PTR(getCS(), getIP());
1134 setIP(getIP() + (USHORT)strlen(DosBiosFileName) + 1); // Skip it
1135
1136 DPRINT("DosInitialize('%s')\n", DosBiosFileName);
1137
1138 /*
1139 * We succeeded, deregister the DOS Loading BOP
1140 * so that no app will be able to call us back.
1141 */
1143
1144 /* Register the DOS BOPs */
1147
1148 if (DosBiosFileName[0] != '\0')
1149 {
1151 HANDLE hDosBios;
1152 ULONG ulDosBiosSize = 0;
1153
1154 /* Open the DOS BIOS file */
1155 hDosBios = FileOpen(DosBiosFileName, &ulDosBiosSize);
1156 if (hDosBios == NULL) goto Quit;
1157
1158 /* Attempt to load the DOS BIOS into memory */
1159 Success = FileLoadByHandle(hDosBios,
1160 REAL_TO_PHYS(TO_LINEAR(0x0070, 0x0000)),
1161 ulDosBiosSize,
1162 &ulDosBiosSize);
1163
1164 DPRINT1("DOS BIOS file '%s' loading %s at %04X:%04X, size 0x%X (Error: %u).\n",
1165 DosBiosFileName,
1166 (Success ? "succeeded" : "failed"),
1167 0x0070, 0x0000,
1168 ulDosBiosSize,
1169 GetLastError());
1170
1171 /* Close the DOS BIOS file */
1172 FileClose(hDosBios);
1173
1174Quit:
1175 if (!Success)
1176 {
1177 BiosDisplayMessage("DOS BIOS file '%s' loading failed (Error: %u). The VDM will shut down.\n",
1178 DosBiosFileName, GetLastError());
1179 return;
1180 }
1181 }
1182 else
1183 {
1184 /* Load the 16-bit startup code for DOS32 and register its Starting BOP */
1185 RtlCopyMemory(SEG_OFF_TO_PTR(0x0070, 0x0000), Startup, sizeof(Startup));
1186
1187 // This is the equivalent of BOP_LOAD_DOS, function 0x11 "Load the DOS kernel"
1188 // for the Windows NT DOS.
1190 }
1191
1192 /* Position execution pointers for DOS startup and return */
1193 setCS(0x0070);
1194 setIP(0x0000);
1195}
static BYTE Startup[]
Definition: dem.c:1121
static VOID WINAPI DosSystemBop(LPWORD Stack)
Definition: dem.c:132
static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
Definition: dem.c:588
static VOID WINAPI DosStart(LPWORD Stack)
Definition: dem.c:1197
#define BOP_CMD
Definition: dem.h:27
#define BOP_START_DOS
Definition: dem.h:25
#define BOP_DOS
Definition: dem.h:26
VOID WINAPI setCS(USHORT)
Definition: registers.c:487

Referenced by DosBootsectorInitialize().

◆ DosProcessConsoleAttach()

static VOID DosProcessConsoleAttach ( VOID  )
static

Definition at line 228 of file dem.c.

229{
230 /* Attach to the console */
233}
BOOL ConsoleAttach(VOID)
Definition: console.c:398
VOID VidBiosAttachToConsole(VOID)
Definition: vidbios.c:3907

Referenced by DosStart(), and DosStartProcess32().

◆ DosProcessConsoleDetach()

static VOID DosProcessConsoleDetach ( VOID  )
static

Definition at line 235 of file dem.c.

236{
237 /* Detach from the console */
240}
VOID ConsoleDetach(VOID)
Definition: console.c:424
VOID VidBiosDetachFromConsole(VOID)
Definition: vidbios.c:3920

Referenced by DosStartProcess32().

◆ DosShutdown()

BOOLEAN DosShutdown ( BOOLEAN  Immediate)

Definition at line 1331 of file dem.c.

1332{
1333 /*
1334 * Immediate = TRUE: Immediate shutdown;
1335 * FALSE: Delayed shutdown (notification).
1336 */
1337
1338#ifndef STANDALONE
1339 if (Immediate)
1340 {
1341 ExitVDM(FALSE, 0);
1342 return TRUE;
1343 }
1344 else
1345 {
1346// HACK!
1347extern HANDLE VdmTaskEvent; // see emulator.c
1348
1349 /*
1350 * Signal the root COMMAND.COM that it should terminate
1351 * when it checks for a new command.
1352 */
1354
1355 /* If the list is already empty, or just contains only one element, bail out */
1356 // FIXME: Question: if the list has only one element, is it ALWAYS RootCmd ??
1357 // FIXME: The following is hackish.
1361 ReentrancyCount == 0 &&
1363 {
1364 /* Nothing runs, so exit immediately */
1365 ExitVDM(FALSE, 0);
1366 return TRUE;
1367 }
1368
1369 return FALSE;
1370 }
1371#else
1372 UNREFERENCED_PARAMETER(Immediate);
1373 return TRUE;
1374#endif
1375}
#define WAIT_TIMEOUT
Definition: dderror.h:14
static LIST_ENTRY ComSpecInfoList
Definition: dem.c:196
VOID WINAPI ExitVDM(BOOL IsWow, ULONG iWowTask)
Definition: vdm.c:1392
HANDLE VdmTaskEvent
Definition: emulator.c:51
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
LIST_ENTRY Entry
Definition: dem.c:186
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121

Referenced by VdmShutdown().

◆ DosStart()

static VOID WINAPI DosStart ( LPWORD  Stack)
static

Definition at line 1197 of file dem.c.

1198{
1200 DWORD Result;
1201#ifndef STANDALONE
1202 INT i;
1203#endif
1204
1205 DPRINT("DosStart\n");
1206
1207 /*
1208 * We succeeded, deregister the DOS Starting BOP
1209 * so that no app will be able to call us back.
1210 */
1212
1213 /* Initialize the callback context */
1215
1217// Success &= DosKRNLInitialize();
1218 if (!Success)
1219 {
1220 BiosDisplayMessage("DOS32 loading failed (Error: %u). The VDM will shut down.\n", GetLastError());
1222 return;
1223 }
1224
1225 /* Load the mouse driver */
1227
1228#ifndef STANDALONE
1229
1230 /* Parse the command line arguments */
1231 for (i = 1; i < NtVdmArgc; i++)
1232 {
1233 if (wcsncmp(NtVdmArgv[i], L"-i", 2) == 0)
1234 {
1235 /* This is the session ID (hex format) */
1236 SessionId = wcstoul(NtVdmArgv[i] + 2, NULL, 16);
1237 }
1238 }
1239
1240 /* Initialize Win32-VDM environment */
1241 Env = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
1242 if (Env == NULL)
1243 {
1244 DosDisplayMessage("Failed to initialize the global environment (Error: %u). The VDM will shut down.\n", GetLastError());
1246 return;
1247 }
1248
1249 /* Clear the structure */
1251
1252 /* Get the initial information */
1256
1257#else
1258
1259 /* Retrieve the command to start */
1260 if (NtVdmArgc >= 2)
1261 {
1263
1264 if (NtVdmArgc >= 3)
1266 else
1267 strcpy(CmdLine, "");
1268 }
1269 else
1270 {
1271 DosDisplayMessage("Invalid DOS command line\n");
1273 return;
1274 }
1275
1276#endif
1277
1278 /*
1279 * At this point, CS:IP points to the DOS BIOS exit code. If the
1280 * root command interpreter fails to start (or if it exits), DOS
1281 * exits and the VDM terminates.
1282 */
1283
1284 /* Start the root command interpreter */
1285 // TODO: Really interpret the 'SHELL=' line of CONFIG.NT, and use it!
1286
1287 /*
1288 * Prepare the stack for DosStartComSpec:
1289 * push Flags, CS and IP, and an extra WORD.
1290 */
1291 setSP(getSP() - sizeof(WORD));
1293 setSP(getSP() - sizeof(WORD));
1294 *((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = getCS();
1295 setSP(getSP() - sizeof(WORD));
1296 *((LPWORD)SEG_OFF_TO_PTR(getSS(), getSP())) = getIP();
1297 setSP(getSP() - sizeof(WORD));
1298
1300 MAKELONG(getIP(), getCS()),
1301#ifndef STANDALONE
1303#else
1304 NULL
1305#endif
1306 );
1307 if (Result != ERROR_SUCCESS)
1308 {
1309 /* Unprepare the stack for DosStartComSpec */
1310 setSP(getSP() + 4*sizeof(WORD));
1311
1312 DosDisplayMessage("Failed to start the Command Interpreter (Error: %u). The VDM will shut down.\n", Result);
1314 return;
1315 }
1316
1317#ifndef STANDALONE
1320#endif
1321
1322
1323 /* Attach to the console and resume the VM */
1326
1327
1328 return;
1329}
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
static VOID DosProcessConsoleAttach(VOID)
Definition: dem.c:228
static VOID InsertComSpecInfo(PCOMSPEC_INFO ComSpecInfo)
Definition: dem.c:214
static DWORD DosStartComSpec(IN BOOLEAN Permanent, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL, OUT PWORD ComSpecPsp OPTIONAL)
Definition: dem.c:772
#define CP_ACP
Definition: compat.h:109
#define WideCharToMultiByte
Definition: compat.h:111
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
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
BOOLEAN DosMouseInitialize(VOID)
Definition: mouse32.c:1260
INT NtVdmArgc
Definition: ntvdm.c:31
WCHAR ** NtVdmArgv
Definition: ntvdm.c:32
#define STANDALONE
Definition: testlist.c:1
_Check_return_ _CRTIMP int __cdecl wcsncmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
#define VDM_GET_FIRST_COMMAND
Definition: vdm.h:61
WORD ComSpecPsp
Definition: dem.c:188
BOOLEAN DosBIOSInitialize(VOID)
Definition: bios.c:221
#define SYSTEM_ENV_BLOCK
Definition: dos.h:37
#define BIOS_CODE_SEGMENT
Definition: dos.h:30
uint16_t * LPWORD
Definition: typedefs.h:56
int32_t INT
Definition: typedefs.h:58
VOID WINAPI setSP(USHORT)
Definition: registers.c:351
USHORT WINAPI getSP(VOID)
Definition: registers.c:344
ULONG WINAPI getEFLAGS(VOID)
Definition: registers.c:680
USHORT WINAPI getSS(VOID)
Definition: registers.c:494

Referenced by DosInitialize().

◆ DosStartComSpec()

static DWORD DosStartComSpec ( IN BOOLEAN  Permanent,
IN LPCSTR Environment  OPTIONAL,
IN DWORD ReturnAddress  OPTIONAL,
OUT PWORD ComSpecPsp  OPTIONAL 
)
static

Definition at line 772 of file dem.c.

776{
777 /*
778 * BOOLEAN Permanent
779 * TRUE to simulate the /P switch of command.com: starts AUTOEXEC.BAT/NT
780 * and makes the interpreter permanent (cannot exit).
781 */
782
784
785 if (ComSpecPsp) *ComSpecPsp = 0;
786
787 Result =
788#ifndef COMSPEC_FULLY_EXTERNAL
790 CommandCom,
791 sizeof(CommandCom),
792 "COMMAND.COM",
793#else
795#ifndef STANDALONE // FIXME: Those values are hardcoded paths on my local test machines!!
796 "C:\\CMDCMD.COM",
797#else
798 "H:\\DOS_tests\\CMDCMD.COM",
799#endif // STANDALONE
800#endif // COMSPEC_FULLY_EXTERNAL
801 NULL,
802 Permanent ? "/P" : "",
803 Environment ? Environment : "", // FIXME: Default environment!
804 ReturnAddress);
805 if (Result != ERROR_SUCCESS) return Result;
806
807 /* TODO: Read AUTOEXEC.NT/BAT */
808
809 /* Retrieve the PSP of the COMSPEC (current PSP set by DosLoadExecutable) */
810 if (ComSpecPsp) *ComSpecPsp = Sda->CurrentPsp;
811
812 return Result;
813}
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
DWORD DosLoadExecutableInternal(IN DOS_EXEC_TYPE LoadType, IN LPBYTE ExeBuffer, IN DWORD ExeBufferSize, IN LPCSTR ExePath, IN PDOS_EXEC_PARAM_BLOCK Parameters, IN LPCSTR CommandLine OPTIONAL, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL)
Definition: process.c:335
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:705
@ DOS_LOAD_AND_EXECUTE
Definition: process.h:20

Referenced by DosStart(), and DosStartProcess32().

◆ DosStartProcess32()

DWORD DosStartProcess32 ( IN LPCSTR  ExecutablePath,
IN LPCSTR  CommandLine,
IN LPCSTR Environment  OPTIONAL,
IN DWORD ReturnAddress  OPTIONAL,
IN BOOLEAN  StartComSpec 
)

Definition at line 916 of file dem.c.

921{
923 HANDLE CommandThread;
924 DOS_START_PROC32 DosStartProc32;
925#ifndef STANDALONE
928#endif
929
930 DosStartProc32.ExecutablePath = (LPSTR)ExecutablePath;
931 DosStartProc32.CommandLine = (LPSTR)CommandLine;
932 DosStartProc32.Environment = (LPSTR)Environment;
933
934#ifndef STANDALONE
935 DosStartProc32.ComSpecInfo =
936 RtlAllocateHeap(RtlGetProcessHeap(),
938 sizeof(*DosStartProc32.ComSpecInfo));
939 ASSERT(DosStartProc32.ComSpecInfo);
940
941 DosStartProc32.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
942 ASSERT(DosStartProc32.hEvent);
943#endif
944
945 /* Pause the VM and detach from the console */
948
949 /* Start the 32-bit process via another thread */
950 CommandThread = CreateThread(NULL, 0, &CommandThreadProc, &DosStartProc32, 0, NULL);
951 if (CommandThread == NULL)
952 {
953 DisplayMessage(L"FATAL: Failed to create the command processing thread: %d", GetLastError());
955 goto Quit;
956 }
957
958#ifndef STANDALONE
959 /* Close the thread handle */
960 CloseHandle(CommandThread);
961
962 /* Wait for the process to be ready to start */
963 WaitForSingleObject(DosStartProc32.hEvent, INFINITE);
964
965 /* Wait for any potential new DOS app started by the 32-bit process */
967
968Retry:
970 DPRINT1("Calling GetNextVDMCommand 32bit for possible new VDM task...\n");
972 DPRINT1("GetNextVDMCommand 32bit awaited, success = %s, last error = %d\n", Success ? "true" : "false", GetLastError());
973
974 /*
975 * Check whether we were awaited because the 32-bit process was stopped,
976 * or because it started a new DOS application.
977 */
978 if (CommandInfo.CmdLen != 0 || CommandInfo.AppLen != 0 || CommandInfo.PifLen != 0)
979 {
980 DPRINT1("GetNextVDMCommand 32bit, this is for a new VDM task - CmdLen = %d, AppLen = %d, PifLen = %d\n",
982
983 /* Repeat the request */
984 Repeat = TRUE;
985
986 /*
987 * Set 'Reentry' to TRUE or FALSE depending on whether we are going
988 * to reenter with a new COMMAND.COM. See the comment for:
989 * BOP_CMD 0x10 'Get start information'
990 * (dem.c!DosCmdInterpreterBop) for more details.
991 */
992 Reentry = StartComSpec;
993
994 /* If needed, start a new command interpreter to handle the possible incoming DOS commands */
995 if (StartComSpec)
996 {
997 //
998 // DosStartProcess32 was only called by DosCreateProcess, called from INT 21h,
999 // so the caller stack is already prepared for running a new DOS program
1000 // (Flags, CS and IP, and the extra interrupt number, are already pushed).
1001 //
1002 Result = DosStartComSpec(FALSE, Environment, ReturnAddress,
1003 &DosStartProc32.ComSpecInfo->ComSpecPsp);
1004 if (Result != ERROR_SUCCESS)
1005 {
1006 DosDisplayMessage("Failed to start a new Command Interpreter (Error: %u).\n", Result);
1007 goto Quit;
1008 }
1009 }
1010 else
1011 {
1012 /* Retrieve the PSP of the COMSPEC (current PSP set by DosLoadExecutable) */
1013 DosStartProc32.ComSpecInfo->ComSpecPsp = Sda->CurrentPsp;
1015 }
1016
1017 /* Insert the new entry in the list; it will be freed when needed by COMMAND.COM */
1018 InsertComSpecInfo(DosStartProc32.ComSpecInfo);
1019 }
1020 else
1021 {
1022 DPRINT1("GetNextVDMCommand 32bit, 32-bit app stopped\n");
1023
1024 /* Check whether this was our 32-bit app which was killed */
1025 if (!DosStartProc32.ComSpecInfo->Terminated)
1026 {
1027 DPRINT1("Not our 32-bit app, retrying...\n");
1028 goto Retry;
1029 }
1030
1031 Result = DosStartProc32.ComSpecInfo->dwExitCode;
1032
1033 /* Delete the entry */
1034 RtlFreeHeap(RtlGetProcessHeap(), 0, DosStartProc32.ComSpecInfo);
1035 }
1036#else
1037 /* Wait for the thread to finish */
1038 WaitForSingleObject(CommandThread, INFINITE);
1039 GetExitCodeThread(CommandThread, &Result);
1040
1041 /* Close the thread handle */
1042 CloseHandle(CommandThread);
1043
1044 DPRINT1("32-bit app stopped\n");
1045#endif
1046
1047Quit:
1048#ifndef STANDALONE
1049 CloseHandle(DosStartProc32.hEvent);
1050#endif
1051
1052 /* Attach to the console and resume the VM */
1055
1056 return Result;
1057}
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
static DWORD WINAPI CommandThreadProc(LPVOID Parameter)
Definition: dem.c:828
static VOID DosProcessConsoleDetach(VOID)
Definition: dem.c:235
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:541
#define VDM_FLAG_NESTED_TASK
Definition: vdm.h:59
LPSTR ExecutablePath
Definition: dem.c:817
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651

Referenced by CmdStartComSpec32(), CmdStartExternalCommand(), and DosCreateProcess().

◆ DosSystemBop()

static VOID WINAPI DosSystemBop ( LPWORD  Stack)
static

Definition at line 132 of file dem.c.

133{
134 /* Get the Function Number and skip it */
135 BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
136 setIP(getIP() + 1);
137
138 switch (FuncNum)
139 {
140 /* Load the DOS kernel */
141 case 0x11:
142 {
144 break;
145 }
146
147 /* Call 32-bit Driver Strategy Routine */
148 case BOP_DRV_STRATEGY:
149 {
151 break;
152 }
153
154 /* Call 32-bit Driver Interrupt Routine */
156 {
158 break;
159 }
160
161 default:
162 {
163 DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum);
164 // setCF(1); // Disable, otherwise we enter an infinite loop
165 break;
166 }
167 }
168}
static VOID DemLoadNTDOSKernel(VOID)
Definition: dem.c:88
VOID DeviceInterruptBop(VOID)
Definition: device.c:436
VOID DeviceStrategyBop(VOID)
Definition: device.c:430
#define BOP_DRV_INTERRUPT
Definition: device.h:19
#define BOP_DRV_STRATEGY
Definition: device.h:18

Referenced by DosInitialize().

◆ FindComSpecInfoByPsp()

static PCOMSPEC_INFO FindComSpecInfoByPsp ( WORD  Psp)
static

Definition at line 199 of file dem.c.

200{
201 PLIST_ENTRY Pointer;
202 PCOMSPEC_INFO ComSpecInfo;
203
204 for (Pointer = ComSpecInfoList.Flink; Pointer != &ComSpecInfoList; Pointer = Pointer->Flink)
205 {
206 ComSpecInfo = CONTAINING_RECORD(Pointer, COMSPEC_INFO, Entry);
207 if (ComSpecInfo->ComSpecPsp == Psp) return ComSpecInfo;
208 }
209
210 return NULL;
211}
base of all file and directory entries
Definition: entries.h:83
Definition: typedefs.h:120
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by CmdSetExitCode(), and CmdStartProcess().

◆ InsertComSpecInfo()

static VOID InsertComSpecInfo ( PCOMSPEC_INFO  ComSpecInfo)
static

Definition at line 214 of file dem.c.

215{
216 InsertHeadList(&ComSpecInfoList, &ComSpecInfo->Entry);
217}
#define InsertHeadList(ListHead, Entry)

Referenced by DosStart(), and DosStartProcess32().

◆ RemoveComSpecInfo()

static VOID RemoveComSpecInfo ( PCOMSPEC_INFO  ComSpecInfo)
static

Definition at line 220 of file dem.c.

221{
222 RemoveEntryList(&ComSpecInfo->Entry);
223 if (ComSpecInfo != &RootCmd)
224 RtlFreeHeap(RtlGetProcessHeap(), 0, ComSpecInfo);
225}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986

Referenced by CmdSetExitCode(), and CmdStartProcess().

Variable Documentation

◆ AppName

◆ Bootsector1

BYTE Bootsector1[]
static
Initial value:
=
{
}
#define EMULATOR_BOP
Definition: bop.h:16
#define HIBYTE(W)
Definition: jmemdos.c:486

Definition at line 1076 of file dem.c.

Referenced by DosBootsectorInitialize().

◆ Bootsector2

BYTE Bootsector2[]
static
Initial value:
=
{
}
#define BOP_UNSIMULATE
Definition: isvbop.h:31

Definition at line 1082 of file dem.c.

Referenced by DosBootsectorInitialize().

◆ CmdLine

CHAR CmdLine[MAX_PATH] = ""
static

Definition at line 251 of file dem.c.

Referenced by CmdStartComSpec32(), CmdStartExternalCommand(), CmdStartProcess(), and DosStart().

◆ CommandInfo

◆ ComSpecInfoList

LIST_ENTRY ComSpecInfoList = { &ComSpecInfoList, &ComSpecInfoList }
static

Definition at line 196 of file dem.c.

Referenced by DosShutdown(), FindComSpecInfoByPsp(), and InsertComSpecInfo().

◆ CurDirectory

CHAR CurDirectory[MAX_PATH] = ""
static

Definition at line 255 of file dem.c.

Referenced by CmdStartProcess().

◆ Desktop

CHAR Desktop[MAX_PATH] = ""
static

Definition at line 256 of file dem.c.

Referenced by CmdStartProcess().

◆ Env

PVOID Env = NULL
static

Definition at line 259 of file dem.c.

Referenced by CmdStartProcess(), DosStart(), and test_Predefined().

◆ EnvSize

ULONG EnvSize = 256
static

Definition at line 258 of file dem.c.

Referenced by CmdStartProcess(), DosStart(), and test_Predefined().

◆ First

BOOLEAN First = TRUE
static

Definition at line 250 of file dem.c.

Referenced by CmdStartProcess().

◆ PifFile

CHAR PifFile[MAX_PATH] = ""
static

Definition at line 254 of file dem.c.

Referenced by CmdStartProcess().

◆ ReentrancyCount

DWORD ReentrancyCount = 0
static

Definition at line 193 of file dem.c.

Referenced by CommandThreadProc(), and DosShutdown().

◆ Reentry

BOOLEAN Reentry = FALSE
static

Definition at line 248 of file dem.c.

Referenced by DosCmdInterpreterBop(), and DosStartProcess32().

◆ Repeat

◆ RootCmd

COMSPEC_INFO RootCmd
static

Definition at line 192 of file dem.c.

Referenced by CmdSetExitCode(), DosShutdown(), DosStart(), and RemoveComSpecInfo().

◆ SessionId

ULONG SessionId = 0
static

Definition at line 179 of file dem.c.

Referenced by CmdSetExitCode(), CmdStartProcess(), DosCmdInterpreterBop(), and DosStart().

◆ Startup

BYTE Startup[]
static

◆ Title

CHAR Title[MAX_PATH] = ""
static

Definition at line 257 of file dem.c.

Referenced by CmdStartProcess().