CreateWindowEx failing with error 1400

-1

The title says it all. I'm just trying to create a window using CreateWindowEx in assembly and the call is failing with error 1400 (Bad Window Handle). I've verified that no other API calls are failing and DefWindowProc is returning 0 (pass) for WM_CREATE. The parameters going to CreateWindowEx look right to me.

Edit: Now sharing code with error checking present that I had previously removed for readability.

extern __imp__GetModuleHandleA@4
extern __imp__RegisterClassA@4
extern __imp__ExitProcess@4
extern __imp__AdjustWindowRect@12
extern __imp__CreateWindowExA@48
extern __imp__GetSystemMetrics@4
extern __imp__GetLastError@0
extern __imp__DefWindowProcA@16

global _main

section main text align=1
_main:
    push    byte 0
    call    [__imp__GetModuleHandleA@4]
    test    eax, eax
    jz      OnError

    mov     dword [hInstance], eax
    push    dword wndclass
    call    [__imp__RegisterClassA@4]
    test    eax, eax
    jz      OnError

    ; WS_VISIBLE | WS_CAPTION | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU
    mov     ebx, 0x10000000 | 0x00C00000 | 0x04000000 | 0x02000000 | 0x00080000

    push    byte 0
    push    ebx
    push    rect
    call    [__imp__AdjustWindowRect@12]
    test    eax, eax
    jz      OnError

    push    byte 0
    push    dword [hInstance]
    push    byte 0
    push    byte 0

    ; rect.bottom - rect.top
    mov     eax, dword [rect.bottom]
    sub     eax, dword [rect.top]
    push    eax

    ; rect.right - rect.left
    mov     eax, dword [rect.right]
    sub     eax, dword [rect.left]
    push    eax

    ; ( GetSystemMetrics(SM_CYSCREEN) - rect.bottom + rect.top ) >> 1
    push    byte 1                      ; SM_CYSCREEN
    call    [__imp__GetSystemMetrics@4]
    sub     eax, dword [rect.bottom]
    add     eax, dword [rect.top]
    sar     eax, 1
    push    eax

    ; ( GetSystemMetrics(SM_CXSCREEN) - rect.right + rect.left ) >> 1
    push    byte 0                      ; SM_CXSCREEN
    call    [__imp__GetSystemMetrics@4]
    sub     eax, [rect.right]
    add     eax, [rect.left]
    sar     eax, 1
    push    eax

    push    ebx                         ; dwStyle
    push    byte 0                      ; lpWindowName
    push    classname                   ; lpClassName
    push    0x00040000 | 0x00000100     ; dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE
    call    [__imp__CreateWindowExA@48]
    test    eax, eax
    jz      OnError

    push    byte 0
    call    [__imp__ExitProcess@4]

OnError:
    call    [__imp__GetLastError@0]
    push    eax
    call    [__imp__ExitProcess@4]

section WinProc text align=1
WinProc:
    push    dword [esp + 20]
    push    dword [esp + 16]
    push    dword [esp + 12]
    push    dword [esp + 8]
    call    [__imp__DefWindowProcA@16]
    ret     16

section wndclass data align=1
wndclass:
    dd      0x0020 | 0x0002 | 0x0001    ; Style CS_OWNDC | CS_HREDRAW | CS_VREDRAW
    dd      WinProc                     ; lpfnWndProc
    dd      0                           ; cbClsExtra
    dd      0                           ; cbWndExtra
hInstance:
    dd      0                           ; hInstance
    dd      0                           ; hIcon
    dd      0                           ; hCursor
    dd      0                           ; hbrBackground
    dd      0                           ; lpszMenuName
    dd      classname                   ; lpszClassName
classname:
    db      '1337Class', 0

section rect data align=1
rect:
    .left:   dd      0
    .top:    dd      0
    .right:  dd      1366
    .bottom: dd      768
winapi
nasm
asked on Stack Overflow Dec 18, 2015 by Orby • edited Dec 19, 2015 by Orby

1 Answer

1

It turns out the problem was with my window procedure. It was totally screwed up. A good example of a working window procedure that just calls DefWindowProc is

WinProc:
    mov     ebp, esp
    push    dword [ebp + 16]
    push    dword [ebp + 12]
    push    dword [ebp + 8]
    push    dword [ebp + 4]
    call    [__imp__DefWindowProcA@16]
    ret     16

Lessons learned:

  1. Always copy ESP to EBP before you start mucking around. It makes the code difficult to maintain otherwise.
  2. Always pay attention to the contents of the stack in your debugger.
  3. DefWindowProcA will return zero even if you pass it garbage!
answered on Stack Overflow Dec 19, 2015 by Orby

User contributions licensed under CC BY-SA 3.0