format PE GUI 4.0

include 'win32a.inc'

		section '.text' code readable executable
; ============================================================================================

  entry $
		enter	 sizeof.MSG, 0
		mov	 ebx, esp
		mov	 [ebx + MSG.wParam], -1

		call	Begin			; Initialize main window
		jc	.Exit

	; Applications primary message pump

	   @@:	xor	eax, eax
		push	eax
		push	eax
		push	eax
		push	ebx
		call	[GetMessage]
		or	eax, eax
		jz	.Exit

		push	ebx
		call	[TranslateMessage]
		push	ebx
		call	[DispatchMessage]
		jmp	@B

	.Exit:	mov	eax, [ebx + MSG.wParam]
		leave
		invoke	ExitProcess, eax

		align	8
; --------------------------------------------------------------------------------------------
;       hWnd Msg wParam & lParam are @ esp + 4 at this point

      ScanMap:	lodsd				; Default proc is window is sub or super class
		mov	ebx, eax
		lodsd				; # of handlers in map
		mov	ecx, eax

	; Scan map for any matching messages

	   @@:	lodsw				; Message #
		cmp	[esp + 8], eax		; Is it message currently being processed
		lodsd				; Get pointer to handler
		jz	.Handle
		loopnz	@B			; Continue till list is exhaused

	; Application is not handling this message so execute default processing

	   @@:	or	ebx, ebx		; EBX = Pointer to windows default proc
		jnz	.Subed
		jmp	 [DefWindowProc]	; Not sub or super classed

	; Push the extra parameter required by API

       .Subed:	pop	eax			; Grab return address
		push	ebx			; lpPrevWndFunc
		push	eax			; Replace return address
		jmp	[CallWindowProc]	; Execute windows default procedure

      .Handle:	lea	esi, [esp + 12] 	; Points to wParam & lParam
		call	eax			; Execute handler
		jc	@B			; CF = 1 if default processing still required

	; Kernel looks after cleaning up stack

		xor	eax, eax
		ret	16

		align	32
; --------------------------------------------------------------------------------------------
  MainWndProc:	mov	esi, MMap
		jmp	ScanMap

		align	16
; --------------------------------------------------------------------------------------------

  Quit_App:	push	0
		call	[PostQuitMessage]
		clc				; Set default processing not required
		ret

		align	16
; --------------------------------------------------------------------------------------------

	Begin:	push	ebp
		mov	ebp, esp

		push	IDI_APPLICATION
		push	0
		call	[LoadIcon]
		or	eax,eax
		jz	.Error

		push	eax			; hIconSm
		push	AppName 		; lpszClassName
		push	0			; lpszMenuName
		push	COLOR_WINDOW + 1	; hbrBackGround

		push	eax
		push	IDC_ARROW
		push	0
		call	[LoadCursor]
		or	eax, eax
		jz	.Error

		xchg	[esp], eax		; hCursor
		push	eax			; hIcon

		push	0
		call	[GetModuleHandle]
		push	eax			; hInstance
		mov	[hInst], eax

		push	0			; cbWndExtra
		push	0			; cbClsExtra
		push	MainWndProc		; lpfnWndProc
		push	CS_OWNDC + CS_HREDRAW + CS_VREDRAW
		push	sizeof.WNDCLASSEX

		push	esp
		call	[RegisterClassEx]
		or	ax, ax
		jz	.Error

	STYLE	=    WS_VISIBLE + WS_BORDER + WS_SYSMENU + WS_MINIMIZEBOX + WS_SIZEBOX

		push	0			; lpParam
		push	[hInst] 		; hInstance
		push	0			; hMenu
		push	0			; hWndParent
		push	600			; nHeight
		push	800			; nWidth
		mov	eax, CW_USEDEFAULT
		push	eax			; y
		push	eax			; x
		push	STYLE			; dwStyle
		push	AppTitle
		push	AppName
		push	WS_EX_STATICEDGE + WS_EX_CLIENTEDGE
		call	[CreateWindowEx]
		or	eax, eax
		jz	.Error

		mov	[MainWnd], eax
		jmp	@F

       .Error:	nop
		clc

	   @@:	leave
		ret

		section '.data' data readable writeable
; ============================================================================================

  AppName	db	'PEVIEW', 0
  AppTitle	db	'PE32 Viewer', 0

		align	8

  hInst 	dd	0
  MainWnd	dd	0

		align	16

   MMap 	dd	0			; Default windows procedure
		dd	( MMapEnd - $ ) / 6

		dw	WM_DESTROY
		dd	Quit_App
   MMapEnd:

		section '.idata' import data readable writeable
; ============================================================================================
  library kernel32,'KERNEL32.DLL',\
	  user32,'USER32.DLL'

  include 'api\kernel32.inc'
  include 'api\user32.inc'
