mov r9,[lpNumberOfBytesWritten] ;returns # bytes written
push NULL
sub rsp,32 ;shadow
call WriteFile
add rsp,32
;DWORD SetFilePointer(
; HANDLE hFile,
; LONG lDistanceToMove,
; PLONG lpDistanceToMoveHigh,
; DWORD dwMoveMethod
;);
mov rcx,[fHandle] ;handle
mov rdx, 7 ;low bits of position
mov r8,0 ;no high order bits in position
mov r9,FILE_BEGIN ;start from beginning
call SetFilePointer
;BOOL ReadFile(
; HANDLE hFile,
; LPCVOID lpBuffer,
; DWORD nNumberOfBytesToRead,
; LPDWORD lpNumberOfBytesRead,
; LPOVERLAPPED
;);
sub rsp,8 ;align
mov rcx,[fHandle] ;handle
lea rdx,[readbuffer] ;buffer to read into
mov r8,nNumberOfBytesToRead ;# bytes to read
mov r9,[lpNumberOfBytesRead] ;# bytes read
push NULL
sub rsp,32 ;shadow
call ReadFile
add rsp,32+8
;print result of ReadFile
mov rcx, fmt
mov rdx, readbuffer
sub rsp,32+8
call printf
add rsp,32+8
;BOOL WINAPI CloseHandle(
; _In_ HANDLE hObject
;);
mov rcx,[fHandle]
sub rsp,32+8
call CloseHandle
add rsp,32+8
leave
ret
Listing 43-1
files.asm
As before, we just use the C template of the Windows API function to build our assembly calls. To create the file, we just used the basic settings for access and security. When the creation succeeds, CreateFileA returns a handle to the created file. Note the parameters. You can read the Microsoft documentation to learn about the different parameters; there are quite a few possibilities that can help you in fine-tuning your file management.
The file handle will be used in WriteFile to write some text to the file. We already used WriteFile before to display a message on the console in Chapter 40.
After we have written the text to the file, we want to read the text back into memory, starting at location 7, where the first byte has index 0. With SetFilePointer, we move a pointer to the location where we want to start reading. If lpDistanceToMoveHigh is NULL, then lDistancetomove is a 32-bit value specifying the number of bytes to move. Otherwise, lpDistanceToMoveHigh and lDistancetomove together form a 64-value for the number of bytes to move. In r9, we indicate from where the move should start; the possibilities are FILE_BEGIN, FILE_CURRENT, and FILE_END.
When the pointer is set to a valid location, ReadFile will be used to start reading at that location. The bytes read are stored in a buffer and then printed. Finally, we close the file. Check your working directory, and you will see that the text file has been created.