/* Advance to the next string */
Ptr += strlen(Ptr) + 1;
- DestBuffer += strlen(Ptr) + 1;
+ DestBuffer += strlen(Ptr);
+
+ /* Put a zero after the string */
+ *(DestBuffer++) = 0;
}
/* Set the final zero */
PspBlock->Exit[0] = 0xCD; // int 0x20
PspBlock->Exit[1] = 0x20;
- /* Set the program size */
- PspBlock->MemSize = ProgramSize;
+ /* Set the number of the last paragraph */
+ PspBlock->LastParagraph = PspSegment + ProgramSize - 1;
/* Save the interrupt vectors */
PspBlock->TerminateAddress = IntVecTable[0x22];
LPSTR ProgramFilePath, Parameters[128];
CHAR CommandLineCopy[128];
INT ParamCount = 0;
- WORD i, Segment = 0, FileSize, ExeSize;
+ DWORD Segment = 0;
+ DWORD i, FileSize, ExeSize;
PIMAGE_DOS_HEADER Header;
PDWORD RelocationTable;
PWORD RelocWord;
// TODO: Verify checksum and executable!
/* Get the base size of the file, in paragraphs (rounded up) */
- ExeSize = (((Header->e_cp - 1) << 8) + Header->e_cblp + 0x0F) >> 4;
+ ExeSize = (((Header->e_cp - 1) * 512) + Header->e_cblp + 0x0F) >> 4;
+
+ /* Add the PSP size, in paragraphs */
+ ExeSize += sizeof(DOS_PSP) >> 4;
+
+ /* Add the maximum size that should be allocated */
+ ExeSize += Header->e_maxalloc;
- /* Loop from the maximum to the minimum number of extra paragraphs */
- for (i = Header->e_maxalloc; i >= Header->e_minalloc; i--)
+ /* Make sure it does not pass 0xFFFF */
+ if (ExeSize > 0xFFFF) ExeSize = 0xFFFF;
+
+ /* Reduce the size one by one until the allocation is successful */
+ for (i = Header->e_maxalloc; i >= Header->e_minalloc; i--, ExeSize--)
{
/* Try to allocate that much memory */
- Segment = DosAllocateMemory(ExeSize + (sizeof(DOS_PSP) >> 4) + i, NULL);
+ Segment = DosAllocateMemory(ExeSize, NULL);
if (Segment != 0) break;
}
/* Initialize the PSP */
DosInitializePsp(Segment,
- CommandLine, ExeSize + (sizeof(DOS_PSP) >> 4) + i,
+ CommandLine,
+ ExeSize,
EnvBlock);
/* The process owns its own memory */
CHAR DosReadCharacter()
{
- // TODO: STDIN can be redirected under DOS 2.0+
- CHAR Character = 0;
+ CHAR Character = '\0';
+ WORD BytesRead;
- /* A zero value for the character indicates a special key */
- do Character = BiosGetCharacter();
- while (!Character);
+ /* Use the file reading function */
+ DosReadFile(DOS_INPUT_HANDLE, &Character, sizeof(CHAR), &BytesRead);
return Character;
}
VOID DosPrintCharacter(CHAR Character)
{
- // TODO: STDOUT can be redirected under DOS 2.0+
- if (Character == '\r') Character = '\n';
- putchar(Character);
+ WORD BytesWritten;
+
+ /* Use the file writing function */
+ DosWriteFile(DOS_OUTPUT_HANDLE, &Character, sizeof(CHAR), &BytesWritten);
}
VOID DosInt20h(WORD CodeSegment)
/* Initialize the MCB */
Mcb->BlockType = 'Z';
- Mcb->Size = (WORD)USER_MEMORY_SIZE;
+ Mcb->Size = USER_MEMORY_SIZE;
Mcb->OwnerPsp = 0;
/* Get the environment strings */
/* Move to the next string */
SourcePtr += wcslen(SourcePtr) + 1;
- DestPtr += strlen(AsciiString) + 1;
+ DestPtr += strlen(AsciiString);
+ *(DestPtr++) = 0;
}
+ *DestPtr = 0;
/* Free the memory allocated for environment strings */
FreeEnvironmentStringsW(Environment);