Annotation of mstools/samples/sdktools/rshell/server/async.c, revision 1.1.1.1

1.1       root        1: /****************************** Module Header ******************************\
                      2: * Module Name: async.c
                      3: *
                      4: * Copyright (c) 1991, Microsoft Corporation
                      5: *
                      6: * This module implements asynchronous I/O on file handles in a more
                      7: * useful way than provided for by Win32 apis.
                      8: *
                      9: * This module provides 2 main apis : ReadFileAsync, WriteFileAsync.
                     10: * These apis take a handle to an async object and always return
                     11: * immediately without waiting for the I/O to complete. An event
                     12: * can be queried from the async object and used to wait for completion.
                     13: * When this event is signalled, the I/O result can be queried from
                     14: * the async object.
                     15: *
                     16: * History:
                     17: * 06-29-92 Davidc       Created.
                     18: \***************************************************************************/
                     19: 
                     20: #include "rcmdsrv.h"
                     21: 
                     22: 
                     23: 
                     24: //
                     25: // Define MYOVERLAPPED structure
                     26: //
                     27: 
                     28: typedef struct {
                     29: 
                     30:     OVERLAPPED  Overlapped;
                     31: 
                     32:     HANDLE      FileHandle; // Non-null when I/O operation in progress.
                     33: 
                     34:     DWORD       CompletionCode;
                     35:     DWORD       BytesTransferred;
                     36:     BOOL        CompletedSynchronously;
                     37: 
                     38: } MYOVERLAPPED, *PMYOVERLAPPED;
                     39: 
                     40: 
                     41: 
                     42: 
                     43: 
                     44: /////////////////////////////////////////////////////////////////////////////
                     45: //
                     46: // CreateAsync
                     47: //
                     48: // Creates an async object.
                     49: // The async event is created with the initial state specified. If this
                     50: // is TRUE the async object created simulates a successfully completed
                     51: // transfer of 0 bytes.
                     52: //
                     53: // Returns handle on success, NULL on failure. GetLastError() for details.
                     54: //
                     55: // The object should be deleted by calling DeleteAsync.
                     56: //
                     57: /////////////////////////////////////////////////////////////////////////////
                     58: 
                     59: HANDLE
                     60: CreateAsync(
                     61:     BOOL    InitialState
                     62:     )
                     63: {
                     64:     SECURITY_ATTRIBUTES SecurityAttributes;
                     65:     PMYOVERLAPPED   MyOverlapped;
                     66: 
                     67:     SecurityAttributes.nLength = sizeof(SecurityAttributes);
                     68:     SecurityAttributes.lpSecurityDescriptor = NULL; // Use default ACL
                     69:     SecurityAttributes.bInheritHandle = FALSE; // No inheritance
                     70: 
                     71:     //
                     72:     // Allocate space for the async structure
                     73:     //
                     74: 
                     75: 
                     76:     MyOverlapped = (PMYOVERLAPPED)Alloc(sizeof(MYOVERLAPPED));
                     77:     if (MyOverlapped == NULL) {
                     78:         DbgPrint("CreateAsync : Failed to allocate space for async object\n");
                     79:         return(NULL);
                     80:     }
                     81: 
                     82:     //
                     83:     // Create the synchronisation event
                     84:     //
                     85: 
                     86:     MyOverlapped->Overlapped.hEvent = CreateEvent( &SecurityAttributes,
                     87:                                                    TRUE,        // Manual-reset
                     88:                                                    InitialState,
                     89:                                                    NULL);       // Name
                     90:     if (MyOverlapped->Overlapped.hEvent == NULL) {
                     91:         DbgPrint("CreateAsync failed to create event, error = %d\n", GetLastError());
                     92:         Free(MyOverlapped);
                     93:         return(NULL);
                     94:     }
                     95: 
                     96:     //
                     97:     // Initialize other fields.
                     98:     // (Set FileHandle non-NULL to keep GetAsyncResult happy)
                     99:     //
                    100: 
                    101:     MyOverlapped->FileHandle = InitialState ? (HANDLE)1 : NULL;
                    102:     MyOverlapped->BytesTransferred = 0;
                    103:     MyOverlapped->CompletionCode = ERROR_SUCCESS;
                    104:     MyOverlapped->CompletedSynchronously = TRUE;
                    105: 
                    106: 
                    107:     return((HANDLE)MyOverlapped);
                    108: }
                    109: 
                    110: 
                    111: 
                    112: 
                    113: /////////////////////////////////////////////////////////////////////////////
                    114: //
                    115: // DeleteAsync
                    116: //
                    117: // Deletes resources used by async object
                    118: //
                    119: // Returns nothing
                    120: //
                    121: /////////////////////////////////////////////////////////////////////////////
                    122: 
                    123: VOID
                    124: DeleteAsync(
                    125:     HANDLE AsyncHandle
                    126:     )
                    127: {
                    128:     PMYOVERLAPPED MyOverlapped = (PMYOVERLAPPED)AsyncHandle;
                    129: 
                    130:     MyCloseHandle(MyOverlapped->Overlapped.hEvent, "async overlapped event");
                    131:     Free(MyOverlapped);
                    132: 
                    133:     return;
                    134: }
                    135: 
                    136: 
                    137: 
                    138: 
                    139: /////////////////////////////////////////////////////////////////////////////
                    140: //
                    141: // ReadFileAsync
                    142: //
                    143: // Reads from file asynchronously.
                    144: //
                    145: // Returns TRUE on success, FALSE on failure (GetLastError() for detail)
                    146: //
                    147: // Caller should wait on async event for operation to complete, then call
                    148: // GetAsyncResult to retrieve information on transfer.
                    149: //
                    150: /////////////////////////////////////////////////////////////////////////////
                    151: 
                    152: BOOL
                    153: ReadFileAsync(
                    154:     HANDLE  hFile,
                    155:     LPVOID  lpBuffer,
                    156:     DWORD   nBytesToRead,
                    157:     HANDLE  AsyncHandle
                    158:     )
                    159: {
                    160:     BOOL Result;
                    161:     DWORD Error;
                    162:     PMYOVERLAPPED MyOverlapped = (PMYOVERLAPPED)AsyncHandle;
                    163: 
                    164:     //
                    165:     // Check an IO operation is not in progress
                    166:     //
                    167: 
                    168:     if (MyOverlapped->FileHandle != NULL) {
                    169:         DbgPrint("ReadFileAsync : Operation already in progress!\n");
                    170:         SetLastError(ERROR_IO_PENDING);
                    171:         return(FALSE);
                    172:     }
                    173: 
                    174:     //
                    175:     // Reset the event
                    176:     //
                    177: 
                    178:     Result = ResetEvent(MyOverlapped->Overlapped.hEvent);
                    179:     if (!Result) {
                    180:         DbgPrint("ReadFileAsync : Failed to reset async event, error = %d\n", GetLastError());
                    181:         return(FALSE);
                    182:     }
                    183: 
                    184: 
                    185:     //
                    186:     // Store the file handle in our structure.
                    187:     // This also functions as a signal that an operation is in progress.
                    188:     //
                    189: 
                    190:     MyOverlapped->FileHandle = hFile;
                    191:     MyOverlapped->CompletedSynchronously = FALSE;
                    192: 
                    193:     Result = ReadFile(hFile,
                    194:                       lpBuffer,
                    195:                       nBytesToRead,
                    196:                       &MyOverlapped->BytesTransferred,
                    197:                       &MyOverlapped->Overlapped);
                    198: 
                    199:     if (!Result) {
                    200: 
                    201:         Error = GetLastError();
                    202: 
                    203:         if (Error == ERROR_IO_PENDING) {
                    204: 
                    205:             //
                    206:             // The I/O has been started synchronously, we're done
                    207:             //
                    208: 
                    209:             return(TRUE);
                    210:         }
                    211: 
                    212:         //
                    213:         // The read really did fail, reset our flag and get out
                    214:         //
                    215: 
                    216:         DbgPrint("ReadFileAsync : ReadFile failed, error = %d\n", Error);
                    217:         MyOverlapped->FileHandle = NULL;
                    218:         return(FALSE);
                    219:     }
                    220: 
                    221: 
                    222:     //
                    223:     // The operation completed synchronously. Store the paramaters in our
                    224:     // structure ready for GetAsyncResult and signal the event
                    225:     //
                    226: 
                    227:     MyOverlapped->CompletionCode = ERROR_SUCCESS;
                    228:     MyOverlapped->CompletedSynchronously = TRUE;
                    229: 
                    230:     //
                    231:     // Set the event
                    232:     //
                    233: 
                    234:     Result = SetEvent(MyOverlapped->Overlapped.hEvent);
                    235:     if (!Result) {
                    236:         DbgPrint("ReadFileAsync : Failed to set async event, error = %d\n", GetLastError());
                    237:     }
                    238: 
                    239:     return(TRUE);
                    240: }
                    241: 
                    242: 
                    243: 
                    244: /////////////////////////////////////////////////////////////////////////////
                    245: //
                    246: // WriteFileAsync
                    247: //
                    248: // Writes to file asynchronously.
                    249: //
                    250: // Returns TRUE on success, FALSE on failure (GetLastError() for detail)
                    251: //
                    252: // Caller should wait on async event for operation to complete, then call
                    253: // GetAsyncResult to retrieve information on transfer.
                    254: //
                    255: /////////////////////////////////////////////////////////////////////////////
                    256: 
                    257: BOOL
                    258: WriteFileAsync(
                    259:     HANDLE  hFile,
                    260:     LPVOID  lpBuffer,
                    261:     DWORD   nBytesToWrite,
                    262:     HANDLE  AsyncHandle
                    263:     )
                    264: {
                    265:     BOOL Result;
                    266:     DWORD Error;
                    267:     PMYOVERLAPPED MyOverlapped = (PMYOVERLAPPED)AsyncHandle;
                    268: 
                    269:     //
                    270:     // Check an IO operation is not in progress
                    271:     //
                    272: 
                    273:     if (MyOverlapped->FileHandle != NULL) {
                    274:         DbgPrint("ReadFileAsync : Operation already in progress!\n");
                    275:         SetLastError(ERROR_IO_PENDING);
                    276:         return(FALSE);
                    277:     }
                    278: 
                    279: 
                    280:     //
                    281:     // Reset the event
                    282:     //
                    283: 
                    284:     Result = ResetEvent(MyOverlapped->Overlapped.hEvent);
                    285:     if (!Result) {
                    286:         DbgPrint("WriteFileAsync : Failed to reset async event, error = %d\n", GetLastError());
                    287:         return(FALSE);
                    288:     }
                    289: 
                    290:     //
                    291:     // Store the file handle in our structure.
                    292:     // This also functions as a signal that an operation is in progress.
                    293:     //
                    294: 
                    295:     MyOverlapped->FileHandle = hFile;
                    296:     MyOverlapped->CompletedSynchronously = FALSE;
                    297: 
                    298:     Result = WriteFile(hFile,
                    299:                       lpBuffer,
                    300:                       nBytesToWrite,
                    301:                       &MyOverlapped->BytesTransferred,
                    302:                       &MyOverlapped->Overlapped);
                    303: 
                    304:     if (!Result) {
                    305: 
                    306:         Error = GetLastError();
                    307: 
                    308:         if (Error == ERROR_IO_PENDING) {
                    309: 
                    310:             //
                    311:             // The I/O has been started synchronously, we're done
                    312:             //
                    313: 
                    314:             return(TRUE);
                    315:         }
                    316: 
                    317:         //
                    318:         // The read really did fail, reset our flag and get out
                    319:         //
                    320: 
                    321:         DbgPrint("WriteFileAsync : WriteFile failed, error = %d\n", Error);
                    322:         MyOverlapped->FileHandle = NULL;
                    323:         return(FALSE);
                    324:     }
                    325: 
                    326: 
                    327:     //
                    328:     // The operation completed synchronously. Store the paramaters in our
                    329:     // structure ready for GetAsyncResult and signal the event
                    330:     //
                    331: 
                    332:     MyOverlapped->CompletionCode = ERROR_SUCCESS;
                    333:     MyOverlapped->CompletedSynchronously = TRUE;
                    334: 
                    335:     //
                    336:     // Set the event
                    337:     //
                    338: 
                    339:     Result = SetEvent(MyOverlapped->Overlapped.hEvent);
                    340:     if (!Result) {
                    341:         DbgPrint("WriteFileAsync : Failed to set async event, error = %d\n", GetLastError());
                    342:     }
                    343: 
                    344:     return(TRUE);
                    345: }
                    346: 
                    347: 
                    348: 
                    349: 
                    350: /////////////////////////////////////////////////////////////////////////////
                    351: //
                    352: // GetCompletionHandle
                    353: //
                    354: // Returns a handle that can be used to wait for completion of the
                    355: // operation associated with this async object
                    356: //
                    357: // Returns an event handle or NULL on failure
                    358: //
                    359: /////////////////////////////////////////////////////////////////////////////
                    360: 
                    361: HANDLE
                    362: GetAsyncCompletionHandle(
                    363:     HANDLE  AsyncHandle
                    364:     )
                    365: {
                    366:     PMYOVERLAPPED MyOverlapped = (PMYOVERLAPPED)AsyncHandle;
                    367: 
                    368:     return(MyOverlapped->Overlapped.hEvent);
                    369: }
                    370: 
                    371: 
                    372: 
                    373: 
                    374: /////////////////////////////////////////////////////////////////////////////
                    375: //
                    376: // GetAsyncResult
                    377: //
                    378: // Returns the result of the last completed operation involving the
                    379: // passed async object handle.
                    380: //
                    381: // Returns the completion code of the last operation OR
                    382: // ERROR_IO_INCOMPLETE if the operation has not completed.
                    383: // ERROR_NO_DATA if there is no operation in progress.
                    384: //
                    385: /////////////////////////////////////////////////////////////////////////////
                    386: 
                    387: DWORD
                    388: GetAsyncResult(
                    389:     HANDLE  AsyncHandle,
                    390:     LPDWORD BytesTransferred
                    391:     )
                    392: {
                    393:     BOOL Result;
                    394:     DWORD WaitResult;
                    395:     PMYOVERLAPPED MyOverlapped = (PMYOVERLAPPED)AsyncHandle;
                    396:     DWORD AsyncResult;
                    397: 
                    398:     //
                    399:     // Check an IO operation is (was) in progress
                    400:     //
                    401: 
                    402:     if (MyOverlapped->FileHandle == NULL) {
                    403:         DbgPrint("GetAsyncResult : No operation in progress !\n");
                    404:         return(ERROR_NO_DATA);
                    405:     }
                    406: 
                    407: 
                    408:     //
                    409:     // Check the event is set - i.e that an IO operation has completed
                    410:     //
                    411: 
                    412:     WaitResult = WaitForSingleObject(MyOverlapped->Overlapped.hEvent, 0);
                    413:     if (WaitResult != 0) {
                    414:         DbgPrint("GetAsyncResult : Event was not set, wait result = %d\n", WaitResult);
                    415:         return(ERROR_IO_INCOMPLETE);
                    416:     }
                    417: 
                    418: 
                    419:     //
                    420:     // If the call completed synchronously, copy the data out of
                    421:     // our structure
                    422:     //
                    423: 
                    424:     if (MyOverlapped->CompletedSynchronously) {
                    425: 
                    426:         AsyncResult = MyOverlapped->CompletionCode;
                    427:         *BytesTransferred = MyOverlapped->BytesTransferred;
                    428: 
                    429:     } else {
                    430: 
                    431:         //
                    432:         // Go get the asynchronous result info from the system
                    433:         //
                    434: 
                    435:         AsyncResult = ERROR_SUCCESS;
                    436: 
                    437:         Result = GetOverlappedResult(MyOverlapped->FileHandle,
                    438:                                      &MyOverlapped->Overlapped,
                    439:                                      BytesTransferred,
                    440:                                      FALSE);
                    441:         if (!Result) {
                    442:             AsyncResult = GetLastError();
                    443:             DbgPrint("GetAsyncResult : GetOverlappedResult failed, error = %d\n", AsyncResult);
                    444:         }
                    445:     }
                    446: 
                    447: 
                    448:     //
                    449:     // Reset the event so it doesn't trigger the caller again
                    450:     //
                    451: 
                    452:     Result = ResetEvent(MyOverlapped->Overlapped.hEvent);
                    453:     if (!Result) {
                    454:         DbgPrint("GetAsyncResult : Failed to reset async event\n");
                    455:     }
                    456: 
                    457: 
                    458:     //
                    459:     // Result the file handle so we know there is no pending operation
                    460:     //
                    461: 
                    462:     MyOverlapped->FileHandle = NULL;
                    463: 
                    464: 
                    465:     return(AsyncResult);
                    466: }
                    467: 
                    468: 
                    469: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.