Category : Files from Magazines
Archive   : PCTV4N1.ZIP
Filename : MAKETEMP.ASM

 
Output of file : MAKETEMP.ASM contained in archive : PCTV4N1.ZIP
;****************************************************************
; Create Temporary File with a Unique Name.
; Copyright (c) 1993 FM de Monasterio. All Rights Reserved.
;
; These procedures may be distributed freely and used in
; application programs with acknowledgement, but may not
; be sold in unit form.
;
; Written for OPTASM 1.65
;----------------------------------------------------------------
; Input:
; DS:DX -> ASCIIz backslash-ending path (e.g."D:\TMP\DATA\",0)
; CX = Attributes: 0=Normal, 1=ReadOnly, 2=Hidden, 4=System
; 20h=Archive, or their ORed combinations
; Output:
; Success: CF=0, AX=handle, 13-byte TempFile field at end
; Failure: CF=1, AX=error code: 03h=Path not found
; 04h=Too many open files
; 05h=Access denied
; 50h=Unique name not found
; ??h=Disk critical error code
; Alters: AX, Flags (DF=0)
;****************************************************************
_CODE segment para public '_code'
assume cs:_code, ds:nothing, es:nothing

PUBLIC TempFile

; LOCAL DATA - Even alignment of words and strings
EVEN
Int24Vect LABEL DWORD
Int24Offs DW ? ; old INT 24h address
Int24Segm DW ?

TempAddr LABEL DWORD ; address of name field
TempOffs DW ? ; in caller's DS segment
TempSegm DW ?

; Temporary ASCIIz filepath

TempBuff DB 120 dup (?) ; TempPath buffer
TempName DB 8 dup (?) ; 8-character name
DB 0 ; ASCIIz mark

TempDisk DB 0 ; TempPath drive

TempAttr DW ? ; file attribute mask
TempTail DW ? ; path-end pointer storage
TempDate DW ? ; date stamp
TempTime DW ? ; time stamp

Int24Flag DB 0 ; 0=no error, 1=crit error

;----------------------------------------------------------------
EVEN
TempFile PROC FAR
push ES ; save used registers
push DS
push DI
push SI
push DX
push BX
push CX

mov SI,DX ; save TempPath offset

; Check DOS version to decide whether to use function 5Ah
; (MS-DOS 3.x through 4.x) or 5Bh (MS-DOS 5A/B and 6A).
;
; Use first function 3306h (get 'true' MS-DOS version) to
; exclude MS-DOS 5+ is executing under SETVER (or another
; TSR) asserting a different version via fxn 30h:
;
; BH= Minor, BL= Major version
; DL= (bits 0-2) Revision no. (Microsoft uses "A"=0, "B"=1)
; CF= Clear in Revision 5A, set in Revision 5B
; DH= Memory location flag bit 3=1: DOS in ROM, else in RAM
; flag bit 4=1: DOS in HMA, else in 640K

xor BX,BX ; MS-DOS 5+ changes BX/DX
mov AX,3306h ; fxn get true MS-DOS ver
int 21h

; Because MS-DOS 5B sets CY, the CF status cannot be used to
; exclude DR-DOS 5+, which also sets CY upon fxn 3306h. Use
; instead BX, which is modified by MS-DOS 5+ (but not by MS-
; or PC-DOS 3 through 4, or by DR-DOS 5 or 6).
;
cmp BX,5 ; MS-DOS 5?
je TempDosBug ; yes, use fxn 5Bh

; Next comp assumes MS-DOS 6 is still buggy - Delete, if not

cmp BX,6 ; assume MS-DOS 6 is
je TempDosBug ; also buggy but that
; a future DOS 7+ is not
;
; Execute function 5Ah and return
;
TempDosOk: mov AH,5Ah ; fxn create temp file
mov DX,SI ; CX and DS unchanged
int 21h
jmp TempFileRetf ; pop and return (CF safe)

;
; ** Function 5Ah buggy - Implement alternative procedure **
;
EVEN
TempDosBug: cld ; strings forward
push CS
pop ES
assume es:_code

mov es:[TempAttr],CX ; save attribute mask
mov es:[TempSegm],DS ; and filepath segment
; (SI has path offset)
;
; Copy TempPath to local buffer
;
mov DI,offset TempBuff ; ES:DI -> local buffer
mov AX,ds:[SI] ; DS:SI -> TempPath
mov CX,120 ; maximum buffer length
cmp AH,":" ; drive spec given?
jne TempPathByte ; no, skip
mov es:[TempDisk],AL ; else update INT-24h ISR
EVEN
TempPathByte: lodsb ; get TempPath character
or AL,AL ; reached null marker?
jz TempPathNull ; yes, skip over
stosb ; else save in buffer and
loop TempPathByte ; get next if within bounds

stc ; too long, signal error and
mov AX,3 ; return Path_Not_Found code
jmp TempFileRetf

;
; Found end of ASCIIz path - Save pointers
EVEN ;
TempPathNull: mov DX,CS
mov DS,DX ; restore DS addressability
assume ds:_code
dec SI ; adjust ptr to last byte
mov [TempTail],DI ; save local tail pointer
mov [TempOffs],SI ; offset for appending name

;
; Save and hook Critical Error handler ** PRESERVE DX=CS **
;
mov AX,3524h ; fxn get INT 24h vector
int 21h
mov [Int24Offs],BX ; offset
mov [Int24Segm],ES ; segment

mov ES,DX
assume es:_code
mov AX,2524h ; fxn set INT 24h vector
mov DX,offset Int24Temp ; ES:DX -> new handler
int 21h

;
; == Reentry point: Calculate new time/date stamp ==
EVEN ;
TempFileName: call GetDate ; AX=(((Y-1980)*512)+M*32)+D
mov [TempDate],AX ; store packed date
call GetTime ; AX=((h*4096)+m*64)+s
mov BX,32 ; init bit rotation counter
; * PRESERVE BX UNTIL DONE *
;
; == Reentry point: Old stamp rotation loop ==
EVEN ;
TempFileLoop: mov DI,offset TempName ; ES:DI -> name chars 1-4
mov [TempTime],AX ; store packed time
call Word2Hex ; write first half stamp

mov DI,offset TempName[4] ; ES:DI -> name chars 5-8
mov AX,[TempDate] ; read packed date
call Word2Hex ; write second half stamp

;
; Append tentative filename to TempPath string
;
mov SI,offset TempName ; DS:SI -> start of name
mov DI,[TempTail] ; ES:DI -> end of path
mov CX,4 ; name to append (words)
rep movsw

;
; Attempt to create new file with current name
;
mov AH,5Bh ; fxn create new file
mov CX,[TempAttr] ; attribute mask
mov DX,offset TempBuff ; DS:DX -> "unique" name
int 21h

mov DX,AX ; save handle/error code
jc TempFileFail ; CF=1, DOS error in AX

mov AL,[Int24Flag] ; get critical-flag status
or AL,AL ; error? (ORing sets CF=0)
jz TempFileExit ; no, return success

TempFileQuit: push DX ; save error code in stack
stc ; reset CF to signal error
jmp short TempFileCrit

;
; *** File creation error
EVEN ;
TempFileFail: cmp AX,50h ; File_Exists error code?
jne TempFileQuit ; no, return failure
dec BX ; all 32 bits rotated?
jz TempFileName ; yes, make new stamp

;
; 32-bit ROL date/time stamp by 1 bit
;
mov DX,[TempDate]
mov AX,[TempTime] ; get old date:time dword

shl DX,1 ; 0-> DX b0... DX b15-> CF
rcl AX,1 ; CF-> AX b0... AX b15-> CF
adc DX,0 ; CF-> DX b0
mov [TempDate],DX ; store rotated date
jmp short TempFileLoop ; and try again

;
; *** Successful temporary file creation:
; Return the 8-character unique name
EVEN ;
TempFileExit: push DX ; save file handle
mov CX,4 ; name to append (words)
mov SI,offset TempName ; DS:SI -> unique name
les DI,[TempAddr] ; ES:DI -> caller's field
rep movsw

;
; Restore INT-24h vector
;
TempFileCrit: pushf ; save CF status
mov AX,2524h ; fxn set INT 24h vector
lds DX,[Int24Vect] ; to old address in DS:DX
int 21h

popf ; restore CF and get back
pop AX ; the handle or error code

;
; Restore registers and return to caller
;
TempFileRetf: pop CX ; and restore registers
pop BX
pop DX
pop SI
pop DI
pop DS
pop ES
retf ; far return to caller
TempFile ENDP


;****************************************************************
; Local INT-24h Handler (DOS critical error)
; On entry:
; AH : bit 7 = 0 if disk I/O error
; DI : lower byte = error code (upper byte undefined)
; BP:SI-> device header structure containing info about
; the device on which the error took place.
; On exit:
; AL = value specifying action that DOS should take
; depending on what is allowed (AH bits 5-3).
;****************************************************************
assume ds:nothing
EVEN
Int24Temp PROC FAR
test AH,80h ; disk error?
jnz Int24Exit ; no, exit
cmp cs:[TempDisk],0 ; drive letter specified?
je Int24Disk ; no, assume TempPath disk

add AL,"A" ; get 0=A, 1=B, etc
cmp AL,cs:[TempDisk] ; is this the right drive?
je Int24Disk ; yes, handle error
sub AL,"A" ; else let DOS handle it
Int24Exit: jmp cs:[Int24Vect]

;
; Drive error
EVEN ;
Int24Disk: mov AX,DI ; save critical error code
mov cs:[Int24Flag],AL ; from lower byte of DI
xor AX,AX ; and tell DOS to ignore
iret ; error (or terminate fxn)
Int24Temp ENDP


;****************************************************************
; Pack date in DOS-file stamp format
; bit 09-15: Year (0-119 offset from 1980) * 512
; bit 05-08: Month (1-12) * 32
; bit 00-04: Day (1-31)
;
; Input: None
; Output: AX = [([Year-1980]*512)+Month*32]+Day
; Alters: AX BX CX DX
;****************************************************************
assume ds:_code
EVEN
GetDate PROC NEAR
mov AH,2Ah ; fxn get current date
int 21h ; CX=YY, DH=MM, DL=DD
mov AX,CX ; get AX=1980 through 2099
sub AX,1980 ; and make offset from 1980
mov CL,1 ; shift reps for (YY*256)*2
jmp short GetStamp ; and chain into next proc
GetDate ENDP


;****************************************************************
; Pack time in quasi-DOS-file format
; bits 12-15: hours (0-12) * 4096
; bits 06-10: minutes (0-59) * 64
; bits 00-05: seconds (0-59)
;
; instead of DOS format
; bit 11-15: hours (0-23) * 2048
; bit 05-10: minutes (0-59) * 32
; bit 00-04: seconds (0-29) in 2-second intervals
;
; Input: None
; Output: AX = [(Hour*4096)+Minute*64]+Second
; Alters: AX BX CX DX
;****************************************************************
assume ds:_code
EVEN
GetTime PROC NEAR
mov AH,2Ch ; fxn get current time
int 21h ; CH=hh, CL=mm, DH=ss
mov AL,CH ; copy 0-23 hour
sub AL,12 ; AM or PM?
jnc GetHour ; PM, keep difference
mov AL,CH ; else AM
EVEN
GetHour: cbw ; AX = 0-12 h
mov DL,DH ; DL = 0-59 s
mov DH,CL ; DH = 0-59 m
shl DH,1 ; DH = m*2
mov CL,4 ; shift reps for (h*256)*16

;
; Repack data in stamp format
EVEN ;
GetStamp: xchg AH,AL ; fast Y*256 or h*256
shl AX,CL ; (Y-1980)*512 or h*4096
xor BX,BX ; zero register
xchg BL,DH ; DX = D or s, BX=M or m*2)
mov CL,5 ; get times-32 shift reps
shl BX,CL ; BX = M*32 or m*64
add AX,BX
add AX,DX ; AX=(h*4096)+(m*64)+s or
retn ; AX=(Y-1980)*512+M*32+D
GetTime ENDP


;****************************************************************
; Convert 16-bit binary to 4-ASCII hexadecimals and store as ES:DI
;
; Input: AX = binary number (word), ES:DI -> memory offset
; Output: None
; Alters: AX CX DX DI
;****************************************************************
assume ds:_code, es:_code
EVEN
Word2Hex PROC NEAR
std ; set to fill backwards
add DI,3 ; (3+1) digits to fill
mov CX,4 ; in 4 nibbles

;
; ** PRESERVE [BX] **
EVEN ;
Word2Hex1: mov DX,AX ; save accumulator
and AX,000Fh ; read LSN
cmp AL,9 ; 0Ah-0Fh range?
ja Word2Hex2 ; yes
add AL,"0" ; no, make ASCII digit
jmp short Word2Hex3 ; and store it

Word2Hex2: add AL,55 ; else make ASCII letter
Word2Hex3: stosb ; and store it
mov AX,DX
ror AX,1 ; rotate nibble
ror AX,1 ; ** PRESERVE [CX] **
ror AX,1
ror AX,1
loop Word2Hex1 ; convert next nibble
cld ; clear DF
retn
Word2Hex ENDP


_CODE ends
END


  3 Responses to “Category : Files from Magazines
Archive   : PCTV4N1.ZIP
Filename : MAKETEMP.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/