1 ; SCCSID = @(#)getset.asm 1.2 85/07/23
2 TITLE GETSET
- GETting
and SETting
MS-DOS system calls
5 ; System Calls which get and set various things
11 ; $GET_DRIVE_FREESPACE
16 ; $GET_INTERRUPT_VECTOR
17 ; $SET_INTERRUPT_VECTOR
20 ; $GetExtendedError DOS 3.3
21 ; Get_Global_CdPg DOS 4.0
26 ; Created: ARR 30 March 1983
28 ; A000 version 4.0 Jan. 1988
29 ; A006 D503-- fake version for IBMCACHE
30 ; A008 P4070- faske version for MS WINDOWS
34 ; get the appropriate segment definitions
42 CODE SEGMENT BYTE PUBLIC 'CODE'
43 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
59 i_need COUNTRY_CDPG
,byte ;DOS 3.3
63 i_need EXTERR_ACTION
,BYTE
64 i_need EXTERR_CLASS
,BYTE
65 i_need EXTERR_LOCUS
,BYTE
68 i_need FILE_UCASE_TAB
,BYTE
70 i_need CURRENTPDB
,WORD
71 i_need DBCS_TAB
,BYTE ;AN000;
72 i_need Special_version
,WORD ;AN006;
73 i_need Fake_Count
,BYTE ;AN008;
74 i_need NLS_YES
,BYTE ;AN000;
75 i_need NLS_yes2
,BYTE ;AN000;
76 i_need NLS_NO
,BYTE ;AN000;
77 i_need NLS_no2
,BYTE ;AN000;
80 BREAK <$Get_Version
-- Return DOS version number
>
81 procedure $GET_VERSION
,NEAR
82 ASSUME
DS:NOTHING
,ES:NOTHING
87 ; Return DOS version number
90 ; User number in BL:CX (24 bits)
91 ; Version number as AL.AH in binary
92 ; NOTE: On pre 1.28 DOSs AL will be zero
102 CMP CS:[Fake_Count
],0FFH ;AN008;
104 CMP CS:[Fake_Count
],0 ;AN008;
106 DEC CS:[Fake_Count
] ;AN008;
108 CMP CS:[Special_version
],0 ;AN006;
110 MOV AX,CS:[Special_version
] ;AN006;
112 MOV [SI.user_AX
],AX ; Really only sets AH
116 BREAK <$Get_Verify_on_Write
- return verify
-after
-write flag
>
117 procedure $GET_VERIFY_ON_WRITE
,NEAR
118 ASSUME
DS:NOTHING
,ES:NOTHING
125 ; AL = value of VERIFY flag
129 EndProc $GET_VERIFY_ON_WRITE
131 BREAK <$Set_Verify_on_Write
- Toggle verify
-after
-write flag
>
132 procedure $SET_VERIFY_ON_WRITE
,NEAR
133 ASSUME
DS:NOTHING
,ES:NOTHING
136 ; AL = desired value of VERIFY flag
145 EndProc $SET_VERIFY_ON_WRITE
147 BREAK <$International
- return country
-dependent information
>
150 ; MOV AH,International
151 ; MOV AL,country (al = 0 => current country)
156 ; give users an idea of what country the application is running
158 ; IF DX != -1 on input (get country)
159 ; AL = 0 means return current country table.
160 ; 0<AL<0FFH means return country table for country AL
161 ; AL = 0FF means return country table for country BX
163 ; Register BX will contain the 16-bit country code.
164 ; Register AL will contain the low 8 bits of the country code.
165 ; The block pointed to by DS:DX is filled in with the information
166 ; for the particular country.
167 ; BYTE Size of this table excluding this byte and the next
168 ; BYTE Country code represented by this table
169 ; A sequence of n bytes, where n is the number specified
170 ; by the first byte above and is not > internat_block_max,
171 ; in the correct order for being returned by the
172 ; INTERNATIONAL call as follows:
173 ; WORD Date format 0=mdy, 1=dmy, 2=ymd
174 ; 5 BYTE Currency symbol null terminated
175 ; 2 BYTE thousands separator null terminated
176 ; 2 BYTE Decimal point null terminated
177 ; 2 BYTE Date separator null terminated
178 ; 2 BYTE Time separator null terminated
179 ; 1 BYTE Bit field. Currency format.
180 ; Bit 0. =0 $ before # =1 $ after #
181 ; Bit 1. no. of spaces between # and $ (0 or 1)
182 ; 1 BYTE No. of significant decimal digits in currency
183 ; 1 BYTE Bit field. Time format.
184 ; Bit 0. =0 12 hour clock =1 24 hour
185 ; DWORD Call address of case conversion routine
186 ; 2 BYTE Data list separator null terminated.
188 ; Register AX has the error code.
189 ; IF DX = -1 on input (set current country)
191 ; 0<AL<0FFH means set current country to country AL
192 ; AL = 0FF means set current country to country BX
194 ; Current country SET
195 ; Register AL will contain the low 8 bits of the country code.
197 ; Register AX has the error code.
200 procedure $INTERNATIONAL
,NEAR ; DOS 3.3
201 ASSUME
DS:NOTHING
,ES:NOTHING
203 JZ BX_HAS_CODE
; -1 means country code is in BX
204 MOV BL,AL ; Put AL country code in BX
210 POP DI ; User buffer to ES:DI
215 JNZ international_find
216 MOV SI,OFFSET DOSGROUP
:COUNTRY_CDPG
217 JMP SHORT international_copy
220 MOV BP,0 ; flag it for GetCntry only
221 CALL international_get
223 CMP BX,0 ; nlsfunc finished it ?
224 JNZ SHORT international_copy
; no, copy by myself
225 MOV BX,DX ; put country back
226 JMP SHORT international_ok3
229 MOV SI,OFFSET DOSGROUP
:COUNTRY_CDPG
230 CMP BX,[SI.ccDosCountry
] ; = current country id
231 retz
; return if equal
233 XOR BX,BX ; bx = 0, default code page
234 CallInstall NLSInstall
,NLSFUNC
,0 ; check if NLSFUNC in memory
236 JNZ interr
; not in memory
237 CMP BP,0 ; GetCntry ?
239 CallInstall GetCntry
,NLSFUNC
,4 ; get country info
242 CallInstall SetCodePage
,NLSFUNC
,3 ; set country info
250 MOV AL,0FFH ; flag nlsfunc error
254 MOV BX,[SI.ccDosCountry
] ; = current country id
255 MOV SI,OFFSET DOSGROUP
:COUNTRY_CDPG
.ccDFormat
256 MOV CX,OLD_COUNTRY_SIZE
257 REP MOVSB ;copy country info
259 invoke get_user_stack
263 MOV AX,BX ; Return country code in AX too.
268 MOV BP,1 ; flag it for SetCodePage only
269 CALL international_get
274 transfer SYS_RET_ERR
; return what we got from NLSFUNC
276 error error_Invalid_Function
; NLSFUNC not existent
279 EndProc $INTERNATIONAL
283 BREAK <$GetExtCntry
- return extended country
-dependent information
>
287 ; AL= 20H capitalize single char, DL= char
288 ; 21H capitalize string ,CX= string length
289 ; 22H capitalize ASCIIZ string
290 ; 23H YES/NO check, DL=1st char DH= 2nd char (DBCS)
291 ; 80H bit 0 = use normal upper case table
292 ; 1 = use file upper case table
293 ; DS:DX points to string
297 ; MOV AH,GetExtCntry ; DOS 3.3
298 ; MOV AL,INFO_ID ( info type,-1 selects all)
299 ; MOV BX,CODE_PAGE ( -1 = active code page )
300 ; MOV DX,COUNTRY_ID ( -1 = active country )
301 ; MOV CX,SIZE ( amount of data to return)
302 ; LES DI,COUNTRY_INFO ( buffer for returned data )
305 ; give users extended country dependent information
306 ; or capitalize chars
309 ; extended country info is succesfully returned
311 ; Register AX has the error code.
312 ; AX=0, NO for YES/NO CHECK
316 procedure $GetExtCntry
,NEAR ; DOS 3.3
317 ASSUME
DS:NOTHING
,ES:NOTHING
318 CMP AL,CAP_ONE_CHAR
;AN000;MS. < 20H ?
319 JAE capcap
;AN000;MS.
320 JMP notcap
;AN000;MS. yes
322 TEST AL,UPPER_TABLE
;AN000;MS. which upper case table
323 JNZ fileupper
;AN000;MS. file upper case
324 MOV BX,OFFSET DOSGROUP
:UCASE_TAB
+2 ;AN000;MS. get normal upper case
325 JMP SHORT capit
;AN000;MS.
327 MOV BX,OFFSET DOSGROUP
:FILE_UCASE_TAB
+2;AN000;MS. get file upper case
329 CMP AL,CAP_ONE_CHAR
;AN000;;MS.cap one char ?
330 JNZ chkyes
;AN000;;MS. no
331 MOV AL,DL ;AN000;;MS. set up AL
332 invoke GETLET3
;AN000;;MS. upper case it
333 invoke get_user_stack
;AN000;;MS. get user stack
334 MOV byte ptr [SI.user_DX
],AL;AN000;;MS. user's DL=AL
335 JMP SHORT nono
;AN000;;MS. done
337 CMP AL,CHECK_YES_NO
;AN000;;MS. check YES or NO ?
338 JNZ capstring
;AN000;;MS. no
339 XOR AX,AX ;AN000;;MS. presume NO
342 MOV AL,DL ;AN000;;MS.
343 invoke TESTKANJ
;AN000;;MS. DBCS ?
345 JNZ dbcs_char
;AN000;;MS. yes, return error
348 CMP DL,NLS_YES
;AN000;;MS. is 'Y' ?
349 JZ yesyes
;AN000;;MS. yes
350 CMP DL,NLS_yes2
;AN000;;MS. is 'y' ?
351 JZ yesyes
;AN000;;MS. yes
352 CMP DL,NLS_NO
;AN000;;MS. is 'N'?
353 JZ nono
;AN000;;MS. no
354 CMP DL,NLS_no2
;AN000;;MS. is 'n' ?
355 JZ nono
;AN000;;MS. no
357 INC AX ;AN000;;MS. not YES or NO
359 INC AX ;AN000;;MS. return 1
361 transfer SYS_RET_OK
;AN000;;MS. done
363 MOV SI,DX ;AN000;;MS. si=dx
364 CMP AL,CAP_STRING
;AN000;;MS. cap string ?
365 JNZ capascii
;AN000;;MS. no
366 CMP CX,0 ;AN000;;MS. check count 0
367 JZ nono
;AN000;;MS. yes finished
369 LODSB ;AN000;;MS. get char
371 invoke TESTKANJ
;AN000;;MS. DBCS ?
372 JZ notdbcs
;AN000;;MS. no
373 INC SI ;AN000;;MS. skip 2 chars
374 DEC CX ;AN000;;MS. bad input, one DBCS char at end
375 JZ nono
;AN000;;MS. yes
376 JMP SHORT next99
;AN000;;MS.
380 invoke GETLET3
;AN000;;MS. upper case it
381 MOV byte ptr [SI-1],AL ;AN000;;MS. store back
383 LOOP concap
;AN000;;MS. continue
384 JMP nono
;AN000;;MS. done
386 CMP AL,CAP_ASCIIZ
;AN000;;MS. cap ASCIIZ string ?
387 JNZ capinval
;AN000;;MS. no
389 LODSB ;AN000;;MS. get char
390 CMP AL,0 ;AN000;;MS. end of string ?
391 JZ nono
;AN000;;MS. yes
393 invoke TESTKANJ
;AN000;;MS. DBCS ?
394 JZ notdbcs2
;AN000;;MS. no
395 CMP BYTE PTR [SI],0 ;AN000;;MS. bad input, one DBCS char at end
396 JZ nono
;AN000;;MS. yes
397 INC SI ;AN000;;MS. skip 2 chars
398 JMP concap2
;AN000;;MS.
401 invoke GETLET3
;AN000;;MS. upper case it
402 MOV byte ptr [SI-1],AL ;AN000;;MS. store back
403 JMP concap2
;AN000;;MS. continue
407 CMP CX,5 ; minimum size is 5
410 MOV SI,OFFSET DOSGROUP
:COUNTRY_CDPG
411 CMP DX,-1 ; active country ?
413 MOV DX,[SI.ccDosCountry
] ; get active country id
415 CMP BX,-1 ; active code page?
416 JNZ CHKAGAIN
; no, check again
417 MOV BX,[SI.ccDosCodePage
] ; get active code page id
419 CMP DX,[SI.ccDosCountry
] ; same as active country id?
421 CMP BX,[SI.ccDosCodePage
] ; same as active code page id?
424 MOV BX,[SI.ccSysCodePage
] ; bx = sys code page id
425 ; CMP AL,SetALL ; select all?
427 ; MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG.ccNumber_of_entries
430 MOV CX,[SI.ccNumber_of_entries
]
431 MOV SI,OFFSET DOSGROUP
:COUNTRY_CDPG
.ccSetUcase
433 CMP AL,[SI] ; compare info type
435 ADD SI,5 ; next entry
439 error error_Invalid_Function
; info type not found
441 MOVSB ; move info id byte
442 POP CX ; retsore char count
443 CMP AL,SetCountryInfo
; select country info type ?
445 MOV CX,4 ; 4 bytes will be moved
446 MOV AX,5 ; 5 bytes will be returned in CX
448 REP MOVSB ; copy info
449 MOV CX,AX ; CX = actual length returned
450 MOV AX,BX ; return sys code page in ax
452 invoke get_user_stack
; return actual length to user's CX
456 SUB CX,3 ; size after length field
457 CMP WORD PTR [SI],CX ; less than table size
459 MOV CX,WORD PTR [SI] ; truncate to table size
461 MOV ES:[DI],CX ; copy actual length to user's
462 ADD DI,2 ; update index
465 ADD AX,3 ; AX has the actual length
466 JMP OK_RETN
; go move it
469 PUSH AX ; save info type
470 POP BP ; bp = info type
471 CallInstall NLSInstall
,NLSFUNC
,0 ; check if NLSFUNC in memory
473 JZ NLSNXT
; in memory
475 error error_Invalid_Function
476 NLSNXT: CallInstall GetExtInfo
,NLSFUNC
,2 ;get extended info
479 MOV AX,[SI.ccSysCodePage
] ; ax = sys code page id
482 transfer SYS_RET_ERR
; return what is got from NLSFUNC
486 BREAK <$GetSetCdPg
- get
or set global
code page
>
489 ; MOV AH,GetSetCdPg ; DOS 3.3
490 ; MOV AL,n ; n = 1 : get code page, n = 2 : set code page
491 ; MOV BX,CODE_PAGE ( set code page only)
494 ; get or set the global code page
497 ; global code page is set (set global code page)
498 ; BX = active code page id (get global code page)
499 ; DX = system code page id (get global code page)
501 ; Register AX has the error code.
504 procedure $GetSetCdPg
,NEAR ; DOS 3.3
505 ASSUME
DS:NOTHING
,ES:NOTHING
507 MOV SI,OFFSET DOSGROUP
:COUNTRY_CDPG
508 CMP AL,1 ; get global code page
509 JNZ setglpg
; set global cod epage
510 MOV BX,[SI.ccDosCodePage
] ; get active code page id
511 MOV DX,[SI.ccSysCodePage
] ; get sys code page id
512 invoke get_user_stack
514 MOV [SI.user_BX
],BX ; update returned bx
515 MOV [SI.user_DX
],DX ; update returned dx
522 ;;;;;;; CMP BX,[SI.ccDosCodePage] ; same as active code page
523 ;;;;;;; JZ OK_RETURN ; yes
524 MOV DX,[SI.ccDosCountry
]
525 CallInstall NLSInstall
,NLSFUNC
,0 ; check if NLSFUNC in memory
527 JNZ nomem
; not in memory
528 CallInstall SetCodePage
,NLSFUNC
,1 ;set the code page
531 CMP AL,65 ; set device code page failed
535 MOV [EXTERR_ACTION
],errACT_Ignore
536 MOV [EXTERR_CLASS
],errCLASS_HrdFail
537 MOV [EXTERR_LOCUS
],errLOC_SerDev
543 error error_Invalid_Function
; function not defined
550 BREAK <$Get_Drive_Freespace
-- Return bytes of free disk space
on a drive
>
551 procedure $GET_DRIVE_FREESPACE
,NEAR
552 ASSUME
DS:NOTHING
,ES:NOTHING
557 ; Return number of free allocation units on drive
559 ; BX = Number of free allocation units
560 ; DX = Total Number of allocation units on disk
562 ; AX = Sectors per allocation unit
563 ; = -1 if bad drive specified
564 ; This call returns the same info in the same registers (except for FAT pointer)
565 ; as the old FAT pointer calls
569 invoke GetThisDrv
; Get drive
574 JC SET_AX_RET
; User FAILed to I 24
575 XOR AH,AH ; Chuck Fat ID byte
577 invoke get_user_stack
585 ; MOV AL,error_invalid_drive ; Assume error
589 EndProc $GET_DRIVE_FREESPACE
591 BREAK <$Get_DMA
, $Set_DMA
-- Get
/Set current DMA address
>
592 procedure $GET_DMA
,NEAR
593 ASSUME
DS:NOTHING
,ES:NOTHING
598 ; Get DISK TRANSFER ADDRESS
600 ; ES:BX is current transfer address
602 MOV BX,WORD PTR [DMAADD
]
603 MOV CX,WORD PTR [DMAADD
+2]
604 invoke get_user_stack
610 procedure $SET_DMA
,NEAR
611 ASSUME
DS:NOTHING
,ES:NOTHING
614 ; DS:DX is desired new disk transfer address
616 ; Set DISK TRANSFER ADDRESS
620 MOV WORD PTR [DMAADD
],DX
621 MOV WORD PTR [DMAADD
+2],DS
625 BREAK <$Get_Default_Drive
, $Set_Default_Drive
-- Set
/Get default drive
>
626 procedure $GET_DEFAULT_DRIVE
,NEAR
627 ASSUME
DS:NOTHING
,ES:NOTHING
632 ; Return current drive number
638 EndProc $GET_DEFAULT_DRIVE
640 procedure $SET_DEFAULT_DRIVE
,NEAR
641 ASSUME
DS:NOTHING
,ES:NOTHING
644 ; DL = Drive number for new default drive
646 ; Set the default drive
648 ; AL = Number of drives, NO ERROR RETURN IF DRIVE NUMBER BAD
652 invoke GetVisDrv
; see if visible drive
653 JC SETRET
; errors do not set
654 ; LDS SI,ThisCDS ; get CDS
655 ; TEST [SI].curdir_flags,curdir_splice ; was it spliced?
656 ; JNZ SetRet ; yes, do not set
657 MOV [CURDRV
],AL ; no, set
659 MOV AL,[CDSCOUNT
] ; let user see what the count really is
661 EndProc $SET_DEFAULT_DRIVE
663 BREAK <$Get_Interrupt_Vector
- Get
/Set interrupt vectors
>
664 procedure $GET_INTERRUPT_VECTOR
,NEAR
665 ASSUME
DS:NOTHING
,ES:NOTHING
668 ; AL = interrupt number
670 ; Get the interrupt vector
672 ; ES:BX is current interrupt vector
675 LES BX,DWORD PTR ES:[BX]
676 invoke get_user_stack
680 EndProc $GET_INTERRUPT_VECTOR
682 procedure $SET_INTERRUPT_VECTOR
,NEAR
683 ASSUME
DS:NOTHING
,ES:NOTHING
686 ; AL = interrupt number
687 ; DS:DX is desired new interrupt vector
689 ; Set the interrupt vector
694 CLI ; Watch out!!!!! Folks sometimes use
695 MOV ES:[BX],DX ; this for hardware ints (like timer).
699 EndProc $SET_INTERRUPT_VECTOR
705 Public GSET001S
,GSET001E
711 LSTVEC
DB ?
; ALL OTHER
719 LSTVEC2
DB ?
; Map to itself
721 NUMVEC
= VECOUT
-VECIN
726 procedure RECSET
,NEAR
730 MOV [LSTVEC
],AL ; Terminate list with real vector
731 MOV [LSTVEC2
],AL ; Terminate list with real vector
732 MOV CX,NUMVEC
; Number of possible translations
733 MOV DI,OFFSET DOSGROUP
:VECIN
; Point to vectors
735 MOV AL,ES:[DI+NUMVEC
-1] ; Get translation
746 BREAK <$Char_Oper
- hack
on paths
, switches so that xenix can look like PCDOS
>
748 ; input: AL = function:
749 ; 0 - read switch char
750 ; 1 - set switch char (char in DL)
751 ; 2 - read device availability
752 ; Always returns available
753 ; 3 - set device availability
754 ; No longer supported (NOP)
755 ; output: (get) DL - character/flag
757 procedure $CHAR_OPER
,NEAR
758 ASSUME
DS:NOTHING
,ES:NOTHING
777 Invoke Get_User_Stack
784 BREAK <$GetExtendedError
- Return Extended DOS error
code>
787 ; output: AX = Extended error code (0 means no extended error)
788 ; BL = recommended action
789 ; BH = class of error
790 ; CH = locus of error
791 ; ES:DI = may be pointer
793 procedure $GetExtendedError
,NEAR
794 ASSUME
DS:NOTHING
,ES:NOTHING
798 MOV BX,WORD PTR [EXTERR_ACTION
] ; BL = Action, BH = Class
799 MOV CH,[EXTERR_LOCUS
]
800 invoke get_user_stack
807 EndProc $GetExtendedError
809 BREAK <$Get_Global_CdPg
- Return Global
Code Page
>
812 ; output: AX = Global Code Page
814 procedure Get_Global_CdPg
,NEAR
815 ASSUME
DS:NOTHING
,ES:NOTHING
817 MOV SI,OFFSET DOSGROUP
:COUNTRY_CDPG
818 MOV AX,CS:[SI.ccDosCodePage
]
821 EndProc Get_Global_CdPg
823 ;-------------------------------Start of DBCS 2/13/KK
824 BREAK <ECS_call
- Extended
Code System support function
>
826 ASSUME
DS:NOTHING
, ES:NOTHING
828 procedure $ECS_call
,NEAR
831 ; AL = 0 get lead byte table
832 ; on return DS:SI has the table location
834 ; AL = 1 set / reset interim console flag
835 ; DL = flag (00H or 01H)
838 ; AL = 2 get interim console flag
839 ; on return DL = current flag value
841 ; AL = OTHER then error, and returns with:
842 ; AX = error_invalid_function
844 ; NOTE: THIS CALL DOES GUARANTEE THAT REGISTER OTHER THAN
845 ; SS:SP WILL BE PRESERVED!
849 or al, al ; AL = 0 (get table)? ;AN000;
851 cmp al, SetInterimMode
; AL = 1 (set / reset interim flag)? ;AN000;
852 je set_interim
;AN000;
853 cmp al, GetInterimMode
; AL = 2 (get interim flag)? ;AN000;
854 je get_interim
;AN000;
855 error error_invalid_function
;AN000;
857 get_lbt: ; get lead byte table ;AN000;
862 MOV BX,offset DOSGROUP
:COUNTRY_CDPG
.ccSetDBCS
;AN000;
863 MOV AX,[BX+1] ; set EV address to DS:SI ;AN000;
864 MOV BX,[BX+3] ;AN000;
865 ADD AX,2 ; Skip Lemgth ;AN000;
866 invoke get_user_stack
;AN000;
867 assume
ds:nothing
;AN000;
868 MOV [SI.user_SI
], AX ;AN000;
869 MOV [SI.user_DS
], BX ;AN000;
873 transfer SYS_RET_OK
;AN000;
875 set_interim: ; Set interim console flag ;AN000;
877 and dl,01 ; isolate bit 1 ;AN000;
878 mov [InterCon
], dl ;AN000;
880 mov ds, [CurrentPDB
] ;AN000;
881 mov byte ptr ds:[PDB_InterCon
], dl ; update value in pdb ;AN000;
884 transfer SYS_RET_OK
;AN000;
889 mov dl,[InterCon
] ;AN000;
890 invoke get_user_stack
; get interim console flag ;AN000;
891 assume
ds:nothing
;AN000;
892 mov [SI.user_DX
],DX ;AN000;
895 transfer SYS_RET_OK
;AN000;
897 or al, al ; AL = 0 (get table)? ;AN000;
900 invoke get_user_stack
;AN000;
901 assume
ds:nothing
;AN000;
902 MOV [SI.user_SI
], Offset Dosgroup
:DBCS_TAB
+2 ;AN000;
903 MOV [SI.user_DS
], CS ;AN000;
905 transfer SYS_RET_OK
; ;AN000;
909 $ECS_call endp
;AN000;