ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

async.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.