Jump to content
Tuts 4 You

[MASM] ReadFile and lpNumberOfBytesRead? *New*


Gushe

Recommended Posts

Hey all!

I am working on my first project in MASM at the moment, and it is actually going quite well. :lol:

Though I ran into a small problem. I want to read a file into memory and save it to another file, with some changes (yeah, I want to encrypt a file), and for doing this I am creating a new procedure. Now, because of everbody has a different amount of memory I let the user define how much bytes they want to be loaded in memory at once for encrypting. The more bytes loaded at once, the less ReadFile has to be called, and the quicker the encrypting will be.

But what if the last block of bytes is to be read? (I reach EOF) the lpNumberOfBytesRead parameter should be set to 0 when EOF is reached, but for my encryption loop I will need to know how many iterations the loop has to make, and therefore the amount of bytes looaded into memory.

What would be the best approach for this?

(If anybody understands what I want to say :lol: )

Because I do not want to be too lazy, here are two idea's I've had. :)

Idea One:

This one is more secure if lpNumberOfBytesRead (here bytesRead) doesn't return 0 when the filesize is actually smaller than lpNumberOfBytesToRead.

		mov eax, bytesRead		
.IF eax <= blockSize
mov isFinished, TRUE
.ENDIF
.IF bytesRead == 0
invoke GetFileSize, hInputFile, NULL
mov bytesRead, eax
.ENDIF

Second:

Depends on correctness of lpNumberOfBytesToRead, but this one is faster in a loop. (Since the blocks are read in a loop also)

.IF bytesRead == 0
mov isFinished, TRUE
invoke GetFileSize, hInputFile, NULL
mov bytesRead, eax
.ENDIF

What would you guys do? :)

~ GuShe

Edited by Gushe
Link to comment

I'll try to explain better.

I want to use the ReadFile function to read a specified amount of bytes from a certain file.

BOOL WINAPI ReadFile(
__in HANDLE hFile,
__out LPVOID lpBuffer,
__in DWORD nNumberOfBytesToRead,
__out_opt LPDWORD lpNumberOfBytesRead,
__inout_opt LPOVERLAPPED lpOverlapped
);

Now, what if the value in nNumberOfBytesToRead is larger than the actual file? msdn says the following:

When a synchronous read operation gets to the end of a file, ReadFile returns TRUE and sets the variable pointed to by the lpNumberOfBytesRead parameter to zero.

But even in this case, I need to know the exact amount of bytes read by the function, because I need them for an encryption algorythm.

My problem is how to get that number. :lol:

Link to comment

Easy, just call GetFileSize:

; ------------ Get File size ----------invoke GetFileSize, hFile, addr lpFileSizeHigh
mov fileSize, eax

Then fileSize will hold the number of bytes to base your array on, like:

; ------------ Create compatible array ----------
invoke VirtualAlloc, NULL, FileSize, MEM_COMMIT, PAGE_READWRITE
mov [pArray], eax
invoke VirtualLock, addr [pArray], fileSize

Don't forget to always check the return value in case it returns INVALID.

MACH4

Link to comment

I stumbled upon another problem.

Let's say I am reading a file with a size of 10, and I am reading it per blocks of 3.

I can read 3 complete blocks, but then only 1 is left. The Read operation will succesfully read the 1 sized block, but I will not have any information on the size of that last block. GetFileSize would give me the size of the complete file, not only the last block.

Does anyone has an idea on how to solve this?

(without creating loads of new variables that will slow my application down o.O)

Thanks in Advance.

Link to comment

Just add bytesRead to your filePtr to know where you are!

Depending on just what your doing, it might be more convenient to read the file into an array to start with!

the same operation either way...

MACH4

Link to comment

It's not to know where I am, it's to determine the amount of bytes read into memory. Does something as arrays exist in MASM anyway? :D

I do not completely understand what you mean, excuse me.

Link to comment

well, just save the bytes read

ie. for every successful WriteFile, add +3 to a var and loop until var >= filesize

one variable sure as hell won't slow your app down lol

optimization is okay, but certainly not worth thinking about more than a minute if you're dealing with file operations.

say your writing and reading the var takes 10 cycles tops, the file operation will take up to 100 ms

considering 1Ghz means around 1 billion cycles per second, what's the point :D

Link to comment

Here you go. Did it a year ago for another programming forum, where I post as simonb2

It's masm code to read in and xor encrypt a file. Files are specified from the command line (or dropped onto the executable - select src then target and drop onto executable), while user is prompted to enter the char to xor encrypt with.

It runs at around 26 MB/sec on a 2.6 ghz celeron. Hope it's of some use.

ASM_Encrypter.zip

Link to comment

enhzflep, thanks for the code, but I do not understand how you get the amount of iterations needed when the filesize limit is reached.

Or I only get it half.

When does the application exactly determine you reached OEP, the last ReadFile that actually reads bytes (that reads one byte in my example above) or a readfile operation after that one, when no byte has been read? That would ease things up.. a LOT! =D

~ GuShe

Link to comment
Let's say I am reading a file with a size of 10, and I am reading it per blocks of 3.

I can read 3 complete blocks, but then only 1 is left. The Read operation will succesfully read the 1 sized block, but I will not have any information on the size of that last block. GetFileSize would give me the size of the complete file, not only the last block.

so, you know the filesize and you know the blocksize? then you can easily calculate the size of the last block.

filesize mod blocksize = lastblocksize

or in asm:

mov eax,filesize
mov ecx,blocksize
cdq
div ecx

result in edx is lastblocksize...

result in eax is number of iterations to read the file with your blocksize

Edited by diablo2oo2
Link to comment
When does the application exactly determine you reached EOF, the last ReadFile that actually reads bytes (that reads one byte in my example above) or a readfile operation after that one, when no byte has been read? That would ease things up.. a LOT! =D

~ GuShe

The last time ReadFile is called, it will read 0 bytes since it has hit the end of the file. This condition will be

recognized by the fact that the variable bytesActuallyRead contains the number 0. When bytesActuallyRead = 0,

I break out of the loop. I never bother to work out the size of the file, or the number of iterations needed

to process it - I just keep going till I can't read any more bytes from the input file.

	invoke	ReadFile, [inputFileHandle], ADDR readBuffer, bufLength, ADDR bytesActuallyRead, NULL
cmp [bytesActuallyRead], 0
je readingDone

E.g

10 byte file, 4 bytes read per iteration

1st loop: ReadFile, bytesActuallyRead = 4 ---> continue

2nd loop: ReadFile, bytesActuallyRead = 4 ----> continue

3rd loop: ReadFile, bytesActuallyRead = 2 ----> continue

4th loop: ReadFile, bytesActuallyRead = 0 -----> stop

Link to comment
When does the application exactly determine you reached EOF, the last ReadFile that actually reads bytes (that reads one byte in my example above) or a readfile operation after that one, when no byte has been read? That would ease things up.. a LOT! =D

~ GuShe

The last time ReadFile is called, it will read 0 bytes since it has hit the end of the file. This condition will be

recognized by the fact that the variable bytesActuallyRead contains the number 0. When bytesActuallyRead = 0,

I break out of the loop. I never bother to work out the size of the file, or the number of iterations needed

to process it - I just keep going till I can't read any more bytes from the input file.

	invoke	ReadFile, [inputFileHandle], ADDR readBuffer, bufLength, ADDR bytesActuallyRead, NULL
cmp [bytesActuallyRead], 0
je readingDone

E.g

10 byte file, 4 bytes read per iteration

1st loop: ReadFile, bytesActuallyRead = 4 ---> continue

2nd loop: ReadFile, bytesActuallyRead = 4 ----> continue

3rd loop: ReadFile, bytesActuallyRead = 2 ----> continue

4th loop: ReadFile, bytesActuallyRead = 0 -----> stop

That's what I used. :D Thanks anyay. ;)

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...