- New winsock (part 2 of x)
[reactos.git] / dll / win32 / mswsock / msafd / async.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winsock 2 SPI
4 * FILE: lib/mswsock/lib/init.c
5 * PURPOSE: DLL Initialization
6 */
7
8 /* INCLUDES ******************************************************************/
9 #include "msafd.h"
10
11 /* DATA **********************************************************************/
12
13 HANDLE SockAsyncQueuePort;
14 LONG SockAsyncThreadReferenceCount;
15
16 /* FUNCTIONS *****************************************************************/
17
18 INT
19 WSPAPI
20 SockCreateAsyncQueuePort(VOID)
21 {
22 NTSTATUS Status;
23 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
24
25 /* Create the port */
26 Status = NtCreateIoCompletion(&SockAsyncQueuePort,
27 IO_COMPLETION_ALL_ACCESS,
28 NULL,
29 -1);
30
31 /* Protect Handle */
32 HandleFlags.ProtectFromClose = TRUE;
33 HandleFlags.Inherit = FALSE;
34 Status = NtSetInformationObject(SockAsyncQueuePort,
35 ObjectHandleFlagInformation,
36 &HandleFlags,
37 sizeof(HandleFlags));
38
39 /* Return */
40 return NO_ERROR;
41 }
42
43 VOID
44 WSPAPI
45 SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback,
46 IN PVOID Context,
47 IN PIO_STATUS_BLOCK IoStatusBlock)
48 {
49 /* Call the completion routine */
50 (*Callback)(Context, IoStatusBlock);
51 }
52
53 BOOLEAN
54 WSPAPI
55 SockCheckAndReferenceAsyncThread(VOID)
56 {
57 LONG Count;
58 HANDLE hAsyncThread;
59 DWORD AsyncThreadId;
60 HANDLE AsyncEvent;
61 NTSTATUS Status;
62 INT ErrorCode;
63 HINSTANCE hInstance;
64 PWINSOCK_TEB_DATA ThreadData;
65
66 /* Loop while trying to increase the reference count */
67 do
68 {
69 /* Get the count, and check if it's already been started */
70 Count = SockAsyncThreadReferenceCount;
71 if ((Count > 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount,
72 Count + 1,
73 Count) == Count))
74 {
75 /* Simply return */
76 return TRUE;
77 }
78 } while (Count > 0);
79
80 /* Acquire the lock */
81 SockAcquireRwLockExclusive(&SocketGlobalLock);
82
83 /* Check if no completion port exists already and create it */
84 if (!SockAsyncQueuePort) SockCreateAsyncQueuePort();
85
86 /* Create an extra reference so the thread stays alive */
87 ErrorCode = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
88 (LPCTSTR)WSPStartup,
89 &hInstance);
90
91 /* Create the Async Event */
92 Status = NtCreateEvent(&AsyncEvent,
93 EVENT_ALL_ACCESS,
94 NULL,
95 NotificationEvent,
96 FALSE);
97
98 /* Allocate the TEB Block */
99 ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData));
100 if (!ThreadData)
101 {
102 /* Release the lock, close the event, free extra reference and fail */
103 SockReleaseRwLockExclusive(&SocketGlobalLock);
104 NtClose(AsyncEvent);
105 FreeLibrary(hInstance);
106 return FALSE;
107 }
108
109 /* Initialize thread data */
110 RtlZeroMemory(ThreadData, sizeof(*ThreadData));
111 ThreadData->EventHandle = AsyncEvent;
112 ThreadData->SocketHandle = (SOCKET)hInstance;
113
114 /* Create the Async Thread */
115 hAsyncThread = CreateThread(NULL,
116 0,
117 (LPTHREAD_START_ROUTINE)SockAsyncThread,
118 ThreadData,
119 0,
120 &AsyncThreadId);
121
122 /* Close the Handle */
123 NtClose(hAsyncThread);
124
125 /* Increase the Reference Count */
126 InterlockedExchangeAdd(&SockAsyncThreadReferenceCount, 2);
127
128 /* Release lock and return success */
129 SockReleaseRwLockExclusive(&SocketGlobalLock);
130 return TRUE;
131 }
132
133 INT
134 WSPAPI
135 SockAsyncThread(PVOID Context)
136 {
137 PVOID AsyncContext;
138 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
139 IO_STATUS_BLOCK IoStatusBlock;
140 NTSTATUS Status;
141 LARGE_INTEGER Timeout;
142 PWINSOCK_TEB_DATA ThreadData = (PWINSOCK_TEB_DATA)Context;
143 HINSTANCE hInstance = (HINSTANCE)ThreadData->SocketHandle;
144
145 /* Return the socket handle back to its unhacked value */
146 ThreadData->SocketHandle = INVALID_SOCKET;
147
148 /* Setup the Thread Data pointer */
149 NtCurrentTeb()->WinSockData = ThreadData;
150
151 /* Make the Thread Higher Priority */
152 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
153
154 /* Setup timeout */
155 Timeout.QuadPart = Int32x32To64(300, 10000000);
156
157 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
158 do {
159 /* Get the next completion item */
160 Status = NtRemoveIoCompletion(SockAsyncQueuePort,
161 (PVOID*)&AsyncCompletionRoutine,
162 &AsyncContext,
163 &IoStatusBlock,
164 &Timeout);
165 /* Check for success */
166 if (NT_SUCCESS(Status))
167 {
168 /* Check if this isn't the termination command */
169 if (AsyncCompletionRoutine != (PVOID)-1)
170 {
171 /* Call the routine */
172 SockHandleAsyncIndication(AsyncCompletionRoutine,
173 Context,
174 &IoStatusBlock);
175 }
176 else
177 {
178 /* We have to terminate, fake a timeout */
179 Status = STATUS_TIMEOUT;
180 InterlockedDecrement(&SockAsyncThreadReferenceCount);
181 }
182 }
183 else if ((SockAsyncThreadReferenceCount > 1) && (NT_ERROR(Status)))
184 {
185 /* It Failed, sleep for a second */
186 Sleep(1000);
187 }
188 } while (((Status != STATUS_TIMEOUT) &&
189 (SockWspStartupCount > 0)) ||
190 InterlockedCompareExchange(&SockAsyncThreadReferenceCount, 0, 1) != 1);
191
192 /* Release the lock */
193 SockReleaseRwLockShared(&SocketGlobalLock);
194
195 /* Remove our extra reference */
196 FreeLibraryAndExitThread(hInstance, NO_ERROR);
197 }
198
199 /*
200 * COPYRIGHT: See COPYING in the top level directory
201 * PROJECT: ReactOS Winsock 2 SPI
202 * FILE: lib/mswsock/lib/init.c
203 * PURPOSE: DLL Initialization
204 */
205
206 /* INCLUDES ******************************************************************/
207 #include "msafd.h"
208
209 /* DATA **********************************************************************/
210
211 HANDLE SockAsyncQueuePort;
212 LONG SockAsyncThreadReferenceCount;
213
214 /* FUNCTIONS *****************************************************************/
215
216 INT
217 WSPAPI
218 SockCreateAsyncQueuePort(VOID)
219 {
220 NTSTATUS Status;
221 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
222
223 /* Create the port */
224 Status = NtCreateIoCompletion(&SockAsyncQueuePort,
225 IO_COMPLETION_ALL_ACCESS,
226 NULL,
227 -1);
228
229 /* Protect Handle */
230 HandleFlags.ProtectFromClose = TRUE;
231 HandleFlags.Inherit = FALSE;
232 Status = NtSetInformationObject(SockAsyncQueuePort,
233 ObjectHandleFlagInformation,
234 &HandleFlags,
235 sizeof(HandleFlags));
236
237 /* Return */
238 return NO_ERROR;
239 }
240
241 VOID
242 WSPAPI
243 SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback,
244 IN PVOID Context,
245 IN PIO_STATUS_BLOCK IoStatusBlock)
246 {
247 /* Call the completion routine */
248 (*Callback)(Context, IoStatusBlock);
249 }
250
251 BOOLEAN
252 WSPAPI
253 SockCheckAndReferenceAsyncThread(VOID)
254 {
255 LONG Count;
256 HANDLE hAsyncThread;
257 DWORD AsyncThreadId;
258 HANDLE AsyncEvent;
259 NTSTATUS Status;
260 INT ErrorCode;
261 HINSTANCE hInstance;
262 PWINSOCK_TEB_DATA ThreadData;
263
264 /* Loop while trying to increase the reference count */
265 do
266 {
267 /* Get the count, and check if it's already been started */
268 Count = SockAsyncThreadReferenceCount;
269 if ((Count > 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount,
270 Count + 1,
271 Count) == Count))
272 {
273 /* Simply return */
274 return TRUE;
275 }
276 } while (Count > 0);
277
278 /* Acquire the lock */
279 SockAcquireRwLockExclusive(&SocketGlobalLock);
280
281 /* Check if no completion port exists already and create it */
282 if (!SockAsyncQueuePort) SockCreateAsyncQueuePort();
283
284 /* Create an extra reference so the thread stays alive */
285 ErrorCode = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
286 (LPCTSTR)WSPStartup,
287 &hInstance);
288
289 /* Create the Async Event */
290 Status = NtCreateEvent(&AsyncEvent,
291 EVENT_ALL_ACCESS,
292 NULL,
293 NotificationEvent,
294 FALSE);
295
296 /* Allocate the TEB Block */
297 ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData));
298 if (!ThreadData)
299 {
300 /* Release the lock, close the event, free extra reference and fail */
301 SockReleaseRwLockExclusive(&SocketGlobalLock);
302 NtClose(AsyncEvent);
303 FreeLibrary(hInstance);
304 return FALSE;
305 }
306
307 /* Initialize thread data */
308 RtlZeroMemory(ThreadData, sizeof(*ThreadData));
309 ThreadData->EventHandle = AsyncEvent;
310 ThreadData->SocketHandle = (SOCKET)hInstance;
311
312 /* Create the Async Thread */
313 hAsyncThread = CreateThread(NULL,
314 0,
315 (LPTHREAD_START_ROUTINE)SockAsyncThread,
316 ThreadData,
317 0,
318 &AsyncThreadId);
319
320 /* Close the Handle */
321 NtClose(hAsyncThread);
322
323 /* Increase the Reference Count */
324 InterlockedExchangeAdd(&SockAsyncThreadReferenceCount, 2);
325
326 /* Release lock and return success */
327 SockReleaseRwLockExclusive(&SocketGlobalLock);
328 return TRUE;
329 }
330
331 INT
332 WSPAPI
333 SockAsyncThread(PVOID Context)
334 {
335 PVOID AsyncContext;
336 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
337 IO_STATUS_BLOCK IoStatusBlock;
338 NTSTATUS Status;
339 LARGE_INTEGER Timeout;
340 PWINSOCK_TEB_DATA ThreadData = (PWINSOCK_TEB_DATA)Context;
341 HINSTANCE hInstance = (HINSTANCE)ThreadData->SocketHandle;
342
343 /* Return the socket handle back to its unhacked value */
344 ThreadData->SocketHandle = INVALID_SOCKET;
345
346 /* Setup the Thread Data pointer */
347 NtCurrentTeb()->WinSockData = ThreadData;
348
349 /* Make the Thread Higher Priority */
350 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
351
352 /* Setup timeout */
353 Timeout.QuadPart = Int32x32To64(300, 10000000);
354
355 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
356 do {
357 /* Get the next completion item */
358 Status = NtRemoveIoCompletion(SockAsyncQueuePort,
359 (PVOID*)&AsyncCompletionRoutine,
360 &AsyncContext,
361 &IoStatusBlock,
362 &Timeout);
363 /* Check for success */
364 if (NT_SUCCESS(Status))
365 {
366 /* Check if this isn't the termination command */
367 if (AsyncCompletionRoutine != (PVOID)-1)
368 {
369 /* Call the routine */
370 SockHandleAsyncIndication(AsyncCompletionRoutine,
371 Context,
372 &IoStatusBlock);
373 }
374 else
375 {
376 /* We have to terminate, fake a timeout */
377 Status = STATUS_TIMEOUT;
378 InterlockedDecrement(&SockAsyncThreadReferenceCount);
379 }
380 }
381 else if ((SockAsyncThreadReferenceCount > 1) && (NT_ERROR(Status)))
382 {
383 /* It Failed, sleep for a second */
384 Sleep(1000);
385 }
386 } while (((Status != STATUS_TIMEOUT) &&
387 (SockWspStartupCount > 0)) ||
388 InterlockedCompareExchange(&SockAsyncThreadReferenceCount, 0, 1) != 1);
389
390 /* Release the lock */
391 SockReleaseRwLockShared(&SocketGlobalLock);
392
393 /* Remove our extra reference */
394 FreeLibraryAndExitThread(hInstance, NO_ERROR);
395 }
396
397 /*
398 * COPYRIGHT: See COPYING in the top level directory
399 * PROJECT: ReactOS Winsock 2 SPI
400 * FILE: lib/mswsock/lib/init.c
401 * PURPOSE: DLL Initialization
402 */
403
404 /* INCLUDES ******************************************************************/
405 #include "msafd.h"
406
407 /* DATA **********************************************************************/
408
409 HANDLE SockAsyncQueuePort;
410 LONG SockAsyncThreadReferenceCount;
411
412 /* FUNCTIONS *****************************************************************/
413
414 INT
415 WSPAPI
416 SockCreateAsyncQueuePort(VOID)
417 {
418 NTSTATUS Status;
419 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
420
421 /* Create the port */
422 Status = NtCreateIoCompletion(&SockAsyncQueuePort,
423 IO_COMPLETION_ALL_ACCESS,
424 NULL,
425 -1);
426
427 /* Protect Handle */
428 HandleFlags.ProtectFromClose = TRUE;
429 HandleFlags.Inherit = FALSE;
430 Status = NtSetInformationObject(SockAsyncQueuePort,
431 ObjectHandleFlagInformation,
432 &HandleFlags,
433 sizeof(HandleFlags));
434
435 /* Return */
436 return NO_ERROR;
437 }
438
439 VOID
440 WSPAPI
441 SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback,
442 IN PVOID Context,
443 IN PIO_STATUS_BLOCK IoStatusBlock)
444 {
445 /* Call the completion routine */
446 (*Callback)(Context, IoStatusBlock);
447 }
448
449 BOOLEAN
450 WSPAPI
451 SockCheckAndReferenceAsyncThread(VOID)
452 {
453 LONG Count;
454 HANDLE hAsyncThread;
455 DWORD AsyncThreadId;
456 HANDLE AsyncEvent;
457 NTSTATUS Status;
458 INT ErrorCode;
459 HINSTANCE hInstance;
460 PWINSOCK_TEB_DATA ThreadData;
461
462 /* Loop while trying to increase the reference count */
463 do
464 {
465 /* Get the count, and check if it's already been started */
466 Count = SockAsyncThreadReferenceCount;
467 if ((Count > 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount,
468 Count + 1,
469 Count) == Count))
470 {
471 /* Simply return */
472 return TRUE;
473 }
474 } while (Count > 0);
475
476 /* Acquire the lock */
477 SockAcquireRwLockExclusive(&SocketGlobalLock);
478
479 /* Check if no completion port exists already and create it */
480 if (!SockAsyncQueuePort) SockCreateAsyncQueuePort();
481
482 /* Create an extra reference so the thread stays alive */
483 ErrorCode = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
484 (LPCTSTR)WSPStartup,
485 &hInstance);
486
487 /* Create the Async Event */
488 Status = NtCreateEvent(&AsyncEvent,
489 EVENT_ALL_ACCESS,
490 NULL,
491 NotificationEvent,
492 FALSE);
493
494 /* Allocate the TEB Block */
495 ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData));
496 if (!ThreadData)
497 {
498 /* Release the lock, close the event, free extra reference and fail */
499 SockReleaseRwLockExclusive(&SocketGlobalLock);
500 NtClose(AsyncEvent);
501 FreeLibrary(hInstance);
502 return FALSE;
503 }
504
505 /* Initialize thread data */
506 RtlZeroMemory(ThreadData, sizeof(*ThreadData));
507 ThreadData->EventHandle = AsyncEvent;
508 ThreadData->SocketHandle = (SOCKET)hInstance;
509
510 /* Create the Async Thread */
511 hAsyncThread = CreateThread(NULL,
512 0,
513 (LPTHREAD_START_ROUTINE)SockAsyncThread,
514 ThreadData,
515 0,
516 &AsyncThreadId);
517
518 /* Close the Handle */
519 NtClose(hAsyncThread);
520
521 /* Increase the Reference Count */
522 InterlockedExchangeAdd(&SockAsyncThreadReferenceCount, 2);
523
524 /* Release lock and return success */
525 SockReleaseRwLockExclusive(&SocketGlobalLock);
526 return TRUE;
527 }
528
529 INT
530 WSPAPI
531 SockAsyncThread(PVOID Context)
532 {
533 PVOID AsyncContext;
534 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
535 IO_STATUS_BLOCK IoStatusBlock;
536 NTSTATUS Status;
537 LARGE_INTEGER Timeout;
538 PWINSOCK_TEB_DATA ThreadData = (PWINSOCK_TEB_DATA)Context;
539 HINSTANCE hInstance = (HINSTANCE)ThreadData->SocketHandle;
540
541 /* Return the socket handle back to its unhacked value */
542 ThreadData->SocketHandle = INVALID_SOCKET;
543
544 /* Setup the Thread Data pointer */
545 NtCurrentTeb()->WinSockData = ThreadData;
546
547 /* Make the Thread Higher Priority */
548 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
549
550 /* Setup timeout */
551 Timeout.QuadPart = Int32x32To64(300, 10000000);
552
553 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
554 do {
555 /* Get the next completion item */
556 Status = NtRemoveIoCompletion(SockAsyncQueuePort,
557 (PVOID*)&AsyncCompletionRoutine,
558 &AsyncContext,
559 &IoStatusBlock,
560 &Timeout);
561 /* Check for success */
562 if (NT_SUCCESS(Status))
563 {
564 /* Check if this isn't the termination command */
565 if (AsyncCompletionRoutine != (PVOID)-1)
566 {
567 /* Call the routine */
568 SockHandleAsyncIndication(AsyncCompletionRoutine,
569 Context,
570 &IoStatusBlock);
571 }
572 else
573 {
574 /* We have to terminate, fake a timeout */
575 Status = STATUS_TIMEOUT;
576 InterlockedDecrement(&SockAsyncThreadReferenceCount);
577 }
578 }
579 else if ((SockAsyncThreadReferenceCount > 1) && (NT_ERROR(Status)))
580 {
581 /* It Failed, sleep for a second */
582 Sleep(1000);
583 }
584 } while (((Status != STATUS_TIMEOUT) &&
585 (SockWspStartupCount > 0)) ||
586 InterlockedCompareExchange(&SockAsyncThreadReferenceCount, 0, 1) != 1);
587
588 /* Release the lock */
589 SockReleaseRwLockShared(&SocketGlobalLock);
590
591 /* Remove our extra reference */
592 FreeLibraryAndExitThread(hInstance, NO_ERROR);
593 }
594
595 /*
596 * COPYRIGHT: See COPYING in the top level directory
597 * PROJECT: ReactOS Winsock 2 SPI
598 * FILE: lib/mswsock/lib/init.c
599 * PURPOSE: DLL Initialization
600 */
601
602 /* INCLUDES ******************************************************************/
603 #include "msafd.h"
604
605 /* DATA **********************************************************************/
606
607 HANDLE SockAsyncQueuePort;
608 LONG SockAsyncThreadReferenceCount;
609
610 /* FUNCTIONS *****************************************************************/
611
612 INT
613 WSPAPI
614 SockCreateAsyncQueuePort(VOID)
615 {
616 NTSTATUS Status;
617 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
618
619 /* Create the port */
620 Status = NtCreateIoCompletion(&SockAsyncQueuePort,
621 IO_COMPLETION_ALL_ACCESS,
622 NULL,
623 -1);
624
625 /* Protect Handle */
626 HandleFlags.ProtectFromClose = TRUE;
627 HandleFlags.Inherit = FALSE;
628 Status = NtSetInformationObject(SockAsyncQueuePort,
629 ObjectHandleFlagInformation,
630 &HandleFlags,
631 sizeof(HandleFlags));
632
633 /* Return */
634 return NO_ERROR;
635 }
636
637 VOID
638 WSPAPI
639 SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback,
640 IN PVOID Context,
641 IN PIO_STATUS_BLOCK IoStatusBlock)
642 {
643 /* Call the completion routine */
644 (*Callback)(Context, IoStatusBlock);
645 }
646
647 BOOLEAN
648 WSPAPI
649 SockCheckAndReferenceAsyncThread(VOID)
650 {
651 LONG Count;
652 HANDLE hAsyncThread;
653 DWORD AsyncThreadId;
654 HANDLE AsyncEvent;
655 NTSTATUS Status;
656 INT ErrorCode;
657 HINSTANCE hInstance;
658 PWINSOCK_TEB_DATA ThreadData;
659
660 /* Loop while trying to increase the reference count */
661 do
662 {
663 /* Get the count, and check if it's already been started */
664 Count = SockAsyncThreadReferenceCount;
665 if ((Count > 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount,
666 Count + 1,
667 Count) == Count))
668 {
669 /* Simply return */
670 return TRUE;
671 }
672 } while (Count > 0);
673
674 /* Acquire the lock */
675 SockAcquireRwLockExclusive(&SocketGlobalLock);
676
677 /* Check if no completion port exists already and create it */
678 if (!SockAsyncQueuePort) SockCreateAsyncQueuePort();
679
680 /* Create an extra reference so the thread stays alive */
681 ErrorCode = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
682 (LPCTSTR)WSPStartup,
683 &hInstance);
684
685 /* Create the Async Event */
686 Status = NtCreateEvent(&AsyncEvent,
687 EVENT_ALL_ACCESS,
688 NULL,
689 NotificationEvent,
690 FALSE);
691
692 /* Allocate the TEB Block */
693 ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData));
694 if (!ThreadData)
695 {
696 /* Release the lock, close the event, free extra reference and fail */
697 SockReleaseRwLockExclusive(&SocketGlobalLock);
698 NtClose(AsyncEvent);
699 FreeLibrary(hInstance);
700 return FALSE;
701 }
702
703 /* Initialize thread data */
704 RtlZeroMemory(ThreadData, sizeof(*ThreadData));
705 ThreadData->EventHandle = AsyncEvent;
706 ThreadData->SocketHandle = (SOCKET)hInstance;
707
708 /* Create the Async Thread */
709 hAsyncThread = CreateThread(NULL,
710 0,
711 (LPTHREAD_START_ROUTINE)SockAsyncThread,
712 ThreadData,
713 0,
714 &AsyncThreadId);
715
716 /* Close the Handle */
717 NtClose(hAsyncThread);
718
719 /* Increase the Reference Count */
720 InterlockedExchangeAdd(&SockAsyncThreadReferenceCount, 2);
721
722 /* Release lock and return success */
723 SockReleaseRwLockExclusive(&SocketGlobalLock);
724 return TRUE;
725 }
726
727 INT
728 WSPAPI
729 SockAsyncThread(PVOID Context)
730 {
731 PVOID AsyncContext;
732 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
733 IO_STATUS_BLOCK IoStatusBlock;
734 NTSTATUS Status;
735 LARGE_INTEGER Timeout;
736 PWINSOCK_TEB_DATA ThreadData = (PWINSOCK_TEB_DATA)Context;
737 HINSTANCE hInstance = (HINSTANCE)ThreadData->SocketHandle;
738
739 /* Return the socket handle back to its unhacked value */
740 ThreadData->SocketHandle = INVALID_SOCKET;
741
742 /* Setup the Thread Data pointer */
743 NtCurrentTeb()->WinSockData = ThreadData;
744
745 /* Make the Thread Higher Priority */
746 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
747
748 /* Setup timeout */
749 Timeout.QuadPart = Int32x32To64(300, 10000000);
750
751 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
752 do {
753 /* Get the next completion item */
754 Status = NtRemoveIoCompletion(SockAsyncQueuePort,
755 (PVOID*)&AsyncCompletionRoutine,
756 &AsyncContext,
757 &IoStatusBlock,
758 &Timeout);
759 /* Check for success */
760 if (NT_SUCCESS(Status))
761 {
762 /* Check if this isn't the termination command */
763 if (AsyncCompletionRoutine != (PVOID)-1)
764 {
765 /* Call the routine */
766 SockHandleAsyncIndication(AsyncCompletionRoutine,
767 Context,
768 &IoStatusBlock);
769 }
770 else
771 {
772 /* We have to terminate, fake a timeout */
773 Status = STATUS_TIMEOUT;
774 InterlockedDecrement(&SockAsyncThreadReferenceCount);
775 }
776 }
777 else if ((SockAsyncThreadReferenceCount > 1) && (NT_ERROR(Status)))
778 {
779 /* It Failed, sleep for a second */
780 Sleep(1000);
781 }
782 } while (((Status != STATUS_TIMEOUT) &&
783 (SockWspStartupCount > 0)) ||
784 InterlockedCompareExchange(&SockAsyncThreadReferenceCount, 0, 1) != 1);
785
786 /* Release the lock */
787 SockReleaseRwLockShared(&SocketGlobalLock);
788
789 /* Remove our extra reference */
790 FreeLibraryAndExitThread(hInstance, NO_ERROR);
791 }
792