;------------------------------------------------------------------------------ ; This program demonstrates the use of kernel32.lib for reading and writing ; disk files. The user will enter a file name to read and a file name to write. ; The program will then access the disk to read and write the files. ; ; Written by Joe Toone 11/28/2004 7:28:26 PM ;------------------------------------------------------------------------------ TITLE files32.asm CR equ 0dh ;ASCII 13 for carriage return LF equ 0ah ;ASCII 10 for line feed TRUE equ 1h ;Boolean flags FALSE equ 0h ; MAXSTR equ 256d ;Max path length for a command window BUFFERSIZE equ 0200h ;Decimal 512 for buffer size CREATE_NEW EQU 1 ;Parameter for creating a new file CREATE_ALWAYS EQU 2 ;Always create (overwrite existing) OPEN_EXISTING EQU 3 ;Parameter for opening an existing file GENERIC_READ EQU 80000000h ;Parameter for reading a file GENERIC_WRITE EQU 40000000h ;Parameter for writing a file STD_INPUT equ -10d ;Function number for keyboard input STD_OUTPUT equ -11d ;Function number for monitor output ENABLE_PROCESSED_INPUT equ 1 ;Flag to turn off line buffering ENABLE_PROCESSED_OUTPUT equ 1 ;Flag to turn off line buffering ENABLE_LINE_WRAP equ 3 ;Flag to turn line wrap on DISABLE_PROCESSED_INPUT equ 7 ;Flag to turn on line buffering .586 ;Allow Pentium instructions .MODEL FLAT ;FLAT memory model INCLUDELIB kernel32.lib ;Include the kernel 32 library ExitProcess PROTO NEAR32 stdcall, ;Prototype for Exit to OS dwExitCode:DWORD SetConsoleMode PROTO NEAR32 stdcall, ;Prototype for attaching to console hConsoleHandle:DWORD, dwMode:DWORD GetStdHandle PROTO NEAR32 stdcall, ;Prototype for obtaining a file handle nStdHandle:DWORD ReadFile PROTO NEAR32 stdcall, ;Prototype for reading a file hFile:DWORD, lpBuffer:NEAR32, nNumberOfCharsToRead:DWORD, lpNumberOfBytesRead:NEAR32, lpOverlapped:NEAR32 WriteFile PROTO NEAR32 stdcall, ;Prototype for writing a file hFile:DWORD, lpBuffer:NEAR32, nNumberOfCharsToWrite:DWORD, lpNumberOfBytesWritten:NEAR32, lpOverlapped:NEAR32 CreateFileA PROTO NEAR32 stdcall, ;Prototype for creating a file lpFileName:NEAR32, access:DWORD, shareMode:DWORD, lpSecurity:NEAR32, creation:DWORD, attributes:DWORD, copyHandle:DWORD CloseHandle PROTO NEAR32 stdcall, ;Prototype for closing a file fHandle:DWORD GetLastError PROTO NEAR32 stdcall ;Prototype for getting specific error .STACK 4096h ;4K hex bytes for stack .DATA InPrompt BYTE 'Enter the name of the disk file to READ --> ',0 OutPrompt BYTE 'Enter the name of the disk file to WRITE --> ',0 FileNotFound BYTE cr,lf,'The Input File was Not Found!',cr,lf,cr,lf,0 PermissionDenied BYTE cr,lf,'Permission Denied!',cr,lf,cr,lf,0 FileExists BYTE cr,lf,'The Output File Already Exists!',cr,lf,cr,lf,0 ErrorMsg BYTE cr,lf,'A file Error has Occured!',cr,lf,cr,lf,0 Success BYTE CR,LF,LF,'The operation completed successfully.',CR,LF,LF,0 Continue BYTE 'Process additional files? (y/n)',0 KeyIn BYTE ? FileErr BYTE FALSE Buffer BYTE BUFFERSIZE dup(0) InFile BYTE MAXSTR dup(0) OutFile BYTE MAXSTR dup(0) InHandle DWORD 0 OutHandle DWORD 0 written DWORD 0 read DWORD 0 hStdOut DWORD 0 hStdIn DWORD 0 hFile DWORD 0 strAddr DWORD 0 strLength DWORD 0 ;-------- Main Body ----------------------------------------------------------- ; Given :Nothing ; Process :Main Body - contains inline code and procedure calls to accept ; input and output file names from the user. Read the input file ; the from disk and write the output file to the disk. ; Return :Nothing ;------------------------------------------------------------------------------ .CODE _main: DoMore: lea esi,InPrompt ;Set esi to InPrompt message call PrintString ;Call the routine to print a string lea esi,InFile ;Pointer to input file name call GetString ;Accept file name from the user lea esi,OutPrompt ;Pointer to output file name prompt call PrintString ;Call the routine to print a string lea esi,OutFile ;Pointer to output file name call GetString ;Accept file name from the user call OpenFiles ;Go open the files and get the handles .if FileErr != TRUE ;If no file errors have occured call ReadWrite ;Read the existing file and write to ; a new file call CloseFiles ;Go close the open files lea esi,Success ;Pointer to successful operation call PrintString ;Go print the congrats .endif ; lea esi,Continue ;Point to continue message call PrintString ; go ask for continue or quit lea esi,KeyIn ;Pointer for character storage call GetString ;Get the reply cmp KeyIn,'y' ;Check for continue jz DoMore ;Jump to do more files INVOKE ExitProcess, 0 ;exit with return code 0 ;--------- Open the user requested disk files --------------------------------- ; Given :Name of file to read in InFile variable and the name of the file to ; :write in the OutFile variable. ; Process :Open the Input and Output files and obtain the file handles. Check ; :for file errors and display error messages if needed. No registers ; :are changed and the flags are not affected. ; Return :File handles in InHandle and OutHandle ;------------------------------------------------------------------------------ OpenFiles PROC NEAR32 pushad ; save all registers pushfd ; save flags mov FileErr,FALSE ; clear previous file name errors INVOKE CreateFileA, ; open input file NEAR32 PTR InFile, ; ASCII file name GENERIC_READ, ; access type (read) 0, ; no sharing 0, ; no predefined security OPEN_EXISTING, ; open only if file exists 0, ; no special attributes 0 ; no copied handle mov InHandle, eax ; store handle for input file cmp InHandle,-1 ; check for file error jz FileError ; go give an error message INVOKE CreateFileA, ; open output file NEAR32 PTR OutFile, ; ASCII file name GENERIC_WRITE, ; access type (write) 0, ; no sharing 0, ; no predefined security CREATE_NEW, ; open if file doesn't exist 0, ; no special attributes 0 ; no copied handle mov OutHandle, eax ; store handle for output file cmp OutHandle,-1 ; was there file error? jnz GotHandles ; no, then we have good handles FileError: INVOKE GetLastError ; yes, then find the specific error .if eax == 2 ; assembler directive .if errno = 2 lea esi,FileNotFound ; then load filenotfound message .elseif eax == 5 ; else if errno = 5 lea esi,PermissionDenied ; load permissiondenied message .elseif eax == 80 ; else if errno = 80 lea esi,FileExists ; load file exists message .else ; else lea esi,ErrorMsg ; load generic message .endif ; end if structure call PrintString ; display appropriate error message mov FileErr,TRUE ; a file name error has occured GotHandles: popfd ; restore flags popad ; restore registers ret ; return to caller OpenFiles ENDP ;--------- Read the Input file and write it to the Output file ---------------- ; Given :InHandle and OutHandle variables for files to be processed. ; Process :Read the user supplied input file and write it's contents to the ; :user supplied output file. No registers are changed and the ; :flags are not affected. ; Return :Nothing ;------------------------------------------------------------------------------ ReadWrite PROC NEAR32 pushad ; save all registers pushfd ; save flags readLoop: INVOKE ReadFile, InHandle, ; file handle to read from NEAR32 PTR Buffer, ; address for input buffer BUFFERSIZE, ; buffer length NEAR32 PTR read, ; number of bytes read 0 ; overlapped mode INVOKE WriteFile, OutHandle, ; file handle for file to write NEAR32 PTR Buffer, ; address for output buffer read, ; write same number as we read NEAR32 PTR written, ; number of bytes written 0 ; overlapped mode cmp read, BUFFERSIZE ; were BUFFERSIZE characters read? jnl readLoop ; if so, continue, else we have EOF popfd ; restore flags popad ; restore registers ret ; return to caller ReadWrite ENDP ;--------- Close the user opened disk files ----------------------------------- ; Given :InHandle and OutHandle variables for files to be closed. ; Process :Close the Input and Output files to insure that all buffers are ; flushed and free up the file handles. ; Return :Nothing ;------------------------------------------------------------------------------ CloseFiles PROC NEAR32 pushad ; save all registers pushfd ; save flags INVOKE CloseHandle, ; close the input file InHandle ; passing the file handle INVOKE CloseHandle, ; close the output file OutHandle ; passing the file handle popfd ; restore flags popad ; restore registers ret ; return to caller CloseFiles ENDP ;--------------------- Near procedure to get a String ------------------------- ; Given : The Address of the String to fill in ESI register ; Process : Input the String using the kernel32.lib ReadFile from the ; : Standard_Input function call. No registers are changed and the ; : flags are not affected. ; Return : The input string in the data segment ;------------------------------------------------------------------------------ GetString PROC NEAR32 ; Define procedure pushad ; save all registers pushfd ; save flags INVOKE GetStdHandle,STD_OUTPUT ; get handle for console mov hStdOut, eax ; save the handle INVOKE SetConsoleMode, ; invoke standard console with hStdOut, ; file handle for keyboard ENABLE_LINE_WRAP ; turn line wrap on INVOKE GetStdHandle,STD_INPUT ; get handle for console mov hStdIn, eax ; save the handle INVOKE SetConsoleMode, ; invoke standard console with hStdIn, ; file handle for keyboard DISABLE_PROCESSED_INPUT ; turn line buffering on mov ecx, MAXSTR ; string length mov strLength, ecx ; maximum string to accept mov strAddr, esi ; save pointer to input string INVOKE ReadFile, ; invoke standard ReadFile with hStdIn, ; file handle for keyboard strAddr, ; address of string strLength, ; length of string NEAR32 PTR read, ; variable for # bytes read 0 ; overlapped mode mov ecx, read ; number of bytes read mov BYTE PTR [esi+ecx-2],0 ; replace CR/LF by trailing null popfd ; restore flags popad ; restore registers ret ; return to caller GetString ENDP ;------------------- NEAR32 procedure to print a string ----------------------- ; Given : The Address of Null (0) terminated String to print in ESI register ; Process : Print the String using the kernel32.lib WriteFile to ; : Standard_Output function call. No registers are changed and the ; : flags are not affected. ; Return : Nothing ;------------------------------------------------------------------------------ PrintString PROC NEAR32 pushad ; save registers pushfd ; save flags mov strAddr, esi ; copy string address ; find string length mov strLength, 0 ; initialize string length WhileChar: cmp BYTE PTR [esi], 0 ; character = null? jz EndWhileChar ; exit if yes inc strLength ; increment character count inc esi ; point at next character jmp WhileChar ; while more characters exist EndWhileChar: INVOKE GetStdHandle,STD_OUTPUT ; get handle for console output mov hStdOut, eax ; copy file handle for screen INVOKE WriteFile, ; invoke standard WriteFile with hStdOut, ; file handle for screen strAddr, ; address of string strLength, ; length of string NEAR32 PTR written, ; variable for # bytes written 0 ; overlapped mode popfd ; restore flags popad ; restore registers ret ; return to caller PrintString ENDP Public _main ;declare _main as a public procedure END ;end of code segment