6-3

/*
 * IoByAPC.c
 *
 * Sample code for Multithreading Applications in Win32
 * This is from Chapter 6, Listing 6-3
 *
 * Demonstrates how to use APC's (asynchronous
 * procedure calls) instead of signaled objects
 * to service multiple outstanding overlapped
 * operations 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
//
void CheckOsVersion();
int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount);


//
// Global variables
//

// Need a single event object so we know when all I/O is finished
HANDLE  ghEvent;
// 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 nCompletionCount;

/*
 * I/O Completion routine gets called
 * when app is alertable (in WaitForSingleObjectEx)
 * and an overlapped I/O operation has completed.
 */
VOID WINAPI FileIOCompletionRoutine(
    DWORD dwErrorCode,  // completion code
    DWORD dwNumberOfBytesTransfered,    // number of bytes transferred
    LPOVERLAPPED lpOverlapped   // pointer to structure with I/O information 
   )
{
    // The event handle is really the user defined data
    int nIndex = (int)(lpOverlapped->hEvent);
    printf("Read #%d returned %d. %d bytes were read.\n",
        nIndex,
        dwErrorCode,
        dwNumberOfBytesTransfered);

    if (++nCompletionCount == MAX_REQUESTS)
        SetEvent(ghEvent);  // Cause the wait to terminate
}


int main()
{
    int i;
    char szPath[MAX_PATH];

    CheckOsVersion();

    // Need to know when to stop
    MTVERIFY(
        ghEvent = CreateEvent(
                     NULL,    // No security
                     TRUE,    // Manual reset - extremely important!
                     FALSE,   // Initially set Event to non-signaled state
                     NULL     // No name
                    )
    );

    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;
    }

    // Queue up a few requests
    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.
    for (;;)
    {
        DWORD rc;
        rc = WaitForSingleObjectEx(ghEvent, INFINITE, TRUE );
        if (rc == WAIT_OBJECT_0)
            break;
        MTVERIFY(rc == WAIT_IO_COMPLETION);
    }

    CloseHandle(ghFile);

    return EXIT_SUCCESS;
}


/*
 * Call ReadFileEx to start an overlapped request.
 * Make sure we handle errors that are recoverable.
 */
int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount)
{
    int i;
    BOOL rc;
    DWORD err;

    gOverlapped[nIndex].hEvent = (HANDLE)nIndex;
    gOverlapped[nIndex].Offset = dwLocation;

    for (i=0; i<MAX_TRY_COUNT; i++)
    {
        rc = ReadFileEx(
            ghFile,
            gBuffers[nIndex],
            dwAmount,
            &gOverlapped[nIndex],
            FileIOCompletionRoutine
        );

        // Handle success
        if (rc)
        {
            // asynchronous i/o is still in progress
            printf("Read #%d queued for overlapped I/O.\n", nIndex);
            return TRUE;
        }

        err = GetLastError();

        // 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("ReadFileEx 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, "IoByAPC must be run under Windows NT.\n");
  exit(EXIT_FAILURE);
    }

}

od

 

00401040  /$  81EC 0C020000 sub     esp, 20C
00401046  |.  56            push    esi
00401047  |.  57            push    edi
00401048  |.  E8 E3020000   call    00401330
0040104D  |.  6A 00         push    0                                ; /EventName = NULL
0040104F  |.  6A 00         push    0                                ; |InitiallySignaled = FALSE
00401051  |.  6A 01         push    1                                ; |ManualReset = TRUE
00401053  |.  6A 00         push    0                                ; |pSecurity = NULL
00401055  |.  FF15 28204000 call    dword ptr [<&KERNEL32.CreateEven>; \CreateEventA
0040105B  |.  85C0          test    eax, eax
0040105D  |.  A3 90314000   mov     dword ptr [403190], eax
00401062  |.  0F85 80000000 jnz     004010E8
00401068  |.  FF15 24204000 call    dword ptr [<&KERNEL32.GetLastErr>; [GetLastError
0040106E  |.  6A 00         push    0                                ; /Arguments = NULL
00401070  |.  8D4C24 0C     lea     ecx, dword ptr [esp+C]           ; |
00401074  |.  6A 00         push    0                                ; |BufSize = 0
00401076  |.  51            push    ecx                              ; |Buffer
00401077  |.  6A 00         push    0                                ; |LanguageId = 0 (LANG_NEUTRAL)
00401079  |.  50            push    eax                              ; |MessageId
0040107A  |.  6A 00         push    0                                ; |pSource = NULL
0040107C  |.  68 00110000   push    1100                             ; |Flags = ALLOCATE_BUFFER|FROM_SYSTEM|0
00401081  |.  FF15 20204000 call    dword ptr [<&KERNEL32.FormatMess>; \FormatMessageA
00401087  |.  8B5424 08     mov     edx, dword ptr [esp+8]
0040108B  |.  8D4424 10     lea     eax, dword ptr [esp+10]
0040108F  |.  52            push    edx                              ; /<%s>
00401090  |.  68 D8304000   push    004030D8                         ; |<%s> = "ghEvent = CreateEvent( NULL, TRUE, FALSE, NULL )"
00401095  |.  68 CC304000   push    004030CC                         ; |<%s> = "IoByAPC.c"
0040109A  |.  6A 55         push    55                               ; |<%d> = 55 (85.)
0040109C  |.  68 88304000   push    00403088                         ; |Format = LF,"The following call failed at line %d in %s:",LF,LF,"    %s",LF,LF,"Reason: %s",LF,""
004010A1  |.  50            push    eax                              ; |s
004010A2  |.  FF15 7C204000 call    dword ptr [<&USER32.wsprintfA>]  ; \wsprintfA
004010A8  |.  83C4 18       add     esp, 18
004010AB  |.  8D4C24 0C     lea     ecx, dword ptr [esp+C]
004010AF  |.  8D7C24 10     lea     edi, dword ptr [esp+10]
004010B3  |.  33C0          xor     eax, eax
004010B5  |.  6A 00         push    0                                ; /pOverlapped = NULL
004010B7  |.  51            push    ecx                              ; |pBytesWritten
004010B8  |.  83C9 FF       or      ecx, FFFFFFFF                    ; |
004010BB  |.  8D5424 18     lea     edx, dword ptr [esp+18]          ; |
004010BF  |.  F2:AE         repne   scas byte ptr es:[edi]           ; |
004010C1  |.  F7D1          not     ecx                              ; |
004010C3  |.  49            dec     ecx                              ; |
004010C4  |.  51            push    ecx                              ; |nBytesToWrite
004010C5  |.  52            push    edx                              ; |Buffer
004010C6  |.  6A F4         push    -0C                              ; |/DevType = STD_ERROR_HANDLE
004010C8  |.  FF15 1C204000 call    dword ptr [<&KERNEL32.GetStdHand>; |\GetStdHandle
004010CE  |.  50            push    eax                              ; |hFile
004010CF  |.  FF15 18204000 call    dword ptr [<&KERNEL32.WriteFile>>; \WriteFile
004010D5  |.  68 B80B0000   push    0BB8                             ; /Timeout = 3000. ms
004010DA  |.  FF15 14204000 call    dword ptr [<&KERNEL32.Sleep>]    ; \Sleep
004010E0  |.  6A 01         push    1                                ; /status = 1
004010E2  |.  FF15 40204000 call    dword ptr [<&MSVCRTD.exit>]      ; \exit
004010E8  |>  53            push    ebx
004010E9  |.  8D8424 140100>lea     eax, dword ptr [esp+114]
004010F0  |.  68 04010000   push    104                              ; /BufSize = 104 (260.)
004010F5  |.  50            push    eax                              ; |Buffer
004010F6  |.  FF15 10204000 call    dword ptr [<&KERNEL32.GetWindows>; \GetWindowsDirectoryA
004010FC  |.  BF 78304000   mov     edi, 00403078                    ;  ASCII "\WINHLP32.EXE"
00401101  |.  83C9 FF       or      ecx, FFFFFFFF
00401104  |.  33C0          xor     eax, eax
00401106  |.  8D9424 140100>lea     edx, dword ptr [esp+114]
0040110D  |.  F2:AE         repne   scas byte ptr es:[edi]
0040110F  |.  F7D1          not     ecx
00401111  |.  2BF9          sub     edi, ecx
00401113  |.  50            push    eax                              ; /hTemplateFile => NULL
00401114  |.  8BF7          mov     esi, edi                         ; |
00401116  |.  8BD9          mov     ebx, ecx                         ; |
00401118  |.  8BFA          mov     edi, edx                         ; |
0040111A  |.  83C9 FF       or      ecx, FFFFFFFF                    ; |
0040111D  |.  F2:AE         repne   scas byte ptr es:[edi]           ; |
0040111F  |.  8BCB          mov     ecx, ebx                         ; |
00401121  |.  4F            dec     edi                              ; |
00401122  |.  C1E9 02       shr     ecx, 2                           ; |
00401125  |.  F3:A5         rep     movs dword ptr es:[edi], dword p>; |
00401127  |.  68 00000040   push    40000000                         ; |Attributes = OVERLAPPED
0040112C  |.  8BCB          mov     ecx, ebx                         ; |
0040112E  |.  6A 03         push    3                                ; |Mode = OPEN_EXISTING
00401130  |.  50            push    eax                              ; |pSecurity => NULL
00401131  |.  83E1 03       and     ecx, 3                           ; |
00401134  |.  6A 03         push    3                                ; |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
00401136  |.  8D8424 280100>lea     eax, dword ptr [esp+128]         ; |
0040113D  |.  68 00000080   push    80000000                         ; |Access = GENERIC_READ
00401142  |.  F3:A4         rep     movs byte ptr es:[edi], byte ptr>; |
00401144  |.  50            push    eax                              ; |FileName
00401145  |.  FF15 0C204000 call    dword ptr [<&KERNEL32.CreateFile>; \CreateFileA
0040114B  |.  83F8 FF       cmp     eax, -1
0040114E  |.  A3 94314000   mov     dword ptr [403194], eax
00401153  |.  5B            pop     ebx
00401154  |.  75 22         jnz     short 00401178
00401156  |.  8D8C24 100100>lea     ecx, dword ptr [esp+110]
0040115D  |.  51            push    ecx                              ; /<%s>
0040115E  |.  68 64304000   push    00403064                         ; |format = "Could not open %s",LF,""
00401163  |.  FF15 3C204000 call    dword ptr [<&MSVCRTD.printf>]    ; \printf
00401169  |.  83C4 08       add     esp, 8
0040116C  |.  83C8 FF       or      eax, FFFFFFFF
0040116F  |.  5F            pop     edi
00401170  |.  5E            pop     esi
00401171  |.  81C4 0C020000 add     esp, 20C
00401177  |.  C3            retn
00401178  |>  33FF          xor     edi, edi
0040117A  |.  33F6          xor     esi, esi
0040117C  |>  68 00020000   /push    200
00401181  |.  56            |push    esi
00401182  |.  57            |push    edi
00401183  |.  E8 E8000000   |call    00401270
00401188  |.  83C4 0C       |add     esp, 0C
0040118B  |.  81C6 00400000 |add     esi, 4000
00401191  |.  47            |inc     edi
00401192  |.  81FE 00400100 |cmp     esi, 14000
00401198  |.^ 72 E2         \jb      short 0040117C
0040119A  |.  68 58304000   push    00403058                         ; /format = "QUEUED!!",LF,""
0040119F  |.  FF15 3C204000 call    dword ptr [<&MSVCRTD.printf>]    ; \printf
004011A5  |.  8B15 90314000 mov     edx, dword ptr [403190]
004011AB  |.  8B35 08204000 mov     esi, dword ptr [<&KERNEL32.WaitF>;  kernel32.WaitForSingleObjectEx
004011B1  |.  83C4 04       add     esp, 4
004011B4  |.  6A 01         push    1                                ; /fAlertable = TRUE
004011B6  |.  6A FF         push    -1                               ; |Timeout = INFINITE
004011B8  |.  52            push    edx                              ; |hObject => NULL
004011B9  |.  FFD6          call    esi                              ; \WaitForSingleObjectEx
004011BB  |.  85C0          test    eax, eax
004011BD  |.  74 17         je      short 004011D6
004011BF  |>  3D C0000000   /cmp     eax, 0C0
004011C4  |.  75 28         |jnz     short 004011EE
004011C6  |.  A1 90314000   |mov     eax, dword ptr [403190]
004011CB  |.  6A 01         |push    1
004011CD  |.  6A FF         |push    -1
004011CF  |.  50            |push    eax
004011D0  |.  FFD6          |call    esi
004011D2  |.  85C0          |test    eax, eax
004011D4  |.^ 75 E9         \jnz     short 004011BF
004011D6  |>  8B0D 94314000 mov     ecx, dword ptr [403194]
004011DC  |.  51            push    ecx                              ; /hObject => NULL
004011DD  |.  FF15 04204000 call    dword ptr [<&KERNEL32.CloseHandl>; \CloseHandle
004011E3  |.  5F            pop     edi
004011E4  |.  33C0          xor     eax, eax
004011E6  |.  5E            pop     esi
004011E7  |.  81C4 0C020000 add     esp, 20C
004011ED  |.  C3            retn
004011EE  |>  FF15 24204000 call    dword ptr [<&KERNEL32.GetLastErr>; [GetLastError
004011F4  |.  6A 00         push    0                                ; /Arguments = NULL
004011F6  |.  8D5424 0C     lea     edx, dword ptr [esp+C]           ; |
004011FA  |.  6A 00         push    0                                ; |BufSize = 0
004011FC  |.  52            push    edx                              ; |Buffer
004011FD  |.  6A 00         push    0                                ; |LanguageId = 0 (LANG_NEUTRAL)
004011FF  |.  50            push    eax                              ; |MessageId
00401200  |.  6A 00         push    0                                ; |pSource = NULL
00401202  |.  68 00110000   push    1100                             ; |Flags = ALLOCATE_BUFFER|FROM_SYSTEM|0
00401207  |.  FF15 20204000 call    dword ptr [<&KERNEL32.FormatMess>; \FormatMessageA
0040120D  |.  8B4424 08     mov     eax, dword ptr [esp+8]
00401211  |.  8D4C24 10     lea     ecx, dword ptr [esp+10]
00401215  |.  50            push    eax                              ; /<%s>
00401216  |.  68 3C304000   push    0040303C                         ; |<%s> = "rc == WAIT_IO_COMPLETION"
0040121B  |.  68 CC304000   push    004030CC                         ; |<%s> = "IoByAPC.c"
00401220  |.  6A 78         push    78                               ; |<%d> = 78 (120.)
00401222  |.  68 88304000   push    00403088                         ; |Format = LF,"The following call failed at line %d in %s:",LF,LF,"    %s",LF,LF,"Reason: %s",LF,""
00401227  |.  51            push    ecx                              ; |s
00401228  |.  FF15 7C204000 call    dword ptr [<&USER32.wsprintfA>]  ; \wsprintfA
0040122E  |.  8D7C24 28     lea     edi, dword ptr [esp+28]
00401232  |.  83C9 FF       or      ecx, FFFFFFFF
00401235  |.  33C0          xor     eax, eax
00401237  |.  83C4 18       add     esp, 18
0040123A  |.  F2:AE         repne   scas byte ptr es:[edi]
0040123C  |.  F7D1          not     ecx
0040123E  |.  8D5424 0C     lea     edx, dword ptr [esp+C]
00401242  |.  6A 00         push    0                                ; /pOverlapped = NULL
00401244  |.  49            dec     ecx                              ; |
00401245  |.  52            push    edx                              ; |pBytesWritten
00401246  |.  8D4424 18     lea     eax, dword ptr [esp+18]          ; |
0040124A  |.  51            push    ecx                              ; |nBytesToWrite
0040124B  |.  50            push    eax                              ; |Buffer
0040124C  |.  6A F4         push    -0C                              ; |/DevType = STD_ERROR_HANDLE
0040124E  |.  FF15 1C204000 call    dword ptr [<&KERNEL32.GetStdHand>; |\GetStdHandle
00401254  |.  50            push    eax                              ; |hFile
00401255  |.  FF15 18204000 call    dword ptr [<&KERNEL32.WriteFile>>; \WriteFile
0040125B  |.  68 B80B0000   push    0BB8                             ; /Timeout = 3000. ms
00401260  |.  FF15 14204000 call    dword ptr [<&KERNEL32.Sleep>]    ; \Sleep
00401266  |.  6A 01         push    1                                ; /status = 1
00401268  |.  FF15 40204000 call    dword ptr [<&MSVCRTD.exit>]      ; \exit
0040126E  |.  90            nop
0040126F  |.  90            nop
00401270  |$  53            push    ebx
00401271  |.  55            push    ebp
00401272  |.  56            push    esi
00401273  |.  57            push    edi
00401274  |.  8B7C24 14     mov     edi, dword ptr [esp+14]
00401278  |.  8B4C24 18     mov     ecx, dword ptr [esp+18]
0040127C  |.  8B5C24 1C     mov     ebx, dword ptr [esp+1C]
00401280  |.  8B2D 2C204000 mov     ebp, dword ptr [<&KERNEL32.ReadF>;  kernel32.ReadFileEx
00401286  |.  8D04BF        lea     eax, dword ptr [edi+edi*4]
00401289  |.  33F6          xor     esi, esi
0040128B  |.  C1E0 02       shl     eax, 2
0040128E  |.  89B8 B03B4000 mov     dword ptr [eax+403BB0], edi
00401294  |.  8988 A83B4000 mov     dword ptr [eax+403BA8], ecx
0040129A  |.  8D90 A03B4000 lea     edx, dword ptr [eax+403BA0]
004012A0  |.  8BC7          mov     eax, edi
004012A2  |.  C1E0 09       shl     eax, 9
004012A5  |.  895424 14     mov     dword ptr [esp+14], edx
004012A9  |.  8D88 A0314000 lea     ecx, dword ptr [eax+4031A0]
004012AF  |.  894C24 18     mov     dword ptr [esp+18], ecx
004012B3  |>  8B5424 14     /mov     edx, dword ptr [esp+14]
004012B7  |.  8B4424 18     |mov     eax, dword ptr [esp+18]
004012BB  |.  8B0D 94314000 |mov     ecx, dword ptr [403194]
004012C1  |.  68 00104000   |push    00401000
004012C6  |.  52            |push    edx
004012C7  |.  53            |push    ebx
004012C8  |.  50            |push    eax
004012C9  |.  51            |push    ecx
004012CA  |.  FFD5          |call    ebp
004012CC  |.  85C0          |test    eax, eax
004012CE  |.  75 3D         |jnz     short 0040130D
004012D0  |.  FF15 24204000 |call    dword ptr [<&KERNEL32.GetLastEr>; [GetLastError
004012D6  |.  3D F8060000   |cmp     eax, 6F8
004012DB  |.  74 0C         |je      short 004012E9
004012DD  |.  3D 18070000   |cmp     eax, 718
004012E2  |.  74 05         |je      short 004012E9
004012E4  |.  83F8 08       |cmp     eax, 8
004012E7  |.  75 0E         |jnz     short 004012F7
004012E9  |>  6A 32         |push    32                              ; /Timeout = 50. ms
004012EB  |.  FF15 14204000 |call    dword ptr [<&KERNEL32.Sleep>]   ; \Sleep
004012F1  |.  46            |inc     esi
004012F2  |.  83FE 05       |cmp     esi, 5
004012F5  |.^ 7C BC         \jl      short 004012B3
004012F7  |>  68 34314000   push    00403134                         ; /format = "ReadFileEx failed.",LF,""
004012FC  |.  FF15 3C204000 call    dword ptr [<&MSVCRTD.printf>]    ; \printf
00401302  |.  83C4 04       add     esp, 4
00401305  |.  83C8 FF       or      eax, FFFFFFFF
00401308  |.  5F            pop     edi
00401309  |.  5E            pop     esi
0040130A  |.  5D            pop     ebp
0040130B  |.  5B            pop     ebx
0040130C  |.  C3            retn
0040130D  |>  57            push    edi                              ; /<%d>
0040130E  |.  68 0C314000   push    0040310C                         ; |format = "Read #%d queued for overlapped I/O.",LF,""
00401313  |.  FF15 3C204000 call    dword ptr [<&MSVCRTD.printf>]    ; \printf
00401319  |.  83C4 08       add     esp, 8
0040131C  |.  B8 01000000   mov     eax, 1
00401321  |.  5F            pop     edi
00401322  |.  5E            pop     esi
00401323  |.  5D            pop     ebp
00401324  |.  5B            pop     ebx
00401325  \.  C3            retn

 

routu

 

00401000   .  8B4424 08     mov     eax, dword ptr [esp+8]
00401004   .  8B5424 0C     mov     edx, dword ptr [esp+C]
00401008   .  8B4C24 04     mov     ecx, dword ptr [esp+4]
0040100C   .  50            push    eax                              ; /<%d>
0040100D   .  8B42 10       mov     eax, dword ptr [edx+10]          ; |
00401010   .  51            push    ecx                              ; |<%d>
00401011   .  50            push    eax                              ; |<%d>
00401012   .  68 10304000   push    00403010                         ; |format = "Read #%d returned %d. %d bytes were read.",LF,""
00401017   .  FF15 3C204000 call    dword ptr [<&MSVCRTD.printf>]    ; \printf
0040101D   .  A1 98314000   mov     eax, dword ptr [403198]
00401022   .  83C4 10       add     esp, 10
00401025   .  40            inc     eax
00401026   .  83F8 05       cmp     eax, 5
00401029   .  A3 98314000   mov     dword ptr [403198], eax
0040102E   .  75 0D         jnz     short 0040103D
00401030   .  8B0D 90314000 mov     ecx, dword ptr [403190]
00401036   .  51            push    ecx                              ; /hEvent => NULL
00401037   .  FF15 00204000 call    dword ptr [<&KERNEL32.SetEvent>] ; \SetEvent
0040103D   >  C2 0C00       retn    0C

 

 

ida

 

posted @ 2010-07-09 15:03  南守拥  阅读(328)  评论(0编辑  收藏  举报