Had to re-install EasyCode and start an entirely new project. Works fine with the exact same code. Only problem now is EasyCode Help won't display. Get browser message that says Can't display html page. Happens at home office AND on every computer at work.
When I call the function WritePathToFile immediately after calling GetExePath nothing is written to CTXT("paths.txt") and I get a notice that the file does not exist. I do know Mov Esi, Offset openfilebuffer works because if I call a messagebox and pass Esi to the messagbox procedure as lpText param it displays correctly. Any hints?
.Data
openfilebuffer DB 260 Dup (?)
szDefExt DB "EXE", 0
.Code
GetExePath Proc Uses Esi lpTitle:DWord, lpFilter:DWord
Local ofn:OPENFILENAME
Local dwPathStringLength:DWord
Align 4
;================================================
; Get the full path to the exe
;================================================
Mov Eax, Offset openfilebuffer
mov BYTE PTR [eax], 0
; --------------------
; zero fill structure
; --------------------
Invoke RtlZeroMemory, Addr ofn, SizeOf ofn
mov ofn.lStructSize, sizeof OPENFILENAME
m2m ofn.hWndOwner, App.Main
m2m ofn.hInstance, App.Instance
m2m ofn.lpstrFilter, lpFilter
m2m ofn.lpstrFile, Offset openfilebuffer
Mov ofn.nMaxFile, SizeOf openfilebuffer
m2m ofn.lpstrTitle, lpTitle
Mov ofn.Flags, OFN_EXPLORER or OFN_FILEMUSTEXIST or \
OFN_LONGNAMES Or OFN_HIDEREADONLY
Mov ofn.lpstrDefExt, Offset szDefExt
Invoke GetOpenFileName, Addr ofn ;Show the Open File Dialog
.If Eax == 0 ; Quit if the user clicks the cancel button or closes the dialog without a selection.
Invoke GlobalFree, Addr ofn
Return FALSE
.Else
Mov Esi, Offset openfilebuffer
Invoke GlobalFree, Addr ofn
Return TRUE
.EndIf
ret
GetExePath EndP
;This procedure expects path to be in Esi prior to being called
WritePathToFile Proc Uses Esi
Local hOpenFile:DWord
Invoke OpenTextFile, CTXT("paths.txt"), ecWrite, ecOpenExisting
Mov hOpenFile, Eax
Invoke SetFilePointer, hOpenFile, 0, 0, FILE_END
Invoke WriteFile, hOpenFile, Esi, SizeOf openfilebuffer, Ecx, NULL
Invoke CloseHandle, hOpenFile
Ret
WritePathToFile EndP
Okay I have made some changes. In this version of GetExePath I have commented out the call to GetOpenFileName. Having done that I am able to call WritePathToFile and that procedure does write the 4 bytes of test data to a file and shows the full path to the selected exe in openfilebuffer. If I uncomment GetOpenFileName, the data in openfilebuffer remains valid but it is never written to the target text file.
I call GetExePath followed by WritePathToFile.
GetExePath Proc lpTitle:DWord, lpFilter:DWord
; LOCAL ofn:OPENFILENAME
Mov Eax, Offset openfilebuffer
mov BYTE PTR [eax], 0
; --------------------
; zero fill structure
; --------------------
Invoke RtlZeroMemory, Addr ofn, SizeOf ofn
mov ofn.lStructSize, sizeof OPENFILENAME
m2m ofn.hWndOwner, App.Main
m2m ofn.hInstance, App.Instance
m2m ofn.lpstrFilter, lpFilter
m2m ofn.lpstrFile, offset openfilebuffer
mov ofn.nMaxFile, sizeof openfilebuffer
m2m ofn.lpstrTitle, lpTitle
Mov ofn.Flags, OFN_EXPLORER or OFN_FILEMUSTEXIST or \
OFN_LONGNAMES Or OFN_HIDEREADONLY
Mov ofn.lpstrDefExt, Offset szDefExt
;Invoke GetOpenFileName, Addr ofn
ret
GetExePath EndP
WritePathToFile Proc
Local hOpenFile:DWord
Local dwNumberOfBytesWritten:DWord
Mov hOpenFile, FUNC(CreateFile, CTXT("test.txt"), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)
Invoke SetFilePointer, hOpenFile, 0, 0, FILE_END
Invoke WriteFile, hOpenFile, CTXT("Test"), 4, Addr dwNumberOfBytesWritten, NULL ;Write 4 bytes of test data
Invoke CloseHandle, hOpenFile
Invoke MessageBox, NULL, Addr openfilebuffer, CTXT("The Path"), MB_OK ;Just another check to see if ofn.lpstrFile data is actually available
Ret
WritePathToFile EndP
Invoke WriteFile, hOpenFile, Esi, SizeOf openfilebuffer, Ecx, NULL
ecx ?????
ecx is trashed
and - it is supposed to be a pointer to a dword that receives the number of bytes written
that probably isn't the only problem
why pass the value in ESI ?
why not pass it as a parm ?
this isn't the way i would write this - lol
but, then, noone seems to like it when i do things my way
WritePathToFile PROTO :DWORD
;
Invoke WritePathToFile,offset PathName ;or addr if local
;
WritePathToFile Proc lpPath:DWORD
Local hOpenFile:DWord
Local dwNumberOfBytesWritten:DWord
Invoke OpenTextFile, CTXT("paths.txt"), ecWrite, ecOpenExisting
Mov hOpenFile, Eax
Invoke SetFilePointer, eax, 0, 0, FILE_END
Invoke WriteFile, hOpenFile, lpPath, SizeOf openfilebuffer, Addr dwNumberOfBytesWritten, NULL
Invoke CloseHandle, hOpenFile
mov ecx, dwNumberOfBytesWritten
Ret
WritePathToFile EndP
also, if you want to align a proc...
Align 16
GetExePath Proc Uses Esi lpTitle:DWord, lpFilter:DWord
Local ofn:OPENFILENAME
Local dwPathStringLength:DWord
we usually use align 16 for procs - align 4 for dwords
Short and elegant - returns bytes written in a register:
Quote push edx
mov edx, esp ; shorter because it avoids a global variable
invoke WriteFile, wHandle, edi, eax, edx, 0
pop edx ; contains bytes written
yah - that's what i meant by "this isn't the way i would write it"
>I get a notice that the file does not exist
Does it exist prior to you trying to opening it? I notice you use ecOpenExisting which should fail if it doesn't exist.
> Invoke GlobalFree, Addr ofn
No need to free a local var.
Quote from: devilhorse on December 21, 2010, 12:42:41 AM
;This procedure expects path to be in Esi prior to being called
WritePathToFile Proc Uses Esi
In your first GetExePath version
GetExePath Proc Uses Esi lpTitle:DWord, lpFilter:DWord
..
push esi ; USES preserves esi
..
mov esi, Offset openfilebuffer ; you make futile assignment
..
pop esi ; USES restores esi
GetExePath EndP
i think a basic concept is also missing, here
in win32, we don't normally pass variables to a routine in register
at least, not a function that you want to be "re-usable" in other programs
for win 32 API callback functions...
EBX, EBP, ESI, EDI are preserved and the DF is left cleared
EAX, ECX, EDX are open game - these registers are usually used to return results like status, length, address, etc
we try to write functions using the same conventions
that way, they may be used inside procedures that might be used for callback