I have data like this:
.data
file db "D:\hi.txt",0
ClassName db "Window1",0
AppName db "testing",0
.data?
pmem dd ?
hmem dd ?
fhandle dd ?
hInst dd ?
hwnd dd ?
The first are stored at 403000 (memory address) But when I call the getmessage function it alters the 8 bits (or maybe more) after 403004 and thus only D:\h is left at the adress of file and by consequence this gives me ERROR_INVALID_NAME error after calling createfile.
Does anyone know how to avoid this from happening ?
Thanks in advance,
Jannes
Check line 42.
... and don't panic :P
the point is, you aren't showing us any code
my guess is to....
check the MSG structure pointer
This is my full code, msg is just a LOCAL variable so I can't change it's address right. I don't get why it's address is mixing up with the existing data. Any comment on my code in general is welcome too because Im not sure whether what I have done is good enough.
Ill explain in short what the code is supposed to do (for now)
Make a window:
allocate 64 bytes to register the WNDCLASSEX structure
show the window
and free the allocated memory.
Allocate new memory as a buffer to store the keystrokes
get in the message loop.
Catch every keystroke
Alter the buffers value and write it to a file. (Im aware that the memory is not being altered in the correct way but first I should get the other things working)
repeat
.386
;.model flat,stdcall
option casemap:none
include \masm32\include\masm32rt.inc
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
.data
file db "D:\hi.txt",0
ClassName db "Window1",0
AppName db "testing",0
.data?
pmem dd ?
hmem dd ?
fhandle dd ?
hInst dd ?
hwnd dd ?
.code
start:
mov eax,SIZEOF WNDCLASSEX
invoke GetModuleHandle, NULL
mov hInst,eax
invoke WinMain, hInst,NULL,NULL, SW_SHOWDEFAULT
invoke ExitProcess, eax
WinMain proc hInstance:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL msg:MSG
invoke GlobalAlloc,GHND,64
mov hmem,eax
invoke GlobalLock,hmem
mov pmem,eax
mov ebp,offset pmem ; filling WNDCLASSEX structure
mov dword ptr [ebp],48
mov dword ptr [ebp+4],CS_HREDRAW or CS_VREDRAW
mov dword ptr [ebp+8],WndProc
mov ecx,1
mov dword ptr [ebp+8*ecx+4],NULL
mov dword ptr [ebp+8*ecx+8],NULL
inc ecx
mov eax,[hInst]
mov dword ptr [ebp+8*ecx+4],eax
mov dword ptr [ebp+8*ecx+8],NULL
inc ecx
push ecx
invoke LoadCursor,NULL,IDC_ARROW
pop ecx
mov dword ptr [ebp+8*ecx+4],eax
mov dword ptr [ebp+8*ecx+8],COLOR_HIGHLIGHT+1
inc ecx
mov dword ptr [ebp+8*ecx+4],NULL
mov dword ptr[ebp+8*ecx+8],offset ClassName
inc ecx
mov dword ptr [ebp+8*ecx+4],NULL
invoke RegisterClassEx, ebp
invoke GlobalUnlock,hmem
invoke GlobalFree,hmem
invoke CreateWindowEx, NULL, addr ClassName, addr AppName, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, NULL,NULL,hInstance,NULL
mov hwnd,eax
invoke ShowWindow,hwnd,SW_MAXIMIZE
invoke UpdateWindow,hwnd
invoke GlobalAlloc,GHND,65535
mov hmem,eax
invoke GlobalLock,hmem
mov pmem,eax
__MessageLoop:
invoke GetMessage,Addr msg,NULL,0,0
cmp eax,0
jz __BreakMessageLoop
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp __MessageLoop
__BreakMessageLoop:
invoke GlobalUnlock,hmem
invoke GlobalFree,hmem
mov eax,msg.wParam ; return exit code in eax
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
mov eax,uMsg
cmp eax, WM_DESTROY
jnz __cont1
invoke PostQuitMessage,NULL
jmp __cont
__cont1:
cmp eax,WM_KEYDOWN
jnz __cont2
;fn MessageBox,0,LastError$(),"can not create file",MB_OK
mov eax,wParam
mov ecx,offset pmem
mov dword ptr [ecx],eax
;fn MessageBox,0,LastError$(),"can not create file",MB_OK
invoke CreateFile, addr file, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
mov fhandle,eax
;fn MessageBox,0,LastError$(),"can not create file",MB_OK
invoke WriteFile, fhandle, pmem, 128, NULL, NULL
;fn MessageBox,0,LastError$(),"can not create file",MB_OK
invoke CloseHandle, fhandle
jmp __cont
__cont2:
invoke DefWindowProc,hWnd,uMsg,wParam,lParam ; Default message processing
ret
__cont:
xor eax,eax
ret
WndProc endp
end start
it's not the message loop
when the message loop receives messages, it dispatches them, as required, to the appropriate WndProc
that results in WndProc getting a message - which is more likely the culprit
on a glance, i do see one problem
invoke WriteFile, fhandle, pmem, 128, NULL, NULL
the 4th parameter should be the address of a dword variable that receives the number of bytes written
QuoteThis parameter can be NULL only when the lpOverlapped parameter is not NULL.
Small suggestion to avoid the "final crash":
; mov eax,msg.wParam ; return exit code in eax
invoke ExitProcess, msg.wParam
; ret
ok - i just noticed a big problem - so, it is the MSG structure, indirectly
when you create local variables, the EBP register is used to address them
that means that EBP is off limits, unless you take care to preserve it, use it, restore it before accessing a local
your WinMain procedure creates a local MSG structure
along the way, you then use EBP for something else - oops !!!!
use EBX, ESI, or EDI, rather than EBP
Thank you very much for the replies jj and dave!
Indeed I have some kind of mistake in the writefile function but I don't realy understand what I am supposed to do to solve it. I am getting the ERROR_INVALID_USER_BUFFER (1784 error). You said I shouldn't use Null for the 4th parameter but I read in the references that
QuotelpNumberOfBytesWritten [out, optional]
A pointer to the variable that receives the number of bytes written when using a synchronous hFile parameter. WriteFile sets this value to zero before doing any work or error checking. Use NULL for this parameter if this is an asynchronous operation to avoid potentially erroneous results.
This parameter can be NULL only when the lpOverlapped parameter is not NULL.
For more information, see the Remarks section.
lpOverlapped [in, out, optional]
A pointer to an OVERLAPPED structure is required if the hFile parameter was opened with FILE_FLAG_OVERLAPPED, otherwise this parameter can be NULL.
For an hFile that supports byte offsets, if you use this parameter you must specify a byte offset at which to start writing to the file or device. This offset is specified by setting the Offset and OffsetHigh members of the OVERLAPPED structure. For an hFile that does not support byte offsets, Offset and OffsetHigh are ignored.
To write to the end of file, specify both the Offset and OffsetHigh members of the OVERLAPPED structure as 0xFFFFFFFF. This is functionally equivalent to previously calling the CreateFile function to open hFile using FILE_APPEND_DATA access.
For more information about different combinations of lpOverlapped and FILE_FLAG_OVERLAPPED, see the Remarks section and the Synchronization and File Position section.
So I am reading that my 5th parameter should be 0 and that the 4th should be 0. But I also read that both can not be 0 at the same time so it is quite contradicting or am I missing something ?
Quote from: QWORDCheck line 42.
:bgrin:
...I always thought Raymond Chen's (http://blogs.msdn.com/b/oldnewthing/) psychic debugging routine was funny, but, DANG,...
Check line 42. This will become my mantra.
just create a DWORD variable and pass the address of it
i don't like to use LOCAL's in WndProc, so i'd put it in the .DATA? section
or, what i often do is create my own temporary local on the stack
xor ecx,ecx
push ecx
mov edx,esp
INVOKE WriteFile,hFile,offset buffer,nNumberOfBytes,edx,ecx
pop ecx ;ECX = number of bytes written
ReadFile is very similar
Thank you very much! I finally got it working as I wanted :)