News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Simple file read & write functions

Started by Vortex, December 19, 2007, 07:41:36 PM

Previous topic - Next topic

Vortex

Two functions to read and write files : ReadFileToMem and WriteFileToDisc

ReadFileToMem :

.386
.model flat,stdcall
option casemap:none

include filefunc.inc

READFILE_MEMINFO STRUCT

    hHeap       DWORD   ?
    hMem        DWORD   ?
    FileSize    DWORD   ?

READFILE_MEMINFO ENDS   

PUBLIC  ReadFileToMem@8

.code

;   ReadFileToMem PROC pFileName:DWORD,pMemInfo:DWORD

;   pFileName       :   pointer to name of the file
;   pMemInfo        :   pointer to structure for allocated memory information

;   Return values   :   if the function succeeds, eax is NULL.
;                       if the function fails, the return value contains the error code                     


ReadFileToMem@8:

    sub     esp,5*4                         ; reserve 20 bytes for the local variables
    push    esi
    mov     esi,DWORD PTR [esp+32]
    invoke  GetProcessHeap
    test    eax,eax
    jne     @f
    mov     eax,1
    jmp     error
@@:
    mov     DWORD PTR [esp+8],eax           ; save the handle of the process heap
    mov     READFILE_MEMINFO.hHeap[esi],eax
    invoke  CreateFile,DWORD PTR [esp+52],GENERIC_READ,0,0,\
            OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,0
    cmp     eax,INVALID_HANDLE_VALUE
    jne     @f
    mov     eax,2
    jmp     error
@@:
    mov     DWORD PTR [esp+20],eax          ; save the handle of file
    invoke  GetFileSize,eax,0
    mov     DWORD PTR [esp+12],eax          ; save the file size
    mov     READFILE_MEMINFO.FileSize[esi],eax
    invoke  HeapAlloc,DWORD PTR [esp+16],HEAP_ZERO_MEMORY,eax
    mov     DWORD PTR [esp+8],eax           ; save the address of the allocated memory
    mov     READFILE_MEMINFO.hMem[esi],eax
    lea     ecx,DWORD PTR [esp+16]          ; get the address of number of bytes read
    invoke  ReadFile,DWORD PTR [esp+36],eax,DWORD PTR [esp+20],ecx,0
    test    eax,eax
    jnz     @f
    mov     eax,3
    jmp     error
@@:   
    invoke  CloseHandle,DWORD PTR [esp+20]
    xor     eax,eax

error:   
   
    pop     esi
    add     esp,5*4                         ; balance the stack
    ret     2*4

;   ENDP ReadFileToMem

END


WriteFileToDisc :

.386
.model flat,stdcall
option casemap:none

include filefunc.inc

PUBLIC  WriteFileToDisc@12

.code

;   WriteFileToDisc PROC pFileName:DWORD,pMemory:DWORD,nSize:DWORD

;   pFileName       :   pointer to name of the file
;   pMemory         :   address of buffer to write file
;   nSize           :   number of bytes to write

;   Return values   :   if the function succeeds, eax is non-NULL
;                   :   if the function fails, the return value is NULL   


WriteFileToDisc@12:

    sub     esp,2*4                 ; reserve 8 bytes for the local variables
    invoke  CreateFile,DWORD PTR [esp+36],GENERIC_WRITE,0,0,\
            CREATE_ALWAYS,FILE_ATTRIBUTE_ARCHIVE,0
    cmp     eax,INVALID_HANDLE_VALUE
    jne     @f
    xor     eax,eax
    jmp     finish
@@:
    mov     DWORD PTR [esp],eax     ; save the handle of file
    lea     ecx,DWORD PTR [esp+4]   ; get the address of number of bytes written
    invoke  WriteFile,eax,DWORD PTR [esp+28],DWORD PTR [esp+28],ecx,0
    test    eax,eax
    jz      finish
    invoke  CloseHandle,DWORD PTR [esp]

finish:

    add     esp,2*4                 ; balance the stack
    ret     3*4

;   ENDP WriteFileToDisc

END

[attachment deleted by admin]

rags

Vortex,
Just curious, why the '2*4', '3*4' etc. in the code and not simply 8, 12, etc.
Is it just personal preference?
Rags
God made Man, but the monkey applied the glue -DEVO

Vortex

Hi rags,

The notation 2*4, 3*4 is more descriptive and it makes easier to understand how the stack is manipulated. Poasm does not support the statements OPTION PROLOGUE and OPTION EPILOGUE statements and I I thought that I should explain the coding style of the procedures stripped of HLL elements.

Vortex

I modified ReadFileToMem to handle the memory allocation for the buffer receiving the file to read. New upload at the top.

Vortex

A FreeMemory function to release the allocated memory to read files :

.386
.model flat,stdcall
option casemap:none

HeapFree PROTO :DWORD,:DWORD,:DWORD

READFILE_MEMINFO STRUCT

    hHeap       DWORD   ?
    hMem        DWORD   ?
    FileSize    DWORD   ?

READFILE_MEMINFO ENDS   

PUBLIC FreeMemory@4

.code

;   FreeMemory  PROC pMemInfo

;   pMemInfo    :   pointer to structure for allocated memory information

FreeMemory@4:

    mov     edx,DWORD PTR [esp+4]
    invoke  HeapFree,READFILE_MEMINFO.hHeap[edx],0,READFILE_MEMINFO.hMem[edx]
    ret     4

;   ENDP FreeMemory

END

[attachment deleted by admin]

Vortex

- Removed some unnecessary local variables :

.386
.model flat,stdcall
option casemap:none

include filefunc.inc

READFILE_MEMINFO STRUCT

    hHeap       DWORD   ?
    hMem        DWORD   ?
    FileSize    DWORD   ?

READFILE_MEMINFO ENDS   

PUBLIC  ReadFileToMem@8

.code

;   ReadFileToMem PROC pFileName:DWORD,pMemInfo:DWORD

;   pFileName       :   pointer to name of the file
;   pMemInfo        :   pointer to structure for allocated memory information

;   Return values   :   if the function succeeds, eax is NULL.
;                       if the function fails, the return value contains the error code                     


ReadFileToMem@8:

    sub     esp,2*4                             ; reserve 8 bytes for the local variables
    push    esi
    mov     esi,DWORD PTR [esp+20]
    invoke  GetProcessHeap
    test    eax,eax
    jne     @f
    mov     eax,1
    jmp     error
@@:
    mov     READFILE_MEMINFO.hHeap[esi],eax ; save the handle of the process heap
    invoke  CreateFile,DWORD PTR [esp+40],GENERIC_READ,0,0,\
            OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,0
    cmp     eax,INVALID_HANDLE_VALUE
    jne     @f
    mov     eax,2
    jmp     error
@@:
    mov     DWORD PTR [esp+4],eax               ; save the handle of file
    invoke  GetFileSize,eax,0
    mov     READFILE_MEMINFO.FileSize[esi],eax
    invoke  HeapAlloc,READFILE_MEMINFO.hHeap[esi],HEAP_ZERO_MEMORY,eax
    mov     READFILE_MEMINFO.hMem[esi],eax      ; save the address of the allocated memory
    lea     ecx,DWORD PTR [esp+8]               ; get the address of number of bytes read
    invoke  ReadFile,DWORD PTR [esp+20],eax,READFILE_MEMINFO.FileSize[esi],ecx,0
    test    eax,eax
    jnz     @f
    mov     eax,3
    jmp     error
@@:   
    invoke  CloseHandle,DWORD PTR [esp+4]
    xor     eax,eax

error:   
   
    pop     esi
    add     esp,2*4                         ; balance the stack
    ret     2*4

;   ENDP ReadFileToMem

END

[attachment deleted by admin]

Vortex

Simplified code with the usage of VirtualAlloc :

.386
.model flat,stdcall
option casemap:none

include filefunc.inc

PUBLIC  ReadFileToMem@12

.code

;   ReadFileToMem PROC pFileName:DWORD,pMem:DWORD,pNumbOfBytesRead:DWORD

;   pFileName           :  pointer to name of the file
;   pMem                :  pointer receiving the memory block allocated to read the input file
;   pNumbOfBytesRead    :  pointer receiving the number of bytes read

;   Return value        :  if the function succeeds, the return value is 3
;                          if the function fails, the return value contains an error code                     


ReadFileToMem@12:

    sub     esp,4*4                                                 ; reserve 12 bytes for local variables
   
    invoke  CreateFile,DWORD PTR [esp+44],GENERIC_READ,0,0,\
            OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,0                  ; open file
    cmp     eax,INVALID_HANDLE_VALUE
    je      _exit2
@@:
    mov     DWORD PTR [esp+12],eax
    invoke  GetFileSize,eax,0
    mov     DWORD PTR [esp],eax
    invoke  VirtualAlloc,0,eax,MEM_COMMIT,PAGE_READWRITE            ; allocate memory
    test    eax,eax
    jnz     @f
    invoke  CloseHandle,DWORD PTR [esp+12]
    mov     eax,1
    jmp     _exit2
@@:
    mov     DWORD PTR [esp+8],eax
    mov     edx,DWORD PTR [esp+24]
    mov     DWORD PTR [edx],eax

    lea     edx,[esp+4]
    invoke  ReadFile,DWORD PTR [esp+28],eax,DWORD PTR [esp+8],edx,0 ; read file
    test    eax,eax
    jnz     @f
    invoke  CloseHandle,DWORD PTR [esp+12]
    mov     eax,2
    jmp     _exit1
@@:
    mov     edx,DWORD PTR [esp+28]
    mov     eax,DWORD PTR [esp+4]
    mov     DWORD PTR [edx],eax
    invoke  CloseHandle,DWORD PTR [esp+12]                          ; close file
    test    eax,eax
    jz      _exit1
    mov     eax,3
    jmp     _exit2
   
_exit1:

    push    eax
    invoke  VirtualFree,DWORD PTR [esp+12],0,MEM_RELEASE            ; release the allocated memory if there was
    pop     eax                                                     ; an error while reading the file
                                                                    ; or closing the handle
_exit2:   

    add     esp,4*4                                                 ; balance the stack manually
    ret     3*4                                                     ; release the three parameters and return back   
                                                                    ; to the main module
;   ENDP ReadFileToMem

END

[attachment deleted by admin]

Vortex

More simplified routines. Now, it's the the caller's responsibility to allocate memory to read file.

.386
.model flat,stdcall
option casemap:none

include filefunc.inc

PUBLIC  ReadFileToMem@12

.code

;   ReadFileToMem PROC pFileName:DWORD,pMem:DWORD,pNumbOfBytesRead:DWORD

;   pFileName           :  pointer to name of the file
;   pMem                :  pointer to the memory block allocated to read the input file
;   pNumbOfBytesRead    :  pointer receiving the number of bytes read

;   Return value        :  if the function succeeds, the return value is 2
;                          if the function fails, the return value is 1,0 or -1
;                          depending on the situation 


ReadFileToMem@12:

    sub     esp,2*4                                                     ; reserve 12 bytes for local variables
    push    edi
   
    invoke  CreateFile,DWORD PTR [esp+40],GENERIC_READ,0,0,\
            OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,0                      ; open file
    cmp     eax,INVALID_HANDLE_VALUE
    je      _exit
@@:
    mov     DWORD PTR [esp+8],eax                                       ; save the file handle
    invoke  GetFileSize,eax,0
    lea     edx,DWORD PTR [esp+4]
    invoke  ReadFile,DWORD PTR [esp+24],DWORD PTR [esp+32],eax,edx,0    ; read file
    test    eax,eax
    jz      _exit
@@:
    push    DWORD PTR [esp+4]
    pop     DWORD PTR [esp+24]                                          ; receive the number of bytes read

    invoke  CloseHandle,DWORD PTR [esp+8]                               ; close file
    test    eax,eax
    jnz     @f
    mov     eax,CLOSE_HANDLE_ERROR
    jmp     _exit
@@:
    mov     eax,READ_FILE_SUCCESS   

_exit:

    pop     edi
    add     esp,2*4                                                     ; balance the stack manually
    ret     3*4                                                         ; release the three parameters and return back   
                                                                        ; to the main module
;   ENDP ReadFileToMem

END

[attachment deleted by admin]