|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.