MISC.A86
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:48k
源码类别:

操作系统开发

开发平台:

Asm

  1. ;    File              : $MISC.A86$
  2. ;
  3. ;    Description       :
  4. ;
  5. ;    Original Author   : DIGITAL RESEARCH
  6. ;
  7. ;    Last Edited By    : $CALDERA$
  8. ;
  9. ;-----------------------------------------------------------------------;
  10. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  11. ;      
  12. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  13. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  14. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  15. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  16. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  17. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  18. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  19. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  20. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  21. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  22. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  23. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  24. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  25. ;    CIVIL LIABILITY.
  26. ;-----------------------------------------------------------------------;
  27. ;
  28. ;    *** Current Edit History ***
  29. ;    *** End of Current Edit History ***
  30. ;    $Log$
  31. ;    MISC.A86 1.29 94/11/30 14:40:17
  32. ;    fixed error return for function 6602
  33. ;    MISC.A86 1.28 94/07/13 15:31:04 
  34. ;    Pass name to share on Int21/5D02 (close file by name)
  35. ;    MISC.A86 1.27 93/11/29 14:18:16
  36. ;    Fix bug in get extended country info if not current country
  37. ;    MISC.A86 1.25 93/11/19 17:00:14
  38. ;    If 21/38 get country info fails for current codepage, try any codepage
  39. ;    MISC.A86 1.24 93/11/16 15:57:08
  40. ;    int 21/5D06 clears CY flag 
  41. ;    MISC.A86 1.23 93/10/21 19:31:16
  42. ;    Move Int 21/5D03+5D04 support (close all files by machine/psp) into share
  43. ;    MISC.A86 1.22 93/10/18 17:41:45
  44. ;    fix for >255 open files (PNW Server)
  45. ;    MISC.A86 1.21 93/09/03 20:28:57
  46. ;    Add intl/dbcs support for int 21/6523 (query yes/no char)
  47. ;    MISC.A86 1.20 93/07/26 20:42:13
  48. ;    Seperate int21/3306 
  49. ;    MISC.A86 1.12 93/03/05 18:12:33
  50. ;    Fix DS corruption for NLSFUNC calls
  51. ;    ENDLOG
  52. ;
  53. VALID_SIG equ 0EDC1h
  54. include pcmode.equ
  55. include i:msdos.equ
  56. include i:mserror.equ
  57. include i:psp.def
  58. include i:driver.equ
  59. include i:char.def
  60. include i:country.def
  61. include i:doshndl.def
  62. include i:redir.equ
  63. include i:fdos.equ
  64. NLSFUNC equ TRUE
  65. ;
  66. GLOBAL_DATA DSEG WORD
  67. extrn default_country:byte
  68. extrn Ucasetbl:word
  69. extrn FileUcasetbl:word
  70. extrn FileCharstbl:word
  71. extrn Collatingtbl:word
  72. extrn DBCS_tbl:word
  73. extrn NoYesChars:byte
  74. extrn info1_len:abs
  75. extrn info2_len:abs
  76. extrn info4_len:abs
  77. extrn info5_len:abs
  78. extrn info6_len:abs
  79. extrn info7_len:abs
  80. extrn dos_version:word
  81. extrn country_filename:byte
  82. PCM_CODE CSEG BYTE
  83. extrn dbcs_lead:near
  84. extrn device_write:near ; Write to a Character Device
  85. extrn device_read:near ; Read from a Character Device
  86. extrn dos_entry:near
  87. extrn error_exit:near
  88. extrn error_ret:near
  89. extrn func5F_common:near
  90. extrn get_dseg:near
  91. extrn valid_drive:near
  92. extrn ifn2dhndl:near
  93. extrn int21_func:near
  94. extrn invalid_function:near
  95. extrn patch_version:word
  96. extrn reload_registers:near
  97. extrn reload_ES:near
  98. extrn return_AX_CLC:near
  99. extrn return_BX:near
  100. extrn return_CX:near
  101. extrn return_DX:near
  102. extrn toupper:near
  103. extrn xlat_xlat:word
  104. ;
  105. ; *****************************
  106. ; ***    DOS Function 34    ***
  107. ; ***   Get The Indos Flag  ***
  108. ; *****************************
  109. Public func34
  110. func34:
  111. mov bx,offset indos_flag
  112. ; jmp return_DSBX_as_ESBX ; return ES:BX -> indos flag
  113. Public return_DSBX_as_ESBX
  114. return_DSBX_as_ESBX:
  115. ;-------------------
  116. ; On Entry:
  117. ; DS:BX to be returned to caller in ES:BX
  118. ; On Exit:
  119. ; ES/DI trashed
  120. ;
  121. les di,ss:int21regs_ptr
  122. mov es:reg_ES[di],ds
  123. mov es:reg_BX[di],bx
  124. ret
  125. ;
  126. ; *****************************
  127. ; ***    DOS Function 52    ***
  128. ; ***   Get Internal Data   ***
  129. ; *****************************
  130. ;
  131. ;
  132. Public func52
  133. func52:
  134. mov bx,offset func52_data
  135. jmps return_DSBX_as_ESBX ; return ES:BX -> internal data
  136. ;
  137. ; *****************************
  138. ; ***    DOS Function 5D    ***
  139. ; ***    Private DOS Func   ***
  140. ; *****************************
  141. ;
  142. ;
  143. Public func5D
  144. func5D:
  145. if DOS5
  146. cmp al,7
  147.  jae f5d_05
  148. mov si,dx ; ES:SI -> callers structure
  149. mov bx,es:word ptr 20[si]
  150. mov ss:owning_psp,bx ; update PSP from there
  151. cmp WindowsHandleCheck,26h
  152.  jne f5D_05 ; check if Windows is running
  153. mov bx,es:word ptr 18[si]
  154. mov ss:machine_id,bx ; no, update machine_id
  155. f5D_05:
  156. else
  157. push ds
  158. push es ! pop ds ; restore users DS
  159. callf ss:win386_remote_machine
  160. pop ds
  161. endif
  162. cbw ; zero AH for valid functions
  163. xchg ax,bx ; sub function in BX
  164. cmp bx,func5D_ftl ; Assume Illegal Subfunction
  165.  jb f5D_10 ; check that it is a valid
  166. mov bx,func5D_ftl ;  subfunction
  167. f5D_10:
  168. shl bx,1
  169. push func5D_ft[bx] ; save function address
  170. shr bx,1
  171. xchg ax,bx ; restore BX
  172. ret ; go to function
  173. f5D_msnet:
  174. mov ax,I2F_REDIR_5D ; magic number to redirect
  175. jmp func5F_common ;  calls to extentions
  176. ;
  177. ;
  178. ; The registers for some of the following sub-functions are passed
  179. ; in the following structure.
  180. ;
  181. RDC_AX equ es:word ptr 00[di] ; User AX
  182. RDC_BX equ es:word ptr 02[di] ; User BX
  183. RDC_CX equ es:word ptr 04[di] ; User CX
  184. RDC_DX equ es:word ptr 06[di] ; User DX
  185. RDC_SI equ es:word ptr 08[di] ; User SI
  186. RDC_DI equ es:word ptr 10[di] ; User DI
  187. RDC_DS equ es:word ptr 12[di] ; User DS
  188. RDC_ES equ es:word ptr 14[di] ; User ES
  189. RDC_RES equ es:word ptr 16[di] ; Remote Machine ID (High Word)
  190. RDC_UID equ es:word ptr 18[di] ; Remote Machine ID (Low Word)
  191. RDC_PID equ es:word ptr 20[di] ; Process ID
  192. ;
  193. ; *****************************
  194. ; ***   DOS Function 5D00   ***
  195. ; ***   Remote DOS Call     ***
  196. ; *****************************
  197. ;
  198. ;
  199. f5D00:
  200. mov remote_call,0ffh ; set remote op flag
  201. push es
  202. les di,int21regs_ptr ; stack image the copy registers
  203. pop ds
  204. mov cx,6
  205. rep movsw ; Copy AX, BX, CX, DX, SI, DI
  206. inc di ! inc di ; Skip BP in the destination
  207. movsw ! movsw ; finally copy DS and ES
  208. push ss ! pop ds ; DS -> PCMDSEG
  209. call reload_registers ; load up the new registers
  210. jmp int21_func ;  then execute that function
  211. ; *****************************
  212. ; ***   DOS Function 5D01   ***
  213. ; ***    Commit all files   ***
  214. ; *****************************
  215. ;
  216. f5D01:
  217. ;-----
  218. ; We are being asked to commit all files to disk
  219. ; By pretending to be FCB's we force use of IFN's, and we commit all possible
  220. ; files in the range 0-255, ignoring errors from unopened handles.
  221. ;
  222. mov remote_call,DHM_FCB ; pretend to be FCB, forces use of IFN
  223. xor bx,bx ; start with handle zero
  224. f5D01_10:
  225. mov ah,MS_X_COMMIT
  226. call dos_entry ; commit this file
  227. inc bx ; onto next candidate
  228. cmp bx,0FFh ; runout yet ?
  229.  jb f5D01_10 ;
  230. ret
  231. ; *****************************
  232. ; ***   DOS Function 5D02   ***
  233. ; ***   Close file by name  ***
  234. ; *****************************
  235. ;
  236. f5D02:
  237. ;-----
  238. ; Close file by name. We do a search first to find out about the file.
  239. ; As long as it's local we call share with the directory cluster/index
  240. ; to close it if it's open.
  241. ;
  242. mov di,dx ; ES:DI -> register block
  243. mov dx,RDC_DX
  244. mov es,RDC_DS ; ES:DX -> filename to close
  245. push dma_offset
  246. push dma_segment
  247. mov dma_offset,offset fcb_search_buf
  248. mov dma_segment,ds
  249. mov cx,DA_RO+DA_SYSTEM+DA_HIDDEN
  250. mov ah,MS_X_FIRST ; look for this file
  251. call dos_entry ;  to get dir entry info
  252. pop dma_segment
  253. pop dma_offset
  254.  jc f5Dret
  255. mov al,fcb_search_buf ; get drive #
  256. test al,al ; reject networked drives
  257.  js f5Dret
  258. dec ax ; make drive zero based
  259. mov cx,word ptr fcb_search_buf+0Dh
  260. ; CX = directory count
  261. mov dx,word ptr fcb_search_buf+0Eh
  262. ; DX = parent directory cluster
  263. lea bx,fcb_search_buf+1 ; DS:BX -> name
  264. mov di,S_CLOSE_IF_OPEN
  265. ; jmps f5D_common
  266. f5D_common:
  267. callf lock_tables ; protect SHARE with a critical section
  268. callf share_stub[di]
  269. callf unlock_tables ; safe again
  270. f5Dret:
  271. ret
  272. ; *****************************
  273. ; ***   DOS Function 5D03   ***
  274. ; *** Close files by machine***
  275. ; *****************************
  276. ;
  277. ; *****************************
  278. ; ***   DOS Function 5D04   ***
  279. ; *** Close by Machine/PSP  ***
  280. ; *****************************
  281. f5D03:
  282. f5D04:
  283. ;-----
  284. ; Close all files for given PSP
  285. ;
  286. mov di,S_CLOSE_FILES
  287. jmps f5D_common
  288. ; *****************************
  289. ; ***   DOS Function 5D05   ***
  290. ; *****************************
  291. ;
  292. f5D05:
  293. ; On Entry:
  294. ; RDC.BX = Share File # to look to
  295. ; RDC.CX = Share Record # to look for
  296. ; On Exit:
  297. ; AX = DOSHNDL Attribute Word
  298. ; BX = machine ID
  299. ; CX = locked blocks count
  300. ; ES:DI -> buffer containing full pathname
  301. ;
  302. ;
  303. callf lock_tables ; protect SHARE with a critical section
  304. callf share_stub+S_GET_LIST_ENTRY
  305. callf unlock_tables ; safe again
  306.  jnc f5Dret ; just return if it went OK
  307. jmp error_ret ;  else return error code in AX
  308. ; *****************************
  309. ; ***   DOS Function 5D06   ***
  310. ; ***   Get Internal Data   ***
  311. ; *****************************
  312. ;
  313. f5D06:
  314. mov cx,offset swap_indos ; Calculate Size of Swap
  315. sub cx,offset internal_data ; Swap INDOS Array
  316. call return_CX ; CX = Swap Indos length
  317. mov dx,offset swap_always ; Calculate Size of Swap
  318. sub dx,offset internal_data ; Swap ALWAYS Array
  319. call return_DX ; DX = Swap Always length
  320. mov si,offset internal_data
  321. call return_DSSI
  322. mov ax,5D06h
  323. jmp return_AX_CLC
  324. ;
  325. ; *****************************
  326. ; ***   DOS Function 5D0A   ***
  327. ; ***Set Extended Error Info***
  328. ; *****************************
  329. ;
  330. f5D0A:
  331. mov si,dx ; ES:SI -> parameter block
  332. lods es:word ptr [si]
  333. mov error_code,ax ; copy the appropriate fields
  334. lods es:word ptr [si]
  335. mov error_class,ah
  336. mov error_action,al
  337. lods es:word ptr [si]
  338. mov error_locus,ah
  339. add si,2*WORD ; skip to device
  340. lods es:word ptr [si]
  341. mov error_dev,ax
  342. lods es:word ptr [si]
  343. mov error_dev+2,ax
  344. xor ax,ax ; return AL=0
  345. ret
  346. ;
  347. ; *****************************
  348. ; *** Get switch character  ***
  349. ; *****************************
  350. ;
  351. ;
  352. Public func37
  353. func37:
  354. cmp al,1 ! jb f37_getswitch ; Get the current Switch Character
  355.    je f37_setswitch ; Set the Switch Character
  356. cmp al,3 ! je f37_s03 ; Sub-Func 03 Return Unchanged
  357. mov dl,0ffh ! jb f37_return_DX ; Sub-Func 02 Return DL == 0FFh
  358. mov al,0FFh ; else invalid sub-function
  359. f37_s03:
  360. ret
  361. f37_getswitch:
  362. mov dl,switch_char
  363. f37_return_DX:
  364. jmp return_DX ; return current setting in DX
  365. f37_setswitch:
  366. mov switch_char,dl
  367. ret
  368. ;**************************************************
  369. ;**************************************************
  370. ;*** ***
  371. ;***   Miscellaneous Isolated Functions ***
  372. ;*** ***
  373. ;**************************************************
  374. ;**************************************************
  375. ;
  376. ; *****************************
  377. ; ***    DOS Function 30    ***
  378. ; ***   Get Version Number  ***
  379. ; *****************************
  380. Public func30
  381. func30:
  382. if DOS5
  383. mov es,current_psp ; version is kept in the PSP
  384. mov ax,PSP_VERSION
  385. else
  386. mov ax,dos_version ; version returned in AX
  387. endif
  388. ReturnVersionNumber:
  389. xor bx,bx ; zero BX and CX
  390. xor cx,cx
  391. call return_BX
  392. call return_CX
  393. jmp return_AX_CLC
  394. ;
  395. ; *****************************
  396. ; ***    DOS Function 33    ***
  397. ; ***  Get/Set Cntl-Break   ***
  398. ; *****************************
  399. Public func33
  400. ; WARNING - called on USER stack
  401. func33:
  402. cmp al,2 ; range check subfunction
  403.  jbe f33_10
  404. mov dl,bootDrv ; assume we want boot drive
  405. cmp al,5 ; did we ?
  406.  je f33_30
  407. if DOS5
  408. cmp al,6 ; get true version ?
  409.  je f33_60
  410. endif
  411. mov reg_AL[bp],0FFh ; return AL = FF
  412. ret ; Illegal function request
  413. f33_10:
  414. and dl,01h ; force a valid value
  415. cmp al,1 ; check for get or set
  416.  jae f33_20
  417. mov dl,break_flag ; it's a get, so use existing setting
  418. f33_20:
  419. xchg dl,break_flag ; replace current setting
  420.  je f33_40
  421. f33_30:
  422. mov reg_DL[bp],dl ; return setting in DL
  423. f33_40:
  424. ret
  425. if DOS5
  426. f33_60:
  427. mov reg_BX[bp],TRUE_VERSION ; return version number
  428. mov ax,patch_version
  429. mov reg_DX[bp],ax ; return revision+HMA
  430. ret
  431. endif
  432. ;
  433. ; *****************************
  434. ; ***    DOS Function 25    ***
  435. ; ***  Set Interrupt Vector ***
  436. ; *****************************
  437. ;
  438. ; WARNING - use no stack as device drivers have called us re-entrantly
  439. Public func25
  440. func25:
  441. mov bx,es ; is really dos_DS - save for later
  442. xor di,di ; replace with the values in dos_DS:DX
  443. mov es,di ; es -> zero segment
  444. xor ah,ah ; the interrupt number
  445. mov di,ax ; 0:di -> vector
  446. shl di,1 ! shl di,1 ; 4 bytes per vector
  447. cli
  448. xchg ax,dx ; Get New Offset
  449. stosw ; and Save
  450. xchg ax,bx ; Get New Segment
  451. stosw ; and Save
  452. sti
  453. xchg ax,dx ; recover entry AL to (preserve it)
  454. ret
  455. ; *****************************
  456. ; ***    DOS Function 35    ***
  457. ; ***  Get Interrupt Vector ***
  458. ; *****************************
  459. ; WARNING - use no stack as device drivers have called us re-entrantly
  460. Public func35
  461. func35:
  462. xor bx,bx
  463. mov ds,bx ; DS:0 -> vector table
  464. mov bl,al ; BX = the interrupt number
  465. shl bx,1 ! shl bx,1 ; 4 bytes per vector
  466. lds bx,ds:dword ptr [bx] ; DS:BX -> vector
  467. les di,ss:int21regs_ptr
  468. mov es:reg_BX[di],bx
  469. mov es:reg_ES[di],ds
  470. jmp get_dseg ; restore DS for return
  471. ;PC-DOS Verify and Break Flags Support
  472. ;
  473. ; *****************************
  474. ; ***    DOS Function 2E    ***
  475. ; ***    Set/Reset Verify   ***
  476. ; *****************************
  477. Public func2E
  478. func2E:
  479. and al,1 ; only use bottom bit
  480. mov verify_flag,al ; store for use later
  481. ret
  482. ; *****************************
  483. ; ***    DOS Function 54    ***
  484. ; ***  Get Verify Setting   ***
  485. ; *****************************
  486. Public func54
  487. func54:
  488. mov al,verify_flag ; return verify flag
  489. ret
  490. ; *****************************
  491. ; ***    DOS Function 63    ***
  492. ; ***  Get Lead Byte Table  ***
  493. ; *****************************
  494. ;
  495. Public func63
  496. func63:
  497. cmp al, 1 ; subfunction #?
  498.  jb f63_get_tbl ; subfunction 0
  499.  je f63_set_flg ; subfunction 1
  500. cmp al, 2 ; subfunction 2?
  501.  je f63_get_flg ;  yes
  502. mov ax, ED_FUNCTION ; invalid subfunction number
  503. jmp error_exit ; so quit
  504. f63_get_flg:
  505. ; Get the current state of the DOS interim character console flag.
  506. ; If this flag is set int 21h functions 07h, 08h, 0Bh, 0Ch are supposed
  507. ; to return "interim character information" which I assume is incomplete
  508. ; characters. (In languages like Korean a given double byte character
  509. ; may be built by the user entering several keystrokes which form
  510. ; incomplete characters.)
  511. mov es, current_psp
  512. mov dl, PSP_RIC ; Return Interim Character flag
  513. jmp return_DX ; flag returned in dl
  514. f63_set_flg:
  515. ; Set the current state of the DOS interim character console flag.
  516. ; dos_DL = 0 - clear flag, dos_DL = 1 - set flag
  517. mov es, current_psp
  518. mov PSP_RIC, dl ; record flag
  519. ret
  520. f63_get_tbl:
  521. ; Get the current DBCS table address.
  522. mov si,offset DBCS_tbl+2; skip the table size entry
  523. ; jmp return_DSSI
  524. return_DSSI:
  525. ;-----------
  526. ; On Entry:
  527. ; DS:SI to be returned to caller
  528. ; On Exit:
  529. ; AX preserved
  530. ;
  531. les di,ss:int21regs_ptr
  532. mov es:reg_DS[di],ds
  533. mov es:reg_SI[di],si
  534. ret
  535. ;
  536. ; *****************************
  537. ; ***    DOS Function 29    ***
  538. ; ***     Parse String      ***
  539. ; *****************************
  540. Public func29
  541. func29:
  542. ;
  543. ; Entry:
  544. ;    DS:SI  -> line to parse
  545. ;    ES:DI  -> resulting fcb
  546. ; Exit:
  547. ;    DS:SI  -> terminating delimeter past parsed filename
  548. ;    ES:DI  -> filled in fcb (Affects 16 bytes:  DnnnnnnnnTTT0000)
  549. ;
  550. push ds
  551. push es
  552. call reload_ES
  553. pop ds
  554. call parse
  555. call return_DSSI ; return result of parse
  556. pop ds
  557. mov al,dh ; return result in AL
  558. ret
  559. ;-----
  560. parse: ; parse DOS filename delimited by TAB,SPACE,or .,+:;=|"/[]<> or ctrl
  561. ;-----
  562. ; Entry:
  563. ;    DS:SI  -> line to parse
  564. ;    ES:DI  -> fcb to parse into
  565. ; AL  == bit options:
  566. ; Bit 0 == 1:  scan off leading delimiters
  567. ; Bit 1 == 1:  change drive only if specified
  568. ; Bit 2 == 1:  change name   " "     "
  569. ; Bit 3 == 1:  change type   " "     "
  570. ; Exit:
  571. ;    DS:SI  -> terminating delimeter past parsed filename
  572. ;    ES:DI  -> filled in fcb (Affects 16 bytes:  DnnnnnnnnTTT0000)
  573. ; DH  == 1 if wild, 0FFh if the drive is invalid, 0 otherwise
  574. ;
  575. push di ; (<--keep DI last on stack)
  576. cld ; ChSh
  577. xor dx,dx ; DH = default return value (0)
  578. xchg al,dl ; put flags into DL, AL = 0
  579. mov cx,1
  580. test dl,0010b ; should we initialize drive?
  581. call nz_store_al ; do conditional store
  582. mov al,' ' ; use spaces for filename & typ
  583. mov cl,8
  584. test dl,0100b ; should we initialize the name?
  585. call nz_store_al
  586. mov cl,3
  587. test dl,1000b ; should we initialize the typ?
  588. call nz_store_al
  589. xor ax,ax ; zero-out the 4 post-typ bytes
  590. stos ax
  591. stos ax
  592. pop di ! push di ; restore DI to start of FCB
  593. deblank_loop:
  594. lods al ; grab char
  595. cmp al,' ' ; is it a blank?
  596.  je deblank_loop ;  Y: keep looping
  597. cmp al,'I'-'@' ; is it a tab?
  598.  je deblank_loop ;  Y: keep looping
  599. test dl,0001b ; skip-delimiter-bit set?
  600.  jz parse_drive ;  N: go start parsing
  601. skip_delim_loop:
  602. call check_delimiters ; check AL for delimiterness
  603.  jb parse_dec_ret ; found terminator, dec SI & leave
  604. mov dl,dh ; flag no-more-delimiter-skip (DL = 0)
  605.  je  deblank_loop ; found separator, go deblank after it
  606. parse_drive:
  607. dec si
  608. cmp byte ptr 1[si],':' ; is the drive specified?
  609.  jne parse_name
  610. lods ax ; get drive, junk colon
  611. and al,01011111b ; upper case it
  612. sub al,'@' ; AL = 1-relative drive #
  613. push ax ! push ds ; Save the drive code and call
  614. call get_dseg ; Restore our Data Segment
  615. call valid_drive ; routine to validate drive ZR == OK
  616. pop ds ! pop ax ; Restore drive code and User DS
  617.  jz parse_d10
  618. dec dh ; flag drive error (0FFh)
  619. parse_d10:
  620. mov es:[di],al ; insert drive in fcb
  621. parse_name:
  622. inc di ; DI -> fname
  623. mov cx,8
  624. call parse_item ; parse an up-to 8 char filename
  625. cmp dl,'.' ; was the delimeter a '.'?
  626.  jne parse_dec_ret ;  N:  the parse is complete
  627. mov cl,3
  628. call parse_item ; parse an up-to 3 char filetype
  629. parse_dec_ret:
  630. dec si ; bump SI back to point to delimeter
  631. parse_ret:
  632. pop di
  633. ret
  634. ;-----------
  635. nz_store_al:
  636. ;-----------
  637. ; Entry:
  638. ; DI  -> destination to conditionally initialize
  639. ; CX  == length of destination
  640. ; AL  == byte to initialize with
  641. ; ZF set: do not initialize destination
  642. ; Exit:
  643. ; DI  -> past destination (initial DI+CX)
  644. ; Changed:
  645. ; CX,DI
  646. ;
  647.  jnz skip_store ; should we initialize?
  648. rep stosb ;  Y: store them bytes
  649. skip_store:
  650. add di,cx ; bump DI to post-dest position
  651. ret
  652. ;==========
  653. parse_item: ; Parses item into fcb if item is specified
  654. ;==========
  655. ;
  656. ; Entry:
  657. ; SI  -> item to parse (name or type)
  658. ; DI  -> fcb area to parse it into
  659. ; CX  == length of item
  660. ; DH  == parse_return
  661. ; Exit:
  662. ; SI  -> past ending delimeter
  663. ; DI  -> past fcb area (initial DI + CX)
  664. ; CH  == If zero on enter zero on exit else 0-255
  665. ; DH  == updated parse_return w/possible wild bit set
  666. ; DL  == character delimiter @(SI-1)
  667. ; Changed:
  668. ; AX,CX,DX,SI,DI
  669. ;
  670. mov ah,FALSE ; specified item flag
  671. parse_item_loop:
  672. lods al ; get char
  673. call check_delimiters ; is it a delimiter?
  674. jbe pi_pad_ret ;  Y:  the parse is complete
  675. jcxz parse_item_loop ; if the name is full, skip the char
  676. mov ah,al ; flag name as present
  677. cmp al,'?' ; is it a single wild char?
  678. je pi_set_wild ;  Y: set wild flag
  679. cmp al,'*' ; is it a multi-char wild card?
  680. jne pi_store ;  N: store it
  681. mov al,'?' ;  Y: fill with '?' to end of name
  682. rep stosb
  683. pi_set_wild:
  684. or dh,1 ; set wild flag
  685. jcxz parse_item_loop ; skip store if name is now filled
  686. pi_store:
  687. dec cx ; another char done
  688. call dbcs_lead ; is it the 1st byte of kanji ?
  689.  jne pi_store10
  690. inc si ; skip 2nd byte
  691.  jcxz parse_item_loop ; can I copy both ?
  692. dec cx ; yes, do so
  693. stosb
  694. dec si ; point at second byte
  695. lodsb ;  so we can copy it too..
  696. pi_store10:
  697. stos al ; put the char in the fcb
  698. jmps parse_item_loop
  699. pi_pad_ret:
  700. mov dl,al ; DL = ending delimeter
  701. or ah,ah ; the the item specified?
  702.  jz pi_ret ;  N: skip padding
  703. mov al,' ' ;  Y: pad to end with spaces
  704. rep stosb
  705. pi_ret:
  706. add di,cx ; bump DI out to end
  707. ret
  708. ;----------------
  709. check_delimiters:
  710. ;----------------
  711. ;
  712. ; Entry:
  713. ; AL  == char to check in list of delimiters
  714. ; Exit:
  715. ; AL  == char changed to uppercase
  716. ; CF set if it is one of the terminators:  |"/[]<>  & ctrl chars != TAB
  717. ; ZF set if it is one of the separators:   .,+:;=    SPACE & TAB
  718. ;        OR one of the non-ctrl terminators
  719. ;
  720. cmp al,'a' ; check for lower case
  721. jb not_lower
  722. cmp al,'z'
  723. ja not_lower
  724. and al,01011111b ; uppercase it, CF clear, ZF clear
  725. ret
  726. not_lower:
  727. push cx ! push di ! push es
  728. push cs ! pop  es ; ES = Code segment
  729. mov di,offset parse_separators
  730. mov cx,length parse_separators
  731. repne scasb ; is AL a separator?
  732. je cpd_pop_ret ;  Y: return ZF set
  733. mov cl,length parse_terminators
  734. repne scasb ; is AL a terminator?
  735.  stc ;  (set CF if true)
  736. je cpd_pop_ret ;  Y: return CF & ZF set
  737. cmp al,' ' ; (AL == ' ') ZF set, (AL < ' ') CF set
  738. cpd_pop_ret:
  739. pop es ! pop  di ! pop  cx
  740. ret
  741. ;
  742. ; *****************************
  743. ; ***    DOS Function 2A    ***
  744. ; ***  Get Current Date     ***
  745. ; *****************************
  746. Public func2A
  747. func2A:
  748. ;
  749. ; entry: None
  750. ;
  751. ; exit: cx = year (1980-2099)
  752. ; dh = month (1-12)
  753. ; dl = day (1-31)
  754. ; al = DOS returns day of week here
  755. ;
  756. call ReadTimeAndDate ; Get the current Time and Date
  757. mov cx,1980
  758. add cx,yearsSince1980
  759. ; mov dl,dayOfMonth
  760. ; mov ah,month
  761. mov dx,word ptr dayOfMonth
  762. mov al,dayOfWeek
  763. jmps f2C_10 ; exit via common routine
  764. ; *****************************
  765. ; ***    DOS Function 2C    ***
  766. ; ***  Get Current Time     ***
  767. ; *****************************
  768. Public func2C
  769. func2C:
  770. ;
  771. ; entry: None
  772. ;
  773. ; exit: ch = hours (0-23)
  774. ; cl = minutes (0-59)
  775. ; dh = seconds (0-59)
  776. ; dl = Hunredths seconds (0-99)
  777. ; al = 0
  778. ;
  779. call ReadTimeAndDate ; Get the current Time and Date
  780. mov cx,biosDate+2 ; Get the Hour and Minute
  781. mov dx,biosDate+4 ; Get the Seconds and Hundredths
  782. xor ax,ax ; return AL = 0
  783. f2C_10:
  784. call return_CX ; and return to caller
  785. jmp return_DX
  786. ; *****************************
  787. ; ***    DOS Function 2B    ***
  788. ; ***  Set Current Date     ***
  789. ; *****************************
  790. Public func2B
  791. func2B:
  792. ;
  793. ; entry: cx = year (1980-2099)
  794. ; dh = month (1-12)
  795. ; dl = day (1-31)
  796. ;
  797. ; exit: al = 00H success
  798. ;    = FFH failure
  799. ;
  800. call ConvertDate ; Convert to BIOS date
  801.  jc f2B_20 ; Abort on Error
  802. push cx ; save the converted date
  803. call ReadTimeAndDate ; Get the current Time and Date
  804. pop biosDate ; new date, existing time
  805. f2B_10: ; Set the current Time and Date
  806. call rw_clock_common ; make sure clock is there/setup regs
  807. call device_write ; Update the Date and Time
  808. xor ax,ax
  809. ret
  810. f2B_20:
  811. mov al,0FFh ; return FAILURE
  812. ret
  813. ; *****************************
  814. ; ***    DOS Function 2D    ***
  815. ; ***  Set Current Time     ***
  816. ; *****************************
  817. Public func2D
  818. func2D:
  819. ;
  820. ; entry: ch = hours (0-23)
  821. ; cl = minutes (0-59)
  822. ; dh = seconds (0-59)
  823. ; dl = hundredth seconds (0-99)
  824. ;
  825. ; exit: al = 00H success
  826. ;    = FFH failure
  827. ;
  828. cmp ch,23 ; Range check hours
  829.  ja f2B_20
  830. cmp cl,59 ; Range check minutes
  831.  ja f2B_20
  832. cmp dh,59 ; Range check seconds
  833.  ja f2B_20
  834. cmp dl,99 ; Range check hundredths
  835.  ja f2B_20
  836. push cx ; save hours/mins
  837. push dx ; save secs/hundredths
  838. call ReadTimeAndDate ; Get the current Time and Date
  839. pop biosDate+4 ; leave the date alone
  840. pop biosDate+2 ;  but update the time
  841. jmps f2B_10 ; Update the Date and Time
  842. Public ReadTimeAndDate
  843. ReadTimeAndDate: ; Get the current Time and Date
  844. call rw_clock_common ; make sure clock is there/setup regs
  845. call device_read ; read the Date and Time
  846. mov ax,biosDate ; get the BIOS date and convert
  847. cmp ax,daysSince1980 ; (but only if necessary)
  848.  jne NewDate
  849. ret
  850. NewDate:
  851. mov daysSince1980,ax ; so we won't have to convert next time
  852. inc ax ; Day number starting 1 Jan 1980
  853. mov cx,ax ; save day count
  854. inc ax ; convert to a sunday as 1/1/80 is tues
  855. xor dx,dx
  856. mov bx,7
  857. div bx
  858. mov dayOfWeek,dl ; save day of week
  859. xor dx,dx
  860. mov ax,cx ; recover day count
  861. xor di,di ; assume zero leap days
  862. sub ax,60 ; less than 60 days
  863.  jc no_leap_days ; means no leap days to subtract
  864. mov bx,1461 ; 1461 = days in four years
  865. div bx ; get number of leap years since 1980
  866. inc ax ; include 1980
  867. sub cx,ax ; normalize years to 365 days
  868. mov di,ax ; save proper leap day count
  869. no_leap_days:
  870. xor dx,dx
  871. xchg ax,cx ; DX:AX = years since 1980 * 365
  872. mov bx,365
  873. div bx ; get number of years since 1980
  874. or dx,dx ; check for zero days left
  875.  jnz days_left
  876. dec ax ; dec year count
  877. mov dx,365 ; set day count to last day of last year
  878. days_left:
  879. mov yearsSince1980,ax ; save the year
  880. xchg ax,si ; save in SI
  881. xor bx,bx
  882. mov cx,12
  883. get_month: ; find the appropriate month
  884. cmp dx,totaldays[bx]
  885.  jbe got_month
  886. inc bx ! inc bx
  887. loop get_month
  888. got_month:
  889. shr bx,1 ; BX = month
  890. mov month,bl
  891. dec bx
  892. shl bx,1 ; BX = index to previous months
  893. sub dx,totaldays[bx] ; get days into this month
  894. cmp bx,2 ; if it's FEB 29th we've lost a day
  895.  jne not_leap_yr ; check it's FEB
  896. test si,3
  897.  jnz not_leap_yr ; but is it a leap year ?
  898. shr si,1 ! shr si,1 ; divide years by 4
  899. inc si ; include this year
  900. cmp si,di ; compare against leap day adjustment
  901.  jne not_leap_yr
  902. inc dx ; put 29th feb back again
  903. not_leap_yr:
  904. mov dayOfMonth,dl ; save the day of the month
  905. ret
  906. ConvertDate:
  907.     sub cx,1980         ; Base year is 1980
  908. jc xset_date_error
  909. cmp cx,2100-1980 ; Year in valid range ?
  910. jnc xset_date_error
  911. mov bl,dh ; Month to BL
  912. xor bh,bh
  913. dec bx ; Adjust month to 0-11
  914. cmp bl,12 ; Month in valid range ?
  915. jnc xset_date_error
  916. mov al,dl ; Day of month
  917. cbw
  918. test cl,3 ; Leap year ?
  919. jnz not_leap_year ; Jump if not
  920. cmp dh,3 ; After February ?
  921. cmc
  922. adc al,ah ; Increment days in current year if so
  923. cmp dl,29 ; Day of month 29 ?
  924. jz day_valid ; Valid if so
  925. not_leap_year:
  926. dec dx
  927. cmp dl,monthdays[bx] ; Day of month within range for non-leap
  928. ; year ?
  929. jnc xset_date_error
  930. day_valid:
  931. shl bx,1
  932. add ax,totaldays[bx] ; Get total days in current year
  933. push ax
  934. mov ax,365
  935. mul cx ; Convert year to days since 1-1-1980
  936. mov cx,ax
  937. ; if total (ax) >= 60 (Feb 29 1980) then
  938. ;   leap$days = (total - 60) / (365 * 4) + 1
  939. sub ax,60 ; Before first leap year date
  940. jc noleap ; Jump if so
  941. mov bx,365*4 ; 4 years worth of days (365 * 4)
  942. sub dx,dx
  943. div bx ; Get number of leap years - 1
  944. inc ax
  945. add cx,ax ; CX now has total days including leap
  946. ; days
  947. noleap:
  948. dec cx
  949. pop ax
  950. add cx,ax ; Get total days since 1-1-1980
  951. clc
  952. ret
  953. xset_date_error:
  954. stc
  955. ret
  956. rw_clock_common:
  957. mov cx,6 ; read/write 6 characters
  958. mov dx,offset biosDate ; DX -> 6 byte buffer
  959. les si,clk_device ; Get the address of the Clock Device
  960. cmp si,-1 ; Has a valid device been selected
  961.  jne rw_clock_common10
  962. add sp,WORD ; discard near return address
  963. rw_clock_common10:
  964. ret
  965. ; *****************************
  966. ; ***    DOS Function 38    ***
  967. ; *** Get/Set Country Data  ***
  968. ; *****************************
  969. Public func38
  970. func38:
  971. xor ah,ah ; Generate 16 Bit country
  972. cmp al,0FFh ; FF means country code in BX
  973.  jne f38_10
  974. xchg ax,bx ; AX = real country code
  975. f38_10:
  976. xchg ax,dx ; DX = country
  977. test dx,dx ; dos_AL = 0 get the current country
  978.      jz f38_get         
  979. inc ax ; now check for dos_DX = FFFF
  980.  jz f38_set ;  which means set country code
  981. dec ax ; no, return buffer to normal
  982. f38_get:
  983. test dx,dx ; Get current?
  984.  jnz f38_g10 ; Yes
  985. mov dx,cur_country ; use current country
  986. f38_g10:
  987. ; look for (and if neccessary load) type 1 info into buffer
  988. xchg ax,di ; ES:DI -> buffer
  989. mov bx,cur_cp ; bx=codepage
  990. call f38_get_info ; get info in current codepage
  991.  jnc f38_g20
  992. push ss ! pop ds
  993. xor bx,bx ; now try any codepage
  994. call f38_get_info ; if none for current codepage
  995.  jc f38_error ; No Match Found
  996. f38_g20:
  997. lea si,EXCI_CI_DATAOFF[si] ; point at CI_, not EXCI_ data
  998. mov bx,CI_CODE[si] ; Return the selected country code
  999. mov cx,CI_STATICLEN/2
  1000. rep movsw
  1001. if NLSFUNC
  1002. push ss
  1003. pop ds
  1004. ; call get_dseg ; DS back to PCMODE
  1005. endif
  1006. call return_BX ; return country code in BX
  1007. xchg ax,bx
  1008. jmp return_AX_CLC ; and in AX
  1009. f38_get_info:
  1010. push es ! push di ! push dx ; save pointer to buffer
  1011. mov al,1 ; Get data list seperators etc...
  1012. call f65_get_info ; DS:SI -> extended country info buffer
  1013. pop dx ! pop di ! pop es ; ES:DI -> users buffer
  1014. ret
  1015. f38_set:
  1016. mov bx,cur_cp ; bx=codepage
  1017. and bx,f38_flag ; force CP to zero if 1st time here
  1018. call f38_set_country ; Update the Internal Data Structures
  1019.  jc f38_error
  1020. f38_s20:
  1021. mov f38_flag,0FFFFh ; Country Code Set Successfully
  1022. mov ax,cur_country ; and return the current country
  1023. jmp return_AX_CLC ;  to the user
  1024. f38_error:
  1025. if NLSFUNC
  1026. push ss
  1027. pop ds
  1028. ; call get_dseg ; DS back to PCMODE
  1029. endif
  1030. mov ax,ED_FILE ; This is the Error to return 
  1031.     jmp error_exit      
  1032. f38_set_country:
  1033. ; On Entry:
  1034. ; BX = codepage
  1035. ; DX = country
  1036. ; On Exit:
  1037. ; AX = error code
  1038. ; preserve codepage/country info if there is an error (ie do type 1 last!)
  1039. ;
  1040. mov al,2 ; Get uppercase & filename table
  1041. mov di,offset Ucasetbl
  1042. mov cx,info2_len
  1043. call f38_update
  1044.  jc f38_seterr
  1045. mov al,4 ; Get uppercase & filename table
  1046. mov di,offset FileUcasetbl
  1047. mov cx,info4_len
  1048. call f38_update
  1049.  jc f38_seterr
  1050. mov al,5 ; Get Legal file characters
  1051. mov di,offset FileCharstbl
  1052. mov cx,info5_len
  1053. call f38_update
  1054.  jc f38_seterr
  1055. mov al,6 ; Get Collating table
  1056. mov di,offset Collatingtbl
  1057. mov cx,info6_len
  1058. call f38_update
  1059.  jc f38_seterr
  1060. mov al,7 ; Get double byte character set table
  1061. mov di,offset DBCS_tbl
  1062. mov cx,info7_len
  1063. call f38_update
  1064.  jc f38_seterr
  1065. mov al,1 ; Get data list seperators etc...
  1066. mov di,offset country_data ; do last since this updates
  1067. mov cx,info1_len ; cur_country/cur_cp
  1068. call f38_update
  1069. ;  jc f38_seterr
  1070. ; clc
  1071. ret
  1072. f38_seterr:
  1073. mov ax,ED_FILE ; return file not found error
  1074. ret
  1075. f38_update:
  1076. push ds ; save important registers
  1077. push bx ; codepage
  1078. push cx ; count for move
  1079. push dx ; country
  1080. push di ; destination offset for move
  1081. push ds ; destination segment
  1082. call f65_get_info ; DS:SI -> buffer with country info
  1083. pop es ; destination seg in ES
  1084. pop di ; ES:DI -> destination of move
  1085. pop dx ; country
  1086. pop cx ; bytes to move
  1087. pop bx ; codepage back again
  1088.  jc f38_update10 ; any problems ?
  1089. rep movsb ; no, copy the data
  1090. f38_update10:
  1091. pop ds ; DS back to PCMDSEG
  1092. ret
  1093. ; *****************************
  1094. ; ***    DOS Function 65    ***
  1095. ; *** Extended Country Data ***
  1096. ; *****************************
  1097. ;
  1098. ;CODEPAGE equ 437 ; Return Standard Code Page
  1099. ;
  1100. ; Get Extended Country Code Sub-Functions
  1101. ;
  1102. func65_dt dw 0FFFFh ; 00 Illegal Sub-Function
  1103. dw offset country_data ; 01 Extended Country Info
  1104. dw offset Ucasetbl ; 02 UpperCase Table
  1105. dw 0FFFFh ; 03 Invalid Subfunction
  1106. dw offset FileUcasetbl ; 04 FileName Upper Case Table
  1107. dw offset FileCharstbl ; 05 Valid Filename Characters
  1108. dw offset Collatingtbl ; 06 Collating Sequence
  1109. dw offset DBCS_tbl ; 07 DBCS Environment Vector 
  1110. func65_dtl equ (offset $ - offset func65_dt)/2
  1111. Public func65
  1112. func65:
  1113. cmp al,func65_dtl ; is sub-function 0-7 ?
  1114.  jb func65_read_table
  1115. sub al,20h ; now check for 20-22
  1116.  jb f65_invalid
  1117.  je func6520 ; it's upper case character
  1118. sub al,2
  1119.  je func6522
  1120.  jb func6521
  1121. sub al,1 ; how about 6523 ?
  1122.  jnz f65_invalid
  1123. ; jmp func6523
  1124. func6523:
  1125. ;--------
  1126. ; On Entry:
  1127. ; DX = character to check
  1128. ; On Exit:
  1129. ; AX = 0, No
  1130. ; AX = 1, Yes
  1131. ; AX = 2, neither
  1132. ;
  1133. push ds
  1134. pop es
  1135. mov di,offset NoYesChars ; 'NnYy'
  1136. cbw ; assume No (AX=0)
  1137. xchg ax,dx ; AX = char, DX = answer
  1138. call dbcs_lead ; is it 1st of a DBCS pair
  1139.  jne func6523_10
  1140. scasw ; check 'N'
  1141.  je func6523_30
  1142. inc dx ; assume Yes (DX=1)
  1143. scasw ; check 'Y'
  1144. jmps func6523_20
  1145. func6523_10:
  1146. scasb ; check 'N'
  1147.  je func6523_30
  1148. scasb ; check 'n'
  1149.  je func6523_30
  1150. inc dx ; assume Yes (DX=1)
  1151. scasb ; check 'Y'
  1152.  je func6523_30
  1153. scasb ; check 'y'
  1154. func6523_20:
  1155.  je func6523_30
  1156. inc dx ; it's neither (DX=2)
  1157. func6523_30:
  1158. xchg ax,dx ; return result in AX
  1159. jmp return_AX_CLC ; Return the Code Page
  1160. func6522:
  1161. ;--------
  1162. ; Upper case ASCIIZ string at ES:DX
  1163. mov cx,0FFFFh ; calculate the length
  1164. mov di,dx ;  of the string
  1165. ; mov al,0
  1166. repne scasb
  1167. not cx ; CX = length, including 0
  1168. ; jmp func6521 ; now use upper case CX bytes
  1169. func6521:
  1170. ;--------
  1171. ; Upper case string of CX bytes at ES:DX
  1172. mov si,dx
  1173. mov di,dx ; point SI & DI at string
  1174. f6521_10:
  1175. lods es:al ; read a character
  1176. call dbcs_lead ; is it 1st of a DBCS pair
  1177.  jne f6521_20
  1178. stosb ; store 1st byte of this pair
  1179. movs es:byte ptr [di],es:byte ptr [si]
  1180. ; copy 2nd byte
  1181. dec cx ; 1st byte of pair
  1182. loopnz f6521_10 ; go around for another one
  1183. ret ; time to go...
  1184. f6521_20:
  1185. call toupper ; upper case the character
  1186. stosb ; 
  1187. loop f6521_10 ; go and do another one
  1188. ret
  1189. func6520:
  1190. ;--------
  1191. ; Upper case character DL
  1192. xchg ax,dx ; character in AX
  1193. call toupper ; upper case it
  1194. mov dl,al ; return in AL and DL
  1195. jmp return_DX ; set return code
  1196. f65_invalid:
  1197. ;-----------
  1198. ; short jump to invalid function
  1199. jmp invalid_function
  1200. func65_read_table:
  1201. ;-----------------
  1202. cmp cx,5 ; Check for valid buffer size
  1203.  jb f65_invalid
  1204. cbw ; Get the request sub-function
  1205. mov si,ax ; into SI
  1206. shl si,1
  1207. mov si,func65_dt[si]
  1208. inc si ; is SI = 0FFFFh
  1209.  jz f65_invalid ; if so it's an invalid function
  1210. dec si
  1211. cmp dx,0ffffh
  1212.  jne f65_21 ; FFFF means
  1213. mov dx,cur_country ;  use default country
  1214. f65_21:
  1215. cmp bx,0ffffh
  1216.  jne f65_22 ; FFFF means
  1217. mov bx,cur_cp ;  use default codepage
  1218. f65_22:
  1219. call f65_get_info ; DS:SI -> extended info for this pair
  1220. mov ax,ED_FILE ; On Error return File Not Found
  1221.  jnc f65_23 ; for any error
  1222. push ss ! pop ds
  1223. jmp error_exit ; so Quit
  1224. f65_23:
  1225. les bx,ss:int21regs_ptr ; point to callers registers
  1226. mov ax,es:reg_AX[bx] ; get the subfunction number
  1227. mov cx,es:reg_CX[bx] ; this much data is requested
  1228. mov di,es:reg_DI[bx] ; Get the Parameter Block Offset
  1229. mov es,es:reg_ES[bx] ; and Segment
  1230. stosb ; fill in Info ID
  1231. cmp al,1 ; 1 is special - the rest
  1232.  jne f65_30 ;  want a DWORD ptr
  1233. cmp cx,EXCI_MAXLEN ; Check CX against the sub-function 1
  1234.  jbe f65_25 ; maximum and force CX to this value
  1235. mov cx,EXCI_MAXLEN ; if it is greater
  1236. f65_25:
  1237. call return_CX ; Return the number of bytes transfered
  1238. sub cx,EXI_DATA_LEN ; Adjust count for 3 byte header 
  1239. mov ax,cx ! stosw ; fill in EXCI_LENGTH
  1240. push cx ; Save the count and copy as much
  1241. cmp cx,EXCI_STATLEN ; valid data a possible. IE at most
  1242.  jbe f65_27 ; EXCI_STATLEN bytes
  1243. mov cx,EXCI_STATLEN
  1244. f65_27:
  1245. rep movsb ; just copy the data
  1246. pop cx ; Zero the rest of the data
  1247. sub cx,EXCI_STATLEN ; Skip if no space left in users
  1248.  jbe f65_40 ; buffer otherwise STOSB
  1249. xor al,al ! rep stosb
  1250. jmps f65_40
  1251. ;
  1252. ; All function 65 sub-functions apart from 01 (Extended Country Info.)
  1253. ; pass use this code to update the users parameter block.
  1254. ;
  1255. f65_30:
  1256.     mov cx,5            
  1257. call return_CX
  1258. mov ax,si ! stosw ; fill in the DWORD ptr to the data
  1259. mov ax,ds ! stosw
  1260. f65_40:
  1261. push ss
  1262. pop ds
  1263. ; call get_dseg ; back to PCMDSEG
  1264. mov ax,cur_cp ; ##jc## Is the Requested or Current
  1265. jmp return_AX_CLC ; Return the Code Page
  1266. ; *****************************
  1267. ; ***    DOS Function 66    ***
  1268. ; ***Get/Set Global CodePage***
  1269. ; *****************************
  1270. ;
  1271. Public func66
  1272. func66:
  1273. cbw
  1274. dec ax ! jz f66_10 ; AL = 1, Get the Current CodePage
  1275. dec ax ! jz f66_20 ; AL = 2, Set the Current CodePage
  1276. jmp invalid_function ; Illegal Sub-Function return an Error
  1277. f66_10: ; Get the Current Code Page Info
  1278. mov bx,cur_cp ; Current CodePage
  1279. call return_BX
  1280. mov dx,SYS_CP ; System CodePage
  1281. jmp return_DX
  1282. f66_20: ; Set the Current CodePage
  1283. mov dx,cur_country ; The Codepage has changed, so update
  1284. call f38_set_country ; Country Info and tables
  1285.  jnc f66_30 ; Reset the Current CodePage if
  1286. mov ax,ED_FILE ; and return the error
  1287. jmp error_exit
  1288. f66_30:
  1289. mov bx,cur_cp ; select the new codepage
  1290. call f66_select_cp ; Prepare CodePage Devices
  1291.  jnc f66_40 ; No Errors Skip Error Handler
  1292. mov ax,-65 ; Update Error Status do not generate
  1293. call error_ret ;  a critical error but return
  1294. ;  "access denied" to the application
  1295. f66_40:
  1296. ret
  1297. f65_get_info:
  1298. ; On Entry:
  1299. ; AL = info type
  1300. ; BX = codepage (zero means any)
  1301. ; DX = country
  1302. ; On Exit:
  1303. ; CY set if error
  1304. ; DS:SI -> buffer with info in it
  1305. ;
  1306. ; NB. Remember to to Xlat fixups !
  1307. ;
  1308. cmp dx,cur_country ; is it default country ?
  1309.  jne f65_p30 ; have we already got correct country ?
  1310. test bx,bx ; CP zero special case and we will
  1311.  jz f65_p20 ;  accept anything for this country
  1312. cmp bx,cur_cp ; otherwise is the codepage
  1313.  jne f65_p30 ;  in the default system ?
  1314. f65_p20:
  1315. cbw ; make info type a word
  1316. mov si,ax ;  into index register
  1317. shl si,1 ; now a word offset
  1318. mov si,func65_dt[si] ; pick up offset of correct table
  1319. jmps f65_p90
  1320. f65_p30:
  1321. push ax
  1322. call f65_locate_and_read ; get info into a buffer at DS:SI
  1323. pop ax
  1324.  jc f65_p_exit
  1325. f65_p90:
  1326. cmp al,1 ; was it country info ?
  1327.  jne f65_p95 ; no, skip the fixup
  1328. mov CI_CASEOFF+EXCI_CI_DATAOFF[si],offset xlat_xlat
  1329. mov CI_CASESEG+EXCI_CI_DATAOFF[si],ss
  1330. f65_p95:
  1331. clc
  1332. f65_p_exit:
  1333. ret
  1334. ;
  1335. ; **********************************************************************
  1336. ; ***  Function 65 support - routines for seeking a country/codepage ***
  1337. ; ***  and loading the required information into the temp data area  ***
  1338. ; **********************************************************************
  1339. ;
  1340. ; **************************************************
  1341. ; ***   Open country.sys and search for the      ***
  1342. ; ***   table of offsets for the given country/  ***
  1343. ; ***   codepage, read it in and exit.           ***
  1344. ; **************************************************
  1345. f65_locate_and_read:
  1346. ; Locate and Read info AL for Country DX Codepage BX
  1347. if NLSFUNC
  1348. mov di,offset country_filename
  1349. ; point at pathname to country.sys 
  1350. xchg ax,cx ; get info into CL
  1351. mov ax,14feh ; then call magic backdoor
  1352. nlsfunc_int2f:
  1353. stc ; assume an error
  1354. int 2fh ; to do the hard work
  1355. ret
  1356. else
  1357. push ax
  1358. call f65x_find_info ; Will need to load up the info 
  1359. pop ax
  1360.  jc f65_lr_exit ; so do it if we can.
  1361. mov dx,offset f65xx_temp_area
  1362. mov cx,256 ; read 256 bytes into local buffer
  1363. push ax
  1364. call f65x_load_info ; Load required info
  1365. pop ax
  1366.  jc f65_lr_exit
  1367. mov ah,MS_X_CLOSE ; All done so 
  1368. mov bx,c_handle  ; Close the file first
  1369. call dos_entry ; before leaving
  1370. ;  jc f65_lr_exit
  1371. mov si,offset f65xx_temp_area ; Tell subroutines where info is
  1372. f65_lr_exit:
  1373. ret
  1374. ;
  1375. ; Entry:  dx=country code, bx=codepage
  1376. ; Exit :  carry set, and country.sys closed if failure
  1377. ;         country.sys open ready for more reads if success
  1378. ;
  1379. f65x_find_info:
  1380. push es ; Save es
  1381. push ds
  1382. pop es ; Make es=ds
  1383. mov f65xx_country,dx
  1384. mov f65xx_codepage,bx
  1385. mov dx,offset country_filename
  1386. mov ax,(MS_X_OPEN*256)+0 ; Attempt to open country.sys 
  1387. test dx,dx
  1388. stc
  1389.  jz f65x_40 
  1390. call dos_entry ; Handle should come back in ax
  1391.  jc f65x_40
  1392. f65x_10:
  1393. mov c_handle,ax ; Save handle
  1394. mov dx,f65xx_country
  1395. cmp f65xx_code,dx ; do we already have the information?
  1396.  jne f65x_30 ; No - get it from country.sys
  1397. f65x_20:
  1398. cmp f65xx_cp,bx ; Does codepage agree too?
  1399.  je f65x_35 ; Yes so exit with no more ado
  1400. f65x_30:
  1401. mov dx,007Eh
  1402. xor cx,cx ; Seek within country.sys
  1403. mov bx,c_handle
  1404. mov ax,(MS_X_LSEEK*256)+0 ; seek from begining
  1405. call dos_entry
  1406.  jc f65x_err
  1407. mov ah,MS_X_READ ; Now read the signature bytes and
  1408. mov bx,c_handle ; check them
  1409. mov  cx,2
  1410. mov  dx,offset f65xx_sig
  1411. call dos_entry
  1412.  jc f65x_err
  1413. cmp f65xx_sig,VALID_SIG
  1414.  jne f65x_err ; If signature bad exit
  1415. f65x_32:
  1416. mov ah,MS_X_READ ; Read from country.sys header until
  1417. mov bx,c_handle ; Country/codepage found or NULL
  1418. mov cx,f65xx_ptable_len
  1419. mov dx,offset f65xx_code
  1420. call dos_entry
  1421.  jc f65x_err
  1422. cmp f65xx_code,0 ; Found NULL so reqd combination
  1423.  je f65x_err ; was not found
  1424. mov dx,f65xx_code ; Get the country/codepage values
  1425. mov bx,f65xx_cp ; read from Country.SYS
  1426. cmp dx,f65xx_country ; Check against the requested
  1427.  jne f65x_32 ; Country. 
  1428. cmp f65xx_codepage,0 ; If a codepage match is not
  1429.  jz f65x_35 ; then return success
  1430. cmp bx,f65xx_codepage ; Check against the requested
  1431.  jne f65x_32 ; Codepage
  1432. f65x_35:
  1433. mov f65xx_country,dx ; Force the Search Country and
  1434. mov f65xx_codepage,bx ; CodePage to be Updated
  1435. f65x_40:
  1436. pop es ; combination found so exit
  1437. ret
  1438. f65x_err:
  1439. pop es
  1440. mov ah,MS_X_CLOSE ; On error close country.sys
  1441. mov bx,c_handle  ; and set the carry flag before
  1442. call dos_entry ; leaving
  1443. stc
  1444. ret
  1445. ;
  1446. ; **************************************************
  1447. ; ***   Load the type of information requested   ***
  1448. ; ***   For the country currently active in the  ***
  1449. ; ***   offset table        ***
  1450. ; **************************************************
  1451. ;
  1452. ; Entry:  al=type of info, dx=offset of buffer to read info into cx=no of bytes
  1453. ; Exit :  carry set, and country.sys closed if failure
  1454. ;
  1455. f65x_load_info:
  1456. push es
  1457. push cx
  1458. push dx
  1459. push ds ; Make es=ds
  1460. pop es
  1461. dec al ; 1=Data , 2=uppercase, 4=fuppercase
  1462. sub bh,bh ; 5=filechars, 6=Collating table
  1463. mov bl,al ; 7=DBCS table
  1464. shl bx,1 ; Retrieve relevant offset
  1465. mov dx,f65xx_data[bx]
  1466. xor cx,cx ; Seek within country.sys
  1467. mov bx,c_handle
  1468. mov ax,(MS_X_LSEEK*256)+0 ; seek from begining
  1469. call dos_entry
  1470. pop dx ; Get buffer address back
  1471. pop cx ; and number of bytes to read
  1472.  jc f65x_err
  1473. test ax,ax ; zero offset is a problem
  1474.  jz f65x_err ; (probably DBCS with old COUNTRY.SYS)
  1475. mov ah,MS_X_READ ; Now read that info into our data area
  1476. mov bx,c_handle
  1477. call dos_entry ; Return when read is done
  1478.  jc f65x_err
  1479. pop es
  1480. ret
  1481. endif
  1482. ;
  1483. ; This function scans the complete device list and prepares
  1484. ; all devices which support codepage.
  1485. ;
  1486. ; On Entry:
  1487. ; BX = codepage
  1488. ; On Exit:
  1489. ; AX = error code
  1490. DA_CODEPAGE equ DA_CHARDEV+DA_IOCTL+DA_GETSET
  1491. f66_select_cp:
  1492. if NLSFUNC
  1493. mov ax,14ffh ; then call magic backdoor
  1494. jmps nlsfunc_int2f ;  to do the hard work
  1495. else
  1496. push ds
  1497. mov f66_cp,bx ; Save requested CodePage
  1498. mov preperr,0000 ; Initialize Prepare Error
  1499. push ds ! pop es
  1500. mov bx,offset dev_root ; Get the Root of the Device List
  1501. f66_p10: ; Skip the NUL Device and check
  1502. lds bx,ds:DH_NEXT[bx] ; each character device for CodePage
  1503. cmp bx,0FFFFh ! jz f66_p50 ; Support.
  1504. mov ax,ds:DH_ATTRIB[bx]
  1505. and ax,DA_CODEPAGE ; Check for a Character Device which
  1506. cmp ax,DA_CODEPAGE ; supports IOCTL strings and GETSET
  1507.  jne f66_p10 ; otherwise skip the device
  1508. push bx
  1509. lea si,DH_NAME[bx] ; Found a matching device so
  1510. mov di,offset prepname ; open the device and select the 
  1511. mov cx,8 ; requested codepage
  1512. f66_p20:
  1513. lodsb
  1514. cmp al,' ' ! jz f66_p30
  1515. stosb
  1516. loop f66_p20
  1517. f66_p30:
  1518. xor al,al ! stosb
  1519. mov ax,(MS_X_OPEN*256)+1 ; Open the device name for
  1520. mov dx,offset prepname ; Write Access
  1521. call dos_entry
  1522.  jc f66_perr
  1523. mov bx,ax ; Save Device Handle in BX
  1524. mov si,es:f66_cp ; Get Requested CodePage in SI
  1525. mov dx,offset cp_packet ; Offset of CodePage Struct
  1526. mov cx,006Ah ; Get Unknown CodePage
  1527. mov ax,(MS_X_IOCTL*256)+0Ch ; Generic IOCTL function
  1528. call dos_entry ; Make function Call
  1529.  jc f66_p32 ; Error so Select requested Code Page
  1530. cmp si,es:cp_cpid ! jz f66_p35 ; If this the currently selected
  1531. f66_p32: ; skip the select CodePage
  1532. mov es:cp_cpid,si
  1533. mov dx,offset cp_packet ; Offset of CodePage Struct
  1534. mov cx,004Ah ; Select Unkown CodePage
  1535. mov ax,(MS_X_IOCTL*256)+0Ch ; Generic IOCTL function
  1536. call dos_entry ; Make function Call
  1537.  jnc f66_p35 ; No Error so skip the error
  1538. f66_p33:
  1539.   mov es:preperr,ax ; save
  1540. f66_p35:
  1541. mov ah,MS_X_CLOSE ; Close the device and check
  1542. call dos_entry ; for more devices to be prepared
  1543. jmps f66_p40
  1544. f66_perr:
  1545. mov es:preperr,ax ; Save the error code and try the
  1546. f66_p40: ; next device in the chain
  1547. pop bx ; Restore the Device offset
  1548. jmps f66_p10 ; and continue
  1549. f66_p50: ; All device have been prepared
  1550. pop ds ; now return the last error code
  1551. mov ax,preperr ; in AX
  1552. or ax,ax
  1553. ret
  1554. endif
  1555. PCMODE_DSIZE DSEG PARA
  1556. extrn swap_indos:word
  1557. PCM_RODATA CSEG WORD
  1558. ;
  1559. ; Get Internal Data DOS function 5Dh
  1560. ;
  1561. func5D_ft   dw  f5D00       
  1562. dw f5D01 ; Commit All
  1563. dw f5D02 ; Close File By Name
  1564. dw f5D03 ; Close All Host Files
  1565. dw f5D04 ; Close Process Host Files
  1566. dw f5D05  ; Get Open File List
  1567. dw f5D06 ; Get DOS Data Area
  1568. dw f5D_msnet ; f5D07 ; Get Truncate Flag used
  1569. ; with Redirected Dev I/O
  1570. dw f5D_msnet ; f5D08 ; Set Truncate Flag with
  1571. ; with Redirected Dev I/O
  1572. dw f5D_msnet ; f5D09 ; Close All Spool Streams
  1573. dw f5D0A ; Set Extended Error Info
  1574. func5D_ftl equ (offset $ - offset func5D_ft)/2
  1575. dw invalid_function
  1576. ;
  1577. ; Data used by the Binary format Time and Date routines
  1578. ;
  1579. totaldays dw 0,31,59,90,120,151,181,212,243,273,304,334,0ffffh
  1580. monthdays db 31,28,31,30,31,30,31,31,30,31,30,31
  1581. parse_separators db TAB,'.,+:;='
  1582. parse_terminators db '|"/[]<>'
  1583. PCMODE_DATA DSEG WORD
  1584. extrn internal_data:word
  1585. extrn error_code:word
  1586. extrn error_class:byte
  1587. extrn error_action:byte
  1588. extrn error_locus:byte
  1589. extrn error_dev:word
  1590. extrn indos_flag:word
  1591. extrn bootDrv:byte
  1592. extrn current_psp:word
  1593. extrn break_flag:byte
  1594. extrn dma_offset:word
  1595. extrn dma_segment:word
  1596. extrn fcb_search_buf:byte
  1597. extrn func52_data:byte ; Internal Data Table Area
  1598. extrn int21regs_ptr:dword
  1599. extrn lock_tables:dword
  1600. extrn unlock_tables:dword
  1601. extrn share_stub:dword
  1602. extrn remote_call:word ; set to FF if remote machine operation
  1603. extrn swap_always:word
  1604. extrn switch_char:byte
  1605. extrn owning_psp:word
  1606. extrn machine_id:word
  1607. extrn country_data:byte
  1608. extrn cur_country:word
  1609. extrn cur_cp:word
  1610. extrn verify_flag:byte
  1611. extrn clk_device:dword ; Clock Device Driver Address
  1612. extrn biosDate:word
  1613. extrn daysSince1980:word
  1614. extrn yearsSince1980:word
  1615. extrn month:byte
  1616. extrn dayOfWeek:byte
  1617. extrn dayOfMonth:byte
  1618. extrn hour:byte
  1619. extrn minute:byte
  1620. extrn second:byte
  1621. extrn hundredth:byte
  1622. if DOS5
  1623. extrn WindowsHandleCheck:byte
  1624. else
  1625. extrn win386_remote_machine:dword
  1626. endif
  1627. SYS_CP equ 437 ; System CodePage
  1628. GLOBAL_DATA dseg word
  1629. f38_flag dw 0 ; Country Code Selected Successfully
  1630. if not NLSFUNC
  1631. extrn dev_root:dword
  1632. f66_cp rw 1 ; INT21/66 Local Variable
  1633. cp_packet dw 2 ; Packet Size
  1634. cp_cpid dw 0 ; Request CodePage
  1635. db 0,0 ; Packet Terminators
  1636. preperr rw 1 ; Prepare function Error Code
  1637. prepname rb 9 ; Reserved for ASCIIZ Device Name
  1638. ;
  1639. ; Area for country.sys current pointer table 
  1640. ; (these are all offsets into country.sys)
  1641. ;
  1642. f65xx_code rw 1 ; Country code
  1643. f65xx_cp rw 1 ; Code page
  1644. rw 1 ; +1 reserved
  1645. f65xx_data rw 1 ; Data area
  1646. rw 1 ; Upper case table
  1647. rw 1 ; +1 reserved
  1648. rw 1 ; Filename upper case table
  1649. rw 1 ; Legal file characters
  1650. rw 1 ; Collating table
  1651. rw 1 ; Double byte character set lead byte table
  1652. f65xx_ptable_len equ offset $ - offset f65xx_code
  1653. f65xx_temp_area rb 256 ; Data area for extended country info
  1654. f65xx_codepage rw 1
  1655. f65xx_country rw 1
  1656. f65xx_sig rw 1 ; Signature
  1657. c_handle rw 1
  1658. endif ;not NLSFUNC
  1659. end