ReactOS 0.4.16-dev-297-gc569aee
process.h File Reference
This graph shows which files directly or indirectly include this file:

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{
21 DOS_LOAD_ONLY = 0x01,
22 DOS_LOAD_OVERLAY = 0x03
DOS_EXEC_TYPE
Definition: process.h:19
@ DOS_LOAD_OVERLAY
Definition: process.h:22
@ DOS_LOAD_ONLY
Definition: process.h:21
@ DOS_LOAD_AND_EXECUTE
Definition: process.h:20

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().

◆ DosCreateProcess()

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

◆ 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().

◆ 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 ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define CloseHandle
Definition: compat.h:739
#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 MAX_PATH
Definition: compat.h:34
#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
unsigned long DWORD
Definition: ntddk_ex.h:95
_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
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
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
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:869
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define CreateFileMapping
Definition: winbase.h:3775
_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 CHAR
Definition: xmlstorage.h:175

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
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
Definition: Header.h:9
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:32
struct _IMAGE_DOS_HEADER * PIMAGE_DOS_HEADER
unsigned short WORD
Definition: ntddk_ex.h:93
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 RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:599
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
#define LOWORD(l)
Definition: pedump.c:82
WORD * PWORD
Definition: pedump.c:67
BYTE * PBYTE
Definition: pedump.c:66
DWORD * PDWORD
Definition: pedump.c:68
WORD LastErrorCode
Definition: dos.h:160
VOID CpuExecute(WORD Segment, WORD Offset)
Definition: cpu.c:102
WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable)
Definition: memory.c:136
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
struct _DOS_PSP DOS_PSP
#define DOS_CMDLINE_LENGTH
Definition: process.h:13
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
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
unsigned char BYTE
Definition: xxhash.c:193

Referenced by DosLoadExecutable(), and DosStartComSpec().

◆ 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
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15
static VOID DosRestoreState(VOID)
Definition: process.c:133
#define MAKEWORD(a, b)
Definition: typedefs.h:248
VOID VDDTerminateUserHook(USHORT DosPDB)
Definition: vddsup.c:466
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639

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