ReactOS  0.4.14-dev-368-gfa26425
process.h File Reference

Go to the source code of this file.

Classes

struct  _DOS_PSP
 
struct  _DOS_EXEC_PARAM_BLOCK
 
struct  _DOS_REGISTER_STATE
 

Macros

#define DOS_CMDLINE_LENGTH   127
 
#define DOS_PROGRAM_NAME_TAG   0x0001
 
#define SEGMENT_TO_PSP(seg)   ((PDOS_PSP)SEG_OFF_TO_PTR((seg), 0))
 

Typedefs

typedef struct _DOS_PSP DOS_PSP
 
typedef struct _DOS_PSPPDOS_PSP
 
typedef struct _DOS_EXEC_PARAM_BLOCK DOS_EXEC_PARAM_BLOCK
 
typedef struct _DOS_EXEC_PARAM_BLOCKPDOS_EXEC_PARAM_BLOCK
 
typedef struct _DOS_REGISTER_STATE DOS_REGISTER_STATE
 
typedef struct _DOS_REGISTER_STATEPDOS_REGISTER_STATE
 

Enumerations

enum  DOS_EXEC_TYPE { DOS_LOAD_AND_EXECUTE = 0x00, DOS_LOAD_ONLY = 0x01, DOS_LOAD_OVERLAY = 0x03 }
 

Functions

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 (LPCSTR ProgramName, PDOS_EXEC_PARAM_BLOCK Parameters, IN DWORD ReturnAddress OPTIONAL)
 
VOID DosTerminateProcess (WORD Psp, BYTE ReturnCode, WORD KeepResident)
 

Macro Definition Documentation

◆ DOS_CMDLINE_LENGTH

#define DOS_CMDLINE_LENGTH   127

Definition at line 13 of file process.h.

◆ DOS_PROGRAM_NAME_TAG

#define DOS_PROGRAM_NAME_TAG   0x0001

Definition at line 14 of file process.h.

◆ SEGMENT_TO_PSP

#define SEGMENT_TO_PSP (   seg)    ((PDOS_PSP)SEG_OFF_TO_PTR((seg), 0))

Definition at line 16 of file process.h.

Typedef Documentation

◆ DOS_EXEC_PARAM_BLOCK

◆ DOS_PSP

◆ DOS_REGISTER_STATE

◆ PDOS_EXEC_PARAM_BLOCK

◆ PDOS_PSP

◆ PDOS_REGISTER_STATE

Enumeration Type Documentation

◆ DOS_EXEC_TYPE

Enumerator
DOS_LOAD_AND_EXECUTE 
DOS_LOAD_ONLY 
DOS_LOAD_OVERLAY 

Definition at line 18 of file process.h.

19 {
20  DOS_LOAD_AND_EXECUTE = 0x00,
21  DOS_LOAD_ONLY = 0x01,
22  DOS_LOAD_OVERLAY = 0x03
DOS_EXEC_TYPE
Definition: process.h:18

Function Documentation

◆ DosClonePsp()

VOID DosClonePsp ( WORD  DestSegment,
WORD  SourceSegment 
)

Definition at line 243 of file process.c.

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

Referenced by DosInt21h().

◆ DosCreateProcess()

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

◆ DosCreatePsp()

VOID DosCreatePsp ( WORD  Segment,
WORD  ProgramSize 
)

Definition at line 270 of file process.c.

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

Referenced by DosInt21h(), and DosLoadExecutableInternal().

◆ DosLoadExecutable()

DWORD DosLoadExecutable ( IN DOS_EXEC_TYPE  LoadType,
IN LPCSTR  ExecutablePath,
IN PDOS_EXEC_PARAM_BLOCK  Parameters,
IN LPCSTR CommandLine  OPTIONAL,
IN LPCSTR Environment  OPTIONAL,
IN DWORD ReturnAddress  OPTIONAL 
)

Definition at line 695 of file process.c.

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

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

◆ DosLoadExecutableInternal()

DWORD DosLoadExecutableInternal ( IN DOS_EXEC_TYPE  LoadType,
IN LPBYTE  ExeBuffer,
IN DWORD  ExeBufferSize,
IN LPCSTR  ExePath,
IN PDOS_EXEC_PARAM_BLOCK  Parameters,
IN LPCSTR CommandLine  OPTIONAL,
IN LPCSTR Environment  OPTIONAL,
IN DWORD ReturnAddress  OPTIONAL 
)

Definition at line 327 of file process.c.

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

Referenced by DosLoadExecutable(), and DosStartComSpec().

◆ DosSetProcessContext()

VOID DosSetProcessContext ( WORD  Segment)

Definition at line 321 of file process.c.

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

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

◆ DosTerminateProcess()

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

Definition at line 873 of file process.c.

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

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