Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2944 lines
74 KiB

/*==========================================================================
*
* Copyright (C) 1998-2002 Microsoft Corporation. All Rights Reserved.
*
* File: Utils.cpp
* Content: Serial service provider utility functions
*
*
* History:
* Date By Reason
* ==== == ======
* 11/25/98 jtk Created
***************************************************************************/
#include "dnwsocki.h"
//**********************************************************************
// Constant definitions
//**********************************************************************
#define DEFAULT_THREADS_PER_PROCESSOR 3
#define REGSUBKEY_DPNATHELP_DIRECTPLAY8PRIORITY L"DirectPlay8Priority"
#define REGSUBKEY_DPNATHELP_DIRECTPLAY8INITFLAGS L"DirectPlay8InitFlags"
#define REGSUBKEY_DPNATHELP_GUID L"Guid"
//**********************************************************************
// Macro definitions
//**********************************************************************
//**********************************************************************
// Structure definitions
//**********************************************************************
//**********************************************************************
// Variable definitions
//**********************************************************************
//
// global variables that are unique for the process
//
#ifndef DPNBUILD_ONLYONETHREAD
static DNCRITICAL_SECTION g_InterfaceGlobalsLock;
#endif // !DPNBUILD_ONLYONETHREAD
static volatile LONG g_iThreadPoolRefCount = 0;
static CThreadPool * g_pThreadPool = NULL;
static volatile LONG g_iWinsockRefCount = 0;
#ifndef DPNBUILD_NONATHELP
static volatile LONG g_iNATHelpRefCount = 0;
#endif // ! DPNBUILD_NONATHELP
#if ((defined(WINNT)) && (! defined(DPNBUILD_NOMULTICAST)))
static volatile LONG g_iMadcapRefCount = 0;
BYTE g_abClientID[MCAST_CLIENT_ID_LEN];
#endif // WINNT and not DPNBUILD_NOMULTICAST
//**********************************************************************
// Function prototypes
//**********************************************************************
#ifndef DPNBUILD_NOREGISTRY
static void ReadSettingsFromRegistry( void );
static BOOL BannedIPv4AddressCompareFunction( PVOID pvKey1, PVOID pvKey2 );
static DWORD BannedIPv4AddressHashFunction( PVOID pvKey, BYTE bBitDepth );
static void ReadBannedIPv4Addresses( CRegistry * pRegObject );
#endif // ! DPNBUILD_NOREGISTRY
//**********************************************************************
// Function definitions
//**********************************************************************
#if defined(WINCE) && !defined(_MAX_DRIVE)
//typedef signed char _TSCHAR;
#define _MAX_DRIVE 3 /* max. length of drive component */
#define _MAX_DIR 256 /* max. length of path component */
#define _MAX_FNAME 256 /* max. length of file name component */
#define _MAX_EXT 256 /* max. length of extension component */
void __cdecl _tsplitpath (
register const _TSCHAR *path,
_TSCHAR *drive,
_TSCHAR *dir,
_TSCHAR *fname,
_TSCHAR *ext
)
{
register _TSCHAR *p;
_TSCHAR *last_slash = NULL, *dot = NULL;
unsigned len;
/* we assume that the path argument has the following form, where any
* or all of the components may be missing.
*
* <drive><dir><fname><ext>
*
* and each of the components has the following expected form(s)
*
* drive:
* 0 to _MAX_DRIVE-1 characters, the last of which, if any, is a
* ':'
* dir:
* 0 to _MAX_DIR-1 characters in the form of an absolute path
* (leading '/' or '\') or relative path, the last of which, if
* any, must be a '/' or '\'. E.g -
* absolute path:
* \top\next\last\ ; or
* /top/next/last/
* relative path:
* top\next\last\ ; or
* top/next/last/
* Mixed use of '/' and '\' within a path is also tolerated
* fname:
* 0 to _MAX_FNAME-1 characters not including the '.' character
* ext:
* 0 to _MAX_EXT-1 characters where, if any, the first must be a
* '.'
*
*/
/* extract drive letter and :, if any */
if ((_tcslen(path) >= (_MAX_DRIVE - 2)) && (*(path + _MAX_DRIVE - 2) == _T(':'))) {
if (drive) {
_tcsncpy(drive, path, _MAX_DRIVE - 1);
*(drive + _MAX_DRIVE-1) = _T('\0');
}
path += _MAX_DRIVE - 1;
}
else if (drive) {
*drive = _T('\0');
}
/* extract path string, if any. Path now points to the first character
* of the path, if any, or the filename or extension, if no path was
* specified. Scan ahead for the last occurence, if any, of a '/' or
* '\' path separator character. If none is found, there is no path.
* We will also note the last '.' character found, if any, to aid in
* handling the extension.
*/
for (last_slash = NULL, p = (_TSCHAR *)path; *p; p++) {
#ifdef _MBCS
if (_ISLEADBYTE (*p))
p++;
else {
#endif /* _MBCS */
if (*p == _T('/') || *p == _T('\\'))
/* point to one beyond for later copy */
last_slash = p + 1;
else if (*p == _T('.'))
dot = p;
#ifdef _MBCS
}
#endif /* _MBCS */
}
if (last_slash) {
/* found a path - copy up through last_slash or max. characters
* allowed, whichever is smaller
*/
if (dir) {
len = __min(((char *)last_slash - (char *)path) / sizeof(_TSCHAR),
(_MAX_DIR - 1));
_tcsncpy(dir, path, len);
*(dir + len) = _T('\0');
}
path = last_slash;
}
else if (dir) {
/* no path found */
*dir = _T('\0');
}
/* extract file name and extension, if any. Path now points to the
* first character of the file name, if any, or the extension if no
* file name was given. Dot points to the '.' beginning the extension,
* if any.
*/
if (dot && (dot >= path)) {
/* found the marker for an extension - copy the file name up to
* the '.'.
*/
if (fname) {
len = __min(((char *)dot - (char *)path) / sizeof(_TSCHAR),
(_MAX_FNAME - 1));
_tcsncpy(fname, path, len);
*(fname + len) = _T('\0');
}
/* now we can get the extension - remember that p still points
* to the terminating nul character of path.
*/
if (ext) {
len = __min(((char *)p - (char *)dot) / sizeof(_TSCHAR),
(_MAX_EXT - 1));
_tcsncpy(ext, dot, len);
*(ext + len) = _T('\0');
}
}
else {
/* found no extension, give empty extension and copy rest of
* string into fname.
*/
if (fname) {
len = __min(((char *)p - (char *)path) / sizeof(_TSCHAR),
(_MAX_FNAME - 1));
_tcsncpy(fname, path, len);
*(fname + len) = _T('\0');
}
if (ext) {
*ext = _T('\0');
}
}
}
#endif // WINCE
#ifndef DPNBUILD_NOREGISTRY
//**********************************************************************
// ------------------------------
// ReadSettingsFromRegistry - read custom registry keys
//
// Entry: Nothing
//
// Exit: Nothing
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "ReadSettingsFromRegistry"
static void ReadSettingsFromRegistry( void )
{
CRegistry RegObject;
CRegistry RegObjectTemp;
CRegistry RegObjectAppEntry;
DWORD dwRegValue;
BOOL fGotPath;
WCHAR wszExePath[_MAX_PATH];
#ifndef UNICODE
char szExePath[_MAX_PATH];
#endif // !UNICODE
if ( RegObject.Open( HKEY_LOCAL_MACHINE, g_RegistryBase ) != FALSE )
{
//
// Find out the current process name.
//
#ifdef UNICODE
if (GetModuleFileName(NULL, wszExePath, _MAX_PATH) > 0)
{
DPFX(DPFPREP, 3, "Loading DLL in process: %ls", wszExePath);
_tsplitpath( wszExePath, NULL, NULL, wszExePath, NULL );
fGotPath = TRUE;
}
#else // ! UNICODE
if (GetModuleFileName(NULL, szExePath, _MAX_PATH) > 0)
{
HRESULT hr;
DPFX(DPFPREP, 3, "Loading DLL in process: %hs", szExePath);
_tsplitpath( szExePath, NULL, NULL, szExePath, NULL );
dwRegValue = _MAX_PATH;
hr = STR_AnsiToWide(szExePath, -1, wszExePath, &dwRegValue );
if ( hr == DPN_OK )
{
//
// Successfully converted ANSI path to Wide characters.
//
fGotPath = TRUE;
}
else
{
//
// Couldn't convert ANSI path to Wide characters
//
fGotPath = FALSE;
}
}
#endif // ! UNICODE
else
{
//
// Couldn't get current process path.
//
fGotPath = FALSE;
}
//
// read receive buffer size
//
if ( RegObject.ReadDWORD( g_RegistryKeyReceiveBufferSize, &dwRegValue ) != FALSE )
{
g_fWinsockReceiveBufferSizeOverridden = TRUE;
g_iWinsockReceiveBufferSize = dwRegValue;
}
#ifndef DPNBUILD_ONLYONETHREAD
//
// read default threads
//
if ( RegObject.ReadDWORD( g_RegistryKeyThreadCount, &dwRegValue ) != FALSE )
{
g_iThreadCount = dwRegValue;
}
//
// if thread count is zero, use the 'default' for the system
//
if ( g_iThreadCount == 0 )
{
g_iThreadCount = DEFAULT_THREADS_PER_PROCESSOR;
#ifndef DPNBUILD_ONLYONEPROCESSOR
SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);
g_iThreadCount *= SystemInfo.dwNumberOfProcessors;
#endif // ! DPNBUILD_ONLYONEPROCESSOR
}
#endif // ! DPNBUILD_ONLYONETHREAD
#if ((! defined(DPNBUILD_NOWINSOCK2)) && (! defined(DPNBUILD_ONLYWINSOCK2)))
//
// Winsock2 9x option
//
if (RegObject.ReadDWORD( g_RegistryKeyWinsockVersion, &dwRegValue ))
{
switch (dwRegValue)
{
case 0:
{
DPFX(DPFPREP, 1, "Explicitly using available Winsock version.");
g_dwWinsockVersion = dwRegValue;
break;
}
case 1:
{
DPFX(DPFPREP, 1, "Explicitly using Winsock 1 only.");
g_dwWinsockVersion = dwRegValue;
break;
}
case 2:
{
DPFX(DPFPREP, 1, "Explicitly using Winsock 2 (when available).");
g_dwWinsockVersion = dwRegValue;
break;
}
default:
{
DPFX(DPFPREP, 0, "Ignoring invalid Winsock version setting (%u).", dwRegValue);
break;
}
}
}
#endif // ! DPNBUILD_NOWINSOCK2 and ! DPNBUILD_ONLYWINSOCK2
#ifndef DPNBUILD_NONATHELP
//
// get global NAT traversal disablers, ignore registry reading error
//
if (RegObject.ReadBOOL( g_RegistryKeyDisableDPNHGatewaySupport, &g_fDisableDPNHGatewaySupport ))
{
if (g_fDisableDPNHGatewaySupport)
{
DPFX(DPFPREP, 1, "Disabling NAT Help gateway support.");
}
else
{
DPFX(DPFPREP, 1, "Explicitly not disabling NAT Help gateway support.");
}
}
if (RegObject.ReadBOOL( g_RegistryKeyDisableDPNHFirewallSupport, &g_fDisableDPNHFirewallSupport ))
{
if (g_fDisableDPNHFirewallSupport)
{
DPFX(DPFPREP, 1, "Disabling NAT Help firewall support.");
}
else
{
DPFX(DPFPREP, 1, "Explicitly not disabling NAT Help firewall support.");
}
}
#endif // DPNBUILD_NONATHELP
#if ((defined(WINNT)) && (! defined(DPNBUILD_NOMULTICAST)))
//
// get global MADCAP API disabler, ignore registry reading error
//
if (RegObject.ReadBOOL( g_RegistryKeyDisableMadcapSupport, &g_fDisableMadcapSupport ))
{
if (g_fDisableMadcapSupport)
{
DPFX(DPFPREP, 1, "Disabling MADCAP support.");
}
else
{
DPFX(DPFPREP, 1, "Explicitly not disabling MADCAP support.");
}
}
#endif // WINNT and not DPNBUILD_NOMULTICAST
//
// If we have an app name, try opening the subkey and looking up the app
// to see if enums are disabled, whether we should disconnect based on
// ICMPs, and which IP protocol families to use.
//
if ( fGotPath )
{
if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyAppsToIgnoreEnums, TRUE, FALSE ) )
{
RegObjectTemp.ReadBOOL( wszExePath, &g_fIgnoreEnums );
RegObjectTemp.Close();
if ( g_fIgnoreEnums )
{
DPFX(DPFPREP, 0, "Ignoring all enumerations (app = %ls).", wszExePath);
}
else
{
DPFX(DPFPREP, 2, "Not ignoring all enumerations (app = %ls).", wszExePath);
}
}
if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyAppsToDisconnectOnICMP, TRUE, FALSE ) )
{
RegObjectTemp.ReadBOOL( wszExePath, &g_fDisconnectOnICMP );
RegObjectTemp.Close();
if ( g_fDisconnectOnICMP )
{
DPFX(DPFPREP, 0, "Disconnecting upon receiving ICMP port not reachable messages (app = %ls).", wszExePath);
}
else
{
DPFX(DPFPREP, 2, "Not disconnecting upon receiving ICMP port not reachable messages (app = %ls).", wszExePath);
}
}
#ifndef DPNBUILD_NONATHELP
if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyTraversalModeSettings, TRUE, FALSE ) )
{
//
// Read the global default traversal mode.
//
if ( RegObjectTemp.ReadDWORD( g_RegistryKeyDefaultTraversalMode, &dwRegValue ) != FALSE )
{
switch (dwRegValue)
{
case DPNA_TRAVERSALMODE_NONE:
case DPNA_TRAVERSALMODE_PORTREQUIRED:
case DPNA_TRAVERSALMODE_PORTRECOMMENDED:
{
g_dwDefaultTraversalMode = dwRegValue;
DPFX(DPFPREP, 1, "Using global default traversal mode %u.",
g_dwDefaultTraversalMode);
break;
}
case (DPNA_TRAVERSALMODE_NONE | FORCE_TRAVERSALMODE_BIT):
case (DPNA_TRAVERSALMODE_PORTREQUIRED | FORCE_TRAVERSALMODE_BIT):
case (DPNA_TRAVERSALMODE_PORTRECOMMENDED | FORCE_TRAVERSALMODE_BIT):
{
g_dwDefaultTraversalMode = dwRegValue;
DPFX(DPFPREP, 1, "Forcing global traversal mode %u.",
g_dwDefaultTraversalMode);
break;
}
default:
{
DPFX(DPFPREP, 0, "Ignoring invalid global default traversal mode (%u).",
dwRegValue);
break;
}
}
}
//
// Override with the per app setting.
//
if ( RegObjectTemp.ReadDWORD( wszExePath, &dwRegValue ) != FALSE )
{
switch (dwRegValue)
{
case DPNA_TRAVERSALMODE_NONE:
case DPNA_TRAVERSALMODE_PORTREQUIRED:
case DPNA_TRAVERSALMODE_PORTRECOMMENDED:
{
g_dwDefaultTraversalMode = dwRegValue;
DPFX(DPFPREP, 1, "Using default traversal mode %u (app = %ls).",
g_dwDefaultTraversalMode, wszExePath);
break;
}
case (DPNA_TRAVERSALMODE_NONE | FORCE_TRAVERSALMODE_BIT):
case (DPNA_TRAVERSALMODE_PORTREQUIRED | FORCE_TRAVERSALMODE_BIT):
case (DPNA_TRAVERSALMODE_PORTRECOMMENDED | FORCE_TRAVERSALMODE_BIT):
{
g_dwDefaultTraversalMode = dwRegValue;
DPFX(DPFPREP, 1, "Forcing traversal mode %u (app = %ls).",
g_dwDefaultTraversalMode, wszExePath);
break;
}
default:
{
DPFX(DPFPREP, 0, "Ignoring invalid default traversal mode (%u, app %ls).",
dwRegValue, wszExePath);
break;
}
}
}
RegObjectTemp.Close();
}
#endif // DPNBUILD_NONATHELP
#ifndef DPNBUILD_NOIPV6
if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyIPAddressFamilySettings, TRUE, FALSE ) )
{
//
// Read the global IP address family setting.
//
if ( RegObjectTemp.ReadDWORD( g_RegistryKeyDefaultIPAddressFamily, &dwRegValue ) != FALSE )
{
switch (dwRegValue)
{
case PF_UNSPEC:
case PF_INET:
case PF_INET6:
{
g_iIPAddressFamily = dwRegValue;
DPFX(DPFPREP, 1, "Using IP address family %i global setting.",
g_iIPAddressFamily);
break;
}
default:
{
DPFX(DPFPREP, 0, "Ignoring invalid IP address family global setting (%u).",
dwRegValue);
break;
}
}
}
//
// Override with the per app setting.
//
if ( RegObjectTemp.ReadDWORD( wszExePath, &dwRegValue ) != FALSE )
{
switch (dwRegValue)
{
case PF_UNSPEC:
case PF_INET:
case PF_INET6:
{
g_iIPAddressFamily = dwRegValue;
DPFX(DPFPREP, 1, "Using IP address family %i (app = %ls).",
g_iIPAddressFamily, wszExePath);
break;
}
default:
{
DPFX(DPFPREP, 0, "Ignoring invalid IP address family setting (%u, app %ls).",
dwRegValue, wszExePath);
break;
}
}
}
RegObjectTemp.Close();
}
#endif // ! DPNBUILD_NOIPV6
}
//
// Get the proxy support options, ignore registry reading error.
//
#ifndef DPNBUILD_NOWINSOCK2
if (RegObject.ReadBOOL( g_RegistryKeyDontAutoDetectProxyLSP, &g_fDontAutoDetectProxyLSP ))
{
if (g_fDontAutoDetectProxyLSP)
{
DPFX(DPFPREP, 1, "Not auto-detected ISA Proxy LSP.");
}
else
{
DPFX(DPFPREP, 1, "Explicitly allowing auto-detection of ISA Proxy LSP.");
}
}
#endif // !DPNBUILD_NOWINSOCK2
if (RegObject.ReadBOOL( g_RegistryKeyTreatAllResponsesAsProxied, &g_fTreatAllResponsesAsProxied ))
{
if (g_fTreatAllResponsesAsProxied)
{
DPFX(DPFPREP, 1, "Treating all responses as proxied.");
}
else
{
DPFX(DPFPREP, 1, "Explicitly not treating all responses as proxied.");
}
}
//
// read MTU overrides
//
if ( RegObject.ReadDWORD( g_RegistryKeyMaxUserDataSize, &dwRegValue ) != FALSE )
{
if ((dwRegValue >= MIN_SEND_FRAME_SIZE) && (dwRegValue <= MAX_SEND_FRAME_SIZE))
{
//
// If the new user data size is smaller than the the default enum setting,
// shrink the enum size as well. It can be explicitly overridden below.
//
if (dwRegValue < g_dwMaxEnumDataSize)
{
g_dwMaxUserDataSize = dwRegValue;
g_dwMaxEnumDataSize = g_dwMaxUserDataSize - ENUM_PAYLOAD_HEADER_SIZE;
DPFX(DPFPREP, 1, "Max user data size is set to %u, assuming enum payload is %u.",
g_dwMaxUserDataSize, g_dwMaxEnumDataSize);
}
else
{
g_dwMaxUserDataSize = dwRegValue;
DPFX(DPFPREP, 1, "Max user data size is set to %u.",
g_dwMaxUserDataSize);
}
}
else
{
DPFX(DPFPREP, 0, "Ignoring invalid max user data size setting (%u).",
dwRegValue);
}
}
if ( RegObject.ReadDWORD( g_RegistryKeyMaxEnumDataSize, &dwRegValue ) != FALSE )
{
if ((dwRegValue >= (MIN_SEND_FRAME_SIZE - ENUM_PAYLOAD_HEADER_SIZE)) &&
(dwRegValue <= (MAX_SEND_FRAME_SIZE - ENUM_PAYLOAD_HEADER_SIZE)))
{
DPFX(DPFPREP, 1, "Max user data size is set to %u.",
dwRegValue);
g_dwMaxEnumDataSize = dwRegValue;
}
else
{
DPFX(DPFPREP, 0, "Ignoring invalid max user data size setting (%u).",
dwRegValue);
}
}
//
// read default port range
//
if ( RegObject.ReadDWORD( g_RegistryKeyBaseDPlayPort, &dwRegValue ) != FALSE )
{
if (dwRegValue < (WORD_MAX - 100)) // cannot be 65435 or above
{
g_wBaseDPlayPort = (WORD) dwRegValue;
DPFX(DPFPREP, 1, "Base DPlay default port set to %u.",
g_wBaseDPlayPort);
}
else
{
DPFX(DPFPREP, 0, "Ignoring invalid base DPlay default port setting (%u).",
dwRegValue);
}
}
if ( RegObject.ReadDWORD( g_RegistryKeyMaxDPlayPort, &dwRegValue ) != FALSE )
{
if (dwRegValue <= WORD_MAX) // cannot be greater than 65535
{
g_wMaxDPlayPort = (WORD) dwRegValue;
DPFX(DPFPREP, 1, "Max DPlay default port set to %u.",
g_wMaxDPlayPort);
}
else
{
DPFX(DPFPREP, 0, "Ignoring invalid max DPlay default port setting (%u).",
dwRegValue);
}
}
if (g_wMaxDPlayPort <= g_wBaseDPlayPort)
{
DPFX(DPFPREP, 1, "Max DPlay default port %u is less than or equal to base %u, setting to %u.",
g_wMaxDPlayPort, g_wBaseDPlayPort, (g_wBaseDPlayPort + 100));
g_wMaxDPlayPort = g_wBaseDPlayPort + 100;
}
RegObject.Close();
}
#pragma TODO(vanceo, "Be able to read while session is still running")
if ( RegObject.Open( HKEY_LOCAL_MACHINE, g_RegistryBase, TRUE, FALSE ) != FALSE )
{
if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyBannedIPv4Addresses, TRUE, FALSE ) )
{
DPFX(DPFPREP, 1, "Reading banned IPv4 addresses for all users.");
ReadBannedIPv4Addresses(&RegObjectTemp);
}
RegObject.Close();
}
if ( RegObject.Open( HKEY_CURRENT_USER, g_RegistryBase, TRUE, FALSE ) != FALSE )
{
if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyBannedIPv4Addresses, TRUE, FALSE ) )
{
DPFX(DPFPREP, 1, "Reading banned IPv4 addresses for current user.");
ReadBannedIPv4Addresses(&RegObjectTemp);
}
RegObject.Close();
}
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// BannedIPv4AddressCompareFunction - compare against another address
//
// Entry: Addresses to compare
//
// Exit: Bool indicating equality of two addresses
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "BannedIPv4AddressCompareFunction"
static BOOL BannedIPv4AddressCompareFunction( PVOID pvKey1, PVOID pvKey2 )
{
DWORD dwAddr1;
DWORD dwAddr2;
dwAddr1 = (DWORD) ((DWORD_PTR) pvKey1);
dwAddr2 = (DWORD) ((DWORD_PTR) pvKey2);
if (dwAddr1 == dwAddr2)
{
return TRUE;
}
return FALSE;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// BannedIPv4AddressHashFunction - hash address to N bits
//
// Entry: Count of bits to hash to
//
// Exit: Hashed value
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "BannedIPv4AddressHashFunction"
static DWORD BannedIPv4AddressHashFunction( PVOID pvKey, BYTE bBitDepth )
{
DWORD dwReturn;
UINT_PTR Temp;
DNASSERT( bBitDepth != 0 );
//
// initialize
//
dwReturn = 0;
//
// hash IP address
//
Temp = (DWORD) ((DWORD_PTR) pvKey);
do
{
dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
Temp >>= bBitDepth;
} while ( Temp != 0 );
return dwReturn;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// ReadBannedIPv4Addresses - reads in additional banned IPv4 addresses from the registry
//
// Entry: Pointer to registry object with values to read
//
// Exit: None
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "ReadBannedIPv4Addresses"
static void ReadBannedIPv4Addresses( CRegistry * pRegObject )
{
WCHAR wszIPAddress[16]; // nnn.nnn.nnn.nnn + NULL termination
char szIPAddress[16]; // nnn.nnn.nnn.nnn + NULL termination
DWORD dwSize;
DWORD dwIndex;
DWORD dwMask;
DWORD dwBit;
PVOID pvMask;
CSocketAddress SocketAddressTemp;
SOCKADDR_IN * psaddrinTemp;
memset(&SocketAddressTemp, 0, sizeof(SocketAddressTemp));
psaddrinTemp = (SOCKADDR_IN*) SocketAddressTemp.GetWritableAddress();
psaddrinTemp->sin_family = AF_INET;
psaddrinTemp->sin_port = 0xAAAA; // doesn't matter, just anything valid for IsValidUnicastAddress()
//
// Create the banned IPv4 addresses hash table, if we don't have it already.
//
if (g_pHashBannedIPv4Addresses == NULL)
{
g_pHashBannedIPv4Addresses = (CHashTable*) DNMalloc(sizeof(CHashTable));
if (g_pHashBannedIPv4Addresses == NULL)
{
DPFX(DPFPREP, 0, "Couldn't allocate banned IPv4 addresses hash table!");
goto Failure;
}
//
// Initialize the banned address hash with 2 entries and grow by a factor of 2.
//
if (! g_pHashBannedIPv4Addresses->Initialize(1,
#ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
1,
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
BannedIPv4AddressCompareFunction,
BannedIPv4AddressHashFunction))
{
DPFX(DPFPREP, 0, "Couldn't initialize banned IPv4 addresses hash table!");
goto Failure;
}
}
dwIndex = 0;
do
{
dwSize = 16;
if (! pRegObject->EnumValues( wszIPAddress, &dwSize, dwIndex ))
{
break;
}
//
// Read the mask associated with the IP address.
//
if ( pRegObject->ReadDWORD(wszIPAddress, &dwMask))
{
//
// Convert the IP address string to binary.
//
if (STR_jkWideToAnsi(szIPAddress, wszIPAddress, 16) == DPN_OK)
{
//
// Convert the IP address string to binary.
//
psaddrinTemp->sin_addr.S_un.S_addr = inet_addr(szIPAddress);
if (SocketAddressTemp.IsValidUnicastAddress(FALSE))
{
//
// Find the first mask bit. We expect the network byte order of
// the IP address to be opposite of host byte order.
//
dwBit = 0x80000000;
while (! (dwBit & dwMask))
{
psaddrinTemp->sin_addr.S_un.S_addr &= ~dwBit;
dwBit >>= 1;
if (dwBit <= 0x80)
{
break;
}
}
if (dwBit & dwMask)
{
//
// If the masked address is already in the hash, update the mask.
// This allows bans to be listed more than once.
//
if (g_pHashBannedIPv4Addresses->Find((PVOID) ((DWORD_PTR) psaddrinTemp->sin_addr.S_un.S_addr), &pvMask))
{
if (! g_pHashBannedIPv4Addresses->Remove((PVOID) ((DWORD_PTR) psaddrinTemp->sin_addr.S_un.S_addr)))
{
DPFX(DPFPREP, 0, "Couldn't remove masked IPv4 entry %u.%u.%u.%u from ban hash.",
psaddrinTemp->sin_addr.S_un.S_un_b.s_b1,
psaddrinTemp->sin_addr.S_un.S_un_b.s_b2,
psaddrinTemp->sin_addr.S_un.S_un_b.s_b3,
psaddrinTemp->sin_addr.S_un.S_un_b.s_b4);
dwMask = dwBit;
}
else
{
dwMask = ((DWORD) ((DWORD_PTR) pvMask)) | dwBit;
}
}
else
{
dwMask = dwBit;
}
//
// Add (or readd) the masked address to the hash.
//
if (g_pHashBannedIPv4Addresses->Insert((PVOID) ((DWORD_PTR) psaddrinTemp->sin_addr.S_un.S_addr), (PVOID) ((DWORD_PTR) dwMask)))
{
g_dwBannedIPv4Masks |= dwBit;
DPFX(DPFPREP, 5, "Added (or readded) %ls (bits = 0x%08x, masked IPv4 entry %u.%u.%u.%u) to ban hash.",
wszIPAddress,
dwMask,
psaddrinTemp->sin_addr.S_un.S_un_b.s_b1,
psaddrinTemp->sin_addr.S_un.S_un_b.s_b2,
psaddrinTemp->sin_addr.S_un.S_un_b.s_b3,
psaddrinTemp->sin_addr.S_un.S_un_b.s_b4);
}
else
{
DPFX(DPFPREP, 0, "Couldn't add %ls (bits = 0x%08x, masked IPv4 entry %u.%u.%u.%u) to ban hash!",
wszIPAddress,
dwMask,
psaddrinTemp->sin_addr.S_un.S_un_b.s_b1,
psaddrinTemp->sin_addr.S_un.S_un_b.s_b2,
psaddrinTemp->sin_addr.S_un.S_un_b.s_b3,
psaddrinTemp->sin_addr.S_un.S_un_b.s_b4);
}
}
else
{
DPFX(DPFPREP, 0, "Ignoring invalid banned IPv4 entry \"%ls\" (mask = 0x%08x)!",
wszIPAddress, dwMask);
}
}
else
{
DPFX(DPFPREP, 0, "Ignoring invalid banned IPv4 entry \"%ls\" (mask = 0x%08x)!",
wszIPAddress, dwMask);
}
}
else
{
DPFX(DPFPREP, 0, "Couldn't convert banned IPv4 entry \"%ls\" (mask = 0x%08x) to ANSI!",
wszIPAddress, dwMask);
}
}
else
{
DPFX(DPFPREP, 0, "Couldn't read banned IPv4 entry \"%ls\"!", wszIPAddress);
}
dwIndex++;
}
while (TRUE);
DPFX(DPFPREP, 2, "There are now a total of %u IPv4 addresses to ban, mask bits = 0x%08x.",
g_pHashBannedIPv4Addresses->GetEntryCount(),
g_dwBannedIPv4Masks);
Exit:
return;
Failure:
goto Exit;
}
//**********************************************************************
#endif // ! DPNBUILD_NOREGISTRY
//**********************************************************************
// ------------------------------
// InitProcessGlobals - initialize the global items needed for the SP to operate
//
// Entry: Nothing
//
// Exit: Boolean indicating success
// TRUE = success
// FALSE = failure
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "InitProcessGlobals"
BOOL InitProcessGlobals( void )
{
BOOL fReturn;
BOOL fCriticalSectionInitialized;
#ifdef _XBOX
BOOL fRefcountXnKeysInitted;
#endif // _XBOX
//
// initialize
//
fReturn = TRUE;
fCriticalSectionInitialized = FALSE;
#ifdef _XBOX
fRefcountXnKeysInitted = FALSE;
#endif // _XBOX
#ifdef DBG
g_blDPNWSockCritSecsHeld.Initialize();
#endif // DBG
#ifndef DPNBUILD_NOREGISTRY
ReadSettingsFromRegistry();
#endif // ! DPNBUILD_NOREGISTRY
if ( DNInitializeCriticalSection( &g_InterfaceGlobalsLock ) == FALSE )
{
fReturn = FALSE;
goto Failure;
}
DebugSetCriticalSectionGroup( &g_InterfaceGlobalsLock, &g_blDPNWSockCritSecsHeld ); // separate dpnwsock CSes from the rest of DPlay's CSes
fCriticalSectionInitialized = TRUE;
if ( InitializePools() == FALSE )
{
fReturn = FALSE;
goto Failure;
}
#ifdef _XBOX
#pragma BUGBUG(vanceo, "Find way to retrieve value from XNet")
if ( InitializeRefcountXnKeys(4) == FALSE )
{
fReturn = FALSE;
goto Failure;
}
fRefcountXnKeysInitted = TRUE;
#endif // _XBOX
DNASSERT( g_pThreadPool == NULL );
Exit:
return fReturn;
Failure:
#ifdef _XBOX
if ( fRefcountXnKeysInitted )
{
CleanupRefcountXnKeys();
fRefcountXnKeysInitted = FALSE;
}
#endif // _XBOX
DeinitializePools();
if ( fCriticalSectionInitialized != FALSE )
{
DNDeleteCriticalSection( &g_InterfaceGlobalsLock );
fCriticalSectionInitialized = FALSE;
}
goto Exit;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// DeinitProcessGlobals - deinitialize the global items
//
// Entry: Nothing
//
// Exit: Nothing
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DeinitProcessGlobals"
void DeinitProcessGlobals( void )
{
DNASSERT( g_pThreadPool == NULL );
DNASSERT( g_iThreadPoolRefCount == 0 );
#ifndef DPNBUILD_NOREGISTRY
if (g_pHashBannedIPv4Addresses != NULL)
{
g_pHashBannedIPv4Addresses->RemoveAll();
g_pHashBannedIPv4Addresses->Deinitialize();
DNFree(g_pHashBannedIPv4Addresses);
g_pHashBannedIPv4Addresses = NULL;
g_dwBannedIPv4Masks = 0;
}
#endif // ! DPNBUILD_NOREGISTRY
#ifdef _XBOX
CleanupRefcountXnKeys();
#endif // _XBOX
DeinitializePools();
DNDeleteCriticalSection( &g_InterfaceGlobalsLock );
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// LoadWinsock - load Winsock module into memory
//
// Entry: Nothing
//
// Exit: Boolean indicating success
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "LoadWinsock"
BOOL LoadWinsock( void )
{
BOOL fReturn = TRUE;
int iResult;
DNEnterCriticalSection( &g_InterfaceGlobalsLock );
if ( g_iWinsockRefCount == 0 )
{
//
// initialize the bindings to Winsock
//
iResult = DWSInitWinSock();
if ( iResult != 0 ) // failure
{
DPFX(DPFPREP, 0, "Problem binding dynamic winsock function (err = %i)!", iResult );
fReturn = FALSE;
goto Failure;
}
DPFX(DPFPREP, 6, "Successfully bound dynamic WinSock functions." );
}
DNASSERT(g_iWinsockRefCount >= 0);
DNInterlockedIncrement( const_cast<LONG*>(&g_iWinsockRefCount) );
Exit:
DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
return fReturn;
Failure:
goto Exit;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// UnloadWinsock - unload Winsock module
//
// Entry: Nothing
//
// Exit: Nothing
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "UnloadWinsock"
void UnloadWinsock( void )
{
DNEnterCriticalSection( &g_InterfaceGlobalsLock );
DNASSERT(g_iWinsockRefCount > 0);
if ( DNInterlockedDecrement( const_cast<LONG*>(&g_iWinsockRefCount) ) == 0 )
{
DPFX(DPFPREP, 6, "Unbinding dynamic WinSock functions.");
DWSFreeWinSock();
}
DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
}
//**********************************************************************
#ifndef DPNBUILD_NONATHELP
//**********************************************************************
// ------------------------------
// LoadNATHelp - create and initialize NAT Help object(s)
//
// Entry: Nothing
//
// Exit: TRUE if some objects were successfully loaded, FALSE otherwise
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "LoadNATHelp"
BOOL LoadNATHelp(void)
{
BOOL fReturn;
HRESULT hr;
#ifndef DPNBUILD_ONLYONENATHELP
CRegistry RegEntry;
CRegistry RegSubentry;
DWORD dwMaxKeyLen;
WCHAR * pwszKeyName = NULL;
DWORD dwEnumIndex;
DWORD dwKeyLen;
GUID guid;
#endif // ! DPNBUILD_ONLYONENATHELP
DWORD dwDirectPlay8Priority;
DWORD dwDirectPlay8InitFlags;
DWORD dwNumLoaded;
DNEnterCriticalSection(&g_InterfaceGlobalsLock);
if ( g_iNATHelpRefCount == 0 )
{
#ifndef DPNBUILD_ONLYONENATHELP
//
// Enumerate all the DirectPlayNAT Helpers.
//
if (! RegEntry.Open(HKEY_LOCAL_MACHINE, DIRECTPLAYNATHELP_REGKEY, TRUE, FALSE))
{
DPFX(DPFPREP, 0, "Couldn't open DirectPlayNATHelp registry key!");
goto Failure;
}
//
// Find length of largest subkey.
//
if (!RegEntry.GetMaxKeyLen(&dwMaxKeyLen))
{
DPFERR("RegistryEntry.GetMaxKeyLen() failed!");
goto Failure;
}
dwMaxKeyLen++; // Null terminator
DPFX(DPFPREP, 9, "dwMaxKeyLen = %ld", dwMaxKeyLen);
pwszKeyName = (WCHAR*) DNMalloc(dwMaxKeyLen * sizeof(WCHAR));
if (pwszKeyName == NULL)
{
DPFERR("Allocating key name buffer failed!");
goto Failure;
}
#endif // ! DPNBUILD_ONLYONENATHELP
//
// Allocate an array to hold the helper objects.
//
g_papNATHelpObjects = (IDirectPlayNATHelp**) DNMalloc(MAX_NUM_DIRECTPLAYNATHELPERS * sizeof(IDirectPlayNATHelp*));
if (g_papNATHelpObjects == NULL)
{
DPFERR("DNMalloc() failed");
goto Failure;
}
ZeroMemory(g_papNATHelpObjects,
(MAX_NUM_DIRECTPLAYNATHELPERS * sizeof(IDirectPlayNATHelp*)));
#ifndef DPNBUILD_ONLYONENATHELP
dwEnumIndex = 0;
#endif // ! DPNBUILD_ONLYONENATHELP
dwNumLoaded = 0;
//
// Enumerate the DirectPlay NAT helpers.
//
do
{
#ifdef DPNBUILD_ONLYONENATHELP
WCHAR * pwszKeyName;
pwszKeyName = L"UPnP";
dwDirectPlay8Priority = 1;
dwDirectPlay8InitFlags = 0; // default UPnP flags
#else // ! DPNBUILD_ONLYONENATHELP
dwKeyLen = dwMaxKeyLen;
if (! RegEntry.EnumKeys(pwszKeyName, &dwKeyLen, dwEnumIndex))
{
break;
}
dwEnumIndex++;
DPFX(DPFPREP, 8, "%ld - %ls (%ld)", dwEnumIndex, pwszKeyName, dwKeyLen);
if (!RegSubentry.Open(RegEntry, pwszKeyName, TRUE, FALSE))
{
DPFX(DPFPREP, 0, "Couldn't open subentry \"%ls\"! Skipping.", pwszKeyName);
continue;
}
//
// Read the DirectPlay8 priority
//
if (!RegSubentry.ReadDWORD(REGSUBKEY_DPNATHELP_DIRECTPLAY8PRIORITY, &dwDirectPlay8Priority))
{
DPFX(DPFPREP, 0, "RegSubentry.ReadDWORD \"%ls\\%ls\" failed! Skipping.",
pwszKeyName, REGSUBKEY_DPNATHELP_DIRECTPLAY8PRIORITY);
RegSubentry.Close();
continue;
}
//
// Read the DirectPlay8 initialization flags
//
if (!RegSubentry.ReadDWORD(REGSUBKEY_DPNATHELP_DIRECTPLAY8INITFLAGS, &dwDirectPlay8InitFlags))
{
DPFX(DPFPREP, 0, "RegSubentry.ReadDWORD \"%ls\\%ls\" failed! Defaulting to 0.",
pwszKeyName, REGSUBKEY_DPNATHELP_DIRECTPLAY8INITFLAGS);
dwDirectPlay8InitFlags = 0;
}
//
// Read the object's CLSID.
//
if (!RegSubentry.ReadGUID(REGSUBKEY_DPNATHELP_GUID, &guid))
{
DPFX(DPFPREP, 0,"RegSubentry.ReadGUID \"%ls\\%ls\" failed! Skipping.",
pwszKeyName, REGSUBKEY_DPNATHELP_GUID);
RegSubentry.Close();
continue;
}
//
// Close the subkey.
//
RegSubentry.Close();
//
// If this helper should be loaded, do so.
//
if (dwDirectPlay8Priority == 0)
{
DPFX(DPFPREP, 1, "DirectPlay NAT Helper \"%ls\" is not enabled for DirectPlay8.", pwszKeyName);
}
else
#endif // ! DPNBUILD_ONLYONENATHELP
{
#ifdef DPNBUILD_ONLYONENATHELP
//
// Try to create the NAT Help object. COM should have been
// initialized by now by someone else.
//
hr = COM_CoCreateInstance(CLSID_DirectPlayNATHelpUPnP,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDirectPlayNATHelp,
(LPVOID*) (&g_papNATHelpObjects[dwDirectPlay8Priority - 1]), FALSE);
#else // ! DPNBUILD_ONLYONENATHELP
//
// Make sure this priority is valid.
//
if (dwDirectPlay8Priority > MAX_NUM_DIRECTPLAYNATHELPERS)
{
DPFX(DPFPREP, 0, "Ignoring DirectPlay NAT helper \"%ls\" with invalid priority level set too high (%u > %u).",
pwszKeyName, dwDirectPlay8Priority, MAX_NUM_DIRECTPLAYNATHELPERS);
continue;
}
//
// Make sure this priority hasn't already been taken.
//
if (g_papNATHelpObjects[dwDirectPlay8Priority - 1] != NULL)
{
DPFX(DPFPREP, 0, "Ignoring DirectPlay NAT helper \"%ls\" with duplicate priority level %u (existing object = 0x%p).",
pwszKeyName, dwDirectPlay8Priority,
g_papNATHelpObjects[dwDirectPlay8Priority - 1]);
continue;
}
//
// Try to create the NAT Help object. COM should have been
// initialized by now by someone else.
//
hr = COM_CoCreateInstance(guid,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDirectPlayNATHelp,
(LPVOID*) (&g_papNATHelpObjects[dwDirectPlay8Priority - 1]), FALSE);
#endif // ! DPNBUILD_ONLYONENATHELP
if ( hr != S_OK )
{
DNASSERT( g_papNATHelpObjects[dwDirectPlay8Priority - 1] == NULL );
DPFX(DPFPREP, 0, "Failed to create \"%ls\" IDirectPlayNATHelp interface (error = 0x%lx)! Skipping.",
pwszKeyName, hr);
continue;
}
//
// Initialize NAT Help.
//
#ifndef DPNBUILD_NOREGISTRY
DNASSERT((! g_fDisableDPNHGatewaySupport) || (! g_fDisableDPNHFirewallSupport));
if (g_fDisableDPNHGatewaySupport)
{
dwDirectPlay8InitFlags |= DPNHINITIALIZE_DISABLEGATEWAYSUPPORT;
}
if (g_fDisableDPNHFirewallSupport)
{
dwDirectPlay8InitFlags |= DPNHINITIALIZE_DISABLELOCALFIREWALLSUPPORT;
}
#endif // ! DPNBUILD_NOREGISTRY
//
// Make sure the flags we're passing are valid.
//
if ((dwDirectPlay8InitFlags & (DPNHINITIALIZE_DISABLEGATEWAYSUPPORT | DPNHINITIALIZE_DISABLELOCALFIREWALLSUPPORT)) == (DPNHINITIALIZE_DISABLEGATEWAYSUPPORT | DPNHINITIALIZE_DISABLELOCALFIREWALLSUPPORT))
{
DPFX(DPFPREP, 1, "Not loading NAT Help \"%ls\" because both DISABLEGATEWAYSUPPORT and DISABLELOCALFIREWALLSUPPORT would have been specified (priority = %u, flags = 0x%lx).",
pwszKeyName, dwDirectPlay8Priority, dwDirectPlay8InitFlags);
IDirectPlayNATHelp_Release(g_papNATHelpObjects[dwDirectPlay8Priority - 1]);
g_papNATHelpObjects[dwDirectPlay8Priority - 1] = NULL;
continue;
}
hr = IDirectPlayNATHelp_Initialize(g_papNATHelpObjects[dwDirectPlay8Priority - 1], dwDirectPlay8InitFlags);
if (hr != DPNH_OK)
{
DPFX(DPFPREP, 0, "Couldn't initialize NAT Help \"%ls\" (error = 0x%lx)! Skipping.",
pwszKeyName, hr);
IDirectPlayNATHelp_Release(g_papNATHelpObjects[dwDirectPlay8Priority - 1]);
g_papNATHelpObjects[dwDirectPlay8Priority - 1] = NULL;
continue;
}
DPFX(DPFPREP, 8, "Initialized NAT Help \"%ls\" (priority = %u, flags = 0x%lx, object = 0x%p).",
pwszKeyName, dwDirectPlay8Priority, dwDirectPlay8InitFlags, g_papNATHelpObjects[dwDirectPlay8Priority - 1]);
dwNumLoaded++;
}
}
#ifdef DPNBUILD_ONLYONENATHELP
while (FALSE);
#else // ! DPNBUILD_ONLYONENATHELP
while (TRUE);
#endif // ! DPNBUILD_ONLYONENATHELP
//
// If we didn't load any NAT helper objects, free up the memory.
//
if (dwNumLoaded == 0)
{
DNFree(g_papNATHelpObjects);
g_papNATHelpObjects = NULL;
//
// We never got anything. Fail.
//
goto Failure;
}
DPFX(DPFPREP, 8, "Loaded %u DirectPlay NAT Helper objects.", dwNumLoaded);
}
else
{
DPFX(DPFPREP, 8, "Already loaded NAT Help objects.");
}
//
// We have the interface globals lock, don't need DNInterlockedIncrement.
//
g_iNATHelpRefCount++;
//
// We succeeded.
//
fReturn = TRUE;
Exit:
DNLeaveCriticalSection(&g_InterfaceGlobalsLock);
#ifndef DPNBUILD_ONLYONENATHELP
if (pwszKeyName != NULL)
{
DNFree(pwszKeyName);
pwszKeyName = NULL;
}
#endif // ! DPNBUILD_ONLYONENATHELP
return fReturn;
Failure:
//
// We can only fail during the first initialize, so therefore we will never be freeing
// g_papNATHelpObjects when we didn't allocate it in this function.
//
if (g_papNATHelpObjects != NULL)
{
DNFree(g_papNATHelpObjects);
g_papNATHelpObjects = NULL;
}
fReturn = FALSE;
goto Exit;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// UnloadNATHelp - release the NAT Help object
//
// Entry: Nothing
//
// Exit: Nothing
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "UnloadNATHelp"
void UnloadNATHelp(void)
{
DWORD dwTemp;
DNEnterCriticalSection(&g_InterfaceGlobalsLock);
//
// We have the interface globals lock, don't need DNInterlockedDecrement.
//
DNASSERT(g_iNATHelpRefCount > 0);
g_iNATHelpRefCount--;
if (g_iNATHelpRefCount == 0 )
{
HRESULT hr;
DNASSERT(g_papNATHelpObjects != NULL);
for(dwTemp = 0; dwTemp < MAX_NUM_DIRECTPLAYNATHELPERS; dwTemp++)
{
if (g_papNATHelpObjects[dwTemp] != NULL)
{
DPFX(DPFPREP, 8, "Closing NAT Help object priority %u (0x%p).",
dwTemp, g_papNATHelpObjects[dwTemp]);
hr = IDirectPlayNATHelp_Close(g_papNATHelpObjects[dwTemp], 0);
if (hr != DPNH_OK)
{
DPFX(DPFPREP, 0, "Problem closing NAT Help object %u (error = 0x%lx), continuing.",
dwTemp, hr);
}
IDirectPlayNATHelp_Release(g_papNATHelpObjects[dwTemp]);
g_papNATHelpObjects[dwTemp] = NULL;
}
}
DNFree(g_papNATHelpObjects);
g_papNATHelpObjects = NULL;
}
else
{
DPFX(DPFPREP, 8, "NAT Help object(s) still have %i references.",
g_iNATHelpRefCount);
}
DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
}
//**********************************************************************
#endif // DPNBUILD_NONATHELP
#if ((defined(WINNT)) && (! defined(DPNBUILD_NOMULTICAST)))
//**********************************************************************
// ------------------------------
// LoadMADCAP - create and initialize MADCAP API
//
// Entry: Nothing
//
// Exit: TRUE if the API was successfully loaded, FALSE otherwise
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "LoadMadcap"
BOOL LoadMadcap(void)
{
BOOL fReturn;
DWORD dwError;
DWORD dwMadcapVersion;
#ifndef DPNBUILD_NOREGISTRY
DNASSERT(! g_fDisableMadcapSupport);
#endif // ! DPNBUILD_NOREGISTRY
DNEnterCriticalSection(&g_InterfaceGlobalsLock);
if ( g_iMadcapRefCount == 0 )
{
//
// Initialize the MADCAP API.
//
dwMadcapVersion = MCAST_API_CURRENT_VERSION;
dwError = McastApiStartup(&dwMadcapVersion);
if (dwError != ERROR_SUCCESS)
{
DPFX(DPFPREP, 0, "Failed starting MADCAP version %u (err = %u)!",
MCAST_API_CURRENT_VERSION, dwError);
goto Failure;
}
DPFX(DPFPREP, 5, "Using MADCAP version %u (supported version = %u).",
MCAST_API_CURRENT_VERSION, dwMadcapVersion);
//
// Create a unique client ID.
//
g_mcClientUid.ClientUID = g_abClientID;
g_mcClientUid.ClientUIDLength = sizeof(g_abClientID);
dwError = McastGenUID(&g_mcClientUid);
if (dwError != ERROR_SUCCESS)
{
DPFX(DPFPREP, 0, "Failed creating MADCAP client ID (err = %u)!",
dwError);
goto Failure;
}
}
else
{
DPFX(DPFPREP, 8, "Already loaded MADCAP.");
}
//
// We have the interface globals lock, don't need DNInterlockedIncrement.
//
g_iMadcapRefCount++;
//
// We succeeded.
//
fReturn = TRUE;
Exit:
DNLeaveCriticalSection(&g_InterfaceGlobalsLock);
return fReturn;
Failure:
fReturn = FALSE;
goto Exit;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// UnloadMadcap - release the MADCAP interface
//
// Entry: Nothing
//
// Exit: Nothing
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "UnloadMadcap"
void UnloadMadcap(void)
{
DNEnterCriticalSection(&g_InterfaceGlobalsLock);
//
// We have the interface globals lock, don't need DNInterlockedDecrement.
//
DNASSERT(g_iMadcapRefCount > 0);
g_iMadcapRefCount--;
if (g_iMadcapRefCount == 0 )
{
DPFX(DPFPREP, 5, "Unloading MADCAP API.");
McastApiCleanup();
}
else
{
DPFX(DPFPREP, 8, "MADCAP API still has %i references.",
g_iMadcapRefCount);
}
DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
}
//**********************************************************************
#endif // WINNT and not DPNBUILD_NOMULTICAST
//**********************************************************************
// ------------------------------
// CreateSPData - create instance data for SP
//
// Entry: Pointer to pointer to SPData
// Interface type
// Pointer to COM interface vtable
//
// Exit: Error code
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CreateSPData"
HRESULT CreateSPData( CSPData **const ppSPData,
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
const short sSPType,
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
const XDP8CREATE_PARAMS * const pDP8CreateParams,
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
IDP8ServiceProviderVtbl *const pVtbl )
{
HRESULT hr;
CSPData *pSPData;
DNASSERT( ppSPData != NULL );
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
DNASSERT( pDP8CreateParams != NULL );
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
DNASSERT( pVtbl != NULL );
//
// initialize
//
hr = DPN_OK;
*ppSPData = NULL;
pSPData = NULL;
//
// create data
//
pSPData = (CSPData*) DNMalloc(sizeof(CSPData));
if ( pSPData == NULL )
{
hr = DPNERR_OUTOFMEMORY;
DPFX(DPFPREP, 0, "Cannot create data for Winsock interface!" );
goto Failure;
}
hr = pSPData->Initialize( pVtbl
#if ((! defined(DPNBUILD_NOIPV6)) || (! defined(DPNBUILD_NOIPX)))
,sSPType
#endif // ! DPNBUILD_NOIPV6 or ! DPNBUILD_NOIPX
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
,pDP8CreateParams
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
);
if ( hr != DPN_OK )
{
DPFX(DPFPREP, 0, "Failed to intialize SP data!" );
DisplayDNError( 0, hr );
goto Failure;
}
DPFX(DPFPREP, 6, "Created SP Data object 0x%p.", pSPData);
pSPData->AddRef(); // reference is now 1
*ppSPData = pSPData;
Exit:
return hr;
Failure:
if ( pSPData != NULL )
{
DNFree(pSPData);
pSPData = NULL;
}
DPFX(DPFPREP, 0, "Problem with CreateSPData (err = 0x%lx)!", hr);
DisplayDNError( 0, hr );
goto Exit;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// InitializeInterfaceGlobals - perform global initialization for an interface.
//
// Entry: Pointer to SPData
//
// Exit: Error code
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "InitializeInterfaceGlobals"
HRESULT InitializeInterfaceGlobals( CSPData *const pSPData )
{
HRESULT hr;
CThreadPool *pThreadPool;
DNASSERT( pSPData != NULL );
//
// initialize
//
hr = DPN_OK;
pThreadPool = NULL;
DNEnterCriticalSection( &g_InterfaceGlobalsLock );
if ( g_pThreadPool == NULL )
{
DNASSERT( g_iThreadPoolRefCount == 0 );
g_pThreadPool = (CThreadPool*)g_ThreadPoolPool.Get();
if ( g_pThreadPool != NULL )
{
hr = g_pThreadPool->Initialize();
if ( hr != DPN_OK )
{
DPFX(DPFPREP, 0, "Initializing thread pool failed (err = 0x%lx)!", hr);
g_ThreadPoolPool.Release(g_pThreadPool);
g_pThreadPool = NULL;
hr = DPNERR_OUTOFMEMORY;
goto Failure;
}
else
{
g_pThreadPool->AddRef();
g_iThreadPoolRefCount++;
pThreadPool = g_pThreadPool;
}
}
}
else
{
DNASSERT( g_iThreadPoolRefCount != 0 );
g_iThreadPoolRefCount++;
g_pThreadPool->AddRef();
pThreadPool = g_pThreadPool;
}
Exit:
DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
pSPData->SetThreadPool( g_pThreadPool );
return hr;
Failure:
goto Exit;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// DeinitializeInterfaceGlobals - deinitialize thread pool and Rsip
//
// Entry: Pointer to service provider
//
// Exit: Nothing
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DeinitializeInterfaceGlobals"
void DeinitializeInterfaceGlobals( CSPData *const pSPData )
{
CThreadPool *pThreadPool;
DNASSERT( pSPData != NULL );
//
// initialize
//
pThreadPool = NULL;
//
// Process as little as possible inside the lock. If any of the items
// need to be released, pointers to them will be set.
//
DNEnterCriticalSection( &g_InterfaceGlobalsLock );
DNASSERT( g_pThreadPool != NULL );
DNASSERT( g_iThreadPoolRefCount != 0 );
DNASSERT( g_pThreadPool == pSPData->GetThreadPool() );
pThreadPool = pSPData->GetThreadPool();
//
// remove thread pool reference
//
DNASSERT( pThreadPool != NULL );
g_iThreadPoolRefCount--;
if ( g_iThreadPoolRefCount == 0 )
{
g_pThreadPool = NULL;
}
else
{
pThreadPool = NULL;
}
DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
//
// The thread pool will be cleaned up when all of the outstanding interfaces
// close.
//
}
//**********************************************************************
#ifndef DPNBUILD_NOIPV6
//**********************************************************************
// ------------------------------
// DNIpv6AddressToStringW - Stolen from RtlIpv6AddressToString
//
// Generates an IPv6 string literal corresponding to the address Addr.
// The shortened canonical forms are used (RFC 1884 etc).
// The basic string representation consists of 8 hex numbers
// separated by colons, with a couple embellishments:
// - a string of zero numbers (at most one) is replaced
// with a double-colon.
// - the last 32 bits are represented in IPv4-style dotted-octet notation
// if the address is a v4-compatible or ISATAP address.
//
// For example,
// ::
// ::1
// ::157.56.138.30
// ::ffff:156.56.136.75
// ff01::
// ff02::2
// 0:1:2:3:4:5:6:7
//
// Entry: S - Receives a pointer to the buffer in which to place the string literal
// Addr - Receives the IPv6 address
//
// Exit: Pointer to the null byte at the end of the string inserted.
// This can be used by the caller to easily append more information
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DNIpv6AddressToStringW"
LPWSTR DNIpv6AddressToStringW(const struct in6_addr *Addr, LPWSTR S)
{
int maxFirst, maxLast;
int curFirst, curLast;
int i;
int endHex = 8;
// Check for IPv6-compatible, IPv4-mapped, and IPv4-translated
// addresses
if ((Addr->s6_words[0] == 0) && (Addr->s6_words[1] == 0) &&
(Addr->s6_words[2] == 0) && (Addr->s6_words[3] == 0) &&
(Addr->s6_words[6] != 0)) {
if ((Addr->s6_words[4] == 0) &&
((Addr->s6_words[5] == 0) || (Addr->s6_words[5] == 0xffff)))
{
// compatible or mapped
S += _stprintf(S, _T("::%hs%u.%u.%u.%u"),
Addr->s6_words[5] == 0 ? "" : "ffff:",
Addr->s6_bytes[12], Addr->s6_bytes[13],
Addr->s6_bytes[14], Addr->s6_bytes[15]);
return S;
}
else if ((Addr->s6_words[4] == 0xffff) && (Addr->s6_words[5] == 0)) {
// translated
S += _stprintf(S, _T("::ffff:0:%u.%u.%u.%u"),
Addr->s6_bytes[12], Addr->s6_bytes[13],
Addr->s6_bytes[14], Addr->s6_bytes[15]);
return S;
}
}
// Find largest contiguous substring of zeroes
// A substring is [First, Last), so it's empty if First == Last.
maxFirst = maxLast = 0;
curFirst = curLast = 0;
// ISATAP EUI64 starts with 00005EFE (or 02005EFE)...
if (((Addr->s6_words[4] & 0xfffd) == 0) && (Addr->s6_words[5] == 0xfe5e)) {
endHex = 6;
}
for (i = 0; i < endHex; i++) {
if (Addr->s6_words[i] == 0) {
// Extend current substring
curLast = i+1;
// Check if current is now largest
if (curLast - curFirst > maxLast - maxFirst) {
maxFirst = curFirst;
maxLast = curLast;
}
}
else {
// Start a new substring
curFirst = curLast = i+1;
}
}
// Ignore a substring of length 1.
if (maxLast - maxFirst <= 1)
maxFirst = maxLast = 0;
// Write colon-separated words.
// A double-colon takes the place of the longest string of zeroes.
// All zeroes is just "::".
for (i = 0; i < endHex; i++) {
// Skip over string of zeroes
if ((maxFirst <= i) && (i < maxLast)) {
S += _stprintf(S, _T("::"));
i = maxLast-1;
continue;
}
// Need colon separator if not at beginning
if ((i != 0) && (i != maxLast))
S += _stprintf(S, _T(":"));
S += _stprintf(S, _T("%x"), NTOHS(Addr->s6_words[i])); // swap bytes
}
if (endHex < 8) {
S += _stprintf(S, _T(":%u.%u.%u.%u"),
Addr->s6_bytes[12], Addr->s6_bytes[13],
Addr->s6_bytes[14], Addr->s6_bytes[15]);
}
return S;
}
#endif // ! DPNBUILD_NOIPV6
//**********************************************************************
// ------------------------------
// AddInfoToBuffer - add an adapter info/multicast scope info structure to a packed buffer
//
// Entry: Pointer to packed buffer
// Pointer to adapter/scope name
// Pointer to adapter/scope guid
//
// Exit: Error code
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "AddInfoToBuffer"
HRESULT AddInfoToBuffer( CPackedBuffer *const pPackedBuffer,
const WCHAR *const pwszInfoName,
const GUID *const pInfoGUID,
const DWORD dwFlags )
{
HRESULT hr;
DPN_SERVICE_PROVIDER_INFO AdapterInfo;
#ifndef DPNBUILD_NOMULTICAST
DBG_CASSERT( sizeof( DPN_SERVICE_PROVIDER_INFO ) == sizeof( DPN_MULTICAST_SCOPE_INFO ) );
DBG_CASSERT( OFFSETOF( DPN_SERVICE_PROVIDER_INFO, dwFlags ) == OFFSETOF( DPN_MULTICAST_SCOPE_INFO, dwFlags ) );
DBG_CASSERT( OFFSETOF( DPN_SERVICE_PROVIDER_INFO, guid ) == OFFSETOF( DPN_MULTICAST_SCOPE_INFO, guid ) );
DBG_CASSERT( OFFSETOF( DPN_SERVICE_PROVIDER_INFO, pwszName ) == OFFSETOF( DPN_MULTICAST_SCOPE_INFO, pwszName ) );
DBG_CASSERT( OFFSETOF( DPN_SERVICE_PROVIDER_INFO, pvReserved ) == OFFSETOF( DPN_MULTICAST_SCOPE_INFO, pvReserved ) );
DBG_CASSERT( OFFSETOF( DPN_SERVICE_PROVIDER_INFO, dwReserved ) == OFFSETOF( DPN_MULTICAST_SCOPE_INFO, dwReserved ) );
#endif // ! DPNBUILD_NOMULTICAST
DNASSERT( pPackedBuffer != NULL );
DNASSERT( pwszInfoName != NULL );
DNASSERT( pInfoGUID != NULL );
//
// initialize
//
hr = DPN_OK;
memset( &AdapterInfo, 0x00, sizeof( AdapterInfo ) );
AdapterInfo.dwFlags = dwFlags;
AdapterInfo.guid = *pInfoGUID;
hr = pPackedBuffer->AddWCHARStringToBack( pwszInfoName );
if ( ( hr != DPNERR_BUFFERTOOSMALL ) && ( hr != DPN_OK ) )
{
DPFX(DPFPREP, 0, "Failed to add info name to buffer!" );
goto Failure;
}
AdapterInfo.pwszName = static_cast<WCHAR*>( pPackedBuffer->GetTailAddress() );
hr = pPackedBuffer->AddToFront( &AdapterInfo, sizeof( AdapterInfo ) );
Exit:
return hr;
Failure:
goto Exit;
}
//**********************************************************************
#ifdef _XBOX
typedef struct _REFCOUNTXNKEY
{
LONG lRefCount;
XNKID xnkid;
XNKEY xnkey;
} REFCOUNTXNKEY;
REFCOUNTXNKEY * g_paRefcountXnKeys = NULL;
DWORD g_dwMaxNumRefcountXnKeys = 0;
#undef DPF_MODNAME
#define DPF_MODNAME "InitializeRefcountXnKeys"
BOOL InitializeRefcountXnKeys(const DWORD dwKeyRegMax)
{
BOOL fResult;
DPFX(DPFPREP, 3, "Parameters: (%u)", dwKeyRegMax);
DNASSERT(dwKeyRegMax != 0);
DNASSERT(g_paRefcountXnKeys == NULL);
g_paRefcountXnKeys = (REFCOUNTXNKEY*) DNMalloc(dwKeyRegMax * sizeof(REFCOUNTXNKEY));
if (g_paRefcountXnKeys == NULL)
{
g_dwMaxNumRefcountXnKeys = 0;
fResult = FALSE;
}
else
{
memset(g_paRefcountXnKeys, 0, (dwKeyRegMax * sizeof(REFCOUNTXNKEY)));
g_dwMaxNumRefcountXnKeys = dwKeyRegMax;
fResult = TRUE;
}
DPFX(DPFPREP, 3, "Returning: [%i]", fResult);
return fResult;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CleanupRefcountXnKeys"
void WINAPI CleanupRefcountXnKeys(void)
{
#ifdef DBG
DWORD dwTemp;
DPFX(DPFPREP, 3, "Enter");
DNASSERT(g_paRefcountXnKeys != NULL);
for(dwTemp = 0; dwTemp < g_dwMaxNumRefcountXnKeys; dwTemp++)
{
DNASSERT(g_paRefcountXnKeys[dwTemp].lRefCount == 0);
}
#endif // DBG
DNFree(g_paRefcountXnKeys);
g_paRefcountXnKeys = NULL;
g_dwMaxNumRefcountXnKeys = 0;
DPFX(DPFPREP, 3, "Leave");
}
#undef DPF_MODNAME
#define DPF_MODNAME "RegisterRefcountXnKey"
INT WINAPI RegisterRefcountXnKey(const XNKID * pxnkid, const XNKEY * pxnkey)
{
int iReturn;
DWORD dwTemp;
DWORD dwIndex = -1;
DPFX(DPFPREP, 3, "Parameters: (0x%p, 0x%p)", pxnkid, pxnkey);
DNASSERT(pxnkid != NULL);
DNASSERT(pxnkey != NULL);
DNASSERT(g_paRefcountXnKeys != NULL);
for(dwTemp = 0; dwTemp < g_dwMaxNumRefcountXnKeys; dwTemp++)
{
if (g_paRefcountXnKeys[dwTemp].lRefCount > 0)
{
if (memcmp(pxnkid, &g_paRefcountXnKeys[dwTemp].xnkid, sizeof(XNKID)) == 0)
{
DPFX(DPFPREP, 1, "Key has already been registered.");
g_paRefcountXnKeys[dwTemp].lRefCount++;
iReturn = 0;
goto Exit;
}
}
else
{
DNASSERT(g_paRefcountXnKeys[dwTemp].lRefCount == 0);
if (dwIndex == -1)
{
dwIndex = dwTemp;
}
}
}
if (dwIndex == -1)
{
DPFX(DPFPREP, 0, "No more keys can be registered!");
DNASSERTX(! "No more keys can be registered!", 2);
iReturn = WSAENOBUFS;
goto Exit;
}
iReturn = XNetRegisterKey(pxnkid, pxnkey);
if (iReturn != 0)
{
DPFX(DPFPREP, 0, "Registering key failed!");
goto Exit;
}
DNASSERT(g_paRefcountXnKeys[dwIndex].lRefCount == 0);
g_paRefcountXnKeys[dwIndex].lRefCount = 1;
memcpy(&g_paRefcountXnKeys[dwIndex].xnkid, pxnkid, sizeof(XNKID));
memcpy(&g_paRefcountXnKeys[dwIndex].xnkey, pxnkey, sizeof(XNKEY));
Exit:
DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
return iReturn;
}
#undef DPF_MODNAME
#define DPF_MODNAME "UnregisterRefcountXnKey"
INT WINAPI UnregisterRefcountXnKey(const XNKID * pxnkid)
{
int iReturn;
DWORD dwTemp;
DPFX(DPFPREP, 3, "Parameters: (0x%p)", pxnkid);
DNASSERT(pxnkid != NULL);
DNASSERT(g_paRefcountXnKeys != NULL);
for(dwTemp = 0; dwTemp < g_dwMaxNumRefcountXnKeys; dwTemp++)
{
if (g_paRefcountXnKeys[dwTemp].lRefCount > 0)
{
if (memcmp(pxnkid, &g_paRefcountXnKeys[dwTemp].xnkid, sizeof(XNKID)) == 0)
{
g_paRefcountXnKeys[dwTemp].lRefCount--;
if (g_paRefcountXnKeys[dwTemp].lRefCount == 0)
{
iReturn = XNetUnregisterKey(pxnkid);
if (iReturn != 0)
{
DPFX(DPFPREP, 0, "Unregistering key failed!");
}
}
else
{
iReturn = 0;
}
goto Exit;
}
}
else
{
DNASSERT(g_paRefcountXnKeys[dwTemp].lRefCount == 0);
}
}
DPFX(DPFPREP, 0, "Key has not been registered!");
DNASSERTX(! "Key has not been registered!", 2);
iReturn = -1;
Exit:
DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
return iReturn;
}
#ifdef XBOX_ON_DESKTOP
typedef struct _SECURITYASSOCIATION
{
BOOL fInUse;
XNADDR xnaddr;
IN_ADDR inaddr;
} SECURITYASSOCIATION;
typedef struct _KEYENTRY
{
BOOL fInUse;
XNKID xnkid;
XNKEY xnkey;
SECURITYASSOCIATION * paSecurityAssociations;
} KEYENTRY;
KEYENTRY * g_paKeys = NULL;
DWORD g_dwMaxNumKeys = 0;
DWORD g_dwMaxNumAssociations = 0;
#undef DPF_MODNAME
#define DPF_MODNAME "XNetStartup"
INT WINAPI XNetStartup(const XNetStartupParams * pxnsp)
{
int iReturn;
XNetStartupParams StartupParamsCapped;
DWORD dwTemp;
#ifdef DBG
//DPFX(DPFPREP, 3, "Parameters: (0x%p)", pxnsp);
// Not using DNASSERT because DPlay may not be initted yet.
if (! (g_paKeys == NULL))
{
OutputDebugString("Assert failed (g_paKeys == NULL)\n");
DebugBreak();
}
#endif // DBG
if (pxnsp == NULL)
{
memset(&StartupParamsCapped, 0, sizeof(StartupParamsCapped));
}
else
{
memcpy(&StartupParamsCapped, pxnsp, sizeof(StartupParamsCapped));
}
if (StartupParamsCapped.cfgKeyRegMax == 0)
{
StartupParamsCapped.cfgKeyRegMax = 4;
}
if (StartupParamsCapped.cfgSecRegMax == 0)
{
StartupParamsCapped.cfgSecRegMax = 32;
}
// Not using DNMalloc because DPlay may not be initted yet.
g_paKeys = (KEYENTRY*) HeapAlloc(GetProcessHeap(), 0, StartupParamsCapped.cfgKeyRegMax * sizeof(KEYENTRY));
if (g_paKeys == NULL)
{
iReturn = -1;
goto Failure;
}
memset(g_paKeys, 0, (StartupParamsCapped.cfgKeyRegMax * sizeof(KEYENTRY)));
for(dwTemp = 0; dwTemp < StartupParamsCapped.cfgKeyRegMax; dwTemp++)
{
// Not using DNMalloc because DPlay may not be initted yet.
g_paKeys[dwTemp].paSecurityAssociations = (SECURITYASSOCIATION*) HeapAlloc(GetProcessHeap(), 0, StartupParamsCapped.cfgSecRegMax * sizeof(SECURITYASSOCIATION));
if (g_paKeys == NULL)
{
iReturn = -1;
goto Failure;
}
memset(g_paKeys[dwTemp].paSecurityAssociations, 0, (StartupParamsCapped.cfgSecRegMax * sizeof(SECURITYASSOCIATION)));
}
g_dwMaxNumKeys = StartupParamsCapped.cfgKeyRegMax;
g_dwMaxNumAssociations = StartupParamsCapped.cfgSecRegMax;
iReturn = 0;
Exit:
//DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
return iReturn;
Failure:
if (g_paKeys != NULL)
{
for(dwTemp = 0; dwTemp < StartupParamsCapped.cfgKeyRegMax; dwTemp++)
{
if (g_paKeys[dwTemp].paSecurityAssociations != NULL)
{
HeapFree(GetProcessHeap(), 0, g_paKeys[dwTemp].paSecurityAssociations);
g_paKeys[dwTemp].paSecurityAssociations = NULL;
}
}
HeapFree(GetProcessHeap(), 0, g_paKeys);
g_paKeys = NULL;
}
g_dwMaxNumKeys = 0;
g_dwMaxNumAssociations = 0;
goto Exit;
}
#undef DPF_MODNAME
#define DPF_MODNAME "XNetCleanup"
INT WINAPI XNetCleanup(void)
{
int iReturn;
DWORD dwTemp;
#ifdef DBG
//DPFX(DPFPREP, 3, "Enter");
// Not using DNASSERT because DPlay may not be initted anymore.
if (! (g_paKeys != NULL))
{
OutputDebugString("Assert failed (g_paKeys != NULL)\n");
DebugBreak();
}
#endif // DBG
for(dwTemp = 0; dwTemp < g_dwMaxNumKeys; dwTemp++)
{
if (g_paKeys[dwTemp].paSecurityAssociations != NULL)
{
HeapFree(GetProcessHeap(), 0, g_paKeys[dwTemp].paSecurityAssociations);
g_paKeys[dwTemp].paSecurityAssociations = NULL;
}
}
HeapFree(GetProcessHeap(), 0, g_paKeys);
g_paKeys = NULL;
g_dwMaxNumKeys = 0;
g_dwMaxNumAssociations = 0;
iReturn = 0;
//DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
return iReturn;
}
#undef DPF_MODNAME
#define DPF_MODNAME "XNetRegisterKey"
INT WINAPI XNetRegisterKey(const XNKID * pxnkid, const XNKEY * pxnkey)
{
int iReturn;
DWORD dwTemp;
DWORD dwIndex = -1;
DPFX(DPFPREP, 3, "Parameters: (0x%p, 0x%p)", pxnkid, pxnkey);
DNASSERT(pxnkid != NULL);
DNASSERT(pxnkey != NULL);
for(dwTemp = 0; dwTemp < g_dwMaxNumKeys; dwTemp++)
{
if (g_paKeys[dwTemp].fInUse)
{
if (memcmp(pxnkid, &g_paKeys[dwTemp].xnkid, sizeof(XNKID)) == 0)
{
DPFX(DPFPREP, 2, "Key has already been registered.");
iReturn = WSAEALREADY;
goto Exit;
}
}
else
{
if (dwIndex == -1)
{
dwIndex = dwTemp;
}
}
}
if (dwIndex == -1)
{
DPFX(DPFPREP, 0, "No more keys can be registered!");
iReturn = WSAENOBUFS;
goto Exit;
}
g_paKeys[dwIndex].fInUse = TRUE;
memcpy(&g_paKeys[dwIndex].xnkid, pxnkid, sizeof(XNKID));
memcpy(&g_paKeys[dwIndex].xnkey, pxnkey, sizeof(XNKEY));
iReturn = 0;
Exit:
DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
return iReturn;
}
#undef DPF_MODNAME
#define DPF_MODNAME "XNetUnregisterKey"
INT WINAPI XNetUnregisterKey(const XNKID * pxnkid)
{
int iReturn;
DWORD dwTemp;
DPFX(DPFPREP, 3, "Parameters: (0x%p)", pxnkid);
DNASSERT(pxnkid != NULL);
for(dwTemp = 0; dwTemp < g_dwMaxNumKeys; dwTemp++)
{
if (g_paKeys[dwTemp].fInUse)
{
if (memcmp(pxnkid, &g_paKeys[dwTemp].xnkid, sizeof(XNKID)) == 0)
{
g_paKeys[dwTemp].fInUse = FALSE;
iReturn = 0;
goto Exit;
}
}
}
DPFX(DPFPREP, 0, "Key has not been registered!");
DNASSERTX(! "Key has not been registered!", 2);
iReturn = -1;
Exit:
DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
return iReturn;
}
#undef DPF_MODNAME
#define DPF_MODNAME "XNetXnAddrToInAddr"
INT WINAPI XNetXnAddrToInAddr(const XNADDR * pxna, const XNKID * pxnkid, IN_ADDR * pina)
{
int iReturn;
DWORD dwKey;
DWORD dwAssociation;
DWORD dwIndex;
DPFX(DPFPREP, 3, "Parameters: (0x%p, 0x%p, 0x%p)", pxna, pxnkid, pina);
DNASSERT(pxna != NULL);
DNASSERT(pxnkid != NULL);
DNASSERT(pina != NULL);
for(dwKey = 0; dwKey < g_dwMaxNumKeys; dwKey++)
{
if ((g_paKeys[dwKey].fInUse) &&
(memcmp(pxnkid, &g_paKeys[dwKey].xnkid, sizeof(XNKID)) == 0))
{
dwIndex = -1;
for(dwAssociation = 0; dwAssociation < g_dwMaxNumAssociations; dwAssociation++)
{
if (g_paKeys[dwKey].paSecurityAssociations[dwAssociation].fInUse)
{
if (memcmp(pxna, &g_paKeys[dwKey].paSecurityAssociations[dwAssociation].xnaddr, sizeof(XNADDR)) == 0)
{
memcpy(pina, &g_paKeys[dwKey].paSecurityAssociations[dwAssociation].inaddr, sizeof(IN_ADDR));
iReturn = 0;
goto Exit;
}
}
else
{
if (dwIndex == -1)
{
dwIndex = dwAssociation;
}
}
}
if (dwIndex == -1)
{
DPFX(DPFPREP, 0, "No more security associations can be made!");
iReturn = WSAENOBUFS;
goto Exit;
}
g_paKeys[dwKey].paSecurityAssociations[dwIndex].fInUse = TRUE;
memcpy(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr, pxna, sizeof(XNADDR));
DBG_CASSERT(sizeof(pxna->abEnet) > (sizeof(IN_ADDR) + 1));
memcpy(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].inaddr, &pxna->abEnet[1], sizeof(IN_ADDR));
memcpy(pina, &g_paKeys[dwKey].paSecurityAssociations[dwIndex].inaddr, sizeof(IN_ADDR));
iReturn = 0;
goto Exit;
}
}
DPFX(DPFPREP, 0, "Key has not been registered!");
DNASSERTX(! "Key has not been registered!", 2);
iReturn = -1;
Exit:
DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
return iReturn;
}
#undef DPF_MODNAME
#define DPF_MODNAME "XNetInAddrToXnAddr"
INT WINAPI XNetInAddrToXnAddr(const IN_ADDR ina, XNADDR * pxna, XNKID * pxnkid)
{
int iReturn;
DWORD dwKey;
DWORD dwAssociation;
DPFX(DPFPREP, 3, "Parameters: (%u.%u.%u.%u, 0x%p, 0x%p)",
ina.S_un.S_un_b.s_b1, ina.S_un.S_un_b.s_b2, ina.S_un.S_un_b.s_b3, ina.S_un.S_un_b.s_b4, pxna, pxnkid);
//
// Special case the loopback address, that just means the title address.
//
if (ina.S_un.S_addr == IP_LOOPBACK_ADDRESS)
{
if (pxna != NULL)
{
iReturn = XNetGetTitleXnAddr(pxna);
DNASSERT((iReturn != XNET_GET_XNADDR_PENDING) && (iReturn != XNET_GET_XNADDR_NONE));
}
if (pxnkid != NULL)
{
memset(pxnkid, 0, sizeof(XNKID));
}
iReturn = 0;
goto Exit;
}
for(dwKey = 0; dwKey < g_dwMaxNumKeys; dwKey++)
{
if (g_paKeys[dwKey].fInUse)
{
for(dwAssociation = 0; dwAssociation < g_dwMaxNumAssociations; dwAssociation++)
{
if (g_paKeys[dwKey].paSecurityAssociations[dwAssociation].fInUse)
{
if (memcmp(&ina, &g_paKeys[dwKey].paSecurityAssociations[dwAssociation].inaddr, sizeof(IN_ADDR)) == 0)
{
if (pxna != NULL)
{
memcpy(pxna, &g_paKeys[dwKey].paSecurityAssociations[dwAssociation].xnaddr, sizeof(XNADDR));
}
if (pxnkid != NULL)
{
memcpy(pxnkid, &g_paKeys[dwKey].xnkid, sizeof(XNKID));
}
iReturn = 0;
goto Exit;
}
}
}
}
}
DPFX(DPFPREP, 0, "No security association for IN_ADDR specified!");
DNASSERTX(! "No security association for IN_ADDR specified!", 2);
iReturn = -1;
Exit:
DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
return iReturn;
}
#undef DPF_MODNAME
#define DPF_MODNAME "XNetGetTitleXnAddr"
DWORD WINAPI XNetGetTitleXnAddr(XNADDR * pxna)
{
DWORD dwReturn;
char szBuffer[256];
PHOSTENT phostent;
IN_ADDR * pinaddr;
DPFX(DPFPREP, 3, "Parameters: (0x%p)", pxna);
DNASSERT(pxna != NULL);
if (gethostname(szBuffer, sizeof(szBuffer)) == SOCKET_ERROR)
{
#ifdef DBG
dwReturn = WSAGetLastError();
DPFX(DPFPREP, 0, "Failed to get host name into fixed size buffer (err = %i)!", dwReturn);
DisplayWinsockError(0, dwReturn);
#endif // DBG
dwReturn = XNET_GET_XNADDR_NONE;
goto Exit;
}
phostent = gethostbyname(szBuffer);
if (phostent == NULL)
{
#ifdef DBG
dwReturn = WSAGetLastError();
DPFX(DPFPREP, 0, "Failed to get host data (err = %i)!", dwReturn);
DisplayWinsockError(0, dwReturn);
#endif // DBG
dwReturn = XNET_GET_XNADDR_NONE;
goto Exit;
}
memset(pxna, 0, sizeof(XNADDR));
//
// We'll use the first address returned.
//
pinaddr = (IN_ADDR*) phostent->h_addr_list[0];
DNASSERT(pinaddr != NULL);
DBG_CASSERT(sizeof(pxna->abEnet) > (sizeof(IN_ADDR) + 1));
memset(&pxna->abEnet, 0xFF, sizeof(pxna->abEnet));
memcpy(&pxna->abEnet[1], pinaddr, sizeof(IN_ADDR));
memcpy(&pxna->ina, pinaddr, sizeof(IN_ADDR));
//
// Pretend it's always DHCP.
//
dwReturn = XNET_GET_XNADDR_DHCP;
Exit:
DPFX(DPFPREP, 3, "Returning: [%u]", dwReturn);
return dwReturn;
}
#undef DPF_MODNAME
#define DPF_MODNAME "XNetGetEthernetLinkStatus"
DWORD WINAPI XNetGetEthernetLinkStatus(void)
{
DWORD dwReturn;
DPFX(DPFPREP, 3, "Enter");
//
// Hard code an active 10 Mbit link.
//
dwReturn = XNET_ETHERNET_LINK_ACTIVE | XNET_ETHERNET_LINK_10MBPS;
DPFX(DPFPREP, 3, "Returning: [0x%x]", dwReturn);
return dwReturn;
}
#undef DPF_MODNAME
#define DPF_MODNAME "XNetPrivCreateAssociation"
INT WINAPI XNetPrivCreateAssociation(const XNKID * pxnkid, const CSocketAddress * const pSocketAddress)
{
int iReturn;
SOCKADDR_IN * psockaddrin;
DWORD dwKey;
DWORD dwAssociation;
DWORD dwIndex;
DPFX(DPFPREP, 3, "Parameters: (0x%p, 0x%p)", pxnkid, pSocketAddress);
DNASSERT(pxnkid != NULL);
DNASSERT(pSocketAddress != NULL);
DNASSERT(pSocketAddress->GetFamily() == AF_INET);
psockaddrin = (SOCKADDR_IN*) pSocketAddress->GetAddress();
for(dwKey = 0; dwKey < g_dwMaxNumKeys; dwKey++)
{
if ((g_paKeys[dwKey].fInUse) &&
(memcmp(pxnkid, &g_paKeys[dwKey].xnkid, sizeof(XNKID)) == 0))
{
dwIndex = -1;
for(dwAssociation = 0; dwAssociation < g_dwMaxNumAssociations; dwAssociation++)
{
if (g_paKeys[dwKey].paSecurityAssociations[dwAssociation].fInUse)
{
if (memcmp(&psockaddrin->sin_addr, &g_paKeys[dwKey].paSecurityAssociations[dwAssociation].xnaddr, sizeof(psockaddrin->sin_addr)) == 0)
{
DPFX(DPFPREP, 2, "Security association already made.");
iReturn = 0;
goto Exit;
}
}
else
{
if (dwIndex == -1)
{
dwIndex = dwAssociation;
}
}
}
if (dwIndex == -1)
{
DPFX(DPFPREP, 0, "No more security associations can be made!");
iReturn = WSAENOBUFS;
goto Exit;
}
g_paKeys[dwKey].paSecurityAssociations[dwIndex].fInUse = TRUE;
memset(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr, 0, sizeof(XNADDR));
memset(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr.abEnet, 0xFF,
sizeof(g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr.abEnet));
DBG_CASSERT(sizeof(g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr.abEnet) > (sizeof(IN_ADDR) + 1));
memcpy(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].xnaddr.abEnet[1],
&psockaddrin->sin_addr, sizeof(IN_ADDR));
memcpy(&g_paKeys[dwKey].paSecurityAssociations[dwIndex].inaddr, &psockaddrin->sin_addr, sizeof(IN_ADDR));
iReturn = 0;
goto Exit;
}
}
DPFX(DPFPREP, 0, "Key has not been registered!");
DNASSERTX(! "Key has not been registered!", 2);
iReturn = -1;
Exit:
DPFX(DPFPREP, 3, "Returning: [%i]", iReturn);
return iReturn;
}
#endif // XBOX_ON_DESKTOP
#endif // _XBOX