Simple Masm64 window template (47 lines of code + 30 lines of resources)

Started by jj2007, September 19, 2023, 11:09:25 PM

Previous topic - Next topic

jj2007

I've tried to keep it short and simple. With RichMasm, just hit F6 to build and run the template. Otherwise, use your dedicated Masm64 batch file.

WndProc proc uses rsi rdi rbx hWnd, uMsg, wParam, lParam
  .if uMsg==WM_COMMAND
cmp wParam, 100
ja @F
invoke MessageBox, 0, str$(wParam), chr$("WM_COMMAND:"), MB_OK
@@:
  .elseif uMsg==WM_CREATE
invoke CreateWindowEx, WS_EX_CLIENTEDGE, chr$("edit"), chr$("The Masm64 SDK works fine"),\
  WS_CHILD or WS_VISIBLE or WS_BORDER or WS_VSCROLL or ES_MULTILINE,\
  9, 9, 270, 126, hWnd, 103, wcx.hInstance, NULL
mov hEdit, rax ; you may need this global variable for further processing
  .elseif uMsg==WM_DESTROY
invoke PostQuitMessage, 0
  .endif
  invoke DefWindowProc, hWnd, uMsg, wParam, lParam ; default processing
  ret
WndProc endp

sinsi

I know this is an old thread but I'm looking for masm64 examples and found this one.
Did the exe work for anyone? I was left with a zombie process, here's why:
WndProc proc uses rsi rdi rbx hWnd, uMsg, wParam, lParamIf you don't define a size, ML64 (others I don't know) defaults to DWORD.
So when your code invokes DefWindowProc it passes the WndProc parameters as DWORDs.
At a guess, when you pass along the WM_CREATE message, the hWnd is invalid, also lParam won't point to a CREATESTRUCT anymore.

I wouldn't blame ML64 for this, a 64-bit CPU defaults to 32-bit sizes unless specified  :biggrin:

jj2007

Quote from: sinsi on April 07, 2024, 03:06:53 AMI was left with a zombie process

This is interesting because I never post code that I haven't tested. So I downloaded the archive and built it: no problem, just a little window as in the screenshot above :cool:

*** assembling M64Gui as Masm64 SDK source ***
Source        D:\Masm64\bin64\test_old\M64Gui.asm
EntryPoint    WinMain
Assembler    ml64
Linker        polink
- - - - - - - - - - - - - - -
*** creating rsrc.res ***
Microsoft (R) Windows (R) Resource Compiler Version 10.0.10011.16384

Copyright (C) Microsoft Corporation.  All rights reserved.


*** assembler options: [] ***
*** linker options: [], EP=[WinMain] ***
*** commandline: \Masm64\bin64\ml64.exe /c /nologo  /FoD:\Masm64\bin64\test_old\Tmp_file.obj D:\Masm64\bin64\test_old\Tmp_file.asm ***
 Assembling: D:\Masm64\bin64\test_old\Tmp_file.asm

*** linking D:\Masm64\bin64\test_old\Tmp_file.obj with resources ***
« OK »

And now comes the surprise: the original exe in the archive creates indeed a zombie process, and is 6144 bytes long. The newly built exe works fine and is 4608 bytes long, see attachment :rolleyes:

This is not the first time I have such problems with 64-bit GUI applications. Everything looks fine, handles returned correctly, CreateWindowEx parameters absolutely correct, but then CreateWindowEx returns zero with GetLastError = 0. Weird.

Below a screenshot from Timo's TLPEView. The failing version has extra .rdata and .reloc sections. It turns out that it builds and runs fine with polink but M$ link of 21.10.2021 causes the trouble...



Here is the CreateWindowEx part for both versions. Note the different address range.

Works fine:
0000000140001163     | FF15 CF100000                   | call [<RegisterClassExA>] |
0000000140001169     | 48:C7C1 10000000                | mov rcx,10                |
0000000140001170     | 48:8B53 40                      | mov rdx,[rbx+40]          | rdx:EntryPoint
0000000140001174     | 4C:8B05 9A0F0000                | mov r8,[140002115]        | qword ptr ds:[0000000140002115]:&"Hello World"
000000014000117B     | 49:C7C1 0000CF10                | mov r9,10CF0000           | r9:EntryPoint
0000000140001182     | 48:C74424 20 7F000000           | mov [rsp+20],7F           |
000000014000118B     | 48:C74424 28 7F000000           | mov [rsp+28],7F           |
0000000140001194     | 48:C74424 30 2C010000           | mov [rsp+30],12C          | [qword ptr ss:[rsp+30]]:RtlUserThreadStart+21
000000014000119D     | 48:C74424 38 C8000000           | mov [rsp+38],C8           |
00000001400011A6     | 48:C74424 40 00000000           | mov [rsp+40],0            |
00000001400011AF     | 48:C74424 48 00000000           | mov [rsp+48],0            |
00000001400011B8     | 48:C74424 50 00000000           | mov [rsp+50],0            |
00000001400011C1     | 48:C74424 58 00000000           | mov [rsp+58],0            |
00000001400011CA     | FF15 40100000                   | call [<CreateWindowExA>] 

Fails:
00007FF6AEA81163     | FF15 EF0E0000                   | call [<RegisterClassExA>] |
00007FF6AEA81169     | 48:C7C1 10000000                | mov rcx,10                |
00007FF6AEA81170     | 48:8B53 40                      | mov rdx,[rbx+40]          | rdx:"Masm64Gui", [qword ptr ds:[rbx+40]]:"Masm64Gui"
00007FF6AEA81174     | 4C:8B05 9A1F0000                | mov r8,[7FF6AEA83115]     | r8:"Hello World", qword ptr ds:[00007FF6AEA83115]:&"Hello World"
00007FF6AEA8117B     | 49:C7C1 0000CF10                | mov r9,10CF0000           |
00007FF6AEA81182     | 48:C74424 20 7F000000           | mov [rsp+20],7F           |
00007FF6AEA8118B     | 48:C74424 28 7F000000           | mov [rsp+28],7F           |
00007FF6AEA81194     | 48:C74424 30 2C010000           | mov [rsp+30],12C          |
00007FF6AEA8119D     | 48:C74424 38 C8000000           | mov [rsp+38],C8           |
00007FF6AEA811A6     | 48:C74424 40 00000000           | mov [rsp+40],0            |
00007FF6AEA811AF     | 48:C74424 48 00000000           | mov [rsp+48],0            |
00007FF6AEA811B8     | 48:C74424 50 00000000           | mov [rsp+50],0            |
00007FF6AEA811C1     | 48:C74424 58 00000000           | mov [rsp+58],0            |
00007FF6AEA811CA     | FF15 980E0000                   | call [<CreateWindowExA>]  |

It's neither the size of arguments, nor is it the address range per se - all previous API calls succeed.

_japheth

QuoteIt's neither the size of arguments, nor is it the address range per se - all previous API calls succeed.

That's indeed an interesting problem. Have you tried yet to tell MS link NOT to create relocations? That's how polink makes the binary, obviously, and perhaps that is what may cause problems ...
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

sinsi

Quote from: jjCreateWindowEx parameters absolutely correct, but then CreateWindowEx returns zero with GetLastError = 0.
I spent the best part of a day tracking that down.

All I did with your code is add sizes to the WndProc args and it worked.

jj2007

Quote from: _japheth on April 07, 2024, 05:07:53 PMThat's indeed an interesting problem. Have you tried yet to tell MS link NOT to create relocations?

Linker option /fixed did the trick, thanks a lot :thumbsup:

Quote from: sinsi on April 07, 2024, 05:14:11 PMAll I did with your code is add sizes to the WndProc args and it worked.

That's interesting but not convincing: in 64-bit land, you can specify DWORD, but args will be passed in rcx, rdx etc anyway, and there is no difference. So I wonder what really happens inside your code. Have you compared the disassemblies?