CreateEvent
proto lpEventAttributes:DWORD,\
bManualReset:DWORD,\
bInitialState:DWORD,\
lpName:DWORD
lpEventAttribute-->
If you specify NULL value, the event object is created with default security
descriptor.
bManualReset-->
If you want Windows to automatically reset the event object to nonsignalled
state after WaitForSingleObject call, you must specify FALSE as this parameter.
Else you must manually reset the event object with the call to ResetEvent.
bInitialState-->
If you want the event object to be created in the signalled state, specify
TRUE as this parameter else the event object will be created in the nonsignalled
state.
lpName-->
Pointer to an ASCIIZ string that is the name of the event object. This
name is used when you want to call OpenEvent.
If
the call is successful, it returns the handle to the newly created event
object else it returns NULL.
You
can modify the state of an event object with two API calls: SetEvent and
ResetEvent. SetEvent function sets the event object into signalled state.
ResetEvent does the reverse.
When
the event object is created, you must put the call to WaitForSingleObject
in the thread that wants to watch for the state of the event object. WaitForSingleObject
has the following syntax:
WaitForSingleObject proto hObject:DWORD, dwTimeout:DWORD
hObject
--> A handle to one of the synchronization object. Event object is a type
of synchronization object.
dwTimeout
-->
specify the time in milliseconds that this function will wait for the object
to be in signalled state. If the specified time has passed and the event
object is still in nonsignalled state, WaitForSingleObject returns the
the caller. If you want to wait for the object indefinitely, you must specify
the value INFINITE as this parameter.
___________________________________________________________________________________
;
Equates:
[M00_Menu
2000
M00_Thread 2001
M00_Run_Thread 2002
M00_Stop_Thread
2003 M00_Exit
2004]
[WM_FINISH
0500] ; WM_USER + 0100
_____________________________________________________________________________________
;
Data:
[WindowHandle:
0 ExitCode: 0 MenuHandle: 0 ThreadID: 0 EventStartHandle:
0
ThreadHandle:
0 EventStop: B§ 0
ClassName:
'Win32ASMThreadClass' 0 AppName: 'Win32 ASM Event Example'
0
SuccessString:
'The calculation is completed!' 0 StopString: 'The thread is stopped'
0]
______________________________________________________________________________________
; Window Class Structure:
[WindowClassEx:
wc_Size: len wc_style:
&CS_HREDRAW+&CS_VREDRAW WndProc: MainWindowProc
wc_ClsExtra: 0 wc_WndExtra: 0
hInstance: 0
wc_hIcon: 0
wc_hCursor: 0
wc_hbrBackground: 6
wc_MenuName: M00_Menu wc_ClassName: ClassName
wc_hIconSm: 0]
[FirstMessage: 0 #7]
Main:
call 'Kernel32.GetModuleHandleA' &NULL | mov D§hInstance
eax
call 'User32.LoadIconA' 0 &IDI_WINLOGO | mov D§wc_hIcon
eax D§wc_hIconSm eax
call 'User32.LoadCursorA' 0 &IDC_ARROW | mov D§wc_hCursor
eax
call 'User32.RegisterClassExA' WindowClassEX
call 'User32.CreateWindowExA' &NULL ClassName AppName,
&WS_OVERLAPPEDWINDOW,
&CW_USEDEFAULT &CW_USEDEFAULT 300 200,
&NULL &NULL D§hInstance &NULL
mov D§WindowHandle eax
call 'User32.ShowWindow' D§WindowHandle &SW_SHOWNORMAL
call 'User32.UpdateWindow' D§WindowHandle
call 'User32.GetMenu' D§WindowHandle
mov D§MenuHandle eax
L1:
call 'User32.GetMessageA' FirstMessage 0 0 0 | cmp eax 0 | je L9>
call 'User32.TranslateMessage' FirstMessage
call 'User32.DispatchMessageA' FirstMessage
jmp L1<
L9: call 'Kernel32.ExitProcess' 0
____________________________________________________________________________________________
____________________________________________________________________________________________
Proc
MainWindowProc:
Arguments @Adressee, @Message, @wParam, @lParam
pushad
.If D@Message = &WM_DESTROY
call 'User32.PostQuitMessage' &NULL
.Else_If D@Message = &WM_CREATE
call 'Kernel32.CreateEventA' &NULL &FALSE &FALSE &NULL
mov D§EventStartHandle eax
call 'Kernel32.CreateThread' &NULL &NULL ThreadProc &NULL,
&NORMAL_PRIORITY_CLASS ThreadID
mov D§ThreadHandle eax
.Else_If D@Message = &WM_COMMAND
mov eax D@wParam
..If D@lParam = 0
...If ax = M00_Run_Thread
call 'Kernel32.SetEvent' D§EventStartHandle
call 'User32.EnableMenuItem' D§MenuHandle M00_Run_Thread
&MF_GRAYED
call 'User32.EnableMenuItem' D§MenuHandle M00_Stop_Thread &MF_ENABLED
...Else_If ax = M00_Stop_Thread
mov B§EventStop &TRUE
call 'User32.EnableMenuItem' D§MenuHandle M00_Run_Thread
&MF_ENABLED
call 'User32.EnableMenuItem' D§MenuHandle M00_Stop_Thread &MF_GRAYED
...Else
call 'User32.DestroyWindow' D@Adressee
...End_If
..End_If
.Else_If D@Message = WM_FINISH
call 'User32.MessageBoxA' &NULL SuccessString AppName &MB_OK
.Else
popad
call 'User32.DefWindowProcA' D@Adressee D@Message D@wParam D@lParam
Exit
.End_If
popad | mov eax &FALSE
EndP
____________________________________________________________________________________________
____________________________________________________________________________________________
ThreadProc:
call 'Kernel32.WaitForSingleObject' D§EventStartHandle &INFINITE
mov ecx 600000000
.While ecx a 0
If B§EventStop = &FALSE
add eax eax
dec ecx
Else
call 'User32.MessageBoxA' D§WindowHandle StopString AppName
&MB_OK
mov B§EventStop &FALSE
jmp ThreadProc
End_If
.End_While
call 'User32.PostMessageA' D§WindowHandle WM_FINISH
&NULL &NULL
call 'User32.EnableMenuItem' D§MenuHandle M00_Run_Thread
&MF_ENABLED
call 'User32.EnableMenuItem' D§MenuHandle M00_Stop_Thread
&MF_GRAYED
jmp ThreadProc
.Else_If D@Message = &WM_CREATE
call 'Kernel32.CreateEventA' &NULL &FALSE &FALSE &NULL
mov D§EventStartHandle eax
call 'Kernel32.CreateThread' &NULL &NULL ThreadProc &NULL,
&NORMAL_PRIORITY_CLASS ThreadID
mov D§ThreadHandle eax
You
can see that I create the event object and the thread during the processing
of WM_CREATE message. I create the event object in the nonsignalled state
with automatic reset. After the event object is created, I create the thread.
However the thread doesn't run immediately because it waits for the event
object to be in the signalled state as the code below:
ThreadProc:
call 'Kernel32.WaitForSingleObject' D§EventStartHandle &INFINITE
mov ecx 600000000
The
first line of the thread procedure is the call to WaitForSingleObject.
It waits infinitely for the signalled state of the event object before
it returns. This means that even when the thread is created, we put it
into a dormant state.
When
the user selects "run thread" command from the menu, we set the event object
into signalled state as below:
...If ax = M00_Run_Thread
call 'Kernel32.SetEvent' D§EventStartHandle
call 'User32.EnableMenuItem' D§MenuHandle M00_Run_Thread
&MF_GRAYED
call 'User32.EnableMenuItem' D§MenuHandle M00_Stop_Thread &MF_ENABLED
The
call to SetEvent turns the event object into the signalled state which
in turn makes the WaitForSingleObject call in the thread procedure return
and the thread starts running. When the user selects "stop thread" command,
we set the value of the global variable "EventStop" to TRUE.
If B§EventStop = &FALSE
add eax eax
dec ecx
Else
call 'User32.MessageBoxA' D§WindowHandle StopString AppName
&MB_OK
mov B§EventStop &FALSE
jmp ThreadProc
End_If
This
stops the thread and jumps to the WaitForSingleObject call again. Note
that we don't have to manually reset the event object into nonsignalled
state because we specify the bManualReset parameter of the CreateEvent
call as FALSE.