/*
* ExitCode.c
*
* Sample code for "Multithreading Applications in Win32"
* This is from Chapter 2, Listing 2-2
*
* Start two threads and try to exit
* when the user presses a key.
*/
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
DWORD WINAPI ThreadFunc(LPVOID);
int main()
{
HANDLE hThrd1;
HANDLE hThrd2;
DWORD exitCode1 = 0;
DWORD exitCode2 = 0;
DWORD threadId;
hThrd1 = CreateThread(NULL,
0,
ThreadFunc,
(LPVOID)1,
0,
&threadId );
if (hThrd1)
printf("Thread 1 launched\n");
hThrd2 = CreateThread(NULL,
0,
ThreadFunc,
(LPVOID)2,
0,
&threadId );
if (hThrd2)
printf("Thread 2 launched\n");
// Keep waiting until both calls to
// GetExitCodeThread succeed AND
// neither of them returns STILL_ACTIVE.
// This method is not optimal - we'll
// see the correct way in Chapter 3.
for (;;)
{
printf("Press any key to exit..\n");
getch();
GetExitCodeThread(hThrd1, &exitCode1);
GetExitCodeThread(hThrd2, &exitCode2);
if ( exitCode1 == STILL_ACTIVE )
puts("Thread 1 is still running!");
if ( exitCode2 == STILL_ACTIVE )
puts("Thread 2 is still running!");
if ( exitCode1 != STILL_ACTIVE
&& exitCode2 != STILL_ACTIVE )
break;
}
CloseHandle(hThrd1);
CloseHandle(hThrd2);
printf("Thread 1 returned %d\n", exitCode1);
printf("Thread 2 returned %d\n", exitCode2);
return EXIT_SUCCESS;
}
/*
* Take the startup value, do some simple math on it,
* and return the calculated value.
*/
DWORD WINAPI ThreadFunc(LPVOID n)
{
Sleep((DWORD)n*1000*2);
return (DWORD)n * 10;
}
od
00401000 /$ 83EC 0C sub esp, 0C
00401003 |. 53 push ebx
00401004 |. 55 push ebp
00401005 |. 56 push esi
00401006 |. 8B35 04204000 mov esi, dword ptr [<&KERNEL32.Creat>; kernel32.CreateThread
0040100C |. 57 push edi
0040100D |. 8D4424 18 lea eax, dword ptr [esp+18]
00401011 |. 33FF xor edi, edi
00401013 |. 50 push eax ; /pThreadId
00401014 |. 57 push edi ; |CreationFlags => 0
00401015 |. 6A 01 push 1 ; |pThreadParm = 00000001
00401017 |. 68 00114000 push 00401100 ; |ThreadFunction = ExitCode.00401100
0040101C |. 57 push edi ; |StackSize => 0
0040101D |. 57 push edi ; |pSecurity => NULL
0040101E |. 897C24 28 mov dword ptr [esp+28], edi ; |
00401022 |. 897C24 2C mov dword ptr [esp+2C], edi ; |
00401026 |. FFD6 call esi ; \CreateThread
00401028 |. 8B2D 18204000 mov ebp, dword ptr [<&MSVCRTD.printf>; MSVCRTD.printf
0040102E |. 8BD8 mov ebx, eax
00401030 |. 3BDF cmp ebx, edi ; 创建成功
00401032 |. 74 0A je short 0040103E
00401034 |. 68 A8304000 push 004030A8 ; /format = "Thread 1 launched",LF,""
00401039 |. FFD5 call ebp ; \printf
0040103B |. 83C4 04 add esp, 4
0040103E |> 8D4C24 18 lea ecx, dword ptr [esp+18]
00401042 |. 51 push ecx
00401043 |. 57 push edi
00401044 |. 6A 02 push 2
00401046 |. 68 00114000 push 00401100
0040104B |. 57 push edi
0040104C |. 57 push edi
0040104D |. FFD6 call esi ; CreateThread
0040104F |. 8BF8 mov edi, eax
00401051 |. 85FF test edi, edi
00401053 |. 74 0A je short 0040105F
00401055 |. 68 94304000 push 00403094 ; ASCII "Thread 2 launched",LF
0040105A |. FFD5 call ebp
0040105C |. 83C4 04 add esp, 4
0040105F |> 8B35 00204000 mov esi, dword ptr [<&KERNEL32.GetEx>; kernel32.GetExitCodeThread
00401065 |> 68 78304000 /push 00403078 ; ASCII "Press any key to exit..",LF
0040106A |. FFD5 |call ebp ; Printf
0040106C |. 83C4 04 |add esp, 4
0040106F |. FF15 50204000 |call dword ptr [<&MSVCRTD._getch>] ; [_getch
00401075 |. 8D5424 10 |lea edx, dword ptr [esp+10] ; hThrd1
00401079 |. 52 |push edx
0040107A |. 53 |push ebx
0040107B |. FFD6 |call esi ; kernel32.GetExitCodeThread
0040107D |. 8D4424 14 |lea eax, dword ptr [esp+14] ; hThrd2
00401081 |. 50 |push eax
00401082 |. 57 |push edi
00401083 |. FFD6 |call esi ; kernel32.GetExitCodeThread
00401085 |. 8B4C24 10 |mov ecx, dword ptr [esp+10]
00401089 |. B8 03010000 |mov eax, 103 ; STILL_ACTIVE
0040108E |. 3BC8 |cmp ecx, eax
00401090 |. 75 13 |jnz short 004010A5
00401092 |. 68 5C304000 |push 0040305C ; /s = "Thread 1 is still running!"
00401097 |. FF15 14204000 |call dword ptr [<&MSVCRTD.puts>] ; \puts
0040109D |. 83C4 04 |add esp, 4
004010A0 |. B8 03010000 |mov eax, 103 ; STILL_ACTIVE
004010A5 |> 394424 14 |cmp dword ptr [esp+14], eax
004010A9 |. 75 13 |jnz short 004010BE
004010AB |. 68 40304000 |push 00403040 ; /s = "Thread 2 is still running!"
004010B0 |. FF15 14204000 |call dword ptr [<&MSVCRTD.puts>] ; \puts
004010B6 |. 83C4 04 |add esp, 4
004010B9 |. B8 03010000 |mov eax, 103
004010BE |> 394424 10 |cmp dword ptr [esp+10], eax
004010C2 |.^ 74 A1 |je short 00401065
004010C4 |. 394424 14 |cmp dword ptr [esp+14], eax
004010C8 |.^ 74 9B \je short 00401065
004010CA |. 8B35 0C204000 mov esi, dword ptr [<&KERNEL32.Close>; kernel32.CloseHandle
004010D0 |. 53 push ebx ; /hObject
004010D1 |. FFD6 call esi ; \CloseHandle
004010D3 |. 57 push edi ; /hObject
004010D4 |. FFD6 call esi ; \CloseHandle
004010D6 |. 8B4C24 10 mov ecx, dword ptr [esp+10]
004010DA |. 51 push ecx
004010DB |. 68 28304000 push 00403028 ; ASCII "Thread 1 returned %d",LF
004010E0 |. FFD5 call ebp
004010E2 |. 8B5424 1C mov edx, dword ptr [esp+1C]
004010E6 |. 52 push edx
004010E7 |. 68 10304000 push 00403010 ; ASCII "Thread 2 returned %d",LF
004010EC |. FFD5 call ebp
004010EE |. 83C4 10 add esp, 10
004010F1 |. 33C0 xor eax, eax
004010F3 |. 5F pop edi
004010F4 |. 5E pop esi
004010F5 |. 5D pop ebp
004010F6 |. 5B pop ebx
004010F7 |. 83C4 0C add esp, 0C
004010FA \. C3 retn
thread
00401100 . 56 push esi
00401101 . 8B7424 08 mov esi, dword ptr [esp+8]
00401105 . 8D04B6 lea eax, dword ptr [esi+esi*4] ; eax=esi*5
00401108 . 8D0480 lea eax, dword ptr [eax+eax*4] ; eax=eax*5
0040110B . 8D0480 lea eax, dword ptr [eax+eax*4] ; eax=eax*5
0040110E . C1E0 04 shl eax, 4 ; 左移四位
00401111 . 50 push eax ; /Timeout
00401112 . FF15 08204000 call dword ptr [<&KERNEL32.Sleep>] ; \Sleep
00401118 . 8D04B6 lea eax, dword ptr [esi+esi*4] ; eax=esi*5
0040111B . 5E pop esi
0040111C . D1E0 shl eax, 1 ; eax左移一位
0040111E . C2 0400 retn 4
ida
.text:00401000
.text:00401000 ; =============== S U B R O U T I N E =======================================
.text:00401000
.text:00401000
.text:00401000 ; int __cdecl main(int argc, const char **argv, const char *envp)
.text:00401000 _main proc near ; CODE XREF: start+FAp
.text:00401000
.text:00401000 ExitCode = dword ptr -0Ch
.text:00401000 ExitCode1 = dword ptr -8
.text:00401000 ThreadId = dword ptr -4
.text:00401000 argc = dword ptr 4
.text:00401000 argv = dword ptr 8
.text:00401000 envp = dword ptr 0Ch
.text:00401000
.text:00401000 sub esp, 0Ch
.text:00401003 push ebx
.text:00401004 push ebp
.text:00401005 push esi
.text:00401006 mov esi, ds:CreateThread
.text:0040100C push edi
.text:0040100D lea eax, [esp+1Ch+ThreadId]
.text:00401011 xor edi, edi ; edi=0
.text:00401013 push eax ; lpThreadId
.text:00401014 push edi ; dwCreationFlags
.text:00401015 push 1 ; lpParameter
.text:00401017 push offset StartAddress ; lpStartAddress
.text:0040101C push edi ; dwStackSize
.text:0040101D push edi ; lpThreadAttributes
.text:0040101E mov [esp+34h+ExitCode], edi
.text:00401022 mov [esp+34h+ExitCode1], edi
.text:00401026 call esi ; CreateThread
.text:00401028 mov ebp, ds:printf
.text:0040102E mov ebx, eax
.text:00401030 cmp ebx, edi
.text:00401032 jz short loc_40103E
.text:00401034 push offset Format ; "Thread 1 launched\n"
.text:00401039 call ebp ; printf
.text:0040103B add esp, 4
.text:0040103E
.text:0040103E loc_40103E: ; CODE XREF: _main+32j
.text:0040103E lea ecx, [esp+1Ch+ThreadId]
.text:00401042 push ecx ; lpThreadId
.text:00401043 push edi ; dwCreationFlags
.text:00401044 push 2 ; lpParameter
.text:00401046 push offset StartAddress ; lpStartAddress
.text:0040104B push edi ; dwStackSize
.text:0040104C push edi ; lpThreadAttributes
.text:0040104D call esi ; CreateThread
.text:0040104F mov edi, eax
.text:00401051 test edi, edi
.text:00401053 jz short loc_40105F
.text:00401055 push offset aThread2Launche ; "Thread 2 launched\n"
.text:0040105A call ebp ; printf
.text:0040105C add esp, 4
.text:0040105F
.text:0040105F loc_40105F: ; CODE XREF: _main+53j
.text:0040105F mov esi, ds:GetExitCodeThread
.text:00401065
.text:00401065 loc_401065: ; CODE XREF: _main+C2j
.text:00401065 ; _main+C8j
.text:00401065 push offset aPressAnyKeyToE ; "Press any key to exit..\n"
.text:0040106A call ebp ; printf
.text:0040106C add esp, 4
.text:0040106F call ds:_getch
.text:00401075 lea edx, [esp+1Ch+ExitCode]
.text:00401079 push edx ; lpExitCode
.text:0040107A push ebx ; hThread
.text:0040107B call esi ; GetExitCodeThread
.text:0040107D lea eax, [esp+1Ch+ExitCode1]
.text:00401081 push eax ; lpExitCode
.text:00401082 push edi ; hThread
.text:00401083 call esi ; GetExitCodeThread
.text:00401085 mov ecx, [esp+1Ch+ExitCode]
.text:00401089 mov eax, STILL_ACTIVE
.text:0040108E cmp ecx, eax
.text:00401090 jnz short loc_4010A5
.text:00401092 push offset Str ; "Thread 1 is still running!"
.text:00401097 call ds:puts
.text:0040109D add esp, 4
.text:004010A0 mov eax, STILL_ACTIVE
.text:004010A5
.text:004010A5 loc_4010A5: ; CODE XREF: _main+90j
.text:004010A5 cmp [esp+1Ch+ExitCode1], eax
.text:004010A9 jnz short loc_4010BE
.text:004010AB push offset aThread2IsStill ; "Thread 2 is still running!"
.text:004010B0 call ds:puts
.text:004010B6 add esp, 4
.text:004010B9 mov eax, STILL_ACTIVE
.text:004010BE
.text:004010BE loc_4010BE: ; CODE XREF: _main+A9j
.text:004010BE cmp [esp+1Ch+ExitCode], eax
.text:004010C2 jz short loc_401065
.text:004010C4 cmp [esp+1Ch+ExitCode1], eax
.text:004010C8 jz short loc_401065
.text:004010CA mov esi, ds:CloseHandle
.text:004010D0 push ebx ; hObject
.text:004010D1 call esi ; CloseHandle
.text:004010D3 push edi ; hObject
.text:004010D4 call esi ; CloseHandle
.text:004010D6 mov ecx, [esp+1Ch+ExitCode]
.text:004010DA push ecx
.text:004010DB push offset aThread1Returne ; "Thread 1 returned %d\n"
.text:004010E0 call ebp ; printf
.text:004010E2 mov edx, [esp+24h+ExitCode1]
.text:004010E6 push edx
.text:004010E7 push offset aThread2Returne ; "Thread 2 returned %d\n"
.text:004010EC call ebp ; printf
.text:004010EE add esp, 10h
.text:004010F1 xor eax, eax
.text:004010F3 pop edi
.text:004010F4 pop esi
.text:004010F5 pop ebp
.text:004010F6 pop ebx
.text:004010F7 add esp, 0Ch
.text:004010FA retn
.text:004010FA _main endp
.text:004010FA
.text:004010FA ; ---------------------------------------------------------------------------
.text:004010FB align 10h
.text:00401100
.text:00401100 ; =============== S U B R O U T I N E =======================================
.text:00401100
.text:00401100
thread
.text:00401100
.text:00401100 ; =============== S U B R O U T I N E =======================================
.text:00401100
.text:00401100
.text:00401100 ; DWORD __stdcall StartAddress(LPVOID)
.text:00401100 StartAddress proc near ; DATA XREF: _main+17o
.text:00401100 ; _main+46o
.text:00401100
.text:00401100 argn = dword ptr 4
.text:00401100
.text:00401100 push esi
.text:00401101 mov esi, [esp+4+argn]
.text:00401105 lea eax, [esi+esi*4]
.text:00401108 lea eax, [eax+eax*4]
.text:0040110B lea eax, [eax+eax*4]
.text:0040110E shl eax, 4
.text:00401111 push eax ; dwMilliseconds
.text:00401112 call ds:Sleep
.text:00401118 lea eax, [esi+esi*4]
.text:0040111B pop esi
.text:0040111C shl eax, 1
.text:0040111E retn 4
.text:0040111E StartAddress endp
.text:0040111E
.text:0040111E ; ---------------------------------------------------------------------------