mirror of
https://github.com/reactos/reactos.git
synced 2024-10-30 19:41:57 +00:00
522 lines
17 KiB
C
522 lines
17 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Ancillary Function Driver DLL
|
|
* FILE: dll/win32/msafd/misc/helpers.c
|
|
* PURPOSE: Helper DLL management
|
|
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
* Alex Ionescu (alex@relsoft.net)
|
|
* REVISIONS:
|
|
* CSH 01/09-2000 Created
|
|
* Alex 16/07/2004 - Complete Rewrite
|
|
*/
|
|
|
|
#include <msafd.h>
|
|
|
|
#include <winreg.h>
|
|
|
|
CRITICAL_SECTION HelperDLLDatabaseLock;
|
|
LIST_ENTRY HelperDLLDatabaseListHead;
|
|
|
|
|
|
INT
|
|
SockGetTdiName(
|
|
PINT AddressFamily,
|
|
PINT SocketType,
|
|
PINT Protocol,
|
|
GROUP Group,
|
|
DWORD Flags,
|
|
PUNICODE_STRING TransportName,
|
|
PVOID *HelperDllContext,
|
|
PHELPER_DATA *HelperDllData,
|
|
PDWORD Events)
|
|
{
|
|
PHELPER_DATA HelperData;
|
|
PWSTR Transports;
|
|
PWSTR Transport;
|
|
PWINSOCK_MAPPING Mapping;
|
|
PLIST_ENTRY Helpers;
|
|
INT Status;
|
|
|
|
TRACE("AddressFamily %p, SocketType %p, Protocol %p, Group %u, Flags %lx, TransportName %p, HelperDllContext %p, HelperDllData %p, Events %p\n",
|
|
AddressFamily, SocketType, Protocol, Group, Flags, TransportName, HelperDllContext, HelperDllData, Events);
|
|
|
|
/* Check in our Current Loaded Helpers */
|
|
for (Helpers = SockHelpersListHead.Flink;
|
|
Helpers != &SockHelpersListHead;
|
|
Helpers = Helpers->Flink ) {
|
|
|
|
HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers);
|
|
|
|
/* See if this Mapping works for us */
|
|
if (SockIsTripleInMapping (HelperData->Mapping,
|
|
*AddressFamily,
|
|
*SocketType,
|
|
*Protocol)) {
|
|
|
|
/* Call the Helper Dll function get the Transport Name */
|
|
if (HelperData->WSHOpenSocket2 == NULL ) {
|
|
|
|
/* DLL Doesn't support WSHOpenSocket2, call the old one */
|
|
HelperData->WSHOpenSocket(AddressFamily,
|
|
SocketType,
|
|
Protocol,
|
|
TransportName,
|
|
HelperDllContext,
|
|
Events
|
|
);
|
|
} else {
|
|
HelperData->WSHOpenSocket2(AddressFamily,
|
|
SocketType,
|
|
Protocol,
|
|
Group,
|
|
Flags,
|
|
TransportName,
|
|
HelperDllContext,
|
|
Events
|
|
);
|
|
}
|
|
|
|
/* Return the Helper Pointers */
|
|
*HelperDllData = HelperData;
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
/* Get the Transports available */
|
|
Status = SockLoadTransportList(&Transports);
|
|
|
|
/* Check for error */
|
|
if (Status) {
|
|
WARN("Can't get transport list\n");
|
|
return Status;
|
|
}
|
|
|
|
/* Loop through each transport until we find one that can satisfy us */
|
|
for (Transport = Transports;
|
|
*Transports != 0;
|
|
Transport += wcslen(Transport) + 1) {
|
|
TRACE("Transport: %S\n", Transports);
|
|
|
|
/* See what mapping this Transport supports */
|
|
Status = SockLoadTransportMapping(Transport, &Mapping);
|
|
|
|
/* Check for error */
|
|
if (Status) {
|
|
ERR("Can't get mapping for %S\n", Transports);
|
|
HeapFree(GlobalHeap, 0, Transports);
|
|
return Status;
|
|
}
|
|
|
|
/* See if this Mapping works for us */
|
|
if (SockIsTripleInMapping(Mapping, *AddressFamily, *SocketType, *Protocol)) {
|
|
|
|
/* It does, so load the DLL associated with it */
|
|
Status = SockLoadHelperDll(Transport, Mapping, &HelperData);
|
|
|
|
/* Check for error */
|
|
if (Status) {
|
|
ERR("Can't load helper DLL for Transport %S.\n", Transport);
|
|
HeapFree(GlobalHeap, 0, Transports);
|
|
HeapFree(GlobalHeap, 0, Mapping);
|
|
return Status;
|
|
}
|
|
|
|
/* Call the Helper Dll function get the Transport Name */
|
|
if (HelperData->WSHOpenSocket2 == NULL) {
|
|
/* DLL Doesn't support WSHOpenSocket2, call the old one */
|
|
HelperData->WSHOpenSocket(AddressFamily,
|
|
SocketType,
|
|
Protocol,
|
|
TransportName,
|
|
HelperDllContext,
|
|
Events
|
|
);
|
|
} else {
|
|
HelperData->WSHOpenSocket2(AddressFamily,
|
|
SocketType,
|
|
Protocol,
|
|
Group,
|
|
Flags,
|
|
TransportName,
|
|
HelperDllContext,
|
|
Events
|
|
);
|
|
}
|
|
|
|
/* Return the Helper Pointers */
|
|
*HelperDllData = HelperData;
|
|
/* We actually cache these ... the can't be freed yet */
|
|
/*HeapFree(GlobalHeap, 0, Transports);*/
|
|
/*HeapFree(GlobalHeap, 0, Mapping);*/
|
|
return NO_ERROR;
|
|
}
|
|
|
|
HeapFree(GlobalHeap, 0, Mapping);
|
|
}
|
|
HeapFree(GlobalHeap, 0, Transports);
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
INT
|
|
SockLoadTransportMapping(
|
|
PWSTR TransportName,
|
|
PWINSOCK_MAPPING *Mapping)
|
|
{
|
|
PWSTR TransportKey;
|
|
HKEY KeyHandle;
|
|
ULONG MappingSize;
|
|
LONG Status;
|
|
|
|
TRACE("TransportName %ws\n", TransportName);
|
|
|
|
/* Allocate a Buffer */
|
|
TransportKey = HeapAlloc(GlobalHeap, 0, (54 + wcslen(TransportName)) * sizeof(WCHAR));
|
|
|
|
/* Check for error */
|
|
if (TransportKey == NULL) {
|
|
ERR("Buffer allocation failed\n");
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Generate the right key name */
|
|
wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\");
|
|
wcscat(TransportKey, TransportName);
|
|
wcscat(TransportKey, L"\\Parameters\\Winsock");
|
|
|
|
/* Open the Key */
|
|
Status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TransportKey, 0, KEY_READ, &KeyHandle);
|
|
|
|
/* We don't need the Transport Key anymore */
|
|
HeapFree(GlobalHeap, 0, TransportKey);
|
|
|
|
/* Check for error */
|
|
if (Status) {
|
|
ERR("Error reading transport mapping registry\n");
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Find out how much space we need for the Mapping */
|
|
Status = RegQueryValueExW(KeyHandle, L"Mapping", NULL, NULL, NULL, &MappingSize);
|
|
|
|
/* Check for error */
|
|
if (Status) {
|
|
ERR("Error reading transport mapping registry\n");
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Allocate Memory for the Mapping */
|
|
*Mapping = HeapAlloc(GlobalHeap, 0, MappingSize);
|
|
|
|
/* Check for error */
|
|
if (*Mapping == NULL) {
|
|
ERR("Buffer allocation failed\n");
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Read the Mapping */
|
|
Status = RegQueryValueExW(KeyHandle, L"Mapping", NULL, NULL, (LPBYTE)*Mapping, &MappingSize);
|
|
|
|
/* Check for error */
|
|
if (Status) {
|
|
ERR("Error reading transport mapping registry\n");
|
|
HeapFree(GlobalHeap, 0, *Mapping);
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Close key and return */
|
|
RegCloseKey(KeyHandle);
|
|
return 0;
|
|
}
|
|
|
|
INT
|
|
SockLoadTransportList(
|
|
PWSTR *TransportList)
|
|
{
|
|
ULONG TransportListSize;
|
|
HKEY KeyHandle;
|
|
LONG Status;
|
|
|
|
TRACE("Called\n");
|
|
|
|
/* Open the Transports Key */
|
|
Status = RegOpenKeyExW (HKEY_LOCAL_MACHINE,
|
|
L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters",
|
|
0,
|
|
KEY_READ,
|
|
&KeyHandle);
|
|
|
|
/* Check for error */
|
|
if (Status) {
|
|
ERR("Error reading transport list registry\n");
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Get the Transport List Size */
|
|
Status = RegQueryValueExW(KeyHandle,
|
|
L"Transports",
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&TransportListSize);
|
|
|
|
/* Check for error */
|
|
if (Status) {
|
|
ERR("Error reading transport list registry\n");
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Allocate Memory for the Transport List */
|
|
*TransportList = HeapAlloc(GlobalHeap, 0, TransportListSize);
|
|
|
|
/* Check for error */
|
|
if (*TransportList == NULL) {
|
|
ERR("Buffer allocation failed\n");
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Get the Transports */
|
|
Status = RegQueryValueExW (KeyHandle,
|
|
L"Transports",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)*TransportList,
|
|
&TransportListSize);
|
|
|
|
/* Check for error */
|
|
if (Status) {
|
|
ERR("Error reading transport list registry\n");
|
|
HeapFree(GlobalHeap, 0, *TransportList);
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Close key and return */
|
|
RegCloseKey(KeyHandle);
|
|
return 0;
|
|
}
|
|
|
|
INT
|
|
SockLoadHelperDll(
|
|
PWSTR TransportName,
|
|
PWINSOCK_MAPPING Mapping,
|
|
PHELPER_DATA *HelperDllData)
|
|
{
|
|
PHELPER_DATA HelperData;
|
|
PWSTR HelperDllName;
|
|
PWSTR FullHelperDllName;
|
|
PWSTR HelperKey;
|
|
HKEY KeyHandle;
|
|
ULONG DataSize;
|
|
LONG Status;
|
|
|
|
/* Allocate space for the Helper Structure and TransportName */
|
|
HelperData = HeapAlloc(GlobalHeap, 0, sizeof(*HelperData) + (wcslen(TransportName) + 1) * sizeof(WCHAR));
|
|
|
|
/* Check for error */
|
|
if (HelperData == NULL) {
|
|
ERR("Buffer allocation failed\n");
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Allocate Space for the Helper DLL Key */
|
|
HelperKey = HeapAlloc(GlobalHeap, 0, (54 + wcslen(TransportName)) * sizeof(WCHAR));
|
|
|
|
/* Check for error */
|
|
if (HelperKey == NULL) {
|
|
ERR("Buffer allocation failed\n");
|
|
HeapFree(GlobalHeap, 0, HelperData);
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Generate the right key name */
|
|
wcscpy(HelperKey, L"System\\CurrentControlSet\\Services\\");
|
|
wcscat(HelperKey, TransportName);
|
|
wcscat(HelperKey, L"\\Parameters\\Winsock");
|
|
|
|
/* Open the Key */
|
|
Status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, HelperKey, 0, KEY_READ, &KeyHandle);
|
|
|
|
HeapFree(GlobalHeap, 0, HelperKey);
|
|
|
|
/* Check for error */
|
|
if (Status) {
|
|
ERR("Error reading helper DLL parameters\n");
|
|
HeapFree(GlobalHeap, 0, HelperData);
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Read Size of SockAddr Structures */
|
|
DataSize = sizeof(HelperData->MinWSAddressLength);
|
|
HelperData->MinWSAddressLength = 16;
|
|
RegQueryValueExW (KeyHandle,
|
|
L"MinSockaddrLength",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&HelperData->MinWSAddressLength,
|
|
&DataSize);
|
|
DataSize = sizeof(HelperData->MinWSAddressLength);
|
|
HelperData->MaxWSAddressLength = 16;
|
|
RegQueryValueExW (KeyHandle,
|
|
L"MaxSockaddrLength",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&HelperData->MaxWSAddressLength,
|
|
&DataSize);
|
|
|
|
/* Size of TDI Structures */
|
|
HelperData->MinTDIAddressLength = HelperData->MinWSAddressLength + 6;
|
|
HelperData->MaxTDIAddressLength = HelperData->MaxWSAddressLength + 6;
|
|
|
|
/* Read Delayed Acceptance Setting */
|
|
DataSize = sizeof(DWORD);
|
|
HelperData->UseDelayedAcceptance = FALSE;
|
|
RegQueryValueExW (KeyHandle,
|
|
L"UseDelayedAcceptance",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&HelperData->UseDelayedAcceptance,
|
|
&DataSize);
|
|
|
|
/* Allocate Space for the Helper DLL Names */
|
|
HelperDllName = HeapAlloc(GlobalHeap, 0, 512);
|
|
|
|
/* Check for error */
|
|
if (HelperDllName == NULL) {
|
|
ERR("Buffer allocation failed\n");
|
|
HeapFree(GlobalHeap, 0, HelperData);
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
FullHelperDllName = HeapAlloc(GlobalHeap, 0, 512);
|
|
|
|
/* Check for error */
|
|
if (FullHelperDllName == NULL) {
|
|
ERR("Buffer allocation failed\n");
|
|
HeapFree(GlobalHeap, 0, HelperDllName);
|
|
HeapFree(GlobalHeap, 0, HelperData);
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Get the name of the Helper DLL*/
|
|
DataSize = 512;
|
|
Status = RegQueryValueExW (KeyHandle,
|
|
L"HelperDllName",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)HelperDllName,
|
|
&DataSize);
|
|
|
|
/* Check for error */
|
|
if (Status) {
|
|
ERR("Error reading helper DLL parameters\n");
|
|
HeapFree(GlobalHeap, 0, FullHelperDllName);
|
|
HeapFree(GlobalHeap, 0, HelperDllName);
|
|
HeapFree(GlobalHeap, 0, HelperData);
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Get the Full name, expanding Environment Strings */
|
|
ExpandEnvironmentStringsW (HelperDllName,
|
|
FullHelperDllName,
|
|
256);
|
|
|
|
/* Load the DLL */
|
|
HelperData->hInstance = LoadLibraryW(FullHelperDllName);
|
|
|
|
HeapFree(GlobalHeap, 0, HelperDllName);
|
|
HeapFree(GlobalHeap, 0, FullHelperDllName);
|
|
|
|
if (HelperData->hInstance == NULL) {
|
|
ERR("Error loading helper DLL\n");
|
|
HeapFree(GlobalHeap, 0, HelperData);
|
|
return WSAEINVAL;
|
|
}
|
|
|
|
/* Close Key */
|
|
RegCloseKey(KeyHandle);
|
|
|
|
/* Get the Pointers to the Helper Routines */
|
|
HelperData->WSHOpenSocket = (PWSH_OPEN_SOCKET)
|
|
GetProcAddress(HelperData->hInstance,
|
|
"WSHOpenSocket");
|
|
HelperData->WSHOpenSocket2 = (PWSH_OPEN_SOCKET2)
|
|
GetProcAddress(HelperData->hInstance,
|
|
"WSHOpenSocket2");
|
|
HelperData->WSHJoinLeaf = (PWSH_JOIN_LEAF)
|
|
GetProcAddress(HelperData->hInstance,
|
|
"WSHJoinLeaf");
|
|
HelperData->WSHNotify = (PWSH_NOTIFY)
|
|
GetProcAddress(HelperData->hInstance, "WSHNotify");
|
|
HelperData->WSHGetSocketInformation = (PWSH_GET_SOCKET_INFORMATION)
|
|
GetProcAddress(HelperData->hInstance,
|
|
"WSHGetSocketInformation");
|
|
HelperData->WSHSetSocketInformation = (PWSH_SET_SOCKET_INFORMATION)
|
|
GetProcAddress(HelperData->hInstance,
|
|
"WSHSetSocketInformation");
|
|
HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE)
|
|
GetProcAddress(HelperData->hInstance,
|
|
"WSHGetSockaddrType");
|
|
HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKADDR)
|
|
GetProcAddress(HelperData->hInstance,
|
|
"WSHGetWildcardSockaddr");
|
|
HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR)
|
|
GetProcAddress(HelperData->hInstance,
|
|
"WSHGetBroadcastSockaddr");
|
|
HelperData->WSHAddressToString = (PWSH_ADDRESS_TO_STRING)
|
|
GetProcAddress(HelperData->hInstance,
|
|
"WSHAddressToString");
|
|
HelperData->WSHStringToAddress = (PWSH_STRING_TO_ADDRESS)
|
|
GetProcAddress(HelperData->hInstance,
|
|
"WSHStringToAddress");
|
|
HelperData->WSHIoctl = (PWSH_IOCTL)
|
|
GetProcAddress(HelperData->hInstance,
|
|
"WSHIoctl");
|
|
|
|
/* Save the Mapping Structure and transport name */
|
|
HelperData->Mapping = Mapping;
|
|
wcscpy(HelperData->TransportName, TransportName);
|
|
|
|
/* Increment Reference Count */
|
|
HelperData->RefCount = 1;
|
|
|
|
/* Add it to our list */
|
|
InsertHeadList(&SockHelpersListHead, &HelperData->Helpers);
|
|
|
|
/* Return Pointers */
|
|
*HelperDllData = HelperData;
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
SockIsTripleInMapping(
|
|
PWINSOCK_MAPPING Mapping,
|
|
INT AddressFamily,
|
|
INT SocketType,
|
|
INT Protocol)
|
|
{
|
|
/* The Windows version returns more detailed information on which of the 3 parameters failed...we should do this later */
|
|
ULONG Row;
|
|
|
|
TRACE("Called, Mapping rows = %d\n", Mapping->Rows);
|
|
|
|
/* Loop through Mapping to Find a matching one */
|
|
for (Row = 0; Row < Mapping->Rows; Row++) {
|
|
TRACE("Examining: row %d: AF %d type %d proto %d\n",
|
|
Row,
|
|
(INT)Mapping->Mapping[Row].AddressFamily,
|
|
(INT)Mapping->Mapping[Row].SocketType,
|
|
(INT)Mapping->Mapping[Row].Protocol);
|
|
|
|
/* Check of all three values Match */
|
|
if (((INT)Mapping->Mapping[Row].AddressFamily == AddressFamily) &&
|
|
((INT)Mapping->Mapping[Row].SocketType == SocketType) &&
|
|
((INT)Mapping->Mapping[Row].Protocol == Protocol)) {
|
|
TRACE("Found\n");
|
|
return TRUE;
|
|
}
|
|
}
|
|
WARN("Not found\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* EOF */
|