Author Topic: Basic Win32 API Window  (Read 19887 times)

Offline encryptor256

  • Full Member
  • **
  • Posts: 250
  • Country: lv
  • Win64 .
    • On Youtube: encryptor256
Basic Win32 API Window
« on: July 23, 2013, 09:31:58 AM »
Hello!

.Intro:
Im new to this forum, so,
this will be the first attempt to share code.
-------------------------------------------------------------------
NASM is the coolest thing i have ever found.
Everytime im opening, starting to code with NASM,
i feel like im in front of some sort of powerfull and dreadfull crafting table,
and only thing, that is needed, is a knowledge, to do some magic. :)
-------------------------------------------------------------------

This is Basic Win32 API Window, it covers,
the basic win32 api window,
and how to manage your code (Seperate larger parts into files and include them).


.For_me:
If i would have, the example like this, it would help a lot,
problems was with stdcall convetion, parameter locations (ebp+).
But now im done with this, so, you can have it.
If you have some small glitches, then this might help.

.Im_using:
  • Code editor: SciTE (higlights asm syntax).
  • NASM to make OJB files.
  • ALINK to make final EXE file, link Win32 api function calls.

.Code_management:
  • main.asm (main compile file)
  • ___RegisterClassEx.asm (include file)
  • ___CreateWindowEx.asm (include file)
  • ___MessageLoop.asm (include file)
  • ___windowProcedure.asm (include file)


.LET_CODE_BEGIN:

main.asm (main compile file)
Code: [Select]
[BITS 32]

; Define import macro, to import function from external DLL files
%macro macro_import_function 2
import %2 %1
extern %2
%endmacro

; Define import functions
macro_import_function user32.dll, LoadIconA
macro_import_function user32.dll, LoadCursorA
macro_import_function user32.dll, RegisterClassExA
macro_import_function user32.dll, MessageBoxA
macro_import_function user32.dll, CreateWindowExA
macro_import_function user32.dll, GetMessageA
macro_import_function user32.dll, TranslateMessage
macro_import_function user32.dll, DispatchMessageA
macro_import_function user32.dll, DefWindowProcA
macro_import_function user32.dll, ShowWindow
macro_import_function user32.dll, UpdateWindow
macro_import_function user32.dll, SendMessageA
macro_import_function user32.dll, PostQuitMessage
macro_import_function user32.dll, DestroyWindow

macro_import_function kernel32.dll, ExitProcess
macro_import_function kernel32.dll, GetModuleHandleA
macro_import_function kernel32.dll, GetCommandLineA

; Define come constants
CS_VREDRAW  equ 0x0001
CS_HREDRAW  equ 0x0002
IDI_APPLICATION equ 32512
COLOR_WINDOW equ 5
IDC_ARROW equ 32512

MB_OK  equ 0x00000000
MB_ICONEXCLAMATION equ 0x00000030

WS_SYSMENU  equ 0x00080000

SW_SHOW  equ 5

WM_CREATE equ 0x1
WM_DESTROY equ 0x2
WM_CLOSE  equ 0x0010


[SEGMENT .DATA USE32]

mainWindowClassName db "mainWindowClass",0
mainWindowName db "mainWindow",0

error_title db "~Error:",0
error_registerClassEx db "Register class error",0
error_createWindowEx db "Create window error",0

[SEGMENT .BSS USE32]

hInstance resb 4
commandLine resb 4

mainWindowClassEx resb 12*4
mainMessageStruct resb 7*4

windowHandle resb 4


[SEGMENT .TEXT USE32]

..start:

; Get instance, once and for all
push dword 0
call [GetModuleHandleA]
mov [hInstance],eax

; Get command line argument
call [GetCommandLineA]
mov [commandLine],eax

; Include external file
; Create window class and register
%include "___RegisterClassEx.asm"

; Include external file
; Create window
%include "___CreateWindowEx.asm"

; Include external file
; Do message loop
%include "___MessageLoop.asm"

jmp quitProgram

; Error handler for RegisterClassEx failure
registerClassError:
push dword MB_OK + MB_ICONEXCLAMATION
push dword error_title
push dword error_registerClassEx
push dword 0
call [MessageBoxA]
jmp quitProgram

; Error handler for CreateWindowEx failure
createWindowError:
push dword MB_OK + MB_ICONEXCLAMATION
push dword error_title
push dword error_createWindowEx
push dword 0
call [MessageBoxA]

; Quit program label
quitProgram:
push dword 0
call [ExitProcess]
ret

; Include external file
; Window procedure goes here
%include "___windowProcedure.asm"

___RegisterClassEx.asm (include file)
Code: [Select]
; Fill main WNDCLASSEX structure ----------------------------------------------------------------
; -----------------------------------------------------------------------------------------------

; 1. WNDCLASSEX.cbSize
mov [mainWindowClassEx + 0], dword 12*4

; 2. WNDCLASSEX.style
mov [mainWindowClassEx + 4], dword CS_VREDRAW + CS_HREDRAW

; 3. WNDCLASSEX.lpfnWndProc
mov [mainWindowClassEx + 8], dword windowProcedure

; 4. WNDCLASSEX.cbClsExtra
mov [mainWindowClassEx + 12], dword 0

; 5. WNDCLASSEX.cbWndExtra
mov [mainWindowClassEx + 16], dword 0

; 6. WNDCLASSEX.hInstance
mov eax,dword [hInstance]
mov [mainWindowClassEx + 20],eax

; 7. WNDCLASSEX.hIcon
push dword IDI_APPLICATION
push dword 0 ; This parameter must be NULL when a standard icon is being loaded.
call [LoadIconA]
mov [mainWindowClassEx + 24],eax

; 8. WNDCLASSEX.hIcon
push dword IDC_ARROW
push dword 0 ; This parameter must be NULL when a standard cursor is being loaded.
call [LoadCursorA]
mov [mainWindowClassEx + 28],eax

; 9. WNDCLASSEX.hbrBackground
mov [mainWindowClassEx + 32],dword COLOR_WINDOW

; 10. WNDCLASSEX.lpszMenuName
mov [mainWindowClassEx + 36],dword 0

; 11. WNDCLASSEX.lpszClassName
mov [mainWindowClassEx + 40],dword mainWindowClassName

; 12. WNDCLASSEX.hIcon
push dword IDC_ARROW
push dword  [hInstance]
call [LoadCursorA]
mov [mainWindowClassEx + 44],eax

; Try Register

push dword mainWindowClassEx
call [RegisterClassExA]
cmp eax,0
je registerClassError

___CreateWindowEx.asm (include file)
Code: [Select]


push dword 0 ;LPVOID lpParam // pointer to window-creation data
push dword 0 ;HINSTANCE hInstance, // handle to application instance
push dword 0 ;HMENU hMenu, // handle to menu, or child-window identifier
push dword 0 ;HWND hWndParent, // handle to parent or owner window
push dword 480 ;int nHeight, // window height
push dword 640 ;int nWidth, // window width
push dword 128 ;int y, // vertical position of window
push dword 128 ;int x, // horizontal position of window
push dword WS_SYSMENU ;DWORD dwStyle, // window style
push dword mainWindowName ;LPCTSTR lpWindowName, // pointer to window name
push dword mainWindowClassName ;LPCTSTR lpClassName, // pointer to registered class name
push dword 0 ;DWORD dwExStyle, // extended window style
call [CreateWindowExA]
mov [windowHandle],eax
cmp eax,0
je createWindowError

___MessageLoop.asm (include file)
Code: [Select]

mainMessageLoop:

push dword 0
push dword 0
push dword 0
push dword mainMessageStruct
call [GetMessageA]
cmp eax,0
jle quitProgram

;push dword mainMessageStruct
;call [TranslateMessage]

push dword mainMessageStruct
call [DispatchMessageA]

jmp mainMessageLoop

___windowProcedure.asm (include file)
Code: [Select]
; Main window procedure
windowProcedure:
push ebp
mov ebp,esp

; Window procedure is stdcall convetion, so,
; the parameters are located at these kind of offsets.
; 4 Parameters
%define ebp_hwnd ebp+8
%define ebp_message ebp+12
%define ebp_wparam ebp+16
%define ebp_lparam ebp+20

; Switch\jump table
cmp [ebp_message],dword WM_CLOSE
je .onClose
cmp [ebp_message],dword WM_DESTROY
je .onDestroy
cmp [ebp_message],dword WM_CREATE
je .onCreate

.defaultProcedure:
push dword [ebp_lparam]
push dword [ebp_wparam]
push dword [ebp_message]
push dword [ebp_hwnd]
call [DefWindowProcA]
mov esp,ebp
pop ebp
ret 16 ; stdcall convetion requres pop all parameters from stack 4*4 = 16 bytes

.onCreate:
push dword SW_SHOW
push dword [ebp_hwnd]
call [ShowWindow]

push dword [ebp_hwnd]
call [UpdateWindow]

mov eax,0
mov esp,ebp
pop ebp
ret 16 ; stdcall convetion requres pop all parameters from stack 4*4 = 16 bytes

.onClose:
push dword [ebp_hwnd]
call [DestroyWindow]
mov eax,0
mov esp,ebp
pop ebp
ret 16 ; stdcall convetion requres pop all parameters from stack 4*4 = 16 bytes

.onDestroy:
push dword 0
call [PostQuitMessage]
mov eax,0
mov esp,ebp
pop ebp
ret 16 ; stdcall convetion requres pop all parameters from stack 4*4 = 16 bytes


.LET_CODE_COMPILE:

Put all those files in same directory, copy nasm and alink exe files too, to this same directory.

NASM: Make OBJ file, cmd command: "nasm -fobj main.asm"

ALINK: Make Win32 Exe file, cmd command: "alink -c -oPE -subsys windows main.obj"

.IF:

If you use code editor SciTE, you can set Menu->Language->Assembler.
Open Menu->Options->asm.properties, at the end of document you can find similarites,
and replace with something like this:

Code: [Select]
command.compile.$(file.patterns.asm)=nasm -fobj $(FileNameExt)
command.name.0.*.asm=Link
command.0.*.asm=alink -c -oPE -subsys windows $(FileName)

So, now open your main.asm file, then Tools->Compile, Link, and execute your program.

Here is some helpfull link, will help you to begin with win32 and nasm:

http://mathimaaran.angelfire.com/helloworld_tutorial.htm

ALINK you can get here:

http://alink.sourceforge.net/download.html

.CODE:

This code is NOT, ALL mine, i dont claim the rights to this,
the only thing what i did,
is to build, collect information of "my" own WORKING version of basic win32 application.
Use it at your own risk. :)
It is your responsibility to evaluate this information and dont blow up your monitor.  :)

It seems here is no way to attach files, so, im skipping that part.
Encryptor256's Investigation \ Research Department.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Basic Win32 API Window
« Reply #1 on: July 23, 2013, 06:00:11 PM »
I think you'll be allowed to attach files after you've made a few postings.

If you put nasm.exe and alink.exe in every directory where you have code, you're going to have an awful lot of multiple copies of these files after a while! Consider setting the "PATH" environment variable to where you've got 'em installed.

I should point out that using Alink in conjunction with the "import" directive, we need to "call [SomeAPI]". This is not "usual" - in other circumstances we want "call SomeAPI" without the square brackets ('{' - hippie parentheses, '[' - republican parentheses :) ).

Thanks for the example! Nice to see new members making contributions! Glad you like Nasm!

Best,
Frank


Offline droid

  • Jr. Member
  • *
  • Posts: 3
Re: Basic Win32 API Window
« Reply #2 on: July 17, 2017, 02:47:12 PM »
Whoa! This is brutal, sick, and priceless!!!!!!   :D
I finally got down to play with NASM. Never in a  thousand years did I think this would be possible within a few hours.
Thank you guys.

For those of you that hate command lines as much as me, using a batch file makes it a lot more friendly.
Keep in mind that for some reason, when run from batch files, programs won't use the system PATH, the batch file has to call it.

My build.bat batch file has the following form:


Code: [Select]

REM COMPILE WITH NASM
REM use 'obj' output or 'imports' won't work

@set path=C:\Program Files\NASM;%path%
nasm -f obj hello_form.asm

REM LINK WITH ALINK
REM use 'con' for console application, 'win' for windowed application

@set path=C:\your path\ALINK;%path%
alink -oPE -subsys win -entry START hello_form.obj

pause


Hope that helps someone!

Quote from: encryptor256
-------------------------------------------------------------------
NASM is the coolest thing i have ever found.
Everytime im opening, starting to code with NASM,
i feel like im in front of some sort of powerfull and dreadfull crafting table,
and only thing, that is needed, is a knowledge, to do some magic. :)
-------------------------------------------------------------------

Indeed
« Last Edit: July 17, 2017, 03:03:21 PM by droid »

Offline ~

  • Jr. Member
  • *
  • Posts: 8
Re: Basic Win32 API Window
« Reply #3 on: August 08, 2017, 11:22:13 PM »
x86_WinAPI_ASM_PE_EXE_Skeleton32--v2017-07-26.zip

I've made a Windows PE EXE skeleton fully in NASM, no linker required.

I've started to add the functions from all standard Windows DLLs to have the whole WinAPI available as if it was JavaScript.

Now we only need to know how to call the functions and define WinAPI structures. The full WinAPI has already been supposedly imported transparently, waiting to be simply used.

I used PEDUMP to get the DLL exported functions and tested from Windows 9x to Windows 10 to ensure that the functions that have been imported are present in all Windows versions.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Basic Win32 API Window
« Reply #4 on: August 09, 2017, 12:27:09 AM »
Cool! Big download, eh? I hope some Windows users
appreciate it.

Best,
Frank