I am trying to do something that crashes my program. There is no output or other apparent response (no "this program has performed an illegal operation...") and the exe file then cannot be opened or deleted.
Following Iczelion's tutorial 4, I declare in winmain
LOCAL wc:WNDCLASSEX
and initialize it ala Iczelion, starting with
mov wc.cbSize,SIZEOF WNDCLASSEX
That works fine.
But now when I declare a global structure outside winmain and initialize it with the same values, I get the odd sort of crash described above.
My question: is the whole idea of using a global structure wrong, or should I keep trying to find some mistake I'm making?
This is my structure (in .DATA)
LFwc LABEL DWORD ;LFile Window Class structure
DD SIZEOF WNDCLASSEX ; 0 wc.cbSize
DD CS_HREDRAW or CS_VREDRAW ; 4 wc.style
DD OF WndProc ; 8 wc.lpfnWndProc
DD 0 ;0C wc.cbClsExtra
DD 0 ;10 wc.cbWndExtra
hinst DD ? ;14 wc.hinst
hbkbr DD ? ;18 CreateSolidBrush,0FF0000h
DD 0 ;1C wc.lpszMenuName
DD OF ClassName ;20 wc.lpszClassName
hicon DD ? ;24 LoadIcon,0,IDI_APPLICATION
hiconsm DD ? ;28 wc.hIconSm
hcurs DD ? ;2C LoadCursor,NULL,IDC_ARROW
;30 end LFwc
I initialize the "?"s at the start of .CODE and none of the invokes used here generates an assembler error or returns 0.
I forgot to mention that "OF" = "OFFSET' via an equate.
There's nothing particularly wrong with having a 'global' structure - it's only done local for the convenience and that it's only used on initialisation.
If that really is the only change then it indicates some other problem with your code, which happens to not show when done as local.
Whatever it is, you'll have to give us the full code so we can test what you actually have (not what we guess you should have :wink)
Here is the whole program. I apologize for its length and for the ideosyncratic stye. And for not being able, for now, to get the tabs to line up right in the post.
The critical change is marked by "***"
;Base
.NOCREF
.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
.NOLIST
include h:\masm32\include\windows.inc
include h:\masm32\include\user32.inc
include h:\masm32\include\kernel32.inc
include h:\masm32\include\gdi32.inc
includelib h:\masm32\lib\user32.lib
includelib h:\masm32\lib\kernel32.lib
includelib h:\masm32\lib\gdi32.lib
.RADIX 16
include g:\orig\prog\lf\leqm.asm
.RADIX 10
.LISTALL
crlf EQU 0A0Dh
tab EQU 9
.DATA
ClassName DB "RICHEDIT_CLASS"
AppName DB "lfw 0.3 7428",0
test$ DB "LFile v. 0.3 7423 (c)RA Leeper - working on drawtext."
DB " Next is test crlf"
DW 0A0Dh
DW 0A0Dh
db "Did it work?",0
DW 0A0Dh
db tab,"Yes!"
DW 0A0Dh
db "Now test long line"
DW 0A0Dh
DB "Now - 7428 - converting to RAL style - The 1st step is doing away w/ the local wc structure. It will be global and in .DATA.",10,13
DW 0A0Dh
DB "0123456789abcdef 123456789abcdef 123456789abcdef 123456789abcdef "
DW 0A0Dh
DB "Next, we'll try to get an 'edit control' working, so we can have rich text.",10,13
DW 0A0Dh
DB "Rich edit test{\rtf1\ansi{\fonttbl\f0\fswiss Helvetica;}\f0\pard"
DW 0A0Dh
DB "This is some {\b bold} text.\par}"
DW 0A0Dh
DW 0A0Dh
DB "Well, the last version does nothing. 7428 - Trying to find what's wrong."
DW 0A0Dh
DW 0A0Dh
DB "There are no assr errors, so try erbeep"
DW 0A0Dh
DW 0A0Dh
DB "last line 5.43"
DB 13,10,10
DB "OK I've done a bunch of cosmetic stuff w/ no problems. Next a few things that should not matter - shorten some variable names - ALIGN 8 - NO GOOD - but just ALIGN is OK"
DW crlf,crlf
DB "Now - replace local wc w/ global LFwc. This is gonna crash it",13,10,10
DB "7428b",tab,"last line 7.15",13,10,10
DB "7429",tab,"last line 6.16a",13,10,10
DB "7430",tab,"last line 5.58a",13,10,10
tslen EQU $-test$
FontName db "TimesNewRoman",0
;FontName db "Courier New",0
;FontName db "Arial",0
;FontName db "Verdana",0
ALIGN
txtclr EQU 0FFFFFFh
LFwc LABEL DWORD ;LFile Window Class structure
DD SIZEOF WNDCLASSEX ; 0 wc.cbSize
DD CS_HREDRAW or CS_VREDRAW ; 4 wc.style
DD OF WndProc ; 8 wc.lpfnWndProc
DD 0 ;0C wc.cbClsExtra
DD 0 ;10 wc.cbWndExtra
hinst DD ? ;14 wc.hinst
hbkbr DD ? ;18 CreateSolidBrush,0FF0000h
DD 0 ;1C wc.lpszMenuName
DD OF ClassName ;20 wc.lpszClassName
hicon DD ? ;24 LoadIcon,0,IDI_APPLICATION
hiconsm DD ? ;28 wc.hIconSm
hcurs DD ? ;2C LoadCursor,NULL,IDC_ARROW
;30 end LFwc
;wc WNDCLASSEX
.DATA?
hin@ HINSTANCE ?
cmdl LPSTR ?
.CODE
; start: Initialize lfwc
start:
invoke CreateSolidBrush,0FF0000h
mov [hbkbr], eax
invoke LoadIcon,0,IDI_APPLICATION
mov [hicon], eax
mov [hiconsm], eax
invoke LoadCursor,0,IDC_ARROW
mov [hcurs], eax
; [hin@] !GetModuleHandle [cmdl] !GetCommandLine
invoke GetModuleHandle, 0
mov [hin@], eax
invoke GetCommandLine
or eax, eax
CALLZ erbeep
mov [cmdl], eax
; !WinMain {...} !ExitProcess,eax
invoke WinMain, hin@, 0, cmdl, SW_SHOWDEFAULT
invoke ExitProcess,eax
; winmain !RegisterClassEx !CreateWindowEx
WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
LOCAL msg:MSG
LOCAL hwnd:HWND
LOCAL wc:WNDCLASSEX
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
mov eax, [hInst]
mov [wc.hInstance], eax
invoke CreateSolidBrush,0FF0000h
mov wc.hbrBackground,eax
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
;invoke RegisterClassEx, addr wc ***
invoke RegisterClassEx, OF LFwc; ***
mov edx, CW_USEDEFAULT
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,edx,edx,edx,edx,0,0,hInst,0
; [hwnd] eax !ShowWindow !UpdateWindow
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWMAXIMIZED
invoke UpdateWindow, hwnd
; msglp: !GetMessage; eax=0 => _ex eax=-1 => _err ; !TranslateMessage !DispatchMessage ; ex:/err: eax msg.wParam ret
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax, msg.wParam
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT
LOCAL rect:RECT
LOCAL hbrsh:DWORD
LOCAL hfont:HFONT
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_PAINT
call dspl
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
;; DSPL main DiSPLay
dspl:
tfmt EQU DT_EXPANDTABS or DT_LEFT or DT_NOCLIP or DT_TOP or DT_WORDBREAK
invoke BeginPaint,hWnd, ADDR ps; fills (ps) w/ defaults
mov hdc,eax
; font, color of text, bkgr
invoke CreateFont,24,16,0,0,400,0,0,0,OEM_CHARSET,\
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\
DEFAULT_QUALITY,DEFAULT_PITCH or FF_ROMAN,\
ADDR FontName
invoke SelectObject, hdc, eax
mov hfont,eax
invoke SetTextColor,hdc,0FFFFFFh
invoke SetBkColor,hdc,0FF0000h
invoke GetClientRect,hWnd, ADDR rect
invoke DrawText, hdc,ADDR test$,tslen, ADDR rect, tfmt
invoke EndPaint,hWnd, ADDR ps
ret
WndProc endp
;; ERBEEP ERror BEEP
; erbeep: push eax eax 200 push eax
erbeep:
push eax
mov eax,200
push eax
; shl eax, 4 push eax call Beep
shl eax, 4
push eax
call Beep
; pop eax ret
pop eax
ret
end start
I just added the code tags for you so it can be read properly. hutch--
raleeper,
Below is a normal WNDCLASSEX structure definition, it is from WINDOWS.INC.
WNDCLASSEX STRUCT
cbSize DWORD ?
style DWORD ?
lpfnWndProc DWORD ?
cbClsExtra DWORD ?
cbWndExtra DWORD ?
hInstance DWORD ?
hIcon DWORD ?
hCursor DWORD ?
hbrBackground DWORD ?
lpszMenuName DWORD ?
lpszClassName DWORD ?
hIconSm DWORD ?
WNDCLASSEX ENDS
You can if you wish initialise the structure globally in the .DATA section with something like,
.DATA
wcex WNDCLASSEX <0,0,0,0,0,0,0,0,0,0,0,0>
You can initialise as many as you like with preset values but remember that this is assembly time initialisation, some WNDCLASSEX values can only be set at runtime so you will still have to copy data into at least some of the structure members.
This will be things like instance, cursor and icon handles which are not known at assembly time. (400000h instance handle excepted).
Okay, very silly problem caused by defining your wndclassex structure wrongly (I didn't look that closely before.)
You've got 'hIcon' and 'hCursor' in the wrong place, which puts everything after hInstance at the wrong offset.
should be..
LFwc LABEL DWORD ;LFile Window Class structure
DD SIZEOF WNDCLASSEX ;cbSize
DD CS_HREDRAW or CS_VREDRAW ;style
DD OF WndProc ;lpfnWndProc
DD 0 ;cbClsExtra
DD 0 ;cbWndExtra
hinst DD ? ;hinst
hicon DD ? ;hIcon = LoadIcon,0,IDI_APPLICATION ; !!!!!
hcurs DD ? ;hCursor = LoadCursor,NULL,IDC_ARROW ; !!!!!
hbkbr DD ? ;hbrBackground = CreateSolidBrush,0FF0000h
DD 0 ;lpszMenuName
DD OF ClassName ;lpszClassName
hiconsm DD ? ;hIconSm
;30 end LFwc
;wc WNDCLASSEX
(This will at least fix one problem, I'm not saying there aren't more :bdg)
Quote from: Tedd on May 01, 2007, 01:45:47 PM
Okay, very silly problem caused by defining your wndclassex structure wrongly (I didn't look that closely before.)
You've got 'hIcon' and 'hCursor' in the wrong place, which puts everything after hInstance at the wrong offset.
should be..[...]
Yes. Thanks Ted and Hutch. I just took the structure members in the order Iczelion's tutorial initialized them without checking against the definition javascript:void(0);
redface. Works fine now.
just looking shouldnt
ClassName DB "RICHEDIT_CLASS"
be
ClassName DB "RICHEDIT_CLASS",0
Nope,
The two direct strings you can use are,
"RichEdit" for richedit 1
or
"RichEdit20a" for richedit 2 and later.
C tends to use the equate that you have in quotes in your posting.
i meant the ",0" at the end. I wasnt sure if RICHEDIT_CLASS would work or not so i didnt want to change that. I use RichEditClass db "RichEdit20A",0
from PSDK
#define RICHEDIT_CLASSA "RichEdit20A"
Yes, strings should be null-terminated (C/C++ do it automagically when you enclose it in quotes.)
The code isn't actually using a rich-edit control, it's just the class name that's being taken for the main window - which, due to the lack of terminating null, really turns out to be "RICHEDIT_CLASSlfw 0.3 7428",0
For creating a rich-edit control, you can use the RICHEDIT_CLASS atom value, it's not a string.
thanks tedd thats exactly what i thought