ReactOS  0.4.14-dev-608-gd495a4f
process.c File Reference
#include "ntvdm.h"
#include <debug.h>
#include "emulator.h"
#include "cpu/cpu.h"
#include "dos.h"
#include "dos/dem.h"
#include "dosfiles.h"
#include "handle.h"
#include "process.h"
#include "memory.h"
#include "bios/bios.h"
#include "io.h"
#include "hardware/ps2.h"
#include "vddsup.h"
Include dependency graph for process.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static VOID DosInitPsp (IN WORD Segment, IN WORD EnvBlock, IN LPCSTR CommandLine, IN LPCSTR ProgramName)
 
static VOID DosSaveState (VOID)
 
static VOID DosRestoreState (VOID)
 
static WORD DosCopyEnvironmentBlock (IN LPCSTR Environment OPTIONAL, IN LPCSTR ProgramName)
 
VOID DosClonePsp (WORD DestSegment, WORD SourceSegment)
 
VOID DosCreatePsp (WORD Segment, WORD ProgramSize)
 
VOID DosSetProcessContext (WORD Segment)
 
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)
 
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)
 
WORD DosCreateProcess (IN LPCSTR ProgramName, IN PDOS_EXEC_PARAM_BLOCK Parameters, IN DWORD ReturnAddress OPTIONAL)
 
VOID DosTerminateProcess (WORD Psp, BYTE ReturnCode, WORD KeepResident)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file process.c.

Function Documentation

◆ DosClonePsp()

VOID DosClonePsp ( WORD  DestSegment,
WORD  SourceSegment 
)

Definition at line 243 of file process.c.

244 {
245  PDOS_PSP DestPsp = SEGMENT_TO_PSP(DestSegment);
246  PDOS_PSP SourcePsp = SEGMENT_TO_PSP(SourceSegment);
247  LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
248 
249  /* Literally copy the PSP first */
250  RtlCopyMemory(DestPsp, SourcePsp, sizeof(*DestPsp));
251 
252  /* Save the interrupt vectors */
253  DestPsp->TerminateAddress = IntVecTable[0x22];
254  DestPsp->BreakAddress = IntVecTable[0x23];
255  DestPsp->CriticalAddress = IntVecTable[0x24];
256 
257  /* No parent PSP */
258  DestPsp->ParentPsp = 0;
259 
260  /* Set the handle table pointers to the internal handle table */
262  DestPsp->HandleTablePtr = MAKELONG(0x18, DestSegment);
263 
264  /* Copy the parent handle table without referencing the SFT */
266  FAR_POINTER(SourcePsp->HandleTablePtr),
268 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define DEFAULT_JFT_SIZE
Definition: handle.h:13
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
#define MAKELONG(a, b)
Definition: typedefs.h:248
#define FAR_POINTER(x)
Definition: emulator.h:31
WORD HandleTableSize
Definition: process.h:39
DWORD HandleTablePtr
Definition: process.h:40
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
DWORD TerminateAddress
Definition: process.h:32
#define LPDWORD
Definition: nt_native.h:46
WORD ParentPsp
Definition: process.h:35
DWORD BreakAddress
Definition: process.h:33
uint32_t * LPDWORD
Definition: typedefs.h:57
DWORD CriticalAddress
Definition: process.h:34

Referenced by DosInt21h().

◆ DosCopyEnvironmentBlock()

static WORD DosCopyEnvironmentBlock ( IN LPCSTR Environment  OPTIONAL,
IN LPCSTR  ProgramName 
)
static

Definition at line 173 of file process.c.

175 {
176  PCHAR Ptr, DestBuffer = NULL;
177  SIZE_T TotalSize = 0;
178  WORD DestSegment;
179 
180  /* If we have an environment strings list, compute its size */
181  if (Environment)
182  {
183  /* Calculate the size of the environment block */
184  Ptr = (PCHAR)Environment;
185  while (*Ptr) Ptr += strlen(Ptr) + 1;
186  TotalSize = (ULONG_PTR)Ptr - (ULONG_PTR)Environment;
187  }
188  else
189  {
190  /* Empty environment string */
191  TotalSize = 1;
192  }
193  /* Add the final environment block NULL-terminator */
194  TotalSize++;
195 
196  /* Add the two bytes for the program name tag */
197  TotalSize += 2;
198 
199  /* Add the string buffer size */
200  TotalSize += strlen(ProgramName) + 1;
201 
202  /* Allocate the memory for the environment block */
203  DestSegment = DosAllocateMemory((WORD)((TotalSize + 0x0F) >> 4), NULL);
204  if (!DestSegment) return 0;
205 
206  DestBuffer = (PCHAR)SEG_OFF_TO_PTR(DestSegment, 0);
207 
208  /* If we have an environment strings list, copy it */
209  if (Environment)
210  {
211  Ptr = (PCHAR)Environment;
212  while (*Ptr)
213  {
214  /* Copy the string and NULL-terminate it */
215  strcpy(DestBuffer, Ptr);
216  DestBuffer += strlen(Ptr);
217  *(DestBuffer++) = '\0';
218 
219  /* Move to the next string */
220  Ptr += strlen(Ptr) + 1;
221  }
222  }
223  else
224  {
225  /* Empty environment string */
226  *(DestBuffer++) = '\0';
227  }
228  /* NULL-terminate the environment block */
229  *(DestBuffer++) = '\0';
230 
231  /* Store the special program name tag */
232  *(DestBuffer++) = LOBYTE(DOS_PROGRAM_NAME_TAG);
233  *(DestBuffer++) = HIBYTE(DOS_PROGRAM_NAME_TAG);
234 
235  /* Copy the program name after the environment block */
236  strcpy(DestBuffer, ProgramName);
237 
238  return DestSegment;
239 }
signed char * PCHAR
Definition: retypes.h:7
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:45
#define LOBYTE(W)
Definition: jmemdos.c:487
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
#define HIBYTE(W)
Definition: jmemdos.c:486
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
uint32_t ULONG_PTR
Definition: typedefs.h:63
smooth NULL
Definition: ftsmooth.c:416
WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable)
Definition: memory.c:136
#define PCHAR
Definition: match.c:90
#define DOS_PROGRAM_NAME_TAG
Definition: process.h:14
unsigned short WORD
Definition: ntddk_ex.h:93
ULONG_PTR SIZE_T
Definition: typedefs.h:78
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define ULONG_PTR
Definition: config.h:101

Referenced by DosLoadExecutableInternal().

◆ DosCreateProcess()

WORD DosCreateProcess ( IN LPCSTR  ProgramName,
IN PDOS_EXEC_PARAM_BLOCK  Parameters,
IN DWORD ReturnAddress  OPTIONAL 
)

Definition at line 783 of file process.c.

786 {
788  DWORD BinaryType;
789 
790  /* Get the binary type */
791  if (!GetBinaryTypeA(ProgramName, &BinaryType)) return GetLastError();
792 
793  /* Check the type of the program */
794  switch (BinaryType)
795  {
796  /* Those are handled by NTVDM */
797  case SCS_WOW_BINARY:
798  {
799  DisplayMessage(L"Trying to load '%S'.\n"
800  L"WOW16 applications are not supported internally by NTVDM at the moment.\n"
801  L"Press 'OK' to continue.",
802  ProgramName);
803  // Fall through
804  }
805  case SCS_DOS_BINARY:
806  {
807  /* Load the executable */
809  ProgramName,
810  Parameters,
811  NULL,
812  NULL,
813  ReturnAddress);
814  if (Result != ERROR_SUCCESS)
815  {
816  DisplayMessage(L"Could not load '%S'. Error: %u", ProgramName, Result);
817  }
818 
819  break;
820  }
821 
822  /* Not handled by NTVDM */
823  default:
824  {
827  LPSTR CmdLinePtr;
828  ULONG CmdLineSize;
829 
830  /* Did the caller specify an environment segment? */
831  if (Parameters->Environment)
832  {
833  /* Yes, use it instead of the parent one */
834  Environment = (LPSTR)SEG_OFF_TO_PTR(Parameters->Environment, 0);
835  }
836 
837  /*
838  * Convert the DOS command line to Win32-compatible format, by concatenating
839  * the program name with the converted command line.
840  * Format of the DOS command line: 1 byte for size; 127 bytes for contents.
841  */
842  CmdLinePtr = CmdLine;
843  strncpy(CmdLinePtr, ProgramName, MAX_PATH); // Concatenate the program name
844  CmdLinePtr += strlen(CmdLinePtr);
845  *CmdLinePtr++ = ' '; // Add separating space
846 
847  CmdLineSize = min(*(PBYTE)FAR_POINTER(Parameters->CommandLine), DOS_CMDLINE_LENGTH);
848  RtlCopyMemory(CmdLinePtr,
849  (LPSTR)FAR_POINTER(Parameters->CommandLine) + 1,
850  CmdLineSize);
851  /* NULL-terminate it */
852  CmdLinePtr[CmdLineSize] = '\0';
853 
854  /* Remove any trailing return carriage character and NULL-terminate the command line */
855  while (*CmdLinePtr && *CmdLinePtr != '\r' && *CmdLinePtr != '\n') CmdLinePtr++;
856  *CmdLinePtr = '\0';
857 
858  Result = DosStartProcess32(ProgramName, CmdLine,
859  Environment, ReturnAddress,
860  TRUE);
861  if (Result != ERROR_SUCCESS)
862  {
863  DisplayMessage(L"Could not load 32-bit '%S'. Error: %u", ProgramName, Result);
864  }
865 
866  break;
867  }
868  }
869 
870  return Result;
871 }
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:45
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define ERROR_SUCCESS
Definition: deptool.c:10
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
char CHAR
Definition: xmlstorage.h:175
#define DOS_CMDLINE_LENGTH
Definition: process.h:13
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
char * LPSTR
Definition: xmlstorage.h:182
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
#define SCS_DOS_BINARY
Definition: winbase.h:235
#define SCS_WOW_BINARY
Definition: winbase.h:239
smooth NULL
Definition: ftsmooth.c:416
_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
#define FAR_POINTER(x)
Definition: emulator.h:31
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
CHAR CmdLine[MAX_PATH]
Definition: mach.c:34
BOOL WINAPI GetBinaryTypeA(IN LPCSTR lpApplicationName, OUT LPDWORD lpBinaryType)
Definition: vdm.c:1327
_In_ PPCI_DEVICE_PRESENCE_PARAMETERS Parameters
Definition: iotypes.h:872
static const WCHAR L[]
Definition: oid.c:1250
DWORD DosStartProcess32(IN LPCSTR ExecutablePath, IN LPCSTR CommandLine, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL, IN BOOLEAN StartComSpec)
Definition: dem.c:916
#define min(a, b)
Definition: monoChain.cc:55
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
unsigned int ULONG
Definition: retypes.h:1
void DisplayMessage(BOOL bConsole, BOOL bSilent, LPCTSTR lpMessage, LPCTSTR lpTitle, UINT uType)
Definition: regsvr32.c:239
BYTE * PBYTE
Definition: pedump.c:66
static LPSTR
Definition: process.c:74

Referenced by DosInt21h().

◆ DosCreatePsp()

VOID DosCreatePsp ( WORD  Segment,
WORD  ProgramSize 
)

Definition at line 270 of file process.c.

271 {
272  PDOS_PSP PspBlock = SEGMENT_TO_PSP(Segment);
273  LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
274 
275  RtlZeroMemory(PspBlock, sizeof(*PspBlock));
276 
277  /* Set the exit interrupt */
278  PspBlock->Exit[0] = 0xCD; // int 0x20
279  PspBlock->Exit[1] = 0x20;
280 
281  /* Set the number of the last paragraph */
282  PspBlock->LastParagraph = Segment + ProgramSize;
283 
284  /* Save the interrupt vectors */
285  PspBlock->TerminateAddress = IntVecTable[0x22];
286  PspBlock->BreakAddress = IntVecTable[0x23];
287  PspBlock->CriticalAddress = IntVecTable[0x24];
288 
289  /* Set the parent PSP */
290  PspBlock->ParentPsp = Sda->CurrentPsp;
291 
292  if (Sda->CurrentPsp != SYSTEM_PSP)
293  {
294  /* Link to the parent's environment block */
295  PspBlock->EnvBlock = SEGMENT_TO_PSP(Sda->CurrentPsp)->EnvBlock;
296  }
297 /*
298  else
299  {
300  PspBlock->EnvBlock = SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0);
301  }
302 */
303 
304  /* Copy the parent handle table */
305  DosCopyHandleTable(PspBlock->HandleTable);
306 
307  /* Set the handle table pointers to the internal handle table */
308  PspBlock->HandleTableSize = DEFAULT_JFT_SIZE;
309  PspBlock->HandleTablePtr = MAKELONG(0x18, Segment);
310 
311  /* Set the DOS version */
312  // FIXME: This is here that SETVER stuff enters into action!
313  PspBlock->DosVersion = DosData->DosVersion;
314 
315  /* Set the far call opcodes */
316  PspBlock->FarCall[0] = 0xCD; // int 0x21
317  PspBlock->FarCall[1] = 0x21;
318  PspBlock->FarCall[2] = 0xCB; // retf
319 }
WORD CurrentPsp
Definition: dos.h:156
#define DEFAULT_JFT_SIZE
Definition: handle.h:13
BYTE HandleTable[20]
Definition: process.h:36
PDOS_DATA DosData
Definition: dos.c:45
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
WORD LastParagraph
Definition: process.h:30
#define MAKELONG(a, b)
Definition: typedefs.h:248
VOID DosCopyHandleTable(LPBYTE DestinationTable)
Definition: handle.c:27
WORD HandleTableSize
Definition: process.h:39
_Inout_ PVOID Segment
Definition: exfuncs.h:893
DWORD HandleTablePtr
Definition: process.h:40
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
BYTE Exit[2]
Definition: process.h:29
DWORD TerminateAddress
Definition: process.h:32
#define LPDWORD
Definition: nt_native.h:46
WORD ParentPsp
Definition: process.h:35
PDOS_SDA Sda
Definition: dos.c:48
#define SYSTEM_PSP
Definition: dos.h:39
DWORD BreakAddress
Definition: process.h:33
BYTE FarCall[3]
Definition: process.h:45
uint32_t * LPDWORD
Definition: typedefs.h:57
WORD DosVersion
Definition: process.h:43
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
DWORD CriticalAddress
Definition: process.h:34
WORD DosVersion
Definition: dos.h:246
WORD EnvBlock
Definition: process.h:37

Referenced by DosInt21h(), and DosLoadExecutableInternal().

◆ DosInitPsp()

static VOID DosInitPsp ( IN WORD  Segment,
IN WORD  EnvBlock,
IN LPCSTR  CommandLine,
IN LPCSTR  ProgramName 
)
static

Definition at line 36 of file process.c.

40 {
41  PDOS_PSP PspBlock = SEGMENT_TO_PSP(Segment);
43  LPCSTR PspName;
44  USHORT i;
45 
46  /* Link the environment block */
47  PspBlock->EnvBlock = EnvBlock;
48 
49  /*
50  * Copy the command line.
51  * Format of the CommandLine parameter: 1 byte for size; 127 bytes for contents.
52  */
53  PspBlock->CommandLineSize = min(*(PBYTE)CommandLine, DOS_CMDLINE_LENGTH);
54  CommandLine++;
55  RtlCopyMemory(PspBlock->CommandLine, CommandLine, DOS_CMDLINE_LENGTH);
56 
57  /*
58  * Initialize the owner name of the MCB of the PSP.
59  */
60 
61  /* Find the start of the file name, skipping all the path elements */
62  PspName = ProgramName;
63  while (*ProgramName)
64  {
65  switch (*ProgramName++)
66  {
67  /* Path delimiter, skip it */
68  case ':': case '\\': case '/':
69  PspName = ProgramName;
70  break;
71  }
72  }
73  /* Copy the file name up to the extension... */
74  for (i = 0; i < sizeof(Mcb->Name) && PspName[i] != '.' && PspName[i] != '\0'; ++i)
75  {
76  Mcb->Name[i] = RtlUpperChar(PspName[i]);
77  }
78  /* ... and NULL-terminate if needed */
79  if (i < sizeof(Mcb->Name)) Mcb->Name[i] = '\0';
80 
81  // FIXME: Initialize the FCBs
82 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define DOS_CMDLINE_LENGTH
Definition: process.h:13
BYTE CommandLineSize
Definition: process.h:48
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
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
CHAR CommandLine[DOS_CMDLINE_LENGTH]
Definition: process.h:49
const char * LPCSTR
Definition: xmlstorage.h:183
_Inout_ PVOID Segment
Definition: exfuncs.h:893
NTSYSAPI CHAR NTAPI RtlUpperChar(CHAR Character)
unsigned short USHORT
Definition: pedump.c:61
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334
#define min(a, b)
Definition: monoChain.cc:55
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15
BYTE * PBYTE
Definition: pedump.c:66
WORD EnvBlock
Definition: process.h:37

Referenced by DosLoadExecutableInternal().

◆ DosLoadExecutable()

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 at line 695 of file process.c.

701 {
703  HANDLE FileHandle = INVALID_HANDLE_VALUE, FileMapping = NULL;
704  DWORD FileSize;
705  LPBYTE Address = NULL;
706  CHAR FullPath[MAX_PATH];
707  CHAR ShortFullPath[MAX_PATH];
708 
709  DPRINT1("DosLoadExecutable(%d, '%s', 0x%p, 0x%p, 0x%p)\n",
710  LoadType, ExecutablePath, Parameters, CommandLine, Environment);
711 
712  /* Try to get the full path to the executable */
713  if (GetFullPathNameA(ExecutablePath, sizeof(FullPath), FullPath, NULL))
714  {
715  /* Get the corresponding short path */
716  if (GetShortPathNameA(FullPath, ShortFullPath, sizeof(ShortFullPath)))
717  {
718  /* Use the shortened full path from now on */
719  ExecutablePath = ShortFullPath;
720  }
721  }
722 
723  /* Open a handle to the executable */
724  FileHandle = CreateFileA(ExecutablePath,
725  GENERIC_READ,
727  NULL,
730  NULL);
732  {
733  Result = GetLastError();
734  goto Cleanup;
735  }
736 
737  /* Get the file size */
739 
740  /* Create a mapping object for the file */
741  FileMapping = CreateFileMapping(FileHandle,
742  NULL,
744  0,
745  0,
746  NULL);
747  if (FileMapping == NULL)
748  {
749  Result = GetLastError();
750  goto Cleanup;
751  }
752 
753  /* Map the file into memory */
754  Address = (LPBYTE)MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 0);
755  if (Address == NULL)
756  {
757  Result = GetLastError();
758  goto Cleanup;
759  }
760 
762  Address,
763  FileSize,
764  ExecutablePath,
765  Parameters,
766  CommandLine,
767  Environment,
768  ReturnAddress);
769 
770 Cleanup:
771  /* Unmap the file*/
773 
774  /* Close the file mapping object */
775  if (FileMapping != NULL) CloseHandle(FileMapping);
776 
777  /* Close the file handle */
779 
780  return Result;
781 }
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:45
#define CloseHandle
Definition: compat.h:406
#define ERROR_SUCCESS
Definition: deptool.c:10
#define MapViewOfFile
Definition: compat.h:410
char CHAR
Definition: xmlstorage.h:175
#define CreateFileMapping
Definition: winbase.h:3584
#define INVALID_HANDLE_VALUE
Definition: compat.h:399
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define FILE_SHARE_READ
Definition: compat.h:125
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:992
HANDLE FileHandle
Definition: stats.c:38
unsigned char * LPBYTE
Definition: typedefs.h:52
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
_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
#define FILE_MAP_READ
Definition: compat.h:435
#define OPEN_EXISTING
Definition: compat.h:434
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
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:481
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
_In_ PPCI_DEVICE_PRESENCE_PARAMETERS Parameters
Definition: iotypes.h:872
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
#define GENERIC_READ
Definition: compat.h:124
static const WCHAR Cleanup[]
Definition: register.c:80
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:327
#define PAGE_READONLY
Definition: compat.h:127
#define DPRINT1
Definition: precomp.h:8
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:407
#define UnmapViewOfFile
Definition: compat.h:411

Referenced by DosCreateProcess(), DosInt21h(), and DosStartComSpec().

◆ DosLoadExecutableInternal()

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 at line 327 of file process.c.

335 {
337  WORD Segment = 0;
338  WORD EnvBlock = 0;
339  WORD ExeSignature;
340  WORD LoadSegment;
341  WORD MaxAllocSize;
342 
343  WORD FinalSS, FinalSP;
344  WORD FinalCS, FinalIP;
345 
346  /* Buffer for command line conversion: 1 byte for size; 127 bytes for contents */
347  CHAR CmdLineBuffer[1 + DOS_CMDLINE_LENGTH];
348 
349  DPRINT1("DosLoadExecutableInternal(%d, 0x%p, '%s', 0x%p, 0x%p, 0x%p)\n",
350  LoadType, ExeBuffer, ExePath, Parameters, CommandLine, Environment);
351 
352  if (LoadType != DOS_LOAD_OVERLAY)
353  {
354  /* If an optional Win32 command line is given... */
355  if (CommandLine)
356  {
357  /* ... convert it into DOS format */
358  BYTE CmdLineLen;
359 
360  PBYTE CmdLineSize = (PBYTE)CmdLineBuffer;
361  LPSTR CmdLineStart = CmdLineBuffer + 1;
362  LPSTR CmdLinePtr = CmdLineStart;
363 
364  // For debugging purposes
365  RtlFillMemory(CmdLineBuffer, sizeof(CmdLineBuffer), 0xFF);
366 
367  /*
368  * Set the command line: it is either an empty command line or has
369  * the format: " foo bar ..." (with at least one leading whitespace),
370  * and is then always followed by '\r' (and optionally by '\n').
371  */
372  CmdLineLen = (BYTE)strlen(CommandLine);
373  *CmdLineSize = 0;
374 
375  /*
376  * Add the leading space if the command line is not empty
377  * and doesn't already start with some whitespace...
378  */
379  if (*CommandLine && *CommandLine != '\r' && *CommandLine != '\n' &&
380  *CommandLine != ' ' && *CommandLine != '\t')
381  {
382  (*CmdLineSize)++;
383  *CmdLinePtr++ = ' ';
384  }
385 
386  /* Compute the number of characters we need to copy from the original command line */
387  CmdLineLen = min(CmdLineLen, DOS_CMDLINE_LENGTH - *CmdLineSize);
388 
389  /* The trailing '\r' or '\n' do not count in the PSP command line size parameter */
390  while (CmdLineLen && (CommandLine[CmdLineLen - 1] == '\r' || CommandLine[CmdLineLen - 1] == '\n'))
391  {
392  CmdLineLen--;
393  }
394 
395  /* Finally, set everything up */
396  *CmdLineSize += CmdLineLen;
397  RtlCopyMemory(CmdLinePtr, CommandLine, CmdLineLen);
398  CmdLineStart[*CmdLineSize] = '\r';
399 
400  /* Finally make the pointer point to the static buffer */
401  CommandLine = CmdLineBuffer;
402  }
403  else
404  {
405  /*
406  * ... otherwise, get the one from the parameter block.
407  * Format of the command line: 1 byte for size; 127 bytes for contents.
408  */
410  CommandLine = (LPCSTR)FAR_POINTER(Parameters->CommandLine);
411  }
412 
413  /* If no optional environment is given... */
414  if (Environment == NULL)
415  {
417  /* ... get the one from the parameter block (if not NULL)... */
418  if (Parameters->Environment)
419  Environment = (LPCSTR)SEG_OFF_TO_PTR(Parameters->Environment, 0);
420  /* ... or the one from the parent (otherwise) */
421  else
423  }
424 
425  /* Copy the environment block to DOS memory */
426  EnvBlock = DosCopyEnvironmentBlock(Environment, ExePath);
427  if (EnvBlock == 0)
428  {
430  goto Cleanup;
431  }
432  }
433 
434  /*
435  * Check if this is an EXE file or a COM file by looking
436  * at the MZ signature:
437  * 0x4D5A 'MZ': old signature (stored as 0x5A, 0x4D)
438  * 0x5A4D 'ZM': new signature (stored as 0x4D, 0x5A)
439  */
440  ExeSignature = *(PWORD)ExeBuffer;
441  if (ExeSignature == 'MZ' || ExeSignature == 'ZM')
442  {
443  /* EXE file */
445  DWORD BaseSize;
446  PDWORD RelocationTable;
447  PWORD RelocWord;
448  WORD RelocFactor;
449  WORD i;
450 
451  /* Get the MZ header */
452  Header = (PIMAGE_DOS_HEADER)ExeBuffer;
453 
454  /* Get the base size of the file, in paragraphs (rounded up) */
455 #if 0 // Normally this is not needed to check for the number of bytes in the last pages.
456  BaseSize = ((((Header->e_cp - (Header->e_cblp != 0)) * 512) + Header->e_cblp) >> 4)
457  - Header->e_cparhdr;
458 #else
459  // e_cp is the number of 512-byte blocks. 512 == (1 << 9)
460  // so this corresponds to (1 << 5) number of paragraphs.
461  //
462  // For DOS compatibility we need to truncate BaseSize to a WORD value.
463  // This fact is exploited by some EXEs which are bigger than 1 Mb while
464  // being able to load on DOS, the main EXE code loads the remaining data.
465 
466  BaseSize = ((Header->e_cp << 5) - Header->e_cparhdr) & 0xFFFF;
467 #endif
468 
469  if (LoadType != DOS_LOAD_OVERLAY)
470  {
471  BOOLEAN LoadHigh = FALSE;
472  DWORD TotalSize;
473 
474  /* Find the maximum amount of memory that can be allocated */
475  DosAllocateMemory(0xFFFF, &MaxAllocSize);
476 
477  /* Compute the total needed size, in paragraphs */
478  TotalSize = BaseSize + (sizeof(DOS_PSP) >> 4);
479 
480  /* We must have the required minimum amount of memory. If not, bail out. */
481  if (MaxAllocSize < TotalSize + Header->e_minalloc)
482  {
484  goto Cleanup;
485  }
486 
487  /* Check if the program should be loaded high */
488  if (Header->e_minalloc == 0 && Header->e_maxalloc == 0)
489  {
490  /* Yes it should. Use all the available memory. */
491  LoadHigh = TRUE;
492  TotalSize = MaxAllocSize;
493  }
494  else
495  {
496  /* Compute the maximum memory size that can be allocated */
497  if (Header->e_maxalloc != 0)
498  TotalSize = min(TotalSize + Header->e_maxalloc, MaxAllocSize);
499  else
500  TotalSize = MaxAllocSize; // Use all the available memory
501  }
502 
503  /* Try to allocate that much memory */
504  Segment = DosAllocateMemory((WORD)TotalSize, NULL);
505  if (Segment == 0)
506  {
508  goto Cleanup;
509  }
510 
511  /* The process owns its memory */
513  DosChangeMemoryOwner(EnvBlock, Segment);
514 
515  /* Set INT 22h to the return address */
516  ((PULONG)BaseAddress)[0x22] = ReturnAddress;
517 
518  /* Create the PSP and initialize it */
519  DosCreatePsp(Segment, (WORD)TotalSize);
520  DosInitPsp(Segment, EnvBlock, CommandLine, ExePath);
521 
522  /* Calculate the segment where the program should be loaded */
523  if (!LoadHigh)
524  LoadSegment = Segment + (sizeof(DOS_PSP) >> 4);
525  else
526  LoadSegment = Segment + TotalSize - BaseSize;
527 
528  RelocFactor = LoadSegment;
529  }
530  else
531  {
533  LoadSegment = Parameters->Overlay.Segment;
534  RelocFactor = Parameters->Overlay.RelocationFactor;
535  }
536 
537  /* Copy the program to the code segment */
538  RtlCopyMemory(SEG_OFF_TO_PTR(LoadSegment, 0),
539  ExeBuffer + (Header->e_cparhdr << 4),
540  min(ExeBufferSize - (Header->e_cparhdr << 4), BaseSize << 4));
541 
542  /* Get the relocation table */
543  RelocationTable = (PDWORD)(ExeBuffer + Header->e_lfarlc);
544 
545  /* Perform relocations */
546  for (i = 0; i < Header->e_crlc; i++)
547  {
548  /* Get a pointer to the word that needs to be patched */
549  RelocWord = (PWORD)SEG_OFF_TO_PTR(LoadSegment + HIWORD(RelocationTable[i]),
550  LOWORD(RelocationTable[i]));
551 
552  /* Add the relocation factor to it */
553  *RelocWord += RelocFactor;
554  }
555 
556  /* Set the stack to the location from the header */
557  FinalSS = LoadSegment + Header->e_ss;
558  FinalSP = Header->e_sp;
559 
560  /* Set the code segment/pointer */
561  FinalCS = LoadSegment + Header->e_cs;
562  FinalIP = Header->e_ip;
563  }
564  else
565  {
566  /* COM file */
567 
568  if (LoadType != DOS_LOAD_OVERLAY)
569  {
570  /* Find the maximum amount of memory that can be allocated */
571  DosAllocateMemory(0xFFFF, &MaxAllocSize);
572 
573  /* Make sure it's enough for the whole program and the PSP */
574  if (((DWORD)MaxAllocSize << 4) < (ExeBufferSize + sizeof(DOS_PSP)))
575  {
577  goto Cleanup;
578  }
579 
580  /* Allocate all of it */
581  Segment = DosAllocateMemory(MaxAllocSize, NULL);
582  if (Segment == 0)
583  {
585  goto Cleanup;
586  }
587 
588  /* The process owns its memory */
590  DosChangeMemoryOwner(EnvBlock, Segment);
591 
592  /* Set INT 22h to the return address */
593  ((PULONG)BaseAddress)[0x22] = ReturnAddress;
594 
595  /* Create the PSP and initialize it */
596  DosCreatePsp(Segment, MaxAllocSize);
597  DosInitPsp(Segment, EnvBlock, CommandLine, ExePath);
598 
599  /* Calculate the segment where the program should be loaded */
600  LoadSegment = Segment + (sizeof(DOS_PSP) >> 4);
601  }
602  else
603  {
605  LoadSegment = Parameters->Overlay.Segment;
606  }
607 
608  /* Copy the program to the code segment */
609  RtlCopyMemory(SEG_OFF_TO_PTR(LoadSegment, 0),
610  ExeBuffer, ExeBufferSize);
611 
612  /* Set the stack to the last word of the segment */
613  FinalSS = Segment;
614  FinalSP = 0xFFFE;
615 
616  /*
617  * Set the value on the stack to 0x0000, so that a near return
618  * jumps to PSP:0000 which has the exit code.
619  */
620  *((LPWORD)SEG_OFF_TO_PTR(Segment, 0xFFFE)) = 0x0000;
621 
622  /* Set the code segment/pointer */
623  FinalCS = Segment;
624  FinalIP = 0x0100;
625  }
626 
627  if (LoadType == DOS_LOAD_AND_EXECUTE)
628  {
629  /* Save the program state */
630  if (Sda->CurrentPsp != SYSTEM_PSP)
631  {
632  /* Push the task state */
633  DosSaveState();
634 
635  DPRINT1("Sda->CurrentPsp = 0x%04x; Old LastStack = 0x%08x, New LastStack = 0x%08x\n",
637 
638  /* Update the last stack in the PSP */
639  SEGMENT_TO_PSP(Sda->CurrentPsp)->LastStack = MAKELONG(getSP(), getSS());
640  }
641 
642  /* Set the initial segment registers */
643  setDS(Segment);
644  setES(Segment);
645 
646  /* Set the stack */
647  setSS(FinalSS);
648  setSP(FinalSP);
649 
650  /*
651  * Set the other registers as in real DOS: some demos expect them so!
652  * See http://www.fysnet.net/yourhelp.htm
653  * and http://www.beroset.com/asm/showregs.asm
654  */
655  setDX(Segment);
656  setDI(FinalSP);
657  setBP(0x091E); // DOS base stack pointer relic value. In MS-DOS 5.0 and Windows' NTVDM it's 0x091C. This is in fact the old SP value inside DosData disk stack.
658  setSI(FinalIP);
659 
660  setAX(0/*0xFFFF*/); // FIXME: fcbcode
661  setBX(0/*0xFFFF*/); // FIXME: fcbcode
662  setCX(0x00FF);
663 
664  /*
665  * Keep critical flags, clear test flags (OF, SF, ZF, AF, PF, CF)
666  * and explicitely set the interrupt flag.
667  */
668  setEFLAGS((getEFLAGS() & ~0x08D5) | 0x0200);
669 
670  /* Notify VDDs of process execution */
672 
673  /* Execute */
675  CpuExecute(FinalCS, FinalIP);
676  }
677  else if (LoadType == DOS_LOAD_ONLY)
678  {
680  Parameters->StackLocation = MAKELONG(FinalSP, FinalSS);
681  Parameters->EntryPoint = MAKELONG(FinalIP, FinalCS);
682  }
683 
684 Cleanup:
685  if (Result != ERROR_SUCCESS)
686  {
687  /* It was not successful, cleanup the DOS memory */
688  if (EnvBlock) DosFreeMemory(EnvBlock);
690  }
691 
692  return Result;
693 }
WORD LastErrorCode
Definition: dos.h:151
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:45
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)
#define ERROR_SUCCESS
Definition: deptool.c:10
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
VOID WINAPI setAX(USHORT)
Definition: registers.c:121
char CHAR
Definition: xmlstorage.h:175
VOID WINAPI setDS(USHORT)
Definition: registers.c:515
BOOLEAN DosFreeMemory(WORD BlockData)
Definition: memory.c:418
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define DOS_CMDLINE_LENGTH
Definition: process.h:13
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
char * LPSTR
Definition: xmlstorage.h:182
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
VOID WINAPI setES(USHORT)
Definition: registers.c:529
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
Definition: Header.h:8
ULONG WINAPI getEFLAGS(VOID)
Definition: registers.c:680
VOID VDDCreateUserHook(USHORT DosPDB)
Definition: vddsup.c:453
VOID WINAPI setSS(USHORT)
Definition: registers.c:501
VOID WINAPI setSI(USHORT)
Definition: registers.c:411
#define MAKELONG(a, b)
Definition: typedefs.h:248
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
struct _IMAGE_DOS_HEADER * PIMAGE_DOS_HEADER
_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
#define FAR_POINTER(x)
Definition: emulator.h:31
VOID DosSetProcessContext(WORD Segment)
Definition: process.c:321
const char * LPCSTR
Definition: xmlstorage.h:183
static PDWORD
Definition: process.c:68
static VOID DosSaveState(VOID)
Definition: process.c:84
_Inout_ PVOID Segment
Definition: exfuncs.h:893
static WORD DosCopyEnvironmentBlock(IN LPCSTR Environment OPTIONAL, IN LPCSTR ProgramName)
Definition: process.c:173
WORD * PWORD
Definition: pedump.c:67
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
struct _DOS_PSP DOS_PSP
static PULONG
Definition: process.c:83
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
static VOID DosInitPsp(IN WORD Segment, IN WORD EnvBlock, IN LPCSTR CommandLine, IN LPCSTR ProgramName)
Definition: process.c:36
VOID WINAPI setBP(USHORT)
Definition: registers.c:381
VOID DosChangeMemoryOwner(WORD Segment, WORD NewOwner)
Definition: memory.c:532
VOID WINAPI setDX(USHORT)
Definition: registers.c:293
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID DosCreatePsp(WORD Segment, WORD ProgramSize)
Definition: process.c:270
VOID CpuExecute(WORD Segment, WORD Offset)
Definition: cpu.c:102
_In_ PPCI_DEVICE_PRESENCE_PARAMETERS Parameters
Definition: iotypes.h:872
unsigned char BYTE
Definition: mem.h:68
PDOS_SDA Sda
Definition: dos.c:48
VOID WINAPI setEFLAGS(ULONG)
Definition: registers.c:687
static const WCHAR Cleanup[]
Definition: register.c:80
VOID WINAPI setBX(USHORT)
Definition: registers.c:177
uint16_t * LPWORD
Definition: typedefs.h:54
VOID WINAPI setDI(USHORT)
Definition: registers.c:441
#define SYSTEM_PSP
Definition: dos.h:39
#define min(a, b)
Definition: monoChain.cc:55
DWORD * PDWORD
Definition: pedump.c:68
VOID WINAPI setCX(USHORT)
Definition: registers.c:235
#define DPRINT1
Definition: precomp.h:8
#define HIWORD(l)
Definition: typedefs.h:246
USHORT WINAPI getSP(VOID)
Definition: registers.c:344
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
BYTE * PBYTE
Definition: pedump.c:66
#define LOWORD(l)
Definition: pedump.c:82

Referenced by DosLoadExecutable(), and DosStartComSpec().

◆ DosRestoreState()

static VOID DosRestoreState ( VOID  )
inlinestatic

Definition at line 129 of file process.c.

130 {
132 
133  /*
134  * Pop the state structure from the stack. Note that we
135  * already have one word allocated (the interrupt number).
136  */
138 
139  DPRINT1("\n"
140  "DosRestoreState(before) -- SS:SP == %04X:%04X\n"
141  "Saved State =\n"
142  "DS = %04X; ES = %04X; AX = %04X; CX = %04X\n"
143  "DX = %04X; BX = %04X; BP = %04X; SI = %04X; DI = %04X"
144  "\n",
145  getSS(), getSP(),
146  State->DS, State->ES, State->AX, State->CX,
147  State->DX, State->BX, State->BP, State->SI, State->DI);
148 
149  setSP(getSP() + sizeof(DOS_REGISTER_STATE) - sizeof(WORD));
150 
151  /* Restore */
152  setDS(State->DS);
153  setES(State->ES);
154  setAX(State->AX);
155  setCX(State->CX);
156  setDX(State->DX);
157  setBX(State->BX);
158  setBP(State->BP);
159  setSI(State->SI);
160  setDI(State->DI);
161 
162  DPRINT1("\n"
163  "DosRestoreState(after) -- SS:SP == %04X:%04X\n"
164  "Restored CPU State =\n"
165  "DS = %04X; ES = %04X; AX = %04X; CX = %04X\n"
166  "DX = %04X; BX = %04X; BP = %04X; SI = %04X; DI = %04X"
167  "\n",
168  getSS(), getSP(),
169  getDS(), getES(), getAX(), getCX(),
170  getDX(), getBX(), getBP(), getSI(), getDI());
171 }
USHORT WINAPI getBX(VOID)
Definition: registers.c:170
USHORT WINAPI getSI(VOID)
Definition: registers.c:404
USHORT WINAPI getCX(VOID)
Definition: registers.c:228
VOID WINAPI setAX(USHORT)
Definition: registers.c:121
VOID WINAPI setDS(USHORT)
Definition: registers.c:515
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
VOID WINAPI setES(USHORT)
Definition: registers.c:529
VOID WINAPI setSP(USHORT)
Definition: registers.c:351
VOID WINAPI setSI(USHORT)
Definition: registers.c:411
USHORT WINAPI getES(VOID)
Definition: registers.c:522
unsigned short WORD
Definition: ntddk_ex.h:93
VOID WINAPI setBP(USHORT)
Definition: registers.c:381
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
VOID WINAPI setDI(USHORT)
Definition: registers.c:441
enum State_ State
Definition: pofuncs.h:54
USHORT WINAPI getDI(VOID)
Definition: registers.c:434
VOID WINAPI setCX(USHORT)
Definition: registers.c:235
#define DPRINT1
Definition: precomp.h:8
USHORT WINAPI getDS(VOID)
Definition: registers.c:508
USHORT WINAPI getBP(VOID)
Definition: registers.c:374
USHORT WINAPI getSP(VOID)
Definition: registers.c:344

Referenced by DosTerminateProcess().

◆ DosSaveState()

static VOID DosSaveState ( VOID  )
inlinestatic

Definition at line 84 of file process.c.

85 {
87  WORD StackPointer = getSP();
88 
89  DPRINT1("\n"
90  "DosSaveState(before) -- SS:SP == %04X:%04X\n"
91  "Original CPU State =\n"
92  "DS = %04X; ES = %04X; AX = %04X; CX = %04X\n"
93  "DX = %04X; BX = %04X; BP = %04X; SI = %04X; DI = %04X"
94  "\n",
95  getSS(), getSP(),
96  getDS(), getES(), getAX(), getCX(),
97  getDX(), getBX(), getBP(), getSI(), getDI());
98 
99  /*
100  * Allocate stack space for the registers. Note that we
101  * already have one word allocated (the interrupt number).
102  */
103  StackPointer -= sizeof(DOS_REGISTER_STATE) - sizeof(WORD);
104  State = SEG_OFF_TO_PTR(getSS(), StackPointer);
105  setSP(StackPointer);
106 
107  /* Save */
108  State->DS = getDS();
109  State->ES = getES();
110  State->AX = getAX();
111  State->CX = getCX();
112  State->DX = getDX();
113  State->BX = getBX();
114  State->BP = getBP();
115  State->SI = getSI();
116  State->DI = getDI();
117 
118  DPRINT1("\n"
119  "DosSaveState(after) -- SS:SP == %04X:%04X\n"
120  "Saved State =\n"
121  "DS = %04X; ES = %04X; AX = %04X; CX = %04X\n"
122  "DX = %04X; BX = %04X; BP = %04X; SI = %04X; DI = %04X"
123  "\n",
124  getSS(), getSP(),
125  State->DS, State->ES, State->AX, State->CX,
126  State->DX, State->BX, State->BP, State->SI, State->DI);
127 }
USHORT WINAPI getBX(VOID)
Definition: registers.c:170
USHORT WINAPI getSI(VOID)
Definition: registers.c:404
USHORT WINAPI getCX(VOID)
Definition: registers.c:228
struct _DOS_REGISTER_STATE DOS_REGISTER_STATE
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
VOID WINAPI setSP(USHORT)
Definition: registers.c:351
USHORT WINAPI getES(VOID)
Definition: registers.c:522
unsigned short WORD
Definition: ntddk_ex.h:93
USHORT WINAPI getDX(VOID)
Definition: registers.c:286
USHORT WINAPI getAX(VOID)
Definition: registers.c:114
enum State_ State
Definition: pofuncs.h:54
USHORT WINAPI getDI(VOID)
Definition: registers.c:434
#define DPRINT1
Definition: precomp.h:8
USHORT WINAPI getDS(VOID)
Definition: registers.c:508
USHORT WINAPI getBP(VOID)
Definition: registers.c:374
USHORT WINAPI getSP(VOID)
Definition: registers.c:344

Referenced by DosLoadExecutableInternal().

◆ DosSetProcessContext()

VOID DosSetProcessContext ( WORD  Segment)

Definition at line 321 of file process.c.

322 {
325 }
WORD CurrentPsp
Definition: dos.h:156
#define MAKELONG(a, b)
Definition: typedefs.h:248
_Inout_ PVOID Segment
Definition: exfuncs.h:893
PDOS_SDA Sda
Definition: dos.c:48
DWORD DiskTransferArea
Definition: dos.h:155

Referenced by DosInt21h(), DosLoadExecutableInternal(), and DosTerminateProcess().

◆ DosTerminateProcess()

VOID DosTerminateProcess ( WORD  Psp,
BYTE  ReturnCode,
WORD  KeepResident 
)

Definition at line 873 of file process.c.

874 {
875  WORD McbSegment = SysVars->FirstMcb;
876  PDOS_MCB CurrentMcb;
877  LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
878  PDOS_PSP PspBlock = SEGMENT_TO_PSP(Psp);
879  LPWORD Stack;
880  BYTE TerminationType;
881 
882  DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X, KeepResident 0x%04X\n",
883  Psp, ReturnCode, KeepResident);
884 
885  /* Notify VDDs of process termination */
887 
888  /* Check if this PSP is its own parent */
889  if (PspBlock->ParentPsp == Psp) goto Done;
890 
891  if (KeepResident == 0)
892  {
893  WORD i;
894  for (i = 0; i < PspBlock->HandleTableSize; i++)
895  {
896  /* Close the handle */
897  DosCloseHandle(i);
898  }
899  }
900 
901  /* Free the memory used by the process */
902  while (TRUE)
903  {
904  /* Get a pointer to the MCB */
905  CurrentMcb = SEGMENT_TO_MCB(McbSegment);
906 
907  /* Make sure the MCB is valid */
908  if (CurrentMcb->BlockType != 'M' && CurrentMcb->BlockType != 'Z') break;
909 
910  /* Check if this block was allocated by the process */
911  if (CurrentMcb->OwnerPsp == Psp)
912  {
913  if (KeepResident)
914  {
915  /* Check if this is the PSP block and we should reduce its size */
916  if ((McbSegment + 1) == Psp && KeepResident < CurrentMcb->Size)
917  {
918  /* Reduce the size of the block */
919  DosResizeMemory(McbSegment + 1, KeepResident, NULL);
920  break;
921  }
922  }
923  else
924  {
925  /* Free this entire block */
926  DosFreeMemory(McbSegment + 1);
927  }
928  }
929 
930  /* If this was the last block, quit */
931  if (CurrentMcb->BlockType == 'Z') break;
932 
933  /* Update the segment and continue */
934  McbSegment += CurrentMcb->Size + 1;
935  }
936 
937 Done:
938  /* Restore the interrupt vectors */
939  IntVecTable[0x22] = PspBlock->TerminateAddress;
940  IntVecTable[0x23] = PspBlock->BreakAddress;
941  IntVecTable[0x24] = PspBlock->CriticalAddress;
942 
943  /* Update the current PSP with the parent's one */
944  if (Psp == Sda->CurrentPsp)
945  {
946  DosSetProcessContext(PspBlock->ParentPsp);
947  if (Sda->CurrentPsp == SYSTEM_PSP)
948  {
949  // NOTE: we can also use the DOS BIOS exit code.
950  CpuUnsimulate();
951  return;
952  }
953  }
954 
955  /* Save the return code - Normal termination or TSR */
956  TerminationType = (KeepResident != 0 ? 0x03 : 0x00);
957  Sda->ErrorLevel = MAKEWORD(ReturnCode, TerminationType);
958 
959  DPRINT1("PspBlock->ParentPsp = 0x%04x; Sda->CurrentPsp = 0x%04x\n",
960  PspBlock->ParentPsp, Sda->CurrentPsp);
961 
962  if (Sda->CurrentPsp != SYSTEM_PSP)
963  {
964  DPRINT1("Sda->CurrentPsp = 0x%04x; Old SS:SP = %04X:%04X going to be LastStack = 0x%08x\n",
965  Sda->CurrentPsp, getSS(), getSP(), SEGMENT_TO_PSP(Sda->CurrentPsp)->LastStack);
966 
967  /* Restore the parent's stack */
968  setSS(HIWORD(SEGMENT_TO_PSP(Sda->CurrentPsp)->LastStack));
969  setSP(LOWORD(SEGMENT_TO_PSP(Sda->CurrentPsp)->LastStack));
970 
971  /* Pop the task state */
972  DosRestoreState();
973  }
974 
975  /* Return control to the parent process */
976  Stack = (LPWORD)SEG_OFF_TO_PTR(getSS(), getSP());
977  Stack[STACK_CS] = HIWORD(PspBlock->TerminateAddress);
978  Stack[STACK_IP] = LOWORD(PspBlock->TerminateAddress);
979 }
BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable)
Definition: memory.c:289
WORD CurrentPsp
Definition: dos.h:156
#define TRUE
Definition: types.h:120
#define MAKEWORD(a, b)
Definition: typedefs.h:247
static VOID DosRestoreState(VOID)
Definition: process.c:129
BOOLEAN DosFreeMemory(WORD BlockData)
Definition: memory.c:418
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
VOID VDDTerminateUserHook(USHORT DosPDB)
Definition: vddsup.c:466
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
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
VOID WINAPI setSS(USHORT)
Definition: registers.c:501
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
VOID DosSetProcessContext(WORD Segment)
Definition: process.c:321
WORD HandleTableSize
Definition: process.h:39
WORD FirstMcb
Definition: dos.h:77
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
unsigned short WORD
Definition: ntddk_ex.h:93
DWORD TerminateAddress
Definition: process.h:32
VOID CpuUnsimulate(VOID)
Definition: cpu.c:203
#define LPDWORD
Definition: nt_native.h:46
WORD OwnerPsp
Definition: memory.h:31
WORD ParentPsp
Definition: process.h:35
unsigned char BYTE
Definition: mem.h:68
PDOS_SDA Sda
Definition: dos.c:48
#define STACK_CS
Definition: int32.h:34
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
WORD ErrorLevel
Definition: dos.h:158
uint16_t * LPWORD
Definition: typedefs.h:54
PDOS_SYSVARS SysVars
Definition: dos.c:47
#define SYSTEM_PSP
Definition: dos.h:39
CHAR BlockType
Definition: memory.h:30
DWORD BreakAddress
Definition: process.h:33
#define DPRINT1
Definition: precomp.h:8
uint32_t * LPDWORD
Definition: typedefs.h:57
#define HIWORD(l)
Definition: typedefs.h:246
DWORD CriticalAddress
Definition: process.h:34
USHORT WINAPI getSP(VOID)
Definition: registers.c:344
WORD Size
Definition: memory.h:32
BOOLEAN DosCloseHandle(WORD DosHandle)
Definition: handle.c:311
#define STACK_IP
Definition: int32.h:33
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15
#define LOWORD(l)
Definition: pedump.c:82

Referenced by DosControlBreak(), DosInt20h(), DosInt21h(), and DosInt27h().