|
|
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.