6-2
/*
* IoByEvnt.c
*
* Sample code for Multithreading Applications in Win32
* This is from Chapter 6, Listing 6-2
*
* Demonstrates how to use event objects instead of
* file handles to signal multiple outstanding
* overlapped operation on a file.
*/
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "MtVerify.h"
//
// Constants
//
#define MAX_REQUESTS 5
#define READ_SIZE 512
#define MAX_TRY_COUNT 5
//
// Function prototypes
//
int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount);
void CheckOsVersion();
//
// Global variables
//
// Need to keep the events in their own array
// so we can wait on them.
HANDLE ghEvents[MAX_REQUESTS];
// Keep track of each individual I/O operation
OVERLAPPED gOverlapped[MAX_REQUESTS];
// Handle to the file of interest.
HANDLE ghFile;
// Need a place to put all this data
char gBuffers[MAX_REQUESTS][READ_SIZE];
int main()
{
int i;
BOOL rc;
char szPath[MAX_PATH];
CheckOsVersion();
GetWindowsDirectory(szPath, sizeof(szPath));
strcat(szPath, "http://www.cnblogs.com/nanshouyong326/admin/file://WINHLP32.EXE/");
// Open the file for overlapped reads
ghFile = CreateFile( szPath,
GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
if (ghFile == INVALID_HANDLE_VALUE)
{
printf("Could not open %s\n", szPath);
return -1;
}
for (i=0; i<MAX_REQUESTS; i++)
{
// Read some bytes every few K
QueueRequest(i, i*16384, READ_SIZE);
}
printf("QUEUED!!\n");
// Wait for all the operations to complete.
MTVERIFY( WaitForMultipleObjects(
MAX_REQUESTS, ghEvents, TRUE, INFINITE
) != WAIT_FAILED );
// Describe what just happened.
for (i=0; i<MAX_REQUESTS; i++)
{
DWORD dwNumread;
rc = GetOverlappedResult(
ghFile,
&gOverlapped[i],
&dwNumread,
FALSE
);
printf("Read #%d returned %d. %d bytes were read.\n",
i, rc, dwNumread);
CloseHandle(gOverlapped[i].hEvent);
}
CloseHandle(ghFile);
return EXIT_SUCCESS;
}
/*
* Call ReadFile to start an overlapped request.
* Make sure we handle errors that are recoverable.
* Properly set up the event object for this operation.
*/
int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount)
{
int i;
BOOL rc;
DWORD dwNumread;
DWORD err;
MTVERIFY(
ghEvents[nIndex] = CreateEvent(
NULL, // No security
TRUE, // Manual reset - extremely important!
FALSE, // Initially set Event to non-signaled state
NULL // No name
)
);
gOverlapped[nIndex].hEvent = ghEvents[nIndex];
gOverlapped[nIndex].Offset = dwLocation;
for (i=0; i<MAX_TRY_COUNT; i++)
{
rc = ReadFile(
ghFile,
gBuffers[nIndex],
dwAmount,
&dwNumread,
&gOverlapped[nIndex]
);
// Handle success
if (rc)
{
printf("Read #%d completed immediately.\n", nIndex);
return TRUE;
}
err = GetLastError();
// Handle the error that isn't an error. rc is zero here.
if (err == ERROR_IO_PENDING)
{
// asynchronous i/o is still in progress
printf("Read #%d queued for overlapped I/O.\n", nIndex);
return TRUE;
}
// Handle recoverable error
if ( err == ERROR_INVALID_USER_BUFFER ||
err == ERROR_NOT_ENOUGH_QUOTA ||
err == ERROR_NOT_ENOUGH_MEMORY )
{
Sleep(50); // Wait around and try later
continue;
}
// Give up on fatal error.
break;
}
printf("ReadFile failed.\n");
return -1;
}
//
// Make sure we are running under an operating
// system that supports overlapped I/O to files.
//
void CheckOsVersion()
{
OSVERSIONINFO ver;
BOOL bResult;
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
bResult = GetVersionEx((LPOSVERSIONINFO) &ver);
if ( (!bResult) ||
(ver.dwPlatformId != VER_PLATFORM_WIN32_NT) )
{
fprintf(stderr, "IoByEvnt must be run under Windows NT.\n");
exit(EXIT_FAILURE);
}
}
od\
00401000 /$ 81EC 0C020000 sub esp, 20C
00401006 |. 53 push ebx
00401007 |. 56 push esi
00401008 |. 57 push edi
00401009 |. E8 52030000 call 00401360
0040100E |. 8D4424 14 lea eax, dword ptr [esp+14]
00401012 |. 68 04010000 push 104 ; /BufSize = 104 (260.)
00401017 |. 50 push eax ; |Buffer
00401018 |. FF15 24204000 call dword ptr [<&KERNEL32.GetWindows>; \GetWindowsDirectoryA
0040101E |. BF FC304000 mov edi, 004030FC ; ASCII "\WINHLP32.EXE"
00401023 |. 83C9 FF or ecx, FFFFFFFF
00401026 |. 33C0 xor eax, eax
00401028 |. 8D5424 14 lea edx, dword ptr [esp+14]
0040102C |. F2:AE repne scas byte ptr es:[edi]
0040102E |. F7D1 not ecx
00401030 |. 2BF9 sub edi, ecx
00401032 |. 50 push eax ; /hTemplateFile => NULL
00401033 |. 8BF7 mov esi, edi ; |
00401035 |. 8BD9 mov ebx, ecx ; |
00401037 |. 8BFA mov edi, edx ; |
00401039 |. 83C9 FF or ecx, FFFFFFFF ; |
0040103C |. F2:AE repne scas byte ptr es:[edi] ; |
0040103E |. 8BCB mov ecx, ebx ; |
00401040 |. 4F dec edi ; |
00401041 |. C1E9 02 shr ecx, 2 ; |
00401044 |. F3:A5 rep movs dword ptr es:[edi], dword p>; |
00401046 |. 68 00000040 push 40000000 ; |Attributes = OVERLAPPED
0040104B |. 8BCB mov ecx, ebx ; |
0040104D |. 6A 03 push 3 ; |Mode = OPEN_EXISTING
0040104F |. 50 push eax ; |pSecurity => NULL
00401050 |. 83E1 03 and ecx, 3 ; |
00401053 |. 6A 03 push 3 ; |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
00401055 |. 8D4424 28 lea eax, dword ptr [esp+28] ; |
00401059 |. 68 00000080 push 80000000 ; |Access = GENERIC_READ
0040105E |. F3:A4 rep movs byte ptr es:[edi], byte ptr>; |
00401060 |. 50 push eax ; |FileName
00401061 |. FF15 20204000 call dword ptr [<&KERNEL32.CreateFile>; \CreateFileA
00401067 |. 83F8 FF cmp eax, -1
0040106A |. A3 F0314000 mov dword ptr [4031F0], eax
0040106F |. 75 20 jnz short 00401091
00401071 |. 8D4C24 14 lea ecx, dword ptr [esp+14]
00401075 |. 51 push ecx ; /<%s>
00401076 |. 68 E8304000 push 004030E8 ; |format = "Could not open %s",LF,""
0040107B |. FF15 40204000 call dword ptr [<&MSVCRTD.printf>] ; \printf
00401081 |. 83C4 08 add esp, 8
00401084 |. 83C8 FF or eax, FFFFFFFF
00401087 |. 5F pop edi
00401088 |. 5E pop esi
00401089 |. 5B pop ebx
0040108A |. 81C4 0C020000 add esp, 20C
00401090 |. C3 retn
00401091 |> 33FF xor edi, edi
00401093 |. 33F6 xor esi, esi
00401095 |> 68 00020000 /push 200
0040109A |. 56 |push esi
0040109B |. 57 |push edi
0040109C |. E8 2F010000 |call 004011D0
004010A1 |. 83C4 0C |add esp, 0C
004010A4 |. 81C6 00400000 |add esi, 4000
004010AA |. 47 |inc edi
004010AB |. 81FE 00400100 |cmp esi, 14000
004010B1 |.^ 72 E2 \jb short 00401095
004010B3 |. 68 DC304000 push 004030DC ; /format = "QUEUED!!",LF,""
004010B8 |. FF15 40204000 call dword ptr [<&MSVCRTD.printf>] ; \printf
004010BE |. 83C4 04 add esp, 4
004010C1 |. 6A FF push -1 ; /Timeout = INFINITE
004010C3 |. 6A 01 push 1 ; |WaitForAll = TRUE
004010C5 |. 68 00324000 push 00403200 ; |pObjects = IoByEvnt.00403200
004010CA |. 6A 05 push 5 ; |nObjects = 5
004010CC |. FF15 1C204000 call dword ptr [<&KERNEL32.WaitForMul>; \WaitForMultipleObjects
004010D2 |. 83F8 FF cmp eax, -1
004010D5 |. 0F85 89000000 jnz 00401164
004010DB |. FF15 18204000 call dword ptr [<&KERNEL32.GetLastErr>; [GetLastError
004010E1 |. 6A 00 push 0 ; /Arguments = NULL
004010E3 |. 8D5424 10 lea edx, dword ptr [esp+10] ; |
004010E7 |. 6A 00 push 0 ; |BufSize = 0
004010E9 |. 52 push edx ; |Buffer
004010EA |. 6A 00 push 0 ; |LanguageId = 0 (LANG_NEUTRAL)
004010EC |. 50 push eax ; |MessageId
004010ED |. 6A 00 push 0 ; |pSource = NULL
004010EF |. 68 00110000 push 1100 ; |Flags = ALLOCATE_BUFFER|FROM_SYSTEM|0
004010F4 |. FF15 14204000 call dword ptr [<&KERNEL32.FormatMess>; \FormatMessageA
004010FA |. 8B4424 0C mov eax, dword ptr [esp+C]
004010FE |. 8D8C24 180100>lea ecx, dword ptr [esp+118]
00401105 |. 50 push eax ; /<%s>
00401106 |. 68 8C304000 push 0040308C ; |<%s> = "WaitForMultipleObjects( MAX_REQUESTS, ghEvents, TRUE, INFINITE ) != WAIT_FAILED"
0040110B |. 68 80304000 push 00403080 ; |<%s> = "IoByEvnt.c"
00401110 |. 6A 53 push 53 ; |<%d> = 53 (83.)
00401112 |. 68 3C304000 push 0040303C ; |Format = LF,"The following call failed at line %d in %s:",LF,LF," %s",LF,LF,"Reason: %s",LF,""
00401117 |. 51 push ecx ; |s
00401118 |. FF15 7C204000 call dword ptr [<&USER32.wsprintfA>] ; \wsprintfA
0040111E |. 8DBC24 300100>lea edi, dword ptr [esp+130]
00401125 |. 83C9 FF or ecx, FFFFFFFF
00401128 |. 33C0 xor eax, eax
0040112A |. 83C4 18 add esp, 18
0040112D |. F2:AE repne scas byte ptr es:[edi]
0040112F |. F7D1 not ecx
00401131 |. 8D5424 10 lea edx, dword ptr [esp+10]
00401135 |. 6A 00 push 0 ; /pOverlapped = NULL
00401137 |. 49 dec ecx ; |
00401138 |. 52 push edx ; |pBytesWritten
00401139 |. 8D8424 200100>lea eax, dword ptr [esp+120] ; |
00401140 |. 51 push ecx ; |nBytesToWrite
00401141 |. 50 push eax ; |Buffer
00401142 |. 6A F4 push -0C ; |/DevType = STD_ERROR_HANDLE
00401144 |. FF15 10204000 call dword ptr [<&KERNEL32.GetStdHand>; |\GetStdHandle
0040114A |. 50 push eax ; |hFile
0040114B |. FF15 0C204000 call dword ptr [<&KERNEL32.WriteFile>>; \WriteFile
00401151 |. 68 B80B0000 push 0BB8 ; /Timeout = 3000. ms
00401156 |. FF15 08204000 call dword ptr [<&KERNEL32.Sleep>] ; \Sleep
0040115C |. 6A 01 push 1 ; /status = 1
0040115E |. FF15 3C204000 call dword ptr [<&MSVCRTD.exit>] ; \exit
00401164 |> 8B1D 04204000 mov ebx, dword ptr [<&KERNEL32.Close>; kernel32.CloseHandle
0040116A |. 55 push ebp
0040116B |. 8B2D 00204000 mov ebp, dword ptr [<&KERNEL32.GetOv>; kernel32.GetOverlappedResult
00401171 |. 33FF xor edi, edi
00401173 |. BE 303C4000 mov esi, 00403C30
00401178 |> A1 F0314000 mov eax, dword ptr [4031F0]
0040117D |. 8D4C24 10 lea ecx, dword ptr [esp+10]
00401181 |. 6A 00 push 0
00401183 |. 8D56 F0 lea edx, dword ptr [esi-10]
00401186 |. 51 push ecx
00401187 |. 52 push edx
00401188 |. 50 push eax
00401189 |. FFD5 call ebp
0040118B |. 8B4C24 10 mov ecx, dword ptr [esp+10]
0040118F |. 51 push ecx ; /<%d>
00401190 |. 50 push eax ; |<%d>
00401191 |. 57 push edi ; |<%d>
00401192 |. 68 10304000 push 00403010 ; |format = "Read #%d returned %d. %d bytes were read.",LF,""
00401197 |. FF15 40204000 call dword ptr [<&MSVCRTD.printf>] ; \printf
0040119D |. 8B16 mov edx, dword ptr [esi]
0040119F |. 83C4 10 add esp, 10
004011A2 |. 52 push edx
004011A3 |. FFD3 call ebx
004011A5 |. 83C6 14 add esi, 14
004011A8 |. 47 inc edi
004011A9 |. 81FE 943C4000 cmp esi, 00403C94
004011AF |.^ 7C C7 jl short 00401178
004011B1 |. A1 F0314000 mov eax, dword ptr [4031F0]
004011B6 |. 50 push eax
004011B7 |. FFD3 call ebx
004011B9 |. 5D pop ebp
004011BA |. 5F pop edi
004011BB |. 5E pop esi
004011BC |. 33C0 xor eax, eax
004011BE |. 5B pop ebx
004011BF |. 81C4 0C020000 add esp, 20C
004011C5 \. C3 retn
ida