ReactOS  0.4.15-dev-3446-g30010a5
process.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: GPL - See COPYING in the top level directory
3  * PROJECT: ReactOS Virtual DOS Machine
4  * FILE: subsystems/mvdm/ntvdm/dos/dos32krnl/process.c
5  * PURPOSE: DOS32 Processes
6  * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7  * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include "ntvdm.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 #include "emulator.h"
18 #include "cpu/cpu.h"
19 
20 #include "dos.h"
21 #include "dos/dem.h"
22 #include "dosfiles.h"
23 #include "handle.h"
24 #include "process.h"
25 #include "memory.h"
26 
27 #include "bios/bios.h"
28 
29 #include "io.h"
30 #include "hardware/ps2.h"
31 
32 #include "vddsup.h"
33 
34 /* PRIVATE FUNCTIONS **********************************************************/
35 
37  IN WORD EnvBlock,
38  IN LPCSTR CommandLine,
39  IN LPCSTR ProgramName)
40 {
41  PDOS_PSP PspBlock = SEGMENT_TO_PSP(Segment);
43  LPCSTR PspName;
44  USHORT i;
45 
46  /* Link the environment block */
47  PspBlock->EnvBlock = EnvBlock;
48 
49  /*
50  * Copy the command line.
51  * Format of the CommandLine parameter: 1 byte for size; 127 bytes for contents.
52  */
53  PspBlock->CommandLineSize = min(*(PBYTE)CommandLine, DOS_CMDLINE_LENGTH);
54  CommandLine++;
55  RtlCopyMemory(PspBlock->CommandLine, CommandLine, DOS_CMDLINE_LENGTH);
56 
57  /*
58  * Initialize the owner name of the MCB of the PSP.
59  */
60 
61  /* Find the start of the file name, skipping all the path elements */
62  PspName = ProgramName;
63  while (*ProgramName)
64  {
65  switch (*ProgramName++)
66  {
67  /* Path delimiter, skip it */
68  case ':': case '\\': case '/':
69  PspName = ProgramName;
70  break;
71  }
72  }
73  /* Copy the file name up to the extension... */
74  for (i = 0; i < sizeof(Mcb->Name) && PspName[i] != '.' && PspName[i] != '\0'; ++i)
75  {
76  Mcb->Name[i] = RtlUpperChar(PspName[i]);
77  }
78  /* ... and NULL-terminate if needed */
79  if (i < sizeof(Mcb->Name)) Mcb->Name[i] = '\0';
80 
81  // FIXME: Initialize the FCBs
82 }
83 
84 static inline VOID DosSaveState(VOID)
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 }
132 
133 static inline VOID DosRestoreState(VOID)
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 }
180 
182  IN LPCSTR ProgramName)
183 {
184  PCHAR Ptr, DestBuffer = NULL;
185  SIZE_T TotalSize = 0;
186  WORD DestSegment;
187 
188  /* If we have an environment strings list, compute its size */
189  if (Environment)
190  {
191  /* Calculate the size of the environment block */
192  Ptr = (PCHAR)Environment;
193  while (*Ptr) Ptr += strlen(Ptr) + 1;
194  TotalSize = (ULONG_PTR)Ptr - (ULONG_PTR)Environment;
195  }
196  else
197  {
198  /* Empty environment string */
199  TotalSize = 1;
200  }
201  /* Add the final environment block NULL-terminator */
202  TotalSize++;
203 
204  /* Add the two bytes for the program name tag */
205  TotalSize += 2;
206 
207  /* Add the string buffer size */
208  TotalSize += strlen(ProgramName) + 1;
209 
210  /* Allocate the memory for the environment block */
211  DestSegment = DosAllocateMemory((WORD)((TotalSize + 0x0F) >> 4), NULL);
212  if (!DestSegment) return 0;
213 
214  DestBuffer = (PCHAR)SEG_OFF_TO_PTR(DestSegment, 0);
215 
216  /* If we have an environment strings list, copy it */
217  if (Environment)
218  {
219  Ptr = (PCHAR)Environment;
220  while (*Ptr)
221  {
222  /* Copy the string and NULL-terminate it */
223  strcpy(DestBuffer, Ptr);
224  DestBuffer += strlen(Ptr);
225  *(DestBuffer++) = '\0';
226 
227  /* Move to the next string */
228  Ptr += strlen(Ptr) + 1;
229  }
230  }
231  else
232  {
233  /* Empty environment string */
234  *(DestBuffer++) = '\0';
235  }
236  /* NULL-terminate the environment block */
237  *(DestBuffer++) = '\0';
238 
239  /* Store the special program name tag */
240  *(DestBuffer++) = LOBYTE(DOS_PROGRAM_NAME_TAG);
241  *(DestBuffer++) = HIBYTE(DOS_PROGRAM_NAME_TAG);
242 
243  /* Copy the program name after the environment block */
244  strcpy(DestBuffer, ProgramName);
245 
246  return DestSegment;
247 }
248 
249 /* PUBLIC FUNCTIONS ***********************************************************/
250 
251 VOID DosClonePsp(WORD DestSegment, WORD SourceSegment)
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 }
277 
279 {
280  PDOS_PSP PspBlock = SEGMENT_TO_PSP(Segment);
281  LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
282 
283  RtlZeroMemory(PspBlock, sizeof(*PspBlock));
284 
285  /* Set the exit interrupt */
286  PspBlock->Exit[0] = 0xCD; // int 0x20
287  PspBlock->Exit[1] = 0x20;
288 
289  /* Set the number of the last paragraph */
290  PspBlock->LastParagraph = Segment + ProgramSize;
291 
292  /* Save the interrupt vectors */
293  PspBlock->TerminateAddress = IntVecTable[0x22];
294  PspBlock->BreakAddress = IntVecTable[0x23];
295  PspBlock->CriticalAddress = IntVecTable[0x24];
296 
297  /* Set the parent PSP */
298  PspBlock->ParentPsp = Sda->CurrentPsp;
299 
300  if (Sda->CurrentPsp != SYSTEM_PSP)
301  {
302  /* Link to the parent's environment block */
303  PspBlock->EnvBlock = SEGMENT_TO_PSP(Sda->CurrentPsp)->EnvBlock;
304  }
305 /*
306  else
307  {
308  PspBlock->EnvBlock = SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0);
309  }
310 */
311 
312  /* Copy the parent handle table */
313  DosCopyHandleTable(PspBlock->HandleTable);
314 
315  /* Set the handle table pointers to the internal handle table */
316  PspBlock->HandleTableSize = DEFAULT_JFT_SIZE;
317  PspBlock->HandleTablePtr = MAKELONG(0x18, Segment);
318 
319  /* Set the DOS version */
320  // FIXME: This is here that SETVER stuff enters into action!
321  PspBlock->DosVersion = DosData->DosVersion;
322 
323  /* Set the far call opcodes */
324  PspBlock->FarCall[0] = 0xCD; // int 0x21
325  PspBlock->FarCall[1] = 0x21;
326  PspBlock->FarCall[2] = 0xCB; // retf
327 }
328 
330 {
333 }
334 
336  IN LPBYTE ExeBuffer,
337  IN DWORD ExeBufferSize,
338  IN LPCSTR ExePath,
340  IN LPCSTR CommandLine OPTIONAL,
342  IN DWORD ReturnAddress OPTIONAL)
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 explicitely set the interrupt flag.
677  */
678  setEFLAGS((getEFLAGS() & ~0x08D5) | 0x0200);
679 
680  /* Notify VDDs of process execution */
682 
683  /* Execute */
685  CpuExecute(FinalCS, FinalIP);
686  }
687  else if (LoadType == DOS_LOAD_ONLY)
688  {
690  Parameters->StackLocation = MAKELONG(FinalSP, FinalSS);
691  Parameters->EntryPoint = MAKELONG(FinalIP, FinalCS);
692  }
693 
694 Cleanup:
695  if (Result != ERROR_SUCCESS)
696  {
697  /* It was not successful, cleanup the DOS memory */
698  if (EnvBlock) DosFreeMemory(EnvBlock);
700  }
701 
702  return Result;
703 }
704 
706  IN LPCSTR ExecutablePath,
708  IN LPCSTR CommandLine OPTIONAL,
710  IN DWORD ReturnAddress OPTIONAL)
711 {
713  HANDLE FileHandle = INVALID_HANDLE_VALUE, FileMapping = NULL;
714  DWORD FileSize;
715  LPBYTE Address = NULL;
716  CHAR FullPath[MAX_PATH];
717  CHAR ShortFullPath[MAX_PATH];
718 
719  DPRINT1("DosLoadExecutable(%d, '%s', 0x%p, 0x%p, 0x%p)\n",
720  LoadType, ExecutablePath, Parameters, CommandLine, Environment);
721 
722  /* Try to get the full path to the executable */
723  if (GetFullPathNameA(ExecutablePath, sizeof(FullPath), FullPath, NULL))
724  {
725  /* Get the corresponding short path */
726  if (GetShortPathNameA(FullPath, ShortFullPath, sizeof(ShortFullPath)))
727  {
728  /* Use the shortened full path from now on */
729  ExecutablePath = ShortFullPath;
730  }
731  }
732 
733  /* Open a handle to the executable */
734  FileHandle = CreateFileA(ExecutablePath,
735  GENERIC_READ,
737  NULL,
740  NULL);
742  {
743  Result = GetLastError();
744  goto Cleanup;
745  }
746 
747  /* Get the file size */
749 
750  /* Create a mapping object for the file */
751  FileMapping = CreateFileMapping(FileHandle,
752  NULL,
754  0,
755  0,
756  NULL);
757  if (FileMapping == NULL)
758  {
759  Result = GetLastError();
760  goto Cleanup;
761  }
762 
763  /* Map the file into memory */
764  Address = (LPBYTE)MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 0);
765  if (Address == NULL)
766  {
767  Result = GetLastError();
768  goto Cleanup;
769  }
770 
772  Address,
773  FileSize,
774  ExecutablePath,
775  Parameters,
776  CommandLine,
777  Environment,
778  ReturnAddress);
779 
780 Cleanup:
781  /* Unmap the file*/
783 
784  /* Close the file mapping object */
785  if (FileMapping != NULL) CloseHandle(FileMapping);
786 
787  /* Close the file handle */
789 
790  return Result;
791 }
792 
795  IN DWORD ReturnAddress OPTIONAL)
796 {
798  DWORD BinaryType;
799 
800  /* Get the binary type */
801  if (!GetBinaryTypeA(ProgramName, &BinaryType)) return GetLastError();
802 
803  /* Check the type of the program */
804  switch (BinaryType)
805  {
806  /* Those are handled by NTVDM */
807  case SCS_WOW_BINARY:
808  {
809  static const PCSTR AppName = "\"%ProgramFiles%\\otvdm\\otvdmw.exe\" ";
810 
811  STARTUPINFOA si;
813  union { DWORD Size; NTSTATUS Status; } Ret;
814  CHAR ExpName[MAX_PATH];
815 
816  Ret.Size = ExpandEnvironmentStringsA(AppName, ExpName, _countof(ExpName));
817  if ((Ret.Size == 0) || (Ret.Size > _countof(ExpName)))
818  {
819  /* We failed or buffer too small, fall back to DOS execution */
820  goto RunAsDOS;
821  }
822  Ret.Size--; // Remove NULL-terminator from count
823 
824  /* Add double-quotes before and after ProgramName */
825  Ret.Status = RtlStringCchPrintfA(ExpName + Ret.Size, _countof(ExpName) - Ret.Size,
826  "\"%s\"", ProgramName);
827  if (!NT_SUCCESS(Ret.Status))
828  {
829  /* We failed or buffer too small, fall back to DOS execution */
830  goto RunAsDOS;
831  }
832 
833  ZeroMemory(&pi, sizeof(pi));
834  ZeroMemory(&si, sizeof(si));
835  si.cb = sizeof(si);
836 
837  /* Create the process */
838  if (CreateProcessA(NULL, // No Application Name
839  ExpName, // Just our Command Line
840  NULL, // Cannot inherit Process Handle
841  NULL, // Cannot inherit Thread Handle
842  FALSE, // No handle inheritance
843  0, // No extra creation flags
844  NULL, // No environment block
845  NULL, // No starting directory
846  &si,
847  &pi))
848  {
849  /* Close the handles */
850  CloseHandle(pi.hThread);
851  CloseHandle(pi.hProcess);
852  break;
853  }
854  else
855  {
856  /* Retrieve the actual path to the "Program Files" directory for displaying the error */
857  ExpandEnvironmentStringsA("%ProgramFiles%", ExpName, _countof(ExpName));
858 
859  DisplayMessage(L"Trying to load '%S'.\n"
860  L"WOW16 applications are not supported internally by NTVDM at the moment.\n"
861  L"Consider installing WineVDM from the ReactOS Applications Manager in\n'%S'.\n\n"
862  L"Click on OK to continue.",
863  ProgramName, ExpName);
864  }
865  // Fall through
866  }
867  RunAsDOS:
868  case SCS_DOS_BINARY:
869  {
870  /* Load the executable */
872  ProgramName,
873  Parameters,
874  NULL,
875  NULL,
876  ReturnAddress);
877  if (Result != ERROR_SUCCESS)
878  {
879  DisplayMessage(L"Could not load '%S'. Error: %u", ProgramName, Result);
880  }
881 
882  break;
883  }
884 
885  /* Not handled by NTVDM */
886  default:
887  {
890  LPSTR CmdLinePtr;
891  ULONG CmdLineSize;
892 
893  /* Did the caller specify an environment segment? */
894  if (Parameters->Environment)
895  {
896  /* Yes, use it instead of the parent one */
897  Environment = (LPSTR)SEG_OFF_TO_PTR(Parameters->Environment, 0);
898  }
899 
900  /*
901  * Convert the DOS command line to Win32-compatible format, by concatenating
902  * the program name with the converted command line.
903  * Format of the DOS command line: 1 byte for size; 127 bytes for contents.
904  */
905  CmdLinePtr = CmdLine;
906  strncpy(CmdLinePtr, ProgramName, MAX_PATH); // Concatenate the program name
907  CmdLinePtr += strlen(CmdLinePtr);
908  *CmdLinePtr++ = ' '; // Add separating space
909 
910  CmdLineSize = min(*(PBYTE)FAR_POINTER(Parameters->CommandLine), DOS_CMDLINE_LENGTH);
911  RtlCopyMemory(CmdLinePtr,
912  (LPSTR)FAR_POINTER(Parameters->CommandLine) + 1,
913  CmdLineSize);
914  /* NULL-terminate it */
915  CmdLinePtr[CmdLineSize] = '\0';
916 
917  /* Remove any trailing return carriage character and NULL-terminate the command line */
918  while (*CmdLinePtr && *CmdLinePtr != '\r' && *CmdLinePtr != '\n') CmdLinePtr++;
919  *CmdLinePtr = '\0';
920 
921  Result = DosStartProcess32(ProgramName, CmdLine,
922  Environment, ReturnAddress,
923  TRUE);
924  if (Result != ERROR_SUCCESS)
925  {
926  DisplayMessage(L"Could not load 32-bit '%S'. Error: %u", ProgramName, Result);
927  }
928 
929  break;
930  }
931  }
932 
933  return Result;
934 }
935 
936 VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode, WORD KeepResident)
937 {
938  WORD McbSegment = SysVars->FirstMcb;
939  PDOS_MCB CurrentMcb;
940  LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
941  PDOS_PSP PspBlock = SEGMENT_TO_PSP(Psp);
942  LPWORD Stack;
943  BYTE TerminationType;
944 
945  DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X, KeepResident 0x%04X\n",
946  Psp, ReturnCode, KeepResident);
947 
948  /* Notify VDDs of process termination */
950 
951  /* Check if this PSP is its own parent */
952  if (PspBlock->ParentPsp == Psp) goto Done;
953 
954  if (KeepResident == 0)
955  {
956  WORD i;
957  for (i = 0; i < PspBlock->HandleTableSize; i++)
958  {
959  /* Close the handle */
960  DosCloseHandle(i);
961  }
962  }
963 
964  /* Free the memory used by the process */
965  while (TRUE)
966  {
967  /* Get a pointer to the MCB */
968  CurrentMcb = SEGMENT_TO_MCB(McbSegment);
969 
970  /* Make sure the MCB is valid */
971  if (CurrentMcb->BlockType != 'M' && CurrentMcb->BlockType != 'Z') break;
972 
973  /* Check if this block was allocated by the process */
974  if (CurrentMcb->OwnerPsp == Psp)
975  {
976  if (KeepResident)
977  {
978  /* Check if this is the PSP block and we should reduce its size */
979  if ((McbSegment + 1) == Psp && KeepResident < CurrentMcb->Size)
980  {
981  /* Reduce the size of the block */
982  DosResizeMemory(McbSegment + 1, KeepResident, NULL);
983  break;
984  }
985  }
986  else
987  {
988  /* Free this entire block */
989  DosFreeMemory(McbSegment + 1);
990  }
991  }
992 
993  /* If this was the last block, quit */
994  if (CurrentMcb->BlockType == 'Z') break;
995 
996  /* Update the segment and continue */
997  McbSegment += CurrentMcb->Size + 1;
998  }
999 
1000 Done:
1001  /* Restore the interrupt vectors */
1002  IntVecTable[0x22] = PspBlock->TerminateAddress;
1003  IntVecTable[0x23] = PspBlock->BreakAddress;
1004  IntVecTable[0x24] = PspBlock->CriticalAddress;
1005 
1006  /* Update the current PSP with the parent's one */
1007  if (Psp == Sda->CurrentPsp)
1008  {
1009  DosSetProcessContext(PspBlock->ParentPsp);
1010  if (Sda->CurrentPsp == SYSTEM_PSP)
1011  {
1012  // NOTE: we can also use the DOS BIOS exit code.
1013  CpuUnsimulate();
1014  return;
1015  }
1016  }
1017 
1018  /* Save the return code - Normal termination or TSR */
1019  TerminationType = (KeepResident != 0 ? 0x03 : 0x00);
1020  Sda->ErrorLevel = MAKEWORD(ReturnCode, TerminationType);
1021 
1022 #ifdef ADVANCED_DEBUGGING
1023  DPRINT1("PspBlock->ParentPsp = 0x%04x; Sda->CurrentPsp = 0x%04x\n",
1024  PspBlock->ParentPsp, Sda->CurrentPsp);
1025 #endif
1026 
1027  if (Sda->CurrentPsp != SYSTEM_PSP)
1028  {
1029 #ifdef ADVANCED_DEBUGGING
1030  DPRINT1("Sda->CurrentPsp = 0x%04x; Old SS:SP = %04X:%04X going to be LastStack = 0x%08x\n",
1031  Sda->CurrentPsp, getSS(), getSP(), SEGMENT_TO_PSP(Sda->CurrentPsp)->LastStack);
1032 #endif
1033 
1034  /* Restore the parent's stack */
1035  setSS(HIWORD(SEGMENT_TO_PSP(Sda->CurrentPsp)->LastStack));
1036  setSP(LOWORD(SEGMENT_TO_PSP(Sda->CurrentPsp)->LastStack));
1037 
1038  /* Pop the task state */
1039  DosRestoreState();
1040  }
1041 
1042  /* Return control to the parent process */
1044  Stack[STACK_CS] = HIWORD(PspBlock->TerminateAddress);
1045  Stack[STACK_IP] = LOWORD(PspBlock->TerminateAddress);
1046 }
1047 
1048 /* EOF */
WORD LastErrorCode
Definition: dos.h:151
signed char * PCHAR
Definition: retypes.h:7
BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable)
Definition: memory.c:289
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
#define IN
Definition: typedefs.h:39
USHORT WINAPI getBX(VOID)
Definition: registers.c:170
WORD CurrentPsp
Definition: dos.h:156
#define CloseHandle
Definition: compat.h:598
WORD DosCreateProcess(IN LPCSTR ProgramName, IN PDOS_EXEC_PARAM_BLOCK Parameters, IN DWORD ReturnAddress OPTIONAL)
Definition: process.c:793
#define ERROR_SUCCESS
Definition: deptool.c:10
#define MapViewOfFile
Definition: compat.h:604
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:863
USHORT WINAPI getSI(VOID)
Definition: registers.c:404
#define LOBYTE(W)
Definition: jmemdos.c:487
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define MAKEWORD(a, b)
Definition: typedefs.h:248
USHORT WINAPI getCX(VOID)
Definition: registers.c:228
struct _DOS_REGISTER_STATE DOS_REGISTER_STATE
DOS_EXEC_TYPE
Definition: process.h:18
#define TRUE
Definition: types.h:120
static VOID DosRestoreState(VOID)
Definition: process.c:133
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
VOID WINAPI setAX(USHORT)
Definition: registers.c:121
char CHAR
Definition: xmlstorage.h:175
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
VOID WINAPI setDS(USHORT)
Definition: registers.c:515
BOOLEAN DosFreeMemory(WORD BlockData)
Definition: memory.c:418
LONG NTSTATUS
Definition: precomp.h:26
#define DEFAULT_JFT_SIZE
Definition: handle.h:13
#define CreateFileMapping
Definition: winbase.h:3606
#define HIBYTE(W)
Definition: jmemdos.c:486
static CHAR AppName[MAX_PATH]
Definition: dem.c:252
_In_ ULONG _In_ ULONG State
Definition: potypes.h:516
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define DOS_CMDLINE_LENGTH
Definition: process.h:13
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
#define ZeroMemory
Definition: winbase.h:1664
USHORT WINAPI getSS(VOID)
Definition: registers.c:494
BYTE HandleTable[20]
Definition: process.h:36
char * LPSTR
Definition: xmlstorage.h:182
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:32
#define FILE_SHARE_READ
Definition: compat.h:136
BYTE CommandLineSize
Definition: process.h:48
PDOS_DATA DosData
Definition: dos.c:45
VOID VDDTerminateUserHook(USHORT DosPDB)
Definition: vddsup.c:466
uint32_t ULONG_PTR
Definition: typedefs.h:65
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:992
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
VOID WINAPI setES(USHORT)
Definition: registers.c:529
HANDLE FileHandle
Definition: stats.c:38
VOID WINAPI setSP(USHORT)
Definition: registers.c:351
static const WCHAR CmdLine[]
Definition: install.c:48
#define L(x)
Definition: ntvdm.h:50
#define SCS_DOS_BINARY
Definition: winbase.h:235
unsigned char * LPBYTE
Definition: typedefs.h:53
#define FALSE
Definition: types.h:117
WORD LastParagraph
Definition: process.h:30
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
CHAR CommandLine[DOS_CMDLINE_LENGTH]
Definition: process.h:49
NTSTRSAFEVAPI RtlStringCchPrintfA(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,...)
Definition: ntstrsafe.h:1085
#define SCS_WOW_BINARY
Definition: winbase.h:239
#define MAKELONG(a, b)
Definition: typedefs.h:249
unsigned char BOOLEAN
VOID DosCopyHandleTable(LPBYTE DestinationTable)
Definition: handle.c:27
static WCHAR Address[46]
Definition: ping.c:68
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
DWORD WINAPI ExpandEnvironmentStringsA(IN LPCSTR lpSrc, IN LPSTR lpDst, IN DWORD nSize)
Definition: environ.c:399
#define FAR_POINTER(x)
Definition: emulator.h:35
#define FILE_MAP_READ
Definition: compat.h:635
VOID DosSetProcessContext(WORD Segment)
Definition: process.c:329
const char * LPCSTR
Definition: xmlstorage.h:183
static PDWORD
Definition: process.c:68
static VOID DosSaveState(VOID)
Definition: process.c:84
WORD HandleTableSize
Definition: process.h:39
#define OPEN_EXISTING
Definition: compat.h:634
_Inout_ PVOID Segment
Definition: exfuncs.h:1101
DWORD HandleTablePtr
Definition: process.h:40
static WORD DosCopyEnvironmentBlock(IN LPCSTR Environment OPTIONAL, IN LPCSTR ProgramName)
Definition: process.c:181
#define PCHAR
Definition: match.c:90
WORD FirstMcb
Definition: dos.h:77
WORD * PWORD
Definition: pedump.c:67
Status
Definition: gdiplustypes.h:24
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
struct _DOS_PSP DOS_PSP
#define DOS_PROGRAM_NAME_TAG
Definition: process.h:14
DWORD cb
Definition: winbase.h:825
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static refpint_t pi[]
Definition: server.c:96
USHORT WINAPI getES(VOID)
Definition: registers.c:522
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
static PULONG
Definition: process.c:83
#define _countof(array)
Definition: sndvol32.h:68
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4743
DWORD WINAPI GetShortPathNameA(IN LPCSTR lpszLongPath, OUT LPSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1751
#define MAX_PATH
Definition: compat.h:34
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
BYTE Exit[2]
Definition: process.h:29
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
DWORD TerminateAddress
Definition: process.h:32
VOID WINAPI setBP(USHORT)
Definition: registers.c:381
VOID DosChangeMemoryOwner(WORD Segment, WORD NewOwner)
Definition: memory.c:532
NTSYSAPI CHAR NTAPI RtlUpperChar(CHAR Character)
VOID WINAPI setDX(USHORT)
Definition: registers.c:293
VOID DosCreatePsp(WORD Segment, WORD ProgramSize)
Definition: process.c:278
VOID CpuUnsimulate(VOID)
Definition: cpu.c:203
BOOL WINAPI GetBinaryTypeA(IN LPCSTR lpApplicationName, OUT LPDWORD lpBinaryType)
Definition: vdm.c:1335
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
VOID CpuExecute(WORD Segment, WORD Offset)
Definition: cpu.c:102
#define LPDWORD
Definition: nt_native.h:46
USHORT WINAPI getDX(VOID)
Definition: registers.c:286
WORD OwnerPsp
Definition: memory.h:31
WORD ParentPsp
Definition: process.h:35
USHORT WINAPI getAX(VOID)
Definition: registers.c:114
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
DWORD DosStartProcess32(IN LPCSTR ExecutablePath, IN LPCSTR CommandLine, IN LPCSTR Environment OPTIONAL, IN DWORD ReturnAddress OPTIONAL, IN BOOLEAN StartComSpec)
Definition: dem.c:916
VOID DosClonePsp(WORD DestSegment, WORD SourceSegment)
Definition: process.c:251
PDOS_SDA Sda
Definition: dos.c:48
VOID WINAPI setEFLAGS(ULONG)
Definition: registers.c:687
#define GENERIC_READ
Definition: compat.h:135
#define STACK_CS
Definition: int32.h:34
static const WCHAR Cleanup[]
Definition: register.c:80
VOID WINAPI setBX(USHORT)
Definition: registers.c:177
unsigned char BYTE
Definition: xxhash.c:193
WORD ErrorLevel
Definition: dos.h:158
uint16_t * LPWORD
Definition: typedefs.h:56
DWORD DiskTransferArea
Definition: dos.h:155
VOID WINAPI setDI(USHORT)
Definition: registers.c:441
ULONG_PTR SIZE_T
Definition: typedefs.h:80
VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode, WORD KeepResident)
Definition: process.c:936
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned short USHORT
Definition: pedump.c:61
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
USHORT WINAPI getDI(VOID)
Definition: registers.c:434
PDOS_SYSVARS SysVars
Definition: dos.c:47
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:343
#define SYSTEM_PSP
Definition: dos.h:39
#define min(a, b)
Definition: monoChain.cc:55
CHAR BlockType
Definition: memory.h:30
#define NULL
Definition: types.h:112
#define PAGE_READONLY
Definition: compat.h:138
DWORD * PDWORD
Definition: pedump.c:68
VOID WINAPI setCX(USHORT)
Definition: registers.c:235
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
DWORD BreakAddress
Definition: process.h:33
#define DPRINT1
Definition: precomp.h:8
BYTE FarCall[3]
Definition: process.h:45
USHORT WINAPI getDS(VOID)
Definition: registers.c:508
uint32_t * LPDWORD
Definition: typedefs.h:59
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
WORD DosVersion
Definition: process.h:43
#define HIWORD(l)
Definition: typedefs.h:247
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
const char * PCSTR
Definition: typedefs.h:52
DWORD CriticalAddress
Definition: process.h:34
USHORT WINAPI getBP(VOID)
Definition: registers.c:374
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:599
USHORT WINAPI getSP(VOID)
Definition: registers.c:344
WORD Size
Definition: memory.h:32
#define DPRINT
Definition: sndvol32.h:71
WORD DosVersion
Definition: dos.h:246
void DisplayMessage(BOOL bConsole, BOOL bSilent, LPCTSTR lpMessage, LPCTSTR lpTitle, UINT uType)
Definition: regsvr32.c:239
BOOLEAN DosCloseHandle(WORD DosHandle)
Definition: handle.c:311
#define UnmapViewOfFile
Definition: compat.h:605
#define STACK_IP
Definition: int32.h:33
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15
BYTE * PBYTE
Definition: pedump.c:66
#define LOWORD(l)
Definition: pedump.c:82
WORD EnvBlock
Definition: process.h:37
static LPSTR
Definition: process.c:74
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68