Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenasync.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS WinSock 2 API 00004 * FILE: async.c 00005 * PURPOSE: Async Block Object and Async Thread Management 00006 * PROGRAMMER: Alex Ionescu (alex@relsoft.net) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 #include "ws2_32.h" 00011 00012 /* DATA **********************************************************************/ 00013 BOOLEAN WsAsyncThreadInitialized; 00014 LONG WsAsyncTaskHandle; 00015 PLIST_ENTRY WsAsyncQueue; 00016 CRITICAL_SECTION WsAsyncCritSect; 00017 HANDLE WsAsyncEvent; 00018 HANDLE WsAsyncCurrentTaskHandle; 00019 HANDLE WsAsyncCancelledTaskHandle; 00020 HINSTANCE WsAsyncDllHandle; 00021 00022 #define WsAsyncLock() EnterCriticalSection(&WsAsyncCritSect); 00023 #define WsAsyncUnlock() LeaveCriticalSection(&WsAsyncCritSect); 00024 00025 /* FUNCTIONS *****************************************************************/ 00026 00027 VOID 00028 WSAAPI 00029 WsAsyncGlobalInitialize(VOID) 00030 { 00031 /* Initialize the async lock */ 00032 InitializeCriticalSection(&WsAsyncCritSect); 00033 } 00034 00035 VOID 00036 WSAAPI 00037 WsAsyncGlobalTerminate(VOID) 00038 { 00039 /* Destroy the async lock */ 00040 DeleteCriticalSection(&WsAsyncCritSect); 00041 } 00042 00043 00044 SIZE_T 00045 WSAAPI 00046 BytesInHostent(PHOSTENT Hostent) 00047 { 00048 SIZE_T Bytes; 00049 INT i; 00050 00051 /* Start with the static stuff */ 00052 Bytes = sizeof(HOSTENT) + strlen(Hostent->h_name) + sizeof(CHAR); 00053 00054 /* Add 2 pointers for the list-terminators */ 00055 Bytes += 2 * sizeof(ULONG_PTR); 00056 00057 /* Now loop for the alises */ 00058 for (i = 0; Hostent->h_aliases[i]; i++) 00059 { 00060 /* Add the alias size, plus the space its pointer takes */ 00061 Bytes += strlen(Hostent->h_aliases[i]) + sizeof(CHAR) + sizeof(ULONG_PTR); 00062 } 00063 00064 /* Now loop for the hostnames */ 00065 for (i = 0; Hostent->h_addr_list[i]; i++) 00066 { 00067 /* Add the alias size, plus the space its pointer takes */ 00068 Bytes += Hostent->h_length + sizeof(ULONG_PTR); 00069 } 00070 00071 /* Align to 8 bytes */ 00072 return (Bytes + 7) & ~7; 00073 } 00074 00075 SIZE_T 00076 WSAAPI 00077 BytesInServent(PSERVENT Servent) 00078 { 00079 SIZE_T Bytes; 00080 INT i; 00081 00082 /* Start with the static stuff */ 00083 Bytes = sizeof(SERVENT) + 00084 strlen(Servent->s_name) + sizeof(CHAR) + 00085 strlen(Servent->s_proto) + sizeof(CHAR); 00086 00087 /* Add 1 pointers for the list terminator */ 00088 Bytes += sizeof(ULONG_PTR); 00089 00090 /* Now loop for the alises */ 00091 for (i = 0; Servent->s_aliases[i]; i++) 00092 { 00093 /* Add the alias size, plus the space its pointer takes */ 00094 Bytes += strlen(Servent->s_aliases[i]) + sizeof(CHAR) + sizeof(ULONG_PTR); 00095 } 00096 00097 /* return */ 00098 return Bytes; 00099 } 00100 00101 SIZE_T 00102 WSAAPI 00103 BytesInProtoent(PPROTOENT Protoent) 00104 { 00105 SIZE_T Bytes; 00106 INT i; 00107 00108 /* Start with the static stuff */ 00109 Bytes = sizeof(SERVENT) + strlen(Protoent->p_name) + sizeof(CHAR); 00110 00111 /* Add 1 pointers for the list terminator */ 00112 Bytes += sizeof(ULONG_PTR); 00113 00114 /* Now loop for the alises */ 00115 for (i = 0; Protoent->p_aliases[i]; i++) 00116 { 00117 /* Add the alias size, plus the space its pointer takes */ 00118 Bytes += strlen(Protoent->p_aliases[i]) + sizeof(CHAR) + sizeof(ULONG_PTR); 00119 } 00120 00121 /* return */ 00122 return Bytes; 00123 } 00124 00125 SIZE_T 00126 WSAAPI 00127 CopyHostentToBuffer(IN PCHAR Buffer, 00128 IN INT BufferLength, 00129 IN PHOSTENT Hostent) 00130 { 00131 SIZE_T BufferSize, CurrentSize, NameSize; 00132 PCHAR p = Buffer; 00133 DWORD Aliases = 0, Names = 0; 00134 DWORD i; 00135 PHOSTENT ReturnedHostent = (PHOSTENT)Buffer; 00136 00137 /* Determine the buffer size required */ 00138 BufferSize = BytesInHostent(Hostent); 00139 00140 /* Check which size to use */ 00141 if ((DWORD)BufferLength > BufferSize) 00142 { 00143 /* Zero the buffer */ 00144 RtlZeroMemory(Buffer, BufferSize); 00145 } 00146 else 00147 { 00148 /* Zero the buffer */ 00149 RtlZeroMemory(Buffer, BufferLength); 00150 } 00151 00152 /* Start with the raw Hostent */ 00153 CurrentSize = sizeof(HOSTENT); 00154 00155 /* Return the size needed now */ 00156 if (CurrentSize > (DWORD)BufferLength) return BufferSize; 00157 00158 /* Copy the Hostent and initialize it */ 00159 CopyMemory(p, Hostent, sizeof(HOSTENT)); 00160 p = Buffer + CurrentSize; 00161 ReturnedHostent->h_name = NULL; 00162 ReturnedHostent->h_aliases = NULL; 00163 ReturnedHostent->h_addr_list = NULL; 00164 00165 /* Find out how many aliases there are */ 00166 while (Hostent->h_aliases[Aliases]) 00167 { 00168 /* Increase the alias count */ 00169 Aliases++; 00170 } 00171 00172 /* Add the aliases to the size, and validate it */ 00173 CurrentSize += (Aliases + 1) * sizeof(ULONG_PTR); 00174 if (CurrentSize > (DWORD)BufferLength) 00175 { 00176 /* Clear the aliases and return */ 00177 Hostent->h_aliases = NULL; 00178 return BufferSize; 00179 } 00180 00181 /* Write the aliases, update the pointer */ 00182 ReturnedHostent->h_aliases = (PCHAR*)p; 00183 p = Buffer + CurrentSize; 00184 00185 /* Find out how many names there are */ 00186 while (Hostent->h_addr_list[Names]) 00187 { 00188 /* Increase the alias count */ 00189 Names++; 00190 } 00191 00192 /* Add the names to the size, and validate it */ 00193 CurrentSize += (Names + 1) * sizeof(ULONG_PTR); 00194 if (CurrentSize > (DWORD)BufferLength) 00195 { 00196 /* Clear the aliases and return */ 00197 Hostent->h_addr_list = NULL; 00198 return BufferSize; 00199 } 00200 00201 /* Write the names, update the pointer */ 00202 ReturnedHostent->h_addr_list = (PCHAR*)p; 00203 p = Buffer + CurrentSize; 00204 00205 /* Now add the names */ 00206 for (i = 0; i < Names; i++) 00207 { 00208 /* Update size and validate */ 00209 CurrentSize += Hostent->h_length; 00210 if (CurrentSize > (DWORD)BufferLength) return BufferSize; 00211 00212 /* Write pointer and copy */ 00213 ReturnedHostent->h_addr_list[i] = p; 00214 CopyMemory(p, Hostent->h_addr_list[i], Hostent->h_length); 00215 00216 /* Update pointer */ 00217 p = Buffer + CurrentSize; 00218 } 00219 00220 /* Finalize the list */ 00221 ReturnedHostent->h_addr_list[i] = NULL; 00222 00223 /* Add the service name to the size, and validate it */ 00224 NameSize = strlen(Hostent->h_name) + sizeof(CHAR); 00225 CurrentSize += NameSize; 00226 if (CurrentSize > (DWORD)BufferLength) return BufferSize; 00227 00228 /* Write the service name and update the pointer */ 00229 ReturnedHostent->h_name = p; 00230 CopyMemory(p, Hostent->h_name, NameSize); 00231 p = Buffer + CurrentSize; 00232 00233 /* Now add the aliases */ 00234 for (i = 0; i < Aliases; i++) 00235 { 00236 /* Update size and validate */ 00237 NameSize = strlen(Hostent->h_aliases[i]) + sizeof(CHAR); 00238 CurrentSize += NameSize; 00239 if (CurrentSize > (DWORD)BufferLength) return BufferSize; 00240 00241 /* Write pointer and copy */ 00242 ReturnedHostent->h_aliases[i] = p; 00243 CopyMemory(p, Hostent->h_aliases[i], NameSize); 00244 00245 /* Update pointer */ 00246 p = Buffer + CurrentSize; 00247 } 00248 00249 /* Finalize the list and return */ 00250 ReturnedHostent->h_aliases[i] = NULL; 00251 return BufferSize; 00252 } 00253 00254 SIZE_T 00255 WSAAPI 00256 CopyServentToBuffer(IN PCHAR Buffer, 00257 IN INT BufferLength, 00258 IN PSERVENT Servent) 00259 { 00260 SIZE_T BufferSize, CurrentSize, NameSize; 00261 PCHAR p = Buffer; 00262 DWORD Aliases = 0; 00263 DWORD i; 00264 PSERVENT ReturnedServent = (PSERVENT)Buffer; 00265 00266 /* Determine the buffer size required */ 00267 BufferSize = BytesInServent(Servent); 00268 00269 /* Check which size to use */ 00270 if ((DWORD)BufferLength > BufferSize) 00271 { 00272 /* Zero the buffer */ 00273 ZeroMemory(Buffer, BufferSize); 00274 } 00275 else 00276 { 00277 /* Zero the buffer */ 00278 ZeroMemory(Buffer, BufferLength); 00279 } 00280 00281 /* Start with the raw servent */ 00282 CurrentSize = sizeof(SERVENT); 00283 00284 /* Return the size needed now */ 00285 if (CurrentSize > (DWORD)BufferLength) return BufferSize; 00286 00287 /* Copy the servent and initialize it */ 00288 CopyMemory(p, Servent, sizeof(SERVENT)); 00289 p = Buffer + CurrentSize; 00290 ReturnedServent->s_name = NULL; 00291 ReturnedServent->s_aliases = NULL; 00292 ReturnedServent->s_proto = NULL; 00293 00294 /* Find out how many aliases there are */ 00295 while (Servent->s_aliases[Aliases]) 00296 { 00297 /* Increase the alias count */ 00298 Aliases++; 00299 } 00300 00301 /* Add the aliases to the size, and validate it */ 00302 CurrentSize += (Aliases + 1) * sizeof(ULONG_PTR); 00303 if (CurrentSize > (DWORD)BufferLength) 00304 { 00305 /* Clear the aliases and return */ 00306 Servent->s_aliases = NULL; 00307 return BufferSize; 00308 } 00309 00310 /* Write the aliases, update the pointer */ 00311 ReturnedServent->s_aliases = (PCHAR*)p; 00312 p = Buffer + CurrentSize; 00313 00314 /* Add the service name to the size, and validate it */ 00315 NameSize = strlen(Servent->s_name) + sizeof(CHAR); 00316 CurrentSize += NameSize; 00317 if (CurrentSize > (DWORD)BufferLength) return BufferSize; 00318 00319 /* Write the service name and update the pointer */ 00320 ReturnedServent->s_name = p; 00321 CopyMemory(p, Servent->s_name, NameSize); 00322 p = Buffer + CurrentSize; 00323 00324 /* Now add the aliases */ 00325 for (i = 0; i < Aliases; i++) 00326 { 00327 /* Update size and validate */ 00328 NameSize = strlen(Servent->s_aliases[i]) + sizeof(CHAR); 00329 CurrentSize += NameSize; 00330 if (CurrentSize > (DWORD)BufferLength) return BufferSize; 00331 00332 /* Write pointer and copy */ 00333 ReturnedServent->s_aliases[i] = p; 00334 CopyMemory(p, Servent->s_aliases[i], NameSize); 00335 00336 /* Update pointer */ 00337 p = Buffer + CurrentSize; 00338 } 00339 00340 /* Finalize the list and return */ 00341 ReturnedServent->s_aliases[i] = NULL; 00342 return BufferSize; 00343 } 00344 00345 SIZE_T 00346 WSAAPI 00347 CopyProtoentToBuffer(IN PCHAR Buffer, 00348 IN INT BufferLength, 00349 IN PPROTOENT Protoent) 00350 { 00351 SIZE_T BufferSize, CurrentSize, NameSize; 00352 PCHAR p = Buffer; 00353 DWORD Aliases = 0; 00354 DWORD i; 00355 PPROTOENT ReturnedProtoent = (PPROTOENT)Buffer; 00356 00357 /* Determine the buffer size required */ 00358 BufferSize = BytesInProtoent(Protoent); 00359 00360 /* Check which size to use */ 00361 if ((DWORD)BufferLength > BufferSize) 00362 { 00363 /* Zero the buffer */ 00364 ZeroMemory(Buffer, BufferSize); 00365 } 00366 else 00367 { 00368 /* Zero the buffer */ 00369 ZeroMemory(Buffer, BufferLength); 00370 } 00371 00372 /* Start with the raw servent */ 00373 CurrentSize = sizeof(PROTOENT); 00374 00375 /* Return the size needed now */ 00376 if (CurrentSize > (DWORD)BufferLength) return BufferSize; 00377 00378 /* Copy the servent and initialize it */ 00379 CopyMemory(p, Protoent, sizeof(PROTOENT)); 00380 p = Buffer + CurrentSize; 00381 ReturnedProtoent->p_name = NULL; 00382 ReturnedProtoent->p_aliases = NULL; 00383 00384 /* Find out how many aliases there are */ 00385 while (Protoent->p_aliases[Aliases]) 00386 { 00387 /* Increase the alias count */ 00388 Aliases++; 00389 } 00390 00391 /* Add the aliases to the size, and validate it */ 00392 CurrentSize += (Aliases + 1) * sizeof(ULONG_PTR); 00393 if (CurrentSize > (DWORD)BufferLength) 00394 { 00395 /* Clear the aliases and return */ 00396 Protoent->p_aliases = NULL; 00397 return BufferSize; 00398 } 00399 00400 /* Write the aliases, update the pointer */ 00401 ReturnedProtoent->p_aliases = (PCHAR*)p; 00402 p = Buffer + CurrentSize; 00403 00404 /* Add the service name to the size, and validate it */ 00405 NameSize = strlen(Protoent->p_name) + sizeof(CHAR); 00406 CurrentSize += NameSize; 00407 if (CurrentSize > (DWORD)BufferLength) return BufferSize; 00408 00409 /* Write the service name and update the pointer */ 00410 ReturnedProtoent->p_name = p; 00411 CopyMemory(p, Protoent->p_name, NameSize); 00412 p = Buffer + CurrentSize; 00413 00414 /* Now add the aliases */ 00415 for (i = 0; i < Aliases; i++) 00416 { 00417 /* Update size and validate */ 00418 NameSize = strlen(Protoent->p_aliases[i]) + sizeof(CHAR); 00419 CurrentSize += NameSize; 00420 if (CurrentSize > (DWORD)BufferLength) return BufferSize; 00421 00422 /* Write pointer and copy */ 00423 ReturnedProtoent->p_aliases[i] = p; 00424 CopyMemory(p, Protoent->p_aliases[i], NameSize); 00425 00426 /* Update pointer */ 00427 p = Buffer + CurrentSize; 00428 } 00429 00430 /* Finalize the list and return */ 00431 ReturnedProtoent->p_aliases[i] = NULL; 00432 return BufferSize; 00433 } 00434 00435 PWSASYNCBLOCK 00436 WSAAPI 00437 WsAsyncAllocateBlock(IN SIZE_T ExtraLength) 00438 { 00439 PWSASYNCBLOCK AsyncBlock; 00440 00441 /* Add the size of the block */ 00442 ExtraLength += sizeof(WSASYNCBLOCK); 00443 00444 /* Allocate it */ 00445 AsyncBlock = HeapAlloc(WsSockHeap, 0, ExtraLength); 00446 00447 /* Get a handle to it */ 00448 AsyncBlock->TaskHandle = UlongToPtr(InterlockedIncrement(&WsAsyncTaskHandle)); 00449 00450 /* Return it */ 00451 return AsyncBlock; 00452 } 00453 00454 BOOL 00455 WINAPI 00456 WsAsyncThreadBlockingHook(VOID) 00457 { 00458 /* Check if this task is being cancelled */ 00459 if (WsAsyncCurrentTaskHandle == WsAsyncCancelledTaskHandle) 00460 { 00461 /* Cancel the blocking call so we can get back */ 00462 WSACancelBlockingCall(); 00463 } 00464 00465 /* Return to system */ 00466 return FALSE; 00467 } 00468 00469 VOID 00470 WSAAPI 00471 WsAsyncFreeBlock(IN PWSASYNCBLOCK AsyncBlock) 00472 { 00473 /* Free it */ 00474 HeapFree(WsSockHeap, 0, AsyncBlock); 00475 } 00476 00477 VOID 00478 WSAAPI 00479 WsAsyncGetServ(IN HANDLE TaskHandle, 00480 IN DWORD Operation, 00481 IN HWND hWnd, 00482 IN UINT wMsg, 00483 IN CHAR FAR *ByWhat, 00484 IN CHAR FAR *Protocol, 00485 IN CHAR FAR *Buffer, 00486 IN INT BufferLength) 00487 { 00488 PSERVENT Servent; 00489 SIZE_T BufferSize = 0; 00490 LPARAM lParam; 00491 INT ErrorCode = 0; 00492 00493 /* Check the operaiton */ 00494 if (Operation == WsAsyncGetServByName) 00495 { 00496 /* Call the API */ 00497 Servent = getservbyname(ByWhat, Protocol); 00498 } 00499 else 00500 { 00501 /* Call the API */ 00502 Servent = getservbyport(PtrToUlong(ByWhat), Protocol); 00503 } 00504 00505 /* Make sure we got one */ 00506 if (!Servent) ErrorCode = GetLastError(); 00507 00508 /* Acquire the lock */ 00509 WsAsyncLock(); 00510 00511 /* Check if this task got cancelled */ 00512 if (TaskHandle == WsAsyncCancelledTaskHandle) 00513 { 00514 /* Return */ 00515 WsAsyncUnlock(); 00516 return; 00517 } 00518 00519 /* If we got a Servent back, copy it */ 00520 if (Servent) 00521 { 00522 /* Copy it into the buffer */ 00523 BufferSize = CopyServentToBuffer(Buffer, BufferLength, Servent); 00524 00525 /* Check if we had enough space */ 00526 if (BufferSize > (DWORD)BufferLength) 00527 { 00528 /* Not enough */ 00529 ErrorCode = WSAENOBUFS; 00530 } 00531 else 00532 { 00533 /* Perfect */ 00534 ErrorCode = NO_ERROR; 00535 } 00536 } 00537 00538 /* Not processing anyomre */ 00539 WsAsyncCurrentTaskHandle = NULL; 00540 00541 /* Release the lock */ 00542 WsAsyncUnlock(); 00543 00544 /* Make the messed-up lParam reply */ 00545 lParam = WSAMAKEASYNCREPLY(BufferSize, ErrorCode); 00546 00547 /* Sent it through the Upcall API */ 00548 WPUPostMessage(hWnd, wMsg, (WPARAM)TaskHandle, lParam); 00549 } 00550 00551 VOID 00552 WSAAPI 00553 WsAsyncGetProto(IN HANDLE TaskHandle, 00554 IN DWORD Operation, 00555 IN HWND hWnd, 00556 IN UINT wMsg, 00557 IN CHAR FAR *ByWhat, 00558 IN CHAR FAR *Buffer, 00559 IN INT BufferLength) 00560 { 00561 PPROTOENT Protoent; 00562 SIZE_T BufferSize = 0; 00563 LPARAM lParam; 00564 INT ErrorCode = 0; 00565 00566 /* Check the operaiton */ 00567 if (Operation == WsAsyncGetProtoByName) 00568 { 00569 /* Call the API */ 00570 Protoent = getprotobyname(ByWhat); 00571 } 00572 else 00573 { 00574 /* Call the API */ 00575 Protoent = getprotobynumber(PtrToUlong(ByWhat)); 00576 } 00577 00578 /* Make sure we got one */ 00579 if (!Protoent) ErrorCode = GetLastError(); 00580 00581 /* Acquire the lock */ 00582 WsAsyncLock(); 00583 00584 /* Check if this task got cancelled */ 00585 if (TaskHandle == WsAsyncCancelledTaskHandle) 00586 { 00587 /* Return */ 00588 WsAsyncUnlock(); 00589 return; 00590 } 00591 00592 /* If we got a Servent back, copy it */ 00593 if (Protoent) 00594 { 00595 /* Copy it into the buffer */ 00596 BufferSize = CopyProtoentToBuffer(Buffer, BufferLength, Protoent); 00597 00598 /* Check if we had enough space */ 00599 if (BufferSize > (DWORD)BufferLength) 00600 { 00601 /* Not enough */ 00602 ErrorCode = WSAENOBUFS; 00603 } 00604 else 00605 { 00606 /* Perfect */ 00607 ErrorCode = NO_ERROR; 00608 } 00609 } 00610 00611 /* Not processing anyomre */ 00612 WsAsyncCurrentTaskHandle = NULL; 00613 00614 /* Release the lock */ 00615 WsAsyncUnlock(); 00616 00617 /* Make the messed-up lParam reply */ 00618 lParam = WSAMAKEASYNCREPLY(BufferSize, ErrorCode); 00619 00620 /* Sent it through the Upcall API */ 00621 WPUPostMessage(hWnd, wMsg, (WPARAM)TaskHandle, lParam); 00622 } 00623 00624 VOID 00625 WSAAPI 00626 WsAsyncGetHost(IN HANDLE TaskHandle, 00627 IN DWORD Operation, 00628 IN HWND hWnd, 00629 IN UINT wMsg, 00630 IN CHAR FAR *ByWhat, 00631 IN INT Length, 00632 IN INT Type, 00633 IN CHAR FAR *Buffer, 00634 IN INT BufferLength) 00635 { 00636 PHOSTENT Hostent; 00637 SIZE_T BufferSize = 0; 00638 LPARAM lParam; 00639 INT ErrorCode = 0; 00640 00641 /* Check the operaiton */ 00642 if (Operation == WsAsyncGetHostByAddr) 00643 { 00644 /* Call the API */ 00645 Hostent = gethostbyaddr(ByWhat, Length, Type); 00646 } 00647 else 00648 { 00649 /* Call the API */ 00650 Hostent = gethostbyname(ByWhat); 00651 } 00652 00653 /* Make sure we got one */ 00654 if (!Hostent) ErrorCode = GetLastError(); 00655 00656 /* Acquire the lock */ 00657 WsAsyncLock(); 00658 00659 /* Check if this task got cancelled */ 00660 if (TaskHandle == WsAsyncCancelledTaskHandle) 00661 { 00662 /* Return */ 00663 WsAsyncUnlock(); 00664 return; 00665 } 00666 00667 /* If we got a Servent back, copy it */ 00668 if (Hostent) 00669 { 00670 /* Copy it into the buffer */ 00671 BufferSize = CopyHostentToBuffer(Buffer, BufferLength, Hostent); 00672 00673 /* Check if we had enough space */ 00674 if (BufferSize > (DWORD)BufferLength) 00675 { 00676 /* Not enough */ 00677 ErrorCode = WSAENOBUFS; 00678 } 00679 else 00680 { 00681 /* Perfect */ 00682 ErrorCode = NO_ERROR; 00683 } 00684 } 00685 00686 /* Not processing anyomre */ 00687 WsAsyncCurrentTaskHandle = NULL; 00688 00689 /* Release the lock */ 00690 WsAsyncUnlock(); 00691 00692 /* Make the messed-up lParam reply */ 00693 lParam = WSAMAKEASYNCREPLY(BufferSize, ErrorCode); 00694 00695 /* Sent it through the Upcall API */ 00696 WPUPostMessage(hWnd, wMsg, (WPARAM)TaskHandle, lParam); 00697 } 00698 00699 DWORD 00700 WINAPI 00701 WsAsyncThread(IN PWSASYNCCONTEXT Context) 00702 { 00703 PWSASYNCBLOCK AsyncBlock; 00704 PLIST_ENTRY Entry; 00705 HANDLE AsyncEvent = Context->AsyncEvent; 00706 PLIST_ENTRY ListHead = &Context->AsyncQueue; 00707 00708 /* Set the blocking hook */ 00709 WSASetBlockingHook((FARPROC)WsAsyncThreadBlockingHook); 00710 00711 /* Loop */ 00712 while (TRUE) 00713 { 00714 /* Wait for the event */ 00715 WaitForSingleObject(AsyncEvent, INFINITE); 00716 00717 /* Get the lock */ 00718 WsAsyncLock(); 00719 00720 /* Process the queue */ 00721 while (ListHead->Flink != ListHead) 00722 { 00723 /* Remove this entry and get the async block */ 00724 Entry = RemoveHeadList(ListHead); 00725 AsyncBlock = CONTAINING_RECORD(Entry, WSASYNCBLOCK, AsyncQueue); 00726 00727 /* Save the current task handle */ 00728 WsAsyncCurrentTaskHandle = AsyncBlock->TaskHandle; 00729 00730 /* Release the lock */ 00731 WsAsyncUnlock(); 00732 00733 /* Check which operation to do */ 00734 switch (AsyncBlock->Operation) 00735 { 00736 /* Get Host by Y */ 00737 case WsAsyncGetHostByAddr: case WsAsyncGetHostByName: 00738 00739 /* Call the handler */ 00740 WsAsyncGetHost(AsyncBlock->TaskHandle, 00741 AsyncBlock->Operation, 00742 AsyncBlock->GetHost.hWnd, 00743 AsyncBlock->GetHost.wMsg, 00744 AsyncBlock->GetHost.ByWhat, 00745 AsyncBlock->GetHost.Length, 00746 AsyncBlock->GetHost.Type, 00747 AsyncBlock->GetHost.Buffer, 00748 AsyncBlock->GetHost.BufferLength); 00749 break; 00750 00751 /* Get Proto by Y */ 00752 case WsAsyncGetProtoByNumber: case WsAsyncGetProtoByName: 00753 00754 /* Call the handler */ 00755 WsAsyncGetProto(AsyncBlock->TaskHandle, 00756 AsyncBlock->Operation, 00757 AsyncBlock->GetProto.hWnd, 00758 AsyncBlock->GetProto.wMsg, 00759 AsyncBlock->GetHost.ByWhat, 00760 AsyncBlock->GetProto.Buffer, 00761 AsyncBlock->GetProto.BufferLength); 00762 break; 00763 00764 /* Get Serv by Y */ 00765 case WsAsyncGetServByPort: case WsAsyncGetServByName: 00766 00767 /* Call the handler */ 00768 WsAsyncGetServ(AsyncBlock->TaskHandle, 00769 AsyncBlock->Operation, 00770 AsyncBlock->GetServ.hWnd, 00771 AsyncBlock->GetServ.wMsg, 00772 AsyncBlock->GetServ.ByWhat, 00773 AsyncBlock->GetServ.Protocol, 00774 AsyncBlock->GetServ.Buffer, 00775 AsyncBlock->GetServ.BufferLength); 00776 break; 00777 00778 /* Termination */ 00779 case WsAsyncTerminate: 00780 00781 /* Clean up the extra reference */ 00782 WSACleanup(); 00783 00784 /* Free the context block */ 00785 WsAsyncFreeBlock(AsyncBlock); 00786 00787 /* Acquire the lock */ 00788 WsAsyncLock(); 00789 00790 /* Loop the queue and flush it */ 00791 while (!IsListEmpty(ListHead)) 00792 { 00793 Entry = RemoveHeadList(ListHead); 00794 AsyncBlock = CONTAINING_RECORD(Entry, 00795 WSASYNCBLOCK, 00796 AsyncQueue); 00797 WsAsyncFreeBlock(AsyncBlock); 00798 } 00799 00800 /* Release lock */ 00801 WsAsyncUnlock(); 00802 00803 /* Close the event, free the Context */ 00804 CloseHandle(AsyncEvent); 00805 HeapFree(WsSockHeap, 0, Context); 00806 00807 /* Remove the extra DLL reference and kill us */ 00808 FreeLibraryAndExitThread(WsAsyncDllHandle, 0); 00809 00810 default: 00811 break; 00812 } 00813 00814 /* Done processing */ 00815 WsAsyncCurrentTaskHandle = NULL; 00816 00817 /* Free this block, get lock and reloop */ 00818 WsAsyncFreeBlock(AsyncBlock); 00819 WsAsyncLock(); 00820 } 00821 00822 /* Release the lock */ 00823 WsAsyncUnlock(); 00824 } 00825 } 00826 00827 BOOL 00828 WSAAPI 00829 WsAsyncCheckAndInitThread(VOID) 00830 { 00831 HANDLE ThreadHandle; 00832 DWORD Tid; 00833 PWSASYNCCONTEXT Context = NULL; 00834 WSADATA WsaData; 00835 00836 /* Make sure we're not initialized */ 00837 if (WsAsyncThreadInitialized) return TRUE; 00838 00839 /* Acquire the lock */ 00840 WsAsyncLock(); 00841 00842 /* Make sure we're not initialized */ 00843 if (!WsAsyncThreadInitialized) 00844 { 00845 /* Initialize Thread Context */ 00846 Context = HeapAlloc(WsSockHeap, 0, sizeof(*Context)); 00847 00848 /* Initialize the Queue and event */ 00849 WsAsyncQueue = &Context->AsyncQueue; 00850 InitializeListHead(WsAsyncQueue); 00851 Context->AsyncEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 00852 WsAsyncEvent = Context->AsyncEvent; 00853 00854 /* Prevent us from ever being killed while running */ 00855 WSAStartup(MAKEWORD(2,2), &WsaData); 00856 00857 /* Create the thread */ 00858 ThreadHandle = CreateThread(NULL, 00859 0, 00860 (LPTHREAD_START_ROUTINE)WsAsyncThread, 00861 Context, 00862 0, 00863 &Tid); 00864 00865 /* Close the handle and set init */ 00866 CloseHandle(ThreadHandle); 00867 WsAsyncThreadInitialized = TRUE; 00868 } 00869 00870 /* Release the lock */ 00871 WsAsyncUnlock(); 00872 return WsAsyncThreadInitialized; 00873 } 00874 00875 VOID 00876 WSAAPI 00877 WsAsyncTerminateThread(VOID) 00878 { 00879 PWSASYNCBLOCK AsyncBlock; 00880 00881 /* Make sure we're initialized */ 00882 if (!WsAsyncThreadInitialized) return; 00883 00884 /* Allocate a block */ 00885 AsyncBlock = WsAsyncAllocateBlock(0); 00886 00887 /* Initialize it for termination */ 00888 AsyncBlock->Operation = WsAsyncTerminate; 00889 00890 /* Queue the request and return */ 00891 WsAsyncQueueRequest(AsyncBlock); 00892 WsAsyncThreadInitialized = FALSE; 00893 } 00894 00895 VOID 00896 WSAAPI 00897 WsAsyncQueueRequest(IN PWSASYNCBLOCK AsyncBlock) 00898 { 00899 /* Get the lock */ 00900 WsAsyncLock(); 00901 00902 /* Insert it into the queue */ 00903 InsertTailList(WsAsyncQueue, &AsyncBlock->AsyncQueue); 00904 00905 /* Wake up the thread */ 00906 SetEvent(WsAsyncEvent); 00907 00908 /* Release lock and return */ 00909 WsAsyncUnlock(); 00910 } 00911 00912 INT 00913 WSAAPI 00914 WsAsyncCancelRequest(IN HANDLE TaskHandle) 00915 { 00916 PLIST_ENTRY Entry; 00917 PWSASYNCBLOCK AsyncBlock; 00918 00919 /* Make sure we're initialized */ 00920 if (!WsAsyncThreadInitialized) return WSAEINVAL; 00921 00922 /* Acquire the lock */ 00923 WsAsyncLock(); 00924 00925 /* Check if we're cancelling the current task */ 00926 if (TaskHandle == WsAsyncCurrentTaskHandle) 00927 { 00928 /* Mark us as cancelled, the async thread will see this later */ 00929 WsAsyncCancelledTaskHandle = TaskHandle; 00930 00931 /* Release lock and return */ 00932 WsAsyncUnlock(); 00933 return NO_ERROR; 00934 } 00935 00936 /* Loop the queue */ 00937 Entry = WsAsyncQueue->Flink; 00938 while (Entry != WsAsyncQueue) 00939 { 00940 /* Get the Async Block */ 00941 AsyncBlock = CONTAINING_RECORD(Entry, WSASYNCBLOCK, AsyncQueue); 00942 00943 /* Check if this is the one */ 00944 if (TaskHandle == AsyncBlock->TaskHandle) 00945 { 00946 /* It is, remove it */ 00947 RemoveEntryList(Entry); 00948 00949 /* Release the lock, free the block, and return */ 00950 WsAsyncUnlock(); 00951 WsAsyncFreeBlock(AsyncBlock); 00952 return NO_ERROR; 00953 } 00954 00955 /* Move to the next entry */ 00956 Entry = Entry->Flink; 00957 } 00958 00959 /* Nothing found, fail */ 00960 WsAsyncUnlock(); 00961 return WSAEINVAL; 00962 } Generated on Sat May 26 2012 04:25:37 for ReactOS by
1.7.6.1
|