2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
5 * PURPOSE: Thread Object
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
12 /* FUNCTIONS *****************************************************************/
16 WsThreadDefaultBlockingHook(VOID
)
19 BOOL GotMessage
= FALSE
;
22 GotMessage
= PeekMessage(&Message
, NULL
, 0, 0, PM_REMOVE
);
24 /* Check if we got one */
28 TranslateMessage(&Message
);
29 DispatchMessage(&Message
);
38 WsThreadBlockingCallback(IN DWORD_PTR Context
)
40 PWSTHREAD Thread
= TlsGetValue(TlsIndex
);
42 /* Set thread as blocking, set cancel callback and the clear cancel flag */
43 Thread
->Blocking
= TRUE
;
44 Thread
->CancelBlockingCall
= (LPWSPCANCELBLOCKINGCALL
)Context
;
45 Thread
->Cancelled
= FALSE
;
47 /* Call the blocking hook */
48 while(Thread
->BlockingHook());
50 /* We're not blocking anymore */
51 Thread
->Blocking
= FALSE
;
53 /* Return whether or not we were cancelled */
54 return !Thread
->Cancelled
;
59 WsThreadSetBlockingHook(IN PWSTHREAD Thread
,
60 IN FARPROC BlockingHook
)
62 FARPROC OldHook
= Thread
->BlockingHook
;
64 /* Check if we're resetting to our default hook */
65 if (BlockingHook
== (FARPROC
)WsThreadDefaultBlockingHook
)
67 /* Clear out the blocking callback */
68 Thread
->BlockingCallback
= NULL
;
72 /* Set the blocking callback */
73 Thread
->BlockingCallback
= WsThreadBlockingCallback
;
76 /* Set the new blocking hook and return the previous */
77 Thread
->BlockingHook
= BlockingHook
;
83 WsThreadUnhookBlockingHook(IN PWSTHREAD Thread
)
85 /* Reset the hook to the default, and remove the callback */
86 Thread
->BlockingHook
= (FARPROC
)WsThreadDefaultBlockingHook
;
87 Thread
->BlockingCallback
= NULL
;
95 WsThreadCancelBlockingCall(IN PWSTHREAD Thread
)
97 INT ErrorCode
, ReturnValue
;
99 /* Make sure that the Thread is really in a blocking call */
100 if (!Thread
->Blocking
) return WSAEINVAL
;
102 /* Make sure we haven't already been cancelled */
103 if (!Thread
->Cancelled
)
105 /* Call the cancel procedure */
106 ReturnValue
= Thread
->CancelBlockingCall(&ErrorCode
);
107 if (ReturnValue
!= ERROR_SUCCESS
) return ErrorCode
;
109 /* Set us as cancelled */
110 Thread
->Cancelled
= TRUE
;
114 return ERROR_SUCCESS
;
119 WsThreadGetProtoBuffer(IN PWSTHREAD Thread
)
121 /* See if it already exists */
122 if (!Thread
->ProtocolInfo
)
124 /* We don't have a buffer; allocate it */
125 Thread
->ProtocolInfo
= HeapAlloc(WsSockHeap
, 0, sizeof(PWSPROTO_BUFFER
));
129 return Thread
->ProtocolInfo
;
134 WsThreadAllocate(VOID
)
138 /* Allocate the object */
139 Thread
= HeapAlloc(WsSockHeap
, HEAP_ZERO_MEMORY
, sizeof(*Thread
));
141 /* Set non-zero data */
142 Thread
->BlockingHook
= (FARPROC
)WsThreadDefaultBlockingHook
;
150 WsThreadStartup(VOID
)
152 INT ErrorCode
= WSASYSCALLFAILURE
;
154 /* Check if we have a valid TLS */
155 if (TlsIndex
!= TLS_OUT_OF_INDEXES
)
157 /* TLS was already OK */
158 ErrorCode
= ERROR_SUCCESS
;
167 WsThreadCleanup(VOID
)
173 WsThreadInitialize(IN PWSTHREAD Thread
,
174 IN PWSPROCESS Process
)
176 INT ErrorCode
= WSASYSCALLFAILURE
;
178 /* Set the process */
179 Thread
->Process
= Process
;
181 /* Get the helper device */
182 if ((WsProcGetAsyncHelper(Process
, &Thread
->AsyncHelper
)) == ERROR_SUCCESS
)
184 /* Initialize a WAH Thread ID */
185 if ((WahOpenCurrentThread(Thread
->AsyncHelper
,
186 &Thread
->WahThreadId
)) == ERROR_SUCCESS
)
189 ErrorCode
= ERROR_SUCCESS
;
199 WsThreadDelete(IN PWSTHREAD Thread
)
201 /* Remove the blocking hook */
202 Thread
->BlockingHook
= NULL
;
204 /* Free our buffers */
205 if (Thread
->Hostent
) HeapFree(WsSockHeap
, 0, Thread
->Hostent
);
206 if (Thread
->Servent
) HeapFree(WsSockHeap
, 0, Thread
->Servent
);
207 if (Thread
->ProtocolInfo
) HeapFree(WsSockHeap
, 0, Thread
->ProtocolInfo
);
210 TlsSetValue(TlsIndex
, NULL
);
212 /* Close the WAH Handle */
213 WahCloseThread(Thread
->AsyncHelper
, &Thread
->WahThreadId
);
215 /* Unlink the process and free us */
216 Thread
->Process
= NULL
;
217 HeapFree(WsSockHeap
, 0, Thread
);
222 WsThreadDestroyCurrentThread(VOID
)
226 /* Make sure we have TLS */
227 if (TlsIndex
!= TLS_OUT_OF_INDEXES
)
230 if ((Thread
= TlsGetValue(TlsIndex
)))
233 WsThreadDelete(Thread
);
234 TlsSetValue(TlsIndex
, 0);
241 WsThreadCreate(IN PWSPROCESS Process
,
242 IN PWSTHREAD
*CurrentThread
)
244 PWSTHREAD Thread
= NULL
;
245 INT ErrorCode
= WSASYSCALLFAILURE
;
247 /* Make sure we have TLS */
248 if (TlsIndex
!= TLS_OUT_OF_INDEXES
)
250 /* Allocate the thread */
251 if ((Thread
= WsThreadAllocate()))
254 if (WsThreadInitialize(Thread
, Process
) == ERROR_SUCCESS
)
257 if (TlsSetValue(TlsIndex
, Thread
))
259 /* Return it and success */
260 *CurrentThread
= Thread
;
261 ErrorCode
= ERROR_SUCCESS
;
265 /* Check for any failures */
266 if (ErrorCode
!= ERROR_SUCCESS
) WsThreadDelete(Thread
);
276 WsThreadGetCurrentThread(IN PWSPROCESS Process
,
277 IN PWSTHREAD
*Thread
)
280 if ((*Thread
= TlsGetValue(TlsIndex
)))
283 return ERROR_SUCCESS
;
287 /* We failed, initialize it */
288 return WsThreadCreate(Process
, Thread
);
294 WsThreadGetThreadId(IN PWSPROCESS Process
)
299 if ((Thread
= TlsGetValue(TlsIndex
)))
302 return &Thread
->WahThreadId
;
306 /* Not a valid thread */
313 WsThreadBlobToHostent(IN PWSTHREAD Thread
,
316 /* Check if our buffer is too small */
317 if (Thread
->HostentSize
< Blob
->cbSize
)
319 /* Delete the current buffer and allocate a new one */
320 HeapFree(WsSockHeap
, 0, Thread
->Hostent
);
321 Thread
->Hostent
= HeapAlloc(WsSockHeap
, 0, Blob
->cbSize
);
323 /* Set the new size */
324 Thread
->HostentSize
= Blob
->cbSize
;
327 /* Do we have a buffer? */
330 /* Copy the data inside */
331 RtlMoveMemory(Thread
->Hostent
, Blob
->pBlobData
, Blob
->cbSize
);
335 /* No buffer space! */
336 Thread
->HostentSize
= 0;
337 SetLastError(WSA_NOT_ENOUGH_MEMORY
);
340 /* Return the buffer */
341 return (PHOSTENT
)Thread
->Hostent
;
346 WsThreadBlobToServent(IN PWSTHREAD Thread
,
349 /* Check if our buffer is too small */
350 if (Thread
->ServentSize
< Blob
->cbSize
)
352 /* Delete the current buffer and allocate a new one */
353 HeapFree(WsSockHeap
, 0, Thread
->Servent
);
354 Thread
->Servent
= HeapAlloc(WsSockHeap
, 0, Blob
->cbSize
);
356 /* Set the new size */
357 Thread
->ServentSize
= Blob
->cbSize
;
360 /* Do we have a buffer? */
363 /* Copy the data inside */
364 RtlMoveMemory(Thread
->Servent
, Blob
->pBlobData
, Blob
->cbSize
);
368 /* No buffer space! */
369 Thread
->ServentSize
= 0;
370 SetLastError(WSA_NOT_ENOUGH_MEMORY
);
373 /* Return the buffer */
374 return (PSERVENT
)Thread
->Servent
;