source: trunk/src/kernel32/overlappedio.cpp@ 8958

Last change on this file since 8958 was 8958, checked in by sandervl, 23 years ago

Return ERROR_OPERATION_ABORTED in GetOverlappedResult if request was cancelled

File size: 23.8 KB
Line 
1/* $Id: overlappedio.cpp,v 1.19 2002-08-04 15:26:52 sandervl Exp $ */
2
3/*
4 * Win32 overlapped IO class
5 *
6 * Copyright 2001 Sander van Leeuwen <sandervl@xs4all.nl>
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 */
11
12
13
14#include <os2win.h>
15#include <string.h>
16#include <handlemanager.h>
17#include <heapstring.h>
18#include <overlappedio.h>
19#include "oslibdos.h"
20
21#define DBG_LOCALLOG DBG_overlappedio
22#include "dbglocal.h"
23
24
25//******************************************************************************
26//******************************************************************************
27OverlappedIOHandler::OverlappedIOHandler(LPOVERLAPPED_HANDLER lpReadHandler,
28 LPOVERLAPPED_HANDLER lpWriteHandler,
29 LPOVERLAPPED_HANDLER lpPollHandler,
30 BOOL fFullDuplex) :
31 hThreadRead(0), hThreadWrite(0), hThreadPoll(0), refCount(0)
32{
33 OverlappedIOError errcode = OutOfMemory;
34
35 this->fFullDuplex = fFullDuplex;
36
37 if(lpReadHandler == NULL) {
38 throw(InvalidParameter);
39 }
40
41 pending[ASYNC_INDEX_READ] = pending[ASYNC_INDEX_WRITE] = NULL;
42 pending [ASYNC_INDEX_POLL] = pending [ASYNC_INDEX_BUSY] = NULL;
43
44 this->lpReadHandler = lpReadHandler;
45 this->lpWriteHandler = lpWriteHandler;
46 this->lpPollHandler = lpPollHandler;
47
48 ::InitializeCriticalSection(&critsect);
49 //poll, read & write event semaphores are auto-reset (one thread wakes up
50 //after a SetEvent call)
51 hEventPoll = ::CreateEventA(NULL, FALSE, FALSE, NULL);
52 hEventRead = ::CreateEventA(NULL, FALSE, FALSE, NULL);
53 hEventWrite = ::CreateEventA(NULL, FALSE, FALSE, NULL);
54
55 dprintf(("OverlappedIOThread: hEventRead %x hEventWrite %x hEventPoll %x", hEventRead, hEventWrite, hEventPoll));
56
57 //the exit & cancel event semaphores are manual reset, because these events
58 //must be able to wake up multiple threads
59 hEventExit = ::CreateEventA(NULL, TRUE, FALSE, NULL);
60 hEventCancel = ::CreateEventA(NULL, TRUE, FALSE, NULL);
61 if(!hEventPoll || !hEventRead || !hEventWrite || !hEventExit || !hEventCancel)
62 {
63 DebugInt3();
64 errcode = EventCreationFailed;
65 goto failed;
66 }
67
68 DWORD dwThreadId;
69 LPOVERLAPPED_THREAD_PARAM threadparam;
70
71 dwAsyncType = (lpWriteHandler && fFullDuplex) ? ASYNCIO_READ : ASYNCIO_READWRITE;
72 threadparam = (LPOVERLAPPED_THREAD_PARAM)malloc(sizeof(OVERLAPPED_THREAD_PARAM));
73 if(!threadparam) goto outofmem;
74 threadparam->dwOperation = dwAsyncType;
75 threadparam->lpOverlappedObj = this;
76 hThreadRead = ::CreateThread(NULL, 32*1024, OverlappedIOThread, (LPVOID)threadparam, 0, &dwThreadId);
77 if(hThreadRead) {//thread uses this object; keep reference count to avoid premature destruction
78 AddRef();
79 }
80
81 if(lpWriteHandler && fFullDuplex) {
82 dwAsyncType |= ASYNCIO_WRITE;
83
84 threadparam = (LPOVERLAPPED_THREAD_PARAM)malloc(sizeof(OVERLAPPED_THREAD_PARAM));
85 if(!threadparam) goto outofmem;
86 threadparam->dwOperation = ASYNCIO_WRITE;
87 threadparam->lpOverlappedObj = this;
88 hThreadWrite = ::CreateThread(NULL, 32*1024, OverlappedIOThread, (LPVOID)threadparam, 0, &dwThreadId);
89 if(hThreadWrite) {//thread uses this object; keep reference count to avoid premature destruction
90 AddRef();
91 }
92 }
93
94 if(lpPollHandler) {
95 dwAsyncType |= ASYNCIO_POLL;
96
97 threadparam = (LPOVERLAPPED_THREAD_PARAM)malloc(sizeof(OVERLAPPED_THREAD_PARAM));
98 if(!threadparam) goto outofmem;
99 threadparam->dwOperation = ASYNCIO_POLL;
100 threadparam->lpOverlappedObj = this;
101 hThreadPoll = ::CreateThread(NULL, 32*1024, OverlappedIOThread, (LPVOID)threadparam, 0, &dwThreadId);
102 SetThreadPriority(hThreadPoll, THREAD_PRIORITY_TIME_CRITICAL);
103 if(hThreadPoll) {//thread uses this object; keep reference count to avoid premature destruction
104 AddRef();
105 }
106 }
107
108 if((lpPollHandler && !hThreadPoll) || !hThreadRead || (lpWriteHandler && fFullDuplex && !hThreadWrite))
109 {
110 DebugInt3();
111 errcode = ThreadCreationFailed;
112 goto failed;
113 }
114 return;
115
116outofmem:
117 errcode = OutOfMemory;
118 //fall through
119failed:
120 //SvL: NOTE: We might not fail gracefully when threads have already been
121 // created. (thread accessing memory that has been freed)
122 // Don't feel like wasting time to fix this as this should never
123 // happen anyway.
124 if(hEventExit) {
125 ::SetEvent(hEventExit);
126 ::CloseHandle(hEventExit);
127 }
128
129 if(hEventRead) ::CloseHandle(hEventRead);
130 if(hEventWrite) ::CloseHandle(hEventWrite);
131 if(hEventPoll) ::CloseHandle(hEventPoll);
132
133 if(hThreadRead) ::CloseHandle(hThreadRead);
134 if(hThreadPoll) ::CloseHandle(hThreadPoll);
135 if(hThreadWrite) ::CloseHandle(hThreadWrite);
136 ::DeleteCriticalSection(&critsect);
137
138 throw(errcode);
139}
140//******************************************************************************
141//******************************************************************************
142OverlappedIOHandler::~OverlappedIOHandler()
143{
144 dprintf(("~OverlappedIOHandler: signalling overlapped threads"));
145 ::SetEvent(hEventExit);
146
147 ::CloseHandle(hEventExit);
148 ::CloseHandle(hEventRead);
149 ::CloseHandle(hEventWrite);
150 ::CloseHandle(hEventPoll);
151
152 ::CloseHandle(hThreadRead);
153 if(hThreadPoll) ::CloseHandle(hThreadPoll);
154 if(hThreadWrite) ::CloseHandle(hThreadWrite);
155
156 DeleteCriticalSection(&critsect);
157}
158//******************************************************************************
159//******************************************************************************
160DWORD OverlappedIOHandler::AddRef()
161{
162 return InterlockedIncrement(&refCount);
163}
164//******************************************************************************
165//******************************************************************************
166DWORD OverlappedIOHandler::Release(BOOL fSignalExit)
167{
168 if(fSignalExit) {
169 ::SetEvent(hEventExit);
170 }
171 if(InterlockedDecrement(&refCount) == 0) {
172 dprintf(("OverlappedIOHandler::Release -> delete now"));
173 delete this;
174 return 0;
175 }
176 return refCount;
177}
178//******************************************************************************
179//******************************************************************************
180DWORD CALLBACK OverlappedIOThread(LPVOID lpThreadParam)
181{
182 LPOVERLAPPED_THREAD_PARAM threadparam = (LPOVERLAPPED_THREAD_PARAM)lpThreadParam;
183 DWORD dwOperation;
184 OverlappedIOHandler *lpOverlappedObj;
185
186 if(threadparam == NULL || threadparam->lpOverlappedObj == NULL) {
187 DebugInt3();
188 return 0;
189 }
190 lpOverlappedObj = threadparam->lpOverlappedObj;
191 dwOperation = threadparam->dwOperation;
192 //free thread parameter first
193 free(threadparam);
194
195 return lpOverlappedObj->threadHandler(dwOperation);
196}
197//******************************************************************************
198//******************************************************************************
199DWORD OverlappedIOHandler::threadHandler(DWORD dwOperation)
200{
201 LPASYNCIOREQUEST lpRequest;
202 LPOVERLAPPED lpOverlapped;
203 HANDLE hEvents[2];
204 HANDLE hEventsWait[2];
205 HANDLE hHandle;
206 DWORD ret, dwTimeOut, dwResult;
207 int index;
208
209 dprintf(("OverlappedIOThread: started for event %d", dwOperation));
210 switch(dwOperation) {
211 case ASYNCIO_READ:
212 case ASYNCIO_READWRITE:
213 hEvents[0] = hEventRead;
214 index = ASYNC_INDEX_READ;
215 break;
216
217 case ASYNCIO_WRITE:
218 hEvents[0] = hEventWrite;
219 index = ASYNC_INDEX_WRITE;
220 break;
221
222 case ASYNCIO_POLL:
223 hEvents[0] = hEventPoll;
224 index = ASYNC_INDEX_POLL;
225 break;
226 default:
227 DebugInt3();
228 }
229 hEvents[1] = hEventExit;
230
231 while(TRUE)
232 {
233 ret = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
234 if(ret == WAIT_FAILED) {
235 dprintf(("!WARNING!: WaitForMultipleObjects -> WAIT_FAILED!"));
236 break;
237 }
238 //if hEventExit has been signalled, then we are told to exit
239 if(ret == (WAIT_OBJECT_0+1)) {
240 dprintf(("end of threadHandler signalled"));
241 break;
242 }
243 //process all pending jobs
244 while(TRUE)
245 {
246 ::EnterCriticalSection(&critsect);
247 if(pending[index] == NULL) {
248 ::LeaveCriticalSection(&critsect);
249 break;
250 }
251 lpRequest = pending[index];
252 pending[index] = lpRequest->next;
253
254 //add to the head of process list
255 lpRequest->next = pending[ASYNC_INDEX_BUSY];
256 pending[ASYNC_INDEX_BUSY] = lpRequest;
257 ::LeaveCriticalSection(&critsect);
258
259 lpOverlapped = lpRequest->lpOverlapped;;
260 hHandle = lpRequest->hHandle;
261
262#ifdef DEBUG
263 switch(lpRequest->dwAsyncType) {
264 case ASYNCIO_READ:
265 case ASYNCIO_WRITE:
266 case ASYNCIO_POLL:
267 break;
268 default:
269 DebugInt3();
270 break;
271 }
272#endif
273 switch(dwOperation) {
274 case ASYNCIO_READ:
275 case ASYNCIO_READWRITE:
276 case ASYNCIO_WRITE:
277 if(lpRequest->dwAsyncType == ASYNCIO_READ || lpWriteHandler == NULL) {
278 lpRequest->dwLastError = lpReadHandler(lpRequest, &dwResult, NULL);
279 }
280 else lpRequest->dwLastError = lpWriteHandler(lpRequest, &dwResult, NULL);
281
282 if(!lpRequest->fCancelled)
283 {
284 lpOverlapped->Internal = lpRequest->dwLastError;
285 lpOverlapped->InternalHigh = dwResult;
286
287 //must NOT store result in specified location!!! (stack corruption)
288 //if(lpRequest->lpdwResult) {
289 // *lpRequest->lpdwResult = dwResult;
290 //}
291#ifdef DEBUG
292 if(lpRequest->dwAsyncType == ASYNCIO_READ) {
293 dprintf(("ASYNCIO_READ %x finished; result %x, last error %d", lpOverlapped, dwResult, lpRequest->dwLastError));
294 }
295 else dprintf(("ASYNCIO_WRITE %x finished; result %x, last error %d", lpOverlapped, dwResult, lpRequest->dwLastError));
296#endif
297 //wake up user thread
298 ::SetEvent(lpOverlapped->hEvent);
299 }
300 break;
301
302 case ASYNCIO_POLL:
303 hEventsWait[0] = hEventCancel;
304 hEventsWait[1] = hEventExit;
305 ret = WAIT_TIMEOUT;
306 while(TRUE)
307 {
308 dwTimeOut = 0;
309 lpRequest->dwLastError = lpPollHandler(lpRequest, &dwResult, &dwTimeOut);
310 if(lpRequest->dwLastError != ERROR_IO_PENDING) {
311 break;
312 }
313 if(dwTimeOut == 0) {
314 dprintf(("!ERROR!: lpPollHandler returned timeout 0!!"));
315 DebugInt3();
316 break;
317 }
318 //sleep a while to avoid wasting too many cpu cycles; we are woken up when a timeout occurs,
319 //when the operation is cancelled or when the process exits
320 ret = WaitForMultipleObjects(2, hEventsWait, FALSE, dwTimeOut);
321 if(ret != WAIT_TIMEOUT) {
322 dprintf(("ASYNCIO_POLL: WaitForSingleObject didn't time out, abort (ret = %x)", ret));
323 break;
324 }
325 }
326 //Don't access the overlapped & result memory when CancelIo was used to cancel the operation
327 if(ret == WAIT_TIMEOUT && !lpRequest->fCancelled)
328 {
329 dprintf(("ASYNCIO_POLL %x: result %x, last error %d", lpOverlapped, dwResult, lpRequest->dwLastError));
330 lpOverlapped->Internal = lpRequest->dwLastError;
331 lpOverlapped->InternalHigh = dwResult;
332 if(lpRequest->lpdwResult) {
333 *lpRequest->lpdwResult = dwResult;
334 }
335 //wake up user thread
336 ::SetEvent(lpOverlapped->hEvent);
337 }
338 break;
339 }
340 //remove from in-process list and delete async request object
341 removeRequest(ASYNC_INDEX_BUSY, lpRequest);
342 delete lpRequest;
343 } //while(TRUE)
344 }
345 Release(); //decrease reference count
346 return 0;
347}
348//******************************************************************************
349//******************************************************************************
350BOOL OverlappedIOHandler::WriteFile(HANDLE hHandle,
351 LPCVOID lpBuffer,
352 DWORD nNumberOfBytesToWrite,
353 LPDWORD lpNumberOfBytesWritten,
354 LPOVERLAPPED lpOverlapped,
355 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
356 DWORD dwUserData,
357 DWORD dwTimeOut)
358{
359 LPASYNCIOREQUEST lpRequest, current;
360 int index;
361
362 if(!lpOverlapped || lpOverlapped->hEvent == 0) {
363 ::SetLastError(ERROR_INVALID_PARAMETER);
364 return FALSE;
365 }
366
367 lpRequest = new ASYNCIOREQUEST;
368 if(lpRequest == NULL) {
369 ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
370 return FALSE;
371 }
372 lpRequest->dwAsyncType = ASYNCIO_WRITE;
373 lpRequest->hHandle = hHandle;
374 lpRequest->lpBuffer = lpBuffer;
375 lpRequest->nNumberOfBytes = nNumberOfBytesToWrite;
376 //must NOT store result in specified location!!! (stack corruption)
377//// lpRequest->lpdwResult = lpNumberOfBytesWritten;
378 lpRequest->lpdwResult = NULL;
379 lpRequest->lpOverlapped = lpOverlapped;
380 lpRequest->lpCompletionRoutine = lpCompletionRoutine;
381 lpRequest->dwUserData = dwUserData;
382 lpRequest->dwTimeOut = dwTimeOut;
383 lpRequest->next = NULL;
384
385 if(dwAsyncType & ASYNCIO_READWRITE) {
386 index = ASYNC_INDEX_READ;
387 }
388 else index = ASYNC_INDEX_WRITE;
389
390 addRequest(index, lpRequest);
391
392 lpOverlapped->Internal = STATUS_PENDING;
393 lpOverlapped->InternalHigh = 0;
394 //reset overlapped semaphore to non-signalled
395 ::ResetEvent(lpOverlapped->hEvent);
396
397 //wake up async thread
398 ::SetEvent((dwAsyncType & ASYNCIO_READWRITE) ? hEventRead : hEventWrite);
399
400 ::SetLastError(ERROR_IO_PENDING);
401 return FALSE;
402}
403//******************************************************************************
404//******************************************************************************
405BOOL OverlappedIOHandler::ReadFile(HANDLE hHandle,
406 LPCVOID lpBuffer,
407 DWORD nNumberOfBytesToRead,
408 LPDWORD lpNumberOfBytesRead,
409 LPOVERLAPPED lpOverlapped,
410 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
411 DWORD dwUserData,
412 DWORD dwTimeOut)
413{
414 LPASYNCIOREQUEST lpRequest, current;
415
416 if(!lpOverlapped || lpOverlapped->hEvent == 0) {
417 ::SetLastError(ERROR_INVALID_PARAMETER);
418 return FALSE;
419 }
420
421 lpRequest = new ASYNCIOREQUEST;
422 if(lpRequest == NULL) {
423 ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
424 return FALSE;
425 }
426 lpRequest->dwAsyncType = ASYNCIO_READ;
427 lpRequest->hHandle = hHandle;
428 lpRequest->lpBuffer = lpBuffer;
429 lpRequest->nNumberOfBytes = nNumberOfBytesToRead;
430 //must NOT store result in specified location!!! (stack corruption)
431//// lpRequest->lpdwResult = lpNumberOfBytesRead;
432 lpRequest->lpdwResult = NULL;
433 lpRequest->lpOverlapped = lpOverlapped;
434 lpRequest->lpCompletionRoutine = lpCompletionRoutine;
435 lpRequest->dwUserData = dwUserData;
436 lpRequest->dwTimeOut = dwTimeOut;
437 lpRequest->next = NULL;
438
439 addRequest(ASYNC_INDEX_READ, lpRequest);
440
441 lpOverlapped->Internal = STATUS_PENDING;
442 lpOverlapped->InternalHigh = 0;
443 //reset overlapped semaphore to non-signalled
444 ::ResetEvent(lpOverlapped->hEvent);
445
446 //wake up async thread
447 ::SetEvent(hEventRead);
448 ::SetLastError(ERROR_IO_PENDING);
449 return FALSE;
450}
451//******************************************************************************
452//******************************************************************************
453BOOL OverlappedIOHandler::WaitForEvent(HANDLE hHandle,
454 DWORD dwEventMask,
455 LPDWORD lpfdwEvtMask,
456 LPOVERLAPPED lpOverlapped,
457 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
458 DWORD dwUserData,
459 DWORD dwTimeOut)
460{
461 LPASYNCIOREQUEST lpRequest, current;
462 DWORD dwLastError, dwResult;
463
464 if(!lpOverlapped || lpOverlapped->hEvent == 0) {
465 ::SetLastError(ERROR_INVALID_PARAMETER);
466 return FALSE;
467 }
468 if(!lpPollHandler) {
469 DebugInt3();
470 ::SetLastError(ERROR_INVALID_PARAMETER);
471 return FALSE;
472 }
473
474 lpRequest = new ASYNCIOREQUEST;
475 if(lpRequest == NULL) {
476 ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
477 return FALSE;
478 }
479 lpRequest->dwAsyncType = ASYNCIO_POLL;
480 lpRequest->hHandle = hHandle;
481 lpRequest->lpBuffer = NULL;
482 lpRequest->nNumberOfBytes = 0;
483 //must store result also in specified location
484 lpRequest->lpdwResult = lpfdwEvtMask;
485 lpRequest->lpOverlapped = lpOverlapped;
486 lpRequest->lpCompletionRoutine = lpCompletionRoutine;
487 lpRequest->dwUserData = dwUserData;
488 lpRequest->dwTimeOut = dwTimeOut;
489 lpRequest->dwEventMask = dwEventMask;
490 lpRequest->next = NULL;
491
492 lpOverlapped->Internal = STATUS_PENDING;
493 lpOverlapped->InternalHigh = 0;
494 //reset overlapped semaphore to non-signalled
495 ::ResetEvent(lpOverlapped->hEvent);
496
497 //first check if the event has already occured; if so, return result
498 //immediately
499 dwLastError = lpPollHandler(lpRequest, &dwResult, &dwTimeOut);
500 if(dwLastError != ERROR_IO_PENDING)
501 {
502 dprintf(("OverlappedIOHandler::WaitForEvent %x: result %x, last error %d", lpOverlapped, dwResult, dwLastError));
503 lpOverlapped->Internal = dwLastError;
504 lpOverlapped->InternalHigh = dwResult;
505 if(lpfdwEvtMask) {
506 *lpfdwEvtMask = dwResult;
507 }
508 //wake up user thread
509 ::SetEvent(lpOverlapped->hEvent);
510
511 delete lpRequest;
512 ::SetLastError(dwLastError);
513 return (dwLastError == ERROR_SUCCESS);
514 }
515
516 addRequest(ASYNC_INDEX_POLL, lpRequest);
517
518 //wake up async thread
519 ::SetEvent(hEventPoll);
520 ::SetLastError(ERROR_IO_PENDING);
521 return FALSE;
522}
523//******************************************************************************
524//******************************************************************************
525BOOL OverlappedIOHandler::CancelIo(HANDLE hHandle)
526{
527 LPASYNCIOREQUEST lpRequest;
528
529 for(int i=ASYNC_INDEX_READ;i<NR_ASYNC_OPERATIONS;i++)
530 {
531 while(TRUE)
532 {
533 lpRequest = findAndRemoveRequest(i, hHandle);
534
535 if(lpRequest) {
536 //TODO: This doesn't work if multiple handles share the
537 // same OverlappedIOHandler
538 lpRequest->fCancelled = TRUE;
539 //GetOverlappedResult must return this error after the request
540 //has been cancelled!
541 lpRequest->lpOverlapped->Internal = ERROR_OPERATION_ABORTED;
542 ::SetEvent(hEventCancel); //cancel pending operation
543 if(i != ASYNC_INDEX_BUSY) {//thread that handles the request will delete it
544 delete lpRequest;
545 }
546 }
547 else break;
548 }
549 }
550 //TODO: return error if there were no pending requests???
551 ::SetLastError(ERROR_SUCCESS);
552 return TRUE;
553}
554//******************************************************************************
555//******************************************************************************
556BOOL OverlappedIOHandler::GetOverlappedResult(HANDLE hHandle,
557 LPOVERLAPPED lpOverlapped,
558 LPDWORD lpcbTransfer,
559 BOOL fWait)
560{
561 DWORD ret;
562
563 ret = ::WaitForSingleObject(lpOverlapped->hEvent, (fWait) ? INFINITE : 0);
564
565 if(lpcbTransfer)
566 *lpcbTransfer = lpOverlapped->InternalHigh;
567
568 ::SetLastError(lpOverlapped->Internal);
569
570 dprintf(("GetOverlappedResult %x -> result %d last error %d", hHandle, lpOverlapped->InternalHigh, lpOverlapped->Internal));
571 return (ret == WAIT_OBJECT_0);
572}
573//******************************************************************************
574//******************************************************************************
575LPASYNCIOREQUEST OverlappedIOHandler::findAndRemoveRequest(int index, HANDLE hHandle)
576{
577 LPASYNCIOREQUEST lpRequest, lpFound = NULL;
578
579 ::EnterCriticalSection(&critsect);
580 if(pending[index])
581 {
582 if(pending[index]->hHandle != hHandle)
583 {
584 lpRequest = pending[index];
585 while(lpRequest->next) {
586 if(lpRequest->next->hHandle == hHandle) {
587 lpFound = lpRequest->next;
588 lpRequest->next = lpFound->next;
589 break;
590 }
591 lpRequest = lpRequest->next;
592 }
593 }
594 else {
595 lpFound = pending[index];
596 pending[index] = lpFound->next;
597 }
598 }
599 ::LeaveCriticalSection(&critsect);
600 return lpFound;
601}
602//******************************************************************************
603//******************************************************************************
604void OverlappedIOHandler::addRequest(int index, LPASYNCIOREQUEST lpRequest)
605{
606 LPASYNCIOREQUEST current;
607
608 ::EnterCriticalSection(&critsect);
609 if(pending[index]) {
610 current = pending[index];
611 while(current->next) {
612 current = current->next;
613 }
614 current->next = lpRequest;
615 }
616 else pending[index] = lpRequest;
617 ::LeaveCriticalSection(&critsect);
618}
619//******************************************************************************
620//******************************************************************************
621void OverlappedIOHandler::removeRequest(int index, LPASYNCIOREQUEST lpRequest)
622{
623 LPASYNCIOREQUEST current;
624
625 ::EnterCriticalSection(&critsect);
626 if(pending[index]) {
627 if(pending[index] == lpRequest) {
628 pending[index] = lpRequest->next;
629 }
630 else {
631 current = pending[index];
632 while(current->next && current->next != lpRequest) {
633 current = current->next;
634 }
635 if(current->next) {
636 current->next = lpRequest->next;
637 }
638 else {
639 dprintf(("!ERROR!: request %x not found!!!!!!", lpRequest));
640 DebugInt3();
641 }
642 }
643 }
644 //else removed from list by cancelio
645 ::LeaveCriticalSection(&critsect);
646}
647//******************************************************************************
648//******************************************************************************
649
Note: See TracBrowser for help on using the repository browser.