; LISTDEV.EXE v2.0 - List the Device Driver chain. ; Creator: Jim Webster 113 Riverview Drive Lafollette, TN 37766 ; EMAIL: jwebste3@bellsouth.net ; Assembler: MASM 5.1 ; To compile: masm /zi listdev; ; link /co /cp:1 listdev; ; Note: This code is free for anyone to use. The way it should be. .model small .stack include macro.inc ;Offset doslist struc ;------ ;Declare DOS List of Lists struc for all. dl_dpb dd ? ; 00 ;Addr of first DPB (Drive Parameter Block). dl_sft dd ? ; 04 ;Address of list of DOS file tables (SFT). dl_clock$ dd ? ; 08 ;Address of CLOCK$ device driver. dl_con dd ? ; 0C ;Address of CON device driver. doslist ends doslist2 struc ;Declare DOS List of Lists struc for 2.xx. dl_2 db size doslist dup(?);Fixed [DOSLIST Struc] portion. dl_log_drvs db ? ; 10 ;Number of logical drives. dl_bps2 dw ? ; 11 ;Max no. of bytes per block (usually 512). dl_dsk_buf2 dd ? ; 13 ;Address of first disk buffer. dl_nul2 dd ? ; 17 ;Beginning of the NUL device driver. doslist2 ends doslist3 struc ;Declare DOS L of L struc for 3.xx and up. dl_3 db size doslist dup(?);Fixed [DOSLIST Struc] portion. dl_bps3 dw ? ; 10 ;Max no. of bytes per block (usually 512). dl_dsk_buf3 dd ? ; 12 ;Address of first disk buffer. dl_cds3 dd ? ; 16 ;Addr of CDS (Current Directory Structure). dl_fcb3 dd ? ; 1A ;Address of FCB table. dl_fcb_sz3 dw ? ; 1E ;Size of FCB table. dl_no_blk3 db ? ; 20 ;Number of block devices. dl_last_dr3 db ? ; 21 ;LASTDRIVE value (default = 5). dl_nul3 dd ? ; 22 ;Beginning of the NUL device driver. dl_joined3 db ? ; 34 ;Number of JOINed drives. doslist3 ends ;Offset devhead struc ;------ ;Declare Device Header Chain struc. next_offs dw ? ; 00 ;Long pointer to next block. next_seg dw ? ; 02 attrib dw ? ; 04 ;Device Drivers attribute. strat dw ? ; 06 ;Offset to strategy. intrp dw ? ; 08 ;Offset to interrupt. dname db 8 dup (?); 0A ;Name or number of units. term db ? ; 12 ;Terminating position. devhead ends dosseg .stack .data comment \ LISTDEV v2.0 by Jim Webster EMAIL: jwebste3@bellsouth.net Device Type Units Attr(FEDCBA9876543210) Address Strategy Interrupt -------- ----- ----- ---------------------- --------- -------- --------- xxxxxxxx Block xx xxxx(................) xxxx:xxxx xxxx xxxx 0 10 18 24 29 44 48 61 71 <<<-----------------------End of Device Driver Chain----------------------->>> \ lpt_number dw 0 ;0 = LPT1, 1 = LPT2, 2 = LPT3. prn_flag db 0 ;If = 1, send contents to LPT1. dd_title db 'LISTDEV v2.0 by Jim Webster EMAIL: jwebste3@bellsout' db 'h.net',0dh,0ah db 0dh,0ah db 'Device Type Units Attr(FEDCBA9876543210) Address' db ' Strategy Interrupt',0dh,0ah db '-------- ----- ----- ---------------------- ---------' db ' -------- ---------',0dh,0ah,0 end_line db '<<<-----------------------End of Device Driver Chain----' db '------------------->>>',0dh,0ah,0 block db 'Block' char db 'Char ' dd_info db 'xxxxxxxx Block xx xxxx(................) xxxx:xxxx' db ' xxxx xxxx',0dh,0ah,0 attr_flag db 0 ;If = 1, display "ATTR_SYNTAX". attr_syntax db 0dh,0ah db '1000000000000011b ;ANSI.SYS device driver ATTRIBUTE and ' db 'its meaning. [8003h]',0dh,0ah db 'FEDCBA9876543210 <--- Bit position. 0 = not set. 1 = set' db '.',0dh,0ah db '||||||||||||||||<-Replace the DOS standard Character Inp' db 'ut Device.',0dh,0ah db '|||||||||||||||<-Replace the DOS standard Character Outp' db 'ut Device.',0dh,0ah db '|||||||||||||| Block device supports 32-bit sector add' db 'ressing (DOS 4.0+).',0dh,0ah db '||||||||||||||<-Replace the DOS NULL device.',0dh,0ah db '|||||||||||||<-Replace the DOS CLOCK device.',0dh,0ah db '||||||||||||<-Allow use of INT 29h, AL = character to wr' db 'ite to screen.',0dh,0ah db '|||||||||||<-Reserved (must be set to 0).',0dh,0ah db '||||||||||<-Device supports GENERIC IOCTL & GET/SET LOGI' db 'CAL DEVICE (DOS 3.2+).',0dh,0ah db '|||||||||<-Device supports QUERY GENERIC IOCTL (DOS 5.0+).' db 0dh,0ah db '||||||||<-Reserved (must be set to 0).',0dh,0ah db '|||||||<-Reserved (must be set to 0).',0dh,0ah db '||||||<-Reserved (must be set to 0).',0dh,0ah db '|||||<-Device supports OPEN/CLOSE/REMOVABLE MEDIA (DOS 3' db '.0+)',0dh,0ah db '||||<-Reserved (must be set to 0).',0dh,0ah db '|||<-Allow Output-Til-Busy for Character Device (DOS 3.0' db '+).',0dh,0ah db '|| Non-IBM format for Block Device.',0dh,0ah db '||<-Supports IOCTL DOS call (INT 21h, Function 44h).' db 0dh,0ah db '|<-0 = Block Device and 1 = Character Device.',0dh,0ah,0 comment * 1000000000000011b ;ANSI.SYS device driver ATTRIBUTE and its meaning. [8003h] FEDCBA9876543210 <--- Bit position. 0 = not set. 1 = set. ||||||||||||||||<-Replace the DOS standard Character Input Device. |||||||||||||||<-Replace the DOS standard Character Output Device. |||||||||||||| Block device supports 32-bit sector addressing (DOS 4.0+). ||||||||||||||<-Replace the DOS NULL device. |||||||||||||<-Replace the DOS CLOCK device. ||||||||||||<-Allow use of INT 29h, AL = character to write to screen. |||||||||||<-Reserved (must be set to 0). ||||||||||<-Device supports GENERIC IOCTL & GET/SET LOGICAL DEVICE (DOS 3.2+). |||||||||<-Device supports QUERY GENERIC IOCTL (DOS 5.0+). ||||||||<-Reserved (must be set to 0). |||||||<-Reserved (must be set to 0). ||||||<-Reserved (must be set to 0). |||||<-Device supports OPEN/CLOSE/REMOVABLE MEDIA (DOS 3.0+) ||||<-Reserved (must be set to 0). |||<-Allow Output-Til-Busy for Character Device (DOS 3.0+). || Non-IBM format for Block Device. ||<-Supports IOCTL DOS call (INT 21h, Function 44h). |<-0 = Block Device and 1 = Character Device. * ver_err_msg db 0dh,0ah,07h db 'Requires DOS v2.00 or greater!',0dh,0ah,0 prn_err_msg db 0dh,0ah,07h db 'Error: Printer is not On Line!',0dh,0ah,0 dd_attribute dw 0 ;Attribute of the Device Driver. dos_version label word dos_ver_min db 0 ;Minor DOS version number. Example: 0Ah = version x.10 dos_ver_maj db 0 ;Major DOS version number. Example: 02h = version 2.xx next_dd_offs dw 0 ;Seg:Offs address of next Device Driver. next_dd_seg dw 0 syntax db ' LISTDEV v2.0 displays the Device Driver Chain and the' db ' contents of each',0dh,0ah db 'Device Header. Redirection to a file or the printer is a' db 'llowed.',0dh,0ah db 'Examples: "LISTDEV > LISTDEV.LOG" or "LISTDEV > PRN". I' db ' hereby proclaim,',0dh,0ah db 'being of unsound mind and body, this program a freebie. ' db 'Enjoy! ',0dh,0ah db 'Please send any suggestions or correspondences to: Jame' db 's Webster',0dh,0ah db '113 Riverview Drive Lafollette, TN 37766 EMAIL: jweb' db 'ste3@bellsouth.net',0dh,0ah,0dh,0ah db 'Syntax: LISTDEV [? h p 0 1]',0dh,0ah,0dh,0ah db ' ? or h = Display this help screen.',0dh,0ah db ' p = Send output to LPT1. Put this switch BE' db 'FORE /0 or /1 !',0dh,0ah db ' If the Device Name contains certain cha' db 'racters of the Extended',0dh,0ah db ' IBM Character Set, "> PRN" will not red' db 'irect them properly.',0dh,0ah db ' 0 = Display the ATTRIBUTE definitions only.' db 0dh,0ah db ' 1 = Display the Device Driver Chain and the' db ' ATTRIBUTE definitions.',0dh,0ah,0 comment \ LISTDEV v2.0 displays the Device Driver Chain and the contents of each Device Header. Redirection to a file or the printer is allowed. Examples: "LISTDEV > LISTDEV.LOG" or "LISTDEV > PRN". I hereby proclaim, being of unsound mind and body, this program a freebie. Enjoy! Please send any suggestions or correspondences to: James Webster 113 Riverview Drive Lafollette, TN 37766 EMAIL: jwebste3@bellsouth.net Syntax: LISTDEV [? h p 0 1] ? or h = Display this help screen. p = Send output to LPT1. Put this switch BEFORE /0 or /1 ! If the Device Name contains certain characters of the Extended IBM Character Set, "> PRN" will not redirect them properly. 0 = Display the ATTRIBUTE definitions only. 1 = Display the Device Driver Chain and the ATTRIBUTE definitions. \ .code main proc mov ax,dgroup mov ds,ax nop push si call read_cmnd_tail ;Check for user input. mov al,0 ;AL = 0 = no errors. jc exit_main ;If CY, display SYNTAX or ATTR_SYNTAX only. call get_dos_vers ;Get the DOS version number. mov al,1 ;Assume < DOS v2.xx. lea si,ver_err_msg ;DS:SI = address of error message. cmp dos_ver_maj,2 ;DOS v2.xx ? jb exit_main ;If < 2.xx, exit with error. lea si,dd_title ;DS:SI = address of title. call write_str ;Write title to the screen. call show_drivers ;Show the Device Driver Chain. lea si,end_line ;DS:SI = address of end line. call write_str ;Write end line message to the screen. lea si,attr_flag ;DS:SI = address of ATTR_FLAG. cmp attr_flag,0 ;Do not display ATTR_SYNTAX ? jz exit_main ;If = 0, no. Exit. inc si ;DS:SI = address of ATTR_SYNTAX. mov al,0 ;AL = 0 = no errors. exit_main: call write_str ;Write SYNTAX, ATTR_SYNTAX, VER_ERR_MSG, pop si ; PRN_ERR_MSG, or nothing. mov ah,4ch int 21h main endp ;--------------------------------------------------------------------; ; This procedure returns the pointer to the DOS "List of Lists". ; ; ; ; Caller(s): ; ; Returns: ES:BX = pointer. ; ; Format of pointer: ; ; Offset Size Description ; ; ------ ----- --------------------------------------------- ; ; All versions of DOS ; ; -02 Word Segment address of first MCB (Memory Control ; ; Block). Offset address is always 0. ; ; 00 DWord Address of first DPB (Drive Parameter Block). ; ; 04 DWord Address of list of DOS file tables (SFT). ; ; 08 DWord Address of CLOCK$ device driver. ; ; 0C DWord Address of CON device driver. ; ; DOS 2.xx ; ; 10 Byte Number of logical drives. ; ; 11 Word Maximum number of bytes per block, for block ; ; devices (usually 512). ; ; 13 DWord Address of first disk buffer. ; ; 17 DWord Beginning of the NUL device driver. ; ; DOS 3.xx and up ; ; 10 Word Maximum number of bytes per block, for block ; ; devices (usually 512). ; ; 12 DWord Address of first disk buffer. ; ; 16 DWord Address of CDS (Current Directory Structure). ; ; 1A DWord Address of FCB table. ; ; 1E Word Size of FCB table. ; ; 20 Byte Number of block devices. ; ; 21 Byte LASTDRIVE value (default = 5). ; ; 22 DWord Beginning of the NUL device driver. ; ; 34 Byte Number of JOINed drives. ; ;--------------------------------------------------------------------; get_dos_list proc push ax mov ah,52h ;Undocumented "Find List of Lists". int 21h ;Returns pointer in ES:BX. pop ax ret get_dos_list endp ;---------------------------------------------------------------------------- show_drivers proc pushad pushr call get_dos_list ;Returns ES:BX ptr to DOS's ; "List of Lists". cld ;Set direction for increment. mov ax,bx ;Set up DX:AX for loop. mov dx,es add ax,22h ;Assume DOS v3.00 or greater. cmp dos_ver_maj,2 ;DOS v2.xx ? ja loop_show_drivers ;If > 2.xx, continue. sub ax,22h-17h ;Else, assumed incorrectly! loop_show_drivers: mov bx,ax ;Initial ES:BX to read the chain. mov es,dx nop mov cx,es:[bx.next_offs] ;Store the address of next driver. mov next_dd_offs,cx mov cx,es:[bx.next_seg] mov next_dd_seg,cx lea si,dd_info+48d ;DS:SI = address of INFO line. xchg ax,dx ;AX = segment address. call hex_word_2asc ;Convert AX to ASCII and store it. inc si ;Move beyond the colon [:] character. mov ax,dx ;AX = offset address. call hex_word_2asc ;Convert AX to ASCII and store it. mov ax,es:[bx.strat] ;AX = offset of Strategy routine. add si,4 call hex_word_2asc ;Convert AX to ASCII and store it. mov ax,es:[bx.intrp] ;AX = offset of Interrupt routine. add si,6 call hex_word_2asc ;Convert AX to ASCII and store it. mov ax,es:[bx.attrib] ;AX = Device Drivers attribute. mov dd_attribute,ax ;Store it. lea si,dd_info+24d ;DS:SI = address of INFO line. call hex_word_2asc ;Convert AX to ASCII and store it. pushr lea di,dd_info ;ES:DI = address of INFO line. mov si,bx add si,0ah ;Point DS:SI to read Device Name. pop ds ;DS = ES. pop es ;ES = DS. nop mov cx,8 ;CX = bytes to copy. rep movsb ;Copy DS:SI to ES:DI. pop ds ;Restore our DATA Segment. nop add di,2 ;ES:DI = destination. mov ax,0101h ;Assume its a Character Device. lea si,char test dd_attribute,8000h ;If bit #15 set, is a Char Device. jnz copy_type ;If bit #15 is set, jump. xor ah,ah ;AH = 0 = Block Device. lea si,block copy_type: mov cx,5 ;CX = bytes to copy. rep movsb ;Copy DS:SI to ES:DI. lea di,dd_info+29d ;Overwrite old Attribute bit display. mov cx,8 ;CX = words to write. push ax ;Save the AX flag state. mov ax,'..' ;AX = word to write. rep stosw ;Copy AX to ES:DI, CX times. dec di ;Point ES:DI to end of Attr bits. mov ax,dd_attribute ;AX = attribute of driver. mov cx,16d ;CX = loop count. lset_abits: shr ax,1 ;Divide AX by 2. jnc cset_abits ;If carry clear, bit was a 0. mov bptr [di],'1' ;Else, show that bit was set. cset_abits: dec di ;Dec offset into bits. loop lset_abits ;Loop until CX = 0. popr nop or ah,ah ;AH = 0 ? jnz copy_units ;If <> 0 is Character Device, jump. lea si,dd_info ;DS:SI = start of INFO line. mov cx,8 ;CX = loop count. lblock_name: lodsb ;AL = character. cmp al,5 ;Assume 5 maximum devices supported. ja cblock_name ;If > 5, jump. add bptr [si-1],30h ;Convert it to ASCII. cblock_name: loop lblock_name ;Loop until CX = 0. mov al,es:[bx.dname] ;AL = number of units supported. copy_units: lea si,dd_info+18d ;DS:SI = address of INFO line. call hex_byte_2asc ;Convert AL to ASCII and store it. lea si,dd_info ;DS:SI = the entire INFO line. call write_str ;Write it to the screen. mov ax,next_dd_offs ;Set up DX:AX [ES:BX] for next write. mov dx,next_dd_seg cmp ax,-1 ;End of Device Driver Chain ? je exit_show_drivers ;If = FFFFh, exit. jmp loop_show_drivers ;Else, show the next driver. exit_show_drivers: popr popad ret show_drivers endp ;---------------------------------------------------------------------------- get_dos_vers proc pushr mov ax,3000h ;Get DOS Version function. int 21h ;Returns: AL=major, AH=minor. xchg ah,al ;Switch AH and AL. or ah,ah ;Check for version 1.xx. jnz save_ver_no ;If AL > 0, jump. mov ax,100h ;Else, its version 1.xx. save_ver_no: mov dos_ver_maj,ah ;Store the major version number. mov dos_ver_min,al ;Store the minor version number. popr ret get_dos_vers endp ;--------------------------------------------------------------------; ; The next 2 routines convert an 8 or 16-bit hex value into ASCII. ; ;--------------------------------------------------------------------; hex_word_2asc proc ;On entry: AX = hex word to convert. ; DS:SI = address to store it. xchg ah,al ;Convert the high byte first. call hex_byte_2asc ;Convert AL and store it. xchg ah,al ;Convert the low byte. hex_word_2asc endp ;---------------------------------------------------------------------------- hex_byte_2asc proc ;On entry: AL = hex byte to convert. push ax ; DS:SI = address to store it. mov ah,al ;AH = AL. shrr ah,4 ;Move bits 4-7 into bits 0-3. and al,0fh ;#AND# out bits 4-7. cmp ah,9 ;Numeral 0 - 9 ? ja ah_letter ;If > 9, jump. add ah,30h ;Convert to an ASCII numeral. jmps al_number ;And continue. ah_letter: add ah,37h ;Convert to uppercase ASCII. al_number: cmp al,9 ;Numeral 0 - 9 ? ja al_letter ;If > 9, jump. add al,30h ;Convert to an ASCII numeral. jmps cnt_conv_al ;And continue. al_letter: add al,37h ;Convert to uppercase ASCII. cnt_conv_al: mov [si],ah ;Store the high ASCII character. inc si ;Inc ptr to next storage area. mov [si],al ;Store the low ASCII character. inc si ;Inc ptr to next storage area. pop ax ret hex_byte_2asc endp ;---------------------------------------------------------------------------- write_str proc ;On entry: DS:SI = address of ASCIIZ string. pushr cld ;Set direction for increment. jmps bwrite_str ;Jump to begin. lwrite_str: cmp al,7fh ;AL = DEL character ? jne cwrite_str mov al,20h ;AL = SPACE character. cwrite_str: cmp prn_flag,1 ;Send output to LPT1 ? je write2_lpt1 ;If = 1, yes. Jump. mov ah,2 ;Character Output to standard output device. mov dl,al ;DL = character to display. int 21h ;Call DOS. jmps bwrite_str ;And jump to fetch the next character. write2_lpt1: cmp al,0dh ;AL = Carriage Return ? je cwrit2_lpt1 cmp al,0ah ;AL = Line Feed ? je cwrit2_lpt1 cmp al,7 ;AL = BELL ? je cwrit2_lpt1 cmp al,0ffh ;AL = high DEL character ? je print_space cmp al,20h ;Filter out the low control codes. jb print_space cmp al,80h ;Filter out the high control codes. jb cwrit2_lpt1 cmp al,9fh ja cwrit2_lpt1 print_space: mov al,20h ;AL = SPACE character. cwrit2_lpt1: mov ah,0 ;Write Character to LPTx. mov dx,lpt_number ;DX = 0 based LPT number (0, 1, or 2). int 17h ;Call BIOS. bwrite_str: lodsb ;AL = next character. or al,al ;End of ASCIIZ string = 00h. jnz lwrite_str ;If AL <> 00h, write it. popr ret ;Return to caller. write_str endp ;---------------------------------------------------------------------------- ;Note: On program entry, ES points to the default DTA (Data Transfer Area). ;---------------------------------------------------------------------------- read_cmnd_tail proc pushr mov bx,80h ;ES:BX = address of the command tail. xor ch,ch ;CH = 0. mov cl,es:[bx] ;CX = length of command tail. jcxz nc_read_ct ;If CX = 0, command tail is empty. inc bx ;Increment ES:BX pointer. parse_ctail: mov al,es:[bx] ;AL = character from command tail. cmp al,20h ;White space (SPACE character) ? je loop_read_ct cmp al,'/' ;Throw out any command line "switch". je loop_read_ct cmp al,'-' ;Throw out any command line "switch". je loop_read_ct cmp al,'?' ;Help screen requested ? je prog_syntax cmp al,'h' ;Help screen requested ? je prog_syntax cmp al,'H' ;Help screen requested ? je prog_syntax cmp al,'p' ;Send output to LPT1 ? je set_prn_flag cmp al,'P' ;Send output to LPT1 ? je set_prn_flag cmp al,'0' ;Display the ATTRIBUTE definitions only ? je req_attrsyn cmp al,'1' ;Display DD Chain and ATTR definitions ? jne loop_read_ct mov attr_flag,1 ;Set the internal flag. nc_read_ct: clc ;Clear the carry flag (NC). jmps exit_rct ;And jump to exit. set_prn_flag:call check_prn_status;See if printer is On Line. jc exit_rct ;If CY, printer is not On Line! loop_read_ct:inc bx ;Increment ES:BX pointer. dec cx ;Decrement counter. jnz parse_ctail ;If CX > 0, fetch the next character. jmps nc_read_ct prog_syntax: lea si,syntax ;DS:SI = address of program SYNTAX. jmps cy_read_ct ;Set the carry flag and exit. req_attrsyn: lea si,attr_syntax ;DS:SI = address of ATTR_SYNTAX. cy_read_ct: stc ;Set the carry flag (CY). exit_rct: popr ret read_cmnd_tail endp ;---------------------------------------------------------------------------- check_prn_status proc pushr mov ah,2 ;LPTx Status Request. mov dx,lpt_number ;DX = 0 based LPT number (0, 1, or 2). int 17h ;Call BIOS. cmp ah,30h ;If DOS v3.2 or less = not On Line. je err_chk_prn ;If AH = 30h, exit with error. test ah,00001000b ;Test bit #3 for I/O ERROR. jnz err_chk_prn ;If bit #3 is set, exit with error. mov prn_flag,1 ;Set the internal flag. clc ;Clear the carry flag (NC). jmps end_chk_prn ;And jump to exit. err_chk_prn: lea si,prn_err_msg ;DS:SI = address of PRN_ERR_MSG. stc ;Set the carry flag (CY). end_chk_prn: popr ret check_prn_status endp end main ;Begin at the procedure MAIN.