News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

how to compile resources

Started by vogelsang, November 27, 2013, 03:43:41 AM

Previous topic - Next topic

vogelsang

Hi,
I'm trying to make an app with menu and events service. I made RC file based on win32 sample but it doesn't work fully with my source. RC compiles and is linked to OBJ but window appears without menu. Below are sources:


;--------MAKE-------------------------------------------------------------
;rc menu_app.rc
;
;jwasm -win64 menu_app.asm
;
;link /SUBSYSTEM:WINDOWS menu_app.obj menu_app.res
;
;--------INCLUDES---------------------------------------------------------

includelib      /JWASM/wininc208/lib64/kernel32.lib
includelib      /JWASM/wininc208/lib64/user32.lib
includelib      /JWASM/wininc208/lib64/gdi32.lib

option casemap:none

;--------PROTOS-----------------------------------------------------------


HINSTANCE typedef QWORD
HWND      typedef QWORD
HMENU    typedef QWORD
HICON      typedef QWORD
HBRUSH    typedef QWORD
HCURSOR    typedef QWORD
WPARAM    typedef QWORD
LPARAM    typedef QWORD
LPSTR      typedef QWORD
LPVOID    typedef QWORD
UINT      typedef DWORD

NULL            equ 0
WS_OVERLAPPEDWINDOW equ 0CF0000h
CW_USEDEFAULT  equ 80000000h
SW_SHOWDEFAULT equ 10
SW_SHOWNORMAL  equ 1
IDC_ARROW      equ 32512
IDI_APPLICATION equ 32512
WM_DESTROY      equ 2
CS_VREDRAW      equ 1
CS_HREDRAW      equ 2
COLOR_WINDOW    equ 5
WM_COMMAND              equ 111h

IDM_TEST    EQU 1
IDM_HELLO   EQU 2
IDM_GOODBYE EQU 3
IDM_EXIT    EQU 4

proto_WNDPROC typedef proto :HWND,:UINT,:WPARAM,:LPARAM
WNDPROC typedef ptr proto_WNDPROC

WNDCLASSEXA struct 8
cbSize          DWORD   ?
style           DWORD   ?
lpfnWndProc     WNDPROC ?
cbClsExtra      DWORD   ?
cbWndExtra      DWORD   ?
hInstance       HINSTANCE ?
hIcon           HICON   ?
hCursor         HCURSOR ?
hbrBackground   HBRUSH  ?
lpszMenuName    LPSTR   ?
lpszClassName   LPSTR   ?
hIconSm         HICON   ?
WNDCLASSEXA ends

POINT   struct
x   SDWORD  ?
y   SDWORD  ?
POINT   ends

MSG struct 8
hwnd    HWND    ?
message DWORD   ?
wParam  WPARAM  ?
lParam  LPARAM  ?
time    DWORD   ?
pt      POINT   <>
MSG ends

GetModuleHandleA proto :LPSTR
GetCommandLineA  proto
ExitProcess      proto :UINT
LoadIconA        proto :HINSTANCE, :LPSTR
LoadCursorA      proto :HINSTANCE, :LPSTR
RegisterClassExA proto :ptr WNDCLASSEXA
CreateWindowExA  proto :DWORD, :LPSTR, :LPSTR, :DWORD, :SDWORD, :SDWORD, :SDWORD, :SDWORD, :HWND, :HMENU, :HINSTANCE, :LPVOID
ShowWindow       proto :HWND, :SDWORD
UpdateWindow     proto :HWND
GetMessageA      proto :ptr MSG, :HWND, :SDWORD, :SDWORD
TranslateMessage proto :ptr MSG
DispatchMessageA proto :ptr MSG
PostQuitMessage  proto :SDWORD
DefWindowProcA   proto :HWND, :UINT, :WPARAM, :LPARAM

EXTERN LoadMenuA :PROC
EXTERN MessageBoxA :PROC

;WinMain proto :HINSTANCE, :HINSTANCE, :LPSTR, :UINT

.data

ClassName db "SimpleWinClass",0
AppName  db "Our First Window",0
MenuName db "FirstMenu",0

Text db "Message test",0
Testing db "test",0
Hello db "Hello!",0
MenuFailed db "LOAD MENU FAILED!",0
.data?

hInstance HINSTANCE ?
CommandLine LPSTR ?
hMenu dq ?

.code

WinMainCRTStartup proc FRAME
push rbp
.pushreg rbp
mov rbp,rsp
.setframe rbp, 0
.endprolog

sub rsp,32
mov ecx,NULL
call GetModuleHandleA
mov hInstance, rax
call GetCommandLineA
mov CommandLine, rax
mov rcx, hInstance
mov rdx, NULL
mov r8, CommandLine
mov r9d, SW_SHOWDEFAULT
call WinMain
mov ecx, eax
call ExitProcess
align 4
WinMainCRTStartup endp

WinMain proc FRAME

push rbp
.pushreg rbp
mov rbp,rsp
.setframe rbp, 0
sub rsp, sizeof WNDCLASSEXA + sizeof MSG + sizeof HWND + 13*8  ;make sure rsp is 16-byte aligned
.allocstack sizeof WNDCLASSEXA + sizeof MSG + sizeof HWND + 13*8
.endprolog

hInst     equ <[rbp+10h]>
hPrevInst equ <[rbp+18h]>
CmdLine   equ <[rbp+20h]>
CmdShow   equ <[rbp+28h]>

wc   equ <[rbp - sizeof WNDCLASSEXA].WNDCLASSEXA>
msg  equ <[rbp - sizeof WNDCLASSEXA - sizeof MSG].MSG>
hwnd equ <[rbp - sizeof WNDCLASSEXA - sizeof MSG - sizeof HWND]>

mov hInst, rcx  ;store param1 in shadow space

mov wc.cbSize, SIZEOF WNDCLASSEXA
mov wc.style, CS_HREDRAW or CS_VREDRAW
;mov   rax, OFFSET WndProc  ;using LEA is preferable
lea rax, [WndProc]
mov wc.lpfnWndProc, rax
mov wc.cbClsExtra, 0
mov wc.cbWndExtra, 0
mov wc.hInstance, rcx
mov wc.hbrBackground, COLOR_WINDOW+1
mov wc.lpszMenuName, NULL
;mov   rax, OFFSET ClassName  ;using LEA is preferable
lea rax, [ClassName]
mov wc.lpszClassName, rax
mov ecx, NULL
mov edx, IDI_APPLICATION
call LoadIconA
mov wc.hIcon, rax
mov wc.hIconSm, rax
mov ecx, NULL
mov edx, IDC_ARROW
call LoadCursorA
mov wc.hCursor,rax
lea rcx, wc
call RegisterClassExA

lea rdx, [MenuName]
mov rcx, hInst
call LoadMenuA
mov hMenu, rax


mov ecx, NULL
lea rdx, [ClassName]
lea r8, [AppName]
mov r9d, WS_OVERLAPPEDWINDOW
mov dword ptr [rsp+4*8], CW_USEDEFAULT
mov dword ptr [rsp+5*8], CW_USEDEFAULT
mov dword ptr [rsp+6*8], CW_USEDEFAULT
mov dword ptr [rsp+7*8], CW_USEDEFAULT
mov qword ptr [rsp+8*8], NULL
mov qword ptr [rsp+9*8], NULL
mov rax, hInst
mov [rsp+10*8], rax
mov qword ptr [rsp+11*8], NULL
call CreateWindowExA
mov hwnd,rax
mov rcx, hwnd
mov edx, SW_SHOWNORMAL
call ShowWindow
mov rcx, hwnd
call UpdateWindow
;--- message loop
@@:
lea rcx, msg
        mov rdx, NULL
        mov r8, 0
        mov r9, 0
        call GetMessageA
        and rax, rax
        jz @F
        lea rcx, msg
        call TranslateMessage
        lea rcx, msg
        call DispatchMessageA
jmp @B
@@:
mov rax, msg.wParam
add rsp, sizeof WNDCLASSEXA + sizeof MSG + sizeof HWND + 13*8
pop rbp
ret
align 4
WinMain endp

WndProc proc FRAME

sub rsp, 5*8
.allocstack 5*8
.endprolog

hWnd    equ <[rbp+10h]>
uMsg equ <[rbp+18h]>
wParam  equ <[rbp+20h]>
lParam  equ <[rbp+28h]>

cmp edx, WM_DESTROY
jne msg_command

mov ecx, NULL
call PostQuitMessage
xor rax,rax
jmp exit
msg_command:
cmp edx, WM_COMMAND
jne no_wm

cmp qword ptr [wParam], IDM_TEST
jne @F

xor r9d, r9d        ; 4. argument: r9d = uType = 0
lea r8, [Testing]   ; 3. argument: r8  = caption
lea rdx, [Text]     ; 2. argument: edx = window text
xor rcx, rcx        ; 1. argument: rcx = hWnd = NULL
call MessageBoxA
@@:
cmp qword ptr [wParam], IDM_HELLO
jne no_wm

xor r9d, r9d        ; 4. argument: r9d = uType = 0
lea r8, [Hello]  ; 3. argument: r8  = caption
lea rdx, [Text]     ; 2. argument: edx = window text
xor rcx, rcx        ; 1. argument: rcx = hWnd = NULL
call MessageBoxA

no_wm:
call DefWindowProcA
exit:
add rsp, 5*8
ret
align 4
WndProc endp

end


and RC file


#define IDM_TEST 1
#define IDM_HELLO 2
#define IDM_GOODBYE 3
#define IDM_EXIT 4

FirstMenu MENU
{
    POPUP "&List"
    {
        MENUITEM "&Hello!",IDM_HELLO
        MENUITEM "&Goodbye!", IDM_GOODBYE
        MENUITEM SEPARATOR
        MENUITEM "&Exit",IDM_EXIT
    }
    MENUITEM "&Test", IDM_TEST
}


Sources are quite big so debugging might be hard. If someone could post an example of compiling RC file and events services I'll be very greatful.
"How beautiful this world ruled by dibs, not a gun!"
...

qWord

you simple forgot to pass hMenu to the call of CreateWindowEx.
There are two more issues in the window procedure:
- wParam's shadow space is accessed, but it has not been filled with R8. (You can use R8W to check the menu item IDs here)
- after the call to MsgBox, DefWindowProc is called with invalid arguments
;--------MAKE-------------------------------------------------------------
;rc menu_app.rc
;
;jwasm -win64 menu_app.asm
;
;link /SUBSYSTEM:WINDOWS menu_app.obj menu_app.res
;
;--------INCLUDES---------------------------------------------------------

includelib      /WinInc/lib64/kernel32.lib
includelib      /WinInc/lib64/user32.lib
includelib      /WinInc/lib64/gdi32.lib

option casemap:none

;--------PROTOS-----------------------------------------------------------


HINSTANCE typedef QWORD
HWND      typedef QWORD
HMENU    typedef QWORD
HICON      typedef QWORD
HBRUSH    typedef QWORD
HCURSOR    typedef QWORD
WPARAM    typedef QWORD
LPARAM    typedef QWORD
LPSTR      typedef QWORD
LPVOID    typedef QWORD
UINT      typedef DWORD

NULL            equ 0
WS_OVERLAPPEDWINDOW equ 0CF0000h
CW_USEDEFAULT  equ 80000000h
SW_SHOWDEFAULT equ 10
SW_SHOWNORMAL  equ 1
IDC_ARROW      equ 32512
IDI_APPLICATION equ 32512
WM_DESTROY      equ 2
CS_VREDRAW      equ 1
CS_HREDRAW      equ 2
COLOR_WINDOW    equ 5
WM_COMMAND              equ 111h

IDM_TEST    EQU 1
IDM_HELLO   EQU 2
IDM_GOODBYE EQU 3
IDM_EXIT    EQU 4

proto_WNDPROC typedef proto :HWND,:UINT,:WPARAM,:LPARAM
WNDPROC typedef ptr proto_WNDPROC

WNDCLASSEXA struct 8
cbSize          DWORD   ?
style           DWORD   ?
lpfnWndProc     WNDPROC ?
cbClsExtra      DWORD   ?
cbWndExtra      DWORD   ?
hInstance       HINSTANCE ?
hIcon           HICON   ?
hCursor         HCURSOR ?
hbrBackground   HBRUSH  ?
lpszMenuName    LPSTR   ?
lpszClassName   LPSTR   ?
hIconSm         HICON   ?
WNDCLASSEXA ends

POINT   struct
x   SDWORD  ?
y   SDWORD  ?
POINT   ends

MSG struct 8
hwnd    HWND    ?
message DWORD   ?
wParam  WPARAM  ?
lParam  LPARAM  ?
time    DWORD   ?
pt      POINT   <>
MSG ends

GetModuleHandleA proto :LPSTR
GetCommandLineA  proto
ExitProcess      proto :UINT
LoadIconA        proto :HINSTANCE, :LPSTR
LoadCursorA      proto :HINSTANCE, :LPSTR
RegisterClassExA proto :ptr WNDCLASSEXA
CreateWindowExA  proto :DWORD, :LPSTR, :LPSTR, :DWORD, :SDWORD, :SDWORD, :SDWORD, :SDWORD, :HWND, :HMENU, :HINSTANCE, :LPVOID
ShowWindow       proto :HWND, :SDWORD
UpdateWindow     proto :HWND
GetMessageA      proto :ptr MSG, :HWND, :SDWORD, :SDWORD
TranslateMessage proto :ptr MSG
DispatchMessageA proto :ptr MSG
PostQuitMessage  proto :SDWORD
DefWindowProcA   proto :HWND, :UINT, :WPARAM, :LPARAM

EXTERN LoadMenuA :PROC
EXTERN MessageBoxA :PROC

;WinMain proto :HINSTANCE, :HINSTANCE, :LPSTR, :UINT

.data

ClassName db "SimpleWinClass",0
AppName  db "Our First Window",0
MenuName db "FirstMenu",0

Text db "Message test",0
Testing db "test",0
Hello db "Hello!",0
MenuFailed db "LOAD MENU FAILED!",0
.data?

hInstance HINSTANCE ?
CommandLine LPSTR ?
hMenu dq ?

.code

WinMainCRTStartup proc FRAME
push rbp
.pushreg rbp
mov rbp,rsp
.setframe rbp, 0
.endprolog

sub rsp,32
mov ecx,NULL
call GetModuleHandleA
mov hInstance, rax
call GetCommandLineA
mov CommandLine, rax
mov rcx, hInstance
mov rdx, NULL
mov r8, CommandLine
mov r9d, SW_SHOWDEFAULT
call WinMain
mov ecx, eax
call ExitProcess
align 4
WinMainCRTStartup endp

WinMain proc FRAME

push rbp
.pushreg rbp
mov rbp,rsp
.setframe rbp, 0
sub rsp, sizeof WNDCLASSEXA + sizeof MSG + sizeof HWND + 13*8  ;make sure rsp is 16-byte aligned
.allocstack sizeof WNDCLASSEXA + sizeof MSG + sizeof HWND + 13*8
.endprolog

hInst     equ <[rbp+10h]>
hPrevInst equ <[rbp+18h]>
CmdLine   equ <[rbp+20h]>
CmdShow   equ <[rbp+28h]>

wc   equ <[rbp - sizeof WNDCLASSEXA].WNDCLASSEXA>
msg  equ <[rbp - sizeof WNDCLASSEXA - sizeof MSG].MSG>
hwnd equ <[rbp - sizeof WNDCLASSEXA - sizeof MSG - sizeof HWND]>

mov hInst, rcx  ;store param1 in shadow space

mov wc.cbSize, SIZEOF WNDCLASSEXA
mov wc.style, CS_HREDRAW or CS_VREDRAW
;mov   rax, OFFSET WndProc  ;using LEA is preferable
lea rax, [WndProc]
mov wc.lpfnWndProc, rax
mov wc.cbClsExtra, 0
mov wc.cbWndExtra, 0
mov wc.hInstance, rcx
mov wc.hbrBackground, COLOR_WINDOW+1
mov wc.lpszMenuName, 0
;mov   rax, OFFSET ClassName  ;using LEA is preferable
lea rax, [ClassName]
mov wc.lpszClassName, rax
mov ecx, NULL
mov edx, IDI_APPLICATION
call LoadIconA
mov wc.hIcon, rax
mov wc.hIconSm, rax
mov ecx, NULL
mov edx, IDC_ARROW
call LoadCursorA
mov wc.hCursor,rax
lea rcx, wc
call RegisterClassExA

lea rdx, [MenuName]
mov rcx, hInst
call LoadMenuA
mov hMenu, rax


mov ecx, NULL
lea rdx, [ClassName]
lea r8, [AppName]
mov r9d, WS_OVERLAPPEDWINDOW
mov dword ptr [rsp+4*8], CW_USEDEFAULT
mov dword ptr [rsp+5*8], CW_USEDEFAULT
mov dword ptr [rsp+6*8], CW_USEDEFAULT
mov dword ptr [rsp+7*8], CW_USEDEFAULT
mov qword ptr [rsp+8*8], NULL
mov rax,hMenu
mov qword ptr [rsp+9*8], rax
mov rax, hInst
mov [rsp+10*8], rax
mov qword ptr [rsp+11*8], NULL
call CreateWindowExA
mov hwnd,rax
mov rcx, hwnd
mov edx, SW_SHOWNORMAL
call ShowWindow
mov rcx, hwnd
call UpdateWindow
;--- message loop
@@:
lea rcx, msg
        mov rdx, NULL
        mov r8, 0
        mov r9, 0
        call GetMessageA
        and rax, rax
        jz @F
        lea rcx, msg
        call TranslateMessage
        lea rcx, msg
        call DispatchMessageA
jmp @B
@@:
mov rax, msg.wParam
add rsp, sizeof WNDCLASSEXA + sizeof MSG + sizeof HWND + 13*8
pop rbp
ret
align 4
WinMain endp

WndProc proc FRAME

sub rsp, 5*8
.allocstack 5*8
.endprolog

hWnd    equ <[rbp+10h]>
uMsg equ <[rbp+18h]>
wParam  equ <[rbp+20h]>
lParam  equ <[rbp+28h]>

cmp edx, WM_DESTROY
jne msg_command
@pqm:
mov ecx, NULL
call PostQuitMessage
xor rax,rax
jmp exit
msg_command:
cmp edx, WM_COMMAND
jne no_wm

cmp r8w,IDM_EXIT
je @pqm

cmp r8w, IDM_TEST
jne @F

xor r9d, r9d        ; 4. argument: r9d = uType = 0
lea r8, [Testing]   ; 3. argument: r8  = caption
lea rdx, [Text]     ; 2. argument: edx = window text
xor rcx, rcx        ; 1. argument: rcx = hWnd = NULL
call MessageBoxA
jmp exit
@@:
cmp r8w, IDM_HELLO
jne no_wm

xor r9d, r9d        ; 4. argument: r9d = uType = 0
lea r8, [Hello]  ; 3. argument: r8  = caption
lea rdx, [Text]     ; 2. argument: edx = window text
xor rcx, rcx        ; 1. argument: rcx = hWnd = NULL
call MessageBoxA
xor eax,eax
jmp exit

no_wm:
call DefWindowProcA
exit:
add rsp, 5*8
ret
align 4
WndProc endp

end
MREAL macros - when you need floating point arithmetic while assembling!

dedndave

another approach is to use "LoadMenu", followed by "SetMenu" (typically after window creation)
the method qWord gave is the way to go
just wanted to mention the "low-level" method so you'd know about it
sometimes, the programmer may switch from one menu to another with the basic method

still another method is to use LoadMenu and place the handle in the class structure
then, all windows of that class use the same menu

vogelsang

Now app works.

Quote from: qWord on November 27, 2013, 04:42:10 AM
- wParam's shadow space is accessed, but it has not been filled with R8. (You can use R8W to check the menu item IDs here)

Yes, I'm still doing 32-bit coding  :biggrin:. I forgot, that R8 contains this parameter. I'm still having problems with understanding fastcall. Maybe when I get more knowlegde and experience I'll stop making bugs.

Thanks guys for replies.
"How beautiful this world ruled by dibs, not a gun!"
...