2-4
/*
* Error.c
*
* Sample code for "Multithreading Applications in Win32"
* This is from Chapter 2, Listing 2-4
*
* Demonstrate ExitThread
*/
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "MtVerify.h"
DWORD WINAPI ThreadFunc(LPVOID);
int main()
{
HANDLE hThrd;
DWORD exitCode = 0;
DWORD threadId;
MTVERIFY( hThrd = CreateThread(NULL,
0,
ThreadFunc,
(LPVOID)1,
0,
&threadId )
);
if (hThrd)
printf("Thread launched\n");
MTVERIFY( CloseHandle(hThrd) );
for(;;)
{
BOOL rc;
MTVERIFY( rc = GetExitCodeThread(hThrd, &exitCode) );
if (rc || exitCode != STILL_ACTIVE )
break;
}
printf("Thread returned %d\n", exitCode);
return EXIT_SUCCESS;
}
DWORD WINAPI ThreadFunc(LPVOID n)
{
printf("Thread running\n");
return 0;
}
od
00401000 /$ 81EC 10010000 sub esp, 110
00401006 |. 53 push ebx
00401007 |. 56 push esi
00401008 |. 8D4424 14 lea eax, dword ptr [esp+14]
0040100C |. 57 push edi
0040100D |. 50 push eax ; /pThreadId
0040100E |. 6A 00 push 0 ; |CreationFlags = 0
00401010 |. 6A 01 push 1 ; |pThreadParm = 00000001
00401012 |. 68 20124000 push 00401220 ; |ThreadFunction = Error.00401220
00401017 |. 6A 00 push 0 ; |StackSize = 0
00401019 |. 6A 00 push 0 ; |pSecurity = NULL
0040101B |. C74424 28 000>mov dword ptr [esp+28], 0 ; |
00401023 |. FF15 1C204000 call dword ptr [<&KERNEL32.CreateThre>; \CreateThread
00401029 |. 8BF0 mov esi, eax
0040102B |. 85F6 test esi, esi
0040102D |. 75 7B jnz short 004010AA
0040102F |. FF15 18204000 call dword ptr [<&KERNEL32.GetLastErr>; [GetLastError
00401035 |. 56 push esi ; /Arguments
00401036 |. 8D4C24 10 lea ecx, dword ptr [esp+10] ; |
0040103A |. 56 push esi ; |BufSize
0040103B |. 51 push ecx ; |Buffer
0040103C |. 56 push esi ; |LanguageId
0040103D |. 50 push eax ; |MessageId
0040103E |. 56 push esi ; |pSource
0040103F |. 68 00110000 push 1100 ; |Flags = ALLOCATE_BUFFER|FROM_SYSTEM|0
00401044 |. FF15 14204000 call dword ptr [<&KERNEL32.FormatMess>; \FormatMessageA
0040104A |. 8B5424 0C mov edx, dword ptr [esp+C]
0040104E |. 8D4424 1C lea eax, dword ptr [esp+1C]
00401052 |. 52 push edx ; /<%s>
00401053 |. 68 C4304000 push 004030C4 ; |<%s> = "hThrd = CreateThread(NULL, 0, ThreadFunc, (LPVOID)1, 0, &threadId )"
00401058 |. 68 BC304000 push 004030BC ; |<%s> = "Error.c"
0040105D |. 6A 1E push 1E ; |<%d> = 1E (30.)
0040105F |. 68 78304000 push 00403078 ; |Format = LF,"The following call failed at line %d in %s:",LF,LF," %s",LF,LF,"Reason: %s",LF,""
00401064 |. 50 push eax ; |s
00401065 |. FF15 60204000 call dword ptr [<&USER32.wsprintfA>] ; \wsprintfA
0040106B |. 83C4 18 add esp, 18
0040106E |. 8D4C24 14 lea ecx, dword ptr [esp+14]
00401072 |. 8D7C24 1C lea edi, dword ptr [esp+1C]
00401076 |. 33C0 xor eax, eax
00401078 |. 56 push esi ; /pOverlapped
00401079 |. 51 push ecx ; |pBytesWritten
0040107A |. 83C9 FF or ecx, FFFFFFFF ; |
0040107D |. 8D5424 24 lea edx, dword ptr [esp+24] ; |
00401081 |. F2:AE repne scas byte ptr es:[edi] ; |
00401083 |. F7D1 not ecx ; |
00401085 |. 49 dec ecx ; |
00401086 |. 51 push ecx ; |nBytesToWrite
00401087 |. 52 push edx ; |Buffer
00401088 |. 6A F4 push -0C ; |/DevType = STD_ERROR_HANDLE
0040108A |. FF15 10204000 call dword ptr [<&KERNEL32.GetStdHand>; |\GetStdHandle
00401090 |. 50 push eax ; |hFile
00401091 |. FF15 0C204000 call dword ptr [<&KERNEL32.WriteFile>>; \WriteFile
00401097 |. 68 B80B0000 push 0BB8 ; /Timeout = 3000. ms
0040109C |. FF15 08204000 call dword ptr [<&KERNEL32.Sleep>] ; \Sleep
004010A2 |. 6A 01 push 1 ; /status = 1
004010A4 |. FF15 2C204000 call dword ptr [<&MSVCRTD.exit>] ; \exit
004010AA |> 8B1D 28204000 mov ebx, dword ptr [<&MSVCRTD.printf>; MSVCRTD.printf
004010B0 |. 68 64304000 push 00403064 ; /format = "Thread launched",LF,""
004010B5 |. FFD3 call ebx ; \printf
004010B7 |. 83C4 04 add esp, 4
004010BA |. 56 push esi ; /hObject
004010BB |. FF15 04204000 call dword ptr [<&KERNEL32.CloseHandl>; \CloseHandle
004010C1 |. 85C0 test eax, eax
004010C3 |. 0F85 80000000 jnz 00401149
004010C9 |. FF15 18204000 call dword ptr [<&KERNEL32.GetLastErr>; [GetLastError
004010CF |. 6A 00 push 0 ; /Arguments = NULL
004010D1 |. 8D4C24 10 lea ecx, dword ptr [esp+10] ; |
004010D5 |. 6A 00 push 0 ; |BufSize = 0
004010D7 |. 51 push ecx ; |Buffer
004010D8 |. 6A 00 push 0 ; |LanguageId = 0 (LANG_NEUTRAL)
004010DA |. 50 push eax ; |MessageId
004010DB |. 6A 00 push 0 ; |pSource = NULL
004010DD |. 68 00110000 push 1100 ; |Flags = ALLOCATE_BUFFER|FROM_SYSTEM|0
004010E2 |. FF15 14204000 call dword ptr [<&KERNEL32.FormatMess>; \FormatMessageA
004010E8 |. 8B5424 0C mov edx, dword ptr [esp+C]
004010EC |. 8D4424 1C lea eax, dword ptr [esp+1C]
004010F0 |. 52 push edx ; /<%s>
004010F1 |. 68 50304000 push 00403050 ; |<%s> = "CloseHandle(hThrd)"
004010F6 |. 68 BC304000 push 004030BC ; |<%s> = "Error.c"
004010FB |. 6A 22 push 22 ; |<%d> = 22 (34.)
004010FD |. 68 78304000 push 00403078 ; |Format = LF,"The following call failed at line %d in %s:",LF,LF," %s",LF,LF,"Reason: %s",LF,""
00401102 |. 50 push eax ; |s
00401103 |. FF15 60204000 call dword ptr [<&USER32.wsprintfA>] ; \wsprintfA
00401109 |. 83C4 18 add esp, 18
0040110C |. 8D4C24 14 lea ecx, dword ptr [esp+14]
00401110 |. 8D7C24 1C lea edi, dword ptr [esp+1C]
00401114 |. 33C0 xor eax, eax
00401116 |. 6A 00 push 0 ; /pOverlapped = NULL
00401118 |. 51 push ecx ; |pBytesWritten
00401119 |. 83C9 FF or ecx, FFFFFFFF ; |
0040111C |. 8D5424 24 lea edx, dword ptr [esp+24] ; |
00401120 |. F2:AE repne scas byte ptr es:[edi] ; |
00401122 |. F7D1 not ecx ; |
00401124 |. 49 dec ecx ; |
00401125 |. 51 push ecx ; |nBytesToWrite
00401126 |. 52 push edx ; |Buffer
00401127 |. 6A F4 push -0C ; |/DevType = STD_ERROR_HANDLE
00401129 |. FF15 10204000 call dword ptr [<&KERNEL32.GetStdHand>; |\GetStdHandle
0040112F |. 50 push eax ; |hFile
00401130 |. FF15 0C204000 call dword ptr [<&KERNEL32.WriteFile>>; \WriteFile
00401136 |. 68 B80B0000 push 0BB8 ; /Timeout = 3000. ms
0040113B |. FF15 08204000 call dword ptr [<&KERNEL32.Sleep>] ; \Sleep
00401141 |. 6A 01 push 1 ; /status = 1
00401143 |. FF15 2C204000 call dword ptr [<&MSVCRTD.exit>] ; \exit
00401149 |> 8B3D 00204000 mov edi, dword ptr [<&KERNEL32.GetEx>; kernel32.GetExitCodeThread
0040114F |. 8D4424 10 lea eax, dword ptr [esp+10]
00401153 |. 50 push eax ; /pExitCode
00401154 |. 56 push esi ; |hThread
00401155 |. FFD7 call edi ; \GetExitCodeThread
00401157 |. 85C0 test eax, eax
00401159 |. 74 21 je short 0040117C
0040115B |> 8B4424 10 /mov eax, dword ptr [esp+10]
0040115F |. 0F85 97000000 |jnz 004011FC
00401165 |. 3D 03010000 |cmp eax, 103
0040116A |. 0F85 8C000000 |jnz 004011FC
00401170 |. 8D4C24 10 |lea ecx, dword ptr [esp+10]
00401174 |. 51 |push ecx
00401175 |. 56 |push esi
00401176 |. FFD7 |call edi
00401178 |. 85C0 |test eax, eax
0040117A |.^ 75 DF \jnz short 0040115B
0040117C |> FF15 18204000 call dword ptr [<&KERNEL32.GetLastErr>; [GetLastError
00401182 |. 6A 00 push 0 ; /Arguments = NULL
00401184 |. 8D5424 10 lea edx, dword ptr [esp+10] ; |
00401188 |. 6A 00 push 0 ; |BufSize = 0
0040118A |. 52 push edx ; |Buffer
0040118B |. 6A 00 push 0 ; |LanguageId = 0 (LANG_NEUTRAL)
0040118D |. 50 push eax ; |MessageId
0040118E |. 6A 00 push 0 ; |pSource = NULL
00401190 |. 68 00110000 push 1100 ; |Flags = ALLOCATE_BUFFER|FROM_SYSTEM|0
00401195 |. FF15 14204000 call dword ptr [<&KERNEL32.FormatMess>; \FormatMessageA
0040119B |. 8B4424 0C mov eax, dword ptr [esp+C]
0040119F |. 8D4C24 1C lea ecx, dword ptr [esp+1C]
004011A3 |. 50 push eax ; /<%s>
004011A4 |. 68 24304000 push 00403024 ; |<%s> = "rc = GetExitCodeThread(hThrd, &exitCode)"
004011A9 |. 68 BC304000 push 004030BC ; |<%s> = "Error.c"
004011AE |. 6A 27 push 27 ; |<%d> = 27 (39.)
004011B0 |. 68 78304000 push 00403078 ; |Format = LF,"The following call failed at line %d in %s:",LF,LF," %s",LF,LF,"Reason: %s",LF,""
004011B5 |. 51 push ecx ; |s
004011B6 |. FF15 60204000 call dword ptr [<&USER32.wsprintfA>] ; \wsprintfA
004011BC |. 8D7C24 34 lea edi, dword ptr [esp+34]
004011C0 |. 83C9 FF or ecx, FFFFFFFF
004011C3 |. 33C0 xor eax, eax
004011C5 |. 83C4 18 add esp, 18
004011C8 |. F2:AE repne scas byte ptr es:[edi]
004011CA |. F7D1 not ecx
004011CC |. 8D5424 14 lea edx, dword ptr [esp+14]
004011D0 |. 6A 00 push 0 ; /pOverlapped = NULL
004011D2 |. 49 dec ecx ; |
004011D3 |. 52 push edx ; |pBytesWritten
004011D4 |. 8D4424 24 lea eax, dword ptr [esp+24] ; |
004011D8 |. 51 push ecx ; |nBytesToWrite
004011D9 |. 50 push eax ; |Buffer
004011DA |. 6A F4 push -0C ; |/DevType = STD_ERROR_HANDLE
004011DC |. FF15 10204000 call dword ptr [<&KERNEL32.GetStdHand>; |\GetStdHandle
004011E2 |. 50 push eax ; |hFile
004011E3 |. FF15 0C204000 call dword ptr [<&KERNEL32.WriteFile>>; \WriteFile
004011E9 |. 68 B80B0000 push 0BB8 ; /Timeout = 3000. ms
004011EE |. FF15 08204000 call dword ptr [<&KERNEL32.Sleep>] ; \Sleep
004011F4 |. 6A 01 push 1 ; /status = 1
004011F6 |. FF15 2C204000 call dword ptr [<&MSVCRTD.exit>] ; \exit
004011FC |> 50 push eax
004011FD |. 68 10304000 push 00403010 ; ASCII "Thread returned %d",LF
00401202 |. FFD3 call ebx
00401204 |. 83C4 08 add esp, 8
00401207 |. 33C0 xor eax, eax
00401209 |. 5F pop edi
0040120A |. 5E pop esi
0040120B |. 5B pop ebx
0040120C |. 81C4 10010000 add esp, 110
00401212 \. C3 retn
thread
00401220 . 68 08314000 push 00403108 ; /format = "Thread running",LF,""
00401225 . FF15 28204000 call dword ptr [<&MSVCRTD.printf>] ; \printf
0040122B . 83C4 04 add esp, 4
0040122E . 33C0 xor eax, eax
00401230 . C2 0400 retn 4
ida
.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 Buffer = byte ptr -110h
.text:00401000 ExitCode = dword ptr -10Ch
.text:00401000 NumberOfBytesWritten= dword ptr -108h
.text:00401000 ThreadId = dword ptr -104h
.text:00401000 var_100 = byte ptr -100h
.text:00401000 argc = dword ptr 4
.text:00401000 argv = dword ptr 8
.text:00401000 envp = dword ptr 0Ch
.text:00401000
.text:00401000 sub esp, 110h
.text:00401006 push ebx
.text:00401007 push esi
.text:00401008 lea eax, [esp+118h+ThreadId]
.text:0040100C push edi
.text:0040100D push eax ; lpThreadId
.text:0040100E push 0 ; dwCreationFlags
.text:00401010 push 1 ; lpParameter
.text:00401012 push offset StartAddress ; lpStartAddress
.text:00401017 push 0 ; dwStackSize
.text:00401019 push 0 ; lpThreadAttributes
.text:0040101B mov [esp+134h+ExitCode], 0
.text:00401023 call ds:CreateThread
.text:00401029 mov esi, eax
.text:0040102B test esi, esi
.text:0040102D jnz short loc_4010AA
.text:0040102F call ds:GetLastError
.text:00401035 push esi ; Arguments
.text:00401036 lea ecx, [esp+120h+Buffer]
.text:0040103A push esi ; nSize
.text:0040103B push ecx ; lpBuffer
.text:0040103C push esi ; dwLanguageId
.text:0040103D push eax ; dwMessageId
.text:0040103E push esi ; lpSource
.text:0040103F push 1100h ; dwFlags
.text:00401044 call ds:FormatMessageA
.text:0040104A mov edx, dword ptr [esp+11Ch+Buffer]
.text:0040104E lea eax, [esp+11Ch+var_100]
.text:00401052 push edx
.text:00401053 push offset aHthrdCreatethr ; "hThrd = CreateThread(NULL, 0, ThreadFun"...
.text:00401058 push offset aError_c ; "Error.c"
.text:0040105D push 1Eh
.text:0040105F push offset aTheFollowingCa ; "\nThe following call failed at line %d i"...
.text:00401064 push eax ; LPSTR
.text:00401065 call ds:wsprintfA
.text:0040106B add esp, 18h
.text:0040106E lea ecx, [esp+11Ch+NumberOfBytesWritten]
.text:00401072 lea edi, [esp+11Ch+var_100]
.text:00401076 xor eax, eax
.text:00401078 push esi ; lpOverlapped
.text:00401079 push ecx ; lpNumberOfBytesWritten
.text:0040107A or ecx, 0FFFFFFFFh
.text:0040107D lea edx, [esp+124h+var_100]
.text:00401081 repne scasb
.text:00401083 not ecx
.text:00401085 dec ecx
.text:00401086 push ecx ; nNumberOfBytesToWrite
.text:00401087 push edx ; lpBuffer
.text:00401088 push 0FFFFFFF4h ; nStdHandle
.text:0040108A call ds:GetStdHandle
.text:00401090 push eax ; hFile
.text:00401091 call ds:WriteFile
.text:00401097 push 0BB8h ; dwMilliseconds
.text:0040109C call ds:Sleep
.text:004010A2 push 1 ; Code
.text:004010A4 call ds:exit
.text:004010AA ; ---------------------------------------------------------------------------
.text:004010AA
.text:004010AA loc_4010AA: ; CODE XREF: _main+2Dj
.text:004010AA mov ebx, ds:printf
.text:004010B0 push offset Format ; "Thread launched\n"
.text:004010B5 call ebx ; printf
.text:004010B7 add esp, 4
.text:004010BA push esi ; hObject
.text:004010BB call ds:CloseHandle
.text:004010C1 test eax, eax
.text:004010C3 jnz loc_401149
.text:004010C9 call ds:GetLastError
.text:004010CF push 0 ; Arguments
.text:004010D1 lea ecx, [esp+120h+Buffer]
.text:004010D5 push 0 ; nSize
.text:004010D7 push ecx ; lpBuffer
.text:004010D8 push 0 ; dwLanguageId
.text:004010DA push eax ; dwMessageId
.text:004010DB push 0 ; lpSource
.text:004010DD push 1100h ; dwFlags
.text:004010E2 call ds:FormatMessageA
.text:004010E8 mov edx, dword ptr [esp+11Ch+Buffer]
.text:004010EC lea eax, [esp+11Ch+var_100]
.text:004010F0 push edx
.text:004010F1 push offset aClosehandleHth ; "CloseHandle(hThrd)"
.text:004010F6 push offset aError_c ; "Error.c"
.text:004010FB push 22h
.text:004010FD push offset aTheFollowingCa ; "\nThe following call failed at line %d i"...
.text:00401102 push eax ; LPSTR
.text:00401103 call ds:wsprintfA
.text:00401109 add esp, 18h
.text:0040110C lea ecx, [esp+11Ch+NumberOfBytesWritten]
.text:00401110 lea edi, [esp+11Ch+var_100]
.text:00401114 xor eax, eax
.text:00401116 push 0 ; lpOverlapped
.text:00401118 push ecx ; lpNumberOfBytesWritten
.text:00401119 or ecx, 0FFFFFFFFh
.text:0040111C lea edx, [esp+124h+var_100]
.text:00401120 repne scasb
.text:00401122 not ecx
.text:00401124 dec ecx
.text:00401125 push ecx ; nNumberOfBytesToWrite
.text:00401126 push edx ; lpBuffer
.text:00401127 push 0FFFFFFF4h ; nStdHandle
.text:00401129 call ds:GetStdHandle
.text:0040112F push eax ; hFile
.text:00401130 call ds:WriteFile
.text:00401136 push 0BB8h ; dwMilliseconds
.text:0040113B call ds:Sleep
.text:00401141 push 1 ; Code
.text:00401143 call ds:exit
.text:00401149 ; ---------------------------------------------------------------------------
.text:00401149
.text:00401149 loc_401149: ; CODE XREF: _main+C3j
.text:00401149 mov edi, ds:GetExitCodeThread
.text:0040114F lea eax, [esp+11Ch+ExitCode]
.text:00401153 push eax ; lpExitCode
.text:00401154 push esi ; hThread
.text:00401155 call edi ; GetExitCodeThread
.text:00401157 test eax, eax
.text:00401159 jz short loc_40117C
.text:0040115B
.text:0040115B loc_40115B: ; CODE XREF: _main+17Aj
.text:0040115B mov eax, [esp+11Ch+ExitCode]
.text:0040115F jnz loc_4011FC
.text:00401165 cmp eax, 103h
.text:0040116A jnz loc_4011FC
.text:00401170 lea ecx, [esp+11Ch+ExitCode]
.text:00401174 push ecx ; lpExitCode
.text:00401175 push esi ; hThread
.text:00401176 call edi ; GetExitCodeThread
.text:00401178 test eax, eax
.text:0040117A jnz short loc_40115B
.text:0040117C
.text:0040117C loc_40117C: ; CODE XREF: _main+159j
.text:0040117C call ds:GetLastError
.text:00401182 push 0 ; Arguments
.text:00401184 lea edx, [esp+120h+Buffer]
.text:00401188 push 0 ; nSize
.text:0040118A push edx ; lpBuffer
.text:0040118B push 0 ; dwLanguageId
.text:0040118D push eax ; dwMessageId
.text:0040118E push 0 ; lpSource
.text:00401190 push 1100h ; dwFlags
.text:00401195 call ds:FormatMessageA
.text:0040119B mov eax, dword ptr [esp+11Ch+Buffer]
.text:0040119F lea ecx, [esp+11Ch+var_100]
.text:004011A3 push eax
.text:004011A4 push offset aRcGetexitcodet ; "rc = GetExitCodeThread(hThrd, &exitCode"...
.text:004011A9 push offset aError_c ; "Error.c"
.text:004011AE push 27h
.text:004011B0 push offset aTheFollowingCa ; "\nThe following call failed at line %d i"...
.text:004011B5 push ecx ; LPSTR
.text:004011B6 call ds:wsprintfA
.text:004011BC lea edi, [esp+134h+var_100]
.text:004011C0 or ecx, 0FFFFFFFFh
.text:004011C3 xor eax, eax
.text:004011C5 add esp, 18h
.text:004011C8 repne scasb
.text:004011CA not ecx
.text:004011CC lea edx, [esp+11Ch+NumberOfBytesWritten]
.text:004011D0 push 0 ; lpOverlapped
.text:004011D2 dec ecx
.text:004011D3 push edx ; lpNumberOfBytesWritten
.text:004011D4 lea eax, [esp+124h+var_100]
.text:004011D8 push ecx ; nNumberOfBytesToWrite
.text:004011D9 push eax ; lpBuffer
.text:004011DA push 0FFFFFFF4h ; nStdHandle
.text:004011DC call ds:GetStdHandle
.text:004011E2 push eax ; hFile
.text:004011E3 call ds:WriteFile
.text:004011E9 push 0BB8h ; dwMilliseconds
.text:004011EE call ds:Sleep
.text:004011F4 push 1 ; Code
.text:004011F6 call ds:exit
.text:004011FC ; ---------------------------------------------------------------------------
.text:004011FC
.text:004011FC loc_4011FC: ; CODE XREF: _main+15Fj
.text:004011FC ; _main+16Aj
.text:004011FC push eax
.text:004011FD push offset aThreadReturned ; "Thread returned %d\n"
.text:00401202 call ebx ; printf
.text:00401204 add esp, 8
.text:00401207 xor eax, eax
.text:00401209 pop edi
.text:0040120A pop esi
.text:0040120B pop ebx
.text:0040120C add esp, 110h
.text:00401212 retn
.text:00401212 _main endp
.text:00401212
.text:00401212 ; ---------------------------------------------------------------------------
.text:00401213 align 10h
.text:00401220
thread
.text:00401220
.text:00401220 ; =============== S U B R O U T I N E =======================================
.text:00401220
.text:00401220
.text:00401220 ; DWORD __stdcall StartAddress(LPVOID)
.text:00401220 StartAddress proc near ; DATA XREF: _main+12o
.text:00401220 push offset aThreadRunning ; "Thread running\n"
.text:00401225 call ds:printf
.text:0040122B add esp, 4
.text:0040122E xor eax, eax
.text:00401230 retn 4
.text:00401230 StartAddress endp
.text:00401230
.text:00401230 ; ---------------------------------------------------------------------------