unresolved ERROR_INVALID_WINDOW_HANDLE at the end of program.

Started by Dogim, November 26, 2010, 07:30:17 PM

Previous topic - Next topic

Dogim

Hello and good/day/night to all.
I,m experimenting with a WNDPROC routine, found in the goasm manual, which seems to run OK, but the error is only visible when i run the program through a debugger ( gobug/or olly )
I have mention this before in another post, but I'm still curios to know why this error occurs.

#DEFINE WIN32_LEAN_AND_MEAN
#DEFINE LINKFILES
#include <windows.h>
#include <commctrl.h>


DATA SECTION
ALIGN 4
WC WNDCLASSEX
MESSAGES MSG
TITLE_WIND DB 'WINDOW PROGRAMMING USING GOASM',0
CLASS_NAME DB 'WINDOWS CLASS',0
MESSAGES_TABLE ;DD WM_CREATE,   ON_CREATE       ;the message then the code address
          DD WM_DESTROY,  ON_DESTROY
          ;DD WM_PAINT,    ON_PAINT
          DD WM_CLOSE, ON_CLOSE


TESTDATA DD ? ; !!!!! SEE IN GOBUG !!!!!
HINST DD ?
HWND DD ?

CODE SECTION
START:
INVOKE GetModuleHandle,NULL
MOV [HINST],EAX
LEA EDI,WC
XOR ECX,ECX
ADD ECX,1 ; JUMP OVER CBSIZE
MOV EDX ,SIZEOF WNDCLASSEX/4
INIT_WNDCLSSEX:
CMP ECX,EDX
JZ >
MOV D[EDI+ECX*4],0
INC ECX
JMP INIT_WNDCLSSEX
:

MOV D[WC.cbSize],SIZEOF WNDCLASSEX
MOV [WC.lpfnWndProc],ADDR WNDPROC
MOV [WC.hInstance],EAX
MOV D[WC.hbrBackground],COLOR_BTNFACE+1
MOV [WC.lpszClassName],ADDR CLASS_NAME
INVOKE RegisterClassEx,ADDR WC

CMP EAX,ERROR_INVALID_WINDOW_HANDLE
JNZ >
INVOKE ExitProcess,0
:
XOR EAX,EAX ; EAX DESTROYED ANYWHAY

PUSH EAX
PUSH [EDI+14H] ; HINSTNCE
PUSH EAX
PUSH EAX
PUSH 500D ; WINDOW HEIGHT
PUSH 500D ; WINDOW WIDTH
PUSH EAX ; Y
PUSH EAX ; X
PUSH WS_OVERLAPPEDWINDOW
PUSH ADDR TITLE_WIND
PUSH ADDR CLASS_NAME
PUSH EAX
CALL CreateWindowEx
OR EAX,EAX
JNZ >
;HANDLE ERROR HERE
INVOKE ExitProcess,EAX
:
MOV [HWND],EAX ; SAVE HANDLE
INVOKE ShowWindow,EAX,SW_SHOWNORMAL
;;INVOKE UpdateWindow,EAX

MSG_LOOP:
INVOKE GetMessage,ADDR MESSAGES,0,0,0
OR EAX,EAX
JZ > END_MESS_LOOP
INVOKE TranslateMessage,ADDR MESSAGES
INVOKE DispatchMessage,ADDR MESSAGES
JMP < MSG_LOOP
END_MESS_LOOP:
INVOKE ExitProcess,[MESSAGES.wParam]

WNDPROC:
FRAME hwnd,uMsg,wParam,lParam      ;establish stack frame and get parameters
USES EDI,ESI,EBX

MOV EAX,[uMsg]          ;get in eax message sent by Windows
MOV ECX,SIZEOF MESSAGES/8       ;get number of messages to look at
MOV EDX,ADDR MESSAGES
L2:
DEC ECX
JS >.notfound
CMP [EDX+ECX*8],EAX      ;see if its the correct message
JNZ L2                  ;no
CALL [EDX+ECX*8+4]      ;call the correct procedure for the message
JNC >.exit
.notfound
INVOKE DefWindowProc,[hwnd],[uMsg],[wParam],[lParam]
.exit
RET
ENDF                   


//ON_CREATE:
// XOR EAX,EAX
// RET
ON_DESTROY:
PUSH 0
CALL PostQuitMessage    ;exit via the message loop
STC                     ;go to DefWindowProc too
RET


//ON_PAINT:
// XOR EAX,EAX
// RET

ON_CLOSE:
INVOKE PostQuitMessage,0
XOR EAX,EAX
RET



gobug dump GoBug - copyright Jeremy Gordon 1996-2009
                 Date: friday 26 november 2010 Time: 20:12:58
                         Dump of event/message logpane
       whilst debugging C:\Users\dogim\Documents\ASM_PROJECKS\EXP1\EXP1.exe


event/message                            to hWnd       wParam        lParam        source        thread     tick

mouse (non-client area) click: left button:-
GetMessage returning with WM_NCLBUTTONDOWN (A1) from message queue for hWnd=20778
executing in ..MSG_LOOP ..
WM_NCLBUTTONDOWN (A1)                 20778         14            901DB         queue         17Ch(main)  7D61h
Main thread is idle
WM_CAPTURECHANGED (215)               20778         0             0             direct        17Ch(main)  7D9Fh
WM_SYSCOMMAND (112)                   20778         F060          901DB         direct        17Ch(main)  7D9Fh
WM_CLOSE (10)                         20778         0             0             direct        17Ch(main)  7D9Fh
Unknown message 90                    20778         0             0             direct        17Ch(main)  7D9Fh
WM_WINDOWPOSCHANGING (46)             20778         0             18F6D8        direct        17Ch(main)  7D9Fh
WM_WINDOWPOSCHANGED (47)              20778         0             18F6D8        direct        17Ch(main)  7D9Fh
WM_NCACTIVATE (86)                    20778         0             0             direct        17Ch(main)  7D9Fh
WM_ACTIVATE (6)                       20778         0             0             direct        17Ch(main)  7D9Fh
WM_ACTIVATEAPP (1C)                   207A2         0             9C4           direct        17Ch(main)  7DBFh
WM_ACTIVATEAPP (1C)                   2077A         0             9C4           direct        17Ch(main)  7DBFh
WM_ACTIVATEAPP (1C)                   20778         0             9C4           direct        17Ch(main)  7DBFh
WM_KILLFOCUS (8)                      20778         0             0             direct        17Ch(main)  7DBFh
Unknown message 287                   2077A         18            20778         direct        17Ch(main)  7DBFh
WM_IME_SETCONTEXT (281)               20778         0             C000000F      direct        17Ch(main)  7DBFh
WM_IME_SETCONTEXT (281)               2077A         0             C000000F      direct        17Ch(main)  7DBFh
WM_IME_SETCONTEXT (281)               207A2         0             C000000F      direct        17Ch(main)  7DBFh
executing in ..WNDPROC.notfound ..
WM_DESTROY (2)                        20778         0             0             direct        17Ch(main)  7DBFh
Unknown message 90                    207A0         0             0             direct        17Ch(main)  7DBFh
WM_DESTROY (2)                        207A0         0             0             direct        17Ch(main)  7DBFh
WM_NCDESTROY (82)                     207A0         0             0             direct        17Ch(main)  7DBFh
GetMessage returning with Registered message C03E from message queue for hWnd=0
Unknown message 90                    30798         0             0             direct        17Ch(main)  7DBFh
WM_DESTROY (2)                        30798         0             0             direct        17Ch(main)  7DBFh
Unknown message 90                    2077A         0             0             direct        17Ch(main)  7DBFh
Unknown message 90                    207A2         0             0             direct        17Ch(main)  7DBFh
WM_DESTROY (2)                        207A2         0             0             direct        17Ch(main)  7DBFh
WM_NCDESTROY (82)                     207A2         0             0             direct        17Ch(main)  7DBFh
WM_DESTROY (2)                        2077A         0             0             direct        17Ch(main)  7DBFh
WM_NCDESTROY (82)                     2077A         0             0             direct        17Ch(main)  7DBFh
WM_NCDESTROY (82)                     30798         0             0             direct        17Ch(main)  7DBFh
Unknown message 90                    2077A         0             0             direct        17Ch(main)  7DBFh
WM_DESTROY (2)                        2077A         0             0             direct        17Ch(main)  7DBFh
WM_NCDESTROY (82)                     2077A         0             0             direct        17Ch(main)  7DBFh
WM_NCDESTROY (82)                     20778         0             0             direct        17Ch(main)  7DBFh
Api error No.1400 at: 76326238h Thread=17Ch(main)
~ Instruction: FS AND B[FCA,FE    Function: ----------------
~ Error code:  ERROR_INVALID_WINDOW_HANDLE

Tight_Coder_Ex

Try using WinDbg as I'm not sure where handles other than 20778H come from.  I suspect GoBug might be the problem.

jorgon

Hi Dogin
The API error appears to occur within an operating system DLL (you can see this from the high value of the instruction pointer), and also occurs just after the window destroy messages.
My theory therefore is that the error message is by design - it looks like the system is testing to see if the window handle still exists.
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

Dogim

Quote from: Tight_Coder_Ex on November 26, 2010, 08:30:19 PM
Try using WinDbg as I'm not sure where handles other than 20778H come from.  I suspect GoBug might be the problem.
Thanks Tight Coder, ill give it a try lateron. :U

Dogim

Quote from: jorgon on November 26, 2010, 09:49:56 PM
Hi Dogin
The API error appears to occur within an operating system DLL (you can see this from the high value of the instruction pointer), and also occurs just after the window destroy messages.
My theory therefore is that the error message is by design - it looks like the system is testing to see if the window handle still exists.
Hi Jorgon, first of all nice work with Goasm :U, and thank you for your answer, my guess was that it have something to do with win 7 64 bits, but ill test this later on another system with vista 32 bit, or on XP 32 bits.

Dogim

Hello again, just out of curiosity, i have tested the code on different OS and it still gives the same error.

Tight_Coder_Ex

Remove PostQuitMessage from ON_CLOSE: or disable handler as you are calling API twice and that is probably the problem.

Dogim

Quote from: Tight_Coder_Ex on November 27, 2010, 10:00:55 PM
Remove PostQuitMessage from ON_CLOSE: or disable handler as you are calling API twice and that is probably the problem.
Hi Tight_Coder,
I removed the PostquitMessage as you said, but the error still pops up ( only when debugging ) so i changed the windows proc to the standard version and the invalid handle error disappears.#DEFINE WIN32_LEAN_AND_MEAN
#DEFINE LINKFILES
#include <windows.h>
#include <commctrl.h>


DATA SECTION
ALIGN 4
WC WNDCLASSEX
MESSAGES MSG
TITLE_WIND DB 'WINDOW PROGRAMMING USING GOASM',0
CLASS_NAME DB 'WINDOWS CLASS',0
HINST DD ?
HWND DD ?

CODE SECTION
START:
INVOKE GetModuleHandle,NULL
MOV [HINST],EAX
LEA EDI,WC
XOR ECX,ECX
ADD ECX,1 ; JUMP OVER CBSIZE
MOV EDX ,SIZEOF WNDCLASSEX/4
INIT_WNDCLSSEX:
CMP ECX,EDX
JZ >@001
MOV D[EDI+ECX*4],0
INC ECX
JMP INIT_WNDCLSSEX
@001:

MOV D[EDI],SIZEOF WNDCLASSEX
MOV [EDI+08H],ADDR WNDPROC
MOV [EDI+14H],EAX
MOV D[EDI+20H],COLOR_BTNFACE+1
MOV [EDI+28H],ADDR CLASS_NAME

INVOKE RegisterClassEx,EDI

CMP EAX,ERROR_INVALID_WINDOW_HANDLE
JNZ >@002
INVOKE ExitProcess,0
@002:
XOR EAX,EAX ; EAX DESTROYED ANYWHAY

PUSH EAX
PUSH [EDI+14H] ; HINSTNCE
PUSH EAX
PUSH EAX
PUSH 500D ; WINDOW HEIGHT
PUSH 500D ; WINDOW WIDTH
PUSH EAX ; Y
PUSH EAX ; X
PUSH WS_OVERLAPPEDWINDOW
PUSH ADDR TITLE_WIND
PUSH ADDR CLASS_NAME
PUSH EAX
CALL CreateWindowEx
OR EAX,EAX
JNZ >@003
;HANDLE ERROR HERE
INVOKE ExitProcess,EAX
@003:
MOV [HWND],EAX ; SAVE HANDLE
INVOKE ShowWindow,EAX,SW_SHOWNORMAL

MSG_LOOP:
INVOKE GetMessage,ADDR MESSAGES,0,0,0
OR EAX,EAX
JZ > END_MESS_LOOP
INVOKE TranslateMessage,ADDR MESSAGES
INVOKE DispatchMessage,ADDR MESSAGES
JMP < MSG_LOOP
END_MESS_LOOP:
INVOKE ExitProcess,[MESSAGES.wParam]

WNDPROC FRAME HWND,UMSG,WPARAM,LPARAM
USES EBX,EDI,ESI
MOV EAX,[UMSG]
CMP EAX,WM_CLOSE
JE > ON_CLOSE
INVOKE DefWindowProc,[HWND],[UMSG],[WPARAM],[LPARAM]
RET
ON_CLOSE:
PUSH 0
CALL PostQuitMessage    ;exit via the message loop
RET
.EXIT:
XOR EAX,EAX
RET
ENDF



I get the same error when i debug these examples 1,2
The program runs however, i was just curios to what may cause the error.

donkey

Have you tried a different debugger to see if the error might be thrown by something GoBug is doing ? It would appear to be a system API call, if you could find out what module and API is executing when the error is thrown you could narrow down the candidates for a cause. Since the debugger uses various hooks to trap events and likely calls a DebugEventThread to process the events it may be making a call to an API using a cloned handle after the window is destroyed. Not the way I would do it since there is an EXIT_PROCESS_DEBUG_EVENT event that is triggered when the debugee shuts down for whatever reason but I can imagine scenarios where my GoP profiler would unintentionally use an invalid handle because the window has already been destroyed but the shutdown event has not yet been triggered.

At any rate I would run it through WinDbg or OllyDbg to see if the same error is generated and I would also check to see which module and API is executing when the error is thrown. BTW Windows does throw errors on purpose from time to time, for example page guard violations when testing memory pages before a write.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Dogim

Quote from: donkey on November 28, 2010, 05:06:43 PM
Have you tried a different debugger to see if the error might be thrown by something GoBug is doing ? It would appear to be a system API call, if you could find out what module and API is executing when the error is thrown you could narrow down the candidates for a cause. Since the debugger uses various hooks to trap events and likely calls a DebugEventThread to process the events it may be making a call to an API using a cloned handle after the window is destroyed. Not the way I would do it since there is an EXIT_PROCESS_DEBUG_EVENT event that is triggered when the debugee shuts down for whatever reason but I can imagine scenarios where my GoP profiler would unintentionally use an invalid handle because the window has already been destroyed but the shutdown event has not yet been triggered.

At any rate I would run it through WinDbg or OllyDbg to see if the same error is generated and I would also check to see which module and API is executing when the error is thrown. BTW Windows does throw errors on purpose from time to time, for example page guard violations when testing memory pages before a write.

Edgar
Hello Edgar, it seems that I'm fishing into advanced waters here : :eek, i did  run the program through OllyDbg and Gobug, both gives  the same error, sorry i have no knowledge of windbg  :red ,the only strange thing that i see on my win7 64bits system is that DefWindowProc is called likes this   401108:PUSH [EBP+20]
    40110B: PUSH [EBP+1C]
    40110E: PUSH [EBP+18]
    401111: PUSH [EBP+14]
    401114: CALL NtdllDefWindowProc_A(ntdll.dll)
from what my inexperienced n00b mind can see in Gobug, is that it looks like the error is caused or generated after te Dispatchmessage call after the window has been destroyed, but i,m (yet) to inexperienced to solve this, so for now i,m going to use the standard Window Proc, and get back at this some time in the future.

donkey

Hi Dogim,

Probably just something in the window destructor sequence is using a handle that has already been released. I would tend just to ignore it but I understand your interest in the source of the problem.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Dogim

Quote from: donkey on November 29, 2010, 10:40:40 PM
Hi Dogim,

Probably just something in the window destructor sequence is using a handle that has already been released. I would tend just to ignore it but I understand your interest in the source of the problem.

Edgar
Thanks Edgar :U

Dogim

Hello it's me again,the invalid error only comes up when i use F5 ( Single-step (trace-into) F6 ( Single-step (jump-over)  and F7 (run/trap/hook/full-log) using F8 (run/hook/part-log) and F9 (run in background) doesn't give the error, so it's definitely something gobug is doing.

donkey

Well, I ran a window application through a debugger and was able to recreate the "error". There is a call that appears to go to user32 and has 4 parameters (all on the stack as well as the call address so I'm not completely sure about the address) could be SendMessage but I doubt it. The interesting thing about where it finds the error is that just before and just after the call Windows modifies the TIB at address FS:(0xFCA). That is a very special address starting around Vista, by ORing it with 1, the call is handled as a debug safe thunk call, by ANDing it with 0xFE afterward the bit is cleared. This suggests to me that Windows is trying to do a transition between managed and unmanaged code probably for that annoying CicMarshalWnd window that I think is part of the Multilingual User Interface. I wouldn't be surprised if they wrote that in .NET. At any rate it appears that Windows simply tries to make a call to a window in debug mode, if an error is thrown then it creates the window sends a message to the MUI (registered message is "MSUIM.Msg.Private") probably to signal to the module that it should stop whatever its doing. It then goes on to shut down the thread and return control to the OS.

"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Dogim

Quote from: donkey on December 12, 2010, 01:40:46 PM
Well, I ran a window application through a debugger and was able to recreate the "error". There is a call that appears to go to user32 and has 4 parameters (all on the stack as well as the call address so I'm not completely sure about the address) could be SendMessage but I doubt it. The interesting thing about where it finds the error is that just before and just after the call Windows modifies the TIB at address FS:(0xFCA). That is a very special address starting around Vista, by ORing it with 1, the call is handled as a debug safe thunk call, by ANDing it with 0xFE afterward the bit is cleared. This suggests to me that Windows is trying to do a transition between managed and unmanaged code probably for that annoying CicMarshalWnd window that I think is part of the Multilingual User Interface. I wouldn't be surprised if they wrote that in .NET. At any rate it appears that Windows simply tries to make a call to a window in debug mode, if an error is thrown then it creates the window sends a message to the MUI (registered message is "MSUIM.Msg.Private") probably to signal to the module that it should stop whatever its doing. It then goes on to shut down the thread and return control to the OS.


Hmmmm to advanced for me  :red, but whatever its doing its doing it only when the debugger is single stepping,running the program in the background does not throw the error.
This is very interesting, thanks for taking the time to figure things out, it seems i got a lot to learn :bg