windows-nt/Source/XPSP1/NT/net/rras/ipx/autonet/netnum.cpp
2020-09-26 16:20:57 +08:00

253 lines
6.6 KiB
C++

/*
File netnum.cpp
Private helper functions for setting the internal network number.
We talk to ndis directly to set this number.
Paul Mayfield, 1/5/98
*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winsvc.h>
#include <ndispnp.h>
extern "C" {
DWORD OutputDebugger (LPSTR pszError, ...);
};
//$ REVIEW - Start - This is moving to private\inc\ipxpnp.h
#define IPX_RECONFIG_VERSION 0x1
#define RECONFIG_AUTO_DETECT 1
#define RECONFIG_MANUAL 2
#define RECONFIG_PREFERENCE_1 3
#define RECONFIG_NETWORK_NUMBER_1 4
#define RECONFIG_PREFERENCE_2 5
#define RECONFIG_NETWORK_NUMBER_2 6
#define RECONFIG_PREFERENCE_3 7
#define RECONFIG_NETWORK_NUMBER_3 8
#define RECONFIG_PREFERENCE_4 9
#define RECONFIG_NETWORK_NUMBER_4 10
#define RECONFIG_PARAMETERS 10
//
// Main configuration structure.
//
typedef struct _RECONFIG {
unsigned long ulVersion;
BOOLEAN InternalNetworkNumber;
BOOLEAN AdapterParameters[RECONFIG_PARAMETERS];
} RECONFIG, *PRECONFIG;
//$ REVIEW - End - This is moving to private\inc\ipxpnp.h
static const TCHAR c_szIpx[] = TEXT("nwlnkipx");
static const TCHAR c_szEmpty[] = TEXT("");
static const TCHAR c_szVirtualNetworkNumber[] = TEXT("VirtualNetworkNumber");
static const TCHAR c_szIpxParameters[] = TEXT("System\\CurrentControlSet\\Services\\NwlnkIpx\\Parameters");
static const TCHAR c_szDevice[] = TEXT("\\Device\\");
ULONG
CchMsz (
LPCTSTR pmsz)
{
ULONG cchTotal = 0;
ULONG cch;
// NULL strings have zero length by definition.
if (!pmsz)
return 0;
while (*pmsz)
{
cch = lstrlen (pmsz) + 1;
cchTotal += cch;
pmsz += cch;
}
// Return the count of characters so far plus room for the
// extra null terminator.
return cchTotal + 1;
}
void
SetUnicodeMultiString (
IN OUT UNICODE_STRING* pustr,
IN LPCWSTR pmsz )
{
//AssertSz( pustr != NULL, "Invalid Argument" );
//AssertSz( pmsz != NULL, "Invalid Argument" );
pustr->Buffer = const_cast<PWSTR>(pmsz);
pustr->Length = (USHORT) (CchMsz(pustr->Buffer) * sizeof(WCHAR));
pustr->MaximumLength = pustr->Length;
}
void
SetUnicodeString (
IN OUT UNICODE_STRING* pustr,
IN LPCWSTR psz )
{
//AssertSz( pustr != NULL, "Invalid Argument" );
//AssertSz( psz != NULL, "Invalid Argument" );
pustr->Buffer = const_cast<PWSTR>(psz);
pustr->Length = (USHORT)(lstrlenW(pustr->Buffer) * sizeof(WCHAR));
pustr->MaximumLength = pustr->Length + sizeof(WCHAR);
}
HRESULT
HrSendNdisHandlePnpEvent (
UINT uiLayer,
UINT uiOperation,
LPCWSTR pszUpper,
LPCWSTR pszLower,
LPCWSTR pmszBindList,
PVOID pvData,
DWORD dwSizeData)
{
UNICODE_STRING umstrBindList;
UNICODE_STRING ustrLower;
UNICODE_STRING ustrUpper;
UINT nRet;
HRESULT hr = S_OK;
//Assert(NULL != pszUpper);
//Assert((NDIS == uiLayer)||(TDI == uiLayer));
//Assert( (BIND == uiOperation) || (RECONFIGURE == uiOperation) || (UNBIND == uiOperation) );
//AssertSz( FImplies( ((NULL != pmszBindList) && (0 != lstrlenW( pmszBindList ))),
// (RECONFIGURE == uiOperation) &&
// (TDI == uiLayer) &&
// (0 == lstrlenW( pszLower ))),
// "bind order change requires a bind list, no lower, only for TDI, and with Reconfig for the operation" );
// optional strings must be sent as empty strings
//
if (NULL == pszLower)
{
pszLower = c_szEmpty;
}
if (NULL == pmszBindList)
{
pmszBindList = c_szEmpty;
}
// build UNICDOE_STRINGs
SetUnicodeMultiString( &umstrBindList, pmszBindList );
SetUnicodeString( &ustrUpper, pszUpper );
SetUnicodeString( &ustrLower, pszLower );
// Now submit the notification
nRet = NdisHandlePnPEvent( uiLayer,
uiOperation,
&ustrLower,
&ustrUpper,
&umstrBindList,
(PVOID)pvData,
dwSizeData );
if (!nRet)
{
//hr = HrFromLastWin32Error();
hr = GetLastError();
}
return( hr );
}
HRESULT
HrSendNdisPnpReconfig (
UINT uiLayer,
LPCWSTR wszUpper,
LPCWSTR wszLower,
PVOID pvData,
DWORD dwSizeData)
{
//Assert(NULL != wszUpper);
//Assert((NDIS == uiLayer)||(TDI == uiLayer));
//tstring strLower;
WCHAR strLower[512];
BOOL bSendNull = FALSE;
if (NULL == wszLower)
{
wszLower = c_szEmpty;
}
// If a lower component is specified, prefix with "\Device\" else
// strLower's default of an empty string will be used.
if ( wszLower && lstrlenW(wszLower))
{
//strLower = c_szDevice;
//strLower += wszLower;
wcscpy(strLower, c_szDevice);
wcscat(strLower, wszLower);
}
else
bSendNull = TRUE;
HRESULT hr = HrSendNdisHandlePnpEvent(uiLayer,
RECONFIGURE,
wszUpper,
//strLower.c_str(),
(bSendNull) ? NULL : strLower,
c_szEmpty,
pvData,
dwSizeData);
OutputDebugger( "HrSendNdisHandlePnpEvent: %x\n", hr);
return hr;
}
HRESULT HrSetIpxVirtualNetNum(DWORD dwValue)
{
RECONFIG Config;
HKEY hkey;
HRESULT hr;
// Open the registry key
LONG lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szIpxParameters, 0,
KEY_ALL_ACCESS, &hkey);
hr = HRESULT_FROM_WIN32(lr);
if (SUCCEEDED(hr))
{
// Splat the data
lr = RegSetValueEx(hkey, c_szVirtualNetworkNumber, 0,
REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
hr = HRESULT_FROM_WIN32(lr);
if (SUCCEEDED(hr))
{
memset(&Config, 0, sizeof(RECONFIG));
Config.ulVersion = IPX_RECONFIG_VERSION;
Config.InternalNetworkNumber = TRUE;
// Workstation or server?
// Paul, Normally I only send this notification for servers. I
// Assume you'll be able to distinguish
// Now submit the global reconfig notification
hr = HrSendNdisPnpReconfig(NDIS, c_szIpx, c_szEmpty, &Config, sizeof(RECONFIG));
}
RegCloseKey(hkey);
}
return hr;
}
// Here's the function we want -- it sets the ipx internal network number
// programatically.
EXTERN_C
DWORD SetIpxInternalNetNumber(DWORD dwNetNum) {
return HrSetIpxVirtualNetNum(dwNetNum);
}