From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/DOS/EXEC.ASM | 931 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 931 insertions(+) create mode 100644 v4.0/src/DOS/EXEC.ASM (limited to 'v4.0/src/DOS/EXEC.ASM') diff --git a/v4.0/src/DOS/EXEC.ASM b/v4.0/src/DOS/EXEC.ASM new file mode 100644 index 0000000..aa120c2 --- /dev/null +++ b/v4.0/src/DOS/EXEC.ASM @@ -0,0 +1,931 @@ +; SCCSID = @(#)exec.asm 1.3 85/08/13 +; SCCSID = @(#)exec.asm 1.3 85/08/13 +; AN000 version 4.0 jan. 1988 +; A007 PTM 3957 - fake vesrion for IBMCACHE.COM +; A008 PTM 4070 - fake version for MS WINDOWS + +SUBTTL $exec - load/go a program +PAGE +; +; Assembler usage: +; LDS DX, name +; LES BX, blk +; MOV AH, Exec +; MOV AL, func +; INT int_command +; +; AL Function +; -- -------- +; 0 Load and execute the program. +; 1 Load, create the program header but do not +; begin execution. +; 3 Load overlay. No header created. +; +; AL = 0 -> load/execute program +; +; +---------------------------+ +; | WORD segment address of | +; | environment. | +; +---------------------------+ +; | DWORD pointer to ASCIZ | +; | command line at 80h | +; +---------------------------+ +; | DWORD pointer to default | +; | FCB to be passed at 5Ch | +; +---------------------------+ +; | DWORD pointer to default | +; | FCB to be passed at 6Ch | +; +---------------------------+ +; +; AL = 1 -> load program +; +; +---------------------------+ +; | WORD segment address of | +; | environment. | +; +---------------------------+ +; | DWORD pointer to ASCIZ | +; | command line at 80h | +; +---------------------------+ +; | DWORD pointer to default | +; | FCB to be passed at 5Ch | +; +---------------------------+ +; | DWORD pointer to default | +; | FCB to be passed at 6Ch | +; +---------------------------+ +; | DWORD returned value of | +; | CS:IP | +; +---------------------------+ +; | DWORD returned value of | +; | SS:IP | +; +---------------------------+ +; +; AL = 3 -> load overlay +; +; +---------------------------+ +; | WORD segment address where| +; | file will be loaded. | +; +---------------------------+ +; | WORD relocation factor to | +; | be applied to the image. | +; +---------------------------+ +; +; Returns: +; AX = error_invalid_function +; = error_bad_format +; = error_bad_environment +; = error_not_enough_memory +; = error_file_not_found +; +; Revision history: +; +; A000 version 4.00 Jan. 1988 +; +include EA.INC +include version.inc + + I_Need Temp_Var2,WORD ;AN000;file type from $open + I_Need Special_Entries,WORD ;AN007;address of special entries + I_Need Special_Version,WORD ;AN007;special version number + I_Need Fake_Count,BYTE ;AN008;fake version count + +IF BUFFERFLAG + extrn restore_user_map:near +ENDIF + +TABLE SEGMENT + +exec_init_SP DW ? +exec_init_SS DW ? +exec_init_IP DW ? +exec_init_CS DW ? + +exec_internal_buffer EQU OpenBuf + +exec_signature DW ? ; must contain 4D5A (yay zibo!) +exec_len_mod_512 DW ? ; low 9 bits of length +exec_pages DW ? ; number of 512b pages in file +exec_rle_count DW ? ; count of reloc entries +exec_par_dir DW ? ; number of paragraphs before image +exec_min_BSS DW ? ; minimum number of para of BSS +exec_max_BSS DW ? ; max number of para of BSS +exec_SS DW ? ; stack of image +exec_SP DW ? ; SP of image +exec_chksum DW ? ; checksum of file (ignored) +exec_IP DW ? ; IP of entry +exec_CS DW ? ; CS of entry +exec_rle_table DW ? ; byte offset of reloc table +Exec_header_len EQU $-Exec_Signature + +exec_internal_buffer_size EQU (128+128+53+curdirLEN) +%out Please make sure that the following are contiguous and of the +%out following sizes: +%out +%out OpenBuf 128 +%out RenBuf 128 +%out SearchBuf 53 +%out DummyCDS CurDirLen + +TABLE ENDS + +.sall + +procedure $Exec,NEAR + ASSUME DS:NOTHING, ES:NOTHING +PUBLIC EXEC001S,EXEC001E +EXEC001S: + LocalVar exec_blk,DWORD + LocalVar exec_func,BYTE + LocalVar exec_load_high,BYTE + LocalVar exec_fh,WORD + LocalVar exec_rel_fac,WORD + LocalVar exec_res_len_para,WORD + LocalVar exec_environ,WORD + LocalVar exec_size,WORD + LocalVar exec_load_block,WORD + LocalVar exec_dma,WORD + LocalVar execNameLen,WORD + LocalVar execName,DWORD +EXEC001E: + Enter +; +; validate function +; + + CMP AL,3 ; only 0, 1 or 3 are allowed + JNA exec_check_2 + +exec_bad_fun: + MOV EXTERR_LOCUS,errLOC_Unk ; Extended Error Locus + mov al,error_invalid_function + +exec_ret_err: + Leave + transfer SYS_RET_ERR + +exec_check_2: + CMP AL,2 + JZ exec_bad_fun + + MOV exec_blkL,BX ; stash args + MOV exec_blkH,ES + MOV exec_func,AL + MOV exec_load_high,0 +; +; set up length of exec name +; + MOV execNameL,DX + MOV execNameH,DS + MOV SI,DX ; move pointer to convenient place + invoke DStrLen + MOV ExecNameLen,CX ; save length + + XOR AL,AL ; open for reading + PUSH BP + invoke $OPEN ; is the file there? + POP BP + JC exec_ret_err +;File Type Checking +; CMP BYTE PTR [Temp_Var2],EAEXISTING ;AN000;;FT. old file ? +; JZ oldexf ;AN000;;FT. yes +; TEST BYTE PTR EXEC_FUNC,EXEC_FUNC_OVERLAY ;AN000;;FT. exec overlay? +; JNZ exovrly ;AN000;;FT. yes +; CMP BYTE PTR [Temp_Var2],EAEXECUTABLE ;AN000;;FT. only file type +; JZ oldexf ;AN000;;FT. 3 & 4 will pass +; CMP BYTE PTR [Temp_Var2],EAINSTALLABLE ;AN000;;FT. +; JZ oldexf ;AN000;;FT. +;exerr: ;AN000;;FT. +; MOV AL,error_access_denied ;AN000;;FT. error +; JMP exec_ret_err ;AN000;;FT. +;exovrly: ;AN000;;FT. +; CMP BYTE PTR [Temp_Var2],EAOVERLAY ;AN000;;FT. only 5,6,7 pass +; JZ oldexf ;AN000;;FT. +; CMP BYTE PTR [Temp_Var2],EADEV_DRIVER ;AN000;;FT. +; JZ oldexf ;AN000;;FT. +; CMP BYTE PTR [Temp_Var2],EAIFS_DRIVER ;AN000;;FT. +; JNZ exerr ;AN000;;FT. +; +;oldexf: ;AN000; +;File Type Checking + + MOV exec_fh,AX + MOV BX,AX + XOR AL,AL + invoke $IOCTL + JC Exec_bombJ + TEST DL,devid_ISDEV + JZ exec_check_environ + MOV AL,error_file_not_found +Exec_bombJ: + JMP Exec_Bomb + +BadEnv: + MOV AL,error_bad_environment + JMP exec_bomb + +exec_check_environ: + MOV exec_load_block,0 + MOV exec_environ,0 + + TEST BYTE PTR exec_func,exec_func_overlay ; overlays... no environment + JNZ exec_read_header + LDS SI,exec_blk ; get block + MOV AX,[SI].Exec1_environ ; address of environ + OR AX,AX + JNZ exec_scan_env + MOV DS,CurrentPDB + MOV AX,DS:[PDB_environ] + MOV exec_environ,AX + OR AX,AX + JZ exec_read_header + +exec_scan_env: + MOV ES,AX + XOR DI,DI + MOV CX,07FFFh ; at most 32k of environment + XOR AL,AL + +exec_get_environ_len: + REPNZ SCASB ; find that nul byte + JNZ BadEnv + DEC CX ; Dec CX for the next nul byte test + JB BadEnv ; gone beyond the end of the environment + SCASB ; is there another nul byte? + JNZ exec_get_environ_len ; no, scan some more + PUSH DI + LEA BX,[DI+0Fh+2] + ADD BX,ExecNameLen ; BX <- length of environment + ; remember argv[0] length + ; round up and remember argc + MOV CL,4 + SHR BX,CL ; number of paragraphs needed + PUSH ES + invoke $ALLOC ; can we get the space? + POP DS + POP CX + JNC exec_save_environ + JMP exec_no_mem ; nope... cry and sob + +exec_save_environ: + MOV ES,AX + MOV exec_environ,AX ; save him for a rainy day + XOR SI,SI + MOV DI,SI + REP MOVSB ; copy the environment + MOV AX,1 + STOSW + LDS SI,execName + MOV CX,execNameLen + REP MOVSB + +exec_read_header: +; +; We read in the program header into the above data area and determine +; where in this memory the image will be located. +; + Context DS + MOV CX,exec_header_len ; header size + MOV DX,OFFSET DOSGROUP:exec_signature + PUSH ES + PUSH DS + CALL ExecRead + POP DS + POP ES + JC exec_bad_file + OR AX,AX + JZ exec_bad_file + CMP AX,exec_header_len ; did we read the right number? + JNZ exec_com_filej ; yep... continue + TEST exec_max_BSS,-1 ; indicate load high? + JNZ exec_check_sig + MOV exec_load_high,-1 +exec_check_sig: + MOV AX,exec_signature + CMP AX,exe_valid_signature ; zibo arises! + JZ exec_save_start ; assume com file if no signature + CMP AX,exe_valid_old_signature ; zibo arises! + JZ exec_save_start ; assume com file if no signature + +exec_com_filej: + JMP exec_com_file + +; +; We have the program header... determine memory requirements +; +exec_save_start: + MOV AX,exec_pages ; get 512-byte pages + MOV CL,5 ; convert to paragraphs + SHL AX,CL + SUB AX,exec_par_dir ; AX = size in paragraphs + MOV exec_res_len_para,AX + +; +; Do we need to allocate memory? Yes if function is not load-overlay +; + TEST BYTE PTR exec_func,exec_func_overlay + JZ exec_allocate ; allocation of space +; +; get load address from block +; + LES DI,exec_blk + MOV AX,ES:[DI].exec3_load_addr + MOV exec_dma,AX + MOV AX,ES:[DI].exec3_reloc_fac + MOV exec_rel_fac,AX +IF DEBUG + JMP exec_find_res +ELSE + JMP SHORT exec_find_res +ENDIF + +exec_no_mem: + MOV AL,error_not_enough_memory + JMP SHORT exec_bomb + +exec_bad_file: + MOV AL,error_bad_format + +exec_bomb: + ASSUME DS:NOTHING,ES:NOTHING + MOV BX,exec_fh + CALL exec_dealloc + LeaveCrit CritMem + SaveReg + invoke $CLOSE + RestoreReg + JMP Exec_Ret_Err + +exec_allocate: + DOSAssume CS,,"EXEC/exec_allocate" + PUSH AX + MOV BX,0FFFFh ; see how much room in arena + PUSH DS + invoke $ALLOC ; should have carry set and BX has max + POP DS + POP AX + ADD AX,10h ; room for header + CMP BX,11h ; enough room for a header + JB exec_no_mem + CMP AX,BX ; is there enough for bare image? + JA exec_no_mem + TEST exec_load_high,-1 ; if load high, use max + JNZ exec_BX_max ; use max + ADD AX,exec_min_BSS ; go for min allocation + JC exec_no_mem ; oops! carry + CMP AX,BX ; enough space? + JA exec_no_mem ; nope... + SUB AX,exec_min_BSS + ADD AX,exec_max_BSS ; go for the MAX + JC exec_BX_max + CMP AX,BX + JBE exec_got_block + +exec_BX_max: + MOV AX,BX + +exec_got_block: + PUSH DS + MOV BX,AX + MOV exec_size,BX + invoke $ALLOC ; get the space + POP DS + JC exec_no_mem + MOV exec_load_block,AX + ADD AX,10h + TEST exec_load_high,-1 + JZ exec_use_ax ; use ax for load info + ADD AX,exec_size ; go to end + SUB AX,exec_res_len_para ; drop off header + SUB AX,10h ; drop off pdb +exec_use_ax: + MOV exec_rel_fac,AX ; new segment + MOV exec_dma,AX ; beginning of dma + +; +; Determine the location in the file of the beginning of the resident +; +exec_find_res: + MOV DX,exec_par_dir + PUSH DX + MOV CL,4 + SHL DX,CL ; low word of location + POP AX + MOV CL,12 + SHR AX,CL ; high word of location + MOV CX,AX ; CX <- high + +; +; Read in the resident image (first, seek to it) +; + MOV BX,exec_fh + PUSH DS + XOR AL,AL + invoke $LSEEK ; seek to resident + POP DS + jnc exec_big_read + jmp exec_bomb + +exec_big_read: ; Read resident into memory + MOV BX,exec_res_len_para + CMP BX,1000h ; too many bytes to read? + JB exec_read_ok + MOV BX,0FE0h ; max in one chunk FE00 bytes + +exec_read_ok: + SUB exec_res_len_para,BX ; we read (soon) this many + PUSH BX + MOV CL,4 + SHL BX,CL ; get count in bytes from paras + MOV CX,BX ; count in correct register + PUSH DS + MOV DS,exec_dma ; Set up read buffer + ASSUME DS:NOTHING + XOR DX,DX + PUSH CX ; save our count + CALL ExecRead + POP CX ; get old count to verify + POP DS + JC exec_bad_fileJ + DOSAssume CS,,"EXEC/exec_read_ok" + CMP CX,AX ; did we read enough? + POP BX ; get paragraph count back + JZ execCheckEnd ; and do reloc if no more to read +; +; The read did not match the request. If we are off by 512 bytes or more +; then the header lied and we have an error. +; + SUB CX,AX + CMP CX,512 + JAE Exec_Bad_fileJ +; +; We've read in CX bytes... bump DTA location +; +ExecCheckEnd: + ADD exec_dma,BX ; bump dma address + TEST exec_res_len_para,-1 + JNZ exec_big_read +; +; The image has now been read in. We must perform relocation to +; the current location. +; +exec_do_reloc: + MOV CX,exec_rel_fac + MOV AX,exec_SS ; get initial SS + ADD AX,CX ; and relocate him + MOV exec_init_SS,AX + + MOV AX,exec_SP ; initial SP + MOV exec_init_SP,AX + + LES AX,DWORD PTR exec_IP + MOV exec_init_IP,AX + MOV AX,ES + ADD AX,CX ; relocated... + MOV exec_init_CS,AX + + XOR CX,CX + MOV DX,exec_rle_table + MOV BX,exec_fh + PUSH DS + XOR AX,AX + invoke $LSEEK + POP DS + + JNC exec_get_entries +exec_bad_filej: + JMP exec_bad_file + +exec_get_entries: + MOV DX,exec_rle_count ; Number of entries left + +exec_read_reloc: + ASSUME DS:NOTHING + PUSH DX + MOV DX,OFFSET DOSGROUP:exec_internal_buffer + MOV CX,((exec_internal_buffer_size)/4)*4 + PUSH DS + CALL ExecRead + POP ES + POP DX + JC exec_bad_filej + MOV CX,(exec_internal_buffer_size)/4 + MOV DI,OFFSET DOSGROUP:exec_internal_buffer ; Pointer to byte location in header +; +; Relocate a single address +; + MOV SI,exec_rel_fac + +exec_reloc_one: + OR DX,DX ; Any more entries? + JE exec_set_PDBJ + +exec_get_addr: + LDS BX,DWORD PTR ES:[DI] ; Get ra/sa of entry + MOV AX,DS ; Relocate address of item + ADD AX,SI + MOV DS,AX + ADD [BX],SI + ADD DI,4 + DEC DX + LOOP exec_reloc_one ; End of internal buffer? + +; +; We've exhausted a single buffer's worth. Read in the next piece +; of the relocation table. +; + + PUSH ES + POP DS + JMP exec_read_reloc + +exec_set_PDBJ: + JMP exec_set_PDB + +exec_no_memj: + JMP exec_no_mem + +; +; we have a .COM file. First, determine if we are merely loading an overlay. +; +exec_com_file: + TEST BYTE PTR exec_func,exec_func_overlay + JZ exec_alloc_com_file + LDS SI,exec_blk ; get arg block + LODSW ; get load address + MOV exec_dma,AX + MOV AX,0FFFFh + JMP SHORT exec_read_block ; read it all! + +; We must allocate the max possible size block (ick!) and set up +; CS=DS=ES=SS=PDB pointer, IP=100, SP=max size of block. +; +exec_alloc_com_file: + MOV BX,0FFFFh + invoke $ALLOC ; largest piece available as error + OR BX,BX + JZ exec_no_memj + MOV exec_size,BX ; save size of allocation block + PUSH BX + invoke $ALLOC ; largest piece available as error + POP BX ; get size of block... + MOV exec_load_block,AX + ADD AX,10h ; increment for header + MOV exec_dma,AX + XOR AX,AX ; presume 64K read... + CMP BX,1000h ; 64k or more in block? + JAE exec_read_com ; yes, read only 64k + MOV AX,BX ; convert size to bytes + MOV CL,4 + SHL AX,CL +exec_read_com: + SUB AX,100h ; remember size of psp +exec_read_block: + PUSH AX ; save number to read + MOV BX,exec_fh ; of com file + XOR CX,CX ; but seek to 0:0 + MOV DX,CX + XOR AX,AX ; seek relative to beginning + invoke $LSEEK ; back to beginning of file + POP CX ; number to read + MOV DS,exec_dma + XOR DX,DX + PUSH CX + CALL ExecRead + POP SI ; get number of bytes to read + jnc OkRead + jmp exec_bad_file +OkRead: + CMP AX,SI ; did we read them all? + JZ exec_no_memj ; exactly the wrong number... no memory + TEST BYTE PTR exec_func,exec_func_overlay + JNZ exec_set_PDB ; no starto, chumo! + MOV AX,exec_DMA + SUB AX,10h + MOV exec_init_CS,AX + MOV exec_init_IP,100h ; initial IP is 100 +; +; SI is at most FF00h. Add FE to account for PSP - word of 0 on stack. +; + ADD SI,0FEh ; make room for stack + MOV exec_init_SP,SI ; max value for read is also SP! + MOV exec_init_SS,AX + MOV DS,AX + MOV WORD PTR [SI],0 ; 0 for return + +exec_set_PDB: + MOV BX,exec_fh ; we are finished with the file. + CALL exec_dealloc + PUSH BP + invoke $CLOSE ; release the jfn + POP BP + CALL exec_alloc + TEST BYTE PTR exec_func,exec_func_overlay + JZ exec_build_header + CALL Scan_Execname ;MS.;AN007; + CALL Scan_Special_Entries ;MS.;AN007; + Leave + transfer SYS_RET_OK ; overlay load -> done + +exec_build_header: + MOV DX,exec_load_block +; +; assign the space to the process +; + + MOV SI,arena_owner ; pointer to owner field + + MOV AX,exec_environ ; get environ pointer + OR AX,AX + JZ NO_OWNER ; no environment + DEC AX ; point to header + MOV DS,AX + MOV [SI],DX ; assign ownership +NO_OWNER: + MOV AX,exec_load_block ; get load block pointer + DEC AX + MOV DS,AX ; point to header + MOV [SI],DX ; assign ownership + + PUSH DS ;AN000;MS. make ES=DS + POP ES ;AN000;MS. + MOV DI,ARENA_NAME ;AN000;MS. ES:DI points to destination + CALL Scan_Execname ;AN007;MS. parse execname + ; ds:si->name, cx=name length + PUSH CX ;AN007;;MS. save for fake version + PUSH SI ;AN007;;MS. save for fake version + +movename: ;AN000; + LODSB ;AN000;;MS. get char + CMP AL,'.' ;AN000;;MS. is '.' ,may be name.exe + JZ mem_done ;AN000;;MS. no, move to header + ;AN000; + STOSB ;AN000;;MS. move char + LOOP movename ;AN000;;MS. continue +mem_done: ;AN000; + XOR AL,AL ;AN000;;MS. make ASCIIZ + CMP DI,SIZE ARENA ;AN000;MS. if not all filled + JAE fill8 ;AN000;MS. + STOSB ;AN000;MS. +fill8: ;AN000; + POP SI ;AN007;MS. ds:si -> file name + POP CX ;AN007;MS. + + CALL Scan_Special_Entries ;AN007;MS. + + PUSH DX + MOV SI,exec_size + ADD SI,DX + invoke $Dup_PDB ; ES is now PDB + POP DX + + PUSH exec_environ + POP ES:[PDB_environ] +; +; set up proper command line stuff +; + LDS SI,exec_blk ; get the block + PUSH DS ; save its location + PUSH SI + LDS SI,[SI.exec0_5C_FCB] ; get the 5c fcb +; +; DS points to user space 5C FCB +; + MOV CX,12 ; copy drive, name and ext + PUSH CX + MOV DI,5Ch + MOV BL,[SI] + REP MOVSB +; +; DI = 5Ch + 12 = 5Ch + 0Ch = 68h +; + XOR AX,AX ; zero extent, etc for CPM + STOSW + STOSW +; +; DI = 5Ch + 12 + 4 = 5Ch + 10h = 6Ch +; + POP CX + POP SI ; get block + POP DS + PUSH DS ; save (again) + PUSH SI + LDS SI,[SI.exec0_6C_FCB] ; get 6C FCB +; +; DS points to user space 6C FCB +; + MOV BH,[SI] ; do same as above + REP MOVSB + STOSW + STOSW + POP SI ; get block (last time) + POP DS + LDS SI,[SI.exec0_com_line] ; command line +; +; DS points to user space 80 command line +; + OR CL,80h + MOV DI,CX + REP MOVSB ; Wham! +; +; Process BX into default AX (validity of drive specs on args). We no longer +; care about DS:SI. +; + DEC CL ; get 0FFh in CL + MOV AL,BH + XOR BH,BH + invoke GetVisDrv + JNC exec_BL + MOV BH,CL +exec_BL: + MOV AL,BL + XOR BL,BL + invoke GetVisDrv + JNC exec_Set_Return + MOV BL,CL +exec_set_return: + invoke get_user_stack ; get his return address + PUSH [SI.user_CS] ; suck out the CS and IP + PUSH [SI.user_IP] + PUSH [SI.user_CS] ; suck out the CS and IP + PUSH [SI.user_IP] + POP WORD PTR ES:[PDB_Exit] + POP WORD PTR ES:[PDB_Exit+2] + XOR AX,AX + MOV DS,AX + POP DS:[addr_int_terminate] ; save them where we can get them later + POP DS:[addr_int_terminate+2] ; when the child exits. + MOV WORD PTR DMAADD,80h + MOV DS,CurrentPDB + MOV WORD PTR DMAADD+2,DS + TEST BYTE PTR exec_func,exec_func_no_execute + JZ exec_go + + LDS SI,DWORD PTR exec_init_SP ; get stack + LES DI,exec_blk ; and block for return + MOV ES:[DI].exec1_SS,DS ; return SS + + DEC SI ; 'push' default AX + DEC SI + MOV [SI],BX ; save default AX reg + MOV ES:[DI].exec1_SP,SI ; return 'SP' + + LDS AX,DWORD PTR exec_init_IP + MOV ES:[DI].exec1_CS,DS ; initial entry stuff + + MOV ES:[DI].exec1_IP,AX + Leave + transfer SYS_RET_OK + +exec_go: + LDS SI,DWORD PTR exec_init_IP ; get entry point + LES DI,DWORD PTR exec_init_SP ; new stack + MOV AX,ES +; +; DS:SI points to entry point +; AX:DI points to initial stack +; DX has PDB pointer +; BX has initial AX value +; + CLI + MOV BYTE PTR INDOS,0 + ASSUME SS:NOTHING + MOV SS,AX ; set up user's stack + MOV SP,DI ; and SP + STI + PUSH DS ; fake long call to entry + PUSH SI + MOV ES,DX ; set up proper seg registers + MOV DS,DX + MOV AX,BX ; set up proper AX +procedure exec_long_ret,FAR + +IF BUFFERFLAG + invoke restore_user_map +ENDIF + + RET +EndProc exec_long_ret + +EndProc $Exec + +Procedure ExecRead,NEAR + CALL exec_dealloc + MOV bx,exec_fh + PUSH BP + invoke $READ + POP BP + CALL exec_alloc + return +EndProc ExecRead + +procedure exec_dealloc,near + ASSUME DS:NOTHING,ES:NOTHING + PUSH BX + MOV BX,arena_owner_system + EnterCrit CritMEM + CALL ChangeOwners + POP BX + return +EndProc exec_dealloc + +procedure exec_alloc,near + PUSH BX + MOV BX,CurrentPDB + CALL ChangeOwners + LeaveCrit CritMEM + POP BX + return +EndProc exec_alloc + +procedure ChangeOwners,NEAR + pushf + PUSH AX + MOV AX,exec_environ + CALL ChangeOwner + MOV AX,exec_load_block + Call ChangeOwner + POP AX + popf + return +EndProc ChangeOwners + +Procedure ChangeOwner,near + OR AX,AX ; is area allocated? + retz ; no, do nothing + DEC AX + PUSH DS + MOV DS,AX + MOV DS:[arena_owner],BX + POP DS + return +EndProc ChangeOwner + +Procedure Scan_Execname,near ;AN000;MS. + + LDS SI,execName ;AN000;MS. DS:SI points to name +save_begin: ;AN000; + MOV CX,SI ;AN000;MS. CX= starting addr +scan0: ;AN000; + LODSB ;AN000;MS. get char + CMP AL,':' ;AN000;;MS. is ':' , may be A:name + JZ save_begin ;AN000;;MS. yes, save si + CMP AL,'\' ;AN000;;MS. is '\', may be A:\name + JZ save_begin ;AN000;;MS. yes, save si + CMP AL,0 ;AN000;;MS. is end of name + JNZ scan0 ;AN000;;MS. no, continue scanning + SUB SI,CX ;AN000;;MS. get name's length + XCHG SI,CX ;AN000;;MS. cx= length, si= starting addr + + return ;AN000;;MS. +EndProc Scan_Execname ;AN000;;MS. + + +Procedure Scan_Special_Entries,near ;AN000;MS. + + DEC CX ;AN007;MS. cx= name length + MOV DI,CS:[Special_Entries] ;AN007;MS. es:di -> addr of special entries + CALL Reset_Version ;AN008;MS. + PUSH CS ;AN007;MS. + POP ES ;AN007;MS. +Getentries: ;AN007;MS. + MOV AL,ES:[DI] ;AN007;MS. end of list + OR AL,AL ;AN007;MS. + JZ end_list ;AN007;MS. yes + MOV CS:[Temp_Var2],DI ;AN007;MS. save di + CMP AL,CL ;AN007;MS. same length ? + JNZ skipone ;AN007;MS. no + INC DI ;AN007;MS. es:di -> special name + PUSH CX ;AN007;MS. save length and name addr + PUSH SI ;AN007;MS. + REPZ CMPSB ;AN007;MS. same name ? + JNZ not_matched ;AN007;MS. no + MOV AX,ES:[DI] ;AN007;MS. get special version + MOV CS:[Special_Version],AX ;AN007;MS. save it + MOV AL,ES:[DI+2] ;AN008;MS. get fake count + MOV CS:[Fake_Count],AL ;AN007;MS. save it + POP SI ;AN007;MS. + POP CX ;AN007;MS. + JMP SHORT end_list ;AN007;MS. +not_matched: ;AN007;MS. + POP SI ;AN007;MS. restore si,cx + POP CX ;AN007;MS. +skipone: ;AN007;MS. + MOV DI,CS:[Temp_Var2] ;AN007;MS. restore old di + XOR AH,AH ;AN007;MS. position to next entry + ADD DI,AX ;AN007;MS. + ADD DI,4 ;AN007;MS. + JMP Getentries ;AN007;MS. + + +end_list: ;AN007;MS. + return +EndProc Scan_Special_Entries ;AN000;;MS. + +Procedure Reset_Version,near ;AN008;MS. + + CMP CS:[Fake_Count],0FFH ;AN008;MS. + JNZ dont_reset ;AN008;MS. + MOV CS:[Special_Version],0 ;AN008;MS. reset to current version +dont_reset: + return +EndProc Reset_Version,near ;AN008;;MS. + \ No newline at end of file -- cgit v1.2.3