├── bin ├── doscalls.dll └── dpmild16.exe ├── LICENSE.md ├── README.md ├── renestub.py ├── DOSEXEC.ASM └── DPMILDR.ASM /bin/doscalls.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ringdingcoder/hx-for-opus/HEAD/bin/doscalls.dll -------------------------------------------------------------------------------- /bin/dpmild16.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ringdingcoder/hx-for-opus/HEAD/bin/dpmild16.exe -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## DOSEXEC.ASM, DPMILDR.ASM 2 | 3 | The HX DOS extender is freeware. Copyright 1996-2010 Japheth. 4 | 5 | ## The rest 6 | 7 | ### The Unlicense 8 | 9 | This is free and unencumbered software released into the public domain. 10 | 11 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. 12 | 13 | In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Winword 1 (Opus) build without excessive amounts of conventional memory 2 | 3 | See http://www.computerhistory.org/atchm/microsoft-word-for-windows-1-1a-source-code/ 4 | 5 | It has always irked me that the supplied OS/2-hosted compiler was not accessible from DOS. After all, all more modern DOS compilers used DOS extenders to have access to somewhat more reasonable amounts of memory. The HX DOS extender should in theory enable this, but there are some stumbling blocks. 6 | 7 | First, the executables must be stubbed with the DPMI loader, and the OS type must be set to OS/2. 8 | 9 | Second, there are some bugs/oversights in the NE loader and OS/2 emulation libraries regarding command line handling. 10 | 11 | With everything in place and with the fixed argument handling, a successful build is just a makeopus invocation away. For me, it succeeds with as little as 325 KB of available DOS memory. Tested under real DOS 6.22, also WfW 3.11 as well as Windows XP. All of them running in VirtualBox. Also tested on qemu. 12 | 13 | - The patched HX files are pre-built under `bin/` in this repository, so you might skip the next two steps. 14 | - Unzip `HXRT217.zip`, `HXSRC217.zip`, `HXDEV217.zip`, `HXD16217.zip`. 15 | - Patch `SRC/DOSXXX/DOSEXEC.ASM` and `SRC/DPMILDR/DPMILDR.ASM` according to this repo. Build the `DOSXXX` and `DPMILDR` directories (at least `DOSCALLS.DLL` and `DPMILD16.EXE`). 16 | - Take `CSL.EXE` and `CSL2.EXE` from `Opus/tools/os2` and apply `DPMIST16.BIN` using `renestub.py`. 17 | - For operation under Windows (NTVDM): Patch 0xffff to 0x0000 at offsets 0x1ec9f (`CSL.EXE`) / 0x133c7 (`CSL2.EXE`). These are invalid seeks to file position -1. 18 | - Copy `DOSCALLS.DLL`, `DPMILD16.EXE`, `CSL.EXE`, `CSL2.EXE` into `Opus/tools/dos`. 19 | - Also stub `MASM.EXE` from `Opus/tools` and replace it with the stubbed version. 20 | - Run `tools\makeopus` normally. 21 | 22 | Initially, this repo hosted the resulting CSL* binaries, but the Winword museum license does not permit this, so I had to remove them. 23 | 24 | Also, at the time I originally did this project, I was not aware of the Microsoft Family API and thus missed the fact that the DOS version of MASM 5 is a bound executable, and thus the same file is already both the DOS and the OS/2 version. 25 | 26 | Additionally, I became aware that it does not work on any NT before Windows XP; ironically, this happens to be the case because these versions support OS/2 executables natively, and im2obj.exe does not seem to work in this mode. I could determine that it issues a large DosRead operation into a not-so-large buffer, and the Windows OS/2 subsystem probes the last byte of the buffer to make sure that it is writable, thus crashing it. The data read from file is apparently never large enough to overflow the buffer; it is specifially the probe that crashes it. 27 | -------------------------------------------------------------------------------- /renestub.py: -------------------------------------------------------------------------------- 1 | # usage: renestub.py 2 | 3 | from __future__ import print_function, division 4 | 5 | import struct 6 | 7 | import os 8 | import os.path 9 | import sys 10 | 11 | def main(): 12 | _NEWSTUBFILE = sys.argv[1] 13 | orig = sys.argv[2] 14 | _B = "= 0x40, "no NE file" 23 | oldstubsize = gw(0x3c) 24 | print("oldstubsize", oldstubsize) 25 | assert gw(oldstubsize) == 0x454e, "no NE file" 26 | shift = gew(0x32) 27 | print("shift", shift) 28 | 29 | with open(_NEWSTUBFILE, "rb") as f: 30 | stub = bytearray(f.read()) 31 | 32 | newstubsize = len(stub) 33 | divisor = 1 << shift 34 | print("divisor", divisor) 35 | oldsects = oldstubsize // divisor 36 | print("old sects", oldsects) 37 | newsects = newstubsize // divisor 38 | if newstubsize > oldstubsize and oldsects == newsects: 39 | # make room for slightly larger stub 40 | newsects += 1 41 | print("distance", newsects - oldsects) 42 | 43 | def putw(offset, val): 44 | stub[offset:offset+2] = struct.pack(_W, val) 45 | 46 | newsize = len(entire) + ((newsects - oldsects) << shift) 47 | print("newsize", newsize) 48 | 49 | putw(2, newsize % 512) 50 | putw(4, (newsize + 511) >> 9) 51 | putw(0x3c, (newsects << shift) + (oldstubsize % divisor)) 52 | 53 | bent = bytearray(entire[oldstubsize:]) 54 | 55 | getew = lambda offset: struct.unpack(_W, bent[offset:offset+2])[0] 56 | def putew(offset, val): 57 | bent[offset:offset+2] = struct.pack(_W, val) 58 | 59 | geted = lambda offset: struct.unpack(_DW, bent[offset:offset+4])[0] 60 | def puted(offset, val): 61 | bent[offset:offset+4] = struct.pack(_DW, val) 62 | 63 | def puteb(offset, val): 64 | bent[offset:offset+1] = struct.pack(_B, val) 65 | 66 | # nonresident name offset 67 | puted(0x2c, geted(0x2c) + ((newsects - oldsects) << shift)) 68 | # os type os/2 69 | puteb(0x36, 1) 70 | 71 | numsegs = getew(0x1c) 72 | print("numsegs", numsegs) 73 | 74 | segtable = getew(0x22) 75 | 76 | # segment offsets in file 77 | for seg in range(numsegs): 78 | print("seg start", seg, hex(getew(segtable + 8*seg) << shift)) 79 | 80 | start = getew(segtable + 8*seg) 81 | if start: 82 | putew(segtable + 8*seg, start + newsects - oldsects) 83 | 84 | tmp = orig + ".tmp" 85 | with open(tmp, "wb") as tmpf: 86 | tmpf.write(stub) 87 | tmpf.write(b"\0" * (((newsects << shift) + (oldstubsize % divisor)) - len(stub))) 88 | tmpf.write(bytes(bent)) 89 | os.rename(tmp, orig) 90 | 91 | if __name__ == "__main__": 92 | main() 93 | -------------------------------------------------------------------------------- /DOSEXEC.ASM: -------------------------------------------------------------------------------- 1 | 2 | .286 3 | 4 | public DOSEXECPGM 5 | 6 | DOSXXX segment word public 'CODE' 7 | 8 | ;--- DosExecPgm(lpObjNameBuf, wObjNameBufLen, wExecFlags, pszArgs, pszEnv, pRet, pszPgm); 9 | 10 | ;-- 6 1E pszPgm 11 | ;-- 10 22 pRet 12 | ;-- 14 26 pszEnv 13 | ;-- 18 2A pszArgs 14 | ;-- 22 2E wExecFlags 15 | ;-- 24 30 wObjNameBufLen 16 | ;-- 26 32 lpObjNameBuf 17 | 18 | DOSEXECPGM: 19 | push BP 20 | sub SP,018h 21 | mov BP,SP 22 | 23 | ;--- exec parameter block is local: 24 | ;--- bp+00: environment 25 | ;--- bp+02: cmdline 26 | ;--- bp+06: fcb1 27 | ;--- bp+0A: fcb2 28 | ;--- bp+0E: res (cs:ip) 29 | ;--- bp+12: res (ss:sp) 30 | 31 | ;--- bp+16: psp 32 | 33 | push ES 34 | push DI 35 | push DS 36 | push SI 37 | push BX 38 | push CX 39 | push DX 40 | mov AH,062h 41 | int 21h 42 | 43 | mov [BP+16h],BX 44 | 45 | mov word ptr [BP+6],05Ch ;fcb1 46 | mov [BP+8],BX 47 | mov word ptr [BP+0Ah],06Ch ;fcb2 48 | mov [BP+0Ch],BX 49 | 50 | xor AX,AX 51 | mov [BP+0],AX ;environment 52 | 53 | les DI,[BP+2Ah] 54 | mov cx,es 55 | and cx,cx 56 | jnz cmdlinegiven 57 | xor di,di 58 | jmp cmdline2 59 | cmdlinegiven: 60 | mov CX,040h 61 | repne scasb 62 | mov SI,DI 63 | mov CX,0100h 64 | repne scasb 65 | sub DI,SI ;size of cmdline 66 | cmdline2: 67 | mov CX,DI 68 | mov BX,CX 69 | add BX,2 ;one byte for cmdline length 70 | and bl,not 1 ;make sure SP remains even 71 | 72 | sub SP,BX ;make room for the cmdline 73 | mov AX,ES 74 | mov DS,AX 75 | mov AX,SS 76 | mov ES,AX 77 | mov DI,SP 78 | dec BX 79 | dec BX 80 | mov es:[DI],BL 81 | mov [bp+2],DI 82 | mov [bp+4],ES 83 | inc DI 84 | rep movsb ;copy cmdline to our stack copy 85 | lds DX,[BP+1Eh] 86 | mov AX,SS 87 | mov ES,AX 88 | mov BX,BP 89 | 90 | mov AX,04B00h 91 | int 21h 92 | jb @F 93 | mov ah,4Dh 94 | int 21h 95 | lds si,[bp+22h] 96 | mov ah,00 97 | mov [si+2],ax ;set codeResult field 98 | xor AX,AX 99 | @@: 100 | lea sp,[bp-7*2] 101 | pop DX 102 | pop CX 103 | pop BX 104 | pop SI 105 | pop DS 106 | pop DI 107 | pop ES 108 | add SP,018h 109 | pop BP 110 | retf 018h 111 | 112 | DOSXXX ends 113 | 114 | end 115 | 116 | -------------------------------------------------------------------------------- /DPMILDR.ASM: -------------------------------------------------------------------------------- 1 | 2 | page ,132 3 | 4 | ;*** HX loader for 16/32-Bit DPMI Apps 5 | ;*** names: 6 | ;*** 32Bit loader: DPMILD32.EXE 7 | ;*** 16Bit loader: DPMILD16.EXE 8 | 9 | ;--- best viewed with TABSIZE 4 10 | 11 | if ?DEBUG 12 | ?EXTLOAD = 0 ;0 dont move loader in extended memory 13 | else 14 | ?EXTLOAD = 1 ;1 move loader in extended memory 15 | endif 16 | 17 | ifndef ?HDPMI 18 | ?HDPMI = 0 ;0 1=assume HDPMI is included (stand-alone MZ stub) 19 | endif 20 | 21 | ?RMSEGMENTS = 0 ;0 1=support realmode segments (doesn't work!) 22 | ?DOSAPI = 1 ;1 1=activate DOS API translation, required for OS/2 23 | ifndef ?LOADDBGDLL 24 | ?LOADDBGDLL = 1 ;1 load DEBUGOUT.DLL on startup if DPMILDR=256 25 | endif 26 | ifndef ?SERVER 27 | ?SERVER = 1 ;1 1=load DPMI host HDPMIXX.EXE if no DPMI installed 28 | endif 29 | ?CLOSEALLFILES = 0 ;0 1=close all files before fatal exit 30 | _CLEARENV_ = 0 ;0 if ?MULTPSP=1: clear PSP:[002C] on exit task 31 | _LOADERPARENT_ = 1 ;1 if ?MULTPSP=1: set PSP:[0016] to ldr PSP on exit task 32 | _SETPSP_ = 1 ;1 if ?MULTPSP=1: set owner in MCB to current PSP 33 | ?USELOADERPSP = 0 ;1 1=switch to ldr PSP for segment loads. 34 | ; 0=for DOS MCB's, set PSP manually to the loader's 35 | _SUPRESDOSERR_ = 1 ;1 bei _RESIZEPSP_: suppress error msg 36 | _WIN87EMWAIT_ = 0 ;0 1=for WIN87EM.DLL always resolve fixup 6 37 | _LINKWORKAROUND_ = 1 ;1 1=fix bug in old linkers (caps/small) 38 | _UNDEFDYNLINK_ = 0 ;0 1=resolve missing imports with UndefDynLink() 39 | _SETCSLIM_ = 0 ;0 1=adjust CS limit of loader (if ?EXTLOAD=0) 40 | _SETDSLIM_ = 0 ;0 1=adjust DS limit of loader (if ?EXTLOAD=0) 41 | ?MAXSEG = 255 ;255 max number of segments for a module (8 Bit!) 42 | _ACCDATA_ = 12h ;12h value for accessrights data segments (memory,r/w) 43 | _ACCCODE_ = 1Ah ;1Ah value for accessrights code segments (memory,e/r) 44 | _MAXTASK_ = 8 ;8 max. number of task recursion 45 | _SFLAGS_ = 20h ;share flags to use for file open (20h=deny write) 46 | _ONLY4B00_ = 1 ;1 1=catch int 21,4B00h+4B01, ignore 4B02-4B7F 47 | _LASTRC_ = 1 ;1 1=catch int 21h, AH=4D 48 | _TRAPEXC0D_ = 0 ;0 1=watch exception 0D (GPFs) 49 | ?EXC01RESET = 0 ;0 1=restore exc 01 when terminating 50 | _CHKLIBENTRYRC_ = 1 ;1 1=error if LibEntry returns ax=0 51 | _CHECKSEGSIZE_ = 1 ;1 1=check segment size (security check for relocs) 52 | _SUPTSR_ = 1 ;1 1=support and watch int 21,AH=31h 53 | _WINNT40BUG_ = 1 ;1 1=workaround for bug in nt 4.0 for 32bit clients: 54 | ; NP exceptions didn't work 55 | _RESIZEPSP_ = 1 ;1 1=resize loader psp to 120h after moved in ext. memory 56 | ?FASTCSCHANGE = 0 ;0 1=modify CS attributes directly (critical) 57 | ?GSFLAT = 1 ;1 1=GS has zero based flat selector for 32bit apps 58 | ?CHECKTOP = 0 ;0 1=check if this instance of the loader is the 59 | ; current one if an app is terminating. (doesnt work 60 | ; yet!) 61 | ?COPYENV = 1 ;1 1=copy environment ptr at PSP:[2Ch] to child psp. 62 | ; required for FreeDOS 63 | ?DOSEMUSUPP = 1 ;1 1=support DOSEMU 64 | ?PHARLABTNT = 1 ;1 1=support PharLab TNT executables (PL) (32bit only) 65 | ?HIDENEASWELL = 1 ;1 1=hide loader and server for NE exes if DPMILDR=8 66 | ?CHECKCALLER = 0 ;0 1=??? (had this ever worked?) 67 | ?SETINIT = 1 ;1 1=set init flag for Dlls 68 | ?SLOADERR = 1 ;1 1=display exact error why HDPMI cannot be loaded 69 | ?MAKENEWENV = 1 ;1 1=make new environment if task > 0 70 | ?LOWENV = 1 ;1 1=alloc new env in dos memory (0 not finished!) 71 | ?FREECHILDSELS = 1 ;1 1=free selectors for psp+env 72 | ?USE1PSP = 1 ;1 1=use just 1 psp if DPMILDR=8 73 | 74 | ifndef ?KERNEL16 75 | ?KERNEL16 = 1 ;1 76 | endif 77 | 78 | ?RESETDEFPATH = 0 ;0 1= reset szPath? No, currently this is done 79 | ; every time a .EXE is loaded 80 | ?PSPSAVEI2FADDR = 007Ch ;address in PSP to save int vector 2Fh 81 | 82 | if ?HDPMI 83 | _COPY2PSP_ = 0 84 | else 85 | _COPY2PSP_ = 1 ;1 1=copy termination code to psp at the end 86 | endif 87 | 88 | if ?32BIT 89 | _DISCARD_ = 0 ;0 1=remove discardable segments if out of memory 90 | ?OS2COMPAT = 0 ;0 1=OS/2 compatible app entry call 91 | ?AUTOCSALIAS = 0 ;0 1=alloc a CS alias for each code segment 92 | ifndef ?NEAPPS 93 | ?NEAPPS = 1 ;1 0=dont support NE apps 94 | endif 95 | else 96 | _DISCARD_ = 1 ;1 1=remove discardable segments if out of memory 97 | ?OS2COMPAT = 1 ;1 1=OS/2 compatible app entry call 98 | ?AUTOCSALIAS = 1 ;1 1=optionally alloc a CS alias for code segments 99 | ?NEAPPS = 1 ;1 0=dont support NE apps 100 | endif 101 | 102 | ENVIRON equ 2Ch 103 | PARPSP equ 16h 104 | 105 | ;*** define segments *** 106 | 107 | if ?32BIT 108 | .386 109 | ?PESUPP = 1 110 | ;;?use16 = 1 ;obsolete 111 | @use16 textequ 112 | 113 | else 114 | .286 115 | 116 | ?PESUPP = 0 117 | @use16 textequ <> 118 | endif 119 | option casemap:none 120 | option proc:private 121 | 122 | if ?HDPMI 123 | HDPMI segment para @use16 public 'CODE' 124 | HDPMI ends 125 | endif 126 | _TEXT segment dword @use16 public 'CODE' 127 | _TEXT ends 128 | CCONST segment word @use16 public 'CODE' 129 | CCONST ends 130 | _DATA segment word @use16 public 'DATA' 131 | _DATA ends 132 | 133 | include ascii.inc 134 | include dpmi.inc 135 | include fixups.inc 136 | include dpmildr.inc 137 | include debug.inc 138 | include debugsys.inc 139 | include version.inc 140 | if ?KERNEL16 141 | include kernel16.inc 142 | endif 143 | if ?PESUPP 144 | include peload.inc 145 | include winnt.inc 146 | include mzhdr32.inc 147 | endif 148 | 149 | _ITEXT segment word @use16 public 'DATA' ;use 'DATA' (OPTLINK bug) 150 | _ITEXT ends 151 | if ?STUB 152 | ENDSTUB segment para @use16 public 'DATA' 153 | db 16 dup (0) 154 | ENDSTUB ends 155 | endif 156 | _BSS segment word @use16 public 'BSS' 157 | _BSS ends 158 | STACK segment para @use16 stack 'STACK' 159 | STACK ends 160 | 161 | if ?HDPMI 162 | HDPMI segment 163 | if ?32BIT 164 | include ..\hdpmi\stub32\hdpmi32.inc 165 | else 166 | include ..\hdpmi\stub16\hdpmi16.inc 167 | endif 168 | align 16 169 | endhdpmi label byte 170 | HDPMI ends 171 | endif 172 | 173 | if ?STUB 174 | DGROUP group _TEXT,CCONST,_DATA,_ITEXT,ENDSTUB,_BSS,STACK 175 | else 176 | DGROUP group _TEXT,CCONST,_DATA,_ITEXT,_BSS,STACK 177 | endif 178 | 179 | ife ?EXTLOAD 180 | _COPY2PSP_ = 0 181 | _RESIZEPSP_ = 0 182 | endif 183 | 184 | assume CS:DGROUP 185 | assume DS:DGROUP 186 | assume SS:NOTHING 187 | assume ES:DGROUP 188 | 189 | ;*** Stack *** 190 | 191 | STACK segment 192 | if ?32BIT 193 | if _TRACE_ 194 | db 480h dup (?) 195 | else 196 | db 280h dup (?) 197 | endif 198 | endif 199 | db 180h dup (?) 200 | 201 | stacktop label byte 202 | STACK ends 203 | 204 | ;*** constants *** 205 | 206 | ;*** variables *** 207 | 208 | _DATA segment 209 | 210 | ;*** global constants, initialized during start 211 | 212 | aliassel dw 0 ;selector for data alias code segments 213 | if ?32BIT 214 | dStktop dd 0 ;top stack pointer 215 | else 216 | wStktop dw 0 ;top stack pointer 217 | endif 218 | 219 | ;*** global variables 220 | 221 | wMDSta dw 0 ;segment of 1. element of 16bit MD table 222 | wTDStk dw offset starttaskstk ;LIFO stack for tasks 223 | if ?LOADDBGDLL 224 | hModDbg dw 0 ;handle for DEBUGOUT.DLL 225 | endif 226 | if ?HDPMI 227 | wResHDPMI dw 0 228 | endif 229 | fLoadMod db 0 ;flag: LoadModule() called int 21h, ax=4B00h 230 | if ?EXTLOAD 231 | fHighLoad db 0 ;1 if loader has been moved in extended memory 232 | endif 233 | 234 | fMode db 0 ;FMODE flags 235 | wEnvFlgs label word 236 | bEnvFlgs db 0 237 | bEnvFlgs2 db 0 238 | 239 | ife ?STUB 240 | fCmdLOpt db 0 ;additional option from cmdline ("-g") 241 | endif 242 | 243 | ;*** variables used temporarily 244 | 245 | callcs dw 0 ;current CS for NP exceptions 246 | wLastRC dw 0 ;RC of last app 247 | if ?32BIT 248 | if ?DOSEMUSUPP 249 | execpm dw 0,offset segtable,0,0,0,0,0 ;exec parameter block 250 | endif 251 | endif 252 | 253 | ;*** task specific variables 254 | 255 | _start_of_instancedata label byte 256 | wErrMode dw 0 ;ErrorMode 257 | _end_of_instancedata label byte 258 | 259 | _DATA ends 260 | 261 | _BSS segment 262 | 263 | ;*** global constants, initialized during start 264 | 265 | wDPMIFlg dw ? ;DPMI init call CX flags (CL=CPU[2,3,4],CH=??) 266 | wDPMIVer dw ? ;DPMI init call DX Flags (DPMI version) 267 | wEquip dw ? ;Int 11h Equipment flags (only bit 1 used) 268 | wCSlim dw ? ;limit CS (=CSSIZE-1), size of loader segment incl. stack 269 | wVersion dw ? ;DOS version major+minor 270 | if ?EXTLOAD 271 | dwMemHdl dd ? ;DPMI memory handle for loader segment 272 | endif 273 | wlError dw ? ;error code (for function 4B00h) 274 | 275 | ;*** std variables, initialization ensured/not required 276 | ife ?MULTPSP 277 | wCurPSP label word 278 | endif 279 | wLdrPSP dw ? ;PSP selector of loader 280 | wRMPSP dw ? ;PSP segment of loader 281 | if ?MULTPSP 282 | wCurPSP dw ? ;PSP selector of current app 283 | endif 284 | 285 | starttaskstk db size TASK * _MAXTASK_ dup (?) 286 | endtaskstk label byte 287 | 288 | szName db ?MAXNAME dup (?) ;moved from behind szPath because of a bug 289 | ;in DPMIONE (int 21h, ah=47h) 290 | szPgmName db ?MAXPATH dup (?) ;program name from command line 291 | szModName db ?MAXPATH dup (?) ;module name (absolute path) 292 | szPath db ?MAXPATH dup (?) ;path of current .EXE (is default for DLLs) 293 | NE_Hdr label NEHDR ;NE header buffer 294 | MZ_Hdr db 40h dup (?) ;MZ header buffer (same memory as NE header 295 | relbuf label byte ;relocation buffer 296 | segtable db ?MAXSEG * 8 dup (?);segment table (temporarily MZ-Header) 297 | RELSIZE equ ?MAXSEG * 8 ;size relocations buffer 298 | ParmBlk dd 6 dup (?) ;parameter block for "exec prog" 299 | 300 | ;*** temp variables 301 | blksize dd ? ;limit for memory allocs 302 | blkaddr dd ? ;address for memory allocs 303 | wCnReloc dw ? ;number of relocations for a segment 304 | NEHdrOfs dw ? ;offset NE-Header 305 | wMDSize dw ? ;size MD 306 | wRelTmp dw ? ;buffer pointer for relocations 307 | 308 | _BSS ends 309 | 310 | _ITEXT segment 311 | 312 | if ?SERVER 313 | if ?32BIT 314 | HostName db "HDPMI32.EXE",00 315 | else 316 | HostName db "HDPMI16.EXE",00 317 | endif 318 | SIZE_HOSTNAME equ $-HostName 319 | endif 320 | 321 | if ?LOADDBGDLL 322 | if ?32BIT 323 | szDbgout db '.\DEBUGO32.DLL',0 324 | else 325 | szDbgout db '.\DEBUGOUT.DLL',0 326 | endif 327 | endif 328 | 329 | ife ?STUB 330 | versionstring textequ @CatStr(!",%?VERMAJOR,.,%?VERMINOR,.,%?VERMINOR2,!") 331 | szHello db lf 332 | db 'DPMI loader version ',versionstring,lf 333 | db 'Copyright (C) 1993-2010 Japheth',lf,lf,00 334 | endif 335 | szInitErr db 'Error in initialization, loading aborted',lf,00 336 | szShrkErr db 'memory shrink Error',lf,00 337 | szNoDPMI db 'No DPMI server available',lf,00 338 | if ?32BIT 339 | szNo32Bit db "DPMI server doesn't support 32-bit apps",lf,00 340 | endif 341 | errstr2 db 'Error allocating memory for DPMI server',lf,00 342 | errstr3 db 'Error switching to protected mode',lf,00 343 | ife ?STUB 344 | errstr8 db 'Filename missing or invalid',lf,00 345 | endif 346 | if ?DOSAPI 347 | ;szAPIerr db "DOS API translation not supported",lf,00 348 | szDOSstr db "MS-DOS",00 349 | endif 350 | szLoader db 'DPMILDR=',0 351 | if ?DOSEMUSUPP 352 | szDosEmuDate db "02/25/93" 353 | endif 354 | 355 | _ITEXT ends 356 | 357 | CCONST segment 358 | 359 | defdgrp dw 0,0,SF_DATA or SF_MOVABL,0 ;default segment flags for dgroup 360 | 361 | fpOSFixups label byte ;Floating Point OS-fixups 362 | dw FIARQQ,FJARQQ 363 | dw FISRQQ,FJSRQQ 364 | dw FICRQQ,FJCRQQ 365 | dw FIERQQ,0 366 | dw FIDRQQ,0 367 | dw FIWRQQ,0 368 | 369 | szTerm db 'Application will be terminated',lf,00 370 | szErr31 db 'memory allocation (DPMI) for segment load failed',lf,00 371 | szErr311 db 'memory realloc failed',lf,00 372 | szErr32 db 'Freeing memory failed. ',0 373 | szErr33 db 'DPMI 0000: Allocate descriptor',lf,00 374 | szErr34 db 'DPMI 0007: Set segment base address',lf,00 375 | szErr35 db 'DPMI 0008: Set segment limit',lf,00 376 | szErr36 db 'DPMI 0009: Set descriptor access rights',lf,00 377 | szErr37 db 'DPMI 000B: Get descriptor',lf,00 378 | szErr23 db "Invalid module handle " 379 | es23hdl db " ",lf,00 380 | szErr22 db "file is corrupt",lf,00 381 | szErr21 db "stack segment of parent destroyed",lf,00 382 | errstr19 db "Can't create PSP (insufficient DOS memory)",lf,00 383 | if ?NEAPPS 384 | errstr20 db "Can't load a 2. instance of an app",lf,00 385 | errstr17 db 'Stack segment is readonly',lf,00 386 | errstr16 db 'Module has no stack',lf,00 387 | endif 388 | errstr15 db 'DLL initialization error',lf,00 389 | errstr14 db 'Relocatable code has zero relocations',lf,00 390 | errstr13 db 'Invalid FixUp Type in relocation table',lf,00 391 | if ?32BIT 392 | szNotaNE label byte 393 | if ?NEAPPS 394 | db 'File is no 32-bit NE application',lf 395 | endif 396 | db 00 397 | else 398 | szNotaNE db 'File is no 16-bit NE application',lf,00 399 | endif 400 | errstr11 db 'Too many segments in EXE',lf,00 401 | if ?NEAPPS 402 | errstr10 db 'Program has no valid start address',lf,00 403 | endif 404 | errstr9 db 'Cannot allocate required memory',lf,00 405 | errstr7 db 'Error while loading segment',lf,00 406 | errstr6 db 'File read error',lf,00 407 | errstr5 db 'Inconsistent module table size',lf,00 408 | int0Berr1 db 'Invalid not present exception',lf,00 409 | if _TRAPEXC0D_ 410 | exc0derr db lf,'protection exception occured',lf,0 411 | endif 412 | if ?SLOADERR 413 | errstr26 db "can't load ",00 414 | endif 415 | szNotFnd db 'File not found error',lf,00 416 | nohandles db 'Out of file handles error',lf,00 417 | szLoadErr db "Load error. ",0 418 | 419 | szModule db "Module ",0 420 | szSegment db ", segment " 421 | SegNo db "00.",0 422 | 423 | errstr24 db 'Entry 0x' 424 | LENTERR db 0,0,0,0,' not found in module ',00 425 | errstr25 db ' not found in name tables of module ',00 426 | 427 | modtext db 'Module: ',00 428 | 429 | 430 | szExtErr db 'Last DOS Error:' 431 | db lf,9,'Extended Error Code ' 432 | szExtErrCod db 4 dup (0) 433 | db ', Error Class ' 434 | szExtErrCls db 2 dup (0) 435 | db lf,9,'Suggested Action ' 436 | szExtErrAct db 2 dup (0) 437 | db ', Locus ' 438 | szExtErrLoc db 2 dup (0) 439 | db lf,0 440 | 441 | szDpmiErr db 'DPMI function 0x' 442 | dpmifunc db 0,0,0,0 443 | db ' failed at 0x' 444 | dpmicaller db 0,0,0,0 445 | szLF db lf,0 446 | 447 | szEntryErr db 'Error code 0x' 448 | szEntryCode db 4 dup (0) 449 | db ' from LibEntry ' 450 | szLibName db 40h dup (0) 451 | 452 | szPathConst db 'PATH=',0 453 | if 0;e ?32BIT 454 | szCmdline db 'CMDLINE=',0 455 | endif 456 | szWEP db 'WEP' 457 | szDotDLL db '.DLL' 458 | nullstr db 00 459 | 460 | if ?RMSEGMENTS 461 | errstr41 db 'PMtoRMCallTHUNK: Cannot convert Selector',lf,00 462 | errstr42 db 'PMtoRMCallTHUNK: Cannot call real mode procedure',lf,00 463 | errstr43 db 'PMtoRMCallTHUNK: Invalid THUNK instruction',lf,00 464 | endif 465 | 466 | CCONST ends 467 | 468 | _TEXT segment 469 | 470 | ;*** if the loader is loaded as overlay (by DPMIST32.BIN) 471 | ;*** DS:DX will point to full path of DPMILDXX.EXE 472 | ;*** and DS:BX will have path of program to load 473 | ;*** (bad design, but cannot be changed anymore) 474 | 475 | ;*** the dpmi host will only be searched in directory of the loader! 476 | 477 | wLdrDS label word 478 | jmp overlayentry 479 | 480 | if ?DISABLESERVER 481 | 482 | int2frm: 483 | if ?HIDENEASWELL 484 | cmp ah, 16h 485 | else 486 | cmp ax, 1687h 487 | endif 488 | jz @F 489 | jmp dword ptr cs:[?PSPSAVEI2FADDR] 490 | @@: 491 | iret 492 | endif 493 | 494 | if _COPY2PSP_ 495 | psp_rou: 496 | int 31h ;free extended memory 497 | mov ax,1 498 | int 31h 499 | pop ax 500 | mov ah,4Ch 501 | int 21h 502 | endif 503 | 504 | endoflowcode label byte 505 | 506 | 507 | if ?CHECKCALLER 508 | ctxt db "DPMILDR" 509 | lctxt equ $ - ctxt 510 | endif 511 | 512 | overlayentry: 513 | ife ?STUB 514 | push es 515 | if ?KERNEL16 516 | mov di,offset KernelNE.szModPath 517 | else 518 | mov di,offset segtable 519 | endif 520 | push cs 521 | pop es 522 | mov si,dx 523 | @@: 524 | lodsb 525 | stosb 526 | and al,al 527 | jnz @B 528 | mov di,offset szPgmName 529 | mov si,bx 530 | @@: 531 | lodsb 532 | stosb 533 | and al,al 534 | jnz @B 535 | pop es 536 | or byte ptr cs:[fMode],FMODE_OVERLAY 537 | jmp step2 538 | endif 539 | 540 | ;--- entry for .EXE 541 | 542 | main: 543 | cld 544 | push es 545 | mov es,ds:[ENVIRON] ;get environment 546 | xor di,di 547 | or cx,-1 548 | xor ax,ax 549 | @@: 550 | repnz scasb ;search end of environment 551 | scasb ;found? 552 | jnz @B ;no, continue 553 | inc di ;skip 0001 554 | inc di ;now comes current file name 555 | if ?KERNEL16 556 | mov si,offset KernelNE.szModPath 557 | else 558 | mov si,offset segtable 559 | endif 560 | @@: 561 | mov al,es:[di] 562 | mov cs:[si],al 563 | inc si 564 | inc di 565 | and al,al 566 | jnz @B 567 | pop es 568 | step2: 569 | push cs 570 | pop ds 571 | mov wLdrDS,ds 572 | push ds 573 | pop ss 574 | mov sp,offset stacktop 575 | mov [wRMPSP],es 576 | mov [wLdrPSP],es ;this will be changed to a selector 577 | if ?STUB 578 | mov [wCurPSP],es ;this also 579 | endif 580 | mov ah,30h 581 | int 21h 582 | mov [wVersion],ax 583 | 584 | mov ax,sp 585 | dec ax 586 | mov [wCSlim],ax 587 | sub ax,001Fh ;important: make 32 bytes room on stack 588 | if ?32BIT 589 | ; movzx eax,ax 590 | mov word ptr [dStktop],ax 591 | else 592 | mov [wStktop],ax 593 | endif 594 | mov bx,sp 595 | shr bx,4 596 | if ?HDPMI 597 | mov ax,cs ;it's not a TINY model if HDPMI is included! 598 | mov cx,es 599 | sub ax,cx 600 | add bx,ax 601 | else 602 | add bx,10h ;+ PSP 603 | endif 604 | mov ah,4Ah ;now shrink memory (Real Mode) 605 | int 21h 606 | mov bx,offset szShrkErr 607 | jc main_err1 ;shrink error (can this happen?) 608 | if ?DOSEMUSUPP 609 | push 0F000h 610 | pop es 611 | mov di,0FFF5h 612 | mov si,offset szDosEmuDate 613 | mov cx,8 614 | repz cmpsb 615 | jnz @F 616 | or byte ptr [fMode], FMODE_DOSEMU 617 | @@: 618 | endif 619 | 620 | if ?LFN 621 | ;detect if lfn is installed 622 | mov ax,7147h 623 | mov si,offset szPath 624 | mov dl,0 625 | stc 626 | int 21h 627 | jc @F 628 | or fMode, FMODE_LFN 629 | @@: 630 | endif 631 | int 11h ;get equipment flags (MPC) 632 | mov [wEquip],ax 633 | call JumpToPM ;initial switch to protected mode 634 | jnc @F 635 | main_err1: 636 | call strout_err 637 | mov ax,4C00h + RC_INITRM 638 | int 21h 639 | @@: 640 | if ?DOSAPI 641 | mov si,offset szDOSstr 642 | mov ax,168Ah 643 | int 2Fh 644 | cmp al,0 645 | jz @F 646 | @trace_s <"fatal: no DOS API translation",lf> 647 | mov ax,4C00h + RC_INITPM ;just exit, dont display anything 648 | int 21h 649 | @@: 650 | @trace_s <"DOS API translation initiated",lf> 651 | endif 652 | mov dx,offset szLoader ;find env variable "DPMILDR=" 653 | call GetLdrEnvironmentVariable 654 | jc @F 655 | call getnum 656 | mov wEnvFlgs,ax 657 | @@: 658 | mov ax,3306h 659 | int 21h 660 | cmp bx,3205h ;NT, 2k, XP? 661 | jnz @F 662 | or fMode, FMODE_ISNT 663 | if ?LFN 664 | ife ?LFNNT 665 | and fMode, not FMODE_LFN 666 | endif 667 | endif 668 | or bEnvFlgs, ENVFL_DONTUSEDPMI1 669 | @@: 670 | mov ax,1600h 671 | int 2Fh 672 | and al,al 673 | jz @F 674 | or fMode, FMODE_ISWIN9X 675 | @@: 676 | if ?32BIT 677 | test fMode, FMODE_ISNT or FMODE_ISWIN9X 678 | jnz @F 679 | or bEnvFlgs2, ENVFL2_ALLOWGUI 680 | @@: 681 | endif 682 | if 0 ;not needed currently 683 | mov ax,004Fh 684 | int 41h 685 | cmp ax,0F386h 686 | jnz @F 687 | or fMode, FMODE_DEBUGGER 688 | @@: 689 | endif 690 | call InitProtMode ;init vectors, alloc internal selectors 691 | jc main_err6 ;---> 692 | ife ?STUB 693 | test [fMode],FMODE_OVERLAY 694 | jnz main_1 695 | @strout szHello,1 696 | main_1: 697 | endif 698 | mov szPath,0 699 | if ?KERNEL16 700 | call InitKernel ;init MD for KERNEL 701 | endif 702 | call GetPgmParms ;program name -> szPgmName, exec parm init 703 | jc main_err3 ;---> error: no program name given 704 | call setvec21 ;now set int 21h vector 705 | if ?LOADDBGDLL 706 | call loaddbg 707 | endif 708 | mov dx,offset szPgmName ;ptr module name 709 | mov bx,offset ParmBlk ;ptr exec parameter block 710 | if ?32BIT 711 | movzx edx,dx 712 | endif 713 | push ds 714 | pop es 715 | mov ax,4B00h ;launch program 716 | int 21h 717 | jc @F 718 | mov ah,4Dh 719 | int 21h 720 | @@: 721 | fatalerror: 722 | push ax 723 | @trace_s <"*** last task terminated (RC="> 724 | @trace_w ax 725 | @trace_s <"), will exit now ***",lf> 726 | call freemodulerest ;free modules not unloaded yet 727 | if ?CHECKTOP 728 | call areweontop 729 | jz @F 730 | pop ax 731 | mov ah,4Ch 732 | int 21h 733 | @@: 734 | endif 735 | call resetvecs 736 | @trace_s <"*** bye from DPMILDXX ***",lf> 737 | pop ax 738 | if _COPY2PSP_ ;free all memory (problem: we are running in 739 | ;it!) 740 | call copy_to_psp_and_exit 741 | endif 742 | mov ah,4Ch 743 | int 21h ;and exit loader 744 | main_err6: ;protected mode init error 745 | mov ax,offset szInitErr 746 | main_err3: 747 | mov bx,ax ;AX might have "missing filename" 748 | @strout_err ;DOS API is ensured to be available! 749 | mov al,RC_INITPM 750 | jmp fatalerror 751 | if 0 752 | main_err4: 753 | mov ds,cs:[wLdrDS] 754 | call stroutax 755 | @strout szTerm,1 756 | if ?CLOSEALLFILES 757 | call CloseAllFiles 758 | endif 759 | mov al,RC_INITPM 760 | jmp fatalerror 761 | endif 762 | 763 | ;------------------------------------------------------- 764 | if _TRAPEXC0D_ 765 | LEXC0D: 766 | push cs:[wLdrDS] 767 | mov ax,offset exc0derr 768 | push ax 769 | push cs 770 | call near ptr FatalAppExit 771 | endif 772 | 773 | if ?USELOADERPSP 774 | 775 | ;--- this was called to ensure 776 | ;--- 1. DOS memory blocks get the loader's PSP 777 | ;--- 2. the file handle for the file to be opened is owned by the loader 778 | ;--- now this code is no longer called. The PSP of the DOS memory blocks is 779 | ;--- set manually to the loader's. 780 | 781 | setldrpsp proc 782 | push ax 783 | mov ah,51h 784 | int 21h 785 | push bx 786 | mov bx,[wLdrPSP] 787 | mov ah,50h 788 | int 21h 789 | pop bx 790 | pop ax 791 | ret 792 | setldrpsp endp 793 | resetldrpsp proc 794 | pushf ;preserve carry flag! 795 | push ax 796 | mov ah,50h 797 | int 21h 798 | pop ax 799 | popf 800 | ret 801 | resetldrpsp endp 802 | endif 803 | 804 | ;*** exception 0Bh handler 805 | ;--- called if segments marked "not present" are accessed 806 | 807 | Exc0BProc proc 808 | 809 | DPMIEXC struct 810 | if ?32BIT 811 | dd ? 812 | dd ? 813 | errcode dd ? 814 | _eip dd ? 815 | _cs dw ? 816 | dw ? 817 | _eflags dd ? 818 | _esp dd ? 819 | _ss dw ? 820 | dw ? 821 | EXCERRC equ [ebp+20h].DPMIEXC.errcode 822 | EXCIP equ [ebp+20h].DPMIEXC._eip 823 | EXCCS equ [ebp+20h].DPMIEXC._cs 824 | EXCFL equ [ebp+20h].DPMIEXC._eflags 825 | EXCSP equ [ebp+20h].DPMIEXC._esp 826 | EXCSS equ [ebp+20h].DPMIEXC._ss 827 | EXCAX equ [ebp+1Ch] 828 | EXCCX equ [ebp+18h] 829 | EXCSI equ [ebp+04h] 830 | else 831 | dw ? 832 | dw ? 833 | errcode dw ? 834 | _ip dw ? 835 | _cs dw ? 836 | _flags dw ? 837 | _sp dw ? 838 | _ss dw ? 839 | EXCERRC equ [bp+10h].DPMIEXC.errcode 840 | EXCIP equ [bp+10h].DPMIEXC._ip 841 | EXCCS equ [bp+10h].DPMIEXC._cs 842 | EXCFL equ [bp+10h].DPMIEXC._flags 843 | EXCSP equ [bp+10h].DPMIEXC._sp 844 | EXCSS equ [bp+10h].DPMIEXC._ss 845 | EXCAX equ [bp+0Eh] 846 | EXCCX equ [bp+0Ch] 847 | EXCSI equ [bp+02h] 848 | endif 849 | DPMIEXC ends 850 | 851 | test cs:[fMode], FMODE_DISABLED 852 | jnz calloldexc0b 853 | if ?32BIT 854 | pushad 855 | mov ebp,esp 856 | movzx edx,dx 857 | movzx ecx,cx 858 | mov ebx,EXCERRC 859 | else 860 | pusha 861 | mov bp,sp 862 | mov bx,EXCERRC 863 | endif 864 | push ds 865 | push es 866 | mov ds,cs:[wLdrDS] 867 | @trace_s <"*** exc 0B handler, ErrCode="> 868 | if ?32BIT 869 | @trace_d ebx 870 | else 871 | @trace_w bx 872 | endif 873 | @trace_s <",cs:ip="> 874 | @trace_w EXCCS 875 | @trace_s <":"> 876 | if ?32BIT 877 | @trace_d EXCIP 878 | else 879 | @trace_w EXCIP 880 | endif 881 | @trace_s <",ss:sp="> 882 | @trace_w EXCSS 883 | @trace_s <":"> 884 | if ?32BIT 885 | @trace_d EXCSP 886 | else 887 | @trace_w EXCSP 888 | endif 889 | @trace_s <" ***",lf> 890 | push 0 891 | pop es 892 | mov ax,cs 893 | and al,03 894 | or bl,al 895 | call GetNPBase ;segm-desc -> ES:SI 896 | jc error 897 | mov ax,EXCCS 898 | if ?RMSEGMENTS 899 | test byte ptr es:[si.SEGITEM.flags],SF_RES1 900 | jz @F 901 | call ExecRMProc ;Call Real Mode Proc 902 | jc error ;error exit (AX->ErrText) 903 | jmp done 904 | @@: 905 | endif 906 | if ?USELOADERPSP 907 | call setldrpsp 908 | push bx 909 | endif 910 | call Load_Segm ;load segment 911 | if ?USELOADERPSP 912 | pop bx 913 | call resetldrpsp 914 | endif 915 | jnc done 916 | error: ;error in exc 0B will terminate task 917 | mov EXCIP, offset exc0berrorexit 918 | mov EXCCS, cs 919 | mov EXCAX, ax 920 | mov EXCCX, es ;will hold NE module (or NULL) 921 | mov EXCSI, si 922 | done: 923 | @trace_s <"*** exception 0B handler exit ***",lf> 924 | pop es 925 | pop ds 926 | @popa 927 | @retf 928 | calloldexc0b: 929 | if ?32BIT 930 | db 66h 931 | db 0eah ;jmp ssss:oooooooo 932 | oldexc0b df 0 933 | else 934 | db 0eah ;jmp ssss:oooo 935 | oldexc0b dd 0 936 | endif 937 | Exc0BProc endp 938 | 939 | ;--- an invalid exception 0Bh occured 940 | 941 | exc0berrorexit proc 942 | mov ds,cs:[wLdrDS] 943 | if 0 944 | push ds 945 | pop ss 946 | if ?32BIT 947 | mov esp,[dStktop] 948 | else 949 | mov sp,[wStktop] 950 | endif 951 | endif 952 | push cx 953 | call stroutax ;display text ^AX 954 | pop cx 955 | jcxz @F ;no valid NE hdr! 956 | mov es, cx 957 | push offset szLoadErr 958 | call stroutstk_err 959 | call displaymodandseg 960 | 961 | ;--- display . in ES:SI 962 | 963 | @@: 964 | @strout_err szTerm,1 965 | if ?CLOSEALLFILES 966 | call CloseAllFiles 967 | endif 968 | ; int 3 969 | mov ax,4C00h + RC_EXC0B 970 | int 21h 971 | 972 | exc0berrorexit endp 973 | 974 | displaymodandseg proc 975 | push offset szModule 976 | call stroutstk 977 | call modnameout ;expects ES=NE hdr 978 | mov ax, si 979 | sub ax, es:[NEHDR.ne_segtab] 980 | shr ax, 3+1 ;size of segment table in ES is 16!!! 981 | inc ax 982 | mov di, offset SegNo 983 | call BYTEOUT 984 | push offset szSegment 985 | call stroutstk 986 | @cr_out 987 | ret 988 | displaymodandseg endp 989 | 990 | if _TRAPEXC0D_ 991 | if ?32BIT 992 | oldexc0D df 0 993 | else 994 | oldexc0D dd 0 995 | endif 996 | endif 997 | 998 | if ?EXC01RESET 999 | if ?32BIT 1000 | oldexc01 df 0 1001 | else 1002 | oldexc01 dd 0 1003 | endif 1004 | endif 1005 | 1006 | if ?DEBUG 1007 | myint41 proc 1008 | cmp ax,0 1009 | jz ischarout 1010 | if ?32BIT 1011 | cmp ax,2 1012 | jz isstrout 1013 | else 1014 | cmp ax,12h 1015 | jz isstrout 1016 | endif 1017 | jmp cs:[oldint41] 1018 | isstrout: 1019 | cld 1020 | push dx 1021 | if ?32BIT 1022 | push esi 1023 | nextitem: 1024 | lods byte ptr [esi] 1025 | else 1026 | push si 1027 | nextitem: 1028 | lods byte ptr [si] 1029 | endif 1030 | and al,al 1031 | jz done 1032 | mov dl,al 1033 | mov ah,2 1034 | int 21h 1035 | jmp nextitem 1036 | done: 1037 | if ?32BIT 1038 | pop esi 1039 | else 1040 | pop si 1041 | endif 1042 | pop dx 1043 | @iret 1044 | ischarout: 1045 | mov ah,2 1046 | int 21h 1047 | @iret 1048 | myint41 endp 1049 | endif 1050 | 1051 | if ?DOS4G 1052 | is4g proc 1053 | cmp dx,0078h 1054 | jnz jmpprevint21 1055 | call checkpsp 1056 | jc jmpprevint21 1057 | push bx 1058 | mov ah,51h 1059 | int 21h 1060 | mov es,bx 1061 | pop bx 1062 | if ?DOS4GMEM 1063 | cmp cs:[w4GSel],0 1064 | jnz @F 1065 | call Init4G 1066 | jc error 1067 | @@: 1068 | mov gs,cs:[w4GSel] 1069 | endif 1070 | mov eax, "G4"*10000h+0FFFFh 1071 | error: 1072 | jmp retf2ex 1073 | is4g endp 1074 | endif 1075 | 1076 | if _SUPTSR_ 1077 | do2131 proc 1078 | cmp [wTDStk],offset starttaskstk + sizeof TASK ;last app? 1079 | jz @F 1080 | ret 1081 | @@: 1082 | push ax 1083 | mov bx,[wLdrPSP] ;set psp of loader 1084 | mov es,bx 1085 | mov ah,50h 1086 | int 21h 1087 | mov ax,0306h ;get real mode entry point 1088 | int 31h 1089 | pop ax 1090 | if ?32BIT 1091 | push esi 1092 | push edi ;push real mode entry point 1093 | else 1094 | push si 1095 | push di ;push real mode entry point 1096 | endif 1097 | mov di,80h 1098 | push di 1099 | cld 1100 | ;BA 10 00 mov dx,0010h 1101 | ;B8 xx 31 mov ax,31xxh 1102 | ;CD 21 int 21h 1103 | mov cl,al 1104 | mov ax,10BAh 1105 | stosw 1106 | mov ax,0B800h 1107 | stosw 1108 | mov al,cl 1109 | mov ah,31h 1110 | stosw 1111 | mov ax,21CDh 1112 | stosw 1113 | pop di ;IP 1114 | mov ax,cs:[wRMPSP] ;DS 1115 | mov cx,ax ;ES 1116 | mov dx,ax ;SS 1117 | mov si,ax ;CS 1118 | mov bx,100h ;SP 1119 | @retf 1120 | do2131 endp 1121 | endif 1122 | 1123 | if _LASTRC_ 1124 | do214d: 1125 | push ds 1126 | mov ds,cs:[wLdrDS] 1127 | xor ax,ax 1128 | xchg ax,[wLastRC] 1129 | pop ds 1130 | jmp retf2ex 1131 | endif 1132 | 1133 | is214b91: 1134 | push ds 1135 | mov ds,cs:[wLdrDS] 1136 | and fMode, not FMODE_DISABLED 1137 | cmp bl,0 1138 | jnz @F 1139 | or fMode, FMODE_DISABLED 1140 | @@: 1141 | pop ds 1142 | jmp retf2ex 1143 | 1144 | align 4 1145 | ;------------------------------------------------------- 1146 | ;*** int 21 handler *** 1147 | 1148 | int21proc proc 1149 | 1150 | cmp ax,4b91h ;enable/disable loader? 1151 | jz is214b91 1152 | test cs:[fMode], FMODE_DISABLED 1153 | jnz jmpprevint21 1154 | if _LASTRC_ 1155 | cmp ah,4Dh 1156 | jz do214d 1157 | endif 1158 | cmp ah,4Ch 1159 | jz int214c 1160 | if _SUPTSR_ 1161 | cmp ah,31h 1162 | jz int2131 1163 | endif 1164 | cmp ah,4bh 1165 | jz is4b 1166 | if ?DOS4G 1167 | cmp ax,0FF00h 1168 | jz is4g 1169 | endif 1170 | jmpprevint21:: 1171 | if ?32BIT 1172 | db 66h 1173 | db 0eah ;jmp ssss:oooooooo 1174 | oldint21 df 0 1175 | else 1176 | db 0eah ;jmp ssss:oooo 1177 | oldint21 dd 0 1178 | endif 1179 | align 4 1180 | 1181 | if ?32BIT 1182 | oldint31 df 0 1183 | else 1184 | oldint31 dd 0 1185 | endif 1186 | align 4 1187 | 1188 | if ?DEBUG 1189 | if ?32BIT 1190 | oldint41 df 0 1191 | else 1192 | oldint41 dd 0 1193 | endif 1194 | endif 1195 | align 4 1196 | is4b: 1197 | if _ONLY4B00_ 1198 | cmp al,01h 1199 | jbe int214b 1200 | else 1201 | cmp al,3 1202 | jbe int214b 1203 | endif 1204 | cmp al, 80h 1205 | jnz @F 1206 | if ?32BIT 1207 | test edx, 0FFFF0000h 1208 | jnz @F 1209 | endif 1210 | mov ax, dx 1211 | call FreeLib16 ;may change ES 1212 | jmp retf2ex 1213 | @@: 1214 | cmp al,85h 1215 | jnz @F 1216 | call GetProcAddress16 1217 | jmp retf2ex 1218 | @@: 1219 | ife ?32BIT 1220 | cmp al,86h 1221 | jnz @F 1222 | call GetModuleFileName16 1223 | jmp retf2ex 1224 | @@: 1225 | endif 1226 | cmp al,88h 1227 | jnz @F 1228 | call GetModuleHandle16 1229 | jmp retf2ex 1230 | @@: 1231 | cmp al,93h ;set error mode? 1232 | jnz @F 1233 | call _SetErrorMode 1234 | jmp retf2ex 1235 | @@: 1236 | cmp al,94h ;set wEnvFlgs? 1237 | jnz @F 1238 | push ds 1239 | mov ds,cs:[wLdrDS] 1240 | mov ax,[wEnvFlgs] 1241 | and dx,cx 1242 | not cx 1243 | and ax,cx 1244 | or ax,dx 1245 | xchg ax,[wEnvFlgs] 1246 | pop ds 1247 | jmp retf2ex 1248 | @@: 1249 | if ?32BIT 1250 | call CheckInt214B ;might directly return to caller! 1251 | endif 1252 | jmp jmpprevint21 1253 | 1254 | int21proc endp 1255 | 1256 | ;--- if CL=1, DX is number of export 1257 | ;--- if CL=0, DS:E/DX -> name of export 1258 | ;--- module handle in BX 1259 | ;--- return address in dx:ax 1260 | 1261 | if ?32BIT 1262 | GetProcAddress16 proc public uses es ebx esi 1263 | mov esi, edx 1264 | else 1265 | GetProcAddress16 proc public uses es bx si 1266 | mov si, dx 1267 | endif 1268 | 1269 | mov ax, bx 1270 | xor dx, dx 1271 | call checkne ;check if AX is a NE (modifies ES) 1272 | mov ax,dx 1273 | jc error 1274 | cmp cl,1 1275 | mov cx,ax 1276 | jz @F 1277 | mov ax,ds 1278 | call strlen ;get length of name into CX 1279 | @@: 1280 | call SearchNEExport 1281 | mov dx,ax 1282 | mov ax,bx 1283 | clc 1284 | error: 1285 | ret 1286 | 1287 | GetProcAddress16 endp 1288 | 1289 | ife ?32BIT 1290 | 1291 | GetModuleFileName16 proc uses es 1292 | 1293 | mov ax,dx 1294 | call checkne 1295 | jc error 1296 | mov ax,offset NEHDR.szModPath 1297 | ret 1298 | error: 1299 | xor ax,ax 1300 | cwd 1301 | ret 1302 | 1303 | GetModuleFileName16 endp 1304 | 1305 | endif 1306 | 1307 | if ?32BIT 1308 | GetModuleHandle16 proc public uses es ds esi ebx 1309 | else 1310 | GetModuleHandle16 proc uses es ds si bx 1311 | endif 1312 | 1313 | mov bx,cs:[wMDSta] 1314 | push bx 1315 | if ?32BIT 1316 | mov esi, edx 1317 | else 1318 | mov si, dx 1319 | endif 1320 | cmp cl, 0 ; is it a handle in DX? 1321 | jz @F 1322 | call Segment2Module ;get module handle for SI segment 1323 | jmp exit 1324 | @@: 1325 | call strlen ; get string length of DS:E/SI into CX 1326 | call SearchModule16 ; will work with DS:ESI in ?32BIT! 1327 | exit: 1328 | pop dx ; return first module in DX 1329 | ret 1330 | GetModuleHandle16 endp 1331 | 1332 | 1333 | ;******************************************* 1334 | ;*** int 21, AH=4Ch (terminate programm) *** 1335 | ;******************************************* 1336 | 1337 | int214c: 1338 | int2131: 1339 | @int3 _INT03PGMEXIT_ 1340 | ;---------------------------------- check if the terminating app 1341 | ;---------------------------------- is one started by the loader 1342 | ;if ?MULTPSP 1343 | ;if _LOADERPARENT_ 1344 | @trace_s <"dpmildr: check psp now",lf> 1345 | call checkpsp ;keine registerveraenderung! 1346 | jc jmpprevint21 ;jmp to previous handler 1347 | @trace_s <"dpmildr: check psp ok",lf> 1348 | ;endif 1349 | ;endif 1350 | mov ds,cs:[wLdrDS] 1351 | @trace_s <"dpmildr: int 21h ah=4C entry, task ptr(si)="> 1352 | mov si,[wTDStk] 1353 | sub si,size TASK 1354 | @trace_w si 1355 | @trace_s <", ldr sp="> 1356 | @trace_w sp 1357 | @trace_s lf 1358 | @trace_s <"dpmildr: task-modul="> 1359 | if ?32BIT 1360 | @trace_d [si.TASK.dwModul] 1361 | else 1362 | @trace_w [si.TASK.wModul] 1363 | endif 1364 | if ?MULTPSP 1365 | @trace_s <" psp="> 1366 | @trace_w [si.TASK.wPSP] 1367 | @trace_s <", parent ss:sp="> 1368 | @trace_w [si.TASK.wSS] 1369 | @trace_s <":"> 1370 | if ?32BIT 1371 | @trace_d [si.TASK.dwESP] 1372 | else 1373 | @trace_w [si.TASK.wSP] 1374 | endif 1375 | @trace_s lf 1376 | endif 1377 | if _SUPTSR_ 1378 | cmp ah,31h ;go resident? 1379 | jnz @F 1380 | call do2131 1381 | jmp i214c_1 1382 | @@: 1383 | endif 1384 | mov ah,00 1385 | mov [wLastRC],ax 1386 | if 0;?INT24RES or ?INT23RES 1387 | call restoreint2x ;restore int 23h/24h,DTA 1388 | endif 1389 | if ?32BIT 1390 | @trace_s <"dpmildr: free modules/libs, handle="> 1391 | mov eax,[si].TASK.dwModul 1392 | @trace_d eax 1393 | @trace_s 1394 | if ?PESUPP 1395 | test eax,0FFFF0000h 1396 | jz @F 1397 | call FreeModule32 1398 | push ds ;FreeLibrary may free the stack mem block 1399 | pop ss ;so set the loader stack here 1400 | mov esp,[dStktop] 1401 | push si 1402 | push eax 1403 | pop di 1404 | pop si 1405 | mov ax,0502h ;free stack handle 1406 | int 31h 1407 | pop si 1408 | jmp i214c_2 1409 | @@: 1410 | endif 1411 | else 1412 | mov ax,[si.TASK.wModul] 1413 | endif 1414 | push ds ;FreeLibrary may free the stack mem block 1415 | pop ss ;so set the loader stack here 1416 | if ?32BIT 1417 | mov esp,[dStktop] 1418 | else 1419 | mov sp,[wStktop] 1420 | endif 1421 | call FreeLib16 1422 | i214c_2: 1423 | if ?INT24RES or ?INT23RES 1424 | call restoreint2x ;restore int 23h/24h,DTA 1425 | endif 1426 | mov [wTDStk],si 1427 | if ?MULTPSP 1428 | mov bx,[si.TASK.wPSP] ;get PSP of terminating task 1429 | and bx,bx ;(hopefully it is it!) 1430 | jz i214c_1 1431 | 1432 | mov es,bx 1433 | if 0 ;win31, 9x, NT, XP work with selector 1434 | mov ax,[wRMPSP] ;use loader psp segment 1435 | test fMode, FMODE_ISNT 1436 | jz @F 1437 | endif 1438 | mov ax,[wLdrPSP] ;use loader psp selector for NT!!! 1439 | @@: 1440 | mov es:[PARPSP],ax 1441 | 1442 | if _CLEARENV_ 1443 | mov word ptr es:[ENVIRON],0000 1444 | endif 1445 | if ?32RTMBUG ;32RTM.EXE doesn't know int 21, ah=00 1446 | call KillManually 1447 | else 1448 | @trace_s <"dpmildr: task ptr(si) before dos kill="> 1449 | @trace_w si 1450 | @trace_s lf 1451 | 1452 | ;--- even if dos kill works it doesn't free selectors for PSP and ENV 1453 | 1454 | push es:[ENVIRON] 1455 | push 0 ;clear es 1456 | pop es 1457 | push bx 1458 | 1459 | if _LOADERPARENT_ 1460 | mov ax,[wLdrPSP] 1461 | mov bx,[wTDStk] 1462 | cmp bx,offset starttaskstk 1463 | jz @F 1464 | mov ax,[bx.TASK.wPSP - sizeof TASK] 1465 | @@: 1466 | push ax 1467 | endif 1468 | 1469 | mov ah,00h ;dos "kill" funktion 1470 | call doscall 1471 | mov di,0 ;di=0 if kill didn't work 1472 | jc @F 1473 | inc di 1474 | @@: 1475 | pop bx 1476 | mov ah,50h ;set "new" PSP direktly 1477 | call doscall 1478 | pop bx ;selector of killed PSP 1479 | verw bx 1480 | jnz pspfreed 1481 | mov ax,1 1482 | and di,di 1483 | jnz @F 1484 | mov dx,bx 1485 | mov ax,101h ;kill didn't work, free psp dos mem 1486 | @@: 1487 | int 31h 1488 | pspfreed: 1489 | pop bx 1490 | cmp [wTDStk],offset starttaskstk ;dont free enviroment sel of task 0 1491 | jz childselsdone ;because it is the loader's ENV as well 1492 | verw bx 1493 | jnz childselsdone 1494 | mov ax,1 1495 | and di,di 1496 | jnz @F 1497 | mov dx,bx 1498 | mov ax,101h ;kill didn't work, free psp dos mem 1499 | @@: 1500 | int 31h 1501 | childselsdone: 1502 | 1503 | endif ;endif ?32RTMBUG 1504 | endif ;endif ?MULTPSP 1505 | 1506 | i214c_1: 1507 | mov ax,[si.TASK.wSS] 1508 | @trace_s <"dpmildr: internal task ptr(si)="> 1509 | @trace_w si 1510 | @trace_s <" parent ss:sp="> 1511 | @trace_w ax 1512 | @trace_s <":"> 1513 | if ?32BIT 1514 | @trace_d [si.TASK.dwESP] 1515 | else 1516 | @trace_w [si.TASK.wSP] 1517 | endif 1518 | @trace_s lf 1519 | verw ax 1520 | jnz l214c_3 1521 | mov ss,ax 1522 | if ?32BIT 1523 | mov esp,[si.TASK.dwESP] 1524 | else 1525 | mov sp,[si.TASK.wSP] 1526 | endif 1527 | if ?SUPAPPTITLE 1528 | call setapptitle2 1529 | endif 1530 | @trace_s <"dpmildr: psp killed, switched to parent psp and stack",lf> 1531 | @restoreregs_exec 1532 | if ?32BIT 1533 | @trace_s <"dpmildr: app terminated, esi="> 1534 | @trace_d esi 1535 | @trace_s <",edi="> 1536 | @trace_d edi 1537 | @trace_s <",ebp="> 1538 | @trace_d ebp 1539 | else 1540 | if _TRACE_ 1541 | @trace_s <"dpmildr: app terminated, [sp]="> 1542 | push bp 1543 | mov bp,sp 1544 | @trace_w 1545 | @trace_s <", "> 1546 | @trace_w 1547 | @trace_s <", "> 1548 | @trace_w 1549 | pop bp 1550 | endif 1551 | endif 1552 | @trace_s 1553 | ; xor ax,ax 1554 | mov ax,cs:[wLastRC] ;modified 29.11.2004 1555 | jmp retf2ex 1556 | l214c_3: 1557 | mov bx,offset szErr21 1558 | @strout_err 1559 | jmp fatalerror 1560 | 1561 | ;*** int 21, AH=4Bh (execute programm, DS:(E)DX=Pfad) 1562 | ;*** ES:(E)BX -> exec parameter block 1563 | ;*** parameter block (16bit) looks like: 1564 | ;*** WORD environment ; environment segment or 0 1565 | ;*** DWORD cmdline ; cmdline (-> PSP:80) 1566 | ;*** DWORD fcb1 ; FCB 1 (-> PSP:5C) 1567 | ;*** DWORD fcb2 ; FCB 2 (-> PSP:6C) 1568 | ;*** parameterblock (32bit) looks like: 1569 | ;*** QWORD cmdline ; cmdline (-> PSP:80) 1570 | ;*** QWORD fcb1 ; FCB 1 (-> PSP:5C) 1571 | ;*** QWORD fcb2 ; FCB 2 (-> PSP:6C) 1572 | 1573 | int214b proc 1574 | if ?CHECKCALLER 1575 | call checkcaller ;called by loader? 1576 | jnz @F 1577 | jmp jmpprevint21 ;jmp to previous int21 handler 1578 | @@: 1579 | endif 1580 | push ds 1581 | push es 1582 | if ?32BIT 1583 | push edx 1584 | push ebx 1585 | push eax 1586 | push esi 1587 | push edi 1588 | else 1589 | push dx 1590 | push bx 1591 | push ax 1592 | push si 1593 | push di 1594 | endif 1595 | call LoadLibIntern2 ;load NE module (DS:EDX -> path) 1596 | if ?32BIT 1597 | pop edi 1598 | pop esi 1599 | pop ecx 1600 | pop ebx 1601 | pop edx 1602 | else 1603 | pop di 1604 | pop si 1605 | pop cx 1606 | pop bx 1607 | pop dx 1608 | endif 1609 | pop es 1610 | pop ds 1611 | jc @F ;not found or not a valid NE file 1612 | if ?NEAPPS 1613 | push ds 1614 | mov ds,ax 1615 | test byte ptr ds:[NEHDR.APPFLGS],AF_DLL ;app or dll? 1616 | pop ds 1617 | jz StartApp16 1618 | endif 1619 | call CallAllLibEntries ;run LibEntries of dlls 1620 | if ?32BIT 1621 | @trace_s <"int 21h, ax=4b00h (dll) will exit now to "> 1622 | @trace_w word ptr [esp+4] 1623 | @trace_s <":"> 1624 | @trace_d dword ptr [esp+0] 1625 | @trace_s 1626 | endif 1627 | jmp retf2ex ;done 1628 | @@: 1629 | cmp ax,offset szNotaNE ;not a "NE" File error? 1630 | stc 1631 | if ?32BIT 1632 | movzx eax,cs:[wlError] 1633 | else 1634 | mov ax,cs:[wlError] 1635 | endif 1636 | jnz retf2ex ;if no, return with error 1637 | mov ax,cx ;restore AX 1638 | if ?PESUPP 1639 | ; cmp byte ptr cs:[bEnabled],0 ;is peloader enabled? 1640 | ; jz int214b_1 1641 | cmp word ptr cs:[NE_Hdr],'EP' 1642 | jz @F 1643 | if ?PHARLABTNT 1644 | cmp word ptr cs:[NE_Hdr],'LP' 1645 | jz @F 1646 | endif 1647 | cmp word ptr cs:[NE_Hdr],'XP' 1648 | jnz int214b_1 ;is not a PE executable 1649 | @@: 1650 | @saveregs_exec 1651 | mov ds,cs:[wLdrDS] ;call with full path so we dont need 1652 | mov edx,offset szModName ;to search PATH again 1653 | call LoadModule32 1654 | mov [esp+1Ch],eax 1655 | @restoreregs_exec 1656 | jnc retf2ex ;done 1657 | and ax,ax 1658 | stc 1659 | jnz retf2ex 1660 | mov ax, 4b00h 1661 | int214b_1: 1662 | endif 1663 | xor cx,cx 1664 | if ?DISABLESERVER 1665 | call disableserver 1666 | endif 1667 | if ?32BIT 1668 | if ?DOSEMUSUPP 1669 | test cs:fMode, FMODE_DOSEMU 1670 | jz @F 1671 | call __loadpgm 1672 | jmp loadpgmdone 1673 | @@: 1674 | endif 1675 | endif 1676 | 1677 | ;------------------- here there was code to reset int21 1678 | ;------------------- so the loader does not intercept int 21, ah=4ch 1679 | ;------------------- of the now launched program (if it is a pm app) 1680 | ;------------------- but it seems better to check in int21,ah=4ch 1681 | ;------------------- if the terminating app is one started by the loader 1682 | call doscall ;exec (real mode) program 1683 | loadpgmdone: 1684 | pushf 1685 | @trace_s 1686 | @trace_s <"dpmildr: return from exec real mode program",lf> 1687 | if ?DISABLESERVER 1688 | call enableserver 1689 | endif 1690 | popf 1691 | pushf 1692 | if _LASTRC_ 1693 | jc @F 1694 | mov ah,4Dh 1695 | call doscall 1696 | push ds 1697 | mov ds,cs:[wLdrDS] 1698 | mov [wLastRC],ax 1699 | pop ds 1700 | @@: 1701 | endif 1702 | if ?SUPAPPTITLE 1703 | call setapptitle2 ;restore app title 1704 | endif 1705 | @int3 _INT03RETEXEC_ 1706 | @trace_s <"dpmildr: returning to previous app",lf> 1707 | popf 1708 | retf2ex:: 1709 | push ax ;copy flags 1710 | lahf ;to ensure trace flag isn't touched 1711 | if ?32BIT 1712 | if 0 1713 | push ebp 1714 | mov ebp,ss 1715 | lar ebp,ebp 1716 | test ebp,400000h 1717 | mov ebp,esp 1718 | jnz @F 1719 | movzx ebp,bp 1720 | @@: 1721 | mov [ebp+4+2+2*4],ah 1722 | pop ebp 1723 | else 1724 | mov [esp+2+2*4],ah 1725 | endif 1726 | else 1727 | push bp 1728 | mov bp,sp 1729 | mov [bp+2+2+2*2],ah 1730 | pop bp 1731 | endif 1732 | pop ax 1733 | @iret 1734 | int214b endp 1735 | 1736 | if ?NEAPPS 1737 | 1738 | ;--- start NE application (16/32 bit) 1739 | 1740 | StartApp_Err17: 1741 | mov ax,offset errstr17 ;error "stack is readonly" 1742 | jmp StartApp_Err 1743 | StartApp_Err10: 1744 | mov ax,offset errstr10 ;error "no valid start address" 1745 | StartApp_Err11: 1746 | StartApp_Err: 1747 | test byte ptr [wErrMode+1],HBSEM_NOOPENFILEBOX 1748 | jnz @F 1749 | mov bx, ax 1750 | @strout_err ;display bx string 1751 | @@: 1752 | 1753 | ;--- the new PSP has been created already and is the active one 1754 | ;--- so best would be to terminate with Ah=4Ch 1755 | if 0 1756 | @restoreregs_exec 1757 | stc 1758 | mov ax,cs:[wlError] 1759 | jmp retf2ex ;exit function 4B with Carry set 1760 | else 1761 | StartApp_ErrExit: 1762 | mov ax,4C00h+RC_INITAPP 1763 | int 21h 1764 | endif 1765 | 1766 | ;*** start new NE application 1767 | ;*** inp: AX=MD 1768 | ;--- CL=value of AL (00/01) of ax=4B0x 1769 | ;*** ES:E/BX-> execute parameter block 1770 | 1771 | StartApp16 proc 1772 | 1773 | @saveregs_exec 1774 | 1775 | mov ds,cs:[wLdrDS] 1776 | mov si,[wTDStk] 1777 | if ?32BIT 1778 | mov [si.TASK.dwESP],esp 1779 | movzx eax,ax 1780 | mov [si.TASK.dwModul],eax 1781 | else 1782 | mov [si.TASK.wSP],sp 1783 | mov [si.TASK.wModul],ax 1784 | endif 1785 | mov [si.TASK.wSS],ss 1786 | if ?MULTPSP 1787 | push es 1788 | mov es,ax 1789 | if ?32BIT 1790 | mov edi,offset NEHDR.szModPath 1791 | else 1792 | mov di,offset NEHDR.szModPath 1793 | endif 1794 | call CreatePsp ;will set new psp (E/BX not modified) 1795 | pop es 1796 | jc StartApp_Err 1797 | endif 1798 | add [wTDStk],sizeof TASK ;update task stack 1799 | if ?INT24RES or ?INT23RES 1800 | call saveint2x 1801 | endif 1802 | call SetCmdLine ;copy cmdline into PSP (ES:E/BX->parmb) 1803 | mov es,[si.TASK.wModul] 1804 | cmp word ptr es:[NEHDR.ne_csip+2],0 1805 | jz StartApp_Err10 1806 | call GetSSSP ;get new SS:E/SP into AX:E/DX 1807 | jc StartApp_Err11 ;error "no stack","mult inst" 1808 | @trace_s <"will force NP exception for "> 1809 | @trace_w ax 1810 | @trace_s <" (SS) now",lf> 1811 | push ds 1812 | mov ds,ax ;cause a NP exception 1813 | pop ds ;to ensure stack segment is loaded 1814 | verw ax 1815 | jnz StartApp_Err17 1816 | mov ss,ax 1817 | if ?32BIT 1818 | mov esp,edx 1819 | else 1820 | mov sp,dx 1821 | endif 1822 | if ?SUPAPPTITLE 1823 | mov al,00 1824 | call SetAppTitle 1825 | endif 1826 | @trace_s "will launch app now, CS:IP=" 1827 | @trace_w 1828 | @trace_s ':' 1829 | @trace_w 1830 | @trace_s " SS:SP=" 1831 | @trace_w ss 1832 | @trace_s ':' 1833 | if ?32BIT 1834 | @trace_d esp 1835 | else 1836 | @trace_w sp 1837 | endif 1838 | @trace_s <" PSP="> 1839 | @trace_w [wCurPSP] 1840 | @trace_s 1841 | 1842 | cld 1843 | sti 1844 | mov cx,word ptr es:[NEHDR.ne_csip+2] 1845 | if ?32BIT 1846 | movzx ebx,word ptr es:[NEHDR.ne_csip+0] 1847 | if ?GSFLAT 1848 | mov gs,[wFlatDS] 1849 | endif 1850 | else 1851 | mov bx,word ptr es:[NEHDR.ne_csip+0] 1852 | endif 1853 | if ?INT41SUPPORT 1854 | mov ax,DS_StartTask ;CX:BX=CS:IP 1855 | int 41h 1856 | test cs:bEnvFlgs,ENVFL_BREAKATENTRY 1857 | jz @F 1858 | push es 1859 | mov es,cx ;force segment to be loaded 1860 | pop es 1861 | mov ax,DS_ForcedGO16 ;force break at cx:bx 1862 | int 41h 1863 | @@: 1864 | endif 1865 | if ?32BIT 1866 | pushfd 1867 | push ecx 1868 | push ebx 1869 | else 1870 | pushf 1871 | push cx 1872 | push bx 1873 | endif 1874 | mov cx,es:[NEHDR.ne_heap] 1875 | mov bx,es:[NEHDR.ne_stack] ;for win16 binaries 1876 | if ?32BIT 1877 | movzx ebx,bx 1878 | movzx ecx,cx 1879 | shl ebx,12 ;new: pages instead of bytes for 32bit 1880 | shl ecx,12 1881 | endif 1882 | mov di,ss ;DI=hInstance 1883 | ife ?32BIT 1884 | xor si,si ;for 16 bit init SI here 1885 | test es:[NEHDR.APPFLGS],10h ;RTM compatible? 1886 | jz @F 1887 | mov ds,[wCurPSP] 1888 | push ds 1889 | pop es 1890 | jmp notos2 1891 | @@: 1892 | cmp es:[NEHDR.ne_exetyp], ET_OS2 1893 | endif 1894 | mov es,[wCurPSP] 1895 | mov ds,di 1896 | ife ?32BIT 1897 | jnz notos2 1898 | endif 1899 | ife ?32BIT 1900 | mov si,cx ;si=heap size 1901 | mov dx,bx ;dx=stack size 1902 | call InitDlls ;simple InitTask for OS/2 1903 | jc StartApp_ErrExit 1904 | add cx,3*2 ;cx=size of DGROUP (account for IRET stack frame) 1905 | add cx,si 1906 | else 1907 | push ebx 1908 | push ecx 1909 | call InitDlls 1910 | pop ecx 1911 | pop ebx 1912 | jc StartApp_ErrExit 1913 | endif 1914 | ife ?32BIT 1915 | or bx,-1 1916 | mov es,es:[002Ch] 1917 | xor ax,ax 1918 | @@: 1919 | inc bx 1920 | cmp ax,es:[bx] 1921 | jnz @B 1922 | inc bx 1923 | @@: 1924 | inc bx 1925 | cmp al,es:[bx] 1926 | jnz @B 1927 | push bx 1928 | @@: 1929 | inc bx 1930 | cmp al,es:[bx] 1931 | jnz @B 1932 | inc bx 1933 | mov di,bx 1934 | xor cx,cx 1935 | push ds 1936 | mov ds,cs:[wCurPSP] 1937 | mov si,80h 1938 | lodsb 1939 | mov cl,al 1940 | rep movsb 1941 | pop ds 1942 | mov al,0 1943 | stosb 1944 | pop bx 1945 | inc bx 1946 | mov ax,es 1947 | push 0 1948 | pop es 1949 | notos2: 1950 | endif 1951 | if _INT01PGMENTRY_ 1952 | pushf 1953 | mov bp,sp 1954 | or word ptr [bp+0],100h ;set TF 1955 | endif 1956 | if ?32BIT 1957 | xor ebp,ebp 1958 | mov esi,ebp 1959 | mov fs,bp 1960 | ife ?GSFLAT 1961 | mov gs,bp 1962 | endif 1963 | else 1964 | xor bp,bp 1965 | endif 1966 | if _INT01PGMENTRY_ 1967 | popf 1968 | endif 1969 | @iret 1970 | StartApp16 endp 1971 | 1972 | endif ;?NEAPPS 1973 | 1974 | if ?32RTMBUG 1975 | KillManually proc 1976 | mov dx,bx 1977 | @trace_s <"freeing psp memory",lf> 1978 | mov ax,0101h 1979 | call dpmicall 1980 | ret 1981 | KillManually endp 1982 | endif 1983 | 1984 | if ?32BIT 1985 | if ?DOSEMUSUPP 1986 | 1987 | ;--- EXEC param block in dosemu is wrong 1988 | 1989 | __loadpgm proc 1990 | push es 1991 | push ds 1992 | pushad 1993 | lds esi,es:[ebx+0] 1994 | movzx ecx,byte ptr [esi] 1995 | inc cl 1996 | inc cl 1997 | mov edi,offset segtable 1998 | mov es,cs:[wLdrDS] 1999 | rep movs byte ptr [edi],[esi] 2000 | popad 2001 | pop ds 2002 | push ebx 2003 | mov ebx, offset execpm 2004 | mov es:[bx+4],es ;cmdline selector 2005 | mov ax,4b00h 2006 | call doscall 2007 | pop ebx 2008 | pop es 2009 | ret 2010 | __loadpgm endp 2011 | endif 2012 | endif 2013 | 2014 | if ?DISABLESERVER 2015 | 2016 | disableserver proc uses ds 2017 | if 1 2018 | mov ds, cs:[wLdrPSP] 2019 | mov word ptr ds:[?PSPSAVEI2FADDR+2],0 2020 | endif 2021 | test cs:[bEnvFlgs], ENVFL_LOAD1APPONLY 2022 | jz exit 2023 | if 0 2024 | cmp cs:[wTasks], 0 ;is anything loaded at all? 2025 | jz exit 2026 | endif 2027 | pusha 2028 | mov bl, 2fh 2029 | mov ax, 200h 2030 | int 31h 2031 | mov ds:[?PSPSAVEI2FADDR+0],dx 2032 | mov ds:[?PSPSAVEI2FADDR+2],cx 2033 | mov cx, cs:[wRMPSP] 2034 | mov dx, 0100h+offset int2frm 2035 | mov ax, 0201h 2036 | int 31h 2037 | popa 2038 | exit: 2039 | ret 2040 | disableserver endp 2041 | 2042 | enableserver proc public uses ds 2043 | pusha 2044 | mov ds, cs:[wLdrPSP] 2045 | xor dx,dx 2046 | xor cx,cx 2047 | xchg dx, ds:[?PSPSAVEI2FADDR+0] 2048 | xchg cx, ds:[?PSPSAVEI2FADDR+2] 2049 | jcxz @F 2050 | mov bl, 2fh 2051 | mov ax, 0201h 2052 | int 31h 2053 | @@: 2054 | popa 2055 | ret 2056 | enableserver endp 2057 | 2058 | endif 2059 | 2060 | if ?SUPAPPTITLE 2061 | 2062 | ;*** prepare call of SetAppTitle 2063 | 2064 | setapptitle2 proc uses ds es si ax 2065 | 2066 | mov ds,cs:[wLdrDS] 2067 | mov si,[wTDStk] 2068 | cmp si, offset starttaskstk 2069 | jz exit 2070 | if ?32BIT 2071 | cmp word ptr [si.TASK.dwModul+2 - sizeof TASK],0 2072 | mov al,01 2073 | jnz @F 2074 | endif 2075 | mov es,[si.TASK.wModul - sizeof TASK] 2076 | mov al,00 2077 | @@: 2078 | call SetAppTitle 2079 | exit: 2080 | ret 2081 | setapptitle2 endp 2082 | 2083 | 2084 | ;*** int 2f,168e only works for win9x and no translation is supplied! 2085 | ;*** since a pointer is used, dos memory has to be allocated! 2086 | ;*** Input: AL=00 + ES=MD or AL=01 + FS=MZHDR 2087 | ;*** DS=dataseg 2088 | 2089 | SetAppTitle proc public 2090 | if ?32BIT 2091 | pushad 2092 | sub esp,sizeof RMCS+2 2093 | mov ebp,esp 2094 | else 2095 | pusha 2096 | sub sp,sizeof RMCS+2 2097 | mov bp,sp 2098 | endif 2099 | test fMode, FMODE_ISWIN9X 2100 | jz exit 2101 | or fMode, FMODE_NOERRDISP ;dont display dpmi errors 2102 | push es 2103 | push ds 2104 | if ?PESUPP 2105 | test al,01 2106 | jz isNE 2107 | mov es,cs:[wFlatDS] 2108 | movzx esi, cs:[wTDStk] 2109 | mov esi, cs:[esi-sizeof TASK].TASK.dwModul 2110 | add esi, es:[esi].MZHDR.pExeNam 2111 | push esi 2112 | mov cl,-1 2113 | @@: 2114 | mov al,es:[esi] 2115 | inc esi 2116 | inc cl 2117 | and al,al 2118 | jnz @B 2119 | pop esi 2120 | push es 2121 | pop ds 2122 | jmp sat_2 2123 | isNE: 2124 | movzx esi,si 2125 | endif 2126 | push es 2127 | pop ds 2128 | mov si,ds:[NEHDR.ne_restab] 2129 | lodsb 2130 | mov cl,al 2131 | sat_2: ;copy name to real mode memory 2132 | mov ch,00 2133 | push cx 2134 | mov bx,8 2135 | mov ax,0100h 2136 | call dpmicall 2137 | pop cx 2138 | jc error 2139 | if ?32BIT 2140 | xor edi,edi 2141 | else 2142 | xor di,di 2143 | endif 2144 | mov es,dx 2145 | if ?32BIT 2146 | mov [ebp.RMCS.rES],ax 2147 | else 2148 | mov [bp.RMCS.rES],ax 2149 | endif 2150 | and cl,7Fh 2151 | if ?32BIT 2152 | movzx ecx,cx 2153 | rep movs byte ptr [edi], [esi] 2154 | xor al,al 2155 | stos byte ptr [edi] 2156 | else 2157 | rep movsb 2158 | xor al,al 2159 | stosb 2160 | endif 2161 | 2162 | if ?32BIT 2163 | xor eax,eax 2164 | mov [ebp.RMCS.rDI],ax 2165 | mov [ebp.RMCS.rDX],ax 2166 | mov [ebp.RMCS.rSSSP],eax 2167 | mov [ebp.RMCS.rAX],168Eh 2168 | mov edi,ebp 2169 | else 2170 | xor ax,ax 2171 | mov [bp.RMCS.rDI],ax 2172 | mov [bp.RMCS.rDX],ax ;set app title 2173 | mov [bp.RMCS.rSS],ax 2174 | mov [bp.RMCS.rSP],ax 2175 | mov [bp.RMCS.rAX],168Eh 2176 | mov di,bp 2177 | endif 2178 | 2179 | ;---------------------- call int 2F, AX=168Eh 2180 | push ss 2181 | pop es 2182 | mov bx,002Fh 2183 | xor cx,cx 2184 | mov ax,0300h 2185 | call dpmicall 2186 | 2187 | mov ax,0101h 2188 | call dpmicall 2189 | error: 2190 | pop ds 2191 | pop es 2192 | and fMode, not FMODE_NOERRDISP 2193 | exit: 2194 | if ?32BIT 2195 | add esp,sizeof RMCS+2 2196 | popad 2197 | else 2198 | add sp,sizeof RMCS+2 2199 | popa 2200 | endif 2201 | ret 2202 | SetAppTitle endp 2203 | 2204 | endif 2205 | 2206 | if ?MULTPSP 2207 | 2208 | ;--- inp: DS=new psp with old env 2209 | ;--- ES:E/DI=program name 2210 | ;--- out: ES=new env 2211 | 2212 | if ?MAKENEWENV 2213 | CopyPgmInEnv proc 2214 | pusha 2215 | ;### changes for differences in environment block 2216 | if ?OS2COMPAT 2217 | mov bl,ds:[0080h] ;length of cmd tail (used later) 2218 | inc bl ;+1 for terminator 2219 | endif 2220 | ;### end 2221 | push ds 2222 | mov ds,ds:[002Ch] 2223 | xor si,si 2224 | xor ax,ax 2225 | dec si 2226 | @@: 2227 | inc si 2228 | cmp ax,[si] 2229 | jnz @B 2230 | ;### more changes for environment 2231 | if ?OS2COMPAT 2232 | add si,2 ;include 00,00 in copy 2233 | xor bp,bp ;bp==0 means OS/2 2234 | cmp es:[NEHDR.ne_exetyp], ET_OS2 2235 | je @f 2236 | add si,2 ;include 01,00 as well 2237 | inc bp 2238 | @@: 2239 | else 2240 | add si,4 ;skip 00 00 and 01 00 2241 | endif 2242 | ;### end 2243 | if ?32BIT 2244 | mov edx,edi 2245 | ; dec edi 2246 | @@: 2247 | ; inc edi 2248 | scas byte ptr es:[edi] 2249 | jnz @B 2250 | xchg edx,edi 2251 | sub edx,edi 2252 | else 2253 | mov dx,di 2254 | ; dec di 2255 | @@: 2256 | ; inc di 2257 | scasb 2258 | jnz @B 2259 | xchg dx,di 2260 | sub dx,di 2261 | endif 2262 | mov ax,si ;now calc size of environment block 2263 | add ax,dx 2264 | ;### yet more changes for environment 2265 | if ?OS2COMPAT 2266 | and bp,bp 2267 | jnz @F 2268 | add ax,dx ;allow for copy of progname 2269 | mov bh,00 ;bl has cmd tail count from psp 2270 | add ax,bx 2271 | @@: 2272 | endif 2273 | ;### end 2274 | add ax,15 ;paragraph align 2275 | and al,0F0h 2276 | shr ax,4 2277 | mov bx,ax 2278 | if ?LOWENV 2279 | mov ax,100h 2280 | int 31h 2281 | else 2282 | mov ah,48h 2283 | int 21h 2284 | endif 2285 | jc done 2286 | push es 2287 | mov es,dx 2288 | mov cx,si 2289 | if ?32BIT 2290 | push edi 2291 | else 2292 | push di 2293 | endif 2294 | xor di,di 2295 | xor si,si 2296 | rep movsb ;copy old environment to new environment block 2297 | if ?32BIT 2298 | pop esi 2299 | pop ds 2300 | @@: 2301 | lods byte ptr [esi] ;copy program name into new environment block 2302 | stosb 2303 | and al,al 2304 | jnz @B 2305 | else 2306 | pop si 2307 | pop ds 2308 | if ?OS2COMPAT 2309 | mov bx,di ;save ptr within env 2310 | endif 2311 | @@: 2312 | lodsb 2313 | stosb 2314 | and al,al 2315 | jnz @B 2316 | endif 2317 | pop ds 2318 | mov ds:[002Ch],es 2319 | push ds 2320 | if ?OS2COMPAT 2321 | ;### and this is what it's all been about 2322 | and bp,bp ;os/2 exe type? 2323 | jnz done 2324 | ; mov ds:[042h],di 2325 | @@: 2326 | mov al,es:[bx] ;OS2v1 has 2 copies of progname 2327 | stos byte ptr es:[di] 2328 | inc bx 2329 | or al,al 2330 | jnz @b 2331 | 2332 | mov si,0080h ;copy from psp (max 127) 2333 | lodsb 2334 | mov cl,al 2335 | mov ch,00 2336 | rep movsb 2337 | mov es:[di],ch ;terminate with 00 2338 | endif 2339 | ;### end changes for environment 2340 | done: 2341 | pop ds 2342 | popa 2343 | ret 2344 | CopyPgmInEnv endp 2345 | endif 2346 | 2347 | ;*** create a new psp of size 100h bytes *** 2348 | ;--- input: 2349 | ;--- DS:SI -> new TASK (ds = loader segment) 2350 | ;--- ES=MD for NE tasks 2351 | ;--- ES:E/DI -> program name 2352 | ;--- wTasks has old value (0 for first task) 2353 | 2354 | ;*** dos function 55h will set current PSP to the new created PSP! 2355 | ;--- out: C on error 2356 | ;--- destroys AX,CX,DX 2357 | 2358 | if ?32BIT 2359 | CreatePsp proc public uses ebx 2360 | else 2361 | CreatePsp proc uses bx 2362 | endif 2363 | 2364 | mov ah,51h 2365 | int 21h 2366 | @trace_s <"createpsp entry DS="> 2367 | @trace_w ds 2368 | @trace_s <" caller psp="> 2369 | @trace_w bx 2370 | @trace_s lf 2371 | mov [wCurPSP],bx 2372 | 2373 | cld 2374 | if ?USE1PSP 2375 | mov dx,bx 2376 | mov [si].TASK.wPSP,0 2377 | test bEnvFlgs, ENVFL_LOAD1APPONLY 2378 | jnz pspdone 2379 | endif 2380 | mov bx,10h 2381 | mov ax,0100h ;alloc DOS memory for PSP 2382 | int 31h 2383 | jc error1 2384 | push ax ;DX = selector, AX = segment 2385 | push si 2386 | mov si,ax 2387 | add si,10h ;SI = value placed at offset 2 2388 | mov ah,55h ;create PSP, DX=segment 2389 | int 21h 2390 | pop si 2391 | pop ax 2392 | ; jc error1 ;RBIL states CF doesnt indicate an error! 2393 | mov [si].TASK.wPSP,dx ;save new PSP 2394 | @trace_s <"new psp is "> 2395 | @trace_w dx 2396 | @trace_s lf 2397 | pspdone: 2398 | if ?COPYENV 2399 | push ds 2400 | mov ds,dx 2401 | cmp word ptr ds:[2ch],0 ;is env of new PSP 0? 2402 | jnz @F 2403 | @trace_s <"environment of PSP is NULL, copy it from previous PSP",lf> 2404 | mov ds, cs:[wCurPSP] ;then copy it from current PSP 2405 | mov cx, ds:[2ch] 2406 | mov ds, dx 2407 | mov ds:[2ch], cx 2408 | @@: 2409 | if ?MAKENEWENV 2410 | if ?OS2COMPAT 2411 | cmp es:[NEHDR.ne_exetyp], ET_OS2 2412 | je cpyenv 2413 | endif 2414 | cmp cs:[wTDStk],offset starttaskstk 2415 | jz @F 2416 | cpyenv: 2417 | @trace_s <"set new pgm path in environment",lf> 2418 | call CopyPgmInEnv ;preserves AX 2419 | @@: 2420 | endif 2421 | pop ds 2422 | endif 2423 | mov [wCurPSP],dx 2424 | if _SETPSP_ 2425 | if ?32BIT 2426 | push ds 2427 | push esi 2428 | push edi 2429 | mov di,ax ;segment of new PSP to DI 2430 | dec di 2431 | movzx edi,di 2432 | shl edi,4 2433 | mov es,[wFlatDS] 2434 | mov es:[edi+1],ax ;set new PSP as owner of itself! 2435 | mov byte ptr es:[edi+8],0 2436 | if 1 2437 | test word ptr [si.TASK.dwModul+2],0FFFFh 2438 | jnz @F ;is PE-Modul 2439 | else 2440 | verr word ptr [si.TASK.dwModul] 2441 | jnz @F ;is PE-Modul 2442 | endif 2443 | mov ds,word ptr [si.TASK.dwModul] 2444 | movzx esi,ds:[NEHDR.ne_restab] 2445 | inc si 2446 | add di,8 2447 | movs dword ptr [edi],[esi] ;copy name to PSP header 2448 | movs dword ptr [edi],[esi] 2449 | @@: 2450 | pop edi 2451 | pop esi 2452 | pop ds 2453 | else 2454 | mov cx,[si.TASK.wModul] 2455 | jcxz createpsp_1 2456 | push ax 2457 | dec ax 2458 | mov bx,ax 2459 | call AllocRMSegment ;create selector in BX for segment BX 2460 | pop cx 2461 | jc createpsp_1 2462 | push ds 2463 | pusha 2464 | mov ds,[si.TASK.wModul] 2465 | mov es,bx 2466 | mov es:[0001],cx 2467 | mov si,ds:[NEHDR.ne_restab] ;entries (exported names) 2468 | inc si 2469 | mov di,8 2470 | movsw 2471 | movsw 2472 | movsw 2473 | movsw 2474 | popa 2475 | pop ds 2476 | mov ax,0001 2477 | int 31h 2478 | endif 2479 | createpsp_1: 2480 | endif 2481 | if ?SETDTA 2482 | mov ah,2fh 2483 | int 21h 2484 | if ?32BIT 2485 | mov dword ptr [si.TASK.dta+0],ebx 2486 | mov word ptr [si.TASK.dta+4],es 2487 | else 2488 | mov word ptr [si.TASK.dta+0],bx 2489 | mov word ptr [si.TASK.dta+2],es 2490 | endif 2491 | push ds 2492 | mov ds,dx 2493 | if ?32BIT 2494 | mov edx,80h 2495 | else 2496 | mov dx,0080h 2497 | endif 2498 | mov ah,1Ah 2499 | int 21h ;set DTA 2500 | pop ds 2501 | endif 2502 | clc 2503 | exit: 2504 | @trace_s <"createpsp exit",lf> 2505 | ret 2506 | error1: 2507 | mov ax,offset errstr19 ;error "insufficient dos memory" 2508 | jmp exit 2509 | CreatePsp endp 2510 | 2511 | endif 2512 | 2513 | ;--- set error mode in DX, return old value in DX 2514 | 2515 | _SetErrorMode proc public 2516 | push ds 2517 | mov ds,cs:[wLdrDS] 2518 | test bEnvFlgs, ENVFL_IGNNOOPENERR 2519 | jz dontmoderrmode 2520 | and dh,7Fh ;reset this bit 2521 | dontmoderrmode: 2522 | xchg dx,[wErrMode] 2523 | pop ds 2524 | ret 2525 | _SetErrorMode endp 2526 | 2527 | ;--- get current values for int 23, int 24 2528 | 2529 | saveint2x proc public uses bx 2530 | mov ax,0204h 2531 | if ?INT23RES 2532 | mov bl,23h 2533 | call dpmicall 2534 | if ?32BIT 2535 | mov dword ptr [si.TASK.dfI23+0],edx 2536 | mov word ptr [si.TASK.dfI23+4],cx 2537 | else 2538 | mov word ptr [si.TASK.dwI23+0],dx 2539 | mov word ptr [si.TASK.dwI23+2],cx 2540 | endif 2541 | endif 2542 | if ?INT24RES 2543 | mov bl,24h 2544 | call dpmicall 2545 | if ?32BIT 2546 | mov dword ptr [si.TASK.dfI24+0],edx 2547 | mov word ptr [si.TASK.dfI24+4],cx 2548 | else 2549 | mov word ptr [si.TASK.dwI24+0],dx 2550 | mov word ptr [si.TASK.dwI24+2],cx 2551 | endif 2552 | endif 2553 | ret 2554 | saveint2x endp 2555 | 2556 | ;--- restore values after task end 2557 | 2558 | restoreint2x proc 2559 | if ?INT23RES 2560 | if ?32BIT 2561 | mov edx,dword ptr [si.TASK.dfI23+0] 2562 | mov cx,word ptr [si.TASK.dfI23+4] 2563 | else 2564 | mov dx,word ptr [si.TASK.dwI23+0] 2565 | mov cx,word ptr [si.TASK.dwI23+2] 2566 | endif 2567 | mov ax,0205h 2568 | mov bl,23h 2569 | call dpmicall 2570 | endif 2571 | if ?INT24RES 2572 | if ?32BIT 2573 | mov edx,dword ptr [si.TASK.dfI24+0] 2574 | mov cx,word ptr [si.TASK.dfI24+4] 2575 | else 2576 | mov dx,word ptr [si.TASK.dwI24+0] 2577 | mov cx,word ptr [si.TASK.dwI24+2] 2578 | endif 2579 | mov ax,0205h 2580 | mov bl,24h 2581 | call dpmicall 2582 | endif 2583 | if ?SETDTA 2584 | push ds 2585 | if ?32BIT 2586 | lds edx, [si.TASK.dta] 2587 | else 2588 | lds dx, [si.TASK.dta] 2589 | endif 2590 | mov ah,1ah 2591 | call doscall ;use doscall in case the app hasn't restored vector 21 2592 | pop ds 2593 | endif 2594 | ret 2595 | restoreint2x endp 2596 | 2597 | ;------------------------------------------------------- 2598 | 2599 | setexc proc 2600 | jcxz @F 2601 | mov ax,0203h 2602 | call dpmicall ;set ext vector 2603 | @@: 2604 | ret 2605 | setexc endp 2606 | 2607 | ;------------------------------------------------------- 2608 | ;*** prepare loader for termination 2609 | 2610 | resetvecs proc 2611 | 2612 | if ?USE1PSP 2613 | test bEnvFlgs, ENVFL_LOAD1APPONLY 2614 | jnz @F 2615 | endif 2616 | @trace_s <"restoring loader PSP="> 2617 | mov bx,[wLdrPSP] 2618 | @trace_w bx 2619 | @trace_s <", segm="> 2620 | @trace_w [wRMPSP] 2621 | @trace_s lf 2622 | mov ah,50h 2623 | call doscall 2624 | @@: 2625 | @trace_s <"restoring exception vectors",lf> 2626 | if ?EXC01RESET 2627 | if ?32BIT 2628 | mov cx,word ptr oldexc01+4 2629 | mov edx,dword ptr oldexc01+0 2630 | else 2631 | mov cx,word ptr oldexc01+2 2632 | mov dx,word ptr oldexc01+0 2633 | endif 2634 | mov bl,01h 2635 | call setexc 2636 | endif 2637 | if ?32BIT 2638 | mov cx,word ptr oldexc0b+4 2639 | mov edx,dword ptr oldexc0b+0 2640 | else 2641 | mov cx,word ptr oldexc0b+2 2642 | mov dx,word ptr oldexc0b+0 2643 | endif 2644 | mov bl,0Bh 2645 | call setexc 2646 | if _TRAPEXC0D_ 2647 | if ?32BIT 2648 | mov cx,word ptr oldexc0D+4 2649 | mov edx,dword ptr oldexc0D+0 2650 | else 2651 | mov cx,word ptr oldexc0D+2 2652 | mov dx,word ptr oldexc0D+0 2653 | endif 2654 | mov bl,0Dh 2655 | call setexc 2656 | endif 2657 | mov bx,[aliassel] 2658 | @trace_s <"freeing alias selector "> 2659 | @trace_w bx 2660 | @trace_s lf 2661 | mov ax,0001 ;free selector 2662 | call dpmicall 2663 | if ?PESUPP 2664 | call DeinitPELoader 2665 | endif 2666 | @trace_s <"restoring vector int 0x21",lf> 2667 | if ?32BIT 2668 | mov cx,word ptr ds:[oldint21+4] 2669 | mov edx,dword ptr ds:[oldint21+0] 2670 | else 2671 | mov cx,word ptr ds:[oldint21+2] 2672 | mov dx,word ptr ds:[oldint21+0] 2673 | endif 2674 | mov bl,21h 2675 | mov ax,0205h ;set pm int 2676 | call dpmicall 2677 | 2678 | if ?DEBUG 2679 | @trace_s <"restoring vector int 0x41",lf> 2680 | if ?32BIT 2681 | mov cx,word ptr ds:[oldint41+4] 2682 | mov edx,dword ptr ds:[oldint41+0] 2683 | else 2684 | mov cx,word ptr ds:[oldint41+2] 2685 | mov dx,word ptr ds:[oldint41+0] 2686 | endif 2687 | mov bl,41h 2688 | mov ax,0205h 2689 | call dpmicall 2690 | endif 2691 | ret 2692 | 2693 | resetvecs endp 2694 | 2695 | if ?CHECKTOP 2696 | areweontop proc 2697 | mov bl,21h 2698 | mov ax,0204h 2699 | int 31h 2700 | mov ax, cs 2701 | cmp ax, cx 2702 | ret 2703 | areweontop endp 2704 | endif 2705 | 2706 | ;------------------------------------------------------- 2707 | 2708 | if ?CLOSEALLFILES 2709 | CloseAllFiles proc 2710 | mov bx,5 ;close open files >= 5 2711 | @@: 2712 | mov ah,3Eh 2713 | int 21h 2714 | inc bx 2715 | cmp bx,_FILEHANDLES_ 2716 | jnz @B 2717 | ret 2718 | CloseAllFiles endp 2719 | endif 2720 | 2721 | ;------------------------------------------------------- 2722 | ;*** insert MD in MD list 2723 | ;*** ES=current NE module 2724 | 2725 | InsertModule16 proc 2726 | mov ax,es 2727 | mov cx,[wMDSta] 2728 | @@: 2729 | jcxz @F 2730 | mov es,cx 2731 | mov cx,es:[NEHDR.NXTMOD] 2732 | jmp @B 2733 | @@: 2734 | mov es:[NEHDR.NXTMOD],ax ;overwrite length of entry table 2735 | mov es,ax 2736 | mov es:[NEHDR.NXTMOD],cx 2737 | ret 2738 | InsertModule16 endp 2739 | 2740 | ;*** delete NE module from MD list 2741 | ;*** MD in AX *** 2742 | 2743 | DeleteModule16 proc 2744 | xor bx,bx 2745 | @trace_s <"DeleteModule16 "> 2746 | @trace_w ax 2747 | @trace_s 2748 | mov cx,[wMDSta] 2749 | nextitem: 2750 | jcxz modnotfound 2751 | mov es,cx 2752 | cmp ax,cx 2753 | mov cx,es:[NEHDR.NXTMOD] 2754 | jz modfound 2755 | mov bx,es 2756 | jmp nextitem 2757 | modfound: ;ES = current MD, BX=previous, CX=next 2758 | and bx,bx 2759 | jnz @F 2760 | mov [wMDSta],cx 2761 | clc 2762 | ret 2763 | @@: 2764 | mov es,bx 2765 | mov es:[NEHDR.NXTMOD],cx 2766 | clc 2767 | ret 2768 | modnotfound: ;module not found 2769 | stc 2770 | ret 2771 | DeleteModule16 endp 2772 | 2773 | ;*** test if AX is referenced 2774 | ;*** C if yes, NC if no 2775 | 2776 | checkifreferenced proc 2777 | mov bx,ax 2778 | mov cx,[wMDSta] 2779 | checkifreferenced1: 2780 | clc 2781 | jcxz checkifreferencedex 2782 | mov es,cx 2783 | cmp bx,cx ;no if it is me 2784 | jz checkifreferenced2 2785 | mov cx,es:[NEHDR.ne_cmod] 2786 | jcxz checkifreferenced2 2787 | mov si,es:[NEHDR.ne_modtab] 2788 | checkifreferenced4: 2789 | lods word ptr es:[NEHDR.ne_cmod] ;lodsw with ES prefix! 2790 | cmp bx,ax 2791 | stc 2792 | jz checkifreferencedex ;yes, module referenced 2793 | loop checkifreferenced4 2794 | checkifreferenced2: 2795 | mov cx,es:[NEHDR.NXTMOD] 2796 | jmp checkifreferenced1 2797 | checkifreferencedex: 2798 | mov ax,bx 2799 | ret 2800 | checkifreferenced endp 2801 | 2802 | freemodulerest proc 2803 | pusha 2804 | if ?LOADDBGDLL 2805 | mov ax,[hModDbg] 2806 | and ax,ax 2807 | jz @F 2808 | @trace_s <"*** delete debugout.dll ***",lf> 2809 | call FreeLib16 2810 | @@: 2811 | endif 2812 | @trace_s <"*** enter auto delete mode ***",lf> 2813 | freemodulerest3: ;<---- 2814 | mov ax,[wMDSta] 2815 | and ax,ax 2816 | jz freemodulerestex_1 2817 | @@: 2818 | verr ax 2819 | jnz freemodulerestex_1 ;error in module list 2820 | mov es,ax 2821 | mov ax,es:[NEHDR.NXTMOD] 2822 | and ax,ax 2823 | jnz @B ;go to end of list 2824 | freemodulerest21: 2825 | mov ax,es 2826 | @trace_s <"checking references of module "> 2827 | @trace_w ax 2828 | @trace_s lf 2829 | call checkifreferenced ;only free modules which arent referenced 2830 | jc freemodulerest2 2831 | call FreeLib16 2832 | if 1 2833 | jmp freemodulerest3 ;now try again 2834 | else 2835 | jnc freemodulerest3 ;now try again 2836 | jmp freemodulerestex_1 2837 | endif 2838 | freemodulerest2: 2839 | mov bx,ax ;current module is referenced 2840 | mov ax,[wMDSta] ;so get previous module 2841 | cmp ax,bx ;if there is none 2842 | jz freemodulerestex_1;immediate exit 2843 | @@: 2844 | mov es,ax 2845 | mov ax,es:[NEHDR.NXTMOD] 2846 | cmp ax,bx 2847 | jnz @B 2848 | jmp freemodulerest21 2849 | freemodulerestex_1: 2850 | if ?PESUPP 2851 | call UnloadPEModules 2852 | endif 2853 | @trace_s <"*** exit auto delete mode ***",lf> 2854 | freemodulerestex: 2855 | popa 2856 | ret 2857 | freemodulerest endp 2858 | 2859 | ;*** save path of .EXE as default for DLLs 2860 | ;*** Input: ES -> MD *** 2861 | ;*** Output: path in szPath *** 2862 | 2863 | savepathNE proc 2864 | @swap ds,es 2865 | 2866 | mov di,offset szPath 2867 | mov si,offset NEHDR.szModPath 2868 | savepath0: 2869 | mov dx,di 2870 | savepath1: 2871 | lodsb 2872 | stosb 2873 | cmp al,'\' 2874 | jz savepath0 2875 | cmp al,'/' 2876 | jz savepath0 2877 | and al,al 2878 | jnz savepath1 2879 | mov di,dx 2880 | stosb 2881 | @swap ds,es 2882 | ret 2883 | savepathNE endp 2884 | 2885 | ;*** copy cmdline in PSP 2886 | ;*** Inp: ES:(E)BX -> exec parm blk 2887 | ;*** regretably there are 2 formats for the parameter string 2888 | ;*** for windows in asciiz format, for DOS in pascal format 2889 | 2890 | SetCmdLine proc public uses es ds 2891 | 2892 | if ?32BIT 2893 | pushad 2894 | else 2895 | pusha 2896 | endif 2897 | mov ds,cs:[wLdrDS] 2898 | xor al,al 2899 | xchg [fLoadMod],al 2900 | if ?32BIT 2901 | lds esi,es:[ebx+0] ;get dos command tail 2902 | @trace_s <"SetCmdLine enter, es:ebx="> 2903 | @trace_w es 2904 | @trace_s <':'> 2905 | @trace_d ebx 2906 | @trace_s <" cmdl="> 2907 | @trace_w ds 2908 | @trace_s <':'> 2909 | @trace_d esi 2910 | if ?DEBUG 2911 | @trace_s <" size="> 2912 | movzx cx,byte ptr [esi] 2913 | @trace_w cx 2914 | endif 2915 | @trace_s 2916 | else 2917 | lds si,es:[bx+2] 2918 | @trace_s <"SetCmdLine enter, es:bx="> 2919 | @trace_w es 2920 | @trace_s <':'> 2921 | @trace_w bx 2922 | @trace_s <" cmdl="> 2923 | @trace_w ds 2924 | @trace_s <':'> 2925 | @trace_w si 2926 | @trace_s 2927 | endif 2928 | mov es,cs:[wCurPSP] 2929 | and al,al 2930 | jz @F 2931 | call strlen ;get size of DS:E/SI into CX 2932 | mov al,cl 2933 | jmp scl_2 2934 | @@: 2935 | if ?32BIT 2936 | lods byte ptr [esi] 2937 | else 2938 | lodsb 2939 | endif 2940 | scl_2: 2941 | mov cl,al ;number of chars 2942 | mov ch,00 2943 | mov di,0080h 2944 | stosb 2945 | if ?32BIT 2946 | movzx ecx,cx 2947 | movzx edi,di 2948 | rep movs byte ptr [edi],[esi] 2949 | else 2950 | rep movsb 2951 | endif 2952 | test di,0FF00h 2953 | jnz @F 2954 | mov al,cr 2955 | stosb 2956 | @@: 2957 | if ?32BIT 2958 | popad 2959 | else 2960 | popa 2961 | endif 2962 | @trace_s <"SetCmdLine exit",lf> 2963 | ret 2964 | 2965 | SetCmdLine endp 2966 | 2967 | if ?NEAPPS 2968 | 2969 | ;--- get stack parameters for a NE module 2970 | ;--- inp: ES -> NE-Header 2971 | ;--- ret: NC: SS:SP in AX:(E)DX 2972 | ;--- ret: C, AX->error string 2973 | 2974 | GetSSSP proc 2975 | @trace_s <"GetSSSP entered",lf> 2976 | mov ax,word ptr es:[NEHDR.ne_sssp+2] ;SS 2977 | test ax,ax 2978 | jz error1 ;no stack for application? -> error 2979 | test byte ptr es:[NEHDR.PGMFLGS],PF_MULTIPLE ;multiple DGROUPS? 2980 | jz @F 2981 | cmp es:[NEHDR.ne_count],1 ;module used more than once? 2982 | jnz MultInst ;error 2983 | @@: 2984 | call SegNo2Sel ;get selector in AX 2985 | lar cx,ax 2986 | test ch,08h ;is SS a code selector? 2987 | jz getsssp_1 ;(might be true for model tiny) 2988 | mov bx,es:[NEHDR.DGROFS] 2989 | mov ax,es:[bx].SEGITEM.wSel 2990 | if _WINNT40BUG_ 2991 | ;winnt 4.0 might not create a NP exc! 2992 | test es:[bx.SEGITEM.flags],SF_ALIAS 2993 | jz @F 2994 | pusha 2995 | mov si,bx 2996 | call Load_Segm ;this will do a "Realloc" 2997 | popa 2998 | @@: 2999 | endif 3000 | getsssp_1: 3001 | if ?32BIT 3002 | push ax ;save selector 3003 | mov cx,0FFFFh 3004 | mov dx,4000h ;set default bit 3005 | call setaccrights 3006 | movzx ebx,bx 3007 | pop ax 3008 | endif 3009 | mov bx,word ptr es:[NEHDR.ne_sssp+0] ;SP 3010 | and bx,bx 3011 | jnz @F 3012 | push ax 3013 | mov ax,word ptr es:[NEHDR.ne_sssp+2] 3014 | dec ax 3015 | mov bl,SGTSIZE 3016 | mul bl 3017 | mov bx,ax 3018 | pop ax 3019 | add bx,es:[NEHDR.ne_segtab] ;stack needn't be == DGROUP! 3020 | mov bx,es:[bx.SEGITEM.memsiz] ;get mem size of stack segment 3021 | if ?32BIT 3022 | movzx edx,word ptr es:[NEHDR.ne_stack] ;+ extra stack space 3023 | shl edx,12 ;alloc pages instead of bytes 3024 | add ebx,edx 3025 | @@: 3026 | mov edx,ebx 3027 | and dl,0FCh 3028 | else 3029 | add bx,es:[NEHDR.ne_stack] ;+ extra Stack 3030 | @@: 3031 | mov dx,bx 3032 | and dl,0FEh 3033 | endif 3034 | @trace_s <"GetSSSP exit",lf> 3035 | clc 3036 | ret 3037 | error1: 3038 | mov ax,offset errstr16 3039 | stc 3040 | ret 3041 | MultInst: 3042 | mov [wlError],0010h 3043 | mov ax,offset errstr20 3044 | stc 3045 | ret 3046 | GetSSSP endp 3047 | 3048 | endif 3049 | 3050 | ;*** search var (dx->name) in loader environment 3051 | ;--- returns NC + offset in DI, else C 3052 | ;--- modifies DI, AX 3053 | 3054 | GetLdrEnvironmentVariable proc 3055 | mov es,[wLdrPSP] 3056 | GetEnvironmentVariable:: ;<--- entry with ES=PSP 3057 | mov es,es:[ENVIRON] ;environment 3058 | SUB DI,DI ;start with es:[0] 3059 | CLD 3060 | mov cx,-1 3061 | nextitem: 3062 | push si 3063 | mov SI,dx 3064 | db 2Eh ;CS prefix 3065 | REPZ CMPSB 3066 | ; cmp word ptr cs:[si-2],"=" 3067 | cmp byte ptr cs:[si-1],0 3068 | pop si 3069 | JZ found 3070 | mov al,00 3071 | repnz scasb 3072 | CMP ES:[DI],al 3073 | JNZ nextitem 3074 | @trace_s <"environment variable not found",lf> 3075 | ; mov ah,0 3076 | STC 3077 | RET 3078 | found: 3079 | dec di 3080 | @trace_s <"environment variable found",lf> 3081 | CLC 3082 | RET 3083 | GetLdrEnvironmentVariable endp 3084 | 3085 | copyfilename proc 3086 | mov SI,offset szName 3087 | @@: 3088 | LODSB 3089 | MOV [DI],AL 3090 | INC DI 3091 | CMP AL,00 3092 | JNZ @B 3093 | ret 3094 | copyfilename endp 3095 | 3096 | if ?32BIT 3097 | openfile proc public uses ebx 3098 | else 3099 | openfile proc public 3100 | endif 3101 | 3102 | ; @trace_s <"try to open: "> 3103 | ; @trace_sx dx 3104 | ; @trace_s lf 3105 | if ?LFN 3106 | test cs:fMode, FMODE_LFN 3107 | jz nolfn 3108 | if ?32BIT 3109 | if ?LFNNT 3110 | test cs:fMode, FMODE_ISNT 3111 | jz nont 3112 | push es 3113 | push esi 3114 | push edi 3115 | push ebp 3116 | sub esp, 32+2 3117 | mov ebp, esp 3118 | mov [ebp].RMCS.rAX,716Ch 3119 | mov [ebp].RMCS.rBX,0 3120 | mov [ebp].RMCS.rCX,0 3121 | mov [ebp].RMCS.rDX,1 3122 | mov cx,80h 3123 | mov [ebp].RMCS.rSI,cx 3124 | mov di, 80h 3125 | mov es, cs:[wLdrPSP] 3126 | mov esi, edx 3127 | @@: 3128 | if ?32BIT 3129 | lods byte ptr [esi] 3130 | else 3131 | lodsb 3132 | endif 3133 | stosb 3134 | and al,al 3135 | loopnz @B 3136 | mov ax,cs:[wRMPSP] 3137 | mov [ebp].RMCS.rDS,ax 3138 | mov [ebp].RMCS.rFlags,1 3139 | mov [ebp].RMCS.rSSSP,0 3140 | mov edi, ebp 3141 | push ss 3142 | pop es 3143 | mov bx,0021h 3144 | xor cx,cx 3145 | mov ax,0300h 3146 | int 31h 3147 | mov ax,[ebp].RMCS.rAX 3148 | test [ebp].RMCS.rFlags, 1 3149 | lea esp, [esp+32+2] 3150 | pop ebp 3151 | pop edi 3152 | pop esi 3153 | pop es 3154 | jz done 3155 | cmp ax,7100h 3156 | jz nolfn 3157 | stc 3158 | jmp done 3159 | nont: 3160 | endif 3161 | endif 3162 | if ?32BIT 3163 | push esi 3164 | mov esi,edx 3165 | else 3166 | push si 3167 | mov si,dx 3168 | endif 3169 | MOV AX,716Ch 3170 | mov dx,1 ;action: fail if not exists 3171 | xor bx,bx ;read only 3172 | xor cx,cx ; 3173 | stc 3174 | int 21h ;use true DOS int (LFN for XP needs DKRNL32!) 3175 | if ?32BIT 3176 | mov edx,esi 3177 | pop esi 3178 | else 3179 | mov dx,si 3180 | pop si 3181 | endif 3182 | jnc done 3183 | cmp ax,7100h 3184 | stc 3185 | jnz done 3186 | nolfn: 3187 | endif 3188 | MOV AX,3D00h or _SFLAGS_ ;open a file for read 3189 | int 21h 3190 | done: 3191 | ret 3192 | openfile endp 3193 | 3194 | ;*** search file in PATH 3195 | ;*** inp: es:di behind "PATH=" in environment 3196 | ;--- inp: szName: file to search 3197 | ;*** out: file handle in AX if NC 3198 | ;--- out: full path of file in szModName 3199 | ;*** modifies szModName, SI 3200 | 3201 | SearchFileInPath proc 3202 | MOV SI,DI 3203 | nextitem: ;<---- 3204 | mov cl,00 3205 | mov DI,offset szModName 3206 | @@: 3207 | MOV AL,ES:[SI] ;get next path from PATH variable 3208 | CMP AL,';' 3209 | JZ @F 3210 | CMP AL,00 3211 | JZ @F 3212 | MOV [DI],AL 3213 | inc cl 3214 | INC SI 3215 | INC DI 3216 | JMP @B 3217 | @@: 3218 | mov ah,0 3219 | and cl,cl ;is an empty path? 3220 | jz skipitem 3221 | CMP Byte Ptr [DI-01],'\' ;ends with backslash? 3222 | JZ @F 3223 | CMP Byte Ptr [DI-01],'/' ;or slash? 3224 | JZ @F 3225 | MOV Byte Ptr [DI],'\' ;add one 3226 | INC DI 3227 | @@: 3228 | push si 3229 | call copyfilename 3230 | mov DX,offset szModName 3231 | call openfile 3232 | pop si 3233 | jnc found 3234 | cmp ax, 4 ;no file handles error? 3235 | jz error 3236 | skipitem: 3237 | mov cl,es:[si] 3238 | INC SI 3239 | cmp cl,';' 3240 | jz nextitem 3241 | error: 3242 | push ax 3243 | mov DI,offset szModName 3244 | call copyfilename 3245 | @trace_s <"module not found in path",lf> 3246 | pop ax 3247 | STC 3248 | RET 3249 | found: 3250 | @trace_s <"module found in path",lf> 3251 | RET 3252 | 3253 | SearchFileInPath endp 3254 | 3255 | ;*** file not found in current directory 3256 | ;*** scan PATH, NC if file was found 3257 | ;*** then file handle in AX and file full path in ??? 3258 | ;*** inp: ds=loader dataseg 3259 | ;--- szName= file to search 3260 | ;*** C if error, then dos error code in AX 3261 | ;*** modifies SI 3262 | 3263 | ScanPath proc near 3264 | 3265 | @trace_s <"Searching PATH Variable",lf> 3266 | if ?32BIT 3267 | cmp [dwSysDir],0 3268 | jz nosysdir 3269 | push es 3270 | push esi 3271 | push di 3272 | mov esi, [dwSysDir] 3273 | mov es,cs:[wFlatDS] 3274 | mov DI,offset szModName 3275 | @@: 3276 | lods byte ptr es:[esi] 3277 | mov [di],al 3278 | inc di 3279 | and al,al 3280 | jnz @B 3281 | mov byte ptr [di-1],'\' 3282 | call copyfilename 3283 | pop di 3284 | pop esi 3285 | pop es 3286 | mov DX,offset szModName 3287 | call openfile 3288 | jnc exit 3289 | nosysdir: 3290 | endif 3291 | mov dx,offset szPathConst ;variable "PATH=" 3292 | if 0 3293 | call GetLdrEnvironmentVariable ;DI=^Path 3294 | else 3295 | mov es,cs:[wCurPSP] 3296 | call GetEnvironmentVariable ;DI=^Path 3297 | endif 3298 | jc exit 3299 | ;PATH variable found (ES:DI) 3300 | call SearchFileInPath ;if found, in AX Handle (modifies SI) 3301 | exit: 3302 | ret 3303 | ScanPath endp 3304 | 3305 | if 1 3306 | ;--- current drive/directory -> ds:si 3307 | ;--- highword of esi has been cleared in 32bit version 3308 | ;--- called by checkpathname 3309 | ;--- return: size in AX 3310 | 3311 | getcurrentdir proc 3312 | @trace_s <"enter getcurrentdir",lf> 3313 | push dx 3314 | push si 3315 | mov ah,19h 3316 | int 21h 3317 | @trace_s <"int 21,ah=19h called",lf> 3318 | mov dl,al 3319 | inc dl 3320 | add al,'A' 3321 | mov [si],al 3322 | mov ax,"\:" 3323 | mov [si+1],ax 3324 | add si,3 3325 | mov ah,47h 3326 | int 21h 3327 | @trace_s <"int 21,ah=47h called",lf> 3328 | mov ah,-1 3329 | @@: 3330 | lodsb 3331 | inc ah 3332 | and al,al 3333 | jnz @B 3334 | and ah,ah 3335 | jz @F 3336 | mov word ptr [si-1],"\" 3337 | @@: 3338 | mov ax,si 3339 | pop si 3340 | sub ax,si 3341 | pop dx 3342 | @trace_s <"exit getcurrentdir",lf> 3343 | ret 3344 | getcurrentdir endp 3345 | endif 3346 | 3347 | ;*** Caller: LoadModule16 3348 | ;*** Input: DX:(E)AX=Path 3349 | ;*** szPath= path of last EXE or 0 3350 | ;*** Output: 3351 | ;*** filename in szName (8.3) 3352 | ;*** Pfad in szModName 3353 | ;*** ??? in szPath 3354 | ;*** DX=0 -> unqualified angabe 3355 | 3356 | checkpathname proc 3357 | @trace_s <"enter checkpathname",lf> 3358 | push ds 3359 | mov di,offset segtable 3360 | mov bx,offset szName 3361 | push ds 3362 | pop es 3363 | mov ds,dx 3364 | xor dx,dx 3365 | if ?32BIT 3366 | mov esi,eax 3367 | mov al,[esi] 3368 | else 3369 | mov si,ax 3370 | mov al,[si] 3371 | endif 3372 | cmp al,'\' 3373 | jz checkpath0 3374 | cmp al,'/' 3375 | jz checkpath0 3376 | if ?32BIT 3377 | mov ax,[esi+1] 3378 | else 3379 | mov ax,[si+1] 3380 | endif 3381 | cmp al,':' 3382 | jnz checkpath1 3383 | cmp ah,'/' 3384 | jz checkpath0 3385 | cmp ah,'\' 3386 | jnz checkpath1 3387 | checkpath0: 3388 | mov di,offset szModName 3389 | inc dh 3390 | checkpath1: ;copy [(E)SI] -> modname 3391 | if ?32BIT 3392 | lods byte ptr [esi] 3393 | else 3394 | lodsb 3395 | endif 3396 | stosb 3397 | mov es:[bx],al ;copy [(E)SI] -> szName 3398 | inc bx 3399 | cmp al,':' 3400 | jz checkpath3 3401 | cmp al,'/' 3402 | jz checkpath3_1 3403 | cmp al,'\' 3404 | jnz @F 3405 | checkpath3_1: 3406 | inc dl 3407 | checkpath3: 3408 | mov bx,offset szName ;reset szName 3409 | @@: 3410 | and al,al 3411 | jnz checkpath1 3412 | pop ds 3413 | mov ax,[bx-3] 3414 | or ax,2020h 3415 | cmp ax,"ex" 3416 | jnz @F 3417 | mov ax,[bx-5] 3418 | or ax,2020h 3419 | cmp ax,"e." 3420 | jnz @F 3421 | mov szPath,0 ;reset szPath if it is an .EXE 3422 | @@: 3423 | and dh,dh ;absolute path given? 3424 | jnz checkpath2 ;then jump 3425 | mov di,offset szModName 3426 | mov si,offset szPath 3427 | if ?32BIT 3428 | movzx esi,si ;is required, not only for getcurrentdir! 3429 | endif 3430 | if 1 3431 | cmp [si],dh ;is szPath set? 3432 | jnz @F 3433 | call getcurrentdir ;current dir -> ds:si 3434 | @trace_s <"relative path given, curdir is "> 3435 | @trace_sx si 3436 | @trace_s 3437 | endif 3438 | @@: ;szPath -> szModName 3439 | lodsb 3440 | stosb 3441 | and al,al 3442 | jnz @B 3443 | dec di 3444 | cmp dl,0 3445 | jz nosubdirs 3446 | mov si,offset segtable 3447 | nextitem: 3448 | lodsb 3449 | stosb 3450 | cmp al,'/' 3451 | jz checkpath4 3452 | cmp al,'\' 3453 | jnz @F 3454 | checkpath4: 3455 | dec dl 3456 | @@: 3457 | or dl,dl 3458 | jnz nextitem 3459 | inc dl ;return dl != 0 to avoid PATH search 3460 | nosubdirs: 3461 | mov si,offset szName ;strcat(szModName, szName) 3462 | if ?32BIT 3463 | mov ah,00 ;switch to dos32 name 3464 | invoke checkandreplace 3465 | endif 3466 | @@: 3467 | lodsb 3468 | stosb 3469 | and al,al 3470 | jnz @B 3471 | checkpath2: 3472 | @trace_s <"szModName: "> 3473 | @trace_sx 3474 | @trace_s 3475 | @trace_sx 3476 | @trace_s 3477 | @trace_sx 3478 | @trace_s 3479 | ret 3480 | checkpathname endp 3481 | 3482 | 3483 | checkoutoffh proc 3484 | cmp ax,4 3485 | jnz exit 3486 | pusha 3487 | push es 3488 | mov ah,62h 3489 | int 21h 3490 | mov es,bx 3491 | mov bx,es:[32h] 3492 | cmp bx,0EFh ;can it be increased? 3493 | jnb @F 3494 | add bx,11h 3495 | mov ah,67h 3496 | int 21h 3497 | @trace_s <"size file handle table increased to "> 3498 | @trace_w bx 3499 | @trace_s 3500 | pop es 3501 | popa 3502 | stc 3503 | ret 3504 | @@: 3505 | @trace_s <"cannot increase file handle table",lf> 3506 | pop es 3507 | popa 3508 | exit: 3509 | clc 3510 | ret 3511 | checkoutoffh endp 3512 | 3513 | ;*** load a NE module 3514 | ;*** Input: DX:(E)AX -> path 3515 | ;*** DS=DGROUP *** 3516 | ;*** RC: C on errors, then in AX=^ErrText 3517 | ;*** else AX=MD 3518 | ;--- modifies E/BX, E/SI, E/DI!!! 3519 | 3520 | LoadModule16 proc 3521 | cld 3522 | if _TRACE_ 3523 | @trace_s <"enter load module: "> 3524 | push ds 3525 | push ax 3526 | mov ds,dx 3527 | if ?32BIT 3528 | mov ebx,eax 3529 | else 3530 | mov bx,ax 3531 | endif 3532 | call _trace_s_bx 3533 | @trace_s lf 3534 | pop ax 3535 | pop ds 3536 | endif 3537 | call checkpathname ;path -> szModName, modulname -> pszName 3538 | tryagain: 3539 | push dx 3540 | mov dx,offset szModName 3541 | if ?32BIT 3542 | movzx edx,dx 3543 | endif 3544 | call openfile 3545 | pop dx 3546 | jnc loadmod_2 3547 | call checkoutoffh 3548 | jc tryagain 3549 | and dx,dx ;was an absolute path given? 3550 | jnz loadmod_1 ;then error 3551 | @trace_s <"open of "> 3552 | @trace_sx 3553 | @trace_s <" failed, error="> 3554 | @trace_w ax 3555 | @trace_s 3556 | @trace_s <"will try to open "> 3557 | @trace_sx 3558 | @trace_s 3559 | push dx 3560 | mov dx,offset szName ;try name without path (current dir) 3561 | call openfile 3562 | pop dx 3563 | jnc loadmod_21 3564 | @trace_s <"will search path now",lf> 3565 | call ScanPath ;load without path didn't work, scan PATH 3566 | jnc loadmod_2 3567 | @trace_s <"ScanPath returned error="> 3568 | @trace_w ax 3569 | @trace_s lf 3570 | loadmod_1: 3571 | cmp ax, 4 3572 | mov ax,offset szNotFnd 3573 | jnz errorx ;error 'file not found' 3574 | mov ax,offset nohandles 3575 | jmp errorx 3576 | loadmod_21: 3577 | push ax 3578 | mov si, offset szModName 3579 | call getcurrentdir 3580 | add si,ax 3581 | mov di,offset szName 3582 | @@: 3583 | mov al,[di] 3584 | mov [si],al 3585 | inc si 3586 | inc di 3587 | and al,al 3588 | jnz @B 3589 | pop ax 3590 | loadmod_2: 3591 | mov bx,ax 3592 | call ReadHdrs ;load headers (0040h Bytes) (to NE_Hdr) 3593 | jc error3 ;error 3594 | test byte ptr NE_Hdr.APPFLGS,AF_DLL ;is app or dll? 3595 | jnz @F 3596 | mov ax,offset szNotaNE 3597 | if ?32BIT 3598 | cmp NE_Hdr.ne_exetyp, ET_DPMI32 ;only load 32bit NE apps!!! 3599 | jnz error3 3600 | else 3601 | cmp NE_Hdr.ne_exetyp, ET_DPMI32 ;dont load 32bit NE apps!!! 3602 | jz error3 3603 | cmp NE_Hdr.ne_exetyp, ET_WINDOWS;dont load Win3 NE apps!!! 3604 | jz error3 3605 | endif 3606 | cmp [wTDStk],offset starttaskstk 3607 | jz @F 3608 | if ?32BIT 3609 | test bEnvFlgs, ENVFL_DISABLENE32 3610 | jnz error3 3611 | endif 3612 | test bEnvFlgs, ENVFL_LOAD1APPONLY 3613 | jnz error3 3614 | @@: 3615 | call AllocMD ;alloc module database 3616 | jc error3 3617 | mov es:[NEHDR.ne_hFile],bx 3618 | call LoadSegmTable ;read segment table 3619 | jc error2 3620 | call LoadNETables ;read other tables 3621 | jc error2 3622 | ;now NE:0006 may be modified 3623 | call InsertModule16 ;save module ES in module list 3624 | call LoadRefMods16 ;load modules of external references 3625 | jc error2 3626 | call DoPreloads ;load PRELOAD and HUGE segments 3627 | jc error4 3628 | mov ax,word ptr es:[NEHDR.ne_csip+2] 3629 | and ax,ax 3630 | jz @F 3631 | call SegNo2Sel ;get selector for entry CS 3632 | mov word ptr es:[NEHDR.ne_csip+2],ax 3633 | @@: 3634 | mov bx,0FFFFh 3635 | xchg bx,es:[NEHDR.ne_hFile] 3636 | mov ah,3Eh ;close file 3637 | int 21h 3638 | jc error1 3639 | @trace_s <"module "> 3640 | @tracemodule 3641 | @trace_s <" ("> 3642 | @trace_w es 3643 | @trace_s <") successfully loaded",lf> 3644 | mov ax,es 3645 | ret 3646 | error4: 3647 | push ax 3648 | call UnloadMod16 ;clear all 3649 | pop ax 3650 | error2: 3651 | push ax 3652 | test byte ptr [wErrMode+1],HBSEM_NOOPENFILEBOX 3653 | jnz @F 3654 | @strout_err "Error while loading module " 3655 | call modnameout 3656 | @cr_out 3657 | @@: 3658 | mov word ptr es:[NEHDR.ne_cmod],0000 3659 | mov ax,es 3660 | call FreeLib16 ;delete module 3661 | pop ax 3662 | stc 3663 | ret 3664 | error3: 3665 | push ax 3666 | mov ah,3Eh ;close file 3667 | int 21h 3668 | pop ax 3669 | jmp errorx 3670 | error1: 3671 | xor ax,ax ;error on close 3672 | errorx: 3673 | if _TRACE_ 3674 | @trace_s <"can't load module "> 3675 | mov bx,offset szModName 3676 | if ?32BIT 3677 | movzx ebx,bx 3678 | endif 3679 | call _trace_s_bx 3680 | @trace_s lf 3681 | and ax,ax 3682 | jz @F 3683 | if ?32BIT 3684 | movzx ebx,ax 3685 | else 3686 | mov bx,ax 3687 | endif 3688 | call _trace_s_bx 3689 | @@: 3690 | endif ;_TRACE_ 3691 | cmp ax,offset szNotaNE ;dont display "not NE format" 3692 | jz @F 3693 | test byte ptr [wErrMode+1],HBSEM_NOOPENFILEBOX 3694 | jnz @F 3695 | @strout_err "Module=" 3696 | mov bx,offset szModName 3697 | @stroutbx 3698 | @cr_out 3699 | @@: 3700 | stc 3701 | ret 3702 | LoadModule16 endp 3703 | 3704 | ;*** read MZ-Header + NE-Header 3705 | ;*** Input: BX=file handle 3706 | ;--- DS=DGROUP 3707 | ;*** C + AX=szNotaNE if not NE format 3708 | 3709 | ReadHdrs proc 3710 | 3711 | @trace_s <"trying to read MZ/NE-Header",lf> 3712 | xor ax,ax 3713 | mov [NEHdrOfs],ax ;init offset NE-Header 3714 | mov cx,0040h 3715 | mov dx,offset MZ_Hdr 3716 | mov ah,3Fh ;read MZ hdr 3717 | int 21h 3718 | jc error1 ;DOS read error 3719 | cmp ax,cx ;could read 40h bytes? 3720 | jnz error2 3721 | mov ax,word ptr [MZ_Hdr] 3722 | cmp ax,'ZM' 3723 | jz @F 3724 | cmp ax,'EN' 3725 | jz found ;MZ hdr is missing, is not an error 3726 | jmp error3 3727 | @@: 3728 | @trace_s <"trying to locate NE-Header",lf> 3729 | mov cx,word ptr [MZ_Hdr+3Eh] 3730 | mov dx,word ptr [MZ_Hdr+3Ch] 3731 | and dx,dx 3732 | jz error4 3733 | mov [NEHdrOfs],dx ;offset NE-Headers 3734 | mov ax,4200h ;lseek NE hdr 3735 | int 21h 3736 | jc error5 ;DOS lseek error, no NE binary 3737 | @trace_s <"trying to read NE-Header",lf> 3738 | mov cx,0040h 3739 | mov dx,offset NE_Hdr 3740 | mov ah,3Fh ;read 3741 | int 21h 3742 | jc error6 ;DOS read error 3743 | cmp ax,cx 3744 | jnz error7 3745 | cmp word ptr [NE_Hdr],'EN' ;"NE" signature found? 3746 | jnz error8 3747 | found: 3748 | clc 3749 | ret 3750 | error4: 3751 | @trace_s <"NE-offset is zero",lf> 3752 | @tracejmp @F 3753 | error2: 3754 | @trace_s <"filesize less than 0x0040 Bytes",lf> 3755 | @tracejmp @F 3756 | error3: 3757 | @trace_s <"cannot find 'MZ' Header",lf> 3758 | @tracejmp @F 3759 | error5: 3760 | @trace_s <"lseek error",lf> 3761 | @tracejmp @F 3762 | error7: 3763 | @trace_s <"NE-Header size less than 0x0040 Bytes",lf> 3764 | @tracejmp @F 3765 | error8: 3766 | @trace_s <"cannot find 'NE' Header",lf> 3767 | @tracejmp @F 3768 | @@: 3769 | mov ax,offset szNotaNE ;File is no NE-EXE 3770 | stc 3771 | ret 3772 | error1: 3773 | @trace_s <"read error (MZ)",lf> 3774 | @tracejmp @F 3775 | error6: 3776 | @trace_s <"read error (NE)",lf> 3777 | @tracejmp @F 3778 | @@: 3779 | mov ax,0000 3780 | ret 3781 | 3782 | ReadHdrs endp 3783 | 3784 | ;*** change descriptor from code to data/from data to code 3785 | ;*** inp BX = source selector 3786 | ;*** inp AX = dest selector 3787 | ;--- out AX = dest selector 3788 | ;*** called by PrestoChangoSelector() 3789 | 3790 | CreateAlias proc public 3791 | 3792 | push es 3793 | push bx 3794 | if ?32BIT 3795 | push edi 3796 | sub esp,8 3797 | mov edi, esp 3798 | else 3799 | push di 3800 | push bp 3801 | mov bp,sp 3802 | sub sp,8 3803 | mov di,sp 3804 | endif 3805 | if _TRACE_ 3806 | if ?32BIT 3807 | pushad 3808 | @trace_s <"CreateAlias, src="> 3809 | @trace_w bx 3810 | lar ecx,ebx 3811 | shr ecx,8 3812 | @trace_s <",acc="> 3813 | @trace_w cx 3814 | @trace_s <" dest="> 3815 | @trace_w ax 3816 | lar ecx,eax 3817 | shr ecx,8 3818 | @trace_s <",acc="> 3819 | @trace_w cx 3820 | @trace_s lf 3821 | popad 3822 | endif 3823 | endif 3824 | push ax 3825 | push ss 3826 | pop es 3827 | mov ax,000Bh ;get BX desc -> ES:(E)DI 3828 | int 31h 3829 | jc exit 3830 | @trace_s <"CreateAlias, get descriptor ok",lf> 3831 | if ?32BIT 3832 | xor byte ptr es:[edi+5],8 3833 | else 3834 | xor byte ptr es:[di+5],8 3835 | endif 3836 | pop bx ;AX -> BX 3837 | push bx 3838 | 3839 | mov ax,000Ch ;set BX desc <- ES:(E)DI 3840 | int 31h 3841 | if _TRACE_ 3842 | jc exit 3843 | @trace_s <"CreateAlias, set descriptor ok",lf> 3844 | clc 3845 | endif 3846 | exit: 3847 | pop ax 3848 | if ?32BIT 3849 | lea esp,[esp+8] 3850 | pop edi 3851 | else 3852 | mov sp,bp 3853 | pop bp 3854 | pop di 3855 | endif 3856 | pop bx 3857 | pop es 3858 | ret 3859 | CreateAlias endp 3860 | 3861 | ;*** copy descriptor (BX) to desc AX 3862 | ;*** modifies ES, BX 3863 | ;*** C if error 3864 | 3865 | CopyDescriptor proc public 3866 | push es 3867 | push ax 3868 | if ?32BIT 3869 | push edi 3870 | sub esp,8 3871 | mov edi,esp 3872 | else 3873 | push di 3874 | push bp 3875 | mov bp,sp 3876 | sub sp,8 3877 | mov di,sp 3878 | endif 3879 | push ss 3880 | pop es 3881 | push ax 3882 | mov ax,000Bh ;get descriptor 3883 | call dpmicall 3884 | pop bx 3885 | jc @F 3886 | mov ax,000Ch ;set descriptor 3887 | call dpmicall 3888 | @@: 3889 | if ?32BIT 3890 | lea esp,[esp+8] 3891 | pop edi 3892 | else 3893 | mov sp,bp 3894 | pop bp 3895 | pop di 3896 | endif 3897 | pop ax 3898 | pop es 3899 | ret 3900 | CopyDescriptor endp 3901 | 3902 | ;*** create a writeable ALIAS for a descriptor 3903 | ;--- in: ES:SI -> segment 3904 | ;--- out: DX = writeable DATA selector, C on errors 3905 | ;--- preserves ax,bx,cx 3906 | 3907 | setrwsel proc near 3908 | 3909 | push es 3910 | push ax 3911 | push bx 3912 | mov bx,es:[si].SEGITEM.wSel 3913 | if ?32BIT 3914 | push edi 3915 | sub esp,8 3916 | mov edi,esp 3917 | else 3918 | push di 3919 | push bp 3920 | mov bp,sp 3921 | sub sp,8 3922 | mov di,sp 3923 | endif 3924 | push ss 3925 | pop es 3926 | mov ax,000Bh ;get descriptor 3927 | call dpmicall 3928 | jc @F 3929 | if ?32BIT 3930 | and byte ptr es:[edi+5],0F7h ;CODE attribut reset 3931 | or byte ptr es:[edi+5],02h ;write attribut set 3932 | else 3933 | and byte ptr es:[di+5],0F7h ;CODE attribut reset 3934 | or byte ptr es:[di+5],02h ;write attribut set 3935 | endif 3936 | mov bx,[aliassel] 3937 | mov ax,000Ch ;set descriptor 3938 | call dpmicall 3939 | mov dx,bx 3940 | @@: 3941 | if ?32BIT 3942 | lea esp,[esp+8] 3943 | pop edi 3944 | else 3945 | mov sp,bp 3946 | pop bp 3947 | pop di 3948 | endif 3949 | pop bx 3950 | pop ax 3951 | pop es 3952 | exit: 3953 | ret 3954 | setrwsel endp 3955 | 3956 | 3957 | ;--- get length of string DS:(E)SI -> CX 3958 | 3959 | if ?32BIT 3960 | strlen proc public uses esi 3961 | else 3962 | strlen proc public uses si 3963 | endif 3964 | mov cx,0FFFFh 3965 | @@: 3966 | inc cx 3967 | if ?32BIT 3968 | lods byte ptr [esi] 3969 | else 3970 | lodsb 3971 | endif 3972 | and al,al 3973 | jnz @B 3974 | ret 3975 | strlen endp 3976 | 3977 | ;************************************************** 3978 | 3979 | ;--- create a NE header Modul database) 3980 | ;--- 1. alloc a selector 3981 | ;--- 2. alloc memory (NE header, segment table, res. names, full path) 3982 | ;--- 3. copy 64 bytes from NE_Hdr 3983 | ;--- 4. init some fields 3984 | ;--- 5. copy full path from szModName 3985 | ;--- inp: DS=dgroup 3986 | ;--- out: ES=MD 3987 | ;--- modifies es, di, si, bx, cx, dx, ax 3988 | 3989 | AllocMD proc uses bx 3990 | mov di,offset szModName 3991 | push ds 3992 | pop es 3993 | mov cx,0FFFFh 3994 | mov al,00 3995 | repnz scasb 3996 | not cx 3997 | mov bx,offset NE_Hdr 3998 | mov ax,cx ;length file name (incl 00) 3999 | mov dx,[NEHdrOfs] ;offset NE-Header 4000 | add dx,[bx.NEHDR.ne_rsrctab];+offset resource table 4001 | mov cx,word ptr [bx.NEHDR.NRESADR] ;abs address nonres names 4002 | sub cx,dx ;gives length of "resident" tables 4003 | add cx,[bx.NEHDR.NRESLEN] ;+ length of table nonres names 4004 | add cx,offset NEHDR.MDCONST ;+ length MD header 4005 | add cx,ax ;+ length file name 4006 | push ax 4007 | mov ax,[bx.NEHDR.ne_cseg] ;number of segments 4008 | inc ax ;add 1 segment !? 4009 | mov bl,SGTSIZE ;for erweiterte segment table 4010 | mul bl 4011 | add cx,ax ;+ length segment table 4012 | mov [wMDSize],cx ;gives size of module database 4013 | push cx 4014 | mov bx,0001 ;set selector to DATA 4015 | call AllocSel ;alloc selector (in AX) 4016 | pop cx 4017 | jc errorx 4018 | mov dx,SF_DATA ;AX=selector 4019 | .if ((bEnvFlgs & ENVFL_DONTLOADHIGH) && (!wMDSta)) 4020 | or dl, SF_PRELOD 4021 | .endif 4022 | call AllocMem ;alloc memory (+ Base,Limit der Descipt) 4023 | jc error1 ;AX is 0000 or error text 4024 | 4025 | call Set_AX_Present 4026 | jc errorx 4027 | 4028 | pop cx 4029 | mov es,ax ;now set ES to MD 4030 | mov word ptr es:[NEHDR.MEMHDL+0],si 4031 | mov word ptr es:[NEHDR.MEMHDL+2],di 4032 | mov ax,si 4033 | and ax,di 4034 | cmp ax,-1 4035 | jnz @F 4036 | mov word ptr es:[NEHDR.MEMHDL+0],dx 4037 | mov word ptr es:[NEHDR.MEMHDL+2],-1 4038 | @@: 4039 | mov si,offset szModName 4040 | mov di,offset NEHDR.szModPath ;copy module name 4041 | rep movsb 4042 | mov es:[NEHDR.NXTFREE],di ;set next free space 4043 | mov si,offset NE_Hdr ;copy NE header (64 bytes) 4044 | sub di,di 4045 | mov cx,0020h 4046 | rep movsw 4047 | mov es:[NEHDR.ne_count],cx ;clear module count 4048 | and es:[NEHDR.APPFLGS],not AF_INIT 4049 | mov es:[NEHDR.FINFO],NEHDR.szModPath-8 ;to be windows compatible 4050 | clc 4051 | ret 4052 | error1: 4053 | mov ax,offset errstr9 ;error: cannot allocate req. memory 4054 | errorx: ;<--- no selector, DPMI error 4055 | pop cx 4056 | stc 4057 | ret 4058 | AllocMD endp 4059 | 4060 | 4061 | ;*** read segment table 4062 | ;*** on errors: C and AX-> error text 4063 | ;*** the loader can handle a maximum of 255 segments 4064 | 4065 | LoadSegmTable proc 4066 | sub cx,cx 4067 | cmp cx,es:[NEHDR.ne_cseg] 4068 | jz done 4069 | mov bx,es:[NEHDR.ne_hFile] 4070 | mov dx,[NEHdrOfs] 4071 | add dx,es:[NEHDR.ne_segtab] ;offset segment table 4072 | adc cx,cx 4073 | mov ax,4200h ;lseek 4074 | int 21h 4075 | jc error1 4076 | mov ax,es:[NEHDR.ne_cseg] 4077 | cmp ax,?MAXSEG 4078 | jg error2 4079 | shl ax,3 ;8 bytes/segment in file 4080 | mov cx,ax 4081 | mov dx,offset segtable 4082 | mov ah,3Fh ;read table 4083 | int 21h 4084 | jc error1 4085 | done: 4086 | ret 4087 | error1: 4088 | sub ax,ax 4089 | stc 4090 | ret 4091 | error2: 4092 | mov ax,offset errstr11 ;too many segments 4093 | stc 4094 | ret 4095 | LoadSegmTable endp 4096 | 4097 | ;*** segments special (auto data segment) 4098 | ;*** ES:DI -> end of segment table 4099 | 4100 | segspecial proc 4101 | push di 4102 | mov cx,SGTSIZE/2 4103 | xor ax,ax 4104 | rep stosw 4105 | pop di 4106 | mov bx,ax 4107 | mov ax,es:[NEHDR.ne_autodata] ;does DGROUP exist? 4108 | and ax,ax 4109 | jz segspecial1 ;no, then done 4110 | cmp ax,es:[NEHDR.ne_cseg] ;is it an empty segment? 4111 | jna @F 4112 | mov ax,es:[NEHDR.ne_heap] 4113 | or ax,es:[NEHDR.ne_stack] 4114 | jz segspecial1 ;no heap or stack? 4115 | inc word ptr es:[NEHDR.ne_cseg] 4116 | mov si,offset defdgrp 4117 | call PrepSegDesc ;selector alloc ES:DI 4118 | jc segspecialex 4119 | mov bx,di 4120 | jmp segspecial1 4121 | @@: ;dgroup exists and not empty 4122 | mov bl,SGTSIZE 4123 | dec ax 4124 | mul bl 4125 | add ax,es:[NEHDR.ne_segtab] 4126 | xchg bx,ax 4127 | mov ax,es:[bx].SEGITEM.wSel 4128 | lar cx,ax 4129 | test ch,8 ;is dgroup a code segment? 4130 | jz @F ;no, then done 4131 | and word ptr es:[bx.SEGITEM.flags],NOT SF_DISCRD 4132 | mov si,offset defdgrp 4133 | push bx 4134 | push es:[bx.SEGITEM.memsiz] 4135 | call PrepSegDesc ;selector alloc ES:DI 4136 | pop cx 4137 | pop ax 4138 | jc segspecialex 4139 | mov bx,di 4140 | if ?32BIT 4141 | ; or word ptr es:[bx.SEGITEM.flags],SF_ALIAS or SF_PRELOD 4142 | or word ptr es:[bx.SEGITEM.flags],SF_ALIAS 4143 | else 4144 | or word ptr es:[bx.SEGITEM.flags],SF_ALIAS 4145 | endif 4146 | mov word ptr es:[bx].SEGITEM.dwHdl+0,ax 4147 | mov es:[bx.SEGITEM.filesiz],cx 4148 | mov es:[bx.SEGITEM.memsiz],cx 4149 | inc word ptr es:[NEHDR.ne_autodata] 4150 | @@: 4151 | segspecial1: 4152 | mov es:[NEHDR.DGROFS],bx ;^ Dgroup Segment 4153 | clc 4154 | segspecialex: 4155 | ret 4156 | segspecial endp 4157 | 4158 | ;*** prepare 1 segment (alloc selector) 4159 | ;*** ES:DI -> segment descriptor in MD 4160 | ;*** DS:SI -> segment descriptor in NE file to copy from (8 byte size) 4161 | 4162 | PrepSegDesc proc 4163 | xor ax,ax 4164 | mov es:[di].SEGITEM.wDosSel,ax 4165 | dec ax 4166 | mov word ptr es:[di].SEGITEM.dwHdl+0,ax ;handle memory block 4167 | mov word ptr es:[di].SEGITEM.dwHdl+2,ax 4168 | mov bx,[si].SEGITEM.flags 4169 | call AllocSel ;alloc selector in AX 4170 | jc exit ;error? 4171 | push di ;copy first 4 words 1:1 4172 | movsw ;segment file position 4173 | movsw ;segment file size 4174 | movsw ;segment flags 4175 | movsw ;segment memory size 4176 | pop di 4177 | mov es:[di].SEGITEM.wSel,ax ;R/E for code,R/W for data 4178 | and byte ptr es:[di.SEGITEM.flags],not SF_LOADED 4179 | exit: 4180 | ret 4181 | PrepSegDesc endp 4182 | 4183 | ;*** prepare segment table 4184 | ;*** input: ES=MD, DI-> free space in MD 4185 | ;*** the segment table has been read into segtable (8 bytes/segment) 4186 | ;*** now prepare segment table in module header 4187 | 4188 | PrepSegmTable proc 4189 | mov si,offset segtable ;segment table 4190 | mov cx,es:[NEHDR.ne_cseg] 4191 | jcxz done 4192 | next: ;<---- 4193 | push cx 4194 | call PrepSegDesc ;get selector 4195 | pop cx 4196 | jc error 4197 | add di,SGTSIZE 4198 | loop next ;----> 4199 | done: 4200 | call segspecial 4201 | add di,SGTSIZE ; in any case 1 segment extra 4202 | inc word ptr es:[NEHDR.ne_cseg] 4203 | error: 4204 | ret 4205 | PrepSegmTable endp 4206 | 4207 | ;*** read all tables of a NE header in module database 4208 | ;*** on errors: C und AX -> error text 4209 | 4210 | LoadNETables proc 4211 | @trace_s <"load segment table",lf> 4212 | mov di,es:[NEHDR.NXTFREE] 4213 | mov es:[NEHDR.ne_segtab],di 4214 | call PrepSegmTable ;prepare segment table 4215 | jc error1 4216 | 4217 | @trace_s <"load resource table",lf> 4218 | push di 4219 | call LoadResTable ;read resource tabl 4220 | pop es:[NEHDR.ne_rsrctab] ;address resource table 4221 | jc error1 4222 | 4223 | @trace_s <"load resident names table",lf> 4224 | push di 4225 | call LoadResNames ;read resident names 4226 | pop es:[NEHDR.ne_restab] ;address resident names 4227 | jc error1 4228 | 4229 | @trace_s <"load module reference table",lf> 4230 | push di 4231 | call LoadModRefs ;read referenced modules 4232 | pop es:[NEHDR.ne_modtab] ;address module references 4233 | jc error1 4234 | 4235 | @trace_s <"load imported names table",lf> 4236 | push di 4237 | call LoadImpTable ;read imported names 4238 | pop es:[NEHDR.ne_imptab] ;address imported names 4239 | jc error1 4240 | 4241 | @trace_s <"load entry table",lf> 4242 | push di 4243 | call LoadEntryTable ;read entries 4244 | pop es:[NEHDR.ne_enttab] ;address entries 4245 | jc error1 4246 | 4247 | @trace_s <"load nres table",lf> 4248 | push di 4249 | call LoadNResNames ;read nonresident names 4250 | pop es:[NEHDR.NRESNAM] ;address nonresident names 4251 | jc error1 4252 | 4253 | cmp di,[wMDSize] ;is length correct? 4254 | jnz error2 4255 | @trace_s <"tables ok",lf> 4256 | ret 4257 | error2: 4258 | mov ax,offset errstr5 4259 | error1: 4260 | @trace_s <"error exit from modul table load",lf> 4261 | stc 4262 | ret 4263 | LoadNETables endp 4264 | 4265 | ;*** error happened (^error text in AX, if ax==0000 -> DOS error) 4266 | ;*** if AX=-1, dont display anything 4267 | ;--- modifies bx, di, cx, ax 4268 | 4269 | stroutax proc 4270 | and ax,ax 4271 | jz @F 4272 | mov bx,ax 4273 | inc ax 4274 | jnz normerr 4275 | ret 4276 | @@: 4277 | mov bx,ax 4278 | mov ax,5900h ;get extended error info 4279 | int 21h 4280 | mov di,offset szExtErrCod 4281 | call WORDOUT 4282 | mov di,offset szExtErrCls 4283 | mov al,bh 4284 | call BYTEOUT 4285 | mov di,offset szExtErrAct 4286 | mov al,bl 4287 | call BYTEOUT 4288 | mov di,offset szExtErrLoc 4289 | mov al,ch 4290 | call BYTEOUT 4291 | mov bx,offset szExtErr 4292 | normerr: 4293 | @strout_err 4294 | ret 4295 | stroutax endp 4296 | 4297 | ;*** alloc 1 Selector 4298 | ;*** Input: segment flags in BX (bit 0) 4299 | ;*** Output: AX=Selector, C=error 4300 | 4301 | AllocSel proc 4302 | mov cx,0001 4303 | if ?AUTOCSALIAS 4304 | test bl,SF_DATA 4305 | jnz @F 4306 | test es:[NEHDR.APPFLGS],10h 4307 | jz @F 4308 | inc cx 4309 | @@: 4310 | endif 4311 | xor ax,ax 4312 | call dpmicall ;alloc selector 4313 | jc error1 4314 | push ax 4315 | test bl,01 ;DATA=1/CODE=0 4316 | jnz @F 4317 | mov cx,_ACCCODE_ 4318 | call SetAccBits 4319 | jc error2 4320 | pop ax ;selector in AX 4321 | clc 4322 | ret 4323 | @@: 4324 | mov cx,_ACCDATA_ ;this should be set already 4325 | call SetAccBits 4326 | jc error2 4327 | pop ax 4328 | clc 4329 | ret 4330 | error1: 4331 | mov ax,offset szErr33 ;error "out of descriptors" 4332 | stc 4333 | ret 4334 | error2: 4335 | pop ax 4336 | mov ax,offset szErr36 ;error "set acc rights failed" 4337 | stc 4338 | ret 4339 | AllocSel endp 4340 | 4341 | ;*** set CODE/DATA accessrights(in CX) for Selector AX 4342 | ;*** BX = segment flags 4343 | 4344 | SetAccBits proc uses ax bx 4345 | 4346 | test bh,20h ;32-Bit? 4347 | jz @F 4348 | or ch,40h 4349 | @@: 4350 | test bl,80h ;readonly? 4351 | jz @F 4352 | and cl,0FDh 4353 | @@: 4354 | test bh,02h ;conforming? 4355 | jz @F 4356 | or cl,04h 4357 | @@: 4358 | mov bx,ax 4359 | mov ax,cs 4360 | and ax,0003h 4361 | shl ax,05 4362 | or cx,ax 4363 | mov ax,0009h ;set access rights 4364 | call dpmicall 4365 | ret 4366 | SetAccBits endp 4367 | 4368 | ;*** alloc memory 4369 | ;*** for segments + MD 4370 | ;*** Input: CX=bytes (0000=64k) 4371 | ;*** DX=flags 4372 | ;*** AX=selector 4373 | ;*** Output: 4374 | ;*** on errors: C, AX=^error text 4375 | ;*** modifies blksize,blkaddr,SI,DI 4376 | 4377 | AllocMem proc 4378 | push ax 4379 | sub bx,bx 4380 | mov word ptr [blksize+2],bx ;set limit 4381 | dec cx 4382 | mov word ptr [blksize+0],cx 4383 | add cx,1 4384 | adc bx,bx 4385 | mov dh,00 4386 | mov al,dl 4387 | cmp es:[NEHDR.ne_exetyp],ET_OS2 ;ignore DOS alloc for OS/2 4388 | jz @F 4389 | and al,SF_MOVABL or SF_PRELOD 4390 | cmp al,SF_PRELOD ;fixed+preload segment? -> then DOS alloc 4391 | jz AllocDosMem 4392 | @@: 4393 | if _DISCARD_ 4394 | mov dl,2 4395 | tryagain: 4396 | endif 4397 | mov ax,0501h ;alloc memory (BX:CX bytes) 4398 | int 31h 4399 | if _DISCARD_ 4400 | jnc @F 4401 | dec dl 4402 | jz error1 4403 | call discardmem 4404 | jmp tryagain 4405 | @@: 4406 | else 4407 | jc error1 4408 | endif 4409 | @trace_s <"memory allocated, handle="> 4410 | @trace_w si 4411 | @trace_w di 4412 | @trace_s <", base="> 4413 | @trace_w bx 4414 | @trace_w cx 4415 | @trace_s <", limit="> 4416 | @trace_w 4417 | @trace_s lf 4418 | 4419 | mov word ptr [blkaddr+2],bx ;save lineare address 4420 | mov word ptr [blkaddr+0],cx 4421 | pop ax 4422 | call SetBaseLimit ;set base and limit of AX 4423 | jc error2 4424 | if ?32BIT 4425 | lsl ecx,eax 4426 | test ecx,0FFFF0000h 4427 | jz @F 4428 | pusha 4429 | mov bx,word ptr [blkaddr+2] 4430 | mov cx,word ptr [blkaddr+0] 4431 | inc ecx 4432 | push ecx 4433 | pop di 4434 | pop si 4435 | mov ax,0703h 4436 | int 31h 4437 | popa 4438 | @@: 4439 | endif 4440 | mov cx,word ptr [blkaddr+2] ;address in CX:DX 4441 | mov dx,word ptr [blkaddr+0] 4442 | clc 4443 | ret 4444 | error1: 4445 | pop ax 4446 | mov ax,offset szErr31 ;error: ALLOC memory 4447 | stc 4448 | ret 4449 | AllocDosMem: 4450 | shr bx,1 4451 | rcr cx,1 4452 | mov bx,cx ;now in CX number of words 4453 | shr bx,03 ;-> paragraphs 4454 | inc bx 4455 | mov ax,0100h ;alloc DOS memory 4456 | call dpmicall 4457 | jc error3 4458 | ife ?USELOADERPSP 4459 | pusha 4460 | dec ax 4461 | mov cx,ax 4462 | shr cx,12 4463 | mov dx,ax 4464 | shl dx,4 4465 | mov bx, [aliassel] 4466 | mov ax,7 4467 | int 31h 4468 | mov ax, [wRMPSP] 4469 | push ds 4470 | mov ds,bx 4471 | mov ds:[1],ax 4472 | pop ds 4473 | popa 4474 | endif 4475 | push dx 4476 | mov cx,ax 4477 | mov bx,0010h ;segment in AX 4478 | mul bx 4479 | mov word ptr [blkaddr+2],dx ;now address in DX:AX 4480 | mov word ptr [blkaddr+0],ax 4481 | pop dx 4482 | 4483 | pop ax ;selector -> AX 4484 | 4485 | push cx 4486 | push dx 4487 | call SetBaseLimit ;set base and limit of AX 4488 | pop dx 4489 | pop cx 4490 | jc error2 4491 | @trace_s <"DOS memory allocated, handle="> 4492 | @trace_w dx 4493 | @trace_s lf 4494 | mov si,-1 ;Handle = -1 4495 | mov di,si ;return in DX: DOS memory selector 4496 | clc 4497 | ret 4498 | error2: 4499 | @trace_s <"AllocMem, SetBaseLimit() failed",lf> 4500 | ret 4501 | error3: 4502 | pop ax 4503 | xor ax,ax 4504 | stc 4505 | ret 4506 | AllocMem endp 4507 | 4508 | if _DISCARD_ 4509 | 4510 | ;*** in BX:CX number of bytes *** 4511 | 4512 | discardmem proc public 4513 | pusha 4514 | push es 4515 | @trace_s <"memory is scarce, try to discard segments",lf> 4516 | mov ax,[wMDSta] 4517 | discardmem_2: 4518 | and ax,ax 4519 | jz discardmem_ex 4520 | mov es,ax 4521 | mov cx,es:[NEHDR.ne_cseg] 4522 | jcxz discardmem_1 4523 | mov si,es:[NEHDR.ne_segtab] 4524 | discardmem_4: 4525 | mov ax,es:[si.SEGITEM.flags] 4526 | and ax,SF_DISCRD or SF_LOADED 4527 | cmp ax,SF_DISCRD or SF_LOADED ;must be loaded + discardable 4528 | jnz discardmem_3 4529 | mov ax,es:[si].SEGITEM.wSel 4530 | cmp ax,callcs 4531 | jz discardmem_3 ;never delete CS of caller 4532 | 4533 | @trace_s <"discarding segment "> 4534 | @trace_w ax 4535 | @trace_s ",cs=" 4536 | @trace_w cs 4537 | @trace_s ",ds=" 4538 | @trace_w ds 4539 | @trace_s ",es=" 4540 | @trace_w es 4541 | @trace_s ",caller=" 4542 | @trace_w callcs 4543 | @trace_s lf 4544 | 4545 | push cx 4546 | mov cx,0FF7Fh ;present bit reset 4547 | xor dx,dx 4548 | call setaccrights ;selector in AX 4549 | call SetNPBase ;set BX base (not present) to ES:SI 4550 | call freesegmmem ;free segment's memory ES:SI 4551 | pop cx 4552 | discardmem_3: 4553 | add si,SGTSIZE 4554 | loop discardmem_4 4555 | discardmem_1: 4556 | mov ax,es:[NEHDR.NXTMOD] 4557 | jmp discardmem_2 4558 | discardmem_ex: 4559 | pop es 4560 | popa 4561 | ret 4562 | discardmem endp 4563 | 4564 | endif 4565 | 4566 | ;*** free a segment's memory 4567 | ;*** Input: DX=segment flags (not used) 4568 | ;*** AX=DOS memory selector 4569 | ;*** SI:DI=DPMI memory handle (if AX==NULL) 4570 | ;*** Output: C=error 4571 | 4572 | FreeMemory proc 4573 | and ax,ax 4574 | jnz freedosmem 4575 | freeextmem:: ;<-entry free dpmi memory 4576 | mov ax,0502h ;free memory 4577 | call dpmicall 4578 | ret 4579 | freedosmem: 4580 | mov dx,ax 4581 | mov ax,0101h ;free DOS memory 4582 | call dpmicall 4583 | ret 4584 | FreeMemory endp 4585 | 4586 | if ?MULTPSP 4587 | if ?32BIT eq 0 4588 | 4589 | ;*** inp: BX=Segment *** 4590 | ;*** out: BX=Selector *** 4591 | 4592 | AllocRMSegment proc uses cx dx 4593 | xor ax,ax 4594 | mov cx,0001 ;alloc selector 4595 | int 31h 4596 | jc exit 4597 | xchg ax,bx ;segment in bx 4598 | mov dx,ax ;zu addr in cx:dx 4599 | shr ax,12 4600 | mov cx,ax 4601 | shl dx,4 4602 | mov ax,0007 4603 | int 31h ;set base 4604 | jc exit 4605 | mov dx,-1 4606 | xor cx,cx 4607 | mov ax,0008 ;set limit to 64k 4608 | int 31h 4609 | exit: 4610 | ret 4611 | AllocRMSegment endp 4612 | 4613 | endif 4614 | endif 4615 | 4616 | ;*** set base and limit 4617 | ;*** inp: AX= selector 4618 | ;*** inp: ES= MD 4619 | ;*** blkaddr: address 4620 | ;*** blksize: limit 4621 | ;*** out: C=error, then AX=^error text 4622 | 4623 | SetBaseLimit proc uses bx 4624 | 4625 | mov cx,word ptr [blkaddr+2] 4626 | mov dx,word ptr [blkaddr+0] 4627 | mov bx,ax 4628 | mov ax,0007h ;set segment base address 4629 | call dpmicall 4630 | mov ax,offset szErr34 ;error 'set segment base' 4631 | jc error1 4632 | mov cx,word ptr [blksize+2] 4633 | mov dx,word ptr [blksize+0] 4634 | or dl,0Fh ;round up to paragraphs 4635 | test cx,0FFF0h ;> 1MB? 4636 | jz @F 4637 | or dx,0FFFh ;then round up to page 4638 | @@: 4639 | mov ax,0008h ;set segment limit 4640 | call dpmicall 4641 | mov ax,offset szErr35 ;error 'set segment limit' 4642 | jc error2 4643 | if ?AUTOCSALIAS 4644 | lar ax,bx 4645 | test ah,8 4646 | jz @F 4647 | test es:[NEHDR.APPFLGS],10h ;is it RTM app? 4648 | jz @F 4649 | mov ax,bx 4650 | add ax,8 4651 | call SetBaseLimit 4652 | jc error1 4653 | @@: 4654 | endif 4655 | mov ax,bx 4656 | error1: 4657 | error2: 4658 | ret 4659 | SetBaseLimit endp 4660 | 4661 | ;*** set access rights in AX 4662 | ;*** Input: DX=OR-mask, CX=AND-mask 4663 | ;*** RC: in CX previous accrights, C on error 4664 | ;*** out: BX=selector 4665 | ;--- modifies AX, BX, CX 4666 | 4667 | setaccrights proc uses es 4668 | 4669 | if ?32BIT 4670 | push edi 4671 | sub esp,8 4672 | mov edi,esp 4673 | else 4674 | push di 4675 | push bp 4676 | mov bp,sp 4677 | sub sp,8 4678 | mov di,sp 4679 | endif 4680 | push ss 4681 | pop es 4682 | mov bx,ax 4683 | mov ax,000Bh ;get descriptor 4684 | call dpmicall 4685 | mov ax,offset szErr37 ;error: Cannot get Descriptor 4686 | jc error1 4687 | if ?32BIT 4688 | mov ax,word ptr es:[edi+5] 4689 | else 4690 | mov ax,word ptr es:[di+5] 4691 | endif 4692 | and ax,cx 4693 | or ax,dx 4694 | mov cx,ax 4695 | mov ax,0009h ;set access rights 4696 | call dpmicall 4697 | mov ax,offset szErr36 ;error: Cannot set Descriptor 4698 | jc error2 4699 | if ?32BIT 4700 | mov cx,word ptr es:[edi+5] 4701 | else 4702 | mov cx,word ptr es:[di+5] 4703 | endif 4704 | error1: 4705 | error2: 4706 | if ?32BIT 4707 | lea esp,[esp+8] 4708 | pop edi 4709 | else 4710 | mov sp,bp 4711 | pop bp 4712 | pop di 4713 | endif 4714 | ret 4715 | setaccrights endp 4716 | 4717 | ;*** set descriptor to present 4718 | ;*** AX=Selestor 4719 | ;*** RC: C on errors 4720 | 4721 | Set_AX_Present: 4722 | pusha 4723 | mov cx,0FFFFh 4724 | mov dx,0080h ;set PRESENT bit 4725 | call setaccrights 4726 | popa 4727 | ret 4728 | 4729 | setexc0b proc uses bx 4730 | mov bl,0Bh 4731 | mov ax,0202h ;get exception 0B 4732 | call dpmicall 4733 | jc @F 4734 | if ?32BIT 4735 | mov dword ptr oldexc0b+0,edx 4736 | mov word ptr oldexc0b+4,cx 4737 | mov edx, offset Exc0BProc 4738 | else 4739 | mov word ptr oldexc0b+0,dx 4740 | mov word ptr oldexc0b+2,cx 4741 | mov dx, offset Exc0BProc 4742 | endif 4743 | mov cx,cs 4744 | call setexc 4745 | @@: 4746 | ret 4747 | setexc0b endp 4748 | 4749 | ;*** set segment BX base to ES:SI 4750 | ;*** this is initialization for NOT PRESENT segments 4751 | 4752 | SetNPBase proc 4753 | if ?32BIT 4754 | cmp word ptr cs:[oldexc0b+4],0 ;is Exc 0B Handler installed? 4755 | else 4756 | cmp word ptr cs:[oldexc0b+2],0 4757 | endif 4758 | jnz @F 4759 | call setexc0b 4760 | jc error 4761 | @@: 4762 | mov cx,es 4763 | mov dx,si 4764 | mov ax,0007h ;set segment base 4765 | call dpmicall 4766 | jc error 4767 | ret 4768 | error: 4769 | mov ax,offset szErr34 ;error 4770 | stc 4771 | ret 4772 | SetNPBase endp 4773 | 4774 | ;*** called from NP-Exception Handler: set ES (^MD) 4775 | ;*** Input: BX=Selector *** 4776 | ;*** RC: ES:SI *** 4777 | 4778 | GetNPBase proc 4779 | mov ax,0006h ;get segment base -> cx:dx 4780 | call dpmicall 4781 | jc error 4782 | lar ax,cx ;in Base there is ^NE.Segment 4783 | jnz error 4784 | mov es,cx 4785 | cmp es:[NEHDR.ne_magic],'EN' 4786 | jnz error 4787 | mov si,dx 4788 | clc 4789 | ret 4790 | error: 4791 | mov ax,offset int0Berr1 ;invalid not present exception 4792 | stc 4793 | ret 4794 | GetNPBase endp 4795 | 4796 | ;--- open image: may be called from exception 0B handler! 4797 | ;--- inp: ES = NE module handle 4798 | ;--- set C on errors 4799 | ;--- modifies BX,AX 4800 | 4801 | openimage proc 4802 | mov bx,es:[NEHDR.ne_hFile] 4803 | cmp bx,-1 4804 | clc 4805 | jnz exit 4806 | push ds 4807 | push dx 4808 | push es 4809 | pop ds 4810 | mov dx,offset NEHDR.szModPath 4811 | call openfile 4812 | jc @F 4813 | mov bx,ax 4814 | mov es:[NEHDR.ne_hFile],ax 4815 | @@: 4816 | pop dx 4817 | pop ds 4818 | exit: 4819 | ret 4820 | openimage endp 4821 | 4822 | ;--- may be called from exception 0B handler 4823 | 4824 | closefile proc 4825 | cmp word ptr callcs,0 4826 | jz exit 4827 | mov bx,-1 4828 | xchg bx,es:[NEHDR.ne_hFile] 4829 | cmp bx,-1 4830 | jz exit 4831 | mov ah,3Eh ;close file 4832 | int 21h 4833 | exit: 4834 | ret 4835 | closefile endp 4836 | 4837 | ;*** load a segment 4838 | ;*** called by Exc 0B handler and for preload segments 4839 | ;*** inp: ES:SI = ptr SEGITEM 4840 | ;*** AX=CS if EXC 0B, else 0000 4841 | ;*** tasks: 4842 | ;*** - alloc memory 4843 | ;*** - do relocation fixups 4844 | ;*** - set descriptor values 4845 | ;*** out: C=error, then in AX error text or 0000 4846 | ;*** must preserve E/BP! 4847 | 4848 | Load_Segm proc 4849 | mov [callcs],ax 4850 | if ?RMSEGMENTS 4851 | test byte ptr es:[si.SEGITEM.flags],SF_RES1 4852 | jnz ls_1 4853 | endif 4854 | @trace_s <"about to allocate memory for "> 4855 | @trace_w es:[si].SEGITEM.wSel 4856 | @trace_s lf 4857 | call Alloc_Mem_for_Segm ;alloc memory (rc in AX=size) 4858 | jc exit ;+ set descriptor to present 4859 | push ax 4860 | ls_1: 4861 | mov dx,es:[si.SEGITEM.filepos] 4862 | and dx,dx ;if filepos == 0 4863 | jz ls_3 ;then segment isnt external object 4864 | call openimage 4865 | jnc ls_2 4866 | @trace_s <"Load_Segm, open() failed",lf> 4867 | @strout_err "Cannot open file " 4868 | push ds 4869 | push es 4870 | pop ds 4871 | mov bx,offset NEHDR.szModPath 4872 | @stroutbx 4873 | pop ds 4874 | @cr_out 4875 | jmp error2 4876 | ls_2: 4877 | sub ax,ax 4878 | mov cx,es:[NEHDR.SEGSHFT] 4879 | @@: 4880 | shl dx,1 4881 | rcl ax,1 4882 | loop @B 4883 | mov cx,ax 4884 | mov ax,4200h ;lseek 4885 | int 21h 4886 | if _TRACE_ 4887 | jnc @F 4888 | @trace_s <"Load_Segm, lseek() failed",lf> 4889 | jmp error2x 4890 | @@: 4891 | else 4892 | jc error2x ;error (+ adjust stack) 4893 | endif 4894 | mov cx,es:[si].SEGITEM.filesiz 4895 | call setrwsel ;get alias in DX 4896 | if ?RMSEGMENTS 4897 | test byte ptr es:[si.SEGITEM.flags],SF_RES1 4898 | jz @F 4899 | mov dx,es:[si].SEGITEM.wDosSel ;selector 4900 | @@: 4901 | endif 4902 | @trace_s <"about to read file",lf> 4903 | push ds 4904 | mov ds,dx 4905 | sub dx,dx 4906 | ife ?32BIT 4907 | test byte ptr es:[si.SEGITEM.flags],SF_ITERED 4908 | jz @F 4909 | call Read_Iterated_Segm 4910 | jmp readdone 4911 | @@: 4912 | endif 4913 | and cx,cx ;is it 64 kB? 4914 | jnz @F 4915 | mov cx,08000h 4916 | mov ah,3Fh 4917 | int 21h ;then do it in 2 reads 4918 | mov dx,8000h 4919 | mov cx,dx 4920 | @@: 4921 | mov ah,3Fh ;read segment (CX bytes) 4922 | int 21h 4923 | readdone: 4924 | pop ds 4925 | if _TRACE_ 4926 | jnc @F 4927 | @trace_s <"Load_Segm, read() failed",lf> 4928 | jmp error2x 4929 | @@: 4930 | else 4931 | jc error2x ;error (mit stackkorrektur) 4932 | endif 4933 | @trace_s <"done file read",lf> 4934 | ls_3: 4935 | pop ax ;size -> AX 4936 | @trace_s <"about to zeroinit rest of segment",lf> 4937 | call ClearSegmentTail ;clear rest with 00 4938 | test word ptr es:[si.SEGITEM.flags],SF_RELOCS ;relocations exist? 4939 | jz ls_4 4940 | @trace_s <"about to handle relocations",lf> 4941 | push si 4942 | call DoRelocs ;do relocations fixups 4943 | pop si 4944 | jc error1 4945 | @trace_s <"relocations done",lf> 4946 | ls_4: 4947 | call closefile 4948 | jc error3 4949 | if ?INT41SUPPORT 4950 | push si 4951 | push di 4952 | mov ax,si 4953 | sub ax,es:[NEHDR.ne_segtab] 4954 | mov bl,SGTSIZE 4955 | div bl 4956 | inc ax 4957 | mov bx,ax ;segment no 4958 | mov cx,es:[si].SEGITEM.wSel ;selector 4959 | mov si,es:[si.SEGITEM.flags] ;segmentflags 4960 | mov di,es:[NEHDR.ne_restab] ;es:di -> module name 4961 | inc di 4962 | mov ax,DS_LoadSeg 4963 | int 41h 4964 | pop di 4965 | pop si 4966 | endif 4967 | clc 4968 | exit: 4969 | ret 4970 | error2x: 4971 | call closefile 4972 | error2: 4973 | pop dx ;clear stack (selector) 4974 | error3: 4975 | sub ax,ax 4976 | stc 4977 | ret 4978 | error1: 4979 | push ax 4980 | @trace_s <"error during relocation",lf> 4981 | call closefile 4982 | pop ax 4983 | stc 4984 | ret 4985 | Load_Segm endp 4986 | 4987 | ife ?32BIT 4988 | 4989 | ;--- inp: DS=segment to iterate 4990 | ;--- CX=file size of segment 4991 | ;--- BX=file handle 4992 | ;--- out: DX=next free byte in segment 4993 | 4994 | Read_Iterated_Segm proc uses es di si bp 4995 | push ds 4996 | pop es 4997 | mov di,cx 4998 | nextitem: 4999 | mov cx,4 5000 | sub sp,cx 5001 | mov si,dx 5002 | mov dx,sp ;this is 16-bit only 5003 | push ss 5004 | pop ds 5005 | mov ah,3Fh 5006 | int 21h 5007 | pop bp ;number of iterations 5008 | pop cx ;size in bytes 5009 | jc error 5010 | push es 5011 | pop ds 5012 | mov dx,si 5013 | mov ah,3Fh 5014 | int 21h 5015 | jc error 5016 | sub di,ax 5017 | jc error 5018 | sub di,4 5019 | jc error 5020 | @@: 5021 | add dx,ax 5022 | dec bp 5023 | jz @F 5024 | mov cx,ax 5025 | push di 5026 | mov di,si 5027 | add di,cx 5028 | rep movsb 5029 | pop di 5030 | jmp @B 5031 | @@: 5032 | and di,di 5033 | jnz nextitem 5034 | error: 5035 | ret 5036 | 5037 | Read_Iterated_Segm endp 5038 | 5039 | endif 5040 | 5041 | ;*** do SF_ALIAS segments 5042 | ;*** input: dx=flags, (e)cx=req size 5043 | ;*** out: NC + selector in ax 5044 | ;--- C + AX= error text or NULL 5045 | ;--- currently most likely doesnt work for dos memory segments (PRELOAD+FIXED) 5046 | 5047 | ReallocMem proc 5048 | @int3 _INT03REALLOC_ 5049 | mov bx,word ptr es:[si].SEGITEM.dwHdl+0 ;here ^segmentdescriptor of alias 5050 | push si 5051 | push ax 5052 | push es 5053 | mov es,es:[bx].SEGITEM.wSel ;load alias segment 5054 | pop es 5055 | mov di,word ptr es:[bx].SEGITEM.dwHdl+0 5056 | mov si,word ptr es:[bx].SEGITEM.dwHdl+2 5057 | mov ax,word ptr es:[bx].SEGITEM.wDosSel 5058 | if ?32BIT 5059 | push ecx 5060 | dec ecx 5061 | mov [blksize],ecx ;set limit 5062 | pop cx 5063 | pop bx 5064 | else 5065 | xor bx,bx 5066 | dec cx 5067 | mov word ptr [blksize+0],cx 5068 | mov word ptr [blksize+2],bx 5069 | inc cx 5070 | endif 5071 | and ax,ax ;is DOS memory used? 5072 | jz isdpmimem 5073 | mov dx,ax 5074 | test bx,0FFF0h ;is limited to 1 MB 5075 | jnz ReallocMem_err 5076 | shr cx,4 5077 | shl bx,12 5078 | or bx,cx 5079 | mov ax,0102h ;the address cannot change 5080 | int 31h ;server will do the selector tiling 5081 | jc ReallocMem_err 5082 | mov ax,dx 5083 | jmp reallocmem_exx 5084 | isdpmimem: 5085 | @trace_s <"realloc alias, handle="> 5086 | @trace_w si 5087 | @trace_w di 5088 | @trace_s <", size="> 5089 | @trace_w bx 5090 | @trace_w cx 5091 | @trace_s 5092 | mov ax,0503h ;realloc memory 5093 | call dpmicall 5094 | jc ReallocMem_err 5095 | reallocmem_1: 5096 | mov dx,si 5097 | pop ax 5098 | pop si 5099 | push si 5100 | push ax 5101 | mov word ptr [blkaddr+2],bx 5102 | mov word ptr [blkaddr+0],cx 5103 | mov si,word ptr es:[si].SEGITEM.dwHdl+0 5104 | mov word ptr es:[si].SEGITEM.dwHdl+0,di 5105 | mov word ptr es:[si].SEGITEM.dwHdl+2,dx 5106 | call SetBaseLimit 5107 | jc ReallocMem_err1 5108 | mov ax,es:[si].SEGITEM.wSel 5109 | call SetBaseLimit 5110 | jc ReallocMem_err1 5111 | reallocmem_exx: 5112 | pop ax 5113 | pop si 5114 | ReallocMem_ex: 5115 | ret 5116 | ReallocMem_err: 5117 | mov ax,offset szErr311 5118 | ReallocMem_err1: 5119 | pop cx 5120 | pop si 5121 | ret 5122 | ReallocMem endp 5123 | 5124 | ;*** ES:SI -> ext. segment table 5125 | ;*** alloc memory for segment and set descriptor values 5126 | ;*** will be called by NP-exception handler as well 5127 | ;*** RC: if NC size in AX 5128 | ;--- on error C and AX=error string or NULL 5129 | 5130 | Alloc_Mem_for_Segm proc 5131 | mov dx,es:[si.SEGITEM.flags] ;flags 5132 | mov cx,es:[si.SEGITEM.memsiz] ;size 5133 | mov ax,es:[si].SEGITEM.wSel 5134 | cmp si,es:[NEHDR.DGROFS] ;Dgroup-Segment? 5135 | jnz @F 5136 | if ?32BIT 5137 | movzx ecx,cx 5138 | movzx ebx,word ptr es:[NEHDR.ne_stack] 5139 | shl ebx,12 ;32bit: pages instead of bytes 5140 | add ecx,ebx 5141 | movzx ebx,word ptr es:[NEHDR.ne_heap] 5142 | shl ebx,12 ;32bit: pages instead of bytes 5143 | add ecx,ebx 5144 | else 5145 | add cx,es:[NEHDR.ne_stack] ;Stack Extra 5146 | add cx,es:[NEHDR.ne_heap] ;Heap Extra 5147 | if 1 5148 | cmp es:[NEHDR.ne_exetyp],ET_OS2 5149 | jnz @F 5150 | xor cx,cx ;alloc 64 kB 5151 | endif 5152 | endif 5153 | @@: 5154 | push cx 5155 | push di 5156 | test dx,SF_ALIAS 5157 | jz amfs_1 5158 | @trace_s <"Alloc_Mem_for_Segm: segment alias",lf> 5159 | call ReallocMem 5160 | jc error1 ;is AX set? 5161 | call Set_AX_Present 5162 | pop di ;dont set "loaded"-flag here 5163 | pop ax ;return: size memory 5164 | ret 5165 | amfs_1: 5166 | push si 5167 | push es 5168 | call AllocMem ;memory alloc (AX=Selector, DX=Flags) 5169 | mov bx,si 5170 | pop es 5171 | pop si ;get ^segment 5172 | jc error1 ;on errors AX is 0000 or error text 5173 | if ?RMSEGMENTS 5174 | test byte ptr es:[si.SEGITEM.flags],SF_RES1 5175 | jz @F 5176 | mov es:[si+XDOSSEG],cx ;CX=Segment 5177 | mov es:[si].SEGITEM.wDosSel,dx ;DX=Selector 5178 | jmp done 5179 | @@: 5180 | endif 5181 | mov word ptr es:[si].SEGITEM.dwHdl+2,bx 5182 | mov word ptr es:[si].SEGITEM.dwHdl+0,di 5183 | and bx,di 5184 | cmp bx,0FFFFh 5185 | jnz done 5186 | mov es:[si].SEGITEM.wDosSel,dx ;DOS memory used 5187 | done: 5188 | call Set_AX_Present 5189 | or byte ptr es:[si.SEGITEM.flags],SF_LOADED 5190 | @trace_s <"alloc_mem_for_segm normal exit",lf> 5191 | pop di 5192 | pop ax ;return: size memory 5193 | ret 5194 | error1: ;memory error 5195 | @trace_s <"alloc_mem_for_segm failed",lf> 5196 | pop di 5197 | pop cx ;preserve ax here (error text) 5198 | ret 5199 | Alloc_Mem_for_Segm endp 5200 | 5201 | 5202 | ;*** get position in file 5203 | 5204 | if 0 5205 | 5206 | GetSegmentPos proc 5207 | sub ax,ax 5208 | mov cx,es:[NEHDR.SEGSHFT] 5209 | @@: 5210 | shl dx,1 5211 | rcl ax,1 5212 | loop @B 5213 | mov cx,ax 5214 | ret 5215 | GetSegmentPos endp 5216 | 5217 | endif 5218 | 5219 | ;*** clear rest of a segment 5220 | ;*** if memsize > filesize 5221 | ;*** Input: ES:SI-> segment, AX = size of memory block (0=64 kB) 5222 | ;*** BX,ES,SI must be kept 5223 | 5224 | ClearSegmentTail proc 5225 | push es 5226 | push di 5227 | mov di,es:[si.SEGITEM.filesiz] 5228 | test byte ptr es:[si.SEGITEM.flags],SF_ITERED 5229 | jz @F 5230 | mov di,dx 5231 | @@: 5232 | mov cx,ax 5233 | jcxz @F 5234 | cmp cx,di 5235 | jbe exit 5236 | @@: 5237 | sub cx,di 5238 | call setrwsel ;get ALIAS in DX 5239 | mov es,dx 5240 | sub ax,ax 5241 | shr cx,1 5242 | rep stosw 5243 | adc cl,al 5244 | rep stosb 5245 | exit: 5246 | pop di 5247 | pop es 5248 | ret 5249 | ClearSegmentTail endp 5250 | 5251 | ;--- DS->loader data segment 5252 | ;*** load PRELOAD- and HUGE- segments 5253 | ;--- modifies cx, si, bx 5254 | ;--- current psp is still the loader's (important for DOS memory alloc) 5255 | 5256 | DoPreloads proc 5257 | @trace_s <"will load preload & huge segments",lf> 5258 | mov cx,es:[NEHDR.ne_cseg] ;no segments 5259 | jcxz done 5260 | mov si,es:[NEHDR.ne_segtab] 5261 | nextitem: ;<---- 5262 | push cx 5263 | cmp word ptr es:[si].SEGITEM.wSel,0 ;dummy entry? 5264 | jz doneitem 5265 | if ?RMSEGMENTS 5266 | test byte ptr es:[si.SEGITEM.flags],SF_RES1 5267 | jz @F 5268 | test byte ptr es:[si.SEGITEM.flags],SF_DATA 5269 | jnz loadit ;DATA always Preload 5270 | mov bx,es:[si+DOSSEL] 5271 | jmp dontloadit2 5272 | @@: 5273 | endif 5274 | cmp word ptr es:[si.SEGITEM.memsiz],0 ;64k Segment? 5275 | jnz @F 5276 | or byte ptr es:[si.SEGITEM.flags],SF_PRELOD 5277 | and byte ptr es:[si.SEGITEM.flags+1],-10h;change NONDISCARDABLE 5278 | cmp cx,2 ;and a possibly succ segment 5279 | jb @F 5280 | or byte ptr es:[si.SEGITEM.flags+SGTSIZE],SF_PRELOD ;as well 5281 | and byte ptr es:[si.SEGITEM.flags+SGTSIZE+1],-10h 5282 | @@: 5283 | test byte ptr es:[si.SEGITEM.flags],SF_PRELOD 5284 | jz dontloadit 5285 | loadit: 5286 | xor ax,ax 5287 | call Load_Segm ;load segment 5288 | jc error1 5289 | jmp doneitem 5290 | dontloadit: 5291 | mov bx,es:[si].SEGITEM.wSel 5292 | dontloadit2: 5293 | call SetNPBase ;set base (Not Present) 5294 | jc errorx 5295 | doneitem: 5296 | add si,SGTSIZE 5297 | pop cx 5298 | loop nextitem ;---> 5299 | @trace_s <"exit load preload & huge segments",lf> 5300 | done: 5301 | clc 5302 | ret 5303 | error1: 5304 | call stroutax ;display AX if it contains text 5305 | mov ax,offset errstr7 ;"error while loading segments" 5306 | errorx: 5307 | pop bx ;adjust stack 5308 | stc 5309 | ret 5310 | DoPreloads endp 5311 | 5312 | ;*** for 1 Module: 5313 | ;*** free all selectors and memory 5314 | ;*** ES=MD 5315 | ;*** will change ES to 0000 5316 | 5317 | CleanUpNE proc 5318 | mov cx,es:[NEHDR.ne_cseg] 5319 | jcxz done 5320 | mov si,es:[NEHDR.ne_segtab] 5321 | nextitem: 5322 | push cx 5323 | mov bx,es:[si].SEGITEM.wSel 5324 | and bx,bx 5325 | jz nextseg 5326 | mov ax,cs 5327 | cmp ax,bx ;not for module KERNEL! 5328 | jz nextseg 5329 | @trace_s <"freeing selector "> 5330 | @trace_w bx 5331 | @trace_s lf 5332 | if ?32BIT ;make sure fs and gs dont get in the way 5333 | mov ax,fs 5334 | cmp ax,bx 5335 | jnz @F 5336 | push 0 5337 | pop fs 5338 | @@: 5339 | mov ax,gs 5340 | cmp ax,bx 5341 | jnz @F 5342 | push 0 5343 | pop gs 5344 | @@: 5345 | endif 5346 | mov ax,0001 ;free selector 5347 | call dpmicall 5348 | jc nextseg 5349 | if ?AUTOCSALIAS 5350 | test es:[NEHDR.APPFLGS],10h 5351 | jz @F 5352 | test byte ptr es:[si].SEGITEM.flags, SF_DATA 5353 | jnz @F 5354 | add bx,8 5355 | mov ax,0001 ;free alias selector 5356 | call dpmicall 5357 | @@: 5358 | endif 5359 | call freesegmmem 5360 | nextseg: 5361 | pop cx 5362 | add si,SGTSIZE 5363 | loop nextitem 5364 | done: 5365 | @trace_s <"freeing MD selector "> 5366 | @trace_w es 5367 | @trace_s <", module "> 5368 | @tracemodule 5369 | @trace_s lf 5370 | mov si,word ptr es:[NEHDR.MEMHDL+0] ;now do MD itself 5371 | mov di,word ptr es:[NEHDR.MEMHDL+2] 5372 | mov bx,es 5373 | push 0 5374 | pop es ;clear es before dpmi call 5375 | mov ax,0001 5376 | call dpmicall 5377 | cmp di,-1 5378 | jnz @F 5379 | @trace_s <"freeing memory of MD, Handle="> 5380 | @trace_w si 5381 | @trace_s lf 5382 | mov dx, si 5383 | mov ax,0101h 5384 | call dpmicall 5385 | jmp done2 5386 | @@: 5387 | ife ?MEMFORKERNEL 5388 | cmp [wMDSta],0 5389 | jz done2 5390 | endif 5391 | @trace_s <"freeing memory of MD, Handle="> 5392 | @trace_w si 5393 | @trace_w di 5394 | @trace_s lf 5395 | call freeextmem ;free memory 5396 | done2: 5397 | @trace_s <"exit proc free_modul",lf> 5398 | ret 5399 | CleanUpNE endp 5400 | 5401 | ;*** free memory of a loaded segment 5402 | ;*** input: ES:SI -> segment 5403 | ;*** out: carry is error, then errortext in AX 5404 | 5405 | ;*** its possibly an error to free dos memory segments here 5406 | ;*** because this memory will already have been freed by 5407 | ;*** dos kill (int21, ah=0) call 5408 | 5409 | freesegmmem proc near uses di 5410 | mov dx,es:[si].SEGITEM.flags 5411 | test dl,SF_LOADED 5412 | jz exit 5413 | and dl,not SF_LOADED 5414 | mov es:[si].SEGITEM.flags,dx 5415 | xor ax,ax 5416 | or di,-1 5417 | mov cx,di 5418 | xchg ax,es:[si].SEGITEM.wDosSel ;DOS memory block sel 5419 | xchg cx,word ptr es:[si].SEGITEM.dwHdl+2 5420 | xchg di,word ptr es:[si].SEGITEM.dwHdl+0 ;DPMI handle 5421 | @trace_s <"freeing memory of segm="> 5422 | @trace_w es 5423 | @trace_s <":"> 5424 | @trace_w si 5425 | @trace_s <", handle "> 5426 | @trace_w cx 5427 | @trace_w di 5428 | @trace_s <", dos sel="> 5429 | @trace_w ax 5430 | @trace_s lf 5431 | push si 5432 | mov si,cx 5433 | call FreeMemory ;free memory (Handle in AX or SI:DI) 5434 | pop si 5435 | jnc exit 5436 | push offset szErr32 ;error: deallocate memory 5437 | call stroutstk_err 5438 | call displaymodandseg 5439 | stc 5440 | exit: 5441 | ret 5442 | freesegmmem endp 5443 | 5444 | ;*** input AX (Segment#), ES -> MD 5445 | ;*** Output AX (Selector) 5446 | 5447 | SegNo2Sel proc uses bx 5448 | dec ax 5449 | mov bl,SGTSIZE 5450 | mul bl 5451 | mov bx,ax 5452 | add bx,es:[NEHDR.ne_segtab] 5453 | mov ax,es:[bx].SEGITEM.wSel ;normal selector (R/E for Code, 5454 | if ?RMSEGMENTS ; R/W for Data) 5455 | test byte ptr es:[bx.SEGITEM.flags],SF_RES1 ;DOS-Block? 5456 | jz exit 5457 | test byte ptr es:[bx.SEGITEM.flags],SF_DATA ;CODE? 5458 | jnz @F 5459 | mov ax,es:[bx+DOSSEL] ;Code selector 5460 | jmp exit 5461 | @@: 5462 | mov ax,es:[bx+XDOSSEG] 5463 | endif 5464 | exit: 5465 | ret 5466 | SegNo2Sel endp 5467 | 5468 | ;*** Input: Seg# in AX *** 5469 | ;*** Output: size of memory for segment in AX 5470 | 5471 | if 0 5472 | 5473 | GetSegmSize proc uses bx 5474 | dec ax 5475 | mov bl,SGTSIZE 5476 | mul bl 5477 | mov bx,ax 5478 | add bx,es:[NEHDR.ne_segtab] 5479 | mov ax,es:[bx.SEGITEM.memsiz] 5480 | ret 5481 | GetSegmSize endp 5482 | 5483 | endif 5484 | 5485 | ;*** handle relocations for 1 segment 5486 | ;*** Input: ES:SI=segment, BX=file handle 5487 | ;*** Output: C=error, AX -> error text 5488 | 5489 | DoRelocs proc 5490 | mov [wlError],0 5491 | mov cx,sizeof wCnReloc 5492 | mov dx,offset wCnReloc ;read 2 Bytes (# of relocs) 5493 | mov ah,3Fh ;this can be done without lseek 5494 | int 21h ;since segment was read just before 5495 | jc error3 5496 | mov cx,wCnReloc 5497 | jcxz error2 ;this may not be null 5498 | call setrwsel ;get alias in DX (in: ES:SI=segment) 5499 | mov ax,offset relbuf 5500 | add ax,RELSIZE 5501 | mov [wRelTmp],ax ;set buffer to overflow, thus causing 5502 | next: 5503 | push cx ;relocs to be read 5504 | call ReadReloc ;set DI to relocation 5505 | jc error3a ;and possibly fill buffer 5506 | call HandleReloc ;do 1 relocation 5507 | pop cx 5508 | jc error1 ;on errors: ax-> error text 5509 | loop next 5510 | clc 5511 | error1: 5512 | ret 5513 | error2: 5514 | mov ax,offset errstr14 ;Error: reloc. code has zero rel.. 5515 | stc 5516 | ret 5517 | error3a: 5518 | pop cx ;error on file access (read) 5519 | error3: 5520 | mov ax,offset errstr6 5521 | stc 5522 | ret 5523 | DoRelocs endp 5524 | 5525 | ;*** for 1 relocation set DI 5526 | ;*** if needed, refill buffer 5527 | ;*** input: CX=number of references to fix 5528 | ;--- ES=module 5529 | 5530 | ReadReloc proc 5531 | mov di,[wRelTmp] 5532 | add di,+08 5533 | mov dx,offset relbuf 5534 | add dx,RELSIZE 5535 | cmp di,dx 5536 | jl rr_1 5537 | mov bx,es:[NEHDR.ne_hFile] ;fill buffer 5538 | cmp cx,RELSIZE/8 ;can buffer hold the rest of entries 5539 | jb @F 5540 | mov cx,RELSIZE/8 5541 | @@: 5542 | shl cx,3 ;each entry requirest 8 bytes 5543 | mov dx,offset relbuf 5544 | mov ah,3Fh 5545 | int 21h ;read relocations 5546 | jc exit 5547 | mov di,offset relbuf 5548 | rr_1: 5549 | mov [wRelTmp],di 5550 | clc 5551 | exit: 5552 | ret 5553 | 5554 | ReadReloc endp 5555 | 5556 | getcssel: 5557 | mov ax,[aliassel] 5558 | @@: 5559 | if ?RMSEGMENTS 5560 | test byte ptr es:[si.SEGITEM.flags],SF_RES1 5561 | jz @F 5562 | mov ax,es:[si].SEGITEM.wDosSel 5563 | @@: 5564 | endif 5565 | ret 5566 | 5567 | 5568 | ;------------------------------ ;Typ 03 (OSFIXUP) 5569 | 5570 | ;*** resolve OSFIXUPs 5571 | 5572 | hr_03: 5573 | mov bx,[di+04] 5574 | if _WIN87EMWAIT_ 5575 | cmp bx,6 5576 | jz @F 5577 | endif 5578 | ; test [eWinFlags.wOfs],0400h ;does FPU exist? 5579 | test byte ptr [wEquip],2 ;does FPU exist? 5580 | jz @F 5581 | clc 5582 | ret 5583 | @@: 5584 | dec bx 5585 | shl bx,2 5586 | add bx,offset fpOSFixups 5587 | mov dx,[bx+2] 5588 | mov cx,[bx+0] 5589 | call getcssel ;cs-alias -> AX 5590 | mov bx,[di+02] ;start offset -> BX 5591 | push ds 5592 | mov ds,ax 5593 | add [bx],cx 5594 | add [bx+1],dx 5595 | pop ds 5596 | clc 5597 | ret 5598 | 5599 | ;--- DS:DI -> 1 relocation 5600 | ;--- ES:SI -> segment 5601 | 5602 | ;*** BYTE DI+0: rel address type 5603 | ;*** BYTE DI+1: relocation type 5604 | ;*** WORD DI+2: offset in segment 5605 | ;*** WORD DI+4: module no of import 5606 | ;*** WORD DI+6: entry no of import 5607 | 5608 | ;*** relocation address type 5609 | ;*** 0:byte | will result in: 5610 | ;*** 2:16 Bit selector | bit 3 (08): 1=offset is 32 Bit 5611 | ;*** 3:32 Bit pointer | bit 2 (04): 1=no selector exists 5612 | ;*** 5:16 Bit offset | bit 1 (02): 1=selector exists 5613 | ;*** 11:48 Bit pointer | bit 0 (01): 1=offset vorhanden 5614 | ;*** 13:32 Bit offset | 5615 | 5616 | ;*** Output: C on errors, in AX then error text 5617 | 5618 | HandleReloc proc 5619 | mov cl,[di+01] ;relocation type 5620 | and cl,03 5621 | cmp cl,00 ;00 (internal reference) 5622 | jz hr_00 5623 | cmp cl,01 ;01 (imported ordinal) 5624 | jz hr_01 5625 | cmp cl,02 ;02 (imported name) 5626 | jz hr_02 5627 | cmp cl,03 ;03 (OSFIXUP) 5628 | jz hr_03 5629 | mov ax,offset errstr13 ;cannot happen 5630 | stc 5631 | ret 5632 | 5633 | ;------------------------------ ;Typ 00 (internal reference) 5634 | hr_00: mov ax,[di+04h] 5635 | cmp ax,00FFh ;moveable??? 5636 | jnz hr_00_1 ;can be selector or Selector:Offset 5637 | mov ax,[di+06h] ;logical segment no 5638 | call GetProcAddr16 ;selector:offset of entry -> AX:BX 5639 | mov dx,ax 5640 | mov cx,bx 5641 | jmp hr_continue 5642 | hr_00_1: 5643 | call SegNo2Sel ;get selector 5644 | mov dx,ax 5645 | mov cx,[di+06h] 5646 | jmp hr_continue 5647 | 5648 | ;------------------------------ ;Typ 01 (reference to entry ordinal) 5649 | hr_01: push es 5650 | push si ;reference "by value" 5651 | mov si,[di+04] 5652 | dec si 5653 | shl si,1 5654 | add si,es:[NEHDR.ne_modtab] 5655 | mov es,es:[si] 5656 | mov ax,[di+06] 5657 | call GetProcAddr16 ;selector:offset of entry -> AX:BX 5658 | if _UNDEFDYNLINK_ 5659 | jnc @F 5660 | mov ax,cs 5661 | mov bx,offset UndefDynLink 5662 | @@: 5663 | else 5664 | jc hr_01_1 5665 | endif 5666 | mov dx,ax 5667 | mov cx,bx 5668 | pop si 5669 | pop es 5670 | jmp hr_continue 5671 | hr_01_1: 5672 | pusha 5673 | mov ax,[di+6] 5674 | mov di,offset LENTERR 5675 | call WORDOUT 5676 | popa 5677 | mov bx,offset errstr24 ;error "entry not found" 5678 | 5679 | notfounderror: ;<--- imported name not found 5680 | @strout_err 5681 | call modnameout 5682 | @cr_out 5683 | pop si 5684 | pop es 5685 | ifdef ?CONTONIMPERR 5686 | mov dx,cs 5687 | mov cx,offset UndefDynLink 5688 | jmp hr_continue 5689 | endif 5690 | xor ax,ax 5691 | stc 5692 | ret 5693 | 5694 | ;------------------------------ Typ 02 (reference to entry in external module) 5695 | hr_02: 5696 | @int3 _INT03NAMEIMP_ 5697 | push es 5698 | push si ;reference "by name" 5699 | push di 5700 | push ds 5701 | mov si,es:[NEHDR.ne_imptab];DS:SI must point to name to import 5702 | add si,[di+06] ;this is the offset into name table 5703 | mov di,[di+04] ;this is the module which exports this func 5704 | dec di 5705 | add di,di 5706 | add di,es:[NEHDR.ne_modtab] 5707 | push es 5708 | mov es,es:[di] 5709 | pop ds ;MD -> DS 5710 | mov cl,[si] ;length of imported name -> CL 5711 | inc si 5712 | if ?32BIT 5713 | movzx esi,si 5714 | endif 5715 | call SearchNEExport ;search in resident+nonresident names 5716 | if _UNDEFDYNLINK_ 5717 | jnc @F 5718 | mov ax,cs 5719 | mov bx,offset UndefDynLink 5720 | @@: 5721 | else 5722 | jc hr_02_1 5723 | endif 5724 | mov dx,ax ;selector -> DX, Offset -> CX 5725 | mov cx,bx 5726 | pop ds 5727 | pop di 5728 | pop si 5729 | pop es 5730 | jmp hr_continue 5731 | hr_02_1: ;error 5732 | mov bx,si 5733 | mov cl,[si-1] 5734 | call stroutBXn 5735 | pop ds 5736 | pop di 5737 | ;imported name not found 5738 | mov bx,offset errstr25 5739 | jmp notfounderror 5740 | ;the entry was found 5741 | ;now patch (CX:DX) 5742 | ;si -> segment descriptor 5743 | ;C is set on errors 5744 | hr_continue: 5745 | call getcssel ;csalias -> AX 5746 | push bp 5747 | push di 5748 | push ds 5749 | push ax 5750 | mov ax,[di+0] ;flags 5751 | mov bx,[di+2] ;start offset -> BX 5752 | pop ds 5753 | call PatchSegment 5754 | pop ds 5755 | pop di 5756 | pop bp 5757 | ret 5758 | HandleReloc endp 5759 | 5760 | 5761 | ;--- DS = segment to patch 5762 | ;--- ES = module, ES:SI -> segment 5763 | 5764 | PatchSegment proc 5765 | mov di,2 ;length offset part 5766 | test al,08 ;offset 32 Bit? 5767 | jz @F 5768 | mov di,4 ;then length offset is 4 5769 | @@: 5770 | and al,03 5771 | test ah,04 ;1 time/several times? 5772 | jz isList 5773 | cmp al,02 ;is selector here (32 Bit pointer)? 5774 | ja ps_fptr 5775 | jnz @F 5776 | add [bx],dx ;2=just selector 5777 | clc 5778 | ret 5779 | @@: 5780 | dec al 5781 | jnz @F 5782 | add [bx],cx ;0/1=word offset 5783 | clc 5784 | ret 5785 | @@: 5786 | add [bx],cl ;0=Byte 5787 | clc 5788 | ret 5789 | ps_fptr: 5790 | add [bx+di],dx ;3=selector/offset 5791 | add [bx],cx 5792 | clc 5793 | ret 5794 | 5795 | ;--- it's a non-additive relocation. 5796 | ;--- such relocs are a linked list terminated by -1 5797 | 5798 | isList: 5799 | if _CHECKSEGSIZE_ 5800 | mov bp,ds 5801 | lsl bp,bp 5802 | endif 5803 | cmp al,02 ;far pointer? 5804 | ja isfar 5805 | jz @F 5806 | mov dx,cx 5807 | @@: 5808 | nextitem: 5809 | 5810 | if _CHECKSEGSIZE_ 5811 | cmp bp,bx 5812 | jbe error1 5813 | endif 5814 | mov ax,[bx] 5815 | mov [bx],dx 5816 | mov bx,ax 5817 | inc ax ;-1 marks end of list 5818 | jnz nextitem 5819 | ret 5820 | 5821 | isfar: ;might be far16 or far32 5822 | 5823 | nextitem2: 5824 | 5825 | if _CHECKSEGSIZE_ 5826 | cmp bp,bx 5827 | jbe error1 5828 | endif 5829 | mov ax,[bx] 5830 | mov [bx+di],dx 5831 | mov [bx],cx 5832 | mov bx,ax 5833 | inc ax ;-1 marks end of list 5834 | jnz nextitem2 5835 | ret 5836 | error1: 5837 | mov ax,offset szErr22 5838 | stc 5839 | ret 5840 | PatchSegment endp 5841 | 5842 | ;*** read a table into MD 5843 | ;*** AX=offset in file 5844 | ;*** ES:DI=address in MD 5845 | ;*** CX=size of table to read 5846 | 5847 | ReadMD proc 5848 | if _TRACE_ 5849 | @trace_w cx 5850 | @trace_s <" bytes to read from md-header",lf> 5851 | endif 5852 | push cx 5853 | mov bx,es:[NEHDR.ne_hFile] 5854 | sub cx,cx 5855 | mov dx,[NEHdrOfs] 5856 | add dx,ax 5857 | adc cx,cx 5858 | mov ax,4200h ;lseek 5859 | int 21h 5860 | pop cx ;laenge restore 5861 | jc readmd_er1 5862 | ; mov bx,es:[NEHDR.ne_hFile] 5863 | mov dx,di 5864 | push ds 5865 | push es 5866 | pop ds 5867 | mov ah,3Fh ;read file 5868 | int 21h 5869 | pop ds 5870 | jc readmd_er2 5871 | add di,cx ;new position to di 5872 | ret 5873 | readmd_er1: 5874 | readmd_er2: 5875 | @trace_s <"error in function ReadMD",lf> 5876 | mov ax,offset errstr6 5877 | ret 5878 | ReadMD endp 5879 | 5880 | ;*** read resource table (to ES:DI) 5881 | 5882 | LoadResTable proc 5883 | 5884 | mov cx,es:[NEHDR.ne_restab] ;are there any? 5885 | mov ax,es:[NEHDR.ne_rsrctab] 5886 | sub cx,ax 5887 | jz @F 5888 | jmp ReadMD 5889 | @@: 5890 | clc 5891 | ret 5892 | 5893 | LoadResTable endp 5894 | 5895 | ;*** read resident names (to ES:DI) 5896 | 5897 | LoadResNames proc 5898 | 5899 | mov cx,es:[NEHDR.ne_modtab] ;are there any? 5900 | mov ax,es:[NEHDR.ne_restab] 5901 | sub cx,ax 5902 | jz done 5903 | push di 5904 | call ReadMD 5905 | pop bx 5906 | jc done 5907 | if _LINKWORKAROUND_ ;old linkers may save module names 5908 | mov cl,es:[bx] ;not in caps! 5909 | nextitem: 5910 | inc bx 5911 | mov al,es:[bx] 5912 | cmp al,'a' 5913 | jb @F 5914 | cmp al,'z' 5915 | ja @F 5916 | sub byte ptr es:[bx],'a'-'A' 5917 | @@: 5918 | dec cl 5919 | jnz nextitem 5920 | clc 5921 | endif 5922 | done: 5923 | ret 5924 | 5925 | LoadResNames endp 5926 | 5927 | ;*** read module references (to ES:DI),C=error 5928 | 5929 | LoadModRefs proc 5930 | mov cx,es:[NEHDR.ne_imptab] ;are there any? 5931 | mov ax,es:[NEHDR.ne_modtab] 5932 | sub cx,ax 5933 | jz @F 5934 | jmp ReadMD 5935 | @@: 5936 | ret 5937 | LoadModRefs endp 5938 | 5939 | ;*** read imported names (to ES:DI),C=error 5940 | 5941 | LoadImpTable proc 5942 | mov cx,es:[NEHDR.ne_enttab] ;offset entry table 5943 | mov ax,es:[NEHDR.ne_imptab] 5944 | sub cx,ax 5945 | jz @F 5946 | jmp ReadMD 5947 | @@: 5948 | ret 5949 | LoadImpTable endp 5950 | 5951 | ;*** read nonresident names (to ES:DI),C=error 5952 | 5953 | LoadNResNames proc 5954 | mov cx,es:[NEHDR.NRESLEN] ;are there any? 5955 | jcxz exit 5956 | push cx 5957 | mov bx,es:[NEHDR.ne_hFile] 5958 | mov cx,word ptr es:[NEHDR.NRESADR+2] 5959 | mov dx,word ptr es:[NEHDR.NRESADR+0] 5960 | mov ax,4200h 5961 | int 21h 5962 | pop cx 5963 | jc error 5964 | ; mov bx,es:[NEHDR.ne_hFile] 5965 | mov dx,di 5966 | push ds 5967 | push es 5968 | pop ds 5969 | mov ah,3Fh 5970 | int 21h 5971 | pop ds 5972 | jc error 5973 | add di,cx 5974 | exit: 5975 | clc 5976 | ret 5977 | error: 5978 | mov ax,offset errstr6 5979 | stc 5980 | ret 5981 | LoadNResNames endp 5982 | 5983 | ;*** read entry table (to ES:DI),C=error 5984 | 5985 | LoadEntryTable proc 5986 | mov cx,es:[NEHDR.ne_cbenttab] ;length of entry table 5987 | mov ax,es:[NEHDR.ne_enttab] ;start of entry table 5988 | jcxz @F 5989 | jmp ReadMD 5990 | @@: clc 5991 | ret 5992 | LoadEntryTable endp 5993 | 5994 | ;--- InitDlls, called internally for OS/2 and DPMI32 5995 | ;--- or by InitTask for DPMI16 5996 | ;--- in: ES=PSP 5997 | ;--- out: DI=MD 5998 | 5999 | InitDlls proc public uses es si dx 6000 | 6001 | if ?DEBUG 6002 | nop 6003 | @trace_s <"InitDlls enter",lf> 6004 | endif 6005 | 6006 | if _FILEHANDLES_ ne 20 6007 | mov bx,_FILEHANDLES_ 6008 | mov ah,67h 6009 | int 21h 6010 | endif 6011 | mov si,ss 6012 | call Segment2ModuleFirst ;find module handle for SI into AX/ES 6013 | jc error 6014 | @trace_s <"call CallAllLibEntries",lf> 6015 | call CallAllLibEntries ;call lib entries for new dlls 6016 | ife ?32BIT 6017 | cmp es:[NEHDR.ne_exetyp],ET_DPMI16 6018 | jnz @F 6019 | test es:[NEHDR.APPFLGS],10h 6020 | jz nodichange 6021 | @@: 6022 | mov di,es ;set DI to hModule for OS/2 and RTM DPMI16 6023 | nodichange: 6024 | clc 6025 | endif 6026 | error: 6027 | ret 6028 | InitDlls endp 6029 | 6030 | 6031 | 6032 | ;*** if module is a dll and not initialized yet: call LibEntry 6033 | ;*** ES=MD *** 6034 | ;*** called by CallAllLibEntries 6035 | 6036 | CallLibEntry proc 6037 | 6038 | ; inc es:[NEHDR.ne_count] ;now done in LoadLibIntern 6039 | @trace_s <"CallLibEntry enter",lf> 6040 | ; cmp es:[NEHDR.ne_count],1 6041 | ; jnz done 6042 | test es:[NEHDR.APPFLGS],AF_DLL ;DLL? 6043 | jz done 6044 | test es:[NEHDR.APPFLGS],AF_INIT ;LibEntry called? 6045 | jnz done 6046 | @trace_s <"calling dll entry of "> 6047 | @tracemodule 6048 | @trace_s 6049 | mov cx,word ptr es:[NEHDR.ne_csip+2] ;exists CS:IP? 6050 | mov bx,word ptr es:[NEHDR.ne_csip+0] 6051 | if ?INT41SUPPORT 6052 | push si 6053 | mov si,es 6054 | mov ax,DS_LOADDLL ;es,si=NE 6055 | int 41h 6056 | pop si 6057 | endif 6058 | and cx,cx 6059 | jz nolibentry 6060 | 6061 | push ds 6062 | push es 6063 | push si 6064 | push di 6065 | mov di,es 6066 | if ?32BIT 6067 | 6068 | push cx 6069 | push bx 6070 | pop edx ;EDX=CS:IP 6071 | 6072 | xor ax,ax ;if no dgroup found, use 0 as 6073 | mov ds,ax ;hInstance (or better MD?) 6074 | ;; mov es:[NEHDR.ne_count],ax 6075 | mov bx,es:[NEHDR.DGROFS] ;offset to dgroup 6076 | and bx,bx 6077 | jz @F 6078 | mov ds,es:[bx].SEGITEM.wSel 6079 | @@: 6080 | mov es,ax 6081 | mov si,ax 6082 | xor cx,cx 6083 | call CallProc16 6084 | else 6085 | push bp 6086 | mov bp,sp 6087 | push cx ;put CS on stack 6088 | push bx ;put IP on stack 6089 | mov cx,es:[NEHDR.ne_heap] ;if no DGROUP exists, 6090 | xor ax,ax ;use 0 (or better MD?) as 6091 | mov ds,ax ;hInstance 6092 | ;; mov es:[NEHDR.ne_count],ax 6093 | mov bx,es:[NEHDR.DGROFS] ;offset to dgroup 6094 | and bx,bx 6095 | jz @F 6096 | mov ds,es:[bx].SEGITEM.wSel 6097 | @@: 6098 | mov es,ax 6099 | mov si,ax 6100 | @trace_s <"call with CS:IP="> 6101 | @trace_w [bp-2] 6102 | @trace_s <":"> 6103 | @trace_w [bp-4] 6104 | @trace_s <", ES="> 6105 | @trace_w es 6106 | @trace_s <", DS="> 6107 | @trace_w ds 6108 | @trace_s <", CX="> 6109 | @trace_w cx 6110 | @trace_s <", BP="> 6111 | @trace_w bp 6112 | @trace_s <", SP="> 6113 | @trace_w sp 6114 | @trace_s lf 6115 | call dword ptr [bp-04] ;call Libentry 6116 | mov sp,bp 6117 | pop bp 6118 | endif 6119 | pop di 6120 | pop si 6121 | pop es 6122 | pop ds 6123 | @trace_s <"returned from init Dll, RC="> 6124 | @trace_w ax 6125 | @trace_s lf 6126 | if _CHKLIBENTRYRC_ 6127 | and ax,ax ;RC must be <> 0 6128 | jz error1 6129 | endif 6130 | nolibentry: 6131 | ;; mov byte ptr es:[NEHDR.ne_count],01 6132 | if ?SETINIT 6133 | or es:[NEHDR.APPFLGS],AF_INIT 6134 | endif 6135 | done: 6136 | @trace_s <"CallLibEntry exit",lf> 6137 | clc 6138 | ret 6139 | error1: ;error in LibEntry 6140 | pusha 6141 | push ds 6142 | mov ds,cs:[wLdrDS] 6143 | ;; dec es:[NEHDR.ne_count] 6144 | mov di,offset szEntryCode 6145 | call WORDOUT ;bin2ascii(errorcode) 6146 | mov si,offset szLibName 6147 | mov di,offset NEHDR.szModPath 6148 | nextchar: 6149 | mov al,es:[di] 6150 | mov [si],al 6151 | inc si 6152 | inc di 6153 | cmp al,00 6154 | jnz nextchar 6155 | mov word ptr [si-1],0A0Dh 6156 | mov [si+1],al 6157 | mov ax,offset szEntryErr 6158 | call stroutax 6159 | pop ds 6160 | popa 6161 | ; mov ax,offset errstr15 ;DLL init error 6162 | @trace_s <"CallLibEntry exit",lf> 6163 | stc 6164 | ret 6165 | CallLibEntry endp 6166 | 6167 | ;*** call LibEntrys of dlls 6168 | ;*** Input: AX=MD *** 6169 | ;--- called by InitTask (apps) 6170 | ;--- or in int 21h, ax=4B00h (dlls) 6171 | 6172 | CallAllLibEntries proc public uses es 6173 | 6174 | clc 6175 | mov es,ax 6176 | @trace_s <"CallAllLibEntries enter, ax="> 6177 | @trace_w ax 6178 | @trace_s 6179 | lsl ax,ax 6180 | @trace_s <"CallAllLibEntries limit of es="> 6181 | @trace_w ax 6182 | @trace_s 6183 | xor cx,cx 6184 | xchg cx,es:[NEHDR.ne_cmod] 6185 | jcxz done 6186 | push si 6187 | push cx 6188 | mov si,es:[NEHDR.ne_modtab] 6189 | @@: 6190 | lods word ptr es:[NEHDR.ne_cmod] 6191 | push cx 6192 | push si 6193 | call CallAllLibEntries ;recursion! 6194 | pop si 6195 | pop cx 6196 | jc @F 6197 | loop @B 6198 | @@: 6199 | pop word ptr es:[NEHDR.ne_cmod] 6200 | pop si 6201 | jc exit 6202 | done: 6203 | call CallLibEntry 6204 | exit: 6205 | @trace_s <"CallAllLibEntries exit",lf> 6206 | mov ax,es 6207 | ret 6208 | CallAllLibEntries endp 6209 | 6210 | ;--- get module handle of a segment 6211 | ;--- inp: segment in SI 6212 | ;--- out: not found: C + AX=0000 6213 | ;--- success: NC + module handle in AX 6214 | ;--- and address of segment descriptor in ES:BX 6215 | 6216 | Segment2ModuleFirst: 6217 | mov bx,cs:[wMDSta] ;search from module list start 6218 | 6219 | Segment2Module proc public 6220 | 6221 | if 0 6222 | @trace_s <"searching module handle, seg="> 6223 | @trace_w si 6224 | @trace_s lf 6225 | endif 6226 | and si,0FFFCh 6227 | mov ax,bx 6228 | nextmodule: 6229 | if 0 6230 | @trace_s <"module: "> 6231 | @trace_w ax 6232 | @trace_s lf 6233 | endif 6234 | and ax,ax 6235 | stc 6236 | jz segm2mod2 6237 | mov es,ax 6238 | mov cx,es:[NEHDR.ne_cseg] 6239 | mov bx,es:[NEHDR.ne_segtab] 6240 | nextsegment: 6241 | mov ax,es:[bx].SEGITEM.wSel 6242 | if 0 6243 | @trace_s <" segment: "> 6244 | @trace_w ax 6245 | @trace_s lf 6246 | endif 6247 | and al,0FCh 6248 | cmp si,ax 6249 | jz found 6250 | add bx,SGTSIZE 6251 | loop nextsegment 6252 | mov ax,es:[NEHDR.NXTMOD] 6253 | jmp nextmodule 6254 | found: 6255 | mov ax,es 6256 | segm2mod2: 6257 | ret 6258 | Segment2Module endp 6259 | 6260 | ;*** search handle of a module 6261 | ;--- inp: 6262 | ;--- 1. DS=0000, SI=selector 6263 | ;--- 2. DS:E/SI -> module name, CL=size of module name 6264 | ;--- out: C=error, AX=0000 6265 | ;--- NC=success, AX=module handle 6266 | 6267 | SearchModule16 proc near public 6268 | 6269 | mov bx,cs:[wMDSta] 6270 | mov ax,ds 6271 | and ax,ax 6272 | jz Segment2Module ;ok, is SI is a selector 6273 | if ?32BIT 6274 | push edi 6275 | else 6276 | push di 6277 | endif 6278 | push es 6279 | mov ah,cl 6280 | nextitem: 6281 | and bx,bx 6282 | jz notfound 6283 | push si 6284 | mov es,bx 6285 | mov di,es:[NEHDR.ne_restab] 6286 | mov cl,ah 6287 | if ?32BIT 6288 | movzx ecx, cl 6289 | else 6290 | mov ch,00 6291 | endif 6292 | cmp cl,es:[di] 6293 | jnz @F 6294 | inc di 6295 | if ?32BIT 6296 | movzx edi,di 6297 | db 67h 6298 | repz cmpsb 6299 | else 6300 | repz cmpsb 6301 | endif 6302 | @@: 6303 | pop si 6304 | jz found 6305 | mov bx,es:[NEHDR.NXTMOD] 6306 | jmp nextitem 6307 | notfound: 6308 | xor ax,ax 6309 | stc 6310 | jmp exit 6311 | found: 6312 | mov ax,es 6313 | clc 6314 | exit: 6315 | pop es 6316 | if ?32BIT 6317 | pop edi 6318 | else 6319 | pop di 6320 | endif 6321 | ret 6322 | SearchModule16 endp 6323 | 6324 | ;*** load module if not already loaded 6325 | ;*** ES:SI -> name of module 6326 | ;*** CL: max. length of module name 6327 | ;*** Out: AX= module handle 6328 | ;*** module name in szModName 6329 | ;*** Entries: LoadLibIntern2: in DS:(E)DX=path 6330 | ;*** LoadLibIntern: in ES:(E)SI=module name, length in CX 6331 | 6332 | LoadLibIntEx: 6333 | ret 6334 | 6335 | LoadLibIntern2 proc ;Name -> DS:(E)DX, length still undefined 6336 | push ds 6337 | pop es 6338 | if ?32BIT 6339 | mov edi,edx 6340 | mov esi,edx 6341 | else 6342 | mov di,dx 6343 | mov si,dx 6344 | endif 6345 | call strlen 6346 | mov ax,cx 6347 | stc 6348 | jcxz LoadLibIntEx 6349 | if ?32BIT 6350 | movzx ecx,cx 6351 | add esi,ecx 6352 | @@: 6353 | dec esi 6354 | mov al,[esi] 6355 | cmp al,'\' 6356 | jz @F 6357 | cmp al,'/' 6358 | jz @F 6359 | cmp al,':' 6360 | jz @F 6361 | loop @B 6362 | dec esi 6363 | @@: 6364 | inc esi 6365 | else 6366 | add si,cx 6367 | @@: 6368 | dec si 6369 | mov al,[si] 6370 | cmp al,'\' 6371 | jz @F 6372 | cmp al,'/' 6373 | jz @F 6374 | cmp al,':' 6375 | jz @F 6376 | loop @B 6377 | dec si 6378 | @@: 6379 | inc si 6380 | endif 6381 | mov ds,cs:[wLdrDS] 6382 | mov [wlError],2 ;default error "file not found" 6383 | if ?RESETDEFPATH 6384 | mov szPath,00 ;reset default path 6385 | endif 6386 | mov cx,0FFFFh 6387 | if ?32BIT 6388 | mov dword ptr [blksize+0],edi 6389 | mov word ptr [blkaddr+0],es 6390 | movzx edi,di 6391 | else 6392 | mov word ptr [blksize+0],di ;is used as temp variable here 6393 | mov word ptr [blksize+2],es 6394 | endif 6395 | jmp @F 6396 | LoadLibIntern:: ;<--- entry 6397 | mov di,offset szModName 6398 | if ?32BIT 6399 | movzx edi,di 6400 | mov dword ptr [blksize+0],edi 6401 | mov word ptr [blkaddr+0],ds 6402 | else 6403 | mov word ptr [blksize+0],di 6404 | mov word ptr [blksize+2],ds 6405 | endif 6406 | @@: ;used by LoadLibIntern+LoadLibIntern2 6407 | mov ah,00 ;copy name 6408 | mov di,offset szModName 6409 | nextitem: 6410 | if ?32BIT 6411 | mov al,es:[esi] 6412 | else 6413 | mov al,es:[si] 6414 | endif 6415 | cmp al,'a' 6416 | jb @F 6417 | cmp al,'z' 6418 | ja @F 6419 | sub al,'a'-'A' 6420 | @@: 6421 | mov [di],al 6422 | and al,al 6423 | jz lli_1 6424 | cmp al,'.' 6425 | jnz @F 6426 | inc ah 6427 | @@: 6428 | inc di 6429 | if ?32BIT 6430 | inc esi 6431 | else 6432 | inc si 6433 | endif 6434 | loop nextitem 6435 | mov [di],cl 6436 | lli_1: 6437 | push ds 6438 | pop es 6439 | and ah,ah 6440 | jnz @F 6441 | mov cx,0005 6442 | mov si,offset szDotDLL ;strcat ".DLL",00 6443 | rep movsb 6444 | @@: 6445 | mov si,offset szModName ;^ name of module 6446 | if ?32BIT 6447 | movzx esi,si 6448 | endif 6449 | call strlen 6450 | sub cx,4 6451 | call SearchModule16 ;check if module already loaded 6452 | jnc LoadLibIntern3 ;if yes, then just simple update 6453 | if ?32BIT 6454 | mov eax,dword ptr [blksize+0] 6455 | mov dx,word ptr [blkaddr+0] 6456 | else 6457 | mov ax,word ptr [blksize+0] 6458 | mov dx,word ptr [blksize+2] 6459 | endif 6460 | call LoadModule16 ;load DLL DX:(E)AX 6461 | jc LoadLib_Err 6462 | mov es,ax ;added 2.7.2005 6463 | cntupdate: 6464 | inc es:[NEHDR.ne_count] ;added 2.7.2005 6465 | @trace_s <"module "> 6466 | @trace_w es 6467 | @trace_s <" count now "> 6468 | @trace_w es:[NEHDR.ne_count] 6469 | @trace_s 6470 | clc 6471 | ret 6472 | LoadLibIntern3: 6473 | mov es,ax 6474 | xor cx,cx 6475 | xchg cx,es:[NEHDR.ne_cmod] ;get no of referenced modules 6476 | jcxz cntupdate 6477 | mov si,es:[NEHDR.ne_modtab] 6478 | push cx 6479 | nextmodule: 6480 | lods word ptr es:[si] 6481 | push es 6482 | push cx 6483 | push si 6484 | call LoadLibIntern3 6485 | pop si 6486 | pop cx 6487 | pop es 6488 | loop nextmodule 6489 | pop es:[NEHDR.ne_cmod] 6490 | mov ax,es 6491 | jmp cntupdate 6492 | LoadLib_Err: 6493 | test byte ptr wErrMode+1,HBSEM_NOOPENFILEBOX 6494 | jnz @F 6495 | cmp ax,offset szNotaNE ;"not NE format"? 6496 | jz @F 6497 | call stroutax 6498 | @@: 6499 | stc 6500 | ret 6501 | LoadLibIntern2 endp 6502 | 6503 | ;*** load all referenced modules 6504 | ;*** ES -> current module 6505 | ;*** in case of errors: C and AX -> error text 6506 | 6507 | LoadRefMods16 proc 6508 | @trace_s <"loading referenced modules",lf> 6509 | test byte ptr es:[NEHDR.APPFLGS],AF_DLL 6510 | jnz @F ;if application save path 6511 | call savepathNE ;as default for DLLs 6512 | @@: 6513 | xor cx,cx 6514 | xchg cx,es:[NEHDR.ne_cmod] ;get no of referenced modules 6515 | jcxz done ;none are there, done 6516 | mov si,es:[NEHDR.ne_modtab] 6517 | push cx 6518 | nextitem: 6519 | mov [wlError],0014h 6520 | push cx 6521 | push si 6522 | mov ax,es:[si] ;this is offset in table 6523 | mov si,es:[NEHDR.ne_imptab] ;of imported names 6524 | add si,ax 6525 | if ?32BIT 6526 | movzx esi, si 6527 | endif 6528 | sub cx,cx 6529 | mov cl,es:[si] ;length of name 6530 | inc si 6531 | push es 6532 | call LoadLibIntern 6533 | pop es 6534 | pop si 6535 | pop cx 6536 | jc UnloadMod16Ex 6537 | mov es:[si],ax ;instead of offset now save module 6538 | inc si ;handle in MD 6539 | inc si 6540 | loop nextitem ;next modul 6541 | pop es:[NEHDR.ne_cmod] 6542 | done: 6543 | clc 6544 | @trace_s <"exit load referenced modules",lf> 6545 | ret 6546 | LoadRefMods16 endp 6547 | 6548 | ;*** error handling when loading modules 6549 | ;*** module counts aren't adjusted yet, but segments 6550 | ;*** are loaded (partially!) 6551 | 6552 | UnloadMod16Ex: 6553 | pop ax 6554 | sub ax,cx 6555 | mov es:[NEHDR.ne_cmod],ax 6556 | UnloadMod16 proc 6557 | mov cx,es:[NEHDR.ne_cmod] 6558 | @@: 6559 | mov si,es:[NEHDR.ne_modtab] 6560 | jcxz done 6561 | nextitem: 6562 | push es 6563 | mov ax,es:[si] 6564 | verr ax 6565 | jnz @F 6566 | mov es,ax 6567 | ; cmp es:[NEHDR.ne_count],0 6568 | ; jnz @F 6569 | push cx 6570 | mov ax,es 6571 | call FreeLib16 6572 | pop cx 6573 | @@: 6574 | inc si 6575 | inc si 6576 | pop es 6577 | loop nextitem 6578 | done: 6579 | mov ax,-1 6580 | stc 6581 | @trace_s <"fatal exit load referenced modules",lf> 6582 | ret 6583 | UnloadMod16 endp 6584 | 6585 | ;--- call dowep, but only for dlls and AF_INIT must be set (LibEntry called) 6586 | ;--- inp: ES=MD 6587 | 6588 | dowep proc 6589 | 6590 | @trace_s <"delete module "> 6591 | @tracemodule 6592 | @trace_s lf 6593 | 6594 | test byte ptr es:[NEHDR.APPFLGS],AF_DLL ;dll? 6595 | jz dowep_3 6596 | if ?SETINIT 6597 | test es:[NEHDR.APPFLGS],AF_INIT ;LibEntry called? 6598 | jz exit 6599 | endif 6600 | push si 6601 | push cx 6602 | mov si,offset szWEP ;search WEP 6603 | if ?32BIT 6604 | movzx esi,si 6605 | endif 6606 | mov ds,cs:[wLdrDS] 6607 | mov cl,3 6608 | call SearchNEExport ;search in resident + nonres names 6609 | jc dowep_2 6610 | @trace_s <"calling WEP",lf> 6611 | if ?32BIT 6612 | push ax 6613 | push bx 6614 | pop edx ;EDX=CS:IP 6615 | push ds 6616 | push 0 6617 | pop ds 6618 | mov bx,es:[NEHDR.DGROFS] ;offset to dgroup 6619 | and bx,bx 6620 | jz @F 6621 | mov ds,es:[bx].SEGITEM.wSel 6622 | @@: 6623 | push 0000 ;WEP parameter 6624 | mov ebx, esp ;DS:EBX -> parameters 6625 | mov cx, 1 6626 | call CallProc16 6627 | pop cx 6628 | movzx edx, dx 6629 | movzx ebx, bx 6630 | pop ds 6631 | else 6632 | push es 6633 | push ds 6634 | mov si,sp 6635 | push 0000 ;WEP Parameter 6636 | push cs 6637 | push offset dowep_1 6638 | push ax 6639 | push bx 6640 | xor ax,ax 6641 | mov ds,ax 6642 | mov bx,es:[NEHDR.DGROFS] ;offset to dgroup 6643 | and bx,bx 6644 | jz @F 6645 | mov ds,es:[bx].SEGITEM.wSel 6646 | @@: 6647 | mov es,ax 6648 | retf 6649 | dowep_1: 6650 | mov sp,si 6651 | pop ds 6652 | pop es 6653 | endif 6654 | @trace_s <"returned from WEP, RC="> 6655 | @trace_w ax 6656 | @trace_s lf 6657 | dowep_2: ;WEP doesnt exist 6658 | pop cx 6659 | pop si 6660 | dowep_3: 6661 | if ?INT41SUPPORT 6662 | mov ax,DS_DELMODULE ;"module about to be removed" 6663 | int 41h 6664 | endif 6665 | exit: 6666 | ret 6667 | dowep endp 6668 | 6669 | 6670 | checkne proc public 6671 | verr ax 6672 | jnz @F 6673 | mov es,ax 6674 | cmp word ptr es:[0],"EN" 6675 | jnz @F 6676 | ret 6677 | @@: 6678 | stc 6679 | ret 6680 | checkne endp 6681 | 6682 | ;*** decrement module reference counter, if 0, call WEP 6683 | ;*** will decrement all referenced modules as well 6684 | ;*** AX = MD *** 6685 | ;*** modifies BX, sets ES=0 if ES=MD 6686 | ;*** C if MD is invalid or other error 6687 | ;--- called for dlls and apps! 6688 | 6689 | if ?32BIT 6690 | FreeLib16 proc public uses ds bx esi edi 6691 | else 6692 | FreeLib16 proc public uses ds bx si di 6693 | endif 6694 | 6695 | push es 6696 | mov ds,cs:[wLdrDS] 6697 | @trace_s <"FreeLib16 "> 6698 | @trace_w ax 6699 | @trace_s 6700 | call checkne 6701 | jc error23 6702 | @trace_s <"cnt="> 6703 | @trace_w es:[NEHDR.ne_count] 6704 | @trace_s 6705 | cmp es:[NEHDR.ne_count],1 6706 | jnz @F 6707 | call dowep 6708 | @@: 6709 | xor cx,cx 6710 | xchg cx,es:[NEHDR.ne_cmod] 6711 | push cx 6712 | jcxz refsdone 6713 | mov si,es:[NEHDR.ne_modtab] 6714 | add si,cx 6715 | add si,cx 6716 | nextitem: 6717 | dec si 6718 | dec si 6719 | mov ax,es:[si] 6720 | push cx 6721 | call FreeLib16 6722 | pop cx 6723 | loop nextitem 6724 | refsdone: 6725 | pop cx 6726 | mov ax,es 6727 | verw ax 6728 | jnz done 6729 | mov es:[NEHDR.ne_cmod],cx 6730 | cmp es:[NEHDR.ne_count],0 6731 | jz @F 6732 | dec es:[NEHDR.ne_count] 6733 | jnz done 6734 | @@: 6735 | push es 6736 | call DeleteModule16 ;delete module from module list 6737 | pop es 6738 | call CleanUpNE ;free resources 6739 | @trace_s <"library freed",lf> 6740 | done: 6741 | clc 6742 | exit: 6743 | pop cx 6744 | pushf 6745 | verr cx ;if ES is invalid now, clear it 6746 | jz @F 6747 | @trace_s <"MD "> 6748 | @trace_w cx 6749 | @trace_s <" now invalid, clearing ES",lf> 6750 | xor cx, cx 6751 | @@: 6752 | mov es, cx 6753 | popf 6754 | ret 6755 | error23: 6756 | test byte ptr [wErrMode+1],HBSEM_NOOPENFILEBOX 6757 | jnz @F 6758 | mov di,offset es23hdl 6759 | call WORDOUT ;bin2ascii(AX) 6760 | mov bx,offset szErr23 6761 | @strout_err 6762 | @@: 6763 | stc 6764 | jmp exit 6765 | FreeLib16 endp 6766 | 6767 | ;*** search entry in external module (Import) 6768 | ;*** input: es -> MD external module 6769 | ;*** DS:(E)SI -> entry to be found 6770 | ;*** CL=length of name 6771 | ;--- if CL=0, it is an ordinal in SI 6772 | ;*** if found, call GetProcAddr16(), return Selector:Offset in AX:BX 6773 | 6774 | SearchNEExport proc public 6775 | mov ax,si 6776 | cmp cl,0 6777 | jz found 6778 | mov bl,cl 6779 | push di 6780 | mov di,es:[NEHDR.ne_restab] 6781 | mov ax,es:[NEHDR.NRESNAM] 6782 | nextitem: ;<---- 6783 | sub cx,cx 6784 | mov cl,es:[di] ;compare names 6785 | jcxz notfound ;table end reached -> error 6786 | inc di 6787 | if _TESTIMPORT_ 6788 | pusha 6789 | push ds 6790 | push es 6791 | 6792 | push es 6793 | pop ds 6794 | mov bx,di 6795 | call stroutBXn 6796 | @cr_out 6797 | 6798 | pop es 6799 | pop ds 6800 | popa 6801 | endif 6802 | cmp bl,cl ;do lengths match? 6803 | jnz skipitem 6804 | if ?32BIT 6805 | push esi 6806 | movzx edi,di 6807 | repe cmps byte ptr [edi],[esi] 6808 | pop esi 6809 | else 6810 | push si 6811 | repe cmpsb 6812 | pop si 6813 | endif 6814 | jz @F 6815 | skipitem: 6816 | add di,cx 6817 | inc di ;skip number 6818 | inc di 6819 | jmp nextitem ;---> 6820 | @@: 6821 | mov ax,es:[di] 6822 | pop di 6823 | found: 6824 | call GetProcAddr16 ;entry ES.AX -> AX:BX 6825 | ret 6826 | notfound: 6827 | mov di,ax ;address of nonres names table (or NULL) to di 6828 | xor ax,ax 6829 | and di,di 6830 | jnz nextitem ;---> 6831 | mov bx,ax 6832 | pop di 6833 | cwd 6834 | stc 6835 | ret 6836 | SearchNEExport endp 6837 | 6838 | ;*** GetProcAddress: Entry# -> selector:offset 6839 | ;*** input: ES -> MD , Entry# in AX 6840 | ;*** output: selector:offset in AX:BX, ^Entry in CX 6841 | 6842 | ;*** structure of entry table (in windows): 6843 | ;*** 6 Bytes header (WORD firstentry#,WORD lastentry#,WORD ^nextentryheader) 6844 | ;*** 5 Bytes entry (BYTE Type,BYTE Flags,BYTE Seg#,WORD Offset) 6845 | 6846 | ;--- here in DPMILDxx it is: 6847 | ;*** if first byte is ZERO, table end is reached 6848 | ;*** if second byte is ZERO, first byte is to be added to entry # 6849 | ;--- else first byte is number of entries 6850 | ;--- and second byte determines if entries are 3 or 6 bytes long 6851 | 6852 | GetProcAddr16 proc uses dx si di 6853 | 6854 | and ax,ax 6855 | jz error1 ;entry 0 is error 6856 | mov si,es:[NEHDR.ne_enttab] ;entries (integer) 6857 | mov dx,0001 6858 | xor cx,cx 6859 | mov bh,ch 6860 | nextitem: ;<---- 6861 | mov cl,es:[si] 6862 | jcxz error1 ;end reached? then error "entry not found" 6863 | inc si 6864 | mov di,si 6865 | mov bl,es:[si] 6866 | inc si 6867 | and bl,bl 6868 | jnz @F 6869 | add dx,cx 6870 | jmp nextitem 6871 | @@: 6872 | cmp bl,0FFh 6873 | mov bl,3 6874 | jnz gpa_1 6875 | mov bl,6 6876 | gpa_1: 6877 | cmp ax,dx 6878 | jz found ;found, we are done 6879 | add si,bx 6880 | inc dx 6881 | loop gpa_1 6882 | jmp nextitem ;----> 6883 | found: 6884 | xor ax,ax 6885 | mov al,es:[di] 6886 | cmp al,0FFh 6887 | jnz @F 6888 | add si,3 6889 | mov al,es:[si+0] ;get segment number 6890 | @@: 6891 | mov bx,es:[si+1] ;offset 6892 | cmp al,0FEh 6893 | jnz @F 6894 | mov ax,bx 6895 | jmp done 6896 | @@: 6897 | call SegNo2Sel ;selector of entry (->AX) 6898 | done: 6899 | mov cx,si ;^ Entry -> CX 6900 | clc 6901 | ret 6902 | error1: 6903 | xor ax,ax 6904 | cwd 6905 | stc 6906 | ret 6907 | 6908 | GetProcAddr16 endp 6909 | 6910 | ;------------------------------------------------------- 6911 | 6912 | if ?RMSEGMENTS 6913 | 6914 | ;--- this code is not active any more!!! 6915 | 6916 | ;*** call a real mode Proc 6917 | ;*** called by exception handler 6918 | ;*** EBP -> PUSHA(D), Errorcode, CS:IP, flags 6919 | 6920 | ExecRMProc proc 6921 | if ?32BIT 6922 | 6923 | push esi 6924 | push ds 6925 | lds esi,[ebp+0Eh] ;CS:EIP of exception address 6926 | cmp byte ptr [esi],9Ah ;far call? 6927 | pop ds 6928 | pop esi 6929 | jnz error2 ;anything else is invalid 6930 | 6931 | push ebp 6932 | mov dx,ss 6933 | mov bx,[ebp+20h] ;get SS:ESP 6934 | mov ebp,[ebp+1Ch] 6935 | mov ss,bx 6936 | mov ecx,[ebp+00h] ;and then CS:EIP 6937 | mov bx,[ebp+04h]? 6938 | mov ss,dx 6939 | pop ebp 6940 | 6941 | else 6942 | push si 6943 | push ds 6944 | lds si,[bp+08h] ;CS:IP of exception 6945 | cmp byte ptr [si],9Ah 6946 | pop ds 6947 | pop si 6948 | jnz error2 6949 | 6950 | push bp 6951 | mov dx,ss 6952 | mov bx,[bp+10h] ;SS 6953 | mov bp,[bp+0Eh] ;SP 6954 | mov ss,bx 6955 | mov cx,[bp+00h] ;IP 6956 | mov bx,[bp+02h] ;CS 6957 | mov ss,dx 6958 | pop bp 6959 | 6960 | endif 6961 | push cx 6962 | call Sel2Segment ;get base von BX 6963 | pop cx 6964 | jc error1 ;error: nicht im 1. MB 6965 | if ?32BIT 6966 | push edi 6967 | sub esp,sizeof RMCS 6968 | mov edi,esp 6969 | else 6970 | push di 6971 | sub sp,sizeof RMCS 6972 | mov di,sp 6973 | endif 6974 | mov ax,es:[si+XDOSSEG] 6975 | push es 6976 | 6977 | push ss 6978 | pop es 6979 | if ?32BIT 6980 | mov es:[edi.RMCS.rCS],ax ;what's with (E)IP? 6981 | else 6982 | mov es:[di.RMCS.rCS],ax 6983 | endif 6984 | push bx 6985 | push cx 6986 | mov cx,0002 ;copy 2 words??? 6987 | xor bx,bx 6988 | mov ax,0301h ;call Real Mode Proc 6989 | call dpmicall 6990 | jc error3 6991 | add sp,+04 6992 | if ?32BIT 6993 | mov eax,word ptr es:[edi.RMCS.rEAX] 6994 | mov edx,word ptr es:[edi.RMCS.rEDX] 6995 | add dword ptr [ebp+0Eh],+07 ;adjust EIP (call far32) 6996 | else 6997 | mov ax,word ptr es:[di.RMCS.rEAX] 6998 | mov dx,word ptr es:[di.RMCS.rEDX] 6999 | add word ptr [bp+08h],+05 ;adjust EIP (call far16) 7000 | endif 7001 | add sp,sizeof RMCS 7002 | clc 7003 | exit: 7004 | pop es 7005 | if ?32BIT 7006 | pop edi 7007 | else 7008 | pop di 7009 | endif 7010 | ret 7011 | 7012 | error1: 7013 | mov ax,offset errstr41 ;error 'cant get base address' 7014 | stc 7015 | ret 7016 | error2: 7017 | mov ax,offset errstr43 ;error 'invalid call instr' 7018 | stc 7019 | ret 7020 | error3: 7021 | mov ax,offset errstr42 ;error 'CallRealModeProc Error' 7022 | add sp,4 + sizeof RMCS 7023 | stc 7024 | jmp exit 7025 | 7026 | ExecRMProc endp 7027 | 7028 | ;*** selector -> segment (BX=selector) *** 7029 | ;*** RC: Carry on errors, else SEGMENT in BX *** 7030 | 7031 | Sel2Segment proc 7032 | mov ax,0006h ;get base 7033 | call dpmicall 7034 | jc exit 7035 | if ?32BIT 7036 | push cx 7037 | push dx 7038 | pop eax 7039 | shr eax,4 7040 | test eax,0FFFF0000h 7041 | else 7042 | mov ax,dx 7043 | mov dx,cx 7044 | mov bx,0010h ;shr 4 7045 | div bx 7046 | cmp dx,+00 ;im 1. MB? 7047 | endif 7048 | stc 7049 | jnz exit 7050 | mov bx,ax 7051 | clc 7052 | exit: 7053 | ret 7054 | 7055 | Sel2Segment endp 7056 | 7057 | endif ;?RMSEGMENTS 7058 | 7059 | ;--------------------------------------------- 7060 | 7061 | ;--- there is no longer a copy to the PSP, since the loader 7062 | ;--- PSP is larger than 100h bytes and the termination code 7063 | ;--- always remains in conv. memory 7064 | 7065 | if ?EXTLOAD 7066 | if _COPY2PSP_ 7067 | 7068 | copy_to_psp_and_exit proc 7069 | test byte ptr fHighLoad,1 7070 | jnz @F 7071 | ret 7072 | @@: 7073 | @trace_s <"critical section: create code alias for PSP and jump",lf> 7074 | mov bx,[wLdrPSP] 7075 | mov ss,bx 7076 | if ?32BIT 7077 | mov esp,100h 7078 | else 7079 | mov sp,100h 7080 | endif 7081 | push ax 7082 | mov si,word ptr [dwMemHdl+2] 7083 | mov di,word ptr [dwMemHdl+0] 7084 | mov ax,ds 7085 | call CreateAlias ;BX -> codesel -> AX 7086 | push ax ;new CS -> [SP] 7087 | if ?HDPMI 7088 | mov ax, offset psp_rou + 100h 7089 | add ax, offset endhdpmi 7090 | push ax 7091 | else 7092 | push offset psp_rou + 100h ;IP 7093 | endif 7094 | mov ax,0502h 7095 | mov bx,cs 7096 | retf 7097 | copy_to_psp_and_exit endp 7098 | 7099 | endif ;_COPY2PSP 7100 | endif ;?EXTLOAD 7101 | 7102 | doscall proc 7103 | if ?32BIT 7104 | pushfd 7105 | call fword ptr cs:[oldint21] 7106 | else 7107 | pushf 7108 | call dword ptr cs:[oldint21] 7109 | endif 7110 | ret 7111 | doscall endp 7112 | 7113 | dpmicall proc 7114 | push ax 7115 | if ?32BIT 7116 | pushfd 7117 | call fword ptr cs:[oldint31] 7118 | else 7119 | pushf 7120 | call dword ptr cs:[oldint31] 7121 | endif 7122 | jc @F 7123 | inc sp 7124 | inc sp 7125 | ret 7126 | @@: 7127 | if _SUPRESDOSERR_ 7128 | test cs:fMode, FMODE_NOERRDISP 7129 | jnz nodisp 7130 | endif 7131 | pusha 7132 | push ds 7133 | mov ds,cs:[wLdrDS] 7134 | ife ?32BIT 7135 | mov bp,sp 7136 | endif 7137 | mov di,offset dpmifunc 7138 | if ?32BIT 7139 | mov ax,[esp+2+16] 7140 | else 7141 | mov ax,[bp+2+16] ;display AX 7142 | endif 7143 | cmp ax,0203h ;not for this function 7144 | jz @F 7145 | call WORDOUT 7146 | mov di,offset dpmicaller 7147 | if ?32BIT 7148 | mov ax,[esp+2+18] 7149 | else 7150 | mov ax,[bp+2+18] ;display IP 7151 | endif 7152 | call WORDOUT 7153 | @strout_err szDpmiErr,1 7154 | @@: 7155 | pop ds 7156 | popa 7157 | nodisp: 7158 | add sp,2 7159 | stc 7160 | ret 7161 | dpmicall endp 7162 | 7163 | ;--- bin to ascii conversion 7164 | 7165 | if ?32BIT 7166 | DWORDOUT: 7167 | push eax 7168 | shr eax, 16 7169 | call WORDOUT 7170 | pop eax 7171 | endif 7172 | 7173 | ;*** bin2ascii(WORD in AX) (-> DS:DI) *** 7174 | 7175 | WORDOUT: 7176 | push ax 7177 | mov al,ah 7178 | call BYTEOUT 7179 | pop ax 7180 | BYTEOUT: 7181 | mov ah,al 7182 | shr al,4 7183 | call NIBOUT 7184 | mov al,ah 7185 | NIBOUT: 7186 | and al,0Fh 7187 | add al,'0' 7188 | cmp al,'9' 7189 | jle @F 7190 | add al,07h 7191 | @@: 7192 | mov [di],al 7193 | inc di 7194 | ret 7195 | 7196 | ;--- display routines 7197 | 7198 | printchar proc public 7199 | if ?32BIT 7200 | push ds 7201 | push ss 7202 | pop ds 7203 | push bx 7204 | push ecx 7205 | push edx 7206 | push eax 7207 | mov edx,esp 7208 | mov ecx,1 7209 | mov bx,2 ;stderr 7210 | mov ah,40h 7211 | int 21h 7212 | pop eax 7213 | pop edx 7214 | pop ecx 7215 | pop bx 7216 | pop ds 7217 | else 7218 | mov dl,al 7219 | mov ah,02 7220 | int 21h 7221 | endif 7222 | ret 7223 | printchar endp 7224 | 7225 | dpmildrout proc 7226 | pusha 7227 | if ?32BIT 7228 | @strout <"DPMILD32: "> 7229 | else 7230 | @strout <"DPMILD16: "> 7231 | endif 7232 | popa 7233 | ret 7234 | dpmildrout endp 7235 | 7236 | ;*** display string onto Stack 7237 | ;--- this is the standard output routine 7238 | 7239 | stroutstk_err: 7240 | call dpmildrout 7241 | ;fall throu 7242 | stroutstk proc public 7243 | if ?32BIT 7244 | push bx 7245 | mov bx,[esp+4] 7246 | else 7247 | push bp 7248 | mov bp,sp 7249 | push bx 7250 | mov bx,[bp+4] 7251 | endif 7252 | push ds 7253 | mov ds,cs:[wLdrDS] 7254 | call stroutBX 7255 | pop ds 7256 | pop bx 7257 | ife ?32BIT 7258 | pop bp 7259 | endif 7260 | ret 2 7261 | stroutstk endp 7262 | 7263 | ;*** display string (^BX) 7264 | ;--- this routine should be bimodal 7265 | 7266 | strout_err: 7267 | call dpmildrout 7268 | 7269 | stroutBX proc public uses ax dx 7270 | 7271 | nextchar: 7272 | mov al,[bx] 7273 | and al,al 7274 | jz done 7275 | cmp al,lf 7276 | jnz @F 7277 | mov al,cr 7278 | if _DBGOUT_ or _TRACE_ or ?DEBUG 7279 | @dbgout 7280 | else 7281 | call printchar 7282 | endif 7283 | mov al,lf 7284 | @@: 7285 | if _DBGOUT_ or _TRACE_ or ?DEBUG 7286 | @dbgout 7287 | else 7288 | call printchar 7289 | endif 7290 | inc bx 7291 | jmp nextchar 7292 | done: 7293 | ret 7294 | stroutBX endp 7295 | 7296 | ;*** display string (^ BX, length in CL) 7297 | 7298 | stroutBXn proc near uses dx 7299 | 7300 | @@: 7301 | mov al,[bx] 7302 | call printchar 7303 | inc bx 7304 | dec cl 7305 | jnz @B 7306 | ret 7307 | stroutBXn endp 7308 | 7309 | ;--- display module name of ES 7310 | 7311 | modnameout proc near 7312 | pusha 7313 | push ds 7314 | push es 7315 | pop ds 7316 | mov bx,offset NEHDR.szModPath 7317 | @stroutbx 7318 | pop ds 7319 | popa 7320 | ret 7321 | modnameout endp 7322 | 7323 | ;---------------------------------------------------------- 7324 | 7325 | include trace.inc 7326 | 7327 | ;--- check if int 21/4bh has been called by loader 7328 | ;--- possibly redundant 7329 | 7330 | if ?CHECKCALLER 7331 | checkcaller proc 7332 | push ds 7333 | push es 7334 | cld 7335 | push cs 7336 | pop ds 7337 | if ?32BIT 7338 | pushad 7339 | les edi,[esp+8*4+2*2+2] ;get cs:eip of caller 7340 | mov esi,offset ctxt 7341 | mov ecx,lctxt 7342 | repz cmps byte ptr [edi],[esi] 7343 | popad 7344 | else 7345 | pusha 7346 | mov bp,sp 7347 | mov si,offset ctxt 7348 | les di,[bp+8*2+2*2+2] 7349 | mov cx,lctxt 7350 | repz cmpsb 7351 | popa 7352 | endif 7353 | pop es 7354 | pop ds 7355 | ret 7356 | checkcaller endp 7357 | endif 7358 | 7359 | ;*** terminate program (int 21h, ah=4Ch) psp security check 7360 | ;*** search current psp in task list! 7361 | ;*** if task isn't found at all 7362 | ;*** then do nothing, route call to previous handler 7363 | ;*** if it wasn't the last task, 7364 | ;*** change tasks values in list 7365 | ;*** new 5.1.2004: dont compare selectors, but base addresses 7366 | 7367 | ;if ?MULTPSP 7368 | ;if _LOADERPARENT_ 7369 | 7370 | getpspr proc uses bx cx 7371 | mov bx,ax 7372 | mov ax,6 7373 | call dpmicall 7374 | mov ax,dx 7375 | shr ax,4 7376 | shl cx,12 7377 | or ax,cx 7378 | ret 7379 | getpspr endp 7380 | 7381 | checkpsp proc 7382 | pusha 7383 | push ds 7384 | mov ds,cs:[wLdrDS] 7385 | mov ah,51h 7386 | call doscall ;current PSP -> BX 7387 | mov ax,bx 7388 | call getpspr 7389 | mov bx,ax 7390 | @trace_s <"checkpsp: DOS psp is "> 7391 | @trace_w bx 7392 | @trace_s lf 7393 | if ?MULTPSP 7394 | mov si,[wTDStk] 7395 | lea di,[si-sizeof TASK] 7396 | nextitem: 7397 | cmp si,offset starttaskstk 7398 | jz error 7399 | sub si,size TASK 7400 | mov ax,[si].TASK.wPSP 7401 | if ?USE1PSP 7402 | and ax,ax 7403 | jnz @F 7404 | mov ax,wLdrPSP 7405 | @@: 7406 | endif 7407 | call getpspr 7408 | @trace_s <"checkpsp: compare with "> 7409 | @trace_w ax 7410 | @trace_s lf 7411 | cmp bx,ax 7412 | jz found 7413 | jmp nextitem 7414 | else 7415 | mov ax,[wRMPSP] 7416 | cmp bx,ax 7417 | jz found 7418 | endif 7419 | error: 7420 | @trace_s <"PSP not found, will route to previous handler",lf> 7421 | stc 7422 | jmp exit 7423 | found: 7424 | if ?DOS4G 7425 | cmp byte ptr [esp+2+0Eh+1],0FFh 7426 | jz allok 7427 | endif 7428 | if ?MULTPSP 7429 | cmp si,di ;is it the last task launched? 7430 | jz allok ;then nothing to do 7431 | mov cx,size TASK 7432 | @@: 7433 | lodsb 7434 | xchg al,[di] ;else exchange si and di 7435 | inc di 7436 | loop @B 7437 | endif 7438 | allok: 7439 | clc 7440 | exit: 7441 | pop ds 7442 | popa 7443 | ret 7444 | checkpsp endp 7445 | 7446 | 7447 | ;endif 7448 | ;endif 7449 | 7450 | _mycrout proc public 7451 | pusha 7452 | mov al,cr 7453 | call printchar 7454 | mov al,lf 7455 | call printchar 7456 | popa 7457 | ret 7458 | _mycrout endp 7459 | 7460 | getnum proc 7461 | xor dx,dx 7462 | next: 7463 | mov al, es:[di] 7464 | inc di 7465 | sub al, '0' 7466 | jc exit 7467 | cmp al, 9 7468 | ja exit 7469 | add dx, dx 7470 | mov cx, dx 7471 | shl dx, 2 7472 | add dx, cx 7473 | mov ah, 0 7474 | add dx, ax 7475 | jmp next 7476 | exit: 7477 | mov ax, dx 7478 | ret 7479 | getnum endp 7480 | 7481 | _TEXT ends 7482 | 7483 | ;------------------------------------------------------- 7484 | ;--- initialization routines, called during startup only 7485 | ;------------------------------------------------------- 7486 | 7487 | _ITEXT segment 7488 | 7489 | ;--- move loader in extended memory 7490 | 7491 | if ?EXTLOAD 7492 | 7493 | moveinextmem proc 7494 | push ds 7495 | @trace_s <"moveinextmem enter",lf> 7496 | xor bx,bx 7497 | mov cx,[wCSlim] ;alloc memory 7498 | inc cx 7499 | mov ax,0501h 7500 | int 31h 7501 | jc exit 7502 | @trace_s <"extload: high memory allocated",lf> 7503 | mov word ptr [dwMemHdl+0],di 7504 | mov word ptr [dwMemHdl+2],si 7505 | 7506 | mov word ptr [blkaddr+2],bx 7507 | mov word ptr [blkaddr+0],cx 7508 | mov dx,cx 7509 | mov cx,bx 7510 | mov bx,[aliassel] 7511 | 7512 | mov ax,0007h ;set base 7513 | int 31h 7514 | jc exit 7515 | @trace_s <"extload: set base ok",lf> 7516 | xor cx,cx 7517 | mov dx,[wCSlim] 7518 | mov ax,0008h ;set limit 7519 | int 31h 7520 | jc exit 7521 | @trace_s <"extload: set limit ok",lf> 7522 | 7523 | mov es,bx ;es now contains ext mem block 7524 | xor si,si ;copy CS:0 -> ES:0, size wCSlim 7525 | mov di,si 7526 | mov cx,wCSlim 7527 | inc cx 7528 | shr cx,1 7529 | cld 7530 | rep movsw 7531 | ;--- the loader has been copied to extended memory now 7532 | ;--- now CS should be switched to the new block (critical) 7533 | ;--- this requires attributes of current CS to change 7534 | if ?FASTCSCHANGE 7535 | mov ax,cs ;copy CS desc first 7536 | call CreateAlias ;descriptor BX -> AX 7537 | jc exit 7538 | else 7539 | mov cx,1 ;do it the safe way, get a temp sel 7540 | xor ax,ax ;alloc selector 7541 | int 31h 7542 | jc exit 7543 | @trace_s <"extload: alloc temp selector ok",lf> 7544 | call CreateAlias ;[BX] -> [AX], AX=Codesel 7545 | jc exit 7546 | @trace_s <"extload: CreateAlias ok",lf> 7547 | push ax 7548 | mov ax,cs 7549 | push offset nextsm ;switch to new CS 7550 | retf 7551 | nextsm: 7552 | call CreateAlias ;now original CS can be modified 7553 | jc exit 7554 | push bx 7555 | push ax 7556 | mov bx,cs 7557 | push offset nextsm2 7558 | retf 7559 | nextsm2: 7560 | @trace_s <"extload: nextsm2 reached",lf> 7561 | mov ax,0001 ;free temp selector 7562 | int 31h 7563 | pop bx 7564 | endif 7565 | if ?32BIT 7566 | push bx 7567 | mov ax,bx 7568 | mov cx,0FFFFh 7569 | mov dx,4000h ;set BIG-Bit of highmem data sel 7570 | call setaccrights 7571 | pop bx 7572 | endif 7573 | mov ss,bx ;set SS temporarily 7574 | 7575 | mov ax,ds 7576 | call CopyDescriptor ;copy DS (BX->AX) 7577 | push ds 7578 | pop ss ;now set SS permanently 7579 | @trace_s <"extload: ds ss copied",lf> 7580 | if _RESIZEPSP_ 7581 | ;--- size PSP + 20h bytes (for int2f rm) 7582 | if ?HDPMI 7583 | mov bx, [wResHDPMI] 7584 | else 7585 | mov bx, offset endoflowcode 7586 | mov al, bl 7587 | shr bx, 4 7588 | test al, 0Fh 7589 | jz @F 7590 | inc bx 7591 | @@: 7592 | endif 7593 | add bl,10h 7594 | mov dx,[wLdrPSP] 7595 | mov ax,0102h ;resize dos memory block 7596 | if _SUPRESDOSERR_ 7597 | or fMode, FMODE_NOERRDISP 7598 | endif 7599 | int 31h 7600 | jc exit 7601 | endif 7602 | @trace_s <"moveinextmem: move high ok, low DOS memory resized",lf> 7603 | or byte ptr fHighLoad,1 7604 | exit: 7605 | if _SUPRESDOSERR_ 7606 | and fMode, not FMODE_NOERRDISP 7607 | endif 7608 | pop ds 7609 | ret 7610 | moveinextmem endp 7611 | 7612 | endif 7613 | 7614 | if ?HDPMI 7615 | 7616 | ;--- this is for the standalone DPMILD32.BIN stub 7617 | ;--- runs in real-mode! 7618 | 7619 | inithdpmi proc 7620 | pusha 7621 | push ds 7622 | mov ah,51h 7623 | int 21h 7624 | mov es,bx ;HDPMI expects ES=PSP 7625 | add bx,10h 7626 | push bx 7627 | push 0 7628 | mov bp,sp 7629 | call far16 ptr [bp] 7630 | add sp,4 7631 | pop ds 7632 | mov [wResHDPMI],dx 7633 | mov ah,0 7634 | cmp al,4 7635 | cmc 7636 | popa 7637 | ret 7638 | inithdpmi endp 7639 | 7640 | endif 7641 | 7642 | ;*** load dpmi server HDPMI (still in real mode) 7643 | ;*** dont display traces in real mode! *** 7644 | 7645 | if ?SERVER 7646 | loadserver proc 7647 | pusha 7648 | mov bp,sp 7649 | 7650 | push ds 7651 | pop es 7652 | 7653 | ;----------------------------- build an exec param struct on stack (real mode) 7654 | mov cx,[wLdrPSP] 7655 | push cx 7656 | push offset 006Ch ;fcb2 7657 | push cx 7658 | push offset 005Ch ;fcb1 7659 | push ds 7660 | push offset nullstr ;dos command tail 7661 | push 0 ;environment segment 7662 | if ?KERNEL16 7663 | mov si,offset KernelNE.szModPath 7664 | else 7665 | mov si,offset segtable 7666 | endif 7667 | mov di,offset szModName ;copy filename 7668 | cld 7669 | nextchar0: 7670 | mov bx,di 7671 | nextchar: 7672 | lodsb 7673 | stosb 7674 | cmp al,00 7675 | jz donechar 7676 | cmp al,'\' 7677 | jz nextchar0 7678 | cmp al,'/' 7679 | jz nextchar0 7680 | jmp nextchar 7681 | donechar: 7682 | mov di,bx 7683 | mov si,offset HostName ;strcat filename to path (HDPMI..) 7684 | mov cx,SIZE_HOSTNAME 7685 | rep movsb 7686 | tryagain: 7687 | mov bx,sp 7688 | mov dx,offset szModName 7689 | mov ax,4b00h ;load dpmi server 7690 | int 21h 7691 | jc loadfailed 7692 | doneload: 7693 | mov sp,bp 7694 | popa 7695 | ret 7696 | loadfailed: 7697 | if ?STUB 7698 | mov di,offset szName 7699 | mov si,offset HostName 7700 | mov cx,SIZE_HOSTNAME 7701 | rep movsb 7702 | call ScanPath 7703 | jc @F 7704 | mov bx,ax 7705 | mov ah,3Eh 7706 | int 21h 7707 | push ds 7708 | pop es 7709 | jmp tryagain 7710 | @@: 7711 | mov dx,offset szModName 7712 | endif 7713 | ; call checkoutoffh 7714 | ; jc tryagain 7715 | if ?SLOADERR 7716 | mov bx,offset errstr26 ;"cannot load " 7717 | @strout_err 7718 | mov bx,dx ;hdpmi path 7719 | @stroutbx 7720 | @cr_out 7721 | xor ax,ax 7722 | call stroutax 7723 | endif 7724 | jmp doneload 7725 | 7726 | loadserver endp 7727 | 7728 | endif 7729 | 7730 | if ?LOADDBGDLL 7731 | loaddbg proc 7732 | test bEnvFlgs2, ENVFL2_LOADDBGOUT 7733 | jz done 7734 | @pusha 7735 | @trace_s <"trying to load debugout.dll",lf> 7736 | or byte ptr [wErrMode+1],HBSEM_NOOPENFILEBOX 7737 | mov ax,offset szDbgout 7738 | if ?32BIT 7739 | movzx eax,ax 7740 | endif 7741 | mov dx,ds 7742 | call LoadModule16 7743 | jc @F 7744 | mov es,ax 7745 | mov hModDbg,ax 7746 | call CallLibEntry 7747 | @@: 7748 | and byte ptr [wErrMode+1],not HBSEM_NOOPENFILEBOX 7749 | @popa 7750 | done: 7751 | ret 7752 | loaddbg endp 7753 | endif 7754 | 7755 | ;--- set vector for int 21h in protected mode 7756 | 7757 | setvec21 proc 7758 | pusha 7759 | mov bl,21h 7760 | mov cx,cs 7761 | if ?32BIT 7762 | mov edx, offset int21proc 7763 | else 7764 | mov dx, offset int21proc 7765 | endif 7766 | mov ax,0205h ;set Int 21 PM vector 7767 | call dpmicall 7768 | popa 7769 | ret 7770 | setvec21 endp 7771 | 7772 | 7773 | ;*** read command line parameter 7774 | ;*** will be called for 1. task only 7775 | ;*** set exec parameter block (int 21,4b) 7776 | ;*** RC: Carry if error 7777 | ;*** else: module name in szPgmName 7778 | ;*** parameter block in ParmBlk 7779 | 7780 | GetPgmParms proc uses ds 7781 | push ds 7782 | pop es ;es=DGROUP 7783 | @trace_s <"GetPgmParms enter",lf> 7784 | if ?STUB 7785 | if ?KERNEL16 7786 | mov si,offset KernelNE.szModPath 7787 | else 7788 | mov si,offset segtable 7789 | endif 7790 | mov di,offset szPgmName 7791 | @@: 7792 | lodsb 7793 | stosb 7794 | and al,al 7795 | jnz @B 7796 | mov si,0080h 7797 | mov ds,[wLdrPSP] 7798 | else 7799 | mov fCmdLOpt,0 7800 | mov ds,[wLdrPSP] 7801 | mov si,0080h 7802 | test cs:[fMode],FMODE_OVERLAY ;loaded as overlay? 7803 | jnz gpp_1 ;then PSP is ok 7804 | mov di,offset szPgmName 7805 | sub cx,cx 7806 | mov cl,[si] ;get parameter line 7807 | inc si 7808 | jcxz error 7809 | mov ah,0 7810 | nextws: 7811 | lodsb 7812 | if ?32BIT 7813 | cmp al,'-' 7814 | jnz @F 7815 | mov ah,al 7816 | jmp skipcharx 7817 | @@: 7818 | endif 7819 | cmp al,' ' ;skip spaces 7820 | jnz parmfound 7821 | skipcharx: 7822 | loop nextws 7823 | error: 7824 | mov ax,offset errstr8 ;"filename missing or invalid" 7825 | stc 7826 | ret 7827 | parmfound: 7828 | if ?32BIT 7829 | and ah,ah 7830 | jz nooption 7831 | or al,20h 7832 | cmp al,'g' 7833 | jnz error 7834 | or es:[fCmdLOpt], FO_GUI 7835 | mov ah,0 7836 | jmp skipcharx 7837 | nooption: 7838 | endif 7839 | dec si 7840 | mov dl,0 7841 | nextchar: 7842 | lodsb 7843 | cmp al,'"' 7844 | jnz @F 7845 | xor ah,1 7846 | jmp skipchar 7847 | @@: 7848 | test ah,1 7849 | jnz @F 7850 | cmp al,' ' 7851 | jz copydone ;copy is done 7852 | @@: 7853 | cmp al,'.' 7854 | jnz @F 7855 | inc dl 7856 | @@: 7857 | stosb 7858 | cmp al,'/' 7859 | jz @F 7860 | cmp al,'\' 7861 | jnz skipchar 7862 | @@: 7863 | mov dl,0 7864 | skipchar: 7865 | loop nextchar 7866 | copydone: 7867 | test ah,1 7868 | jnz error 7869 | and dl,dl ;file extension supplied? 7870 | jnz @F 7871 | @trace_s <"'.EXE' added to module name",lf> 7872 | mov ax,'E.' 7873 | stosw 7874 | mov ax,'EX' 7875 | stosw 7876 | @@: 7877 | mov al,00 7878 | stosb 7879 | 7880 | ;------------------- copy rest of parameter line to psp cmd tail 7881 | 7882 | push es 7883 | push ds 7884 | pop es 7885 | mov di, 80h 7886 | push di 7887 | mov al,cl 7888 | stosb 7889 | dec si 7890 | inc cl ; copy 0D at least 7891 | rep movsb 7892 | pop si 7893 | pop es 7894 | gpp_1: 7895 | endif ;?STUB 7896 | 7897 | mov di,offset ParmBlk 7898 | if ?32BIT 7899 | movzx eax,si 7900 | stosd ;cmdline 7901 | mov ax,ds 7902 | stosd 7903 | xor eax,eax ;fcb1+fcb2 7904 | stosd 7905 | stosd 7906 | stosd 7907 | stosd 7908 | else 7909 | xor ax,ax 7910 | stosw ;environment (nur bei 16 Bit) 7911 | mov ax,si 7912 | stosw ;cmdline 7913 | mov ax,ds 7914 | stosw 7915 | xor ax,ax ;fcb1+fcb2 7916 | stosw 7917 | stosw 7918 | stosw 7919 | stosw 7920 | endif 7921 | clc 7922 | ret 7923 | GetPgmParms endp 7924 | 7925 | 7926 | changememstrat proc 7927 | mov ax,5802h ;save umb link state 7928 | int 21h 7929 | xor ah,ah 7930 | mov word ptr [blksize+0],ax 7931 | mov ax,5800h ;save memory alloc strategie 7932 | int 21h 7933 | xor ah,ah 7934 | mov word ptr [blksize+2],ax 7935 | mov ax,5803h ;set umb link state 7936 | mov bx,0001h 7937 | int 21h 7938 | mov ax,5801h ;set "fit best" strategy 7939 | mov bx,0081h ;first high, then low 7940 | int 21h 7941 | ret 7942 | changememstrat endp 7943 | 7944 | restorememstrat proc 7945 | mov bx,word ptr [blksize+2] 7946 | mov ax,5801h ;memory alloc strat restore 7947 | int 21h 7948 | mov bx,word ptr [blksize+0] 7949 | mov ax,5803h ;umb link restore 7950 | int 21h 7951 | ret 7952 | restorememstrat endp 7953 | 7954 | ;*** JumpToPM 7955 | ;--- returns C on errors, bx->error msg 7956 | 7957 | JumpToPM proc 7958 | call changememstrat 7959 | if ?SERVER 7960 | mov cx,1 7961 | endif 7962 | JumpToPM_1: 7963 | push cx 7964 | mov ax,1687h ;get address of PM entry in ES:DI 7965 | int 2Fh 7966 | pop cx 7967 | mov bp,offset szNoDPMI ;message "no dpmi server" 7968 | if ?32BIT 7969 | and ax,ax ;ax=0 -> DPMI server installed 7970 | jnz JumpToPM_2 7971 | mov bp,offset szNo32Bit ;message "no 32 bit apps supported" 7972 | test bl,1 7973 | jnz JumpToPM_3 ;jmp if ok 7974 | else 7975 | and ax,ax 7976 | jz JumpToPM_3 ;ok, DPMI host found 7977 | endif 7978 | JumpToPM_2: 7979 | if ?SERVER 7980 | mov ax,bp 7981 | if ?DEBUG 7982 | and cx,cx 7983 | jz ERROR0 7984 | else 7985 | jcxz ERROR0 ;just try 2 times, else error 7986 | endif 7987 | call loadserver ;try to load HDPMIxx 7988 | xor cx,cx 7989 | jmp JumpToPM_1 ;try a second time 7990 | else 7991 | if ?HDPMI 7992 | call inithdpmi 7993 | jnc JumpToPM_1 7994 | endif 7995 | mov ax,bp 7996 | jmp ERROR0 7997 | endif 7998 | JumpToPM_3: 7999 | push es 8000 | push di 8001 | test si,si 8002 | jz @F 8003 | mov bx,si 8004 | mov ah,48h ;alloc real-mode mem block 8005 | int 21h 8006 | jc ERROR1 8007 | mov es,ax 8008 | @@: 8009 | call restorememstrat 8010 | if ?32BIT 8011 | mov ax,0001 8012 | else 8013 | xor ax,ax 8014 | endif 8015 | mov bp,sp 8016 | call dword ptr [bp] 8017 | mov ax,offset errstr3 ;cannot switch to prot-mode 8018 | jc ERROR3 8019 | @int3 _INT03JMPPM_ 8020 | mov [wLdrDS],ds 8021 | mov [wDPMIFlg],cx ;DPMI Flags 8022 | mov [wDPMIVer],dx ;dito 8023 | mov [wLdrPSP],es ;psp 8024 | if 1;?USE1PSP 8025 | mov [wCurPSP],es 8026 | endif 8027 | if ?32BIT 8028 | movzx eax,ax 8029 | movzx ebx,bx 8030 | movzx ecx,cx 8031 | movzx edx,dx 8032 | movzx esi,si 8033 | movzx edi,di 8034 | endif 8035 | @trace_s 8036 | @trace_s <"DPMILDxx now in protected mode, PSP="> 8037 | @trace_w es 8038 | @trace_s <",CS="> 8039 | @trace_w cs 8040 | @trace_s <",SS="> 8041 | @trace_w ss 8042 | @trace_s <",DS="> 8043 | @trace_w ds 8044 | @trace_s 8045 | add sp,4 8046 | ret 8047 | ERROR1: 8048 | mov ax,offset errstr2 ;insufficient DOS memory 8049 | ERROR3: 8050 | add sp,4 8051 | ERROR0: 8052 | push ax 8053 | call restorememstrat 8054 | pop bx 8055 | stc 8056 | ret 8057 | JumpToPM endp 8058 | 8059 | ;*** global constructor *** 8060 | 8061 | InitProtMode proc 8062 | 8063 | @trace_s <"enter initialize PM",lf> 8064 | 8065 | mov bl,21h ;get int 21 PM vector 8066 | mov ax,0204h ;get pm int 8067 | int 31h 8068 | if ?32BIT 8069 | mov dword ptr [oldint21+0],edx 8070 | mov word ptr [oldint21+4],cx 8071 | else 8072 | mov word ptr [oldint21+0],dx 8073 | mov word ptr [oldint21+2],cx 8074 | endif 8075 | mov bl,31h ;get int 31 PM vector 8076 | int 31h 8077 | if ?32BIT 8078 | mov dword ptr [oldint31+0],edx 8079 | mov word ptr [oldint31+4],cx 8080 | else 8081 | mov word ptr [oldint31+0],dx 8082 | mov word ptr [oldint31+2],cx 8083 | endif 8084 | if ?DEBUG 8085 | mov bl,41h 8086 | int 31h 8087 | if ?32BIT 8088 | mov dword ptr [oldint41+0],edx 8089 | mov word ptr [oldint41+4],cx 8090 | mov edx,offset myint41 8091 | else 8092 | mov word ptr [oldint41+0],dx 8093 | mov word ptr [oldint41+2],cx 8094 | mov dx,offset myint41 8095 | endif 8096 | mov al,5 8097 | mov cx,cs 8098 | int 31h 8099 | endif 8100 | 8101 | if _SETCSLIM_ 8102 | mov bx,cs 8103 | xor cx,cx 8104 | mov dx,[wCSlim] 8105 | mov ax,0008h ;set limit 8106 | int 31h 8107 | endif 8108 | if _SETDSLIM_ 8109 | mov bx,ds 8110 | xor cx,cx 8111 | mov dx,[wCSlim] 8112 | mov ax,0008h ;set limit 8113 | int 31h 8114 | endif 8115 | mov cx,0001 ;get a selector for ALIAS segments 8116 | mov ax,0000 8117 | int 31h 8118 | jc initprex 8119 | mov [aliassel],ax 8120 | ;--- for 32bit clients: clear bits FF00h (dosemu + cwsdpmi) 8121 | if ?DOSEMUSUPP 8122 | if ?32BIT 8123 | mov bx,ax 8124 | lar cx,ax 8125 | shr cx,8 8126 | mov ax,0009 ;set acc rights 8127 | int 31h 8128 | endif 8129 | endif 8130 | 8131 | if ?EXTLOAD 8132 | test bEnvFlgs,ENVFL_DONTLOADHIGH 8133 | jnz @F 8134 | cmp byte ptr wVersion,20 ;not for OS/2 8135 | jnb @F 8136 | if 0;?DOSEMUSUPP 8137 | test fMode, FMODE_DOSEMU ;not for DOSEMU 8138 | jnz @F 8139 | endif 8140 | call moveinextmem ;move ldr Code/Data in extended memory 8141 | @@: 8142 | endif 8143 | if ?PESUPP 8144 | call InitPELoader 8145 | endif 8146 | if _TRAPEXC0D_ 8147 | mov bl,0Dh 8148 | mov ax,0202h ;get Exception 0D 8149 | int 31h 8150 | if ?32BIT 8151 | mov dword ptr oldexc0D+0,edx 8152 | mov word ptr oldexc0D+4,cx 8153 | mov edx, offset LEXC0D 8154 | else 8155 | mov word ptr oldexc0D+0,dx 8156 | mov word ptr oldexc0D+2,cx 8157 | mov dx, offset LEXC0D 8158 | endif 8159 | mov cx,cs 8160 | call setexc 8161 | jc initprex 8162 | endif 8163 | if ?EXC01RESET 8164 | mov bl,01h 8165 | mov ax,0202h ;get Exception 01 8166 | int 31h 8167 | if ?32BIT 8168 | mov dword ptr oldexc01+0,edx 8169 | mov word ptr oldexc01+4,cx 8170 | else 8171 | mov word ptr oldexc01+2,dx 8172 | mov word ptr oldexc01+2,cx 8173 | endif 8174 | endif 8175 | 8176 | initprex: 8177 | ret 8178 | InitProtMode endp 8179 | 8180 | _ITEXT ends 8181 | 8182 | end main 8183 | 8184 | --------------------------------------------------------------------------------