News:

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

Macros for normal file IO

Started by hutch--, February 03, 2005, 03:00:02 AM

Previous topic - Next topic

hutch--

I have just finished a set of macros for performing normal file IO operations. They are almost exclusively wrappers for API file IO functions with a number of extras so that this capacity can be put into function/statement format using names that are closer to historical file operations than disconnected API functions.

The example file uses an include file for the normal prototypes, processor model and the like called masm32rt.inc which is included in the example zip file. It should be placed in the include directory in MASM32.

Feedback, comments and suggestions are welcome. I want this capacity for the next revision/update/version of MASM32.

[attachment deleted by admin]
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Peterpan

Hutch,

Thanks for the macro  :U
I found a few mistake in the macro.

WriteFile returns a BOOL value to indicate success or failure. The bytes written is returned in the parameter. And so with the ReadFile

Your fwrite and fread macro is

    fread MACRO hFile,buffer,bcnt
      LOCAL var
      .data?
        var dd ?
      .code
      invoke ReadFile,hFile,buffer,bcnt,ADDR var,NULL
      mov eax, var
      EXITM <eax>       ; return bytes read
    ENDM

    fwrite MACRO hFile,buffer,bcnt
      LOCAL var
      .data?
        var dd ?
      .code
      invoke WriteFile,hFile,buffer,bcnt,ADDR var,NULL
      mov eax, var
      EXITM <eax>       ; return bytes written
    ENDM


Could be simpler

    fread MACRO hFile,buffer,bcnt
       invoke ReadFile, hFile, buffer, bcnt, ADDR bcnt, NULL
       EXITM <eax>    ; return success or failed
    ENDM

    fwrite MACRO hFile, buffer, bcnt
       invoke WriteFile, hFile, buffer, bcnt, Addr bcnt, NULL
       EXITM <eax>    ; return success or failed
    ENDM

pbrennick

Peterpan,
I tried your changes and got compile errors.  Hutch's version compiles without errors.

Paul

hutch--

Peter,

Thanks for the effort. I return the DWORD vaiable because it contains useful information on the byte count that is either read or written. You can test for error conditions using GetLastError() as well as getting the return value with the current system.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Peterpan

Hutch,

Arrrggghh... :bdg  :'(
Sorry for my english. I should not said that it is a mistake  :'(
Maybe it's because of my flu. I had a a great headeache for the last couple days. Actually I just want to make it simpler, that's all.

I changed the macro to be simpler (well, for me of course  :green2 ) and it is still return both values. which is the status in EAX, and the bytes read or written is in the parameter directly.

However your macro is more convinience, because we don't have to create a variable. The macro will do it for us  :U

So I can call like this ( this code taken from Self Delete thread ):

SelfDelete Proc uses ESI EDI

Local lh_File:HFILE
Local ln_Bytes:DWORD, ln_MajorVersion:DWORD
Local lb_Succeed:BOOL
Local lc_FileName[MAX_PATH]:BYTE
Local l_Buffer[512]:BYTE

   lea esi, lc_FileName
   lea edi, l_Buffer
   invoke GetModuleFileName, hInstance, esi, MAX_PATH
   invoke wsprintf, edi, offset BatchText, esi, esi

   mov ln_Bytes, FUNC( lstrlen, edi )

   mov lh_File, fcreate( offset BatchName )
   .If ( lh_File )

      mov lb_Succeed, fwrite( lh_File, edi, ln_Bytes )
      ; lb_Succeed = status
      ; ln_Bytes = bytes written

      fclose lh_File

      .If ( lb_Succeed )
         invoke ShellExecute, NULL, offset BatchOp, offset BatchName,
               NULL, NULL, SW_HIDE
      .else
         invoke DeleteFile, offset BatchName
      .endif
   .endif

   ret
SelfDelete EndP


Again, I'm sorry for my words. Oh there is one more macro that missing. Flushing the buffers ( FlushFileBuffers API )


pbrennick,

I'm not sure why you have the error. But the difference between the original and the changes I made, is, you have to create the variable your own and pass it in the third parameter, because it also use to return the bytes read or written. The original macro doesn't have to, the macro already take care of it.

pbrennick

Peterpan,
Color me silly.  Your SelfDelete code in another thread compiled just fine.  Guess I am getting lazy or senile, maybe both.  Wouldn't that be fun?

Paul

Peterpan

pbrennick,

No offends, but I think you are just getting lazy. Hehehe.... :bg
Well..that is fine. I see you are one of the most active moderator here
:U

pbrennick

Peterpan,
As was said in my introduction, it is because I am functionally disabled and I pretty much live in a recliner these days.  I very seldom walk any more and when I do I must wear braces which are very painful.  Anyway, it is really nothing special about me, others would be more active if they had the same free time as I have.  I can't wait for Donkey to solve his problems and get back because he is very smart.

Paul

zooba

Quote from: Peterpan on February 08, 2005, 04:23:47 PM

    fread MACRO hFile,buffer,bcnt
       invoke ReadFile, hFile, buffer, bcnt, ADDR bcnt, NULL
       EXITM <eax>    ; return success or failed
    ENDM


Just from looking at this, I'd say pbrennick's compile error came from passing 'ADDR bcnt' to the macro, which then expanded to:


    invoke ReadFile, hFile, buffer, bcnt, ADDR ADDR bcnt, NULL


I don't know if there is a standard regarding passing ADDR to macro's or not, but at the very least, you should keep it consistent throughout one single macro  :wink

Peterpan

Quote from: pbrennick on February 14, 2005, 04:57:02 PM
As was said in my introduction, it is because I am functionally disabled and I pretty much live in a recliner these days.  I very seldom walk any more and when I do I must wear braces which are very painful.  Anyway, it is really nothing special about me, others would be more active if they had the same free time as I have.  I can't wait for Donkey to solve his problems and get back because he is very smart.

pbrennick,

I truly am sorry to hear that. ::)
When I said "you are getting lazy", I thought that sometimes you get sick & tired to answer all the question, especially newbie's question. I really didn't know about your condition and I have no intention to offended you in anyway. Please accept my apologies :)
BTW, yes I do know Donkey is a smart guy ( as well as all moderators here  :U ) ever since win32asmboard.cjb.net


Quote from: zoobaI don't know if there is a standard regarding passing ADDR to macro's or not, but at the very least, you should keep it consistent throughout one single macro 

zooba
I agree. Well I kept my macros and other things consistent. However when I posted that, I only want to make it worked, so I didn't think too far  :bg

hutch--

Issues like those mentioned are why I built the macro in this form.


    fread MACRO hFile,buffer,bcnt
      LOCAL var
      .data?
        var dd ?
      .code
      invoke ReadFile,hFile,buffer,bcnt,ADDR var,NULL
      mov eax, var
      EXITM <eax>       ; return bytes read
    ENDM


The return value is the data section variable so that the user does not have to set the variable on the stack first.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Gustav

> The return value is the data section variable so that the user does not have to set the variable on the stack first

That's ok but this strategy is not thread safe. What about a slight modifcation:

    fread MACRO hFile,buffer,bcnt
      push 0
      invoke ReadFile,hFile,buffer,bcnt,ADDR [esp+4],NULL
      pop eax
      EXITM <eax>       ; return bytes read
    ENDM

hutch--

Gustav,

Thansk for the suggestion, its an interesting idea and looks like it is safe enough to use.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php