ReactOS  0.4.15-dev-4874-g57c84dd
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 251 of file process.c.

252 {
253  PDOS_PSP DestPsp = SEGMENT_TO_PSP(DestSegment);
254  PDOS_PSP SourcePsp = SEGMENT_TO_PSP(SourceSegment);
255  LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
256 
257  /* Literally copy the PSP first */
258  RtlCopyMemory(DestPsp, SourcePsp, sizeof(*DestPsp));
259 
260  /* Save the interrupt vectors */
261  DestPsp->TerminateAddress = IntVecTable[0x22];
262  DestPsp->BreakAddress = IntVecTable[0x23];
263  DestPsp->CriticalAddress = IntVecTable[0x24];
264 
265  /* No parent PSP */
266  DestPsp->ParentPsp = 0;
267 
268  /* Set the handle table pointers to the internal handle table */
270  DestPsp->HandleTablePtr = MAKELONG(0x18, DestSegment);
271 
272  /* Copy the parent handle table without referencing the SFT */
274  FAR_POINTER(SourcePsp->HandleTablePtr),
276 }
#define DEFAULT_JFT_SIZE
Definition: handle.h:13
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
#define MAKELONG(a, b)
Definition: typedefs.h:249
#define FAR_POINTER(x)
Definition: emulator.h:35
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:59
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
DWORD CriticalAddress
Definition: process.h:34

Referenced by DosInt21h().

◆ DosCopyEnvironmentBlock()

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

Definition at line 181 of file process.c.

183 {
184  PCHAR Ptr, DestBuffer = NULL;
185  SIZE_T TotalSize = 0;
186  WORD DestSegment;
187 
188  /* If we have an environment strings list, compute its size */
189  if (Environment)
190  {
191  /* Calculate the size of the environment block */
192  Ptr = (PCHAR)Environment;
193  while (*Ptr) Ptr += strlen(Ptr) + 1;
194  TotalSize = (ULONG_PTR)Ptr - (ULONG_PTR)Environment;
195  }
196  else
197  {
198  /* Empty environment string */
199  TotalSize = 1;
200  }
201  /* Add the final environment block NULL-terminator */
202  TotalSize++;
203 
204  /* Add the two bytes for the program name tag */
205  TotalSize += 2;
206 
207  /* Add the string buffer size */
208  TotalSize += strlen(ProgramName) + 1;
209 
210  /* Allocate the memory for the environment block */
211  DestSegment = DosAllocateMemory((WORD)((TotalSize + 0x0F) >> 4), NULL);
212  if (!DestSegment) return 0;
213 
214  DestBuffer = (PCHAR)SEG_OFF_TO_PTR(DestSegment, 0);
215 
216  /* If we have an environment strings list, copy it */
217  if (Environment)
218  {
219  Ptr = (PCHAR)Environment;
220  while (*Ptr)
221  {
222  /* Copy the string and NULL-terminate it */
223  strcpy(DestBuffer, Ptr);
224  DestBuffer += strlen(Ptr);
225  *(DestBuffer++) = '\0';
226 
227  /* Move to the next string */
228  Ptr += strlen(Ptr) + 1;
229  }
230  }
231  else
232  {
233  /* Empty environment string */
234  *(DestBuffer++) = '\0';
235  }
236  /* NULL-terminate the environment block */
237  *(DestBuffer++) = '\0';
238 
239  /* Store the special program name tag */
240  *(DestBuffer++) = LOBYTE(DOS_PROGRAM_NAME_TAG);
241  *(DestBuffer++) = HIBYTE(DOS_PROGRAM_NAME_TAG);
242 
243  /* Copy the program name after the environment block */
244  strcpy(DestBuffer, ProgramName);
245 
246  return DestSegment;
247 }
signed char * PCHAR
Definition: retypes.h:7
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
#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:32
uint32_t ULONG_PTR
Definition: typedefs.h:65
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:80
#define NULL
Definition: types.h:112
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 793 of file process.c.

796 {
798  DWORD BinaryType;
799 
800  /* Get the binary type */
801  if (!GetBinaryTypeA(ProgramName, &BinaryType)) return GetLastError();
802 
803  /* Check the type of the program */
804  switch (BinaryType)
805  {
806  /* Those are handled by NTVDM */
807  case SCS_WOW_BINARY:
808  {
809  static const PCSTR AppName = "\"%ProgramFiles%\\otvdm\\otvdmw.exe\" ";
810 
811  STARTUPINFOA si;
813  union { DWORD Size; NTSTATUS Status; } Ret;
814  CHAR ExpName[MAX_PATH];
815 
816  Ret.Size = ExpandEnvironmentStringsA(AppName, ExpName, _countof(ExpName));
817  if ((Ret.Size == 0) || (Ret.Size > _countof(ExpName)))
818  {
819  /* We failed or buffer too small, fall back to DOS execution */
820  goto RunAsDOS;
821  }
822  Ret.Size--; // Remove NULL-terminator from count
823 
824  /* Add double-quotes before and after ProgramName */
825  Ret.Status = RtlStringCchPrintfA(ExpName + Ret.Size, _countof(ExpName) - Ret.Size,
826  "\"%s\"", ProgramName);
827  if (!NT_SUCCESS(Ret.Status))
828  {
829  /* We failed or buffer too small, fall back to DOS execution */
830  goto RunAsDOS;
831  }
832 
833  ZeroMemory(&pi, sizeof(pi));
834  ZeroMemory(&si, sizeof(si));
835  si.cb = sizeof(si);
836 
837  /* Create the process */
838  if (CreateProcessA(NULL, // No Application Name
839  ExpName, // Just our Command Line
840  NULL, // Cannot inherit Process Handle
841  NULL, // Cannot inherit Thread Handle
842  FALSE, // No handle inheritance
843  0, // No extra creation flags
844  NULL, // No environment block
845  NULL, // No starting directory
846  &si,
847  &pi))
848  {
849  /* Close the handles */
850  CloseHandle(pi.hThread);
851  CloseHandle(pi.hProcess);
852  break;
853  }
854  else
855  {
856  /* Retrieve the actual path to the "Program Files" directory for displaying the error */
857  ExpandEnvironmentStringsA("%ProgramFiles%", ExpName, _countof(ExpName));
858 
859  DisplayMessage(L"Trying to load '%S'.\n"
860  L"WOW16 applications are not supported internally by NTVDM at the moment.\n"
861  L"Consider installing WineVDM from the ReactOS Applications Manager in\n'%S'.\n\n"
862  L"Click on OK to continue.",
863  ProgramName, ExpName);
864  }
865  // Fall through
866  }
867  RunAsDOS:
868  case SCS_DOS_BINARY:
869  {
870  /* Load the executable */
872  ProgramName,
873  Parameters,
874  NULL,
875  NULL,
876  ReturnAddress);
877  if (Result != ERROR_SUCCESS)
878  {
879  DisplayMessage(L"Could not load '%S'. Error: %u", ProgramName, Result);
880  }
881 
882  break;
883  }
884 
885  /* Not handled by NTVDM */
886  default:
887  {
890  LPSTR CmdLinePtr;
891  ULONG CmdLineSize;
892 
893  /* Did the caller specify an environment segment? */
894  if (Parameters->Environment)
895  {
896  /* Yes, use it instead of the parent one */
897  Environment = (LPSTR)SEG_OFF_TO_PTR(Parameters->Environment, 0);
898  }
899 
900  /*
901  * Convert the DOS command line to Win32-compatible format, by concatenating
902  * the program name with the converted command line.
903  * Format of the DOS command line: 1 byte for size; 127 bytes for contents.
904  */
905  CmdLinePtr = CmdLine;
906  strncpy(CmdLinePtr, ProgramName, MAX_PATH); // Concatenate the program name
907  CmdLinePtr += strlen(CmdLinePtr);
908  *CmdLinePtr++ = ' '; // Add separating space
909 
910  CmdLineSize = min(*(PBYTE)FAR_POINTER(Parameters->CommandLine), DOS_CMDLINE_LENGTH);
911  RtlCopyMemory(CmdLinePtr,
912  (LPSTR)FAR_POINTER(Parameters->CommandLine) + 1,
913  CmdLineSize);
914  /* NULL-terminate it */
915  CmdLinePtr[CmdLineSize] = '\0';
916 
917  /* Remove any trailing return carriage character and NULL-terminate the command line */
918  while (*CmdLinePtr && *CmdLinePtr != '\r' && *CmdLinePtr != '\n') CmdLinePtr++;
919  *CmdLinePtr = '\0';
920 
921  Result = DosStartProcess32(ProgramName, CmdLine,
922  Environment, ReturnAddress,
923  TRUE);
924  if (Result != ERROR_SUCCESS)
925  {
926  DisplayMessage(L"Could not load 32-bit '%S'. Error: %u", ProgramName, Result);
927  }
928 
929  break;
930  }
931  }
932 
933  return Result;
934 }
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
#define CloseHandle
Definition: compat.h:598
#define ERROR_SUCCESS
Definition: deptool.c:10
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:863
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define TRUE
Definition: types.h:120
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
static CHAR AppName[MAX_PATH]
Definition: dem.c:252
#define DOS_CMDLINE_LENGTH
Definition: process.h:13
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
#define ZeroMemory
Definition: winbase.h:1667
char * LPSTR
Definition: xmlstorage.h:182
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:32
static const WCHAR CmdLine[]
Definition: install.c:48
#define L(x)
Definition: ntvdm.h:50
#define SCS_DOS_BINARY
Definition: winbase.h:235
#define FALSE
Definition: types.h:117
NTSTRSAFEVAPI RtlStringCchPrintfA(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,...)
Definition: ntstrsafe.h:1085
#define SCS_WOW_BINARY
Definition: winbase.h:239
_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
DWORD WINAPI ExpandEnvironmentStringsA(IN LPCSTR lpSrc, IN LPSTR lpDst, IN DWORD nSize)
Definition: environ.c:399
#define FAR_POINTER(x)
Definition: emulator.h:35
Status
Definition: gdiplustypes.h:24
DWORD cb
Definition: winbase.h:828
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static refpint_t pi[]
Definition: server.c:96
#define _countof(array)
Definition: sndvol32.h:68
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:4743
#define MAX_PATH
Definition: compat.h:34
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL WINAPI GetBinaryTypeA(IN LPCSTR lpApplicationName, OUT LPDWORD lpBinaryType)
Definition: vdm.c:1335
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
#define NULL
Definition: types.h:112
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
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
const char * PCSTR
Definition: typedefs.h:52
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 278 of file process.c.

279 {
280  PDOS_PSP PspBlock = SEGMENT_TO_PSP(Segment);
281  LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
282 
283  RtlZeroMemory(PspBlock, sizeof(*PspBlock));
284 
285  /* Set the exit interrupt */
286  PspBlock->Exit[0] = 0xCD; // int 0x20
287  PspBlock->Exit[1] = 0x20;
288 
289  /* Set the number of the last paragraph */
290  PspBlock->LastParagraph = Segment + ProgramSize;
291 
292  /* Save the interrupt vectors */
293  PspBlock->TerminateAddress = IntVecTable[0x22];
294  PspBlock->BreakAddress = IntVecTable[0x23];
295  PspBlock->CriticalAddress = IntVecTable[0x24];
296 
297  /* Set the parent PSP */
298  PspBlock->ParentPsp = Sda->CurrentPsp;
299 
300  if (Sda->CurrentPsp != SYSTEM_PSP)
301  {
302  /* Link to the parent's environment block */
303  PspBlock->EnvBlock = SEGMENT_TO_PSP(Sda->CurrentPsp)->EnvBlock;
304  }
305 /*
306  else
307  {
308  PspBlock->EnvBlock = SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0);
309  }
310 */
311 
312  /* Copy the parent handle table */
313  DosCopyHandleTable(PspBlock->HandleTable);
314 
315  /* Set the handle table pointers to the internal handle table */
316  PspBlock->HandleTableSize = DEFAULT_JFT_SIZE;
317  PspBlock->HandleTablePtr = MAKELONG(0x18, Segment);
318 
319  /* Set the DOS version */
320  // FIXME: This is here that SETVER stuff enters into action!
321  PspBlock->DosVersion = DosData->DosVersion;
322 
323  /* Set the far call opcodes */
324  PspBlock->FarCall[0] = 0xCD; // int 0x21
325  PspBlock->FarCall[1] = 0x21;
326  PspBlock->FarCall[2] = 0xCB; // retf
327 }
WORD CurrentPsp
Definition: dos.h:165
#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:65
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
WORD LastParagraph
Definition: process.h:30
#define MAKELONG(a, b)
Definition: typedefs.h:249
VOID DosCopyHandleTable(LPBYTE DestinationTable)
Definition: handle.c:27
WORD HandleTableSize
Definition: process.h:39
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
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:59
WORD DosVersion
Definition: process.h:43
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
DWORD CriticalAddress
Definition: process.h:34
WORD DosVersion
Definition: dos.h:255
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 }
#define DOS_CMDLINE_LENGTH
Definition: process.h:13
BYTE CommandLineSize
Definition: process.h:48
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
CHAR CommandLine[DOS_CMDLINE_LENGTH]
Definition: process.h:49
const char * LPCSTR
Definition: xmlstorage.h:183
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
CHAR NTAPI RtlUpperChar(_In_ CHAR Source)
Definition: nlsboot.c:229
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
unsigned short USHORT
Definition: pedump.c:61
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:343
#define min(a, b)
Definition: monoChain.cc:55
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#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 705 of file process.c.

711 {
713  HANDLE FileHandle = INVALID_HANDLE_VALUE, FileMapping = NULL;
714  DWORD FileSize;
715  LPBYTE Address = NULL;
716  CHAR FullPath[MAX_PATH];
717  CHAR ShortFullPath[MAX_PATH];
718 
719  DPRINT1("DosLoadExecutable(%d, '%s', 0x%p, 0x%p, 0x%p)\n",
720  LoadType, ExecutablePath, Parameters, CommandLine, Environment);
721 
722  /* Try to get the full path to the executable */
723  if (GetFullPathNameA(ExecutablePath, sizeof(FullPath), FullPath, NULL))
724  {
725  /* Get the corresponding short path */
726  if (GetShortPathNameA(FullPath, ShortFullPath, sizeof(ShortFullPath)))
727  {
728  /* Use the shortened full path from now on */
729  ExecutablePath = ShortFullPath;
730  }
731  }
732 
733  /* Open a handle to the executable */
734  FileHandle = CreateFileA(ExecutablePath,
735  GENERIC_READ,
737  NULL,
740  NULL);
742  {
743  Result = GetLastError();
744  goto Cleanup;
745  }
746 
747  /* Get the file size */
749 
750  /* Create a mapping object for the file */
751  FileMapping = CreateFileMapping(FileHandle,
752  NULL,
754  0,
755  0,
756  NULL);
757  if (FileMapping == NULL)
758  {
759  Result = GetLastError();
760  goto Cleanup;
761  }
762 
763  /* Map the file into memory */
764  Address = (LPBYTE)MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 0);
765  if (Address == NULL)
766  {
767  Result = GetLastError();
768  goto Cleanup;
769  }
770 
772  Address,
773  FileSize,
774  ExecutablePath,
775  Parameters,
776  CommandLine,
777  Environment,
778  ReturnAddress);
779 
780 Cleanup:
781  /* Unmap the file*/
783 
784  /* Close the file mapping object */
785  if (FileMapping != NULL) CloseHandle(FileMapping);
786 
787  /* Close the file handle */
789 
790  return Result;
791 }
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
#define CloseHandle
Definition: compat.h:598
#define ERROR_SUCCESS
Definition: deptool.c:10
#define MapViewOfFile
Definition: compat.h:604
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:863
char CHAR
Definition: xmlstorage.h:175
#define CreateFileMapping
Definition: winbase.h:3611
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
#define FILE_SHARE_READ
Definition: compat.h:136
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:993
unsigned char * LPBYTE
Definition: typedefs.h:53
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:635
#define OPEN_EXISTING
Definition: compat.h:634
DWORD WINAPI GetShortPathNameA(IN LPCSTR lpszLongPath, OUT LPSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1752
#define MAX_PATH
Definition: compat.h:34
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
#define GENERIC_READ
Definition: compat.h:135
static const WCHAR Cleanup[]
Definition: register.c:80
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1230
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
#define NULL
Definition: types.h:112
#define PAGE_READONLY
Definition: compat.h:138
#define DPRINT1
Definition: precomp.h:8
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:599
#define UnmapViewOfFile
Definition: compat.h:605

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 335 of file process.c.

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

134 {
136 
137  /*
138  * Pop the state structure from the stack. Note that we
139  * already have one word allocated (the interrupt number).
140  */
142 
143 #ifdef ADVANCED_DEBUGGING
144  DPRINT1("\n"
145  "DosRestoreState(before) -- SS:SP == %04X:%04X\n"
146  "Saved State =\n"
147  "DS = %04X; ES = %04X; AX = %04X; CX = %04X\n"
148  "DX = %04X; BX = %04X; BP = %04X; SI = %04X; DI = %04X"
149  "\n",
150  getSS(), getSP(),
151  State->DS, State->ES, State->AX, State->CX,
152  State->DX, State->BX, State->BP, State->SI, State->DI);
153 #endif
154 
155  setSP(getSP() + sizeof(DOS_REGISTER_STATE) - sizeof(WORD));
156 
157  /* Restore */
158  setDS(State->DS);
159  setES(State->ES);
160  setAX(State->AX);
161  setCX(State->CX);
162  setDX(State->DX);
163  setBX(State->BX);
164  setBP(State->BP);
165  setSI(State->SI);
166  setDI(State->DI);
167 
168 #ifdef ADVANCED_DEBUGGING
169  DPRINT1("\n"
170  "DosRestoreState(after) -- SS:SP == %04X:%04X\n"
171  "Restored CPU State =\n"
172  "DS = %04X; ES = %04X; AX = %04X; CX = %04X\n"
173  "DX = %04X; BX = %04X; BP = %04X; SI = %04X; DI = %04X"
174  "\n",
175  getSS(), getSP(),
176  getDS(), getES(), getAX(), getCX(),
177  getDX(), getBX(), getBP(), getSI(), getDI());
178 #endif
179 }
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
_In_ ULONG _In_ ULONG State
Definition: potypes.h:516
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:32
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
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 #ifdef ADVANCED_DEBUGGING
90  DPRINT1("\n"
91  "DosSaveState(before) -- SS:SP == %04X:%04X\n"
92  "Original CPU State =\n"
93  "DS = %04X; ES = %04X; AX = %04X; CX = %04X\n"
94  "DX = %04X; BX = %04X; BP = %04X; SI = %04X; DI = %04X"
95  "\n",
96  getSS(), getSP(),
97  getDS(), getES(), getAX(), getCX(),
98  getDX(), getBX(), getBP(), getSI(), getDI());
99 #endif
100 
101  /*
102  * Allocate stack space for the registers. Note that we
103  * already have one word allocated (the interrupt number).
104  */
105  StackPointer -= sizeof(DOS_REGISTER_STATE) - sizeof(WORD);
106  State = SEG_OFF_TO_PTR(getSS(), StackPointer);
107  setSP(StackPointer);
108 
109  /* Save */
110  State->DS = getDS();
111  State->ES = getES();
112  State->AX = getAX();
113  State->CX = getCX();
114  State->DX = getDX();
115  State->BX = getBX();
116  State->BP = getBP();
117  State->SI = getSI();
118  State->DI = getDI();
119 
120 #ifdef ADVANCED_DEBUGGING
121  DPRINT1("\n"
122  "DosSaveState(after) -- SS:SP == %04X:%04X\n"
123  "Saved State =\n"
124  "DS = %04X; ES = %04X; AX = %04X; CX = %04X\n"
125  "DX = %04X; BX = %04X; BP = %04X; SI = %04X; DI = %04X"
126  "\n",
127  getSS(), getSP(),
128  State->DS, State->ES, State->AX, State->CX,
129  State->DX, State->BX, State->BP, State->SI, State->DI);
130 #endif
131 }
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
_In_ ULONG _In_ ULONG State
Definition: potypes.h:516
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:32
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
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 329 of file process.c.

330 {
333 }
WORD CurrentPsp
Definition: dos.h:165
#define MAKELONG(a, b)
Definition: typedefs.h:249
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
PDOS_SDA Sda
Definition: dos.c:48
DWORD DiskTransferArea
Definition: dos.h:164

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

◆ DosTerminateProcess()

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

Definition at line 936 of file process.c.

937 {
938  WORD McbSegment = SysVars->FirstMcb;
939  PDOS_MCB CurrentMcb;
940  LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
941  PDOS_PSP PspBlock = SEGMENT_TO_PSP(Psp);
942  LPWORD Stack;
943  BYTE TerminationType;
944 
945  DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X, KeepResident 0x%04X\n",
946  Psp, ReturnCode, KeepResident);
947 
948  /* Notify VDDs of process termination */
950 
951  /* Check if this PSP is its own parent */
952  if (PspBlock->ParentPsp == Psp) goto Done;
953 
954  if (KeepResident == 0)
955  {
956  WORD i;
957  for (i = 0; i < PspBlock->HandleTableSize; i++)
958  {
959  /* Close the handle */
960  DosCloseHandle(i);
961  }
962  }
963 
964  /* Free the memory used by the process */
965  while (TRUE)
966  {
967  /* Get a pointer to the MCB */
968  CurrentMcb = SEGMENT_TO_MCB(McbSegment);
969 
970  /* Make sure the MCB is valid */
971  if (CurrentMcb->BlockType != 'M' && CurrentMcb->BlockType != 'Z') break;
972 
973  /* Check if this block was allocated by the process */
974  if (CurrentMcb->OwnerPsp == Psp)
975  {
976  if (KeepResident)
977  {
978  /* Check if this is the PSP block and we should reduce its size */
979  if ((McbSegment + 1) == Psp && KeepResident < CurrentMcb->Size)
980  {
981  /* Reduce the size of the block */
982  DosResizeMemory(McbSegment + 1, KeepResident, NULL);
983  break;
984  }
985  }
986  else
987  {
988  /* Free this entire block */
989  DosFreeMemory(McbSegment + 1);
990  }
991  }
992 
993  /* If this was the last block, quit */
994  if (CurrentMcb->BlockType == 'Z') break;
995 
996  /* Update the segment and continue */
997  McbSegment += CurrentMcb->Size + 1;
998  }
999 
1000 Done:
1001  /* Restore the interrupt vectors */
1002  IntVecTable[0x22] = PspBlock->TerminateAddress;
1003  IntVecTable[0x23] = PspBlock->BreakAddress;
1004  IntVecTable[0x24] = PspBlock->CriticalAddress;
1005 
1006  /* Update the current PSP with the parent's one */
1007  if (Psp == Sda->CurrentPsp)
1008  {
1009  DosSetProcessContext(PspBlock->ParentPsp);
1010  if (Sda->CurrentPsp == SYSTEM_PSP)
1011  {
1012  // NOTE: we can also use the DOS BIOS exit code.
1013  CpuUnsimulate();
1014  return;
1015  }
1016  }
1017 
1018  /* Save the return code - Normal termination or TSR */
1019  TerminationType = (KeepResident != 0 ? 0x03 : 0x00);
1020  Sda->ErrorLevel = MAKEWORD(ReturnCode, TerminationType);
1021 
1022 #ifdef ADVANCED_DEBUGGING
1023  DPRINT1("PspBlock->ParentPsp = 0x%04x; Sda->CurrentPsp = 0x%04x\n",
1024  PspBlock->ParentPsp, Sda->CurrentPsp);
1025 #endif
1026 
1027  if (Sda->CurrentPsp != SYSTEM_PSP)
1028  {
1029 #ifdef ADVANCED_DEBUGGING
1030  DPRINT1("Sda->CurrentPsp = 0x%04x; Old SS:SP = %04X:%04X going to be LastStack = 0x%08x\n",
1031  Sda->CurrentPsp, getSS(), getSP(), SEGMENT_TO_PSP(Sda->CurrentPsp)->LastStack);
1032 #endif
1033 
1034  /* Restore the parent's stack */
1035  setSS(HIWORD(SEGMENT_TO_PSP(Sda->CurrentPsp)->LastStack));
1036  setSP(LOWORD(SEGMENT_TO_PSP(Sda->CurrentPsp)->LastStack));
1037 
1038  /* Pop the task state */
1039  DosRestoreState();
1040  }
1041 
1042  /* Return control to the parent process */
1044  Stack[STACK_CS] = HIWORD(PspBlock->TerminateAddress);
1045  Stack[STACK_IP] = LOWORD(PspBlock->TerminateAddress);
1046 }
BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable)
Definition: memory.c:289
WORD CurrentPsp
Definition: dos.h:165
#define MAKEWORD(a, b)
Definition: typedefs.h:248
#define TRUE
Definition: types.h:120
static VOID DosRestoreState(VOID)
Definition: process.c:133
BOOLEAN DosFreeMemory(WORD BlockData)
Definition: memory.c:418
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:32
VOID VDDTerminateUserHook(USHORT DosPDB)
Definition: vddsup.c:466
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
VOID WINAPI setSP(USHORT)
Definition: registers.c:351
VOID WINAPI setSS(USHORT)
Definition: registers.c:501
VOID DosSetProcessContext(WORD Segment)
Definition: process.c:329
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
PDOS_SDA Sda
Definition: dos.c:48
#define STACK_CS
Definition: int32.h:34
unsigned char BYTE
Definition: xxhash.c:193
WORD ErrorLevel
Definition: dos.h:167
uint16_t * LPWORD
Definition: typedefs.h:56
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
PDOS_SYSVARS SysVars
Definition: dos.c:47
#define SYSTEM_PSP
Definition: dos.h:39
CHAR BlockType
Definition: memory.h:30
#define NULL
Definition: types.h:112
DWORD BreakAddress
Definition: process.h:33
#define DPRINT1
Definition: precomp.h:8
uint32_t * LPDWORD
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
DWORD CriticalAddress
Definition: process.h:34
USHORT WINAPI getSP(VOID)
Definition: registers.c:344
WORD Size
Definition: memory.h:32
#define DPRINT
Definition: sndvol32.h:71
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().