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
8 /* INCLUDES ******************************************************************/
11 /* DATA **********************************************************************/
13 HANDLE SockAsyncQueuePort
;
14 LONG SockAsyncThreadReferenceCount
;
16 /* FUNCTIONS *****************************************************************/
20 SockCreateAsyncQueuePort(VOID
)
23 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags
;
26 Status
= NtCreateIoCompletion(&SockAsyncQueuePort
,
27 IO_COMPLETION_ALL_ACCESS
,
32 HandleFlags
.ProtectFromClose
= TRUE
;
33 HandleFlags
.Inherit
= FALSE
;
34 Status
= NtSetInformationObject(SockAsyncQueuePort
,
35 ObjectHandleFlagInformation
,
45 SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback
,
47 IN PIO_STATUS_BLOCK IoStatusBlock
)
49 /* Call the completion routine */
50 (*Callback
)(Context
, IoStatusBlock
);
55 SockCheckAndReferenceAsyncThread(VOID
)
64 PWINSOCK_TEB_DATA ThreadData
;
66 /* Loop while trying to increase the reference count */
69 /* Get the count, and check if it's already been started */
70 Count
= SockAsyncThreadReferenceCount
;
71 if ((Count
> 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount
,
80 /* Acquire the lock */
81 SockAcquireRwLockExclusive(&SocketGlobalLock
);
83 /* Check if no completion port exists already and create it */
84 if (!SockAsyncQueuePort
) SockCreateAsyncQueuePort();
86 /* Create an extra reference so the thread stays alive */
87 ErrorCode
= GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
91 /* Create the Async Event */
92 Status
= NtCreateEvent(&AsyncEvent
,
98 /* Allocate the TEB Block */
99 ThreadData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData
));
102 /* Release the lock, close the event, free extra reference and fail */
103 SockReleaseRwLockExclusive(&SocketGlobalLock
);
105 FreeLibrary(hInstance
);
109 /* Initialize thread data */
110 RtlZeroMemory(ThreadData
, sizeof(*ThreadData
));
111 ThreadData
->EventHandle
= AsyncEvent
;
112 ThreadData
->SocketHandle
= (SOCKET
)hInstance
;
114 /* Create the Async Thread */
115 hAsyncThread
= CreateThread(NULL
,
117 (LPTHREAD_START_ROUTINE
)SockAsyncThread
,
122 /* Close the Handle */
123 NtClose(hAsyncThread
);
125 /* Increase the Reference Count */
126 InterlockedExchangeAdd(&SockAsyncThreadReferenceCount
, 2);
128 /* Release lock and return success */
129 SockReleaseRwLockExclusive(&SocketGlobalLock
);
135 SockAsyncThread(PVOID Context
)
138 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine
;
139 IO_STATUS_BLOCK IoStatusBlock
;
141 LARGE_INTEGER Timeout
;
142 PWINSOCK_TEB_DATA ThreadData
= (PWINSOCK_TEB_DATA
)Context
;
143 HINSTANCE hInstance
= (HINSTANCE
)ThreadData
->SocketHandle
;
145 /* Return the socket handle back to its unhacked value */
146 ThreadData
->SocketHandle
= INVALID_SOCKET
;
148 /* Setup the Thread Data pointer */
149 NtCurrentTeb()->WinSockData
= ThreadData
;
151 /* Make the Thread Higher Priority */
152 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL
);
155 Timeout
.QuadPart
= Int32x32To64(300, 10000000);
157 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
159 /* Get the next completion item */
160 Status
= NtRemoveIoCompletion(SockAsyncQueuePort
,
161 (PVOID
*)&AsyncCompletionRoutine
,
165 /* Check for success */
166 if (NT_SUCCESS(Status
))
168 /* Check if this isn't the termination command */
169 if (AsyncCompletionRoutine
!= (PVOID
)-1)
171 /* Call the routine */
172 SockHandleAsyncIndication(AsyncCompletionRoutine
,
178 /* We have to terminate, fake a timeout */
179 Status
= STATUS_TIMEOUT
;
180 InterlockedDecrement(&SockAsyncThreadReferenceCount
);
183 else if ((SockAsyncThreadReferenceCount
> 1) && (NT_ERROR(Status
)))
185 /* It Failed, sleep for a second */
188 } while (((Status
!= STATUS_TIMEOUT
) &&
189 (SockWspStartupCount
> 0)) ||
190 InterlockedCompareExchange(&SockAsyncThreadReferenceCount
, 0, 1) != 1);
192 /* Release the lock */
193 SockReleaseRwLockShared(&SocketGlobalLock
);
195 /* Remove our extra reference */
196 FreeLibraryAndExitThread(hInstance
, NO_ERROR
);
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
206 /* INCLUDES ******************************************************************/
209 /* DATA **********************************************************************/
211 HANDLE SockAsyncQueuePort
;
212 LONG SockAsyncThreadReferenceCount
;
214 /* FUNCTIONS *****************************************************************/
218 SockCreateAsyncQueuePort(VOID
)
221 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags
;
223 /* Create the port */
224 Status
= NtCreateIoCompletion(&SockAsyncQueuePort
,
225 IO_COMPLETION_ALL_ACCESS
,
230 HandleFlags
.ProtectFromClose
= TRUE
;
231 HandleFlags
.Inherit
= FALSE
;
232 Status
= NtSetInformationObject(SockAsyncQueuePort
,
233 ObjectHandleFlagInformation
,
235 sizeof(HandleFlags
));
243 SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback
,
245 IN PIO_STATUS_BLOCK IoStatusBlock
)
247 /* Call the completion routine */
248 (*Callback
)(Context
, IoStatusBlock
);
253 SockCheckAndReferenceAsyncThread(VOID
)
262 PWINSOCK_TEB_DATA ThreadData
;
264 /* Loop while trying to increase the reference count */
267 /* Get the count, and check if it's already been started */
268 Count
= SockAsyncThreadReferenceCount
;
269 if ((Count
> 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount
,
278 /* Acquire the lock */
279 SockAcquireRwLockExclusive(&SocketGlobalLock
);
281 /* Check if no completion port exists already and create it */
282 if (!SockAsyncQueuePort
) SockCreateAsyncQueuePort();
284 /* Create an extra reference so the thread stays alive */
285 ErrorCode
= GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
289 /* Create the Async Event */
290 Status
= NtCreateEvent(&AsyncEvent
,
296 /* Allocate the TEB Block */
297 ThreadData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData
));
300 /* Release the lock, close the event, free extra reference and fail */
301 SockReleaseRwLockExclusive(&SocketGlobalLock
);
303 FreeLibrary(hInstance
);
307 /* Initialize thread data */
308 RtlZeroMemory(ThreadData
, sizeof(*ThreadData
));
309 ThreadData
->EventHandle
= AsyncEvent
;
310 ThreadData
->SocketHandle
= (SOCKET
)hInstance
;
312 /* Create the Async Thread */
313 hAsyncThread
= CreateThread(NULL
,
315 (LPTHREAD_START_ROUTINE
)SockAsyncThread
,
320 /* Close the Handle */
321 NtClose(hAsyncThread
);
323 /* Increase the Reference Count */
324 InterlockedExchangeAdd(&SockAsyncThreadReferenceCount
, 2);
326 /* Release lock and return success */
327 SockReleaseRwLockExclusive(&SocketGlobalLock
);
333 SockAsyncThread(PVOID Context
)
336 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine
;
337 IO_STATUS_BLOCK IoStatusBlock
;
339 LARGE_INTEGER Timeout
;
340 PWINSOCK_TEB_DATA ThreadData
= (PWINSOCK_TEB_DATA
)Context
;
341 HINSTANCE hInstance
= (HINSTANCE
)ThreadData
->SocketHandle
;
343 /* Return the socket handle back to its unhacked value */
344 ThreadData
->SocketHandle
= INVALID_SOCKET
;
346 /* Setup the Thread Data pointer */
347 NtCurrentTeb()->WinSockData
= ThreadData
;
349 /* Make the Thread Higher Priority */
350 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL
);
353 Timeout
.QuadPart
= Int32x32To64(300, 10000000);
355 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
357 /* Get the next completion item */
358 Status
= NtRemoveIoCompletion(SockAsyncQueuePort
,
359 (PVOID
*)&AsyncCompletionRoutine
,
363 /* Check for success */
364 if (NT_SUCCESS(Status
))
366 /* Check if this isn't the termination command */
367 if (AsyncCompletionRoutine
!= (PVOID
)-1)
369 /* Call the routine */
370 SockHandleAsyncIndication(AsyncCompletionRoutine
,
376 /* We have to terminate, fake a timeout */
377 Status
= STATUS_TIMEOUT
;
378 InterlockedDecrement(&SockAsyncThreadReferenceCount
);
381 else if ((SockAsyncThreadReferenceCount
> 1) && (NT_ERROR(Status
)))
383 /* It Failed, sleep for a second */
386 } while (((Status
!= STATUS_TIMEOUT
) &&
387 (SockWspStartupCount
> 0)) ||
388 InterlockedCompareExchange(&SockAsyncThreadReferenceCount
, 0, 1) != 1);
390 /* Release the lock */
391 SockReleaseRwLockShared(&SocketGlobalLock
);
393 /* Remove our extra reference */
394 FreeLibraryAndExitThread(hInstance
, NO_ERROR
);
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
404 /* INCLUDES ******************************************************************/
407 /* DATA **********************************************************************/
409 HANDLE SockAsyncQueuePort
;
410 LONG SockAsyncThreadReferenceCount
;
412 /* FUNCTIONS *****************************************************************/
416 SockCreateAsyncQueuePort(VOID
)
419 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags
;
421 /* Create the port */
422 Status
= NtCreateIoCompletion(&SockAsyncQueuePort
,
423 IO_COMPLETION_ALL_ACCESS
,
428 HandleFlags
.ProtectFromClose
= TRUE
;
429 HandleFlags
.Inherit
= FALSE
;
430 Status
= NtSetInformationObject(SockAsyncQueuePort
,
431 ObjectHandleFlagInformation
,
433 sizeof(HandleFlags
));
441 SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback
,
443 IN PIO_STATUS_BLOCK IoStatusBlock
)
445 /* Call the completion routine */
446 (*Callback
)(Context
, IoStatusBlock
);
451 SockCheckAndReferenceAsyncThread(VOID
)
460 PWINSOCK_TEB_DATA ThreadData
;
462 /* Loop while trying to increase the reference count */
465 /* Get the count, and check if it's already been started */
466 Count
= SockAsyncThreadReferenceCount
;
467 if ((Count
> 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount
,
476 /* Acquire the lock */
477 SockAcquireRwLockExclusive(&SocketGlobalLock
);
479 /* Check if no completion port exists already and create it */
480 if (!SockAsyncQueuePort
) SockCreateAsyncQueuePort();
482 /* Create an extra reference so the thread stays alive */
483 ErrorCode
= GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
487 /* Create the Async Event */
488 Status
= NtCreateEvent(&AsyncEvent
,
494 /* Allocate the TEB Block */
495 ThreadData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData
));
498 /* Release the lock, close the event, free extra reference and fail */
499 SockReleaseRwLockExclusive(&SocketGlobalLock
);
501 FreeLibrary(hInstance
);
505 /* Initialize thread data */
506 RtlZeroMemory(ThreadData
, sizeof(*ThreadData
));
507 ThreadData
->EventHandle
= AsyncEvent
;
508 ThreadData
->SocketHandle
= (SOCKET
)hInstance
;
510 /* Create the Async Thread */
511 hAsyncThread
= CreateThread(NULL
,
513 (LPTHREAD_START_ROUTINE
)SockAsyncThread
,
518 /* Close the Handle */
519 NtClose(hAsyncThread
);
521 /* Increase the Reference Count */
522 InterlockedExchangeAdd(&SockAsyncThreadReferenceCount
, 2);
524 /* Release lock and return success */
525 SockReleaseRwLockExclusive(&SocketGlobalLock
);
531 SockAsyncThread(PVOID Context
)
534 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine
;
535 IO_STATUS_BLOCK IoStatusBlock
;
537 LARGE_INTEGER Timeout
;
538 PWINSOCK_TEB_DATA ThreadData
= (PWINSOCK_TEB_DATA
)Context
;
539 HINSTANCE hInstance
= (HINSTANCE
)ThreadData
->SocketHandle
;
541 /* Return the socket handle back to its unhacked value */
542 ThreadData
->SocketHandle
= INVALID_SOCKET
;
544 /* Setup the Thread Data pointer */
545 NtCurrentTeb()->WinSockData
= ThreadData
;
547 /* Make the Thread Higher Priority */
548 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL
);
551 Timeout
.QuadPart
= Int32x32To64(300, 10000000);
553 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
555 /* Get the next completion item */
556 Status
= NtRemoveIoCompletion(SockAsyncQueuePort
,
557 (PVOID
*)&AsyncCompletionRoutine
,
561 /* Check for success */
562 if (NT_SUCCESS(Status
))
564 /* Check if this isn't the termination command */
565 if (AsyncCompletionRoutine
!= (PVOID
)-1)
567 /* Call the routine */
568 SockHandleAsyncIndication(AsyncCompletionRoutine
,
574 /* We have to terminate, fake a timeout */
575 Status
= STATUS_TIMEOUT
;
576 InterlockedDecrement(&SockAsyncThreadReferenceCount
);
579 else if ((SockAsyncThreadReferenceCount
> 1) && (NT_ERROR(Status
)))
581 /* It Failed, sleep for a second */
584 } while (((Status
!= STATUS_TIMEOUT
) &&
585 (SockWspStartupCount
> 0)) ||
586 InterlockedCompareExchange(&SockAsyncThreadReferenceCount
, 0, 1) != 1);
588 /* Release the lock */
589 SockReleaseRwLockShared(&SocketGlobalLock
);
591 /* Remove our extra reference */
592 FreeLibraryAndExitThread(hInstance
, NO_ERROR
);
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
602 /* INCLUDES ******************************************************************/
605 /* DATA **********************************************************************/
607 HANDLE SockAsyncQueuePort
;
608 LONG SockAsyncThreadReferenceCount
;
610 /* FUNCTIONS *****************************************************************/
614 SockCreateAsyncQueuePort(VOID
)
617 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags
;
619 /* Create the port */
620 Status
= NtCreateIoCompletion(&SockAsyncQueuePort
,
621 IO_COMPLETION_ALL_ACCESS
,
626 HandleFlags
.ProtectFromClose
= TRUE
;
627 HandleFlags
.Inherit
= FALSE
;
628 Status
= NtSetInformationObject(SockAsyncQueuePort
,
629 ObjectHandleFlagInformation
,
631 sizeof(HandleFlags
));
639 SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback
,
641 IN PIO_STATUS_BLOCK IoStatusBlock
)
643 /* Call the completion routine */
644 (*Callback
)(Context
, IoStatusBlock
);
649 SockCheckAndReferenceAsyncThread(VOID
)
658 PWINSOCK_TEB_DATA ThreadData
;
660 /* Loop while trying to increase the reference count */
663 /* Get the count, and check if it's already been started */
664 Count
= SockAsyncThreadReferenceCount
;
665 if ((Count
> 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount
,
674 /* Acquire the lock */
675 SockAcquireRwLockExclusive(&SocketGlobalLock
);
677 /* Check if no completion port exists already and create it */
678 if (!SockAsyncQueuePort
) SockCreateAsyncQueuePort();
680 /* Create an extra reference so the thread stays alive */
681 ErrorCode
= GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
685 /* Create the Async Event */
686 Status
= NtCreateEvent(&AsyncEvent
,
692 /* Allocate the TEB Block */
693 ThreadData
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData
));
696 /* Release the lock, close the event, free extra reference and fail */
697 SockReleaseRwLockExclusive(&SocketGlobalLock
);
699 FreeLibrary(hInstance
);
703 /* Initialize thread data */
704 RtlZeroMemory(ThreadData
, sizeof(*ThreadData
));
705 ThreadData
->EventHandle
= AsyncEvent
;
706 ThreadData
->SocketHandle
= (SOCKET
)hInstance
;
708 /* Create the Async Thread */
709 hAsyncThread
= CreateThread(NULL
,
711 (LPTHREAD_START_ROUTINE
)SockAsyncThread
,
716 /* Close the Handle */
717 NtClose(hAsyncThread
);
719 /* Increase the Reference Count */
720 InterlockedExchangeAdd(&SockAsyncThreadReferenceCount
, 2);
722 /* Release lock and return success */
723 SockReleaseRwLockExclusive(&SocketGlobalLock
);
729 SockAsyncThread(PVOID Context
)
732 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine
;
733 IO_STATUS_BLOCK IoStatusBlock
;
735 LARGE_INTEGER Timeout
;
736 PWINSOCK_TEB_DATA ThreadData
= (PWINSOCK_TEB_DATA
)Context
;
737 HINSTANCE hInstance
= (HINSTANCE
)ThreadData
->SocketHandle
;
739 /* Return the socket handle back to its unhacked value */
740 ThreadData
->SocketHandle
= INVALID_SOCKET
;
742 /* Setup the Thread Data pointer */
743 NtCurrentTeb()->WinSockData
= ThreadData
;
745 /* Make the Thread Higher Priority */
746 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL
);
749 Timeout
.QuadPart
= Int32x32To64(300, 10000000);
751 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
753 /* Get the next completion item */
754 Status
= NtRemoveIoCompletion(SockAsyncQueuePort
,
755 (PVOID
*)&AsyncCompletionRoutine
,
759 /* Check for success */
760 if (NT_SUCCESS(Status
))
762 /* Check if this isn't the termination command */
763 if (AsyncCompletionRoutine
!= (PVOID
)-1)
765 /* Call the routine */
766 SockHandleAsyncIndication(AsyncCompletionRoutine
,
772 /* We have to terminate, fake a timeout */
773 Status
= STATUS_TIMEOUT
;
774 InterlockedDecrement(&SockAsyncThreadReferenceCount
);
777 else if ((SockAsyncThreadReferenceCount
> 1) && (NT_ERROR(Status
)))
779 /* It Failed, sleep for a second */
782 } while (((Status
!= STATUS_TIMEOUT
) &&
783 (SockWspStartupCount
> 0)) ||
784 InterlockedCompareExchange(&SockAsyncThreadReferenceCount
, 0, 1) != 1);
786 /* Release the lock */
787 SockReleaseRwLockShared(&SocketGlobalLock
);
789 /* Remove our extra reference */
790 FreeLibraryAndExitThread(hInstance
, NO_ERROR
);