ReactOS 0.4.16-dev-297-gc569aee
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 FAR_POINTER(x)
Definition: emulator.h:35
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define LPDWORD
Definition: nt_native.h:46
DWORD CriticalAddress
Definition: process.h:34
DWORD TerminateAddress
Definition: process.h:32
WORD HandleTableSize
Definition: process.h:39
WORD ParentPsp
Definition: process.h:35
DWORD BreakAddress
Definition: process.h:33
DWORD HandleTablePtr
Definition: process.h:40
#define DEFAULT_JFT_SIZE
Definition: handle.h:13
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
uint32_t * LPDWORD
Definition: typedefs.h:59
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MAKELONG(a, b)
Definition: typedefs.h:249

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 */
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 {
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}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define NULL
Definition: types.h:112
#define ULONG_PTR
Definition: config.h:101
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:32
unsigned short WORD
Definition: ntddk_ex.h:93
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
#define PCHAR
Definition: match.c:90
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable)
Definition: memory.c:136
#define DOS_PROGRAM_NAME_TAG
Definition: process.h:14
ULONG_PTR SIZE_T
Definition: typedefs.h:80
char * PCHAR
Definition: typedefs.h:51

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,
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}
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
LONG NTSTATUS
Definition: precomp.h:26
INT __cdecl DisplayMessage(_In_opt_ HWND hWnd, _In_ UINT uType, _In_opt_ PCWSTR pszTitle, _In_opt_ PCWSTR pszFormatMessage,...)
Definition: reactos.c:211
static CHAR AppName[MAX_PATH]
Definition: dem.c:252
DWORD DosStartProcess32(IN LPCSTR ExecutablePath, IN LPCSTR CommandLine, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL, IN BOOLEAN StartComSpec)
Definition: dem.c:916
#define ERROR_SUCCESS
Definition: deptool.c:10
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define CloseHandle
Definition: compat.h:739
#define MAX_PATH
Definition: compat.h:34
DWORD WINAPI ExpandEnvironmentStringsA(IN LPCSTR lpSrc, IN LPSTR lpDst, IN DWORD nSize)
Definition: environ.c:399
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:4747
BOOL WINAPI GetBinaryTypeA(IN LPCSTR lpApplicationName, OUT LPDWORD lpBinaryType)
Definition: vdm.c:1335
static const WCHAR CmdLine[]
Definition: install.c:48
unsigned long DWORD
Definition: ntddk_ex.h:95
Status
Definition: gdiplustypes.h:25
static refpint_t pi[]
Definition: server.c:96
#define min(a, b)
Definition: monoChain.cc:55
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 L(x)
Definition: ntvdm.h:50
BYTE * PBYTE
Definition: pedump.c:66
#define _countof(array)
Definition: sndvol32.h:70
DWORD cb
Definition: winbase.h:856
DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType, IN LPCSTR ExecutablePath, IN PDOS_EXEC_PARAM_BLOCK Parameters, IN LPCSTR CommandLine OPTIONAL, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL)
Definition: process.c:705
@ DOS_LOAD_AND_EXECUTE
Definition: process.h:20
#define DOS_CMDLINE_LENGTH
Definition: process.h:13
const char * PCSTR
Definition: typedefs.h:52
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:869
#define ZeroMemory
Definition: winbase.h:1737
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define SCS_DOS_BINARY
Definition: winbase.h:264
#define SCS_WOW_BINARY
Definition: winbase.h:268
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
char * LPSTR
Definition: xmlstorage.h:182
char CHAR
Definition: xmlstorage.h:175

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 */
314
315 /* Set the handle table pointers to the internal handle table */
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}
PDOS_SDA Sda
Definition: dos.c:48
PDOS_DATA DosData
Definition: dos.c:45
WORD DosVersion
Definition: dos.h:255
BYTE HandleTable[20]
Definition: process.h:36
BYTE FarCall[3]
Definition: process.h:45
WORD LastParagraph
Definition: process.h:30
WORD DosVersion
Definition: process.h:43
WORD EnvBlock
Definition: process.h:37
BYTE Exit[2]
Definition: process.h:29
WORD CurrentPsp
Definition: dos.h:165
#define SYSTEM_PSP
Definition: dos.h:39
VOID DosCopyHandleTable(LPBYTE DestinationTable)
Definition: handle.c:27
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Inout_ PVOID Segment
Definition: exfuncs.h:1101

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{
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}
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:349
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 NTAPI RtlUpperChar(_In_ CHAR Source)
Definition: nlsboot.c:229
unsigned short USHORT
Definition: pedump.c:61
CHAR CommandLine[DOS_CMDLINE_LENGTH]
Definition: process.h:49
BYTE CommandLineSize
Definition: process.h:48
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15
const char * LPCSTR
Definition: xmlstorage.h:183

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{
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,
737 NULL,
740 NULL);
742 {
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 {
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 {
768 goto Cleanup;
769 }
770
772 Address,
773 FileSize,
774 ExecutablePath,
776 CommandLine,
778 ReturnAddress);
779
780Cleanup:
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}
#define DPRINT1
Definition: precomp.h:8
#define PAGE_READONLY
Definition: compat.h:138
#define UnmapViewOfFile
Definition: compat.h:746
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GENERIC_READ
Definition: compat.h:135
#define FILE_MAP_READ
Definition: compat.h:776
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define MapViewOfFile
Definition: compat.h:745
#define FILE_SHARE_READ
Definition: compat.h:136
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
DWORD WINAPI GetShortPathNameA(IN LPCSTR lpszLongPath, OUT LPSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1752
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:993
static const WCHAR Cleanup[]
Definition: register.c:80
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
static WCHAR Address[46]
Definition: ping.c:68
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
unsigned char * LPBYTE
Definition: typedefs.h:53
#define CreateFileMapping
Definition: winbase.h:3775

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
694Cleanup:
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}
unsigned char BOOLEAN
Definition: Header.h:9
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
struct _IMAGE_DOS_HEADER * PIMAGE_DOS_HEADER
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599
#define ASSERT(a)
Definition: mode.c:44
#define LOWORD(l)
Definition: pedump.c:82
WORD * PWORD
Definition: pedump.c:67
DWORD * PDWORD
Definition: pedump.c:68
WORD LastErrorCode
Definition: dos.h:160
VOID CpuExecute(WORD Segment, WORD Offset)
Definition: cpu.c:102
VOID DosChangeMemoryOwner(WORD Segment, WORD NewOwner)
Definition: memory.c:532
BOOLEAN DosFreeMemory(WORD BlockData)
Definition: memory.c:418
VOID DosCreatePsp(WORD Segment, WORD ProgramSize)
Definition: process.c:278
static VOID DosInitPsp(IN WORD Segment, IN WORD EnvBlock, IN LPCSTR CommandLine, IN LPCSTR ProgramName)
Definition: process.c:36
VOID DosSetProcessContext(WORD Segment)
Definition: process.c:329
static WORD DosCopyEnvironmentBlock(IN LPCSTR Environment OPTIONAL, IN LPCSTR ProgramName)
Definition: process.c:181
static VOID DosSaveState(VOID)
Definition: process.c:84
@ DOS_LOAD_OVERLAY
Definition: process.h:22
@ DOS_LOAD_ONLY
Definition: process.h:21
struct _DOS_PSP DOS_PSP
uint32_t * PULONG
Definition: typedefs.h:59
uint16_t * LPWORD
Definition: typedefs.h:56
#define HIWORD(l)
Definition: typedefs.h:247
VOID VDDCreateUserHook(USHORT DosPDB)
Definition: vddsup.c:453
VOID WINAPI setBX(USHORT)
Definition: registers.c:177
VOID WINAPI setCX(USHORT)
Definition: registers.c:235
VOID WINAPI setDX(USHORT)
Definition: registers.c:293
VOID WINAPI setSP(USHORT)
Definition: registers.c:351
VOID WINAPI setDS(USHORT)
Definition: registers.c:515
VOID WINAPI setEFLAGS(ULONG)
Definition: registers.c:687
USHORT WINAPI getSP(VOID)
Definition: registers.c:344
VOID WINAPI setBP(USHORT)
Definition: registers.c:381
VOID WINAPI setSS(USHORT)
Definition: registers.c:501
VOID WINAPI setAX(USHORT)
Definition: registers.c:121
VOID WINAPI setES(USHORT)
Definition: registers.c:529
ULONG WINAPI getEFLAGS(VOID)
Definition: registers.c:680
VOID WINAPI setSI(USHORT)
Definition: registers.c:411
VOID WINAPI setDI(USHORT)
Definition: registers.c:441
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
unsigned char BYTE
Definition: xxhash.c:193

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 getDS(VOID)
Definition: registers.c:508
USHORT WINAPI getCX(VOID)
Definition: registers.c:228
USHORT WINAPI getSI(VOID)
Definition: registers.c:404
USHORT WINAPI getDX(VOID)
Definition: registers.c:286
USHORT WINAPI getAX(VOID)
Definition: registers.c:114
USHORT WINAPI getES(VOID)
Definition: registers.c:522
USHORT WINAPI getBP(VOID)
Definition: registers.c:374
USHORT WINAPI getDI(VOID)
Definition: registers.c:434

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}
struct _DOS_REGISTER_STATE DOS_REGISTER_STATE

Referenced by DosLoadExecutableInternal().

◆ DosSetProcessContext()

VOID DosSetProcessContext ( WORD  Segment)

Definition at line 329 of file process.c.

330{
333}
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);
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 */
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
1000Done:
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 {
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 */
1040 }
1041
1042 /* Return control to the parent process */
1044 Stack[STACK_CS] = HIWORD(PspBlock->TerminateAddress);
1045 Stack[STACK_IP] = LOWORD(PspBlock->TerminateAddress);
1046}
PDOS_SYSVARS SysVars
Definition: dos.c:47
#define STACK_IP
Definition: int32.h:33
#define STACK_CS
Definition: int32.h:34
#define DPRINT
Definition: sndvol32.h:73
CHAR BlockType
Definition: memory.h:30
WORD Size
Definition: memory.h:32
WORD OwnerPsp
Definition: memory.h:31
WORD ErrorLevel
Definition: dos.h:167
WORD FirstMcb
Definition: dos.h:77
VOID CpuUnsimulate(VOID)
Definition: cpu.c:203
BOOLEAN DosCloseHandle(WORD DosHandle)
Definition: handle.c:311
BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable)
Definition: memory.c:289
static VOID DosRestoreState(VOID)
Definition: process.c:133
#define MAKEWORD(a, b)
Definition: typedefs.h:248
VOID VDDTerminateUserHook(USHORT DosPDB)
Definition: vddsup.c:466
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639

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