2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: dll/win32/ws2_32_new/src/dthread.c
5 * PURPOSE: Thread Object
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
13 /* FUNCTIONS *****************************************************************/
17 WsThreadDefaultBlockingHook(VOID
)
20 BOOL GotMessage
= FALSE
;
23 GotMessage
= PeekMessage(&Message
, NULL
, 0, 0, PM_REMOVE
);
25 /* Check if we got one */
29 TranslateMessage(&Message
);
30 DispatchMessage(&Message
);
39 WsThreadBlockingCallback(IN DWORD_PTR Context
)
41 PWSTHREAD Thread
= TlsGetValue(TlsIndex
);
43 /* Set thread as blocking, set cancel callback and the clear cancel flag */
44 Thread
->Blocking
= TRUE
;
45 Thread
->CancelBlockingCall
= (LPWSPCANCELBLOCKINGCALL
)Context
;
46 Thread
->Cancelled
= FALSE
;
48 /* Call the blocking hook */
49 while(Thread
->BlockingHook());
51 /* We're not blocking anymore */
52 Thread
->Blocking
= FALSE
;
54 /* Return whether or not we were cancelled */
55 return !Thread
->Cancelled
;
60 WsThreadSetBlockingHook(IN PWSTHREAD Thread
,
61 IN FARPROC BlockingHook
)
63 FARPROC OldHook
= Thread
->BlockingHook
;
65 /* Check if we're resetting to our default hook */
66 if (BlockingHook
== (FARPROC
)WsThreadDefaultBlockingHook
)
68 /* Clear out the blocking callback */
69 Thread
->BlockingCallback
= NULL
;
73 /* Set the blocking callback */
74 Thread
->BlockingCallback
= WsThreadBlockingCallback
;
77 /* Set the new blocking hook and return the previous */
78 Thread
->BlockingHook
= BlockingHook
;
84 WsThreadUnhookBlockingHook(IN PWSTHREAD Thread
)
86 /* Reset the hook to the default, and remove the callback */
87 Thread
->BlockingHook
= (FARPROC
)WsThreadDefaultBlockingHook
;
88 Thread
->BlockingCallback
= NULL
;
96 WsThreadCancelBlockingCall(IN PWSTHREAD Thread
)
98 INT ErrorCode
, ReturnValue
;
100 /* Make sure that the Thread is really in a blocking call */
101 if (!Thread
->Blocking
) return WSAEINVAL
;
103 /* Make sure we haven't already been cancelled */
104 if (!Thread
->Cancelled
)
106 /* Call the cancel procedure */
107 ReturnValue
= Thread
->CancelBlockingCall(&ErrorCode
);
108 if (ReturnValue
!= ERROR_SUCCESS
) return ErrorCode
;
110 /* Set us as cancelled */
111 Thread
->Cancelled
= TRUE
;
115 return ERROR_SUCCESS
;
120 WsThreadGetProtoBuffer(IN PWSTHREAD Thread
)
122 /* See if it already exists */
123 if (!Thread
->ProtocolInfo
)
125 /* We don't have a buffer; allocate it */
126 Thread
->ProtocolInfo
= HeapAlloc(WsSockHeap
, 0, sizeof(WSPROTO_BUFFER
));
130 return Thread
->ProtocolInfo
;
135 WsThreadAllocate(VOID
)
139 /* Allocate the object */
140 Thread
= HeapAlloc(WsSockHeap
, HEAP_ZERO_MEMORY
, sizeof(*Thread
));
142 /* Set non-zero data */
143 Thread
->BlockingHook
= (FARPROC
)WsThreadDefaultBlockingHook
;
151 WsThreadStartup(VOID
)
153 INT ErrorCode
= WSASYSCALLFAILURE
;
155 /* Check if we have a valid TLS */
156 if (TlsIndex
!= TLS_OUT_OF_INDEXES
)
158 /* TLS was already OK */
159 ErrorCode
= ERROR_SUCCESS
;
168 WsThreadCleanup(VOID
)
174 WsThreadInitialize(IN PWSTHREAD Thread
,
175 IN PWSPROCESS Process
)
177 INT ErrorCode
= WSASYSCALLFAILURE
;
179 /* Set the process */
180 Thread
->Process
= Process
;
182 /* Get the helper device */
183 if ((WsProcGetAsyncHelper(Process
, &Thread
->AsyncHelper
)) == ERROR_SUCCESS
)
185 /* Initialize a WAH Thread ID */
186 if ((WahOpenCurrentThread(Thread
->AsyncHelper
,
187 &Thread
->WahThreadId
)) == ERROR_SUCCESS
)
190 ErrorCode
= ERROR_SUCCESS
;
200 WsThreadDelete(IN PWSTHREAD Thread
)
202 /* Remove the blocking hook */
203 Thread
->BlockingHook
= NULL
;
205 /* Free our buffers */
206 if (Thread
->Hostent
) HeapFree(WsSockHeap
, 0, Thread
->Hostent
);
207 if (Thread
->Servent
) HeapFree(WsSockHeap
, 0, Thread
->Servent
);
208 if (Thread
->ProtocolInfo
) HeapFree(WsSockHeap
, 0, Thread
->ProtocolInfo
);
211 TlsSetValue(TlsIndex
, NULL
);
213 /* Close the WAH Handle */
214 WahCloseThread(Thread
->AsyncHelper
, &Thread
->WahThreadId
);
216 /* Unlink the process and free us */
217 Thread
->Process
= NULL
;
218 HeapFree(WsSockHeap
, 0, Thread
);
223 WsThreadDestroyCurrentThread(VOID
)
227 /* Make sure we have TLS */
228 if (TlsIndex
!= TLS_OUT_OF_INDEXES
)
231 if ((Thread
= TlsGetValue(TlsIndex
)))
234 WsThreadDelete(Thread
);
235 TlsSetValue(TlsIndex
, 0);
242 WsThreadCreate(IN PWSPROCESS Process
,
243 IN PWSTHREAD
*CurrentThread
)
245 PWSTHREAD Thread
= NULL
;
246 INT ErrorCode
= WSASYSCALLFAILURE
;
248 /* Make sure we have TLS */
249 if (TlsIndex
!= TLS_OUT_OF_INDEXES
)
251 /* Allocate the thread */
252 if ((Thread
= WsThreadAllocate()))
255 if (WsThreadInitialize(Thread
, Process
) == ERROR_SUCCESS
)
258 if (TlsSetValue(TlsIndex
, Thread
))
260 /* Return it and success */
261 *CurrentThread
= Thread
;
262 ErrorCode
= ERROR_SUCCESS
;
266 /* Check for any failures */
267 if (ErrorCode
!= ERROR_SUCCESS
) WsThreadDelete(Thread
);
277 WsThreadGetCurrentThread(IN PWSPROCESS Process
,
278 IN PWSTHREAD
*Thread
)
281 if ((*Thread
= TlsGetValue(TlsIndex
)))
284 return ERROR_SUCCESS
;
288 /* We failed, initialize it */
289 return WsThreadCreate(Process
, Thread
);
295 WsThreadGetThreadId(IN PWSPROCESS Process
)
300 if ((Thread
= TlsGetValue(TlsIndex
)))
303 return &Thread
->WahThreadId
;
307 /* Not a valid thread */
314 WsThreadBlobToHostent(IN PWSTHREAD Thread
,
317 /* Check if our buffer is too small */
318 if (Thread
->HostentSize
< Blob
->cbSize
)
320 /* Delete the current buffer and allocate a new one */
321 HeapFree(WsSockHeap
, 0, Thread
->Hostent
);
322 Thread
->Hostent
= HeapAlloc(WsSockHeap
, 0, Blob
->cbSize
);
324 /* Set the new size */
325 Thread
->HostentSize
= Blob
->cbSize
;
328 /* Do we have a buffer? */
331 /* Copy the data inside */
332 RtlMoveMemory(Thread
->Hostent
, Blob
->pBlobData
, Blob
->cbSize
);
336 /* No buffer space! */
337 Thread
->HostentSize
= 0;
338 SetLastError(WSA_NOT_ENOUGH_MEMORY
);
341 /* Return the buffer */
342 return (PHOSTENT
)Thread
->Hostent
;
347 WsThreadBlobToServent(IN PWSTHREAD Thread
,
350 /* Check if our buffer is too small */
351 if (Thread
->ServentSize
< Blob
->cbSize
)
353 /* Delete the current buffer and allocate a new one */
354 HeapFree(WsSockHeap
, 0, Thread
->Servent
);
355 Thread
->Servent
= HeapAlloc(WsSockHeap
, 0, Blob
->cbSize
);
357 /* Set the new size */
358 Thread
->ServentSize
= Blob
->cbSize
;
361 /* Do we have a buffer? */
364 /* Copy the data inside */
365 RtlMoveMemory(Thread
->Servent
, Blob
->pBlobData
, Blob
->cbSize
);
369 /* No buffer space! */
370 Thread
->ServentSize
= 0;
371 SetLastError(WSA_NOT_ENOUGH_MEMORY
);
374 /* Return the buffer */
375 return (PSERVENT
)Thread
->Servent
;