Solved Problem using OpenTextFile after calling getOpenFileName

Started by devilhorse, December 21, 2010, 12:42:41 AM

Previous topic - Next topic

devilhorse

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

dedndave

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 ?

dedndave

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

jj2007

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

dedndave

yah - that's what i meant by "this isn't the way i would write it"

sinsi

>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.
Light travels faster than sound, that's why some people seem bright until you hear them.

ramguru

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

dedndave

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