1314 lines
31 KiB
C++
1314 lines
31 KiB
C++
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1998-2000 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"
|
|
|
|
|
|
#undef DPF_SUBCOMP
|
|
#define DPF_SUBCOMP DN_SUBCOMP_WSOCK
|
|
|
|
//**********************************************************************
|
|
// Constant definitions
|
|
//**********************************************************************
|
|
|
|
#define DEFAULT_WIN9X_THREADS 2
|
|
|
|
#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
|
|
//
|
|
static DNCRITICAL_SECTION g_InterfaceGlobalsLock;
|
|
|
|
static volatile LONG g_iThreadPoolRefCount = 0;
|
|
static CThreadPool * g_pThreadPool = NULL;
|
|
|
|
|
|
static DWSSTATE g_dwsState; // state info for the WS1/2 glue lib
|
|
static volatile LONG g_iWinsockRefCount = 0;
|
|
|
|
|
|
static volatile LONG g_iNATHelpRefCount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// Function prototypes
|
|
//**********************************************************************
|
|
static void ReadSettingsFromRegistry( void );
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// Function definitions
|
|
//**********************************************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// 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 WINNT
|
|
char szExePath[_MAX_PATH];
|
|
#endif // ! WINNT
|
|
|
|
|
|
if ( RegObject.Open( HKEY_LOCAL_MACHINE, g_RegistryBase ) != FALSE )
|
|
{
|
|
|
|
//
|
|
// read receive buffer size
|
|
//
|
|
if ( RegObject.ReadDWORD( g_RegistryKeyReceiveBufferSize, dwRegValue ) != FALSE )
|
|
{
|
|
g_fWinsockReceiveBufferSizeOverridden = TRUE;
|
|
g_iWinsockReceiveBufferSize = dwRegValue;
|
|
}
|
|
|
|
//
|
|
// read buffer multiplier, make sure this does note get set to zero
|
|
//
|
|
if ( RegObject.ReadDWORD( g_RegistryKeyReceiveBufferMultiplier, dwRegValue ) != FALSE )
|
|
{
|
|
if ( dwRegValue != 0 )
|
|
{
|
|
g_dwWinsockReceiveBufferMultiplier = dwRegValue;
|
|
DPFX(DPFPREP, 3, "Setting Winsock receive buffer multiplier to: %d", dwRegValue );
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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 )
|
|
{
|
|
#ifdef WIN95
|
|
g_iThreadCount = DEFAULT_WIN9X_THREADS;
|
|
#else // WINNT
|
|
SYSTEM_INFO SystemInfo;
|
|
|
|
|
|
//
|
|
// as suggested by 'Multithreading Applications in Win32' book:
|
|
// dwNTThreadCount = ( ( processors * 2 ) + 2 )
|
|
//
|
|
memset( &SystemInfo, 0x00, sizeof( SystemInfo ) );
|
|
GetSystemInfo( &SystemInfo );
|
|
|
|
g_iThreadCount = ( ( 2 * SystemInfo.dwNumberOfProcessors ) + 2 );
|
|
#endif
|
|
}
|
|
|
|
|
|
//
|
|
// get global NAT traversal disablers, ignore registry reading error
|
|
//
|
|
RegObject.ReadBOOL( g_RegistryKeyDisableDPNHGatewaySupport, g_fDisableDPNHGatewaySupport );
|
|
RegObject.ReadBOOL( g_RegistryKeyDisableDPNHFirewallSupport, g_fDisableDPNHFirewallSupport );
|
|
|
|
//
|
|
// get NAT Help alert mechanism disabler, ignore registry reading error
|
|
//
|
|
RegObject.ReadBOOL( g_RegistryKeyUseNATHelpAlert, g_fUseNATHelpAlert );
|
|
|
|
|
|
//
|
|
// Find out the current process name and see if enums are disabled.
|
|
//
|
|
#ifdef WINNT
|
|
if (GetModuleFileNameW(NULL, wszExePath, _MAX_PATH) > 0)
|
|
{
|
|
DPFX(DPFPREP, 3, "Loading DLL in process: %S", wszExePath);
|
|
_wsplitpath( wszExePath, NULL, NULL, wszExePath, NULL );
|
|
fGotPath = TRUE;
|
|
}
|
|
#else // ! WINNT
|
|
if (GetModuleFileNameA(NULL, szExePath, _MAX_PATH) > 0)
|
|
{
|
|
HRESULT hr;
|
|
|
|
|
|
DPFX(DPFPREP, 3, "Loading DLL in process: %s", szExePath);
|
|
_splitpath( 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 // ! WINNT
|
|
else
|
|
{
|
|
//
|
|
// Couldn't get current process path.
|
|
//
|
|
fGotPath = FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// If we have an app name, try opening the subkey and looking up the app
|
|
// to see if enums are disabled or there are IP addresses to ban.
|
|
//
|
|
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 = %S).", wszExePath);
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 2, "Not ignoring all enumerations (app = %S).", wszExePath);
|
|
}
|
|
}
|
|
|
|
#ifdef IPBANNING
|
|
if ( RegObjectTemp.Open( RegObject.GetHandle(), g_RegistryKeyAppsToBanIPs, TRUE, FALSE ) )
|
|
{
|
|
if ( RegObjectAppEntry.Open( RegObjectTemp.GetHandle(), wszExePath, TRUE, FALSE ) )
|
|
{
|
|
RegObjectTemp.Close();
|
|
|
|
RegObjectAppEntry.EnumValues( wszExePath, g_fIgnoreEnums );
|
|
|
|
//
|
|
// Read in IP addresses to ban from registry.
|
|
//
|
|
/*
|
|
if ( ? )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
}
|
|
*/
|
|
|
|
RegObjectAppEntry.Close();
|
|
}
|
|
else
|
|
{
|
|
RegObjectTemp.Close();
|
|
}
|
|
}
|
|
#endif // IPBANNING
|
|
}
|
|
|
|
|
|
//
|
|
// Get the proxy support options, ignore registry reading error.
|
|
//
|
|
RegObject.ReadBOOL( g_RegistryKeyDontAutoDetectProxyLSP, g_fDontAutoDetectProxyLSP );
|
|
RegObject.ReadBOOL( g_RegistryKeyTreatAllResponsesAsProxied, g_fTreatAllResponsesAsProxied );
|
|
|
|
|
|
RegObject.Close();
|
|
}
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// 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;
|
|
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
fReturn = TRUE;
|
|
fCriticalSectionInitialized = FALSE;
|
|
|
|
ReadSettingsFromRegistry();
|
|
|
|
if ( DNInitializeCriticalSection( &g_InterfaceGlobalsLock ) == FALSE )
|
|
{
|
|
fReturn = FALSE;
|
|
goto Failure;
|
|
}
|
|
|
|
fCriticalSectionInitialized = TRUE;
|
|
|
|
|
|
if ( InitializePools() == FALSE )
|
|
{
|
|
fReturn = FALSE;
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
DNASSERT( g_pThreadPool == NULL );
|
|
|
|
|
|
Exit:
|
|
return fReturn;
|
|
|
|
Failure:
|
|
|
|
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 );
|
|
|
|
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_PTR iVersion;
|
|
|
|
|
|
DNEnterCriticalSection( &g_InterfaceGlobalsLock );
|
|
|
|
if ( g_iWinsockRefCount == 0 )
|
|
{
|
|
//
|
|
// initialize the bindings to Winsock
|
|
//
|
|
iVersion = DWSInitWinSock( &g_dwsState );
|
|
if ( iVersion == 0 ) // failure
|
|
{
|
|
DPFX(DPFPREP, 0, "Problem binding dynamic winsock functions!" );
|
|
fReturn = FALSE;
|
|
goto Failure;
|
|
}
|
|
|
|
DPFX(DPFPREP, 8, "Detected WinSock version %d.%d", LOBYTE( iVersion ), HIBYTE( iVersion ) );
|
|
}
|
|
|
|
DNInterlockedIncrement( &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 );
|
|
|
|
if ( DNInterlockedDecrement( &g_iWinsockRefCount ) == 0 )
|
|
{
|
|
BOOL fFreeReturn;
|
|
|
|
|
|
fFreeReturn = DWSFreeWinSock( &g_dwsState );
|
|
if ( fFreeReturn == FALSE )
|
|
{
|
|
DPFX(DPFPREP, 0, "Problem unbinding dynamic WinSock functions!" );
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 6, "Successfully unbound dynamic WinSock functions." );
|
|
}
|
|
}
|
|
|
|
DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
#ifdef WIN95
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// GetWinsockVersion - get the version of Winsock
|
|
//
|
|
// Entry: Nothing
|
|
//
|
|
// Exit: Winsock version
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetWinsockVersion"
|
|
|
|
INT GetWinsockVersion( void )
|
|
{
|
|
return g_dwsState.nVersion;
|
|
}
|
|
//**********************************************************************
|
|
#endif
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// 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;
|
|
CRegistry RegEntry;
|
|
CRegistry RegSubentry;
|
|
DWORD dwMaxKeyLen;
|
|
WCHAR * pwszKeyName = NULL;
|
|
DWORD dwEnumIndex;
|
|
DWORD dwKeyLen;
|
|
DWORD dwDirectPlay8Priority;
|
|
DWORD dwDirectPlay8InitFlags;
|
|
DWORD dwNumLoaded;
|
|
GUID guid;
|
|
|
|
|
|
DNEnterCriticalSection(&g_InterfaceGlobalsLock);
|
|
|
|
if ( g_iNATHelpRefCount == 0 )
|
|
{
|
|
//
|
|
// 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("DNMalloc() failed");
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// 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*)));
|
|
|
|
|
|
dwEnumIndex = 0;
|
|
dwNumLoaded = 0;
|
|
|
|
//
|
|
// Enumerate the DirectPlay NAT helpers.
|
|
//
|
|
do
|
|
{
|
|
dwKeyLen = dwMaxKeyLen;
|
|
if (! RegEntry.EnumKeys(pwszKeyName, &dwKeyLen, dwEnumIndex))
|
|
{
|
|
break;
|
|
}
|
|
dwEnumIndex++;
|
|
|
|
|
|
DPFX(DPFPREP, 8, "%ld - %S (%ld)", dwEnumIndex, pwszKeyName, dwKeyLen);
|
|
|
|
if (!RegSubentry.Open(RegEntry, pwszKeyName, TRUE, FALSE))
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't open subentry \"%S\"! Skipping.", pwszKeyName);
|
|
continue;
|
|
}
|
|
|
|
|
|
//
|
|
// Read the DirectPlay8 priority
|
|
//
|
|
if (!RegSubentry.ReadDWORD(REGSUBKEY_DPNATHELP_DIRECTPLAY8PRIORITY, dwDirectPlay8Priority))
|
|
{
|
|
DPFX(DPFPREP, 0, "RegSubentry.ReadDWORD \"%S\\%S\" 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 \"%S\\%S\" 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 \"%S\\%S\" 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)
|
|
{
|
|
//
|
|
// Make sure this priority is valid.
|
|
//
|
|
if (dwDirectPlay8Priority > MAX_NUM_DIRECTPLAYNATHELPERS)
|
|
{
|
|
DPFX(DPFPREP, 0, "Ignoring DirectPlay NAT helper \"%S\" 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 \"%S\" 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]));
|
|
if ( hr != S_OK )
|
|
{
|
|
DNASSERT( g_papNATHelpObjects[dwDirectPlay8Priority - 1] == NULL );
|
|
DPFX(DPFPREP, 0, "Failed to create \"%S\" IDirectPlayNATHelp interface (error = 0x%lx)! Skipping.",
|
|
pwszKeyName, hr);
|
|
continue;
|
|
}
|
|
|
|
|
|
//
|
|
// Initialize NAT Help.
|
|
//
|
|
|
|
DNASSERT((! g_fDisableDPNHGatewaySupport) || (! g_fDisableDPNHFirewallSupport));
|
|
|
|
if (g_fDisableDPNHGatewaySupport)
|
|
{
|
|
dwDirectPlay8InitFlags |= DPNHINITIALIZE_DISABLEGATEWAYSUPPORT;
|
|
}
|
|
|
|
if (g_fDisableDPNHFirewallSupport)
|
|
{
|
|
dwDirectPlay8InitFlags |= DPNHINITIALIZE_DISABLELOCALFIREWALLSUPPORT;
|
|
}
|
|
|
|
|
|
//
|
|
// 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 \"%S\" 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 \"%S\" (error = 0x%lx)! Skipping.",
|
|
pwszKeyName, hr);
|
|
|
|
IDirectPlayNATHelp_Release(g_papNATHelpObjects[dwDirectPlay8Priority - 1]);
|
|
g_papNATHelpObjects[dwDirectPlay8Priority - 1] = NULL;
|
|
|
|
continue;
|
|
}
|
|
|
|
|
|
DPFX(DPFPREP, 8, "Initialized NAT Help \"%S\" (priority = %u, flags = 0x%lx, object = 0x%p).",
|
|
pwszKeyName, dwDirectPlay8Priority, dwDirectPlay8InitFlags, g_papNATHelpObjects[dwDirectPlay8Priority - 1]);
|
|
|
|
dwNumLoaded++;
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 1, "DirectPlay NAT Helper \"%S\" is not enabled for DirectPlay8.", pwszKeyName);
|
|
}
|
|
}
|
|
while (TRUE);
|
|
|
|
|
|
//
|
|
// 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 InterlockedIncrement.
|
|
//
|
|
g_iNATHelpRefCount++;
|
|
|
|
//
|
|
// We succeeded.
|
|
//
|
|
fReturn = TRUE;
|
|
|
|
Exit:
|
|
|
|
DNLeaveCriticalSection(&g_InterfaceGlobalsLock);
|
|
|
|
if (pwszKeyName != NULL)
|
|
{
|
|
DNFree(pwszKeyName);
|
|
pwszKeyName = NULL;
|
|
}
|
|
|
|
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 InterlockedDecrement.
|
|
//
|
|
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 );
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// CreateSPData - create instance data for SP
|
|
//
|
|
// Entry: Pointer to pointer to SPData
|
|
// Pointer to class GUID
|
|
// Interface type
|
|
// Pointer to COM interface vtable
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CreateSPData"
|
|
|
|
HRESULT CreateSPData( CSPData **const ppSPData,
|
|
const CLSID *const pClassID,
|
|
const SP_TYPE SPType,
|
|
IDP8ServiceProviderVtbl *const pVtbl )
|
|
{
|
|
HRESULT hr;
|
|
CSPData *pSPData;
|
|
|
|
|
|
DNASSERT( ppSPData != NULL );
|
|
DNASSERT( pClassID != NULL );
|
|
DNASSERT( pVtbl != NULL );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
*ppSPData = NULL;
|
|
pSPData = NULL;
|
|
|
|
//
|
|
// create data
|
|
//
|
|
pSPData = new CSPData;
|
|
if ( pSPData == NULL )
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
DPFX(DPFPREP, 0, "Cannot create data for Winsock interface!" );
|
|
goto Failure;
|
|
}
|
|
pSPData->AddRef();
|
|
|
|
hr = pSPData->Initialize( pClassID, SPType, pVtbl );
|
|
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);
|
|
|
|
Exit:
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Problem with CreateSPData!" );
|
|
DisplayDNError( 0, hr );
|
|
}
|
|
|
|
*ppSPData = pSPData;
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
if ( pSPData != NULL )
|
|
{
|
|
pSPData->DecRef();
|
|
pSPData = NULL;
|
|
}
|
|
|
|
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;
|
|
CRsip *pRsip;
|
|
|
|
|
|
DNASSERT( pSPData != NULL );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
pThreadPool = NULL;
|
|
pRsip = NULL;
|
|
|
|
DNEnterCriticalSection( &g_InterfaceGlobalsLock );
|
|
|
|
if ( g_pThreadPool == NULL )
|
|
{
|
|
DNASSERT( g_iThreadPoolRefCount == 0 );
|
|
g_pThreadPool = CreateThreadPool();
|
|
if ( g_pThreadPool != NULL )
|
|
{
|
|
hr = g_pThreadPool->Initialize();
|
|
if ( hr != DPN_OK )
|
|
{
|
|
g_pThreadPool->DecRef();
|
|
g_pThreadPool = NULL;
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
else
|
|
{
|
|
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 );
|
|
|
|
//
|
|
// Now that we're outside of the lock, clean up any pointers we have.
|
|
// The thread pool will be cleaned up when all of the outstanding interfaces
|
|
// close.
|
|
//
|
|
if ( pThreadPool != NULL )
|
|
{
|
|
pThreadPool->StopAllIO();
|
|
pThreadPool = NULL;
|
|
}
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// AddNetworkAdapterToBuffer - add a network address to a packed buffer
|
|
//
|
|
// Entry: Pointer to packed buffer
|
|
// Pointer to adapter name
|
|
// Pointer to adapter guid
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "AddNetworkAdapterToBuffer"
|
|
|
|
HRESULT AddNetworkAdapterToBuffer( CPackedBuffer *const pPackedBuffer,
|
|
const char *const pAdapterName,
|
|
const GUID *const pAdapterGUID )
|
|
{
|
|
HRESULT hr;
|
|
DPN_SERVICE_PROVIDER_INFO AdapterInfo;
|
|
|
|
|
|
DNASSERT( pPackedBuffer != NULL );
|
|
DNASSERT( pAdapterName != NULL );
|
|
DNASSERT( pAdapterGUID != NULL );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
|
|
memset( &AdapterInfo, 0x00, sizeof( AdapterInfo ) );
|
|
DNASSERT( AdapterInfo.dwFlags == 0 );
|
|
DNASSERT( AdapterInfo.pvReserved == NULL );
|
|
DNASSERT( AdapterInfo.dwReserved == NULL );
|
|
|
|
AdapterInfo.guid = *pAdapterGUID;
|
|
|
|
hr = pPackedBuffer->AddStringToBack( pAdapterName );
|
|
if ( ( hr != DPNERR_BUFFERTOOSMALL ) && ( hr != DPN_OK ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to add adapter name to buffer!" );
|
|
goto Failure;
|
|
}
|
|
AdapterInfo.pwszName = static_cast<WCHAR*>( pPackedBuffer->GetTailAddress() );
|
|
|
|
hr = pPackedBuffer->AddToFront( &AdapterInfo, sizeof( AdapterInfo ) );
|
|
|
|
Exit:
|
|
return hr;
|
|
|
|
Failure:
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// ConvertURLDataToBinaryW - convert a Unicode string with URL escaped characters into a binary buffer
|
|
//
|
|
// Entry: String to convert
|
|
// Destination buffer pointer
|
|
// Pointer to size of buffer. If too small, size required will be stored here. Otherwise bytes written will be stored here.
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ConvertURLDataToBinaryW"
|
|
|
|
HRESULT ConvertURLDataToBinaryW( const WCHAR * const wszURLData,
|
|
void * const pvBuffer,
|
|
DWORD * const pdwBufferSize )
|
|
{
|
|
HRESULT hr;
|
|
WCHAR * pwszTemp = NULL;
|
|
IDirectPlay8Address * pDP8AddressTemp = NULL;
|
|
|
|
|
|
DNASSERT(wszURLData != NULL);
|
|
DNASSERT(pdwBufferSize != NULL);
|
|
|
|
|
|
//
|
|
// Create a DirectPlay8Address object.
|
|
//
|
|
hr = COM_CoCreateInstance(CLSID_DirectPlay8Address,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IDirectPlay8Address,
|
|
(PVOID*) (&pDP8AddressTemp));
|
|
if (hr != S_OK)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't create temporary DirectPlay8Address object (err = 0x%lx)!", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Allocate a buffer and stick "x-directplay:/#" in front of the
|
|
// data (i.e. make the string passed in user data for a bogus URL).
|
|
//
|
|
|
|
pwszTemp = (WCHAR*) DNMalloc((wcslen(DPNA_HEADER) + 1 + wcslen(wszURLData) + 1) * sizeof(WCHAR));
|
|
if (pwszTemp == NULL)
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
wcscpy(pwszTemp, DPNA_HEADER);
|
|
pwszTemp[wcslen(DPNA_HEADER)] = DPNA_SEPARATOR_USERDATA;
|
|
wcscpy((pwszTemp + wcslen(DPNA_HEADER) + 1), wszURLData);
|
|
|
|
|
|
//
|
|
// Let the addressing library's parsing routine handle the grunt
|
|
// work of converting the string to binary data.
|
|
//
|
|
hr = IDirectPlay8Address_BuildFromURLW(pDP8AddressTemp, pwszTemp);
|
|
if (hr != DPN_OK)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't build URL from string \"%S\"!", pwszTemp);
|
|
goto Exit;
|
|
}
|
|
|
|
hr = IDirectPlay8Address_GetUserData(pDP8AddressTemp, pvBuffer, pdwBufferSize);
|
|
if (hr != DPN_OK)
|
|
{
|
|
if (hr != DPNERR_BUFFERTOOSMALL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't get user data from temporary DirectPlay8Address object!");
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
if (pwszTemp != NULL)
|
|
{
|
|
DNFree(pwszTemp);
|
|
pwszTemp = NULL;
|
|
}
|
|
|
|
if (pDP8AddressTemp != NULL)
|
|
{
|
|
IDirectPlay8Address_Release(pDP8AddressTemp);
|
|
pDP8AddressTemp = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// ConvertURLDataToBinaryA - convert an ANSI string with URL escaped characters into a binary buffer
|
|
//
|
|
// Entry: String to convert
|
|
// Destination buffer pointer
|
|
// Pointer to size of buffer. If too small, size required will be stored here. Otherwise bytes written will be stored here.
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ConvertURLDataToBinaryA"
|
|
|
|
HRESULT ConvertURLDataToBinaryA( const char * const szURLData,
|
|
void * const pvBuffer,
|
|
DWORD * const pdwBufferSize )
|
|
{
|
|
HRESULT hr;
|
|
char * pszTemp = NULL;
|
|
IDirectPlay8Address * pDP8AddressTemp = NULL;
|
|
|
|
|
|
DNASSERT(szURLData != NULL);
|
|
DNASSERT(pdwBufferSize != NULL);
|
|
|
|
|
|
//
|
|
// Create a DirectPlay8Address object.
|
|
//
|
|
hr = COM_CoCreateInstance(CLSID_DirectPlay8Address,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IDirectPlay8Address,
|
|
(PVOID*) (&pDP8AddressTemp));
|
|
if (hr != S_OK)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't create temporary DirectPlay8Address object (err = 0x%lx)!", hr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Allocate a buffer and stick "x-directplay:/#" in front of the
|
|
// data (i.e. make the string passed in user data for a bogus URL).
|
|
//
|
|
|
|
pszTemp = (char*) DNMalloc((strlen(DPNA_HEADER_A) + 1 + strlen(szURLData) + 1) * sizeof(char));
|
|
if (pszTemp == NULL)
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
strcpy(pszTemp, DPNA_HEADER_A);
|
|
pszTemp[strlen(DPNA_HEADER_A)] = DPNA_SEPARATOR_USERDATA_A;
|
|
strcpy((pszTemp + strlen(DPNA_HEADER_A) + 1), szURLData);
|
|
|
|
|
|
//
|
|
// Let the addressing library's parsing routine handle the grunt
|
|
// work of converting the string to binary data.
|
|
//
|
|
hr = IDirectPlay8Address_BuildFromURLA(pDP8AddressTemp, pszTemp);
|
|
if (hr != DPN_OK)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't build URL from string \"%s\"!", pszTemp);
|
|
goto Exit;
|
|
}
|
|
|
|
hr = IDirectPlay8Address_GetUserData(pDP8AddressTemp, pvBuffer, pdwBufferSize);
|
|
if (hr != DPN_OK)
|
|
{
|
|
if (hr != DPNERR_BUFFERTOOSMALL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't get user data from temporary DirectPlay8Address object!");
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
if (pszTemp != NULL)
|
|
{
|
|
DNFree(pszTemp);
|
|
pszTemp = NULL;
|
|
}
|
|
|
|
if (pDP8AddressTemp != NULL)
|
|
{
|
|
IDirectPlay8Address_Release(pDP8AddressTemp);
|
|
pDP8AddressTemp = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
#endif // 0
|
|
|