|
|
1.1.1.3 ! root 1: ! 2: /******************************************************************************\ ! 3: * This is a part of the Microsoft Source Code Samples. ! 4: * Copyright (C) 1993 Microsoft Corporation. ! 5: * All rights reserved. ! 6: * This source code is only intended as a supplement to ! 7: * Microsoft Development Tools and/or WinHelp documentation. ! 8: * See these sources for detailed information regarding the ! 9: * Microsoft samples programs. ! 10: \******************************************************************************/ ! 11: 1.1.1.2 root 12: /****************************************************************************\ 13: ** MODULE: IO.C ** 14: ** ** 15: ** ** 16: ** PURPOSE: Demonstrates the basic concepts envolved when using ** 17: ** asynchronous IO. In particular the main advantage is your ** 18: ** app more correctly thread can go about doing useful work ** 19: ** while waiting for IO. The main disadvantage is you must keep ** 20: ** track of the file pointer. ** 21: ** ** 22: ** INPUT: Both the File to read and File to write to must be entered ** 23: ** on via the command line. Note the file to write to must be ** 24: ** unique. ** 25: ** ** 26: ** FUNCTIONS: ** 27: ** ** 28: ** Do_BackgroundTask() ** 29: ** ** 30: ** ** 31: ** COMMENTS: Reads a file asynchronously writes to another synchronously ** 32: ** ** 33: ** ** 34: \***************************************************************************/ 35: 36: 37: 1.1 root 38: #define STRICT 39: #define NOMINMAX 40: #include <windows.h> 41: 42: #include <stdlib.h> 43: #include <stdio.h> 44: #include <memory.h> 45: #include <string.h> 46: 47: #define DEFAULT 0L 48: #define SUCCESS 0L 49: #define IO_ERROR (HANDLE)0xFFFFFFFF 50: #define WAIT_ERROR 0xFFFFFFFF 51: #define SECTOR_SIZE 1024 52: #define RETURN_IMEDIATELY 0L 53: 54: #if !defined(HEVENT) 55: typedef HANDLE HEVENT; 56: #endif 57: 58: #if !defined(HFILEEX) 59: typedef HANDLE HFILEEX; 60: #endif 61: 62: VOID ErrorMsg ( PSZ psz ) ; 63: VOID Do_BackgroundTask ( VOID ) ; 64: 65: 66: 67: void main ( int argc, char *argv[] ) 68: 69: { 70: 71: 72: HFILEEX hInfile, // Handle to the file to read 73: hOutfile; // Handle to the file to write to 74: 75: HEVENT hEvent ; // Handle to the synchronization Event 76: 77: OVERLAPPED 1.1.1.3 ! root 78: OverLapped ; // The operating system does not automatically ! 79: // track the current file position of a file ! 80: // open for asynchroous I/O. Instead one must ! 81: // manually track this by updating the OVERLAPPED ! 82: // structure. To update this structure one uses ! 83: // the result returned by GetOverLappedResults(). 1.1 root 84: 85: 1.1.1.3 ! root 86: CHAR buf[SECTOR_SIZE] ; // Buffer used by either ! 87: // ReadFile() or WriteFile() 1.1 root 88: 1.1.1.3 ! root 89: DWORD cbBytesRead, // count of bytes read by ReadFile() ! 90: // When asynchonous I/O is performed ! 91: // one must check how many bytes were ! 92: // read by calling GetOverLappedResults(). 1.1 root 93: 94: 1.1.1.3 ! root 95: cbBytesWritten, // count of bytes written by WriteFile() 1.1 root 96: 1.1.1.3 ! root 97: cbBytesTransfered ; // this value is returned by ! 98: // GetOverLappedResults() represents the ! 99: // count of bytes transfered asynchronous 1.1 root 100: 1.1.1.3 ! root 101: DWORD dwStatus, // value returned by GetLastError() 1.1 root 102: dwSuccess ; // return code of last API called 103: 104: BOOL bSuccess ; // return code of last API called 105: 106: CHAR buffer[80] ; 107: 108: /***************************************************************************\ 1.1.1.3 ! root 109: ** ** 1.1 root 110: ** This block of code initalizes all the necessary variables needed to do ** 111: ** asynchronous IO. Specfically it opens the files and initializes the ** 112: ** synchronization EVENT and OVERLAPPED structure needed to keep track ** 113: ** of asynchronous file I/O ** 1.1.1.3 ! root 114: ** ** 1.1 root 115: \***************************************************************************/ 116: 117: 118: if ( argc != 3 ) 119: { 120: printf ( "\nUsage: IO1 input_file output_file\n" ) ; 121: exit ( EXIT_FAILURE ) ; 122: } 123: 124: 125: 126: /* 127: * Open file which we will be copying. Note we are opening this 128: * asynchronously. 129: */ 130: 131: hInfile = CreateFile 1.1.1.3 ! root 132: ( ! 133: argv[1] // File to read ! 134: ,GENERIC_READ // Open file for reading only ! 135: ,FILE_SHARE_READ // Allow others to read file ! 136: ,NULL // No security ! 137: ,OPEN_EXISTING // Fail if file doesn't exit ! 138: ,FILE_FLAG_OVERLAPPED // Async I/o ! 139: ,DEFAULT ! 140: ) ; 1.1 root 141: 142: 143: if ( hInfile == IO_ERROR ) 144: { 145: strcpy ( buffer, "Error opening" ) ; 146: strcat ( buffer, argv[1] ) ; 147: ErrorMsg ( buffer ) ; 148: } 149: 150: 151: /* 152: * Create the file to write to; here we have opened it for synchronous IO. 153: */ 154: 155: hOutfile = CreateFile 1.1.1.3 ! root 156: ( ! 157: argv[2] // File to write to ! 158: ,GENERIC_WRITE // Open file only to write to ! 159: ,DEFAULT // No sharing allowed ! 160: ,NULL // No security ! 161: ,CREATE_NEW // Fail if file exists ! 162: ,FILE_ATTRIBUTE_NORMAL // No attributes ! 163: ,DEFAULT ! 164: ) ; 1.1 root 165: 166: 167: if ( hOutfile == IO_ERROR ) 168: { 169: strcpy ( buffer, "Error opening" ) ; 170: strcat ( buffer, argv[1] ) ; 171: ErrorMsg ( buffer ) ; 172: } 173: 174: 175: 176: /* 177: * Create Synchronoizing Event 178: */ 179: 180: hEvent = CreateEvent 1.1.1.3 ! root 181: ( ! 182: NULL // No security ! 183: ,TRUE // Manual reset ! 184: ,FALSE // Initially Event set to non-signaled state ! 185: ,NULL // No name ! 186: ) ; 1.1 root 187: if ( !hEvent ) 188: ErrorMsg ( "Error creating Event" ) ; 189: 190: 191: /* 192: * Intialize OverLapped structure. We will be using an Event instead 193: * of the file handle for synchronizing I/O. One reason to use a unique 194: * event instead of the file handle would be a so multi-threaded app 195: * would know which thread to unblock when the handle is set to the 196: * signaled state. 197: */ 198: 199: memset ( &OverLapped, 0, sizeof ( OVERLAPPED ) ) ; 200: OverLapped.hEvent = hEvent ; 201: 202: 203: bSuccess = TRUE ; 204: 205: 206: /***************************************************************************\ 207: ** ** 208: ** This is the main function of this program. Here we loop until the file ** 209: ** has been copied. Notice that even though we are using asynchronous I/O ** 210: ** ReadFile() may still return sychronously if it can be done fast enough ** 1.1.1.3 ! root 211: ** ** 1.1 root 212: \***************************************************************************/ 213: 214: while ( bSuccess ) 215: { 216: 217: /* 218: * Read file asynchronously 219: */ 220: 221: bSuccess = ReadFile 1.1.1.3 ! root 222: ( ! 223: hInfile // Handle of file to read ! 224: ,buf // Buffer to store input ! 225: ,SECTOR_SIZE // Number of bytes to read ! 226: ,&cbBytesRead // Number of bytes read. See note] ! 227: // above in delcaration ! 228: ,&OverLapped // Used for asynchronous I/O ! 229: ) ; 1.1 root 230: 231: 232: 233: /* 234: * Check whether ReadFile() has completed yet 235: */ 236: if ( !bSuccess && (( dwStatus = GetLastError ()) == ERROR_IO_PENDING ) ) 237: { 1.1.1.3 ! root 238: printf ( "\nIO Pending" ) ; 1.1 root 239: /* 240: * Read not complete yet first execute the background task then check 241: * to the if event "hEvent" set to the signaled state. If the event is 242: * not set signaled state then loop through again - run the background 243: * task and check the event. 244: * 245: */ 246: 247: Do_BackgroundTask () ; 248: 249: dwSuccess = WaitForSingleObject ( hEvent, RETURN_IMEDIATELY ) ; 250: 1.1.1.3 ! root 251: if ( dwSuccess == WAIT_ERROR ) ! 252: ErrorMsg("Error in WaitForSingleObject") ; ! 253: else if ( dwSuccess == SUCCESS ) 1.1 root 254: { 255: 256: bSuccess = GetOverlappedResult( 257: hInfile, &OverLapped, &cbBytesTransfered, FALSE) ; 258: if ( !bSuccess ) 259: ErrorMsg ( "Error in GetOverLappedResult" ) ; 260: else 261: { 1.1.1.3 ! root 262: // Read has completed now find out how many bytes have been read 1.1 root 263: 1.1.1.3 ! root 264: printf ( "\nNumber of bytes transfered is %d\n", cbBytesTransfered ) ; ! 265: OverLapped.Offset += cbBytesTransfered ; ! 266: cbBytesRead = cbBytesTransfered ; 1.1 root 267: } 268: } 269: else if ( dwSuccess == WAIT_TIMEOUT ) 270: Do_BackgroundTask () ; 271: } 272: /* 273: * ReadFile() read file synchronously; update Overlapped structure 274: */ 275: else if ( bSuccess && cbBytesRead != 0 ) 276: { 1.1.1.3 ! root 277: printf ( "\nNumber of bytes transfered is %d\n", cbBytesRead ) ; ! 278: OverLapped.Offset += cbBytesRead ; 1.1 root 279: } 280: /* 281: * ReadFile() has found the end of the file; exit loop 282: */ 283: else if ( bSuccess && cbBytesRead == 0 ) 284: { 1.1.1.3 ! root 285: printf ( "End of file read\n" ) ; ! 286: break ; 1.1 root 287: } 288: /* 289: * An error occured while reading, print out status and exit loop. 290: */ 291: else 1.1.1.3 ! root 292: ErrorMsg ( "Error reading to file" ) ; 1.1 root 293: 294: 295: 296: /* 297: * Write to file synchronously 298: */ 299: bSuccess = WriteFile 1.1.1.3 ! root 300: ( ! 301: hOutfile // Handle of file to write to ! 302: ,buf // Data to write to file ! 303: ,cbBytesRead // Number of bytes to write ! 304: ,&cbBytesWritten // Number of bytes written ! 305: ,NULL // Only need for asynchonous output ! 306: ) ; 1.1 root 307: 308: 309: if ( !bSuccess ) 1.1.1.3 ! root 310: ErrorMsg ( "Error writing to file" ) ; 1.1 root 311: 312: } // End of WHILE loop 313: 314: 315: 1.1.1.3 ! root 316: CloseHandle ( hInfile ) ; // Close handle to input file 1.1 root 317: FlushFileBuffers ( hOutfile ) ; // Make sure all data written to file first 1.1.1.3 ! root 318: CloseHandle ( hOutfile ) ; // Close handle to output file 1.1 root 319: exit ( EXIT_SUCCESS ) ; 320: 321: } 322: 323: 324: 325: /***************************************************************************\ 326: ** ** 327: ** FUNCTION: ErrorMsg(LPTSTR) ** 328: ** ** 329: ** PURPOSE: Prints out an error message the return code of the last API ** 330: ** to fail. ** 331: ** ** 332: ** INPUT: psz: This string is a description of where the code failed in ** 333: ** the module ** 334: ** ** 335: ** OUTPUT: None ** 336: ** ** 337: \****************************************************************************/ 338: 339: VOID ErrorMsg ( PSZ psz ) 340: { 341: 342: printf ("\n%s: return code = %d\n", psz, GetLastError()) ; 343: exit ( EXIT_FAILURE ) ; 344: } 345: 346: /***************************************************************************\ 347: ** ** 348: ** FUNCTION: Do_BackgroundTask ( VOID ) ** 349: ** ** 350: ** PURPOSE: Works in the background while IO sytems ** 351: ** ** 352: ** COMMENTS: ** 353: ** ** 354: ** Currently this does nothing if I have the time I will come up ** 355: ** with some silly task to keep the user entertained. ** 356: ** ** 357: ** INPUT: None ** 358: ** ** 359: ** OUTPUT: None ** 360: ** ** 361: \***************************************************************************/ 362: 363: VOID Do_BackgroundTask ( VOID ) 364: { 365: Sleep ( 5000L ) ; 366: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.