;; ; @(#) erasedir.asm - Dir and file complete (unrecoverable) erase utility. ; (c) 1995 Ivan Maidanski http://ivmai.chat.ru ; Freeware program source. All rights reserved. ;; ; Language: ASM8086 (for IBM PC/AT, MS-DOS v3.0+, COM file) ; Tested with: Turbo Assembler v3.1, Turbo Link v5.1 ; Last modified: 1995-05-26 13:40:00 GMT+04:00 ;; NAME EraseDir ; tasm /m2 erasedir.asm ; tlink /t erasedir.obj IDEAL MODEL TINY LOCALS ; Definitions MaxFileNameLen EQU 100h CODESEG ; PSP variables ORG 80h LABEL DosCmdLine BYTE LABEL Dta BYTE ; Program initialization ORG 100h LABEL Start NEAR mov sp,OFFSET StackEnd mov bx,(ProgramLen+0Fh)/10h mov ah,4Ah int 21h ; Main program call AnalyzeDos call AnalyzeCmdLine call GetClearedBuffer call TestIsDir jnc @@Skip call ClearAllDirAndReturn @@Skip: call WriteToFile call DeleteOneFile call FreeBuffer call ClearFileName ; Return to DOS mov ax,4C00h int 21h ; Procedures PROC AnalyzeDos ; Expects: - ; Returns: - ; Uses: ax,bx,cx mov ah,30h int 21h cmp al,2h jb @@InvalidVersion ret @@InvalidVersion: lea si,[@@MsgInvalidVer] call WriteStr mov ax,4C02h int 21h @@MsgInvalidVer DB 'MS-DOS Version too low (must be 2.00 or higher).' DB 0Dh,0Ah,0 ENDP PROC AnalyzeCmdLine ; Expects: [ds:DosCmdLine] ; Returns: [ds:FileName] ; Uses: ax,cx,si,di,es mov cl,[DosCmdLine] lea si,[DosCmdLine] inc cl @@Loop: dec cl jz @@ShowInfo inc si cmp [byte ptr si],' ' jbe @@Loop lea di,[FileName] mov [FileNameStart],cl @@CopyName: mov al,[si] mov [di],al inc si inc di dec cl jnz @@CopyName @@Back: dec di cmp [byte ptr di],' ' jbe @@Back mov [byte ptr di+1],0 ret @@ShowInfo: lea si,[@@MsgInfo] call WriteStr mov ax,4C01h int 21h @@MsgInfo DB 'Directory (and Files) Complete Erase Utility v1.0',0Dh,0Ah DB ' Usage: ERASEDIR path',0Dh,0Ah,0 ENDP PROC GetClearedBuffer ; Expects: - ; Returns: [ds:BufSeg], [ds:BufLen] ; Uses: ax,bx,cx,di,es mov ah,48h ; determine available memory mov bx,0FFFFh int 21h jnc @@Error and bx,bx jz @@Error cmp bh,0 je @@LowMem mov bl,0 cmp bh,0Fh jbe @@LowMem mov bh,0Fh @@LowMem: mov ax,bx REPT 4h shl ax,1 ENDM mov [BufLen],ax shr ax,1 mov cx,ax mov ah,48h ; get memory block int 21h jc @@Error mov [BufSeg],ax mov es,ax mov di,0 mov ax,0 rep stosw ret @@Error: call FatalError ENDP PROC FreeBuffer ; Expects: [ds:BufSeg] ; Returns: - ; Uses: ax,es mov ah,49h mov es,[BufSeg] int 21h jc @@Error ret @@Error: call FatalError ENDP PROC FatalError ; Expects: - ; Returns: - ; Uses: - lea si,[@@MsgFatalError] call WriteStr mov ax,4CFFh int 21h @@MsgFatalError DB 'Fatal Error!',0Dh,0Ah,0 ENDP PROC ClearFileName ; Expects: - ; Returns: [ds:FileName] ; Uses: al,cx,di,es cld mov cx,ds mov es,cx lea di,[FileName] mov al,0 mov cx,MaxFileNameLen rep stosb ret ENDP PROC TestIsDir ; Expects: [ds:FileName] ; Returns: cf=(0-File,1-Dir) ; Uses: ax,bx,dx mov ax,3D00h ; open file for reading lea dx,[FileName] int 21h jc @@TestDir mov bx,ax mov ah,3Eh ; close file int 21h jc @@Error clc ret @@TestDir: cmp ax,5h jne @@Error stc ret @@Error: call TestError ENDP PROC ClearAllDirAndReturn ; Expects: [ds:FileName] ; Returns: [ds:FileName] ; Uses: ax,bx,cx,dx,si,di,es [ds:Dta] inc [FileNameStart] lea si,[@@BackSlash] call AppendToFileName @@EnterDir: call FindDir jnc @@EnterDir call CountEntries push cx call ClearAllFiles pop cx call DeleteOneDirectory jnc @@EnterDir ret @@BackSlash DB '\',0 ENDP PROC ClearAllFiles ; Expects: [ds:FileName] ; Returns: [ds:FileName] ; Uses: ax,bx,cx,dx,si,di,es, [ds:Dta] clc @@Next: mov bl,0 call FindFile jc @@Exit call WriteToFile call RenameOneFile call DeleteOneFile stc jmp @@Next @@Exit: ret ENDP PROC WriteToFile ; Expects: [ds:FileName] ; Returns: - ; Uses: ax,bx,cx,dx,si,di mov ax,3D00h ; open file for reading lea dx,[FileName] int 21h jc @@Error mov bx,ax mov ax,4202h ; set file pointer to the end mov cx,0 mov dx,0 int 21h jc @@Error mov si,dx mov di,ax mov ah,3Eh ; close file int 21h jc @@Error mov ax,3D01h ; open file for writing lea dx,[FileName] int 21h jc @@Error mov bx,ax @@Loop: mov ah,40h ; write to file mov cx,[BufLen] mov dx,0 push ds mov ds,[BufSeg] int 21h pop ds jc @@Error cmp ax,[BufLen] jne @@Error sub di,[BufLen] jnc @@Loop sub si,1 jnc @@Loop mov ax,4200h ; set file pointer mov cx,0 mov dx,0 int 21h jc @@Error mov ah,40h ; truncate file mov cx,0 int 21h jc @@Error mov ah,3Eh ; close file int 21h jc @@Error ret @@Error: call TestError ENDP PROC CountEntries ; Expects: [ds:FileName] ; Returns: cx=AmountOfEntries ; Uses: ax,bl,cx,dx,si,di, [ds:Dta] mov cx,0 push cx mov bl,0 clc @@Loop: call FindFile jc @@NotFound call GetLastFileName pop cx inc cx push cx stc jmp @@Loop @@NotFound: pop cx inc cx inc cx ret ENDP PROC DeleteAllFiles ; Expects: [ds:FileName] ; Returns: - ; Uses: ax,bl,cx,dx,si,di, [ds:Dta] mov bl,0 clc @@Loop: call FindFile jc @@NotFound call DeleteOneFile stc jmp @@Loop @@NotFound: ret ENDP PROC RenameOneFile ; Expects: [ds:FileName] ; Returns: [ds:FileName] ; Uses: ax,dx,si,di,es mov ax,ds mov es,ax lea si,[FileName] lea di,[OldFileName] @@Copy: mov al,[si] mov [di],al inc si inc di cmp al,0 jne @@Copy call GetLastFileName lea si,[@@NewName] call AppendToFileName mov ah,56h ; rename file lea di,[FileName] lea dx,[OldFileName] int 21h jc @@Error ret @@Error: call TestError @@NewName DB '$$$$$$$$.$$$',0 ENDP PROC DeleteOneFile ; Expects: [ds:FileName] ; Returns: [ds:FileName] ; Uses: ax,dx,di mov ah,41h lea dx,[FileName] int 21h jc @@Error call GetLastFileName ret @@Error: call TestError ENDP PROC DeleteOneDirectory ; Expects: cx=AmountOfEntries, [ds:FileName] ; Returns: cf=(1-ParentStartDir), [ds:FileName] ; Uses: ax,bx,cx,dx,di lea di,[FileName] dec di @@FindEnd: inc di cmp [byte ptr di],0 jne @@FindEnd mov [byte ptr di-1],0 mov ah,3Ah ; delete directory lea dx,[FileName] int 21h jc @@Error push cx mov ah,3Ch ; create file mov cx,00100000b ; attr - ARCfile int 21h jc @@Error pop dx mov bx,ax mov ax,4200h ; set file pointer mov cx,0 REPT 5h shl dx,1 rcl cx,1 ENDM int 21h jc @@Error mov ah,40h ; truncate file mov cx,0 int 21h jc @@Error mov ah,3Eh ; close file int 21h jc @@Error call GetLastFileName ret @@Error: call TestError ENDP PROC FindDir ; Expects: [ds:FileName] ; Returns: [ds:FileName], cf=(1-No (more) files) ; Uses: ax,bl,cx,dx,si,di, [ds:Dta] mov bl,1 clc call FindFile jc @@Exit lea si,[@@BackSlash] call AppendToFileName @@Exit: ret @@BackSlash DB '\',0 ENDP PROC FindFile ; Expects: [ds:FileName], bl=(0-File,1-Dir), cf=(0-First,1-Next) ; Returns: [ds:FileName], [ds:Dta], cf=(1-No (more) files) ; Uses: ax,cx,dx,si,di, [ds:Dta] mov ah,4Eh adc ah,0 lea si,[@@WildCard] call AppendToFileName lea dx,[FileName] mov cx,0FFh @@TryAgain: int 21h jnc @@Found cmp ax,12h jne @@Error call GetLastFileName stc ret @@Found: cmp bl,0 je @@File mov ah,4Fh test [byte ptr Dta+15h],00010000b jz @@TryAgain cmp [byte ptr Dta+1Eh],'.' ; current or last dir je @@TryAgain jmp @@AddName @@File: test [byte ptr Dta+15h],11011110b mov ah,4Fh jnz @@TryAgain @@AddName: call GetLastFileName lea si,[Dta+1Eh] ; File name call AppendToFileName clc ret @@Error: call GetLastFileName call TestError @@WildCard DB '*.*',0 ENDP PROC TestError ; Expects: ax=ErrorCode, [ds:FileName] ; Returns: (none) ; Uses: - lea si,[@@MsgUnknown] cmp ah,0 jne @@Print lea si,[@@MsgFileNotFound] cmp al,2h je @@Print lea si,[@@MsgPathNotFound] cmp al,3h je @@Print lea si,[@@MsgTooManyFiles] cmp al,4h je @@Print lea si,[@@MsgAccessDenied] cmp al,5h je @@Print lea si,[@@MsgInvalidFormat] cmp al,0Bh je @@Print lea si,[@@MsgInvalidDrive] cmp al,0Fh je @@Print lea si,[@@MsgCannotRmDir] cmp al,10h je @@Print lea si,[@@MsgUnknown] @@Print: call WriteStr lea si,[FileName] call WriteStr lea si,[@@CrLf] call WriteStr call FreeBuffer call ClearFileName mov ax,4C04h int 21h @@MsgUnknown DB 'Unknown Error: ',0 @@MsgFileNotFound DB 'File not found: ',0 @@MsgPathNotFound DB 'Path not found: ',0 @@MsgTooManyFiles DB 'Too many open files: ',0 @@MsgAccessDenied DB 'Access denied: ',0 @@MsgInvalidFormat DB 'Invalid format: ',0 @@MsgInvalidDrive DB 'Invalid drive specified: ',0 @@MsgCannotRmDir DB 'Cannot remove directory: ',0 @@CrLf DB 0Dh,0Ah,0 ENDP PROC AppendToFileName ; Expects: [ds:si] - ASCIIZ String ; Returns: [ds:FileName] - ASCIIZ String ; Uses: al,si,di lea di,[FileName] dec di @@FindEnd: inc di cmp [byte ptr di],0 jne @@FindEnd @@AddChar: mov al,[si] mov [di],al cmp al,0 je @@Exit inc si inc di cmp di,OFFSET FileName+MaxFileNameLen jb @@AddChar lea si,[@@MsgStrOverflow] call FreeBuffer call ClearFileName call WriteStr mov ax,4C03h int 21h @@Exit: ret @@MsgStrOverflow DB 'Error: File name too long.',0Dh,0Ah,0 ENDP PROC GetLastFileName ; Expects: [ds:FileName] - ASCIIZ String ; Returns: [ds:FileName] - ASCIIZ String, cf=(1-StrUnderflow) ; Uses: ax,di lea di,[FileName] dec di @@FindEnd: inc di cmp [byte ptr di],0 jne @@FindEnd mov ax,di dec di sub ax,OFFSET FileName cmp al,[FileNameStart] jc @@Exit @@FindSlash: dec di cmp [byte ptr di],'\' jne @@FindSlash mov [byte ptr di+1],0 clc @@Exit: ret ENDP PROC WriteStr ; Expects: [ds:si] - ASCIIZ String ; Returns: - ; Uses: ax,dl,si mov ah,2h @@Loop: mov dl,[si] cmp dl,0 je @@Exit int 21h inc si jmp @@Loop @@Exit: ret ENDP ; Undefined data FileNameStart DB ? BufSeg DW ? BufLen DW ? ; in bytes FileName DB MaxFileNameLen DUP(?) OldFileName DB MaxFileNameLen DUP(?) ; Program Stack EVENDATA DB 100h DUP(?) LABEL StackEnd NEAR ; End of program ProgramLen= $-Start+100h END Start