mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-02 13:27:35 +00:00
Implemented DOS INT21 AH=4B (EXEC).
This commit is contained in:
parent
7b0bf0f08d
commit
7c4bee569c
5 changed files with 242 additions and 60 deletions
|
@ -14,7 +14,7 @@
|
||||||
struct _DOSEVENT;
|
struct _DOSEVENT;
|
||||||
|
|
||||||
typedef struct _DOSTASK {
|
typedef struct _DOSTASK {
|
||||||
WORD psp_seg;
|
WORD psp_seg, retval;
|
||||||
WORD dpmi_flag;
|
WORD dpmi_flag;
|
||||||
} DOSTASK, *LPDOSTASK;
|
} DOSTASK, *LPDOSTASK;
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ typedef struct _DOSTASK {
|
||||||
#define V86_FLAG 0x00020000
|
#define V86_FLAG 0x00020000
|
||||||
|
|
||||||
extern BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename );
|
extern BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename );
|
||||||
|
extern BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
|
||||||
|
extern void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval );
|
||||||
extern LPDOSTASK MZ_Current( void );
|
extern LPDOSTASK MZ_Current( void );
|
||||||
extern LPDOSTASK MZ_AllocDPMITask( void );
|
extern LPDOSTASK MZ_AllocDPMITask( void );
|
||||||
extern int DOSVM_Enter( CONTEXT86 *context );
|
extern int DOSVM_Enter( CONTEXT86 *context );
|
||||||
|
|
|
@ -26,7 +26,7 @@ typedef struct
|
||||||
WORD parentPSP; /* 16 Selector of parent PSP */
|
WORD parentPSP; /* 16 Selector of parent PSP */
|
||||||
BYTE fileHandles[20]; /* 18 Open file handles */
|
BYTE fileHandles[20]; /* 18 Open file handles */
|
||||||
HANDLE16 environment; /* 2c Selector of environment */
|
HANDLE16 environment; /* 2c Selector of environment */
|
||||||
WORD reserved2[2];
|
DWORD saveStack; /* 2e SS:SP on last int21 call */
|
||||||
WORD nbFiles; /* 32 Number of file handles */
|
WORD nbFiles; /* 32 Number of file handles */
|
||||||
SEGPTR fileHandlesPtr; /* 34 Pointer to file handle table */
|
SEGPTR fileHandlesPtr; /* 34 Pointer to file handle table */
|
||||||
HANDLE16 hFileHandles; /* 38 Handle to fileHandlesPtr */
|
HANDLE16 hFileHandles; /* 38 Handle to fileHandlesPtr */
|
||||||
|
|
|
@ -55,6 +55,26 @@ static LPDOSTASK dos_current;
|
||||||
#define SEG16(ptr,seg) ((LPVOID)((BYTE*)ptr+((DWORD)(seg)<<4)))
|
#define SEG16(ptr,seg) ((LPVOID)((BYTE*)ptr+((DWORD)(seg)<<4)))
|
||||||
#define SEGPTR16(ptr,segptr) ((LPVOID)((BYTE*)ptr+((DWORD)SELECTOROF(segptr)<<4)+OFFSETOF(segptr)))
|
#define SEGPTR16(ptr,segptr) ((LPVOID)((BYTE*)ptr+((DWORD)SELECTOROF(segptr)<<4)+OFFSETOF(segptr)))
|
||||||
|
|
||||||
|
/* structures for EXEC */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD env_seg;
|
||||||
|
DWORD cmdline WINE_PACKED;
|
||||||
|
DWORD fcb1 WINE_PACKED;
|
||||||
|
DWORD fcb2 WINE_PACKED;
|
||||||
|
WORD init_sp;
|
||||||
|
WORD init_ss;
|
||||||
|
WORD init_ip;
|
||||||
|
WORD init_cs;
|
||||||
|
} ExecBlock;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD load_seg;
|
||||||
|
WORD rel_seg;
|
||||||
|
} OverlayBlock;
|
||||||
|
|
||||||
|
/* global variables */
|
||||||
|
|
||||||
static WORD init_cs,init_ip,init_ss,init_sp;
|
static WORD init_cs,init_ip,init_ss,init_sp;
|
||||||
static char mm_name[128];
|
static char mm_name[128];
|
||||||
|
|
||||||
|
@ -66,15 +86,20 @@ static void MZ_Launch(void);
|
||||||
static BOOL MZ_InitTask(void);
|
static BOOL MZ_InitTask(void);
|
||||||
static void MZ_KillTask(void);
|
static void MZ_KillTask(void);
|
||||||
|
|
||||||
static void MZ_CreatePSP( LPVOID lpPSP, WORD env )
|
static void MZ_CreatePSP( LPVOID lpPSP, WORD env, WORD par )
|
||||||
{
|
{
|
||||||
PDB16*psp=lpPSP;
|
PDB16*psp=lpPSP;
|
||||||
|
|
||||||
psp->int20=0x20CD; /* int 20 */
|
psp->int20=0x20CD; /* int 20 */
|
||||||
/* some programs use this to calculate how much memory they need */
|
/* some programs use this to calculate how much memory they need */
|
||||||
psp->nextParagraph=0x9FFF;
|
psp->nextParagraph=0x9FFF; /* FIXME: use a real value */
|
||||||
psp->environment=env;
|
/* FIXME: dispatcher */
|
||||||
/* FIXME: more PSP stuff */
|
psp->savedint22 = INT_GetRMHandler(0x22);
|
||||||
|
psp->savedint23 = INT_GetRMHandler(0x23);
|
||||||
|
psp->savedint24 = INT_GetRMHandler(0x24);
|
||||||
|
psp->parentPSP=par;
|
||||||
|
psp->environment=env;
|
||||||
|
/* FIXME: more PSP stuff */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MZ_FillPSP( LPVOID lpPSP, LPCSTR cmdline )
|
static void MZ_FillPSP( LPVOID lpPSP, LPCSTR cmdline )
|
||||||
|
@ -178,25 +203,30 @@ static BOOL MZ_InitMemory(void)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
|
BOOL MZ_DoLoadImage( HMODULE module, HANDLE hFile, LPCSTR filename, OverlayBlock *oblk )
|
||||||
{
|
{
|
||||||
LPDOSTASK lpDosTask = dos_current;
|
LPDOSTASK lpDosTask = dos_current;
|
||||||
IMAGE_NT_HEADERS *win_hdr = PE_HEADER(module);
|
|
||||||
IMAGE_DOS_HEADER mz_header;
|
IMAGE_DOS_HEADER mz_header;
|
||||||
DWORD image_start,image_size,min_size,max_size,avail;
|
DWORD image_start,image_size,min_size,max_size,avail;
|
||||||
BYTE*psp_start,*load_start;
|
BYTE*psp_start,*load_start,*oldenv;
|
||||||
int x, old_com=0, alloc=0;
|
int x, old_com=0, alloc;
|
||||||
SEGPTR reloc;
|
SEGPTR reloc;
|
||||||
WORD env_seg, load_seg;
|
WORD env_seg, load_seg, rel_seg, oldpsp_seg;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
|
|
||||||
win_hdr->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
if (lpDosTask) {
|
||||||
win_hdr->OptionalHeader.AddressOfEntryPoint = (LPBYTE)MZ_Launch - (LPBYTE)module;
|
/* DOS process already running, inherit from it */
|
||||||
|
PDB16* par_psp = (PDB16*)((DWORD)lpDosTask->psp_seg << 4);
|
||||||
if (!lpDosTask) {
|
alloc=0;
|
||||||
|
oldenv = (LPBYTE)((DWORD)par_psp->environment << 4);
|
||||||
|
oldpsp_seg = lpDosTask->psp_seg;
|
||||||
|
} else {
|
||||||
|
/* allocate new DOS process, inheriting from Wine environment */
|
||||||
alloc=1;
|
alloc=1;
|
||||||
lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
|
lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
|
||||||
dos_current = lpDosTask;
|
dos_current = lpDosTask;
|
||||||
|
oldenv = GetEnvironmentStringsA();
|
||||||
|
oldpsp_seg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetFilePointer(hFile,0,NULL,FILE_BEGIN);
|
SetFilePointer(hFile,0,NULL,FILE_BEGIN);
|
||||||
|
@ -220,29 +250,37 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
|
||||||
max_size=image_size+((DWORD)mz_header.e_maxalloc<<4)+(PSP_SIZE<<4);
|
max_size=image_size+((DWORD)mz_header.e_maxalloc<<4)+(PSP_SIZE<<4);
|
||||||
}
|
}
|
||||||
|
|
||||||
MZ_InitMemory();
|
if (alloc) MZ_InitMemory();
|
||||||
|
|
||||||
/* allocate environment block */
|
if (oblk) {
|
||||||
env_seg=MZ_InitEnvironment(GetEnvironmentStringsA(),filename);
|
/* load overlay into preallocated memory */
|
||||||
|
load_seg=oblk->load_seg;
|
||||||
|
rel_seg=oblk->rel_seg;
|
||||||
|
load_start=(LPBYTE)((DWORD)load_seg<<4);
|
||||||
|
} else {
|
||||||
|
/* allocate environment block */
|
||||||
|
env_seg=MZ_InitEnvironment(oldenv, filename);
|
||||||
|
|
||||||
/* allocate memory for the executable */
|
/* allocate memory for the executable */
|
||||||
TRACE("Allocating DOS memory (min=%ld, max=%ld)\n",min_size,max_size);
|
TRACE("Allocating DOS memory (min=%ld, max=%ld)\n",min_size,max_size);
|
||||||
avail=DOSMEM_Available();
|
avail=DOSMEM_Available();
|
||||||
if (avail<min_size) {
|
if (avail<min_size) {
|
||||||
ERR("insufficient DOS memory\n");
|
ERR("insufficient DOS memory\n");
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
goto load_error;
|
goto load_error;
|
||||||
}
|
}
|
||||||
if (avail>max_size) avail=max_size;
|
if (avail>max_size) avail=max_size;
|
||||||
psp_start=DOSMEM_GetBlock(avail,&lpDosTask->psp_seg);
|
psp_start=DOSMEM_GetBlock(avail,&lpDosTask->psp_seg);
|
||||||
if (!psp_start) {
|
if (!psp_start) {
|
||||||
ERR("error allocating DOS memory\n");
|
ERR("error allocating DOS memory\n");
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
goto load_error;
|
goto load_error;
|
||||||
}
|
}
|
||||||
load_seg=lpDosTask->psp_seg+(old_com?0:PSP_SIZE);
|
load_seg=lpDosTask->psp_seg+(old_com?0:PSP_SIZE);
|
||||||
load_start=psp_start+(PSP_SIZE<<4);
|
rel_seg=load_seg;
|
||||||
MZ_CreatePSP(psp_start, env_seg);
|
load_start=psp_start+(PSP_SIZE<<4);
|
||||||
|
MZ_CreatePSP(psp_start, env_seg, oldpsp_seg);
|
||||||
|
}
|
||||||
|
|
||||||
/* load executable image */
|
/* load executable image */
|
||||||
TRACE("loading DOS %s image, %08lx bytes\n",old_com?"COM":"EXE",image_size);
|
TRACE("loading DOS %s image, %08lx bytes\n",old_com?"COM":"EXE",image_size);
|
||||||
|
@ -262,18 +300,20 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
|
||||||
SetLastError(ERROR_BAD_FORMAT);
|
SetLastError(ERROR_BAD_FORMAT);
|
||||||
goto load_error;
|
goto load_error;
|
||||||
}
|
}
|
||||||
*(WORD*)SEGPTR16(load_start,reloc)+=load_seg;
|
*(WORD*)SEGPTR16(load_start,reloc)+=rel_seg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init_cs = load_seg+mz_header.e_cs;
|
if (!oblk) {
|
||||||
init_ip = mz_header.e_ip;
|
init_cs = load_seg+mz_header.e_cs;
|
||||||
init_ss = load_seg+mz_header.e_ss;
|
init_ip = mz_header.e_ip;
|
||||||
init_sp = mz_header.e_sp;
|
init_ss = load_seg+mz_header.e_ss;
|
||||||
|
init_sp = mz_header.e_sp;
|
||||||
|
|
||||||
TRACE("entry point: %04x:%04x\n",init_cs,init_ip);
|
TRACE("entry point: %04x:%04x\n",init_cs,init_ip);
|
||||||
|
}
|
||||||
|
|
||||||
if (!MZ_InitTask()) {
|
if (alloc && !MZ_InitTask()) {
|
||||||
MZ_KillTask();
|
MZ_KillTask();
|
||||||
SetLastError(ERROR_GEN_FAILURE);
|
SetLastError(ERROR_GEN_FAILURE);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -282,6 +322,7 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
load_error:
|
load_error:
|
||||||
|
lpDosTask->psp_seg = oldpsp_seg;
|
||||||
if (alloc) {
|
if (alloc) {
|
||||||
dos_current = NULL;
|
dos_current = NULL;
|
||||||
if (mm_name[0]!=0) unlink(mm_name);
|
if (mm_name[0]!=0) unlink(mm_name);
|
||||||
|
@ -290,6 +331,80 @@ load_error:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
|
||||||
|
{
|
||||||
|
IMAGE_NT_HEADERS *win_hdr = PE_HEADER(module);
|
||||||
|
|
||||||
|
if (win_hdr) {
|
||||||
|
win_hdr->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||||
|
win_hdr->OptionalHeader.AddressOfEntryPoint = (LPBYTE)MZ_Launch - (LPBYTE)module;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MZ_DoLoadImage( module, hFile, filename, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
|
||||||
|
{
|
||||||
|
/* this may only be called from existing DOS processes
|
||||||
|
* (i.e. one DOS app spawning another) */
|
||||||
|
/* FIXME: do we want to check binary type first, to check
|
||||||
|
* whether it's a NE/PE executable? */
|
||||||
|
LPDOSTASK lpDosTask = MZ_Current();
|
||||||
|
HFILE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ,
|
||||||
|
NULL, OPEN_EXISTING, 0, -1);
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE) return FALSE;
|
||||||
|
switch (func) {
|
||||||
|
case 0: /* load and execute */
|
||||||
|
case 1: /* load but don't execute */
|
||||||
|
{
|
||||||
|
/* save current process's return SS:SP now */
|
||||||
|
LPBYTE psp_start = (LPBYTE)((DWORD)lpDosTask->psp_seg << 4);
|
||||||
|
PDB16 *psp = (PDB16 *)psp_start;
|
||||||
|
psp->saveStack = (DWORD)PTR_SEG_OFF_TO_SEGPTR(context->SegSs, LOWORD(context->Esp));
|
||||||
|
}
|
||||||
|
ret = MZ_DoLoadImage( NULL, hFile, filename, NULL );
|
||||||
|
if (ret) {
|
||||||
|
/* MZ_LoadImage created a new PSP and loaded new values into lpDosTask,
|
||||||
|
* let's work on the new values now */
|
||||||
|
LPBYTE psp_start = (LPBYTE)((DWORD)lpDosTask->psp_seg << 4);
|
||||||
|
ExecBlock *blk = (ExecBlock *)paramblk;
|
||||||
|
MZ_FillPSP(psp_start, DOSMEM_MapRealToLinear(blk->cmdline));
|
||||||
|
/* the lame MS-DOS engineers decided that the return address should be in int22 */
|
||||||
|
INT_SetRMHandler(0x22, (FARPROC16)PTR_SEG_OFF_TO_SEGPTR(context->SegCs, LOWORD(context->Eip)));
|
||||||
|
if (func) {
|
||||||
|
/* don't execute, just return startup state */
|
||||||
|
blk->init_cs = init_cs;
|
||||||
|
blk->init_ip = init_ip;
|
||||||
|
blk->init_ss = init_ss;
|
||||||
|
blk->init_sp = init_sp;
|
||||||
|
} else {
|
||||||
|
/* execute by making us return to new process */
|
||||||
|
context->SegCs = init_cs;
|
||||||
|
context->Eip = init_ip;
|
||||||
|
context->SegSs = init_ss;
|
||||||
|
context->Esp = init_sp;
|
||||||
|
context->SegDs = lpDosTask->psp_seg;
|
||||||
|
context->SegEs = lpDosTask->psp_seg;
|
||||||
|
context->Eax = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3: /* load overlay */
|
||||||
|
{
|
||||||
|
OverlayBlock *blk = (OverlayBlock *)paramblk;
|
||||||
|
ret = MZ_DoLoadImage( NULL, hFile, filename, blk );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FIXME("EXEC load type %d not implemented\n", func);
|
||||||
|
SetLastError(ERROR_INVALID_FUNCTION);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
LPDOSTASK MZ_AllocDPMITask( void )
|
LPDOSTASK MZ_AllocDPMITask( void )
|
||||||
{
|
{
|
||||||
LPDOSTASK lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
|
LPDOSTASK lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
|
||||||
|
@ -435,21 +550,70 @@ static void MZ_KillTask(void)
|
||||||
kill(dosmod_pid,SIGTERM);
|
kill(dosmod_pid,SIGTERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
|
||||||
|
{
|
||||||
|
LPDOSTASK lpDosTask = MZ_Current();
|
||||||
|
if (lpDosTask) {
|
||||||
|
WORD psp_seg = cs_psp ? context->SegCs : lpDosTask->psp_seg;
|
||||||
|
LPBYTE psp_start = (LPBYTE)((DWORD)psp_seg << 4);
|
||||||
|
PDB16 *psp = (PDB16 *)psp_start;
|
||||||
|
WORD parpsp = psp->parentPSP; /* check for parent DOS process */
|
||||||
|
if (parpsp) {
|
||||||
|
/* retrieve parent's return address */
|
||||||
|
FARPROC16 retaddr = INT_GetRMHandler(0x22);
|
||||||
|
/* restore interrupts */
|
||||||
|
INT_SetRMHandler(0x22, psp->savedint22);
|
||||||
|
INT_SetRMHandler(0x23, psp->savedint23);
|
||||||
|
INT_SetRMHandler(0x24, psp->savedint24);
|
||||||
|
/* FIXME: deallocate file handles etc */
|
||||||
|
/* free process's associated memory
|
||||||
|
* FIXME: walk memory and deallocate all blocks owned by process */
|
||||||
|
DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(MAKELONG(0,psp->environment)));
|
||||||
|
DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(MAKELONG(0,lpDosTask->psp_seg)));
|
||||||
|
/* switch to parent's PSP */
|
||||||
|
lpDosTask->psp_seg = parpsp;
|
||||||
|
psp_start = (LPBYTE)((DWORD)parpsp << 4);
|
||||||
|
psp = (PDB16 *)psp_start;
|
||||||
|
/* now return to parent */
|
||||||
|
lpDosTask->retval = retval;
|
||||||
|
context->SegCs = SELECTOROF(retaddr);
|
||||||
|
context->Eip = OFFSETOF(retaddr);
|
||||||
|
context->SegSs = SELECTOROF(psp->saveStack);
|
||||||
|
context->Esp = OFFSETOF(psp->saveStack);
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
MZ_KillTask();
|
||||||
|
}
|
||||||
|
ExitThread( retval );
|
||||||
|
}
|
||||||
|
|
||||||
#else /* !MZ_SUPPORTED */
|
#else /* !MZ_SUPPORTED */
|
||||||
|
|
||||||
BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
|
BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
|
||||||
{
|
{
|
||||||
WARN("DOS executables not supported on this architecture\n");
|
WARN("DOS executables not supported on this platform\n");
|
||||||
SetLastError(ERROR_BAD_FORMAT);
|
SetLastError(ERROR_BAD_FORMAT);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
|
||||||
|
{
|
||||||
|
/* can't happen */
|
||||||
|
SetLastError(ERROR_BAD_FORMAT);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPDOSTASK MZ_AllocDPMITask( void )
|
LPDOSTASK MZ_AllocDPMITask( void )
|
||||||
{
|
{
|
||||||
ERR("Actual real-mode calls not supported on this architecture!\n");
|
ERR("Actual real-mode calls not supported on this platform!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
|
||||||
|
{
|
||||||
|
ExitThread( retval );
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* !MZ_SUPPORTED */
|
#endif /* !MZ_SUPPORTED */
|
||||||
|
|
||||||
LPDOSTASK MZ_Current( void )
|
LPDOSTASK MZ_Current( void )
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
/* #define DEBUG_INT */
|
/* #define DEBUG_INT */
|
||||||
#include "debugtools.h"
|
#include "debugtools.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
#include "dosexe.h"
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* INT_Int20Handler
|
* INT_Int20Handler
|
||||||
|
@ -16,5 +17,5 @@
|
||||||
*/
|
*/
|
||||||
void WINAPI INT_Int20Handler( CONTEXT86 *context )
|
void WINAPI INT_Int20Handler( CONTEXT86 *context )
|
||||||
{
|
{
|
||||||
ExitThread( 0 );
|
MZ_Exit( context, TRUE, 0 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -954,7 +954,7 @@ static void INT21_SetCurrentPSP(WORD psp)
|
||||||
ERR("Cannot change PSP for non-DOS task!\n");
|
ERR("Cannot change PSP for non-DOS task!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static WORD INT21_GetCurrentPSP()
|
static WORD INT21_GetCurrentPSP(void)
|
||||||
{
|
{
|
||||||
LPDOSTASK lpDosTask = MZ_Current();
|
LPDOSTASK lpDosTask = MZ_Current();
|
||||||
if (lpDosTask)
|
if (lpDosTask)
|
||||||
|
@ -963,6 +963,15 @@ static WORD INT21_GetCurrentPSP()
|
||||||
return GetCurrentPDB16();
|
return GetCurrentPDB16();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WORD INT21_GetReturnCode(void)
|
||||||
|
{
|
||||||
|
LPDOSTASK lpDosTask = MZ_Current();
|
||||||
|
if (lpDosTask) {
|
||||||
|
WORD ret = lpDosTask->retval;
|
||||||
|
lpDosTask->retval = 0;
|
||||||
|
return ret;
|
||||||
|
} else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* INT21_GetExtendedError
|
* INT21_GetExtendedError
|
||||||
|
@ -1136,7 +1145,7 @@ void WINAPI DOS3Call( CONTEXT86 *context )
|
||||||
|
|
||||||
case 0x00: /* TERMINATE PROGRAM */
|
case 0x00: /* TERMINATE PROGRAM */
|
||||||
TRACE("TERMINATE PROGRAM\n");
|
TRACE("TERMINATE PROGRAM\n");
|
||||||
ExitThread( 0 );
|
MZ_Exit( context, FALSE, 0 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
|
case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
|
||||||
|
@ -1835,21 +1844,27 @@ void WINAPI DOS3Call( CONTEXT86 *context )
|
||||||
|
|
||||||
case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
|
case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
|
||||||
TRACE("EXEC %s\n",
|
TRACE("EXEC %s\n",
|
||||||
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx ));
|
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ));
|
||||||
AX_reg(context) = WinExec16( CTX_SEG_OFF_TO_LIN(context, context->SegDs,
|
if (ISV86(context)) {
|
||||||
context->Edx ),
|
if (!MZ_Exec( context, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx),
|
||||||
SW_NORMAL );
|
AL_reg(context), CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx) ))
|
||||||
if (AX_reg(context) < 32) SET_CFLAG(context);
|
bSetDOSExtendedError = TRUE;
|
||||||
|
} else {
|
||||||
|
AX_reg(context) = WinExec16( CTX_SEG_OFF_TO_LIN(context, context->SegDs,
|
||||||
|
context->Edx ),
|
||||||
|
SW_NORMAL );
|
||||||
|
if (AX_reg(context) < 32) SET_CFLAG(context);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
|
case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
|
||||||
TRACE("EXIT with return code %d\n",AL_reg(context));
|
TRACE("EXIT with return code %d\n",AL_reg(context));
|
||||||
ExitThread( AL_reg(context) );
|
MZ_Exit( context, FALSE, AL_reg(context) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x4d: /* GET RETURN CODE */
|
case 0x4d: /* GET RETURN CODE */
|
||||||
TRACE("GET RETURN CODE (ERRORLEVEL)\n");
|
TRACE("GET RETURN CODE (ERRORLEVEL)\n");
|
||||||
AX_reg(context) = 0; /* normal exit */
|
AX_reg(context) = INT21_GetReturnCode();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
|
case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
|
||||||
|
|
Loading…
Reference in a new issue