Windows2003-3790/inetcore/wininet/apdetect/sockreg.cxx
2020-09-30 16:53:55 +02:00

1471 lines
39 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
sockreg.cxx
Abstract:
Contains the registry/ini-file specific functions from gethost.c
Taken from Win95 Winsock 1.1 project
Contents:
SockGetSingleValue
(CheckRegistryForParameter)
(GetDnsServerListFromDhcp)
(GetDomainNameFromDhcp)
(GetDhcpHardwareInfo)
(OpenDhcpVxdHandle)
(DhcpVxdRequest)
Author:
Richard L Firth (rfirth) 10-Feb-1994
Environment:
Win32 user-mode DLL
Revision History:
10-Feb-1994 (rfirth)
Created
--*/
//
// includes
//
#include <wininetp.h>
#include "aproxp.h"
//
// manifests
//
#define PLATFORM_TYPE_UNKNOWN ((DWORD)(-1))
#define PLATFORM_TYPE_WIN95 ((DWORD)(0))
#define PLATFORM_TYPE_WINNT ((DWORD)(1))
#define PLATFORM_SUPPORTS_UNICODE 0x00000001
#define DEVICE_PREFIX "\\Device\\"
//
// manifests
//
//
// macros
//
#define FSTRLEN(p) lstrlen((LPSTR)(p))
#define FSTRCPY(p1, p2) lstrcpy((LPSTR)(p1), (LPSTR)(p2))
#define FSTRCAT(p1, p2) lstrcat((LPSTR)(p1), (LPSTR)(p2))
//
// MAP_PARAMETER_ID - returns a string corresponding to the database parameter
//
// N.B. id MUST start at 1
//
#define MAP_PARAMETER_ID(id) ParameterNames[(id) - 1]
//
// globally available registry keys
//
extern HKEY ServicesKey; // = INVALID_HANDLE_VALUE;
//
// private prototypes
//
PRIVATE
UINT
CheckRegistryForParameter(
IN UINT ParameterId,
OUT LPBYTE Data,
IN UINT DataLength
);
PRIVATE
UINT
GetDnsServerListFromDhcp(
LPBYTE Data,
UINT DataLength
);
PRIVATE
UINT
GetDomainNameFromDhcp(
LPBYTE Data,
UINT DataLength
);
PRIVATE
LPDHCP_QUERYINFO
GetDhcpHardwareInfo(
VOID
);
PRIVATE
DWORD_PTR
OpenDhcpVxdHandle(
VOID
);
PRIVATE
WORD
DhcpVxdRequest(
IN DWORD_PTR Handle,
IN WORD Request,
IN WORD BufferLength,
OUT LPVOID Buffer
);
PRIVATE
DWORD_PTR
OsOpenVxdHandle(
CHAR * VxdName,
WORD VxdId
);
PRIVATE
VOID
OsCloseVxdHandle(
DWORD_PTR VxdHandle
);
PRIVATE
INT
OsSubmitVxdRequest(
DWORD_PTR VxdHandle,
INT OpCode,
LPVOID Param,
INT ParamLength
);
//
// private data
//
//
// ParameterNames - the names of the registry values corresponding to the
// variables retrieved by SockGetSingleValue.
//
// N.B. These MUST be in order of the CONFIG_ manifests in sockreg.h
//
PRIVATE const LPCSTR ParameterNames[] = {
"HostName",
"Domain",
"SearchList",
"NameServer"
};
//
// functions
//
/*******************************************************************************
*
* GetBoundAdapterList
*
* Gets a list of names of all adapters bound to a protocol (TCP/IP). Returns
* a pointer to an array of pointers to strings - basically an argv list. The
* memory for the strings is concatenated to the array and the array is NULL
* terminated. If Elnkii1 and IbmTok2 are bound to TCP/IP then this function
* will return:
*
* ---> addr of string1 \
* addr of string2 \
* NULL > allocated as one block
* &string1: "Elnkii1" /
* &string2: "IbmTok2" /
*
* ENTRY BindingsSectionKey
* - Open registry handle to a linkage key (e.g. Tcpip\Linkage)
*
* EXIT
*
* RETURNS pointer to argv[] style array, or NULL
*
* ASSUMES
*
******************************************************************************/
LPSTR* GetBoundAdapterList(HKEY BindingsSectionKey)
{
LPSTR* resultBuffer;
LONG err;
DWORD valueType;
PBYTE valueBuffer = NULL;
DWORD valueLength;
LPSTR* nextResult;
int len;
DWORD resultLength;
LPSTR nextValue;
LPSTR variableData;
DWORD numberOfBindings;
//
// get required size of value buffer
//
valueLength = 0;
resultBuffer = NULL;
err = RegQueryValueEx(BindingsSectionKey,
"Bind",
NULL, // reserved
&valueType,
NULL,
&valueLength
);
if (err != ERROR_SUCCESS) {
goto quit;
}
if (valueType != REG_MULTI_SZ) {
goto quit;
}
if (!valueLength) {
goto quit;
}
valueBuffer = (PBYTE)ALLOCATE_MEMORY(LPTR, valueLength);
if ( valueBuffer == NULL ) {
goto quit;
}
err = RegQueryValueEx(BindingsSectionKey,
"Bind",
NULL, // reserved
&valueType,
valueBuffer,
&valueLength
);
if (err != ERROR_SUCCESS) {
goto quit;
}
resultLength = sizeof(LPSTR); // the NULL at the end of the list
numberOfBindings = 0;
nextValue = (LPSTR)valueBuffer;
while (len = strlen(nextValue)) {
resultLength += sizeof(LPSTR) + len + 1;
if (!_strnicmp(nextValue, DEVICE_PREFIX, sizeof(DEVICE_PREFIX) - 1)) {
resultLength -= sizeof(DEVICE_PREFIX) - 1;
}
nextValue += len + 1;
++numberOfBindings;
}
resultBuffer = (LPSTR*)ALLOCATE_MEMORY(LPTR, resultLength);
if ( resultBuffer == NULL ) {
goto quit;
}
nextValue = (LPSTR)valueBuffer;
nextResult = resultBuffer;
variableData = (LPSTR)(((LPSTR*)resultBuffer) + numberOfBindings + 1);
while (numberOfBindings--) {
LPSTR adapterName;
adapterName = nextValue;
if (!_strnicmp(adapterName, DEVICE_PREFIX, sizeof(DEVICE_PREFIX) - 1)) {
adapterName += sizeof(DEVICE_PREFIX) - 1;
}
*nextResult++ = variableData;
strcpy(variableData, adapterName);
while (*variableData) {
++variableData;
}
++variableData;
while (*nextValue) {
++nextValue;
}
++nextValue;
}
*nextResult = NULL;
quit:
if ( valueBuffer != NULL )
{
FREE_MEMORY(valueBuffer);
}
return resultBuffer;
}
/*******************************************************************************
*
* OpenAdapterKey
*
* Opens one of the 2 per-adapter registry keys: <Adapter>\Parameters\Tcpip, or
* NetBT\Adapters\<Adapter>
*
* ENTRY KeyType - KEY_TCP or KEY_NBT
* Name - pointer to adapter name to use
* Key - pointer to returned key
*
* EXIT Key updated
*
* RETURNS TRUE if success
*
* ASSUMES
*
******************************************************************************/
BOOL OpenAdapterKey(DWORD KeyType, LPSTR Name, PHKEY Key)
{
LONG err;
CHAR keyName[MAX_ADAPTER_NAME_LENGTH + sizeof("\\Parameters\\Tcpip")];
if ((lstrlen(Name)+sizeof("\\Parameters\\Tcpip")) < ARRAY_ELEMENTS(keyName))
{
if (KeyType == KEY_TCP) {
//
// open the handle to this adapter's TCPIP parameter key
//
strcpy(keyName, Name);
strcat(keyName, "\\Parameters\\Tcpip");
} else if (KeyType == KEY_NBT) {
//
// open the handle to the NetBT\Adapters\<Adapter> handle
//
strcpy(keyName, "NetBT\\Adapters\\");
strcat(keyName, Name);
}
}
else
{
INET_ASSERT((lstrlen(Name)+sizeof("\\Parameters\\Tcpip")) < ARRAY_ELEMENTS(keyName));
return FALSE;
}
err = REGOPENKEY(ServicesKey,
keyName,
Key
);
DEBUG_PRINT( SOCKETS,
INFO,
("RegOpenKey %s %s %s %d\n",
SERVICES_KEY_NAME, keyName,
(err != ERROR_SUCCESS )? "failed":"success",
GetLastError() ));
return (err == ERROR_SUCCESS);
}
/*******************************************************************************
*
* ReadRegistryDword
*
* Reads a registry value that is stored as a DWORD
*
* ENTRY Key - open registry key where value resides
* ParameterName - name of value to read from registry
* Value - pointer to returned value
*
* EXIT *Value = value read
*
* RETURNS TRUE if success
*
* ASSUMES
*
******************************************************************************/
BOOL ReadRegistryDword(HKEY Key, LPSTR ParameterName, LPDWORD Value)
{
LONG err;
DWORD valueLength;
DWORD valueType;
valueLength = sizeof(*Value);
err = RegQueryValueEx(Key,
ParameterName,
NULL, // reserved
&valueType,
(LPBYTE)Value,
&valueLength
);
if( (err == ERROR_SUCCESS )
&& (valueType == REG_DWORD )
&& (valueLength == sizeof(DWORD))) {
return 1;
} else {
DEBUG_PRINT(SOCKETS, INFO,
("ReadRegistryDword(%s): err=%d\n", ParameterName, err ));
return 0;
}
}
/*******************************************************************************
*
* ReadRegistryString
*
* Reads a registry value that is stored as a string
*
* ENTRY Key - open registry key
* ParameterName - name of value to read from registry
* String - pointer to returned string
* Length - IN: length of String buffer. OUT: length of returned string
*
* EXIT String contains string read
*
* RETURNS TRUE if success
*
* ASSUMES
*
******************************************************************************/
BOOL
ReadRegistryString(HKEY Key, LPSTR ParameterName, LPSTR String, LPDWORD Length)
{
LONG err;
DWORD valueType;
*String = '\0';
err = RegQueryValueEx(Key,
ParameterName,
NULL, // reserved
&valueType,
(LPBYTE)String,
Length
);
if (err == ERROR_SUCCESS) {
DLL_ASSERT(valueType == REG_SZ || valueType == REG_MULTI_SZ);
return (*Length) > sizeof(char);
} else {
DEBUG_PRINT(SOCKETS,
INFO,
("ReadRegistryString(%s): err=%d\n", ParameterName, err ));
return 0;
}
}
UINT
SockGetSingleValue(
IN UINT ParameterId,
OUT LPBYTE Data,
IN UINT DataLength
)
/*++
Routine Description:
Retrieve parameter from Registry/DHCP/TCPIP
This is what we look for and where:
HostName: 1. HKLM\Services\CurrentControlSet\System\Vxd\MSTCP\HostName (Win95)
HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\Hostname (NT)
2. (SYSTEM.INI:DNS.HostName)* (N/A)
3. GetComputerName()
DomainName: 1. HKLM\Services\CurrentControlSet\System\Vxd\MSTCP\Domain (Win95)
HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\DhcpDomain (NT)
HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\Domain (NT)
2. (SYSTEM.INI:DNS.DomainName)* (N/A)
3. DHCP (Win95)
SearchList: 1. HKLM\Services\CurrentControlSet\System\Vxd\MSTCP\SearchList (Win95)
HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\SearchList (NT)
2. (SYSTEM.INI:DNS.DNSDomains)* (N/A)
NameServer: 1. HKLM\Services\CurrentControlSet\System\Vxd\MSTCP\NameServer (Win95)
HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\DhcpNameServer (NT)
HKLM\Services\CurrentControlSet\System\Tcpip\Parameters\NameServer (NT)
2. (SYSTEM.INI:DNS.DNSServers)* (N/A)
3. DHCP (Win95)
* Entries marked thus are registry backups from SYSTEM.INI until all
keys are moved into registry or if platform is WFW 3.11 (in which
case there is no registry)
ASSUMES 1. Data is big enough to hold the default value (single byte for
strings, dword for dwords)
2. Registry is accessible from 16-bit code too
Arguments:
ParameterId - identifier of parameter to retrieve
Data - pointer to untyped storage space for parameter
DataLength - length of data returned (in bytes)
Return Value:
UINT
Success - ERROR_SUCCESS
Failure - ERROR_PATH_NOT_FOUND
can't locate required parameter in registry/ini/etc.
--*/
{
UINT error = CheckRegistryForParameter(ParameterId, Data, DataLength);
//
// if the value was not in the registry then we must attempt to get it from
// another place, specific to the particular variable requested
//
if (error != ERROR_SUCCESS) {
if (ParameterId == CONFIG_HOSTNAME) {
//
// on Win32 platform we can call GetComputerName() to provide the
// computer name, which is the default host name, if none is
// specified elsewhere
//
DWORD length;
length = DataLength;
if (!GetComputerName((LPSTR)Data, &length)) {
error = GetLastError();
}
} else if (ParameterId == CONFIG_DOMAIN) {
if (GlobalPlatformType == PLATFORM_TYPE_WIN95) {
error = GetDomainNameFromDhcp(Data, DataLength);
}
} else if (ParameterId == CONFIG_NAME_SERVER) {
if (GlobalPlatformType == PLATFORM_TYPE_WIN95) {
error = GetDnsServerListFromDhcp(Data, DataLength);
}
} else {
//
// the caller is requesting the domain list (or an invalid config
// parameter value?!?). We have nowhere else to get this value -
// return an error
//
error = ERROR_PATH_NOT_FOUND;
}
}
IF_DEBUG(REGISTRY) {
if (error != ERROR_SUCCESS) {
DLL_PRINT(("SockGetSingleValue(%s) returns %d\r",
MAP_PARAMETER_ID(ParameterId),
error
));
} else {
DLL_PRINT(("SockGetSingleValue(%s) returns \"%s\"\n",
MAP_PARAMETER_ID(ParameterId),
Data
));
}
}
return error;
}
PRIVATE
UINT
CheckRegistryForParameter(
IN UINT ParameterId,
OUT LPBYTE Data,
IN UINT DataLength
)
/*++
Routine Description:
Retrieve parameter from registry
ASSUMES 1. Data is big enough to hold the default value (single byte for
strings, dword for dwords)
Arguments:
ParameterId - identifier of parameter to retrieve
Data - pointer to untyped storage space for parameter
DataLength - length of data returned (in bytes)
Return Value:
UINT
Success - ERROR_SUCCESS
Failure - ERROR_PATH_NOT_FOUND
ERROR_INSUFFICIENT_BUFFER
--*/
{
HKEY key;
LONG error = REGOPENKEY(HKEY_LOCAL_MACHINE,
(GlobalPlatformType == PLATFORM_TYPE_WINNT)
? "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
: "System\\CurrentControlSet\\Services\\VxD\\MSTCP",
&key
);
if (error == ERROR_SUCCESS) {
char dhcpBuffer[128]; // arbitrary
LPSTR p;
DWORD length;
DWORD type;
BOOL tryDhcp;
if (GlobalPlatformType == PLATFORM_TYPE_WINNT) {
FSTRCPY(dhcpBuffer, "Dhcp");
p = &dhcpBuffer[sizeof("Dhcp") - 1];
tryDhcp = TRUE;
} else {
p = dhcpBuffer;
tryDhcp = FALSE;
}
FSTRCPY(p, MAP_PARAMETER_ID(ParameterId));
//
// on NT, we look first for the manually-entered variables e.g. "Domain"
// and if not found, we look a second time for the DHCP-configured
// variant, e.g. "DhcpDomain"
//
for (int i = 0; i < 2; ++i) {
//
// if NT, first we try the transient key which is written to the
// registry when we have a dial-up connection
//
if ((i == 0) && (GlobalPlatformType == PLATFORM_TYPE_WINNT)) {
HKEY transientKey;
error = REGOPENKEY(key, "Transient", &transientKey);
if (error == ERROR_SUCCESS) {
length = DataLength;
error = RegQueryValueEx(transientKey,
p,
NULL, // reserved
&type,
Data,
&length
);
REGCLOSEKEY(transientKey);
//
// if we succeeded in retrieving a non-empty string then
// we're done.
//
// We test for > 1 because the registry returns the length
// including the zero-terminator
//
if ((error == ERROR_SUCCESS) && (length > 1)) {
break;
}
}
}
length = DataLength;
error = RegQueryValueEx(key,
p,
NULL, // reserved
&type,
Data,
&length
);
//
// if the key exists, but there is no value then return an error OR
// if we didn't find the key (or value) AND NT then try for the DHCP
// version (Note: We try for DhcpSearchList even though it doesn't
// exist)
//
if ((error != ERROR_SUCCESS)
|| (length == 0)
|| ((length == 1) && (Data[0] == '\0'))) {
if (tryDhcp) {
p = dhcpBuffer;
tryDhcp = FALSE;
continue;
} else {
error = ERROR_PATH_NOT_FOUND;
break;
}
} else if ((UINT)length > DataLength) {
error = ERROR_INSUFFICIENT_BUFFER;
break;
}
}
REGCLOSEKEY(key);
}
IF_DEBUG(REGISTRY) {
DLL_PRINT(("CheckRegistryForParameter(%s): returning %d\n",
MAP_PARAMETER_ID(ParameterId),
error
));
}
return (UINT)error;
}
UINT
GetDhcpServerFromDhcp(
IN OUT CAdapterInterface * paiInterface
)
/*******************************************************************************
*
* GetDhcpServerFromDhcp
*
* Updates an CAdapterInterface with the DHCP server from the DHCP info
*
* ENTRY paiInterface - pointer to CAdapterInterface to update
*
* EXIT paiInterface - DhcpServer may be updated
*
* RETURNS TRUE if AdapterInfo->DhcpServer updated
*
* ASSUMES 1. AdapterInfo->Address is valid
*
******************************************************************************/
{
LPDHCP_QUERYINFO pDhcpInfoPtr;
if ( GlobalPlatformType == PLATFORM_TYPE_WINNT )
{
HKEY key;
if (paiInterface->GetAdapterName() &&
OpenAdapterKey(KEY_TCP, paiInterface->GetAdapterName(), &key))
{
char dhcpServerAddress[4 * 4];
DWORD addressLength;
DWORD fDhcpEnabled = FALSE;
ReadRegistryDword(key,
"EnableDHCP",
&fDhcpEnabled
);
if ( fDhcpEnabled )
{
addressLength = sizeof(dhcpServerAddress);
if (ReadRegistryString(key,
"DhcpServer",
dhcpServerAddress,
&addressLength
))
{
DWORD ipAddress = _I_inet_addr(dhcpServerAddress);
if ( IS_VALID_NON_LOOPBACK_IP_ADDRESS(ipAddress) )
{
paiInterface->AddDhcpServer(ipAddress);
paiInterface->SetDhcp();
}
}
}
//ReadRegistryDword(key,
// "LeaseObtainedTime",
// &AdapterInfo->LeaseObtained
// );
//ReadRegistryDword(key,
// "LeaseTerminatesTime",
// &AdapterInfo->LeaseExpires
// );
REGCLOSEKEY(key);
return fDhcpEnabled;
}
}
else
{
if (pDhcpInfoPtr = GetDhcpHardwareInfo()) {
DWORD i;
for (i = 0; i < pDhcpInfoPtr->NumNICs; ++i)
{
LPDHCP_NIC_INFO info;
register BOOL match;
info = &pDhcpInfoPtr->NicInfo[i];
match = paiInterface->IsHardwareAddress( ((LPBYTE)pDhcpInfoPtr + info->OffsetHardwareAddress) );
if (match && info->DhcpServerAddress) {
paiInterface->AddDhcpServer(info->DhcpServerAddress);
//
// side-effect: this adapter is DHCP enabled
//
paiInterface->SetDhcp();
DEBUG_PRINT(SOCKETS,
INFO,
( "GetDhcpServerFromDhcp %s\n",
"bugbug"/*inet_ntoa((int)info->DhcpServerAddress)*/ ));
return TRUE;
}
}
} else {
DEBUG_PRINT(SOCKETS,
INFO,
("GetDhcpServerFromDhcp: DhcpInfoPtr is 0\n"));
}
}
return FALSE;
}
PRIVATE
UINT
GetDnsServerListFromDhcp(
LPBYTE Data,
UINT DataLength
)
/*++
Routine Description:
Attempts to retrieve a list of DNS servers from DHCP if DHCP is active and
the DNS servers option was specified at the DHCP server
Arguments:
Data - pointer to place to return the list
DataLength - length of Data
Return Value:
UINT
Success - ERROR_SUCCESS
Failure - ERROR_PATH_NOT_FOUND
--*/
{
LPDHCP_QUERYINFO pInfo;
LPBYTE originalData;
originalData = Data;
*Data = 0;
if (pInfo = GetDhcpHardwareInfo()) {
UINT n = (UINT)pInfo->NumNICs;
LPDHCP_NIC_INFO pNicInfo = &pInfo->NicInfo[0];
UINT first = TRUE;
DWORD smallCache[16];
UINT cacheIndex = 0;
IF_DEBUG(REGISTRY) {
DLL_PRINT(("GetDnsServerListFromDhcp(): DHCP has %d adapters\n",
pInfo->NumNICs
));
}
while (n-- && DataLength) {
UINT i;
LPDWORD pServers = (LPDWORD)((LPBYTE)pInfo + pNicInfo->OffsetDNSServers);
IF_DEBUG(REGISTRY) {
DLL_PRINT(("GetDnsServerListFromDhcp(): NIC %x has %d DNS addresses\n",
pNicInfo,
pNicInfo->DNSServersLen / 4
));
}
for (i = 0; i < pNicInfo->DNSServersLen; i += 4) {
IN_ADDR inaddr;
char* p;
//
// copy the next DNS address from the DHCP list
//
memcpy(&inaddr, pServers++, sizeof(DWORD));
//
// inet_ntoa will validate the address: if it returns NULL, the
// address is no good, so we skip it
//
p = _I_inet_ntoa(inaddr);
if ((p != NULL) && *p) {
BOOL found;
UINT cachePos;
//
// now check if we've already seen this address. If we have
// then we skip it: no sense in adding redundant DNS addresses.
// This can happen when we have multiple cards, all configured
// with the same DNS info
//
found = FALSE;
for (cachePos = 0; cachePos < cacheIndex; ++cachePos) {
if (smallCache[cachePos] == (DWORD)inaddr.s_addr) {
found = TRUE;
break;
}
}
if (!found) {
UINT len;
//
// new one: add it
//
if (cacheIndex < (sizeof(smallCache)/sizeof(smallCache[0])) - 1) {
IF_DEBUG(REGISTRY) {
DLL_PRINT(("GetDnsServerListFromDhcp(): adding %s to smallCache[%d]\n",
p,
cacheIndex
));
}
smallCache[cacheIndex] = (DWORD)inaddr.s_addr;
//
// increment the cache index; don't let it go past
// the last element
//
if (cacheIndex < (sizeof(smallCache)/sizeof(smallCache[0])) - 1) {
++cacheIndex;
}
} else {
IF_DEBUG(REGISTRY) {
DLL_PRINT(("GetDnsServerListFromDhcp(): smallCache full (!)\n"));
}
}
len = FSTRLEN(p);
//
// this assumes that we have more buffer than just
// enough for one string: if there is only one address
// and we have been supplied with DataLength == length
// of the address plus 1 for the zero terminator, then
// we will fail to copy it since we check for space
// enough for the string, zero terminator, plus an extra
// byte for the space separator. But this is being
// overly pedantic. Casuistry even
//
if (DataLength > len + 1) {
if (!first) {
*Data++ = ' ';
--DataLength;
}
IF_DEBUG(REGISTRY) {
DLL_PRINT(("GetDnsServerListFromDhcp() found \"%s\"\n",
p
));
}
FSTRCPY(Data, p);
DataLength -= len;
Data += len;
first = FALSE;
} else {
IF_DEBUG(REGISTRY) {
DLL_PRINT(("GetDnsServerListFromDhcp(): out of buffer space (need=%d, left=%d)\n",
len + 1,
DataLength
));
}
}
} else {
IF_DEBUG(REGISTRY) {
DLL_PRINT(("GetDnsServerListFromDhcp(): already seen address %s\n",
p
));
}
}
}
}
++pNicInfo;
}
DllFreeMem((void*)pInfo);
//
// if we didn't find any DNS addresses or couldn't fit them in the
// supplied buffer then return an error
//
return (UINT)((*originalData != 0) ? ERROR_SUCCESS : ERROR_PATH_NOT_FOUND);
} else {
IF_DEBUG(REGISTRY) {
DLL_PRINT(("GetDnsServerListFromDhcp() returning %d\n",
ERROR_PATH_NOT_FOUND
));
}
return ERROR_PATH_NOT_FOUND;
}
}
PRIVATE
UINT
GetDomainNameFromDhcp(
LPBYTE Data,
UINT DataLength
)
/*++
Routine Description:
Attempts to retrieve the domain from DHCP. In this case, the DHCP server
gave out the domain name we are supposed to use
Arguments:
Data - pointer to place to return the list
DataLength - length of Data
Return Value:
UINT
--*/
{
LPDHCP_QUERYINFO pInfo;
pInfo = GetDhcpHardwareInfo();
if (pInfo) {
UINT n;
LPDHCP_NIC_INFO pNicInfo;
//
// search for the first domain name in the NIC list
//
n = (UINT)pInfo->NumNICs;
pNicInfo = &pInfo->NicInfo[0];
//
// BUGBUG - is this correct for multi-homed hosts?
//
while (n--) {
DWORD dnLen;
dnLen = pNicInfo->DomainNameLen;
if (dnLen && (DataLength >= dnLen)) {
IF_DEBUG(REGISTRY) {
DLL_PRINT(("GetDomainNameFromDhcp() found \"%s\"\n",
(LPBYTE)pInfo + pNicInfo->OffsetDomainName
));
}
memcpy(Data,
(LPBYTE)pInfo + pNicInfo->OffsetDomainName,
(size_t)dnLen
);
//
// we've got our one and only domain name (that we're interested
// in, anyway), so exit
//
break;
}
}
DllFreeMem((void*)pInfo);
return ERROR_SUCCESS;
} else {
IF_DEBUG(REGISTRY) {
DLL_PRINT(("GetDomainNameFromDhcp() returning %d\n",
ERROR_PATH_NOT_FOUND
));
}
return ERROR_PATH_NOT_FOUND;
}
}
/*******************************************************************************
*
* GetDhcpHardwareInfo
*
* Retrieves all the hardware-specific information for all adapters from the
* DHCP VxD
*
* ENTRY nothing
*
* EXIT nothing
*
* RETURNS Success - pointer to allocated buffer containing all hardware info
* Failure - NULL
*
* ASSUMES
*
******************************************************************************/
PRIVATE
LPDHCP_QUERYINFO
GetDhcpHardwareInfo(
VOID
)
{
LPDHCP_QUERYINFO info = NULL;
DWORD_PTR handle = OpenDhcpVxdHandle();
if (handle) {
WORD result;
DWORD sizeRequired;
result = DhcpVxdRequest(handle,
DHCP_QUERY_INFO,
sizeof(sizeRequired),
&sizeRequired
);
//
// ERROR_BUFFER_OVERFLOW tells us exactly how many bytes we need. If we
// don't get this error back, then its an unexpected (i.e. error)
// situation
//
if (result == ERROR_BUFFER_OVERFLOW) {
info = (LPDHCP_QUERYINFO)DllAllocMem((size_t)sizeRequired);
if (info) {
result = DhcpVxdRequest(handle,
DHCP_QUERY_INFO,
(WORD)sizeRequired,
info
);
if (result != ERROR_SUCCESS) {
DllFreeMem((void*)info);
}
}
}
}
if (handle) {
OsCloseVxdHandle(handle);
}
return info;
}
/*******************************************************************************
*
* OpenDhcpVxdHandle
*
* On Snowball, just retrieves the (real-mode) entry point address to the VxD
*
* ENTRY nothing
*
* EXIT DhcpVxdEntryPoint set
*
* RETURNS DhcpVxdEntryPoint
*
* ASSUMES 1. We are running in V86 mode
*
******************************************************************************/
PRIVATE
DWORD_PTR
OpenDhcpVxdHandle(
VOID
)
{
return OsOpenVxdHandle("VDHCP", VDHCP_Device_ID);
}
/*******************************************************************************
*
* DhcpVxdRequest
*
* Makes a DHCP VxD request - passes a function code, parameter buffer and
* length to the (real-mode/V86) VxD entry-point
*
* ENTRY Handle - handle for Win32 call
* Request - DHCP VxD request
* BufferLength - length of Buffer
* Buffer - pointer to request-specific parameters
*
* EXIT depends on request
*
* RETURNS Success - 0
* Failure - ERROR_PATH_NOT_FOUND
* Returned if a specified adapter address could not be
* found
*
* ERROR_BUFFER_OVERFLOW
* Returned if the supplied buffer is too small to contain
* the requested information
*
* ASSUMES
*
******************************************************************************/
PRIVATE
WORD
DhcpVxdRequest(
IN DWORD_PTR Handle,
IN WORD Request,
IN WORD BufferLength,
OUT LPVOID Buffer
)
{
return (WORD) OsSubmitVxdRequest(Handle,
(INT)Request,
(LPVOID)Buffer,
(INT)BufferLength
);
}
PRIVATE
DWORD_PTR
OsOpenVxdHandle(
CHAR * VxdName,
WORD VxdId
)
{
HANDLE VxdHandle;
CHAR VxdPath[MAX_PATH];
//
// Sanity check.
//
DLL_ASSERT( VxdName != NULL );
DLL_ASSERT( VxdId != 0 );
IF_DEBUG( VXD_IO )
{
DLL_PRINT(( "OsOpenVxdHandle: id = %04X, name = %s\n",
VxdId,
VxdName ));
}
//
// Build the VxD path.
//
FSTRCPY( VxdPath, "\\\\.\\");
if(FSTRLEN(VxdPath) + FSTRLEN(VxdName) >= sizeof(VxdPath) / sizeof(VxdPath[0]))
{
DLL_ASSERT(FALSE);
return 0;
}
FSTRCAT( VxdPath, VxdName);
//
// Open the device.
//
// First try the name without the .VXD extension. This will
// cause CreateFile to connect with the VxD if it is already
// loaded (CreateFile will not load the VxD in this case).
//
VxdHandle = CreateFile( VxdPath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_DELETE_ON_CLOSE,
NULL );
if( VxdHandle == INVALID_HANDLE_VALUE )
{
//
// Not found. Append the .VXD extension and try again.
// This will cause CreateFile to load the VxD.
//
FSTRCAT( VxdPath, ".VXD" );
VxdHandle = CreateFile( VxdPath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_DELETE_ON_CLOSE,
NULL );
}
if( VxdHandle != INVALID_HANDLE_VALUE )
{
IF_DEBUG( VXD_IO )
{
DLL_PRINT(( "OsOpenVxdHandle: returning handle %08lX\n",
VxdHandle ));
}
return (DWORD_PTR)VxdHandle;
}
IF_DEBUG( VXD_IO )
{
DLL_PRINT(( "OsOpenVxdHandle: cannot open %s (%04X), error %d\n",
VxdPath,
VxdId,
GetLastError() ));
}
return 0;
} // OsOpenVxdHandle
PRIVATE
VOID
OsCloseVxdHandle(
DWORD_PTR VxdHandle
)
{
//
// Sanity check.
//
DLL_ASSERT( VxdHandle != 0 );
IF_DEBUG( VXD_IO )
{
DLL_PRINT(( "OsCloseVxdHandle: handle %08X\n",
VxdHandle ));
}
if( !CloseHandle( (HANDLE)VxdHandle ) )
{
DLL_PRINT(( "OsCloseVxdHandle: cannot close handle %08X, error %d\n",
VxdHandle,
GetLastError() ));
}
} // OsCloseVxdHandle
PRIVATE
INT
OsSubmitVxdRequest(
DWORD_PTR VxdHandle,
INT OpCode,
LPVOID Param,
INT ParamLength
)
{
DWORD BytesRead;
INT Result = 0;
//
// Sanity check.
//
DLL_ASSERT( VxdHandle != 0 );
DLL_ASSERT( ( Param != NULL ) || ( ParamLength == 0 ) );
IF_DEBUG( VXD_IO )
{
DLL_PRINT(( "OsSubmitVxdRequest: opcode %04X, param %08lX, length %d\n",
OpCode,
Param,
ParamLength ));
}
if( !DeviceIoControl( (HANDLE)VxdHandle,
OpCode,
Param,
ParamLength,
Param,
ParamLength,
&BytesRead,
NULL ) )
{
Result = GetLastError();
}
IF_DEBUG( VXD_IO )
{
DLL_PRINT(( "OsSubmitVxdRequest: returning %d\n",
Result ));
}
return Result;
} // OsSubmitVxdRequest