4b7c65de73843f2d7ccacf0c3ec35d22a5b3bf1f
[reactos.git] / reactos / dll / win32 / ws2_32_new / src / dthread.c
1 /*
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)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ws2_32.h>
12
13 /* FUNCTIONS *****************************************************************/
14
15 DWORD
16 WSAAPI
17 WsThreadDefaultBlockingHook(VOID)
18 {
19 MSG Message;
20 BOOL GotMessage = FALSE;
21
22 /* Get the message */
23 GotMessage = PeekMessage(&Message, NULL, 0, 0, PM_REMOVE);
24
25 /* Check if we got one */
26 if (GotMessage)
27 {
28 /* Process it */
29 TranslateMessage(&Message);
30 DispatchMessage(&Message);
31 }
32
33 /* return */
34 return GotMessage;
35 }
36
37 BOOL
38 WSAAPI
39 WsThreadBlockingCallback(IN DWORD_PTR Context)
40 {
41 PWSTHREAD Thread = TlsGetValue(TlsIndex);
42
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;
47
48 /* Call the blocking hook */
49 while(Thread->BlockingHook());
50
51 /* We're not blocking anymore */
52 Thread->Blocking = FALSE;
53
54 /* Return whether or not we were cancelled */
55 return !Thread->Cancelled;
56 }
57
58 FARPROC
59 WSAAPI
60 WsThreadSetBlockingHook(IN PWSTHREAD Thread,
61 IN FARPROC BlockingHook)
62 {
63 FARPROC OldHook = Thread->BlockingHook;
64
65 /* Check if we're resetting to our default hook */
66 if (BlockingHook == (FARPROC)WsThreadDefaultBlockingHook)
67 {
68 /* Clear out the blocking callback */
69 Thread->BlockingCallback = NULL;
70 }
71 else
72 {
73 /* Set the blocking callback */
74 Thread->BlockingCallback = WsThreadBlockingCallback;
75 }
76
77 /* Set the new blocking hook and return the previous */
78 Thread->BlockingHook = BlockingHook;
79 return OldHook;
80 }
81
82 DWORD
83 WSAAPI
84 WsThreadUnhookBlockingHook(IN PWSTHREAD Thread)
85 {
86 /* Reset the hook to the default, and remove the callback */
87 Thread->BlockingHook = (FARPROC)WsThreadDefaultBlockingHook;
88 Thread->BlockingCallback = NULL;
89
90 /* Return success */
91 return ERROR_SUCCESS;
92 }
93
94 DWORD
95 WSAAPI
96 WsThreadCancelBlockingCall(IN PWSTHREAD Thread)
97 {
98 INT ErrorCode, ReturnValue;
99
100 /* Make sure that the Thread is really in a blocking call */
101 if (!Thread->Blocking) return WSAEINVAL;
102
103 /* Make sure we haven't already been cancelled */
104 if (!Thread->Cancelled)
105 {
106 /* Call the cancel procedure */
107 ReturnValue = Thread->CancelBlockingCall(&ErrorCode);
108 if (ReturnValue != ERROR_SUCCESS) return ErrorCode;
109
110 /* Set us as cancelled */
111 Thread->Cancelled = TRUE;
112 }
113
114 /* Success */
115 return ERROR_SUCCESS;
116 }
117
118 PWSPROTO_BUFFER
119 WSAAPI
120 WsThreadGetProtoBuffer(IN PWSTHREAD Thread)
121 {
122 /* See if it already exists */
123 if (!Thread->ProtocolInfo)
124 {
125 /* We don't have a buffer; allocate it */
126 Thread->ProtocolInfo = HeapAlloc(WsSockHeap, 0, sizeof(WSPROTO_BUFFER));
127 }
128
129 /* Return it */
130 return Thread->ProtocolInfo;
131 }
132
133 PWSTHREAD
134 WSAAPI
135 WsThreadAllocate(VOID)
136 {
137 PWSTHREAD Thread;
138
139 /* Allocate the object */
140 Thread = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Thread));
141
142 /* Set non-zero data */
143 Thread->BlockingHook = (FARPROC)WsThreadDefaultBlockingHook;
144
145 /* Return it */
146 return Thread;
147 }
148
149 DWORD
150 WSAAPI
151 WsThreadStartup(VOID)
152 {
153 INT ErrorCode = WSASYSCALLFAILURE;
154
155 /* Check if we have a valid TLS */
156 if (TlsIndex != TLS_OUT_OF_INDEXES)
157 {
158 /* TLS was already OK */
159 ErrorCode = ERROR_SUCCESS;
160 }
161
162 /* Return */
163 return ErrorCode;
164 }
165
166 VOID
167 WSAAPI
168 WsThreadCleanup(VOID)
169 {
170 }
171
172 DWORD
173 WSAAPI
174 WsThreadInitialize(IN PWSTHREAD Thread,
175 IN PWSPROCESS Process)
176 {
177 INT ErrorCode = WSASYSCALLFAILURE;
178
179 /* Set the process */
180 Thread->Process = Process;
181
182 /* Get the helper device */
183 if ((WsProcGetAsyncHelper(Process, &Thread->AsyncHelper)) == ERROR_SUCCESS)
184 {
185 /* Initialize a WAH Thread ID */
186 if ((WahOpenCurrentThread(Thread->AsyncHelper,
187 &Thread->WahThreadId)) == ERROR_SUCCESS)
188 {
189 /* Success */
190 ErrorCode = ERROR_SUCCESS;
191 }
192 }
193
194 /* Return */
195 return ErrorCode;
196 }
197
198 VOID
199 WSAAPI
200 WsThreadDelete(IN PWSTHREAD Thread)
201 {
202 /* Remove the blocking hook */
203 Thread->BlockingHook = NULL;
204
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);
209
210 /* Clear the TLS */
211 TlsSetValue(TlsIndex, NULL);
212
213 /* Close the WAH Handle */
214 WahCloseThread(Thread->AsyncHelper, &Thread->WahThreadId);
215
216 /* Unlink the process and free us */
217 Thread->Process = NULL;
218 HeapFree(WsSockHeap, 0, Thread);
219 }
220
221 VOID
222 WSAAPI
223 WsThreadDestroyCurrentThread(VOID)
224 {
225 PWSTHREAD Thread;
226
227 /* Make sure we have TLS */
228 if (TlsIndex != TLS_OUT_OF_INDEXES)
229 {
230 /* Get the thread */
231 if ((Thread = TlsGetValue(TlsIndex)))
232 {
233 /* Delete it */
234 WsThreadDelete(Thread);
235 TlsSetValue(TlsIndex, 0);
236 }
237 }
238 }
239
240 DWORD
241 WSAAPI
242 WsThreadCreate(IN PWSPROCESS Process,
243 IN PWSTHREAD *CurrentThread)
244 {
245 PWSTHREAD Thread = NULL;
246 INT ErrorCode = WSASYSCALLFAILURE;
247
248 /* Make sure we have TLS */
249 if (TlsIndex != TLS_OUT_OF_INDEXES)
250 {
251 /* Allocate the thread */
252 if ((Thread = WsThreadAllocate()))
253 {
254 /* Initialize it */
255 if (WsThreadInitialize(Thread, Process) == ERROR_SUCCESS)
256 {
257 /* Set the TLS */
258 if (TlsSetValue(TlsIndex, Thread))
259 {
260 /* Return it and success */
261 *CurrentThread = Thread;
262 ErrorCode = ERROR_SUCCESS;
263 }
264 }
265
266 /* Check for any failures */
267 if (ErrorCode != ERROR_SUCCESS) WsThreadDelete(Thread);
268 }
269 }
270
271 /* Return */
272 return ErrorCode;
273 }
274
275 DWORD
276 WSAAPI
277 WsThreadGetCurrentThread(IN PWSPROCESS Process,
278 IN PWSTHREAD *Thread)
279 {
280 /* Get the thread */
281 if ((*Thread = TlsGetValue(TlsIndex)))
282 {
283 /* Success */
284 return ERROR_SUCCESS;
285 }
286 else
287 {
288 /* We failed, initialize it */
289 return WsThreadCreate(Process, Thread);
290 }
291 }
292
293 LPWSATHREADID
294 WSAAPI
295 WsThreadGetThreadId(IN PWSPROCESS Process)
296 {
297 PWSTHREAD Thread;
298
299 /* Get the thread */
300 if ((Thread = TlsGetValue(TlsIndex)))
301 {
302 /* Return the ID */
303 return &Thread->WahThreadId;
304 }
305 else
306 {
307 /* Not a valid thread */
308 return NULL;
309 }
310 }
311
312 PHOSTENT
313 WSAAPI
314 WsThreadBlobToHostent(IN PWSTHREAD Thread,
315 IN LPBLOB Blob)
316 {
317 /* Check if our buffer is too small */
318 if (Thread->HostentSize < Blob->cbSize)
319 {
320 /* Delete the current buffer and allocate a new one */
321 HeapFree(WsSockHeap, 0, Thread->Hostent);
322 Thread->Hostent = HeapAlloc(WsSockHeap, 0, Blob->cbSize);
323
324 /* Set the new size */
325 Thread->HostentSize = Blob->cbSize;
326 }
327
328 /* Do we have a buffer? */
329 if (Thread->Hostent)
330 {
331 /* Copy the data inside */
332 RtlMoveMemory(Thread->Hostent, Blob->pBlobData, Blob->cbSize);
333 }
334 else
335 {
336 /* No buffer space! */
337 Thread->HostentSize = 0;
338 SetLastError(WSA_NOT_ENOUGH_MEMORY);
339 }
340
341 /* Return the buffer */
342 return (PHOSTENT)Thread->Hostent;
343 }
344
345 PSERVENT
346 WSAAPI
347 WsThreadBlobToServent(IN PWSTHREAD Thread,
348 IN LPBLOB Blob)
349 {
350 /* Check if our buffer is too small */
351 if (Thread->ServentSize < Blob->cbSize)
352 {
353 /* Delete the current buffer and allocate a new one */
354 HeapFree(WsSockHeap, 0, Thread->Servent);
355 Thread->Servent = HeapAlloc(WsSockHeap, 0, Blob->cbSize);
356
357 /* Set the new size */
358 Thread->ServentSize = Blob->cbSize;
359 }
360
361 /* Do we have a buffer? */
362 if (Thread->Servent)
363 {
364 /* Copy the data inside */
365 RtlMoveMemory(Thread->Servent, Blob->pBlobData, Blob->cbSize);
366 }
367 else
368 {
369 /* No buffer space! */
370 Thread->ServentSize = 0;
371 SetLastError(WSA_NOT_ENOUGH_MEMORY);
372 }
373
374 /* Return the buffer */
375 return (PSERVENT)Thread->Servent;
376 }
377