static int Execute (const char *path, const char *args, char **env) { union REGS reg; EXEC_BLK blk; char buf[256]; int len; ULONG minPages, maxPages; UCHAR *our_env = (UCHAR*) SetupEnvironment(); *env = our_env; len = strlen (args); if (len > sizeof(buf)-2) return (0); _dx_cmem_usage (0, FALSE, &minPages, &maxPages); strcpy (buf+1, args); buf [0] = len++; buf [len] = '\r'; /* if `our_env' is NULL we'll inherit the environment without any * variables added by `putenv()' */ blk.ex_eoff = our_env; /* pass new environment */ blk.ex_eseg = SS_DATA; blk.ex_coff = (UCHAR*) buf; /* command line address */ blk.ex_cseg = SS_DATA; reg.x.ax = 0x4B00; reg.x.bx = (UINT) &blk; reg.x.dx = (UINT) path; fflush (stdout); /* flush buffers now */ fflush (stderr); intdos (®, ®); if (reg.x.cflag & 1) /* carry set, return -1 */ return (-1); reg.x.ax = 0x4D00; intdos (®, ®); return (reg.h.al); /* return child exit code */ }
static REALPTR _dx_alloc_rmode_wrapper (pmodeHook pmHook, rmodeHook rmHook, int len, int stack_size, ReturnType returnType) { #define DOFS 0x2C /* offset of data section (tiny model) */ #define DSIZE 16 /* sizeof data section at wrapper end */ #define WOFS (DOFS+DSIZE) /* offset of userWrapper code (optional) */ static unsigned char wrapper[] = { 0x16, // 00 push ss 0x06, // 01 push es 0x1E, // 02 push ds 0x0E, // 03 push cs 0x1F, // 04 pop ds ;DS = CS 0xF8, // 05 clc 0xE8,0x33,0, // 06 call userWrapper ;33 relative (3A-8) 0x72,0x1C, // 09 jc short @exit 0x66,0x60, // 0B pushad 0x66,0xFF,0x36,DOFS+12,0, // 0D push taskId ;taskId to call 0x66,0x6A,0, // 12 push 0 ;use default selectors 0xFF,0x36,DOFS+4,0, // 15 push ourCS 0x66,0xFF,0x36,DOFS,0, // 19 push protGlue ;(*protGlue)() 0xFF,0x1E,DOFS+8,0, // 1E call rm2pmAddr 0x83,0xC4,14, // 22 add sp,14 ;discard used stack 0x66,0x61, // 25 popad 0x1F, // 27 @exit:pop ds 0x07, // 28 pop es 0x17, // 29 pop ss 0xCB, // 2A retf 0x90, // 2B nop 0,0,0,0, // +0 protGlue dd ? 0,0,0,0, // +4 ourCS dw ?,? 0,0,0,0, // +8 rm2pmAddr dd ? 0,0,0,0 // +12 taskId dd ? }; // +16 userWrapper: .. FARPTR pmCbuf, fpWrapper; REALPTR rmCbuf, rm2pmAddr, dosReal; USHORT para, paras, left; ULONG cbufSize, i; UINT *stack; assert (sizeof(wrapper) == (DOFS+DSIZE)); if (!pmHook || numWrappers == MAX_WRAPPERS) return (0); _dx_rmlink_get (&rm2pmAddr,&rmCbuf,&cbufSize,&pmCbuf); len += sizeof(wrapper); paras = (len + 15) / 16; para = 0; if (_dx_real_above(paras,¶,&left)) { ULONG temp; if (_dx_cmem_usage(0,0,&temp,&temp)) return (0); if (_dx_real_above(paras,¶,&left)) para = 0; if (_dx_cmem_usage(0,1,&temp,&temp)) { if (para) _dx_real_free (para); return (0); } if (!para) return (0); } for (i = 0; i < MAX_WRAPPERS; i++) if (!_rmcb[i].dosReal) break; *(ULONG*) (wrapper+DOFS+0) = (ULONG)&PmodeGlue; /* pmode helper */ *(ULONG*) (wrapper+DOFS+4) = My_CS(); /* pmode CS */ *(ULONG*) (wrapper+DOFS+8) = (ULONG)rm2pmAddr; /* rm->pm addr */ *(ULONG*) (wrapper+DOFS+12) = i; /* task Id */ wrapper [0x2A] = returnType; /* RETF or IRET */ /* * lock pages used by callback (for 386|VMM, allthough untested) */ FP_SET (fpWrapper,para << 4, SS_DOSMEM); _dx_lock_pgs (fpWrapper, len); _dx_lock_pgsn ((void*)&PmodeGlue, (UINT)&PmGlueEnd - (UINT)&PmodeGlue); RP_SET (dosReal,0,para); FillRealMem (dosReal, 0, len); WriteRealMem (dosReal, &wrapper, sizeof(wrapper)); if (rmHook) WriteRealMem(dosReal+WOFS,(void*)rmHook,len-sizeof(wrapper)); else FillRealMem (dosReal+5,0x90,6); stack_size += sizeof(UINT) + 3; /* add a DWORD for marker */ stack_size &= ~3; /* make number of DWORDs */ stack = malloc (stack_size); if (!stack) return (0); _rmcb [i].dosReal = dosReal; _rmcb [i].callback = pmHook; _rmcb [i].stackStart = stack; _rmcb [i].stackTop = stack + stack_size/sizeof(UINT) - 2; _rmcb [i].stackTop[1] = MARKER; _rmcb [i].marker = MARKER; _dx_lock_pgsn ((void*)stack, stack_size); #if 0 printf ("dosReal %08lX, rm2pmAddr %08lX, len %d, stack %08X\n", dosReal,rm2pmAddr,len,stack); #endif numWrappers++; return (dosReal); }