📄 woainit.asm
字号:
@@:
cmp ax,_WOARLMSEG ;comapare with stub
ja @f ;no need to swap
mov ax,_WOARLMSEG ;load stub seg
mov bx,StubSegSize ;and its size
@@:
shiftr bx,4 ;convert to para
add ax,bx ;get to end of segment
sub ax,LowMemSel ;subtract the PSP seg
mov SizeReservedArea,ax ;size of reserved area
add ax,LowMemSel ;segment where stub seg will be loaded
mov SegAfterReservedArea,ax ;address of segment after reserved area
mov UsableLowHeapSel,ax ;seg for usable area
ret
GetSegmentLimits endp
;----------------------------------------------------------------------------;
; CheckXmsRequirements: ;
; ;
; If no XMS memory is required by the application, a flag would be set to ;
; indicate that. ;
; ;
; If XMS is required but no XMS driver is loaded we will exit and report the ;
; error. ;
; ;
; We will then find out details about the XMS block allocated for the high ;
; heap and find out whether we can meet the oldapps requiremsts. ;
;----------------------------------------------------------------------------;
cProc CheckXmsRequirements,<NEAR,PUBLIC,PASCAL>
cBegin
;----------------------------------------------------------------------------;
; real mode specific code. In real mode we need the address of the XMS contr-;
; -ol fuction, so get the address and save it. ;
; ;
; (note: this instance may not need any XMS memory, but this instance may ;
; later handle some old app which does need XMS and will then be needing ;
; the address of the control function). ;
;----------------------------------------------------------------------------;
cmp AppMinXmsK,0 ;is there any requirement ?
jnz XmsMemoryDesired ;yes
; as no xms memory is required, set the XMS flag off.
mov wptr [XmsBankSize],0 ;no XMS memory needed
mov wptr [XmsBankSize+2],0 ;reset hiword too
jmp short CheckXmsReqRet ;go back.
XmsMemoryDesired:
; test to see if XMS driver is loaded.
mov ErrorType,ER_NO_XMS_DRV ;anticipating no XMS driver
cmp XmsFlag,0ffh ;driver loaded ?
njnz NearErrorHandler ;no xms driver loaded
; XMS driver is loaded, check to see if we can support apps requirements.
mov cx,wptr [HighMemSize+2]
mov dx,wptr [HighMemSize] ;CX:DX has size of high heap block
; get the number of K bytes this amounts to.
mov dl,dh ;divide by 256
mov dh,cl
mov cl,ch
xor ch,ch ;we have divided by 256, now by 4
shr cx,1 ;get lsb into carry
rcr dx,1 ;get it into dx
shr cx,1 ;get lsb into carry
rcr dx,1 ;CX:DX has mem available in K
or cx,cx ;if cx > 0 we have enough
jnz GrantXmsMemory ;enough is available
mov ErrorType,ER_LOW_XMS_MEM;anticipate not enough memory
cmp AppMinXmsK,-1 ;all of memory needed ?
jz AllOfXmsNeeded ;yes
cmp dx,AppMinXmsK ;compare with min requirement
njb NearErrorHandler ;not enough for minimum requirement
GrantXmsMemory:
; we have made sure that minimum requirement is met, but we must try to grant
; the maximum requirement.
mov ax,AppMaxXmsK ;this is what we want to give
cmp ax,-1 ;do we need all ?
jz AllOfXmsNeeded ;yes
cmp dx,AppMaxXmsK ;compare with max requirement.
jbe AllOfXmsNeeded ;availabe is < desired, grant all
jmp short SetXmsRequired ;set up size to be granted
AllOfXmsNeeded:
;----------------------------------------------------------------------------;
; In real mode, DX has the size of the XMS block rounded down to a K. ;
;----------------------------------------------------------------------------;
mov ax,dx ;all of XMS to be granted
;----------------------------------------------------------------------------;
SetXmsRequired:
mov bx,1024 ;need to do Kilo to byte conversion
mul bx ;DX:AX has apps xms bank size
SaveXmsSize:
mov wptr [XmsBankSize+2],dx ;save high word
mov wptr [XmsBankSize],ax ;save low word
CheckXmsReqRet:
cEnd
;----------------------------------------------------------------------------;
; AllocateXms: ;
; ;
; This routine gets the information about the XMS block to use. The XMS block;
; handle is will be saved in the global switch structure by the first inst. ;
; of the switcher (it would be 0 otherwise) and all other instances would use;
; it to get the size. ;
;----------------------------------------------------------------------------;
cProc AllocateXms,<NEAR,PUBLIC,PASCAL>,<es,di>
cBegin
; check to see if XMS driver is installed or not.
mov XmsFlag,0 ;assume no xms.
mov ax,4300h ;installation check
int 2fh
cmp al,80h ;failure ?
njne AllocateXmsRet ;yes, no driver installed.
mov XmsFlag,0ffh ;XMS exists
; get the XMS entry point address.
push es ;will get thrashed
mov ax,4310h ;code to get the address
int 2fh ;address in es:bx
mov wptr [lpXmsControl+2],es;save segment of control function
mov wptr [lpXmsControl],bx ;save the offset
pop es ;restore
; get a pointer to the global switch structure and find out whether a privious
; instance had allocated the block or not.
mov ax,4a05h ;opcode
mov si,CGET_GLOBAL_SWITCH_DATA
int 2fh ;dx:ax has the long pointer
mov es,dx ;load it into es
mov di,ax ;es:di -> info structure
mov dx,es:[di].XMS_Handle ;get the stored handle
or dx,dx ;if zero then not allocated.
jz DoAllocateXMS ;must allocate it.
; the XMS block has already been allocated, save the handle and get the size.
mov HighMemXmsHandle,dx ;save the handle
mov ax,wptr es:[di][0].XMS_Size
mov word ptr [HighMemSize],ax;save low word of size
mov ax,wptr es:[di][2].XMS_Size
mov word ptr [HighMemSize+2],ax;save high word
jmp short AllocateXMSRet ;done.
DoAllocateXMS:
; get the size of the largest available block.
mov ah,08h ;query amt. of free memory
call lpXmsControl ;AX has largest free block size in K
cmp bl,80h ;error ?
jz AllocateXmsRet ;no XMS available
cmp bl,81h ;error ?
jz AllocateXmsRet ;no XMS available
; allocate the block and get it's handle.
push ax ;save the size of the largest block.
mov dx,ax ;requested size = size of largest block
mov ah,09h ;allocate XMS block
call lpXmsControl ;AX has largest free block size in K
or ax,ax ;failed ?
pop ax ;get back size
jz AllocateXmsRet ;allocation failed.
; save the handle and the size of the block.
mov HighMemXmsHandle,dx ;save the handle
mov bx,1024 ;need size in KB
xor dx,dx ;clear out before mul
mul bx ;dx:ax has size in bytes
mov word ptr [HighMemSize],ax;save low word of size
mov word ptr [HighMemSize+2],dx;save high word
; now save the block information in the global structure.
mov wptr es:[di][0].XMS_Size,ax
mov wptr es:[di][2].XMS_Size,dx
mov dx,HighMemXmsHandle ;get the handle
mov es:[di].XMS_Handle,dx ;save it
; finally lock the block.
mov ah,0ch ;lock XMS block
call lpXmsControl ;AX has largest free block size in K
AllocateXmsRet:
cEnd
;----------------------------------------------------------------------------;
; GetSizeFromArena: ;
; ;
; This routine will be assembled only in real mode and it looks into the ;
; arena associated with a segment whose values in in ax and returns the size ;
; in bytes in AX. ;
;----------------------------------------------------------------------------;
GetSizeFromArena proc near
dec ax ;get to the arena
mov es,ax ;have es pointing to arena
mov ax,es:[3] ;get the size in paragraphs
shiftl ax,4 ;get it in bytes
ret
GetSizeFromArena endp
;----------------------------------------------------------------------------;
; GetSwapFilePathPrefix: ;
; ;
; This routine gets the path prefix for the swap files to be used. ;
; ;
; . If the [NowWindowsAppf] section in SYSTEM.INI has an entry specifi-;
; -ed for the key, 'swapdisk=', then that will be the path for temp ;
; files,else ;
; . the 'GetTempFileName' function is invoked to get the complete ;
; path name of the temp drive and part of the name upto the unique ;
; number is extracted from it. ;
;----------------------------------------------------------------------------;
GetSwapFilePathPrefix proc near
cld ;do not take chances with this
; copy the paths. First the first swap path
mov si,DataOFFSET WoaSwapFilePrefix
mov di,DataOFFSET WoaSwap1Path
call AppendDsSiToDsDi
; now the second swap path.
mov si,DataOFFSET WoaSwapFilePrefix
mov di,DataOFFSET WoaSwap2Path
call AppendDsSiToDsDi
; prepare the grabber swap file name from the second swap path
mov di,DataOFFSET DosAppSwapFileName;prepare name here
call FarCopyBasicSwap2FileName;copy the name until the unique num
mov ax,0ffeeh ;irrelevant, grabber will redo this
call FarAppendUniqueNumber ;just have a win style file name
mov si,DataOFFSET DosAppSwapFileName
mov di,StubSegOFFSET WoaGrabberSwapPath
push es ;save
smov es,ds ;es:si ppints to file name
call CopyEsSiToCsDi ;copy over to the stubsegment
pop es
ret
GetSwapFilePathPrefix endp
;----------------------------------------------------------------------------;
; AppendDsSiToDsDi: ;
; ;
; Appends the strung at DS:SI to the string at ES:DI and makes sure that the ;
; composite string end with a '\' ;
;----------------------------------------------------------------------------;
AppendDsSiToDsDi proc near
; first get to the end of the path.
push es
smov es,ds ;es=ds
@@:
mov al,es:[di] ;get the next byte
inc di ;next byte
or al,al ;NULL ?
jnz @b ;no.
sub di,2 ;go back to last character
mov al,es:[di] ;get the last character
cmp al,'\' ;path separator ?
jz @f ;yes
mov al,'\' ;load it, zero in high byte
@@:
stosb ;append a path separator
; now copy the path prefix.
@@:
lodsb ;get the next byte
stosb ;save it
or al,al ;NULL copied ?
jnz @b ;no.
pop es ;restore
ret
AppendDsSiToDsDi endp
;----------------------------------------------------------------------------;
; GetSwapFileInformation: ;
; ;
; Gets information for building up swap file names. ;
;----------------------------------------------------------------------------;
cProc GetSwapFileInformation,<NEAR,PUBLIC,PASCAL>,<si,di>
cBegin
; get the path prefix to be used for all swap files.
call GetSwapFilePathPrefix ;get the prefix
; obtain the drive letter for the swap drive from the basic swap name.
mov al,WoaSwap1Path ;get the first letter
and al,0dfh ;convert to upper case
mov DiskSwap1Drive,al ;save
mov al,WoaSwap2Path ;get the first letter
and al,0dfh ;convert to upper case
mov DiskSwap2Drive,al ;save
cEnd
;----------------------------------------------------------------------------;
; find_next_arg: ;
; Takes ES:SI over DOS delimiters and if poitions it to point ;
; to the next valid dos argument, or resturns NZ if end of line is reached ;
;----------------------------------------------------------------------------;
find_next_arg proc near
push ds ;save
smov ds,es ;load it in ds:si
find_next_arg_1:
lodsb ;get the next byte
cmp al,0dh ;end of command line?
je no_more_args ;there is no second argument
call delim ;is this a DOS delimiter?
jz find_next_arg_1 ;yes, skip over it
dec si ;point to this char
xor al,al ; set zero flag
jmp short find_next_arg_ret
no_more_args:
dec si
or al,al ;If end then AL is non zero
find_next_arg_ret:
pop ds ;restore
ret
find_next_arg endp
delim proc near
cmp al,' ' ;space ?
jz delim_ret
cmp al,'='
jz delim_Ret
cmp al,',' ;comma ?
jz delim_ret
cmp al,';' ;semicolon ?
jz delim_ret
cmp al,09H ;tab
jz delim_ret
cmp al,0AH ; Line Feed
delim_ret:
ret
Delim endp
;----------------------------------------------------------------------------;
; GetCompleteFileName: ;
; ;
; This routine takes a long pointer to a complete or partial file name and ;
; returns the complete file name in the same buffer. If the file cannot be ;
; found, AX will be set to -1. Also it assumes that the file name with the ;
; NULL terminator is not more than 64 characters long. ;
;----------------------------------------------------------------------------;
cProc GetCompleteFileName,<NEAR,PUBLIC,PASCAL>
parmD lpName ;input file name
cBegin
cld ;do not take chances with this
cEnd
;----------------------------------------------------------------------------;
; DeleteTempFiles: ;
; ;
; This routine goes through a sequence of find first/find next calls and ;
; deletes all woa and grabber left over temp files if any. The current DTA ;
; address is saved and this routine uses a DTA on the stack for these calls ;
; ;
; The grabber files will not be deleted if we have an instance of Windows ;
; 3.0 winoldap active or if this is not the first instance of the switcher. ;
; ;
; The grabber swap files can only be in the second swap path (the grabbers ;
; do not support two swap paths and Winoldap lets the grabber know only of ;
; the second swap path.). There will thus be 3 groups to delete (woa swap ;
; files in two swap paths and grabber swap file groups in the second path). ;
;----------------------------------------------------------------------------;
cProc DeleteTempFiles,<NEAR,PUBLIC,PASCAL>,<es,si,di>
localD CurrentDta ;saves current DTA address here
localV NewDta,128 ;used for find/first and find next.
cBegin
; get and save the current DTA address
mov ah,2fh ;get DTA address call
int 21h ;es:bx has the current address
mov seg_CurrentDta,es ;save segment
mov off_CurrentDta,bx ;save offset
; set the new DTA address to stack.
lea dx,NewDta ;will have it here on stack.
push ds ;save
smov ds,ss ;ds:dx is the new DTA area
mov ah,1ah ;set DTA address
int 21h ;new DTA on stack
pop ds ;restore
; now delete the WOA temp files.
mov cx,3 ;3 chains to delete
DeleteAChain:
; get the template of the next chain based on the value of cx:
; CX = 3 implies woa files in second path, CX = 2 implies grabber files in
; second path and CX = 1 implies woa files in first path.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -