I have a crazy problem with GetOpenFileName. It terminates my program.

If the desired file happens to be in the default directory, everything works OK. But in the moment i click the upper left combo box to change the directory, the whole program crashes. There's no system error message whatsoever, the process just vanishes.

I have in the same program 2 other GetOpenFileName dialogs, they work just fine. Below is the code with the problem:



.data
DWGofn OPENFILENAME <>
DWGFilterString db "DWG Files",0,"*.dwg",0
db "All Files",0,"*.*",0,0
DWGbuffer db 260 dup (0)

.code
mov DWGofn.lStructSize,SIZEOF DWGofn
mov DWGofn.hWndOwner,NULL
push hInstance
pop DWGofn.hInstance
mov DWGofn.lpstrFilter, OFFSET DWGFilterString
mov DWGofn.lpstrFile, OFFSET DWGbuffer
mov DWGofn.nMaxFile,260
mov DWGofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
[color=red]invoke GetOpenFileName, ADDR DWGofn[/color]


What could cause this?
Posted on 2003-10-24 11:40:16 by Janne
That's strange

it does work well the error maybe some place else so it would be better if you could paste more detailed code.

additionally, do try copying and pasting code blocks from the sections that work.

Regards,
Art
Posted on 2003-10-24 12:07:59 by art_sands
This is the context of the problem code:



ZoomSingleObj proc uses ebx esi edi pObjToZoom:dword
;pObjToZoom is an address BSOBJ.
;1. get it's floor ID
;2. find that ID from Floor array
;3. switch to autocad drawing of the found floor
;4. zoom to coordinates of pObjToZoom
LOCAL LowLeftVar:VARIANT
LOCAL UpRightVar:VARIANT
LOCAL LowLeftArr:SAFEARRAY
LOCAL UpRightArr:SAFEARRAY
LOCAL LowLeftPnt:F3DPOINT
LOCAL UpRightPnt:F3DPOINT

LOCAL openvar:VARIANT
LOCAL acHWND:DWORD

.if pIAcadDocuments==0
invoke InitAcad
.endif

mov edi,pObjToZoom
mov eax,pFloors
mov ebx,[eax].Floor.Floor_ID
mov esi,1

.while (ebx!=[edi].BSOBJ.Floor_ID)
inc esi
.if esi>FloorAmount
MsgBox NULL,"Objects floor ID not in floor list","ERROR",MB_OK or MB_ICONSTOP
mov eax,-1
ret
.endif
add eax,FloorSize
mov ebx,[eax].Floor.Floor_ID
.endw
;when here, the ID was found in Floor array

mov esi,eax

.if [esi].Floor.pDwgDoc==UnusedSlot
;fill the variant structure needed for file open method
invoke VariantInit,addr openvar
mov openvar.vt,VT_BOOL
mov openvar.wReserved1,0
mov openvar.wReserved2,0
mov openvar.wReserved3,0
mov openvar.boolVal,VBTRUE;OPEN READ-ONLY
;;;;;;;;;

lea ecx,[esi].Floor.DwgName
Open:
invoke MultiByteToWideChar,CP_ACP,MB_PRECOMPOSED,ecx,-1,addr Wbuffer,SIZEOF Wbuffer
.if eax==0
MsgBox NULL,"MultiByteToWideChar of DWG file name failed","ERROR",MB_OK or MB_ICONSTOP
mov eax,-1
ret
.endif
invoke SysAllocString, addr Wbuffer
mov ebx,eax
lea ecx,[esi].Floor.pDwgDoc
invoke vf(pIAcadDocuments,IAcadDocuments,Open),ebx,openvar,ecx
.IF eax!=S_OK
lea ecx,[esi].Floor.DwgName
invoke MessageBox,NULL,CStr("File not found, specify the location manually?"),ecx,\
MB_YESNO or MB_ICONQUESTION or MB_TASKMODAL
.if eax==IDNO
ret
.endif

;fill the DWG OPENFILENAME struct
mov DWGofn.lStructSize,SIZEOF DWGofn
mov DWGofn.hWndOwner,NULL
push hInstance
pop DWGofn.hInstance
mov DWGofn.lpstrFilter, OFFSET DWGFilterString
mov DWGofn.lpstrFile, OFFSET DWGbuffer
mov DWGofn.nMaxFile,260
mov DWGofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
[color=red] invoke GetOpenFileName, ADDR DWGofn[/color]
.if eax==0
mov eax,-1
ret
.endif
mov ecx,DWGofn.lpstrFile
jmp Open
.endif

.endif



;fill the safearray structures
mov LowLeftArr.cDims,1
mov LowLeftArr.fFeatures,1
mov LowLeftArr.cbElements,8
mov LowLeftArr.cLocks,0
lea eax,LowLeftPnt
mov LowLeftArr.pvData,eax
mov LowLeftArr.rgsabound.lLbound,0
mov LowLeftArr.rgsabound.cElements,3

mov UpRightArr.cDims,1
mov UpRightArr.fFeatures,1
mov UpRightArr.cbElements,8
mov UpRightArr.cLocks,0
lea eax,UpRightPnt
mov UpRightArr.pvData,eax
mov UpRightArr.rgsabound.lLbound,0
mov UpRightArr.rgsabound.cElements,3

;fill the variant structures
mov LowLeftVar.vt,VT_R8 or VT_ARRAY
mov LowLeftVar.wReserved1,0
mov LowLeftVar.wReserved2,0
mov LowLeftVar.wReserved3,0
lea eax,LowLeftArr
mov LowLeftVar.parray,eax

mov UpRightVar.vt,VT_R8 or VT_ARRAY
mov UpRightVar.wReserved1,0
mov UpRightVar.wReserved2,0
mov UpRightVar.wReserved3,0
lea eax,UpRightArr
mov UpRightVar.parray,eax

finit
;set the X coord for both points
fld [edi].BSOBJ.AbsPos.X
fsub AcZoomXsize
fst LowLeftPnt.X
fadd AcZoomXsize
fadd AcZoomXsize
fstp UpRightPnt.X

;set the Y coord for both points
fld [edi].BSOBJ.AbsPos.Y
fsub AcZoomYsize
fst LowLeftPnt.Y
fadd AcZoomYsize
fadd AcZoomYsize
fstp UpRightPnt.Y

;set the Z coord for both points
fldz
fst LowLeftPnt.Z
fstp UpRightPnt.Z


invoke vf(pIAcadApplication,IAcadApplication,put_ActiveDocument),[esi].Floor.pDwgDoc
invoke vf([esi].Floor.pDwgDoc,IAcadDocument,put_ActiveSpace),acModelSpace
invoke vf(pIAcadApplication,IAcadApplication,put_WindowState),acMax
invoke vf([esi].Floor.pDwgDoc,IAcadDocument,put_WindowState),acMax
invoke vf(pIAcadApplication,IAcadApplication,ZoomWindow),LowLeftVar,UpRightVar
invoke vf(pIAcadApplication,IAcadApplication,Update)
invoke vf([esi].Floor.pDwgDoc,IAcadDocument,get_HWND),addr acHWND
INVOKE SetForegroundWindow,acHWND
ret
ZoomSingleObj endp


Above is called by a double click in a listview



.elseif [edi].NMHDR.code==NM_DBLCLK
.if errorcount > 0
invoke GetCurrentFocusLparam,hList
mov ecx,sizeof BSOBJ
mul ecx
add eax,pBSbase
invoke ZoomSingleObj,eax
.endif
Posted on 2003-10-24 15:39:26 by Janne
I suspect this is the problem:

invoke MultiByteToWideChar,CP_ACP,MB_PRECOMPOSED,ecx,-1,addr Wbuffer,SIZEOF Wbuffer

The last parameter is the character count, so it should be (SIZEOF Wbuffer)/2. Then you won't overrun the buffer.
Posted on 2003-10-24 20:19:49 by tenkey
If the crash happens when calling GetOpenFileName, the problem could also be in the DWGofn structure. Could you post it's contents? (I'm assuming it's in the .data or .data? section. Otherwise you should initialize all of it's members, because the initial value of local variables is undefined).
Posted on 2003-10-24 21:09:33 by QvasiModo
try to fill other members of OPENFILENAME.
Posted on 2003-10-24 21:47:40 by cakmak
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/CommonDialogBoxLibrary/UsingCommonDialogBoxes.asp

Look almost halfway down the page for opening a file and click 'Show Example' to expand it. It's in C/C++ but hopefully you can work it out.
Posted on 2003-10-24 22:13:46 by drarem
Tried filling all the OPENFILENAME members



mov DWGofn.lStructSize,SIZEOF DWGofn
mov DWGofn.hWndOwner,NULL
push hInstance
pop DWGofn.hInstance
mov DWGofn.lpstrFilter, OFFSET DWGFilterString
mov DWGofn.lpstrCustomFilter,0
mov DWGofn.nMaxCustFilter,0
mov DWGofn.nFilterIndex,0
mov DWGofn.lpstrFile, OFFSET DWGbuffer
mov DWGofn.nMaxFile,260
mov DWGofn.lpstrFileTitle,0
mov DWGofn.nMaxFileTitle,0
mov DWGofn.lpstrInitialDir,0
mov DWGofn.lpstrTitle,0
mov DWGofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES ;or\
OFN_EXPLORER or OFN_HIDEREADONLY
mov DWGofn.nFileOffset,0
mov DWGofn.nFileExtension,0
mov DWGofn.lpstrDefExt,0
mov DWGofn.lCustData,0
mov DWGofn.lpfnHook,0
mov DWGofn.lpTemplateName,0


Did not help.

I must have a big bug somewhere else in the program, i just wonder why the crash happens inside the GetOpenFileName call.
Posted on 2003-10-25 00:14:33 by Janne
Hi Janne,

just a guess: if youre using winnt/2k/xp it could be an alignment problem. change code



.data
align 4
DWGofn OPENFILENAME <>
align 4
DWGFilterString db "DWG Files",0,"*.dwg",0
db "All Files",0,"*.*",0,0
align 4
DWGbuffer db 260 dup (0)


Japheth
Posted on 2003-10-25 01:40:47 by japheth
Try


invoke RtlZeroMemory, addr DWGofn, sizeof DWGofn

I had a similar problem in Xp, but, with this instruction, the problem is solved
Posted on 2003-10-25 04:09:49 by greenant
Are you sure it is happening in there? You can trace the bug down hardcore style, something like:

DTEXT MACRO TEXT1
szText title1,"title"
invoke MessageBox,NULL,ADDR TEXT1,ADDR title1,MB_OK
ENDM

and do:
szText test,"test"
DTEXT test

before and after every call and trace it through.. I question this though:

mov ecx,DWGofn.lpstrFile (after you have retrieved the filename).. it looks suspicious

and FILEMUSTEXIST?? PATHMUSTEXIST? Are those flags necessary?

Hope that helps..
Posted on 2003-10-25 04:10:18 by drarem
This code was not tested, but it should work (sorry for the lack of formatting, but IE's text editing is terrible):


.data?
align DWORD
DWGbuffer db MAX_PATH dup (?)

.data
align DWORD
DWGofn OPENFILENAME <sizeof OPENFILENAME,,,offset DWGFilterString,,,,offset DWGbuffer,sizeof DWGbuffer,,,,offset DWGtitle,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_HIDEREADONLY>
DWGFilterString db "DWG Files",0,"*.dwg",0
db "All Files",0,"*.*",0,0
align DWORD
DWGTitle db "Open DWG file...",0

.code
GetDWGFileName proc hWin

push hWin
pop DWGofn.hwndOwner
invoke GetOpenFileName,offset DWGofn
ret ;returns TRUE if successful, FALSE on error

GetDWGFileName endp

Tell me how it did. :)
Posted on 2003-10-25 10:55:29 by QvasiModo
Thanks for all the ideas.

Fixed


invoke MultiByteToWideChar,CP_ACP,MB_PRECOMPOSED,ecx,-1,addr Wbuffer,SIZEOF Wbuffer

to


invoke MultiByteToWideChar,CP_ACP,MB_PRECOMPOSED,ecx,-1,addr Wbuffer,(SIZEOF Wbuffer)/2

That did'nt solve the GetOpenFileName problem, though.


I'm running the program on Win98, but tested anyway


align 4
DWGofn OPENFILENAME <>
align 4
DWGFilterString db "DWG Files",0,"*.dwg",0
db "All Files",0,"*.*",0,0
align 4
DWGbuffer db 260 dup (0)

That did'nt have any effect.


Tested adding before the OPENFILENAME filling code


invoke RtlZeroMemory, addr DWGofn, sizeof DWGofn

but no effect.
And actually, looking with a debugger, it can be seen that the structure is initially all zeros anyway.

I am pretty sure that the crash happens inside the GetOpenFileName because
- the error always occures when clicking the upper left combobox. If a file is selected without using the combo, everything works.
- i used vkim's debug macros


PrintText "About to GetOpenFileName"
invoke GetOpenFileName, ADDR DWGofn
PrintHex eax,"GetOpenFileName ret value"

The first string is displayed in debug window, the second one not.
- i made a Softice breakpoint to the instruction after the GetOpenFileName call, but it won't break.

Soon after the program has crashed in the GetOpenFileName, few other programs usually crash too, like Explorer and Radasm. So i must have an ugly bug somewhere.

I wonder, what actually happens on a click of the GetOpenFileName combobox. Messages are naturally sent, but which messages and to who?
Posted on 2003-10-25 14:38:54 by Janne
What is the value in hinstance?
Posted on 2003-10-25 14:46:36 by roticv
Hi roticv,
hinstance=400000h
Posted on 2003-10-25 15:47:13 by Janne
This leads me to the final conclusion which is that your flag values are wrong. For me I use the following code:


ofn OPENFILENAME <sizeof OPENFILENAME,0,40000h,OFFSET FileFilter,0,0,0,OFFSET FileName,\
256,0,0,0,0,\
OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY,\
0,0,0,0,0,0>
Posted on 2003-10-25 23:47:49 by roticv
Can you post a log of your crashed program? You can use Dr Watson
Posted on 2003-10-26 02:03:24 by greenant
greenant,
thanks for mentioning Dr Watson, did'nt even know that such thing exists.

However, the problem is that Dr Watson does not craete any log regarding this problem. There's no any system error message either, the process just disappears.
Posted on 2003-10-26 06:01:54 by Janne
Just tested on a different machine, using Win2000, program runs just fine without the above error.
Posted on 2003-10-28 00:58:03 by Janne

greenant,
thanks for mentioning Dr Watson, did'nt even know that such thing exists.

However, the problem is that Dr Watson does not craete any log regarding this problem. There's no any system error message either, the process just disappears.

As I recall there are two kind of errors that can cause that. One is a stack overflow, and the other is failure to preserve registers (esi, edi, ebx, ebp). But in the second case it should work under Win9x and fail under NT (not the other way around). And stack overflows cause the program to crash always. So I'm puzzled about this one. :confused:
Perhaps you could try OllyDbg to see exactly where does the crash happen inside comdlg32.dll.
Posted on 2003-10-28 17:21:33 by QvasiModo