- Add ws2help from alex-network-branch

svn path=/trunk/; revision=42115
This commit is contained in:
Dmitry Chapyshev 2009-07-21 09:16:26 +00:00
parent fd8fa4a64c
commit c2018d5633
11 changed files with 1739 additions and 0 deletions

View file

@ -0,0 +1,152 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: include/ws2_32.h
* PURPOSE: WinSock 2 DLL header
*/
/* INCLUDES ******************************************************************/
#include "precomp.h"
/* DATA **********************************************************************/
#define APCH (HANDLE)'SOR '
/* FUNCTIONS *****************************************************************/
DWORD
WINAPI
WahOpenApcHelper(OUT PHANDLE ApcHelperHandle)
{
DWORD ErrorCode;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate handle */
if (!ApcHelperHandle) return ERROR_INVALID_PARAMETER;
/*
* Return a bogus handle ("ROS")
* Historical note:(MS sends "CKM", which probably stands for "Keith Moore"
* (KM), one of the core architects of Winsock 2.2 from Microsoft.
*/
*ApcHelperHandle = APCH;
return ERROR_SUCCESS;
}
DWORD
WINAPI
WahCloseApcHelper(IN HANDLE ApcHelperHandle)
{
DWORD ErrorCode;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate handle */
if (ApcHelperHandle != APCH) return ERROR_INVALID_PARAMETER;
/* return */
return ERROR_SUCCESS;
}
DWORD
WINAPI
WahCloseThread(IN HANDLE ApcHelperHandle,
IN LPWSATHREADID ThreadId)
{
DWORD ErrorCode;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate handles */
if ((ApcHelperHandle != APCH) || (!ThreadId) || (!ThreadId->ThreadHandle))
{
/* Invalid helper/thread handles */
return ERROR_INVALID_PARAMETER;
}
/* Close the thread handle */
if (CloseHandle(ThreadId->ThreadHandle))
{
/* Clear the sturcture */
ThreadId->ThreadHandle = NULL;
ThreadId->Reserved = 0;
return NO_ERROR;
}
/* return */
return GetLastError();
}
INT
WINAPI
WahQueueUserApc(IN HANDLE ApcHelperHandle,
IN LPWSATHREADID ThreadId,
IN LPWSAUSERAPC ApcRoutine,
IN PVOID ApcContext OPTIONAL)
{
/* Validate params */
if ((ApcHelperHandle != APCH) ||
(!ThreadId) ||
(!ThreadId->ThreadHandle) ||
(!ApcRoutine))
{
/* Invalid parameters */
return ERROR_INVALID_PARAMETER;
}
/* Queue the APC */
if (QueueUserAPC(ApcRoutine, ThreadId->ThreadHandle, (ULONG_PTR)ApcContext))
{
/* Return success */
return ERROR_SUCCESS;
}
/* Fail */
return GetLastError();
}
DWORD
WINAPI
WahOpenCurrentThread(IN HANDLE ApcHelperHandle,
OUT LPWSATHREADID ThreadId)
{
HANDLE ProcessHandle, ThreadHandle;
/* Validate params */
if ((ApcHelperHandle != APCH) || (!ThreadId))
{
/* Invalid parameters */
return ERROR_INVALID_PARAMETER;
}
/* Get the process/thread handles */
ProcessHandle = GetCurrentProcess();
ThreadHandle = GetCurrentThread();
/* Duplicate the handle */
if (DuplicateHandle(ProcessHandle,
ThreadHandle,
ProcessHandle,
&ThreadId->ThreadHandle,
0,
FALSE,
DUPLICATE_SAME_ACCESS))
{
/* Save the thread handle and return */
ThreadId->Reserved = (DWORD_PTR)ThreadHandle;
return ERROR_SUCCESS;
}
/* Fail */
return GetLastError();
}
/* EOF */

View file

@ -0,0 +1,601 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: include/ws2_32.h
* PURPOSE: WinSock 2 DLL header
*/
/* INCLUDES ******************************************************************/
#include "precomp.h"
/* DATA **********************************************************************/
CRITICAL_SECTION WshHandleTableLock;
HANDLE ghWriterEvent;
DWORD gdwSpinCount = 0;
DWORD gHandleToIndexMask;
CONST DWORD SockPrimes[] =
{
31, 61, 127, 257, 521, 1031, 2053,
4099, 8191, 16381, 32749, 65537, 131071, 261983,
-1
};
typedef volatile LONG VLONG;
typedef VLONG *PVLONG;
/* DEFINES *******************************************************************/
/* Yes, we "abuse" the lower bits */
#define WSH_SEARCH_TABLE_FROM_HANDLE(h, t) \
(&t->SearchTables[(((ULONG_PTR)h >> 2) & t->Mask)])
#define WSH_HASH_FROM_HANDLE(h, hs) \
(hs->Handles[((ULONG_PTR)h % hs->Size)])
#define AcquireWriteLock(t) \
EnterCriticalSection(&t->Lock);
#define ReleaseWriteLock(t) \
LeaveCriticalSection(&t->Lock);
/* FUNCTIONS *****************************************************************/
VOID
static __inline
AcquireReadLock(IN PWAH_SEARCH_TABLE Table,
IN PVLONG *Count)
{
LONG OldCount;
/* Start acquire loop */
do
{
/* Write and save count value */
*Count = Table->CurrentCount;
OldCount = **Count;
/* Check if it's valid and try to increment it */
if ((OldCount > 0) && (InterlockedCompareExchange(*Count,
OldCount + 1,
OldCount) == OldCount))
{
/* Everything went OK */
break;
}
} while (TRUE);
}
VOID
static __inline
ReleaseReadLock(IN PWAH_SEARCH_TABLE Table,
IN PVLONG Count)
{
/* Decrement the count. If we went below 0, someone is waiting... */
if (InterlockedDecrement(Count) < 0)
{
/* We use pulse since this is a shared event */
PulseEvent(ghWriterEvent);
}
}
VOID
WINAPI
DoWaitForReaders(IN PWAH_SEARCH_TABLE Table,
IN PVLONG Counter)
{
HANDLE EventHandle;
/* Do a context switch */
SwitchToThread();
/* Check if the counter is above one */
if (*Counter > 0)
{
/*
* This shouldn't happen unless priorities are messed up. Do a wait so
* that the threads with lower priority will get their chance now.
*/
if (!ghWriterEvent)
{
/* We don't even have an event! Allocate one manually... */
EventHandle = CreateEvent(NULL, TRUE, FALSE, NULL);
if (EventHandle)
{
/* Save the event handle atomically */
if ((InterlockedCompareExchangePointer((PVOID*)&ghWriterEvent,
EventHandle,
NULL)))
{
/* Someone beat us to it, close ours */
CloseHandle(EventHandle);
}
}
else
{
/* Things couldn't get worse for us. Do a last-resort hack */
while (*Counter > 0) Sleep(10);
}
}
/*
* Our event is ready. Tell the others to signal us by making sure
* that the last counter will be -1, notifying the last thread of our
* request.
*/
if (InterlockedDecrement(Counter) >= 0)
{
/* Keep looping */
do
{
/* Wait in tiny bursts, so we can catch the PulseEvent */
WaitForSingleObject(ghWriterEvent, 10);
} while (*Counter >= 0);
}
}
}
VOID
static __inline
TryWaitForReaders(IN PWAH_SEARCH_TABLE Table)
{
PVLONG OldCount = Table->CurrentCount;
LONG SpinCount;
/* See which counter is being used */
if (OldCount == &Table->Count1)
{
/* Use counter 2 now */
Table->Count2 = 1;
Table->CurrentCount = &Table->Count2;
}
else
{
/* Use counter 1 now */
Table->Count1 = 1;
Table->CurrentCount = &Table->Count1;
}
/* Decrease the old count to block new readers */
if (InterlockedDecrement(OldCount) > 0)
{
/* On an MP machine, spin a bit first */
if (Table->SpinCount)
{
/* Get the spincount and loop it */
SpinCount = Table->SpinCount;
while (*OldCount > 0)
{
/* Check if the spin failed */
if (--SpinCount <= 0) break;
}
}
/* Check one last time if someone is still active */
if (*OldCount > 0)
{
/* Yep, we'll have to do a blocking (slow) wait */
DoWaitForReaders(Table, OldCount);
}
}
}
DWORD
WINAPI
WahCreateHandleContextTable(OUT PWAH_HANDLE_TABLE *Table)
{
DWORD ErrorCode;
PWAH_HANDLE_TABLE LocalTable;
DWORD i;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Assume NULL */
*Table = NULL;
/* Allocate enough tables */
LocalTable = HeapAlloc(GlobalHeap,
0,
FIELD_OFFSET(WSH_HANDLE_TABLE,
SearchTables[gHandleToIndexMask + 1]));
/* Make sure it was allocated */
if (!LocalTable) return WSA_NOT_ENOUGH_MEMORY;
/* Set the mask for the table */
LocalTable->Mask = gHandleToIndexMask;
/* Now initialize every table */
for (i = 0; i <= gHandleToIndexMask; i++)
{
/* No hash table yet */
LocalTable->SearchTables[i].HashTable = NULL;
/* Set the current count */
LocalTable->SearchTables[i].CurrentCount = &LocalTable->SearchTables[i].Count1;
/* Initialize the counts */
LocalTable->SearchTables[i].Count1 = 1;
LocalTable->SearchTables[i].Count2 = 0;
/* Set expanding state and spin count */
LocalTable->SearchTables[i].Expanding = FALSE;
LocalTable->SearchTables[i].SpinCount = gdwSpinCount;
/* Initialize the lock */
(VOID)InitializeCriticalSectionAndSpinCount(&LocalTable->
SearchTables[i].Lock,
gdwSpinCount);
}
/* Return pointer */
*Table = LocalTable;
/* Return success */
return ERROR_SUCCESS;
}
DWORD
WINAPI
WahDestroyHandleContextTable(IN PWAH_HANDLE_TABLE Table)
{
DWORD i;
/* Make sure the table is valid */
if (!Table)
{
/* No valid table */
return ERROR_INVALID_PARAMETER;
}
/* Loop each search table */
for (i = 0; i <= Table->Mask; i++)
{
/* Check if there's a table here */
if (Table->SearchTables[i].HashTable)
{
/* Free it */
HeapFree(GlobalHeap, 0, Table->SearchTables[i].HashTable);
}
/* Delete the lock */
DeleteCriticalSection(&Table->SearchTables[i].Lock);
}
/* Delete the table */
HeapFree(GlobalHeap, 0, Table);
/* Return success */
return ERROR_SUCCESS;
}
BOOL
WINAPI
WahEnumerateHandleContexts(IN PWAH_HANDLE_TABLE Table,
IN PWAH_HANDLE_ENUMERATE_PROC Callback,
IN PVOID Context)
{
DWORD i, j;
PWAH_SEARCH_TABLE SearchTable;
PWAH_HASH_TABLE HashTable;
PWAH_HANDLE Handle;
BOOL GoOn = TRUE;
/* Loop the table */
for (i = 0; i <= Table->Mask; i++)
{
/* Get the Search table */
SearchTable = &Table->SearchTables[i];
/* Lock it */
AcquireWriteLock(SearchTable);
/* Mark us as expanding and wait for everyone */
SearchTable->Expanding = TRUE;
TryWaitForReaders(SearchTable);
/* Get the hash table */
HashTable = SearchTable->HashTable;
/* Make sure it exists */
if (HashTable)
{
/* Loop every handle in it */
for (j = 0; j < HashTable->Size; j++)
{
/* Get this handle */
Handle = HashTable->Handles[j];
if (!Handle) continue;
/* Call the callback proc */
GoOn = Callback(Context, Handle);
if (!GoOn) break;
}
}
/* Disable the expansion bit and release the lock */
SearchTable->Expanding = FALSE;
ReleaseWriteLock(SearchTable);
/* Check again if we should leave */
if (!GoOn) break;
}
/* return */
return GoOn;
}
PWAH_HANDLE
WINAPI
WahInsertHandleContext(IN PWAH_HANDLE_TABLE Table,
IN PWAH_HANDLE Handle)
{
PWAH_HANDLE *HashHandle, OldHandle;
PVLONG Count;
PWAH_HASH_TABLE HashTable, NewHashTable;
DWORD HandleCount, i;
PWAH_SEARCH_TABLE SearchTable;
/* Get the current Search Table */
SearchTable = WSH_SEARCH_TABLE_FROM_HANDLE(Handle->Handle, Table);
/* Start loop */
do
{
/* Get reader lock */
AcquireReadLock(SearchTable, &Count);
/* Get the hash table */
HashTable = SearchTable->HashTable;
/* Make sure we are not expanding, and that the table is there */
if (!(SearchTable->Expanding) && (HashTable))
{
/* Get the hash handle */
HashHandle = &WSH_HASH_FROM_HANDLE(Handle->Handle, HashTable);
/* Do the insert */
if (InterlockedCompareExchangePointer((PVOID*)HashHandle,
Handle,
NULL) == NULL)
{
/* Success, release the reader lock */
ReleaseReadLock(SearchTable, Count);
/* Save old handle */
OldHandle = Handle;
break;
}
}
/* Release the read lock since we're done with it now */
ReleaseReadLock(SearchTable, Count);
/* We need the writer lock to expand/create the table */
AcquireWriteLock(SearchTable);
/* Mark the table in use */
SearchTable->Expanding = TRUE;
/* Wait for all the readers to finish */
TryWaitForReaders(SearchTable);
/* Start loop */
do
{
/* Get the hash table again */
HashTable = SearchTable->HashTable;
/* Check if exists now */
if (HashTable)
{
/* It does! Do what we wanted to do earlier. Get the hash... */
HashHandle = &WSH_HASH_FROM_HANDLE(Handle->Handle, HashTable);
/* Check if it doesn't exist */
if (!(*HashHandle))
{
/* Write it (no need for interlock, we have the RW lock) */
OldHandle = Handle;
*HashHandle = Handle;
break;
}
else if ((*HashHandle)->Handle == Handle->Handle)
{
/* Handle matches, write it (see comment above) */
OldHandle = *HashHandle;
*HashHandle = Handle;
break;
}
/* No go, we need to expand the table. Remember the size now */
HandleCount = HashTable->Size;
}
else
{
/* Table is empty, we have to create it */
HandleCount = 0;
}
ExpandTable:
/* Find a free prime */
for (i = 0; HandleCount >= SockPrimes[i]; i++);
/* Check if we found one */
if (SockPrimes[i] != 0xFFFFFFFF)
{
/* Use the prime */
HandleCount = SockPrimes[i];
}
else
{
/* No primes left. Table is quite large, so simply double it */
HandleCount *= 2;
}
/* Allocate the table */
NewHashTable = HeapAlloc(GlobalHeap,
0,
FIELD_OFFSET(WSH_HASH_TABLE,
Handles[HandleCount]));
/* Hopefully we have one now */
if (NewHashTable)
{
/* Set its size */
NewHashTable->Size = HandleCount;
/* Initialize it */
RtlZeroMemory(NewHashTable->Handles, HandleCount * sizeof(PVOID));
/* Insert us first */
WSH_HASH_FROM_HANDLE(Handle->Handle, NewHashTable) = Handle;
/* Now check if our old table had entries in it */
if (HashTable)
{
/* We need to move them */
for (i = 0; i < HashTable->Size; i++)
{
/* Make sure the hash handle exists */
if (HashTable->Handles[i])
{
/* Get it */
HashHandle = &WSH_HASH_FROM_HANDLE(HashTable->
Handles[i]->Handle,
NewHashTable);
/* Check if it has a value */
if (!(*HashHandle))
{
/* It's empty, so just write the handle */
*HashHandle = HashTable->Handles[i];
}
else
{
/* Not empty :/... that implies a collision */
HeapFree(GlobalHeap, 0, NewHashTable);
goto ExpandTable;
}
}
}
/* Write the new hash table */
SearchTable->HashTable = NewHashTable;
/* Wait for everyone to be done with it, then free it */
TryWaitForReaders(SearchTable);
HeapFree(GlobalHeap, 0, HashTable);
}
else
{
/* It was empty, nothing to worry about */
SearchTable->HashTable = NewHashTable;
}
/* Save the old handle */
OldHandle = Handle;
}
else
{
/* There was no old handle */
OldHandle = Handle;
}
} while (0);
/* Mark us as free, and release the write lock */
SearchTable->Expanding = FALSE;
ReleaseWriteLock(SearchTable);
break;
} while (1);
/* Return the old handle */
return OldHandle;
}
PWAH_HANDLE
WINAPI
WahReferenceContextByHandle(IN PWAH_HANDLE_TABLE Table,
IN HANDLE Handle)
{
PWAH_HANDLE HashHandle;
PWAH_SEARCH_TABLE SearchTable;
PWAH_HASH_TABLE HashTable;
PVLONG Count;
/* Get the current Search Table */
SearchTable = WSH_SEARCH_TABLE_FROM_HANDLE(Handle, Table);
/* Lock it */
AcquireReadLock(SearchTable, &Count);
/* Get the hash table and handle */
HashTable = SearchTable->HashTable;
/* Check if it's valid, and if it's the one we want */
if ((HashTable) &&
(HashHandle = WSH_HASH_FROM_HANDLE(Handle, HashTable)) &&
(HashHandle->Handle == Handle))
{
/* Reference the handle */
InterlockedIncrement(&HashHandle->RefCount);
}
else
{
/* Invalid handle */
HashHandle = NULL;
}
/* Release the lock */
ReleaseReadLock(SearchTable, Count);
/* Return */
return HashHandle;
}
DWORD
WINAPI
WahRemoveHandleContext(IN PWAH_HANDLE_TABLE Table,
IN PWAH_HANDLE Handle)
{
PWAH_HANDLE *HashHandle;
PWAH_SEARCH_TABLE SearchTable;
PWAH_HASH_TABLE HashTable;
DWORD ErrorCode = ERROR_SUCCESS;
/* Get the current Search Table */
SearchTable = WSH_SEARCH_TABLE_FROM_HANDLE(Handle->Handle, Table);
/* Lock it */
AcquireWriteLock(SearchTable);
/* Get the hash table and handle */
HashTable = SearchTable->HashTable;
HashHandle = &WSH_HASH_FROM_HANDLE(Handle->Handle, HashTable);
/* Make sure we have a handle, and write the new pointer */
if (HashHandle && (InterlockedCompareExchangePointer((PVOID*)HashHandle,
NULL,
Handle) == Handle))
{
/* Wait for everyone to be done with it */
TryWaitForReaders(SearchTable);
}
else
{
/* Invalid handle */
ErrorCode = ERROR_INVALID_PARAMETER;
}
/* Release the lock */
ReleaseWriteLock(SearchTable);
/* Return */
return ErrorCode;
}
/* EOF */

View file

@ -0,0 +1,170 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: include/ws2_32.h
* PURPOSE: WinSock 2 DLL header
*/
/* INCLUDES ******************************************************************/
#include "precomp.h"
/* DATA **********************************************************************/
HANDLE GlobalHeap;
BOOL Ws2helpInitialized = FALSE;
CRITICAL_SECTION StartupSyncronization;
HINSTANCE LibraryHdl;
/* FUNCTIONS *****************************************************************/
VOID
WINAPI
NewCtxInit(VOID)
{
NT_PRODUCT_TYPE ProductType = NtProductWinNt;
SYSTEM_INFO SystemInfo;
DWORD NumHandleBuckets;
HKEY KeyHandle;
DWORD RegSize = sizeof(DWORD);
DWORD RegType;
DWORD Mask;
/* Try to figure out if this is a workstation or server install */
RtlGetNtProductType(&ProductType);
/* Get the system info */
GetSystemInfo(&SystemInfo);
/* If this is an MP machine, set the default spinlock */
if (SystemInfo.dwNumberOfProcessors > 1) gdwSpinCount = 2000;
/* Figure how many "Handle Buckets" we'll use. Start with the default */
NumHandleBuckets = ProductType == NtProductWinNt ? 8 : 32;
/* Open the registry settings */
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Services\\Winsock2\\Parameters",
0,
KEY_QUERY_VALUE,
&KeyHandle) == ERROR_SUCCESS)
{
/* Query the key */
RegQueryValueEx(KeyHandle,
"Ws2_32NumHandleBuckets",
0,
&RegType,
(LPBYTE)&NumHandleBuckets,
&RegSize);
/* Are we on MP? */
if (SystemInfo.dwNumberOfProcessors > 1)
{
/* Also check for a custom spinlock setting */
RegQueryValueEx(KeyHandle,
"Ws2_32SpinCount",
0,
&RegType,
(LPBYTE)&gdwSpinCount,
&RegSize);
}
/* Close the key, we're done */
RegCloseKey(KeyHandle);
}
/* Now get the bucket count and normalize it to be log2 and within 256 */
for (Mask = 256; !(Mask & NumHandleBuckets); Mask >>= 1);
NumHandleBuckets = Mask;
/* Normalize it again, to be within OS parameters */
if (ProductType == NtProductWinNt)
{
/* Is it within norms for non-server editions? */
if (NumHandleBuckets > 32) NumHandleBuckets = 32;
else if (NumHandleBuckets < 8) NumHandleBuckets = 8;
}
else
{
/* Is it within norms for server editions? */
if (NumHandleBuckets > 256) NumHandleBuckets = 256;
else if (NumHandleBuckets < 32) NumHandleBuckets = 32;
}
/* Normalize the spincount */
if (gdwSpinCount > 8000) gdwSpinCount = 8000;
/* Set the final mask */
gHandleToIndexMask = NumHandleBuckets -1;
}
DWORD
WINAPI
Ws2helpInitialize(VOID)
{
/* Enter the startup CS */
EnterCriticalSection(&StartupSyncronization);
/* Check again for init */
if (!Ws2helpInitialized)
{
/* Initialize us */
NewCtxInit();
Ws2helpInitialized = TRUE;
}
/* Leave the CS and return */
LeaveCriticalSection(&StartupSyncronization);
return ERROR_SUCCESS;
}
BOOL
APIENTRY
DllMain(HANDLE hModule,
DWORD dwReason,
LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
/* Save our handle */
LibraryHdl = hModule;
/* Improve Performance */
DisableThreadLibraryCalls(hModule);
/* Initialize startup CS */
InitializeCriticalSection(&StartupSyncronization);
/* Get Global Heap */
GlobalHeap = GetProcessHeap();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
/* Make sure we loaded */
if (!LibraryHdl) break;
/* Check if we are cleaning up */
if (lpReserved)
{
/* Free the security descriptor */
if (pSDPipe) HeapFree(GlobalHeap, 0, pSDPipe);
/* Close the event */
if (ghWriterEvent) CloseHandle(ghWriterEvent);
/* Delete the startup CS */
DeleteCriticalSection(&StartupSyncronization);
Ws2helpInitialized = FALSE;
}
break;
}
return TRUE;
}

View file

@ -0,0 +1,447 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: include/ws2_32.h
* PURPOSE: WinSock 2 DLL header
*/
/* INCLUDES ******************************************************************/
#include "precomp.h"
/* DATA **********************************************************************/
typedef struct _WSH_HELPER_CONTEXT
{
HANDLE FileHandle;
HANDLE ThreadHandle;
HANDLE DllHandle;
} WSH_HELPER_CONTEXT, *PWAH_HELPER_CONTEXT;
LPFN_WSASEND pWSASend;
LPFN_WSARECV pWSARecv;
LPFN_WSASENDTO pWSASendTo;
LPFN_WSARECVFROM pWSARecvFrom;
LPFN_WSAGETLASTERROR pWSAGetLastError;
LPFN_WSACANCELBLOCKINGCALL pWSACancelBlockingCall;
LPFN_WSASETBLOCKINGHOOK pWSASetBlockingHook;
LPFN_SELECT pSelect;
LPFN_WSASTARTUP pWSAStartup;
LPFN_WSACLEANUP pWSACleanup;
LPFN_GETSOCKOPT pGetSockOpt;
LPFN_WSAIOCTL pWSAIoctl;
#define APCH (HANDLE)'SOR '
/* FUNCTIONS *****************************************************************/
VOID
CALLBACK
ApcThread(ULONG_PTR Context)
{
}
NTSTATUS
WINAPI
DoSocketCancel(PVOID Context1,
PVOID Context2,
PVOID Context3)
{
return STATUS_SUCCESS;
}
NTSTATUS
WINAPI
DoSocketRequest(PVOID Context1,
PVOID Context2,
PVOID Context3)
{
return STATUS_SUCCESS;
}
VOID
CALLBACK
ExitThreadApc(ULONG_PTR Context)
{
PWAH_HELPER_CONTEXT HelperContext = (PWAH_HELPER_CONTEXT)Context;
/* Close the file handle */
CloseHandle(HelperContext->FileHandle);
/* Free the context */
HeapFree(GlobalHeap, 0, HelperContext);
/* Exit the thread and library */
FreeLibraryAndExitThread(HelperContext->DllHandle, ERROR_SUCCESS);
}
DWORD
WINAPI
WahCloseHandleHelper(IN HANDLE HelperHandle)
{
DWORD ErrorCode;
PWAH_HELPER_CONTEXT Context = HelperHandle;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate the handle */
if (!Context) return ERROR_INVALID_PARAMETER;
/* Queue an APC to exit the thread */
if (QueueUserAPC(ExitThreadApc, Context->ThreadHandle, (ULONG_PTR)Context))
{
/* Done */
return ERROR_SUCCESS;
}
else
{
/* We failed somewhere */
return ERROR_GEN_FAILURE;
}
}
DWORD
WINAPI
WahCloseSocketHandle(IN HANDLE HelperHandle,
IN SOCKET Socket)
{
DWORD ErrorCode;
PWAH_HELPER_CONTEXT Context = HelperHandle;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate the handle */
if (!(Context) || (Socket == INVALID_SOCKET) || !(Socket))
{
/* Invalid handle and/or socket */
return ERROR_INVALID_PARAMETER;
}
/* Just close the handle and return */
CloseHandle((HANDLE)Socket);
return ERROR_SUCCESS;
}
DWORD
WINAPI
WahCreateSocketHandle(IN HANDLE HelperHandle,
OUT SOCKET *Socket)
{
DWORD ErrorCode;
INT OpenType;
DWORD Size = sizeof(OpenType);
DWORD CreateOptions = 0;
UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
PFILE_FULL_EA_INFORMATION Ea;
PWAH_EA_DATA EaData;
CHAR EaBuffer[sizeof(*Ea) + sizeof(*EaData)];
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
PWAH_HELPER_CONTEXT Context = (PWAH_HELPER_CONTEXT)HelperHandle;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate the handle and pointer */
if (!(Context) || !(Socket))
{
/* Invalid handle and/or socket */
return ERROR_INVALID_PARAMETER;
}
/* Set pointer to EA */
Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
/* Get the open type to determine the create options */
if ((pGetSockOpt(INVALID_SOCKET,
SOL_SOCKET,
SO_OPENTYPE,
(PCHAR)&OpenType,
(INT FAR*)&Size) == ERROR_SUCCESS) && (OpenType))
{
/* This is a sync open */
CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT;
}
/* Initialize the attributes for the driver */
RtlInitUnicodeString(&Name, L"\\Device\\WS2IFSL\\NifsSct");
InitializeObjectAttributes(&ObjectAttributes,
&Name,
0,
NULL,
NULL);
/* Set up the EA */
Ea->NextEntryOffset = 0;
Ea->Flags = 0;
Ea->EaNameLength = sizeof("NifsSct");
Ea->EaValueLength = sizeof(*EaData);
RtlCopyMemory(Ea->EaName, "NifsSct", Ea->EaNameLength);
/* Get our EA data */
EaData = (PWAH_EA_DATA)(Ea + 1);
/* Write the EA Data */
EaData->FileHandle = Context->FileHandle;
EaData->Context = NULL;
/* Call the driver */
Status = NtCreateFile((PHANDLE)Socket,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN_IF,
CreateOptions,
Ea,
sizeof(*Ea) + sizeof(*EaData));
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Write the socket handle */
EaData->Context =(HANDLE)*Socket;
/* Tell the driver about it */
if (DeviceIoControl((HANDLE)*Socket,
IOCTL_WS2IFSL_SET_HANDLE,
&EaData,
sizeof(WSH_EA_DATA),
NULL,
0,
&Size,
NULL))
{
/* Set success */
ErrorCode = NO_ERROR;
}
else
{
/* We failed. Get the error and close the socket */
ErrorCode = GetLastError();
CloseHandle((HANDLE)*Socket);
*Socket = 0;
}
}
else
{
/* Create file failed, conver error code */
ErrorCode = RtlNtStatusToDosError(Status);
}
/* Return to caller */
return ErrorCode;
}
INT
WINAPI
WahDisableNonIFSHandleSupport(VOID)
{
DWORD ErrorCode;
SC_HANDLE ServiceMgrHandle, Ws2IfsHandle;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Open the service DB */
ServiceMgrHandle = OpenSCManager(NULL,
SERVICES_ACTIVE_DATABASE,
SC_MANAGER_CREATE_SERVICE);
if (!ServiceMgrHandle) return GetLastError();
/* Open the service */
Ws2IfsHandle = OpenService(ServiceMgrHandle, "WS2IFSL", SERVICE_ALL_ACCESS);
/* Disable the servce */
ChangeServiceConfig(Ws2IfsHandle,
SERVICE_NO_CHANGE,
SERVICE_DISABLED,
SERVICE_NO_CHANGE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
/* Close the handles and return */
CloseServiceHandle(ServiceMgrHandle);
CloseServiceHandle(Ws2IfsHandle);
return ERROR_SUCCESS;
}
INT
WINAPI
WahEnableNonIFSHandleSupport(VOID)
{
return 0;
}
DWORD
WINAPI
WahOpenHandleHelper(OUT PHANDLE HelperHandle)
{
DWORD ErrorCode;
HINSTANCE hWs2_32;
UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
PFILE_FULL_EA_INFORMATION Ea;
PWAH_EA_DATA2 EaData;
CHAR EaBuffer[sizeof(*Ea) + sizeof(*EaData)];
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
DWORD Tid;
PWAH_HELPER_CONTEXT Context;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate the pointer */
if (!HelperHandle)
{
/* Invalid handle and/or socket */
return ERROR_INVALID_PARAMETER;
}
/* Get ws2_32.dll's handle. We don't load it: it MUST be here */
hWs2_32 = GetModuleHandle ("WS2_32.DLL");
if (!hWs2_32) return WSASYSCALLFAILURE;
/* Dynamically load all its APIs */
if (!((pGetSockOpt = (LPFN_GETSOCKOPT)GetProcAddress(hWs2_32, "getsockopt"))) ||
!((pSelect = (LPFN_SELECT)GetProcAddress(hWs2_32, "select"))) ||
!((pWSACancelBlockingCall = (LPFN_WSACANCELBLOCKINGCALL)GetProcAddress(hWs2_32, "WSACancelBlockingCall"))) ||
!((pWSACleanup = (LPFN_WSACLEANUP)GetProcAddress(hWs2_32, "WSACleanup"))) ||
!((pWSAGetLastError = (LPFN_WSAGETLASTERROR)GetProcAddress(hWs2_32, "WSAGetLastError"))) ||
!((pWSASetBlockingHook = (LPFN_WSASETBLOCKINGHOOK)GetProcAddress(hWs2_32, "WSASetBlockingHook"))) ||
!((pWSARecv = (LPFN_WSARECV)GetProcAddress(hWs2_32, "WSARecv"))) ||
!((pWSASend = (LPFN_WSASEND)GetProcAddress(hWs2_32, "WSASend"))) ||
!((pWSASendTo = (LPFN_WSASENDTO)GetProcAddress(hWs2_32, "WSASendTo"))) ||
!((pWSAStartup = (LPFN_WSASTARTUP)GetProcAddress(hWs2_32, "WSAStartup"))) ||
!((pWSARecvFrom = (LPFN_WSARECVFROM)GetProcAddress(hWs2_32, "WSARecvFrom"))) ||
!((pWSAIoctl = (LPFN_WSAIOCTL)GetProcAddress(hWs2_32, "WSAIoctl"))))
{
/* Uh, guess we failed somewhere */
return WSASYSCALLFAILURE;
}
/* Set pointer EA structure */
Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
/* Create the helper context */
Context = HeapAlloc(GlobalHeap, 0, sizeof(WSH_HELPER_CONTEXT));
if (Context)
{
/* Create the special request thread */
Context->ThreadHandle = CreateThread(NULL,
0,
(PVOID)ApcThread,
Context,
CREATE_SUSPENDED,
&Tid);
if (Context->ThreadHandle)
{
/* Create the attributes for the driver open */
RtlInitUnicodeString(&Name, L"\\Device\\WS2IFSL\\NifsPvd");
InitializeObjectAttributes(&ObjectAttributes,
&Name,
0,
NULL,
NULL);
/* Setup the EA */
Ea->NextEntryOffset = 0;
Ea->Flags = 0;
Ea->EaNameLength = sizeof("NifsPvd");
Ea->EaValueLength = sizeof(*EaData);
RtlCopyMemory(Ea->EaName, "NifsPvd", Ea->EaNameLength);
/* Get our EA data */
EaData = (PWAH_EA_DATA2)(Ea + 1);
/* Fill out the EA Data */
EaData->ThreadHandle = Context->ThreadHandle;
EaData->RequestRoutine = DoSocketRequest;
EaData->CancelRoutine = DoSocketCancel;
EaData->ApcContext = Context;
EaData->Reserved = 0;
/* Call the driver */
Status = NtCreateFile(&Context->FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN_IF,
0,
Ea,
sizeof(*Ea) + sizeof(*EaData));
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Resume the thread and return a handle to the context */
ResumeThread(Context->ThreadHandle);
*HelperHandle = (HANDLE)Context;
return ERROR_SUCCESS;
}
else
{
/* Get the error code */
ErrorCode = RtlNtStatusToDosError(Status);
}
/* We failed, mark us as such */
Context->FileHandle = NULL;
ResumeThread(Context->ThreadHandle);
}
else
{
/* Get the error code */
ErrorCode = GetLastError();
}
/* If we got here, we failed, so free the context */
HeapFree(GlobalHeap, 0, Context);
}
else
{
/* Get the errror code */
ErrorCode = GetLastError();
}
/* Return to caller */
return ErrorCode;
}
DWORD
WINAPI
WahCompleteRequest(IN HANDLE HelperHandle,
IN SOCKET Socket,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD ErrorCode,
IN DWORD BytesTransferred)
{
UNREFERENCED_PARAMETER(HelperHandle);
UNREFERENCED_PARAMETER(Socket);
UNREFERENCED_PARAMETER(lpOverlapped);
UNREFERENCED_PARAMETER(ErrorCode);
UNREFERENCED_PARAMETER(BytesTransferred);
return ERROR_SUCCESS;
}
/* EOF */

View file

@ -0,0 +1,87 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: include/ws2_32.h
* PURPOSE: WinSock 2 DLL header
*/
/* INCLUDES ******************************************************************/
#include "precomp.h"
/* DATA **********************************************************************/
#define HANH (HANDLE)'2SOR'
PSECURITY_DESCRIPTOR pSDPipe = NULL;
/* FUNCTIONS *****************************************************************/
DWORD
WINAPI
WahCloseNotificationHandleHelper(IN HANDLE HelperHandle)
{
DWORD ErrorCode;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate handle */
if (HelperHandle != HANH) return ERROR_INVALID_PARAMETER;
/* return */
return ERROR_SUCCESS;
}
DWORD
WINAPI
WahCreateNotificationHandle(IN HANDLE HelperHandle,
OUT PHANDLE NotificationHelperHandle)
{
UNREFERENCED_PARAMETER(HelperHandle);
UNREFERENCED_PARAMETER(NotificationHelperHandle);
return 0;
}
DWORD
WINAPI
WahOpenNotificationHandleHelper(OUT PHANDLE HelperHandle)
{
DWORD ErrorCode;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate handle */
if (!HelperHandle) return ERROR_INVALID_PARAMETER;
/* Return a bogus handle ("ROS2") */
*HelperHandle = HANH;
return ERROR_SUCCESS;
}
INT
WINAPI
WahNotifyAllProcesses(IN HANDLE NotificationHelperHandle)
{
UNREFERENCED_PARAMETER(NotificationHelperHandle);
return 0;
}
INT
WINAPI
WahWaitForNotification(IN HANDLE NotificationHelperHandle,
IN HANDLE lpNotificationHandle,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
UNREFERENCED_PARAMETER(NotificationHelperHandle);
UNREFERENCED_PARAMETER(lpNotificationHandle);
UNREFERENCED_PARAMETER(lpOverlapped);
UNREFERENCED_PARAMETER(lpCompletionRoutine);
return 0;
}
/* EOF */

View file

@ -0,0 +1,47 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 Helper DLL
* FILE: lib/ws2help/precomp.h
* PURPOSE: WinSock 2 Helper DLL
*/
#ifndef __PRECOMP_H
#define __PRECOMP_H
/* Winsock Provider Headers */
#define WIN32_NO_STATUS
#define _WIN32_WINNT 0x502
#define NTOS_MODE_USER
#define INCL_WINSOCK_API_TYPEDEFS 1
#include <ws2spi.h>
/* NDK Headers */
#include <rtlfuncs.h>
#include <iofuncs.h>
/* Shared Winsock Helper headers */
#include <ws2help.h>
#include <wshdrv.h>
/* Missing definition */
#define SO_OPENTYPE 0x20
/* Global data */
extern HANDLE GlobalHeap;
extern PSECURITY_DESCRIPTOR pSDPipe;
extern HANDLE ghWriterEvent;
extern BOOL Ws2helpInitialized;
extern DWORD gdwSpinCount;
extern DWORD gHandleToIndexMask;
/* Functions */
DWORD
WINAPI
Ws2helpInitialize(VOID);
/* Initialization macro */
#define WS2HELP_PROLOG() \
(Ws2helpInitialized? ERROR_SUCCESS : Ws2helpInitialize())
#endif /* __WS2HELP_H */
/* EOF */

View file

@ -0,0 +1,163 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 Helper DLL
* FILE: include/libs/winsock/ws2help.h
* PURPOSE: WinSock 2 Helper DLL header
*/
#ifndef __WS2HELP_H
#define __WS2HELP_H
/* Types */
typedef struct _WSH_HANDLE
{
LONG RefCount;
HANDLE Handle;
} WSH_HANDLE, *PWAH_HANDLE;
typedef struct _WSH_HASH_TABLE
{
DWORD Size;
PWAH_HANDLE Handles[1];
} WSH_HASH_TABLE, *PWAH_HASH_TABLE;
typedef struct _WSH_SEARCH_TABLE
{
volatile PWAH_HASH_TABLE HashTable;
volatile PLONG CurrentCount;
LONG Count1;
LONG Count2;
LONG SpinCount;
BOOL Expanding;
CRITICAL_SECTION Lock;
} WSH_SEARCH_TABLE, *PWAH_SEARCH_TABLE;
typedef struct _WSH_HANDLE_TABLE
{
DWORD Mask;
WSH_SEARCH_TABLE SearchTables[1];
} WSH_HANDLE_TABLE, *PWAH_HANDLE_TABLE;
//typedef struct _WSH_HANDLE_TABLE *PWAH_HANDLE_TABLE;
typedef BOOL
(WINAPI *PWAH_HANDLE_ENUMERATE_PROC)(
IN PVOID Context,
IN PWAH_HANDLE Handle
);
PWAH_HANDLE
WINAPI
WahReferenceContextByHandle(
IN PWAH_HANDLE_TABLE Table,
IN HANDLE Handle
);
DWORD
WINAPI
WahRemoveHandleContext(
IN PWAH_HANDLE_TABLE Table,
IN PWAH_HANDLE Handle
);
DWORD
WINAPI
WahCloseSocketHandle(
IN HANDLE HelperHandle,
IN SOCKET Socket
);
DWORD
WINAPI
WahOpenCurrentThread(
IN HANDLE HelperHandle,
OUT LPWSATHREADID ThreadId
);
DWORD
WINAPI
WahCloseApcHelper(
IN HANDLE HelperHandle
);
DWORD
WINAPI
WahCloseThread(
IN HANDLE HelperHandle,
IN LPWSATHREADID ThreadId
);
DWORD
WINAPI
WahCloseHandleHelper(
IN HANDLE HelperHandle
);
DWORD
WINAPI
WahCloseNotificationHandleHelper(
IN HANDLE HelperHandle
);
DWORD
WINAPI
WahOpenNotificationHandleHelper(
OUT PHANDLE HelperHandle
);
DWORD
WINAPI
WahCreateNotificationHandle(
IN HANDLE HelperHandle,
OUT PHANDLE NotificationHelperHandle
);
INT
WINAPI
WahWaitForNotification(
IN HANDLE NotificationHelperHandle,
IN HANDLE lpNotificationHandle,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
INT
WINAPI
WahNotifyAllProcesses(
IN HANDLE NotificationHelperHandle
);
BOOL
WINAPI
WahEnumerateHandleContexts(
IN PWAH_HANDLE_TABLE Table,
IN PWAH_HANDLE_ENUMERATE_PROC Callback,
IN PVOID Context
);
DWORD
WINAPI
WahCreateHandleContextTable(
OUT PWAH_HANDLE_TABLE *Table
);
DWORD
WINAPI
WahDestroyHandleContextTable(
IN PWAH_HANDLE_TABLE Table
);
PWAH_HANDLE
WINAPI
WahInsertHandleContext(
IN PWAH_HANDLE_TABLE Table,
IN PWAH_HANDLE Handle
);
DWORD
WINAPI
WahOpenApcHelper(
OUT PHANDLE ApcHelperHandle
);
#endif

View file

@ -0,0 +1,14 @@
<module name="ws2help" type="win32dll" baseaddress="${BASEADDRESS_WS2HELP}" installbase="system32" installname="ws2help.dll">
<importlibrary definition="ws2help.spec" />
<include base="ws2help">.</include>
<library>advapi32</library>
<library>ntdll</library>
<library>kernel32</library>
<library>ws2_32</library>
<file>apc.c</file>
<file>context.c</file>
<file>dllmain.c</file>
<file>handle.c</file>
<file>notify.c</file>
<file>ws2help.rc</file>
</module>

View file

@ -0,0 +1,7 @@
/* $Id: ws2help.rc 12852 2005-01-06 13:58:04Z mf $ */
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "Windows Sockets 2 Helper API\0"
#define REACTOS_STR_INTERNAL_NAME "ws2help\0"
#define REACTOS_STR_ORIGINAL_FILENAME "ws2help.dll\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,23 @@
@ stdcall WahCloseApcHelper(long)
@ stdcall WahCloseHandleHelper(long)
@ stdcall WahCloseNotificationHandleHelper(long)
@ stdcall WahCloseSocketHandle(long ptr)
@ stdcall WahCloseThread(long ptr)
@ stdcall WahCompleteRequest(long ptr ptr long long)
@ stdcall WahCreateHandleContextTable(ptr)
@ stdcall WahCreateNotificationHandle(long ptr)
@ stdcall WahCreateSocketHandle(long ptr)
@ stdcall WahDestroyHandleContextTable(ptr)
@ stdcall WahDisableNonIFSHandleSupport()
@ stdcall WahEnableNonIFSHandleSupport()
@ stdcall WahEnumerateHandleContexts(ptr ptr ptr)
@ stdcall WahInsertHandleContext(ptr ptr)
@ stdcall WahNotifyAllProcesses(long)
@ stdcall WahOpenApcHelper(ptr)
@ stdcall WahOpenCurrentThread(long ptr)
@ stdcall WahOpenHandleHelper(ptr)
@ stdcall WahOpenNotificationHandleHelper(ptr)
@ stdcall WahQueueUserApc(long ptr ptr ptr)
@ stdcall WahReferenceContextByHandle(ptr long)
@ stdcall WahRemoveHandleContext(ptr ptr)
@ stdcall WahWaitForNotification(long long ptr ptr)

View file

@ -0,0 +1,28 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: include/drivers/ws2ifsl/wshdrv.h
* PURPOSE: WinSock 2 Helper Driver header
*/
#ifndef __WSHDRV_H
#define __WSHDRV_H
typedef struct _WSH_EA_DATA
{
HANDLE FileHandle;
PVOID Context;
} WSH_EA_DATA, *PWAH_EA_DATA;
typedef struct _WAH_EA_DATA2
{
HANDLE ThreadHandle;
PVOID RequestRoutine;
PVOID CancelRoutine;
PVOID ApcContext;
ULONG Reserved;
} WAH_EA_DATA2, *PWAH_EA_DATA2;
#define IOCTL_WS2IFSL_SET_HANDLE 0x12B00
#endif