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

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

Overlapped IO bugfixes for synchronization + ip logging fix

File size: 24.1 KB
Line 
1/* $Id: overlappedio.cpp,v 1.20 2002-10-10 16:28:40 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 lpOverlapped->Internal = STATUS_PENDING;
391 lpOverlapped->InternalHigh = 0;
392 //reset overlapped semaphore to non-signalled
393 ::ResetEvent(lpOverlapped->hEvent);
394
395 //Add request to queue; must make sure we do this right before waking the async thread
396 addRequest(index, lpRequest);
397
398 //wake up async thread
399 ::SetEvent((dwAsyncType & ASYNCIO_READWRITE) ? hEventRead : hEventWrite);
400
401 ::SetLastError(ERROR_IO_PENDING);
402 return FALSE;
403}
404//******************************************************************************
405//******************************************************************************
406BOOL OverlappedIOHandler::ReadFile(HANDLE hHandle,
407 LPCVOID lpBuffer,
408 DWORD nNumberOfBytesToRead,
409 LPDWORD lpNumberOfBytesRead,
410 LPOVERLAPPED lpOverlapped,
411 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
412 DWORD dwUserData,
413 DWORD dwTimeOut)
414{
415 LPASYNCIOREQUEST lpRequest, current;
416
417 if(!lpOverlapped || lpOverlapped->hEvent == 0) {
418 ::SetLastError(ERROR_INVALID_PARAMETER);
419 return FALSE;
420 }
421
422 lpRequest = new ASYNCIOREQUEST;
423 if(lpRequest == NULL) {
424 ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
425 return FALSE;
426 }
427 lpRequest->dwAsyncType = ASYNCIO_READ;
428 lpRequest->hHandle = hHandle;
429 lpRequest->lpBuffer = lpBuffer;
430 lpRequest->nNumberOfBytes = nNumberOfBytesToRead;
431 //must NOT store result in specified location!!! (stack corruption)
432//// lpRequest->lpdwResult = lpNumberOfBytesRead;
433 lpRequest->lpdwResult = NULL;
434 lpRequest->lpOverlapped = lpOverlapped;
435 lpRequest->lpCompletionRoutine = lpCompletionRoutine;
436 lpRequest->dwUserData = dwUserData;
437 lpRequest->dwTimeOut = dwTimeOut;
438 lpRequest->next = NULL;
439
440 lpOverlapped->Internal = STATUS_PENDING;
441 lpOverlapped->InternalHigh = 0;
442 //reset overlapped semaphore to non-signalled
443 ::ResetEvent(lpOverlapped->hEvent);
444
445 //Add request to queue; must make sure we do this right before waking the async thread
446 addRequest(ASYNC_INDEX_READ, lpRequest);
447
448 //wake up async thread
449 ::SetEvent(hEventRead);
450 ::SetLastError(ERROR_IO_PENDING);
451 return FALSE;
452}
453//******************************************************************************
454//******************************************************************************
455BOOL OverlappedIOHandler::WaitForEvent(HANDLE hHandle,
456 DWORD dwEventMask,
457 LPDWORD lpfdwEvtMask,
458 LPOVERLAPPED lpOverlapped,
459 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
460 DWORD dwUserData,
461 DWORD dwTimeOut)
462{
463 LPASYNCIOREQUEST lpRequest, current;
464 DWORD dwLastError, dwResult;
465
466 if(!lpOverlapped || lpOverlapped->hEvent == 0) {
467 ::SetLastError(ERROR_INVALID_PARAMETER);
468 return FALSE;
469 }
470 if(!lpPollHandler) {
471 DebugInt3();
472 ::SetLastError(ERROR_INVALID_PARAMETER);
473 return FALSE;
474 }
475
476 lpRequest = new ASYNCIOREQUEST;
477 if(lpRequest == NULL) {
478 ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
479 return FALSE;
480 }
481 lpRequest->dwAsyncType = ASYNCIO_POLL;
482 lpRequest->hHandle = hHandle;
483 lpRequest->lpBuffer = NULL;
484 lpRequest->nNumberOfBytes = 0;
485 //must store result also in specified location
486 lpRequest->lpdwResult = lpfdwEvtMask;
487 lpRequest->lpOverlapped = lpOverlapped;
488 lpRequest->lpCompletionRoutine = lpCompletionRoutine;
489 lpRequest->dwUserData = dwUserData;
490 lpRequest->dwTimeOut = dwTimeOut;
491 lpRequest->dwEventMask = dwEventMask;
492 lpRequest->next = NULL;
493
494 lpOverlapped->Internal = STATUS_PENDING;
495 lpOverlapped->InternalHigh = 0;
496 //reset overlapped semaphore to non-signalled
497 ::ResetEvent(lpOverlapped->hEvent);
498
499 //first check if the event has already occured; if so, return result
500 //immediately
501 dwLastError = lpPollHandler(lpRequest, &dwResult, &dwTimeOut);
502 if(dwLastError != ERROR_IO_PENDING)
503 {
504 dprintf(("OverlappedIOHandler::WaitForEvent %x: result %x, last error %d", lpOverlapped, dwResult, dwLastError));
505 lpOverlapped->Internal = dwLastError;
506 lpOverlapped->InternalHigh = dwResult;
507 if(lpfdwEvtMask) {
508 *lpfdwEvtMask = dwResult;
509 }
510 //wake up user thread
511 ::SetEvent(lpOverlapped->hEvent);
512
513 delete lpRequest;
514 ::SetLastError(dwLastError);
515 return (dwLastError == ERROR_SUCCESS);
516 }
517
518 //add request to list; must make sure we do this right before waking the async thread
519 addRequest(ASYNC_INDEX_POLL, lpRequest);
520
521 //wake up async thread
522 ::SetEvent(hEventPoll);
523 ::SetLastError(ERROR_IO_PENDING);
524 return FALSE;
525}
526//******************************************************************************
527//******************************************************************************
528BOOL OverlappedIOHandler::CancelIo(HANDLE hHandle)
529{
530 LPASYNCIOREQUEST lpRequest;
531
532 for(int i=ASYNC_INDEX_READ;i<NR_ASYNC_OPERATIONS;i++)
533 {
534 while(TRUE)
535 {
536 lpRequest = findAndRemoveRequest(i, hHandle);
537
538 if(lpRequest) {
539 //TODO: This doesn't work if multiple handles share the
540 // same OverlappedIOHandler
541 lpRequest->fCancelled = TRUE;
542 //GetOverlappedResult must return this error after the request
543 //has been cancelled!
544 lpRequest->lpOverlapped->Internal = ERROR_OPERATION_ABORTED;
545 ::SetEvent(hEventCancel); //cancel pending operation
546 if(i != ASYNC_INDEX_BUSY) {//thread that handles the request will delete it
547 delete lpRequest;
548 }
549 }
550 else break;
551 }
552 }
553 //TODO: return error if there were no pending requests???
554 ::SetLastError(ERROR_SUCCESS);
555 return TRUE;
556}
557//******************************************************************************
558//******************************************************************************
559BOOL OverlappedIOHandler::GetOverlappedResult(HANDLE hHandle,
560 LPOVERLAPPED lpOverlapped,
561 LPDWORD lpcbTransfer,
562 BOOL fWait)
563{
564 DWORD ret;
565
566 ret = ::WaitForSingleObject(lpOverlapped->hEvent, (fWait) ? INFINITE : 0);
567
568 if(lpcbTransfer)
569 *lpcbTransfer = lpOverlapped->InternalHigh;
570
571 ::SetLastError(lpOverlapped->Internal);
572
573 dprintf(("GetOverlappedResult %x -> result %d last error %d", hHandle, lpOverlapped->InternalHigh, lpOverlapped->Internal));
574 return (ret == WAIT_OBJECT_0);
575}
576//******************************************************************************
577//******************************************************************************
578LPASYNCIOREQUEST OverlappedIOHandler::findAndRemoveRequest(int index, HANDLE hHandle)
579{
580 LPASYNCIOREQUEST lpRequest, lpFound = NULL;
581
582 ::EnterCriticalSection(&critsect);
583 if(pending[index])
584 {
585 if(pending[index]->hHandle != hHandle)
586 {
587 lpRequest = pending[index];
588 while(lpRequest->next) {
589 if(lpRequest->next->hHandle == hHandle) {
590 lpFound = lpRequest->next;
591 lpRequest->next = lpFound->next;
592 break;
593 }
594 lpRequest = lpRequest->next;
595 }
596 }
597 else {
598 lpFound = pending[index];
599 pending[index] = lpFound->next;
600 }
601 }
602 ::LeaveCriticalSection(&critsect);
603 return lpFound;
604}
605//******************************************************************************
606//******************************************************************************
607void OverlappedIOHandler::addRequest(int index, LPASYNCIOREQUEST lpRequest)
608{
609 LPASYNCIOREQUEST current;
610
611 ::EnterCriticalSection(&critsect);
612 if(pending[index]) {
613 current = pending[index];
614 while(current->next) {
615 current = current->next;
616 }
617 current->next = lpRequest;
618 }
619 else pending[index] = lpRequest;
620 ::LeaveCriticalSection(&critsect);
621}
622//******************************************************************************
623//******************************************************************************
624void OverlappedIOHandler::removeRequest(int index, LPASYNCIOREQUEST lpRequest)
625{
626 LPASYNCIOREQUEST current;
627
628 ::EnterCriticalSection(&critsect);
629 if(pending[index]) {
630 if(pending[index] == lpRequest) {
631 pending[index] = lpRequest->next;
632 }
633 else {
634 current = pending[index];
635 while(current->next && current->next != lpRequest) {
636 current = current->next;
637 }
638 if(current->next) {
639 current->next = lpRequest->next;
640 }
641 else {
642 dprintf(("!ERROR!: request %x not found!!!!!!", lpRequest));
643 DebugInt3();
644 }
645 }
646 }
647 //else removed from list by cancelio
648 ::LeaveCriticalSection(&critsect);
649}
650//******************************************************************************
651//******************************************************************************
652
Note: See TracBrowser for help on using the repository browser.