Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1208 lines
32 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1998.
//
// File: N C A C S . C P P
//
// Contents: Installation support for ACS service
//
// Notes:
//
// Author: RameshPa 02/12/98
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "ncxbase.h"
#include "ncerror.h"
#include "ncreg.h"
#include "ncacs.h"
#include "ncsvc.h"
#include "netoc.h"
#include "ncnetcfg.h"
#include "resource.h"
#include <iphlpapi.h>
#include <winsock2.h>
#include <ntsecapi.h>
extern const WCHAR c_szSvcRsvp[];
static const WCHAR c_szTcpIp[] = L"TcpIp";
static const WCHAR c_szAfd[] = L"Afd";
static const WCHAR c_szAcsService[] = L"AcsService";
static const WCHAR c_szRegKeyRsvpParams[] = L"System\\CurrentControlSet\\Services\\RSVP\\Parameters\\";
static const WCHAR c_szRegKeyRsvpSubnet1[] = L"System\\CurrentControlSet\\Services\\RSVP\\Parameters\\Subnet\\Subnet1\\";
static const WCHAR c_szRegKeyRsvpSubnet[] = L"System\\CurrentControlSet\\Services\\RSVP\\Parameters\\Subnet\\";
static const WCHAR c_szRegKeyRsvpAdapters[]= L"System\\CurrentControlSet\\Services\\RSVP\\Parameters\\Adapters\\";
static const WCHAR c_szRegKeyRsvpPcmConfig[]= L"System\\CurrentControlSet\\Services\\RSVP\\PCM Config\\";
static const WCHAR c_szRegKeyRsvpMsidlpm[] = L"System\\CurrentControlSet\\Services\\RSVP\\MSIDLPM\\";
//$ REVIEW : RameshPa : 02/13/98 : Is this defined anywhere?
const DWORD dwKilo = 1024;
const DWORD dwMega = (1024 * dwKilo);
const DWORD dwGiga = (1024 * dwMega);
static const WCHAR c_szIpHlpApiDllName[] = L"IpHlpApi";
static const CHAR c_szaGetIpAddrTable[] = "GetIpAddrTable";
typedef DWORD (*GETIPADDRTABLE)(
OUT PMIB_IPADDRTABLE pIpAddrTable,
IN OUT PDWORD pdwSize,
IN BOOL bOrder);
struct ACS_SUBNET_REG_DATA
{
DWORD dwSubnetIpAddress; // This is in host order
DWORD dwDSBMPriority;
DWORD dwMaxRSVPBandwidth;
DWORD dwMaxTotalPeakRate;
DWORD dwMaxTokenBucketRatePerFlow;
DWORD dwMaxPeakRatePerFlow;
DWORD dwIAmDsbmRefreshInterval;
DWORD dwDSBMDeadInterval;
BOOL fRunAsDSBM;
};
// Subnet registry keys
//
static const WCHAR c_szRunAsDSBM[] = L"Run as DSBM";
static const WCHAR c_szSubnetIPAddress[] = L"Subnet IP Address";
static const WCHAR c_szMaxPeakRate[] = L"Maximum peak rate per flow";
static const WCHAR c_szMaxRSVPBandwidth[] = L"Maximum RSVP bandwidth";
static const WCHAR c_szMaxTokenBucket[] = L"Maximum token bucket rate per flow";
static const WCHAR c_szMaxTotalPeakRate[] = L"Maximum total peak rate";
static const WCHAR c_szIAmDsbmRefresh[] = L"I_AM_DSBM Refresh Interval";
static const WCHAR c_szDSBMDeadInterval[] = L"DSBM Dead Interval";
static const WCHAR c_szDSBMPriority[] = L"DSBM Priority";
// Default general property sheet values
//
const BOOL c_fRunAsDSBMDef = TRUE;
// Default subnet values
//
const DWORD c_dwIpAddressDef = 0;
static const WCHAR c_szIpAddressDef[] = L"0.0.0.0";
const DWORD c_dwMaxPeakRateDef = 0xFFFFFFFF;
const DWORD c_dwMaxRSVPBandwidthDef = 0;
const DWORD c_dwMaxTokenBucketDef = 0xFFFFFFFF;
const DWORD c_dwMaxTotalPeakRateDef = 0xFFFFFFFF;
const DWORD c_dwIAmDsbmRefreshDef = 5;
const DWORD c_dwDSBMDeadIntervalDef = 15;
const DWORD c_dwDSBMPriorityDef = 4;
// General values
// 127.0.0.0, host order
//
const DWORD c_dwLocalSubnet = 0x7f000000;
const DWORD c_dwNullSubnet = 0x00000000;
static const VALUETABLE c_avtAcsSubnet[] =
{
{c_szSubnetIPAddress, REG_IP, offsetof(ACS_SUBNET_REG_DATA, dwSubnetIpAddress),
(BYTE*)(&c_szIpAddressDef)},
{c_szMaxPeakRate, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwMaxPeakRatePerFlow),
(BYTE*)(&c_dwMaxPeakRateDef)},
{c_szMaxRSVPBandwidth, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwMaxRSVPBandwidth),
(BYTE*)(&c_dwMaxRSVPBandwidthDef)},
{c_szMaxTokenBucket, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwMaxTokenBucketRatePerFlow),
(BYTE*)(&c_dwMaxTokenBucketDef)},
{c_szMaxTotalPeakRate, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwMaxTotalPeakRate),
(BYTE*)(&c_dwMaxTotalPeakRateDef)},
{c_szIAmDsbmRefresh, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwIAmDsbmRefreshInterval),
(BYTE*)(&c_dwIAmDsbmRefreshDef)},
{c_szDSBMDeadInterval, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwDSBMDeadInterval),
(BYTE*)(&c_dwDSBMDeadIntervalDef)},
{c_szDSBMPriority, REG_DWORD, offsetof(ACS_SUBNET_REG_DATA, dwDSBMPriority),
(BYTE*)(&c_dwDSBMPriorityDef)},
{c_szRunAsDSBM, REG_BOOL, offsetof(ACS_SUBNET_REG_DATA, fRunAsDSBM),
(BYTE*) &c_fRunAsDSBMDef},
};
//+---------------------------------------------------------------------------
//
// Function: OpenPolicy
//
// Purpose: This routine opens the policy object on the local computer
//
// Arguments: PolicyHandle - Pointer to the opended handle
//
// Returns: ERROR_SUCCESS if successful, Win32 error otherwise.
//
// Notes: The retruned PolicyHandle must be closed by the caller
//
DWORD
OpenPolicy( PLSA_HANDLE PolicyHandle )
{
NTSTATUS Status;
DWORD Error;
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
SECURITY_QUALITY_OF_SERVICE QualityOfService;
QualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
QualityOfService.ImpersonationLevel = SecurityImpersonation;
QualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
QualityOfService.EffectiveOnly = FALSE;
//
// The two fields that must be set are length and the quality of service.
//
ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory = NULL;
ObjectAttributes.ObjectName = NULL;
ObjectAttributes.Attributes = 0;
ObjectAttributes.SecurityDescriptor = NULL;
ObjectAttributes.SecurityQualityOfService = &QualityOfService;
//
// Attempt to open the policy for all access on the local machine
//
Status = LsaOpenPolicy(
NULL,
&ObjectAttributes,
POLICY_ALL_ACCESS,
PolicyHandle );
Error = LsaNtStatusToWinError(Status);
return(Error);
}
//+---------------------------------------------------------------------------
//
// Function: InitLsaString
//
// Purpose: This routine intializes LSA_UNICODE_STRING given an UNICODE string0
//
// Arguments: LsaString
// String
//
// Returns:
//
// Notes:
//
void
InitLsaString(
PLSA_UNICODE_STRING LsaString,
PWSTR String )
{
DWORD StringLength;
if (String == NULL)
{
LsaString->Buffer = NULL;
LsaString->Length = 0;
LsaString->MaximumLength = 0;
return;
}
StringLength = wcslen(String);
LsaString->Buffer = String;
LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
LsaString->MaximumLength = (USHORT) (StringLength + 1) * sizeof(WCHAR);
}
//+---------------------------------------------------------------------------
//
// Function: InitLsaString
//
// Purpose: This routine intializes LSA_UNICODE_STRING given an UNICODE string0
//
// Arguments: LsaString
// String
//
// Returns:
//
// Notes:
//
PSID
GetAccountSid(
LSA_HANDLE PolicyHandle,
PWSTR AccountName
)
{
DWORD NewSidLength;
DWORD SubAuthorityCount;
PSID Sid;
PSID DomainSid;
NTSTATUS Status;
PLSA_TRANSLATED_SID TranslatedSid;
PLSA_REFERENCED_DOMAIN_LIST Domains;
LSA_UNICODE_STRING AccountString;
//
// Convert the string to a LSA_UNICODE_STRING
//
InitLsaString(
&AccountString,
AccountName
);
//
// Call the LSA to lookup the name
//
Status = LsaLookupNames(
PolicyHandle,
1,
&AccountString,
&Domains,
&TranslatedSid
);
if (!SUCCEEDED(Status))
return(NULL);
//
// Build a SID from the Domain SID and account RID
//
DomainSid = Domains->Domains[TranslatedSid->DomainIndex].Sid;
//
// Compute the length of the new SID. This is the length required for the
// number of subauthorities in the domain sid plus one for the user RID.
//
SubAuthorityCount = *GetSidSubAuthorityCount(DomainSid);
NewSidLength = GetSidLengthRequired( (UCHAR) (SubAuthorityCount + 1) );
Sid = LocalAlloc(0,NewSidLength);
if (Sid == NULL)
{
LsaFreeMemory(Domains);
LsaFreeMemory(TranslatedSid);
return(NULL);
}
//
// Build the SID by copying the domain SID and, increasing the sub-
// authority count in the new sid by one, and setting the last
// subauthority to be the relative id of the user.
//
CopySid(
NewSidLength,
Sid,
DomainSid
);
*GetSidSubAuthorityCount(Sid) = (UCHAR) SubAuthorityCount + 1;
*GetSidSubAuthority(Sid, SubAuthorityCount) = TranslatedSid->RelativeId;
LsaFreeMemory(Domains);
LsaFreeMemory(TranslatedSid);
return(Sid);
}
//+---------------------------------------------------------------------------
//
// Function: AddUserRightToAccount
//
// Purpose: This routine grants the SE_TCB_NAME right to the specified user
// account on the local machine
//
// Arguments: PolicyHandle
// AccountName
//
// Returns: ERROR_SUCCESS if the right was granted successfully
// Win32 error otherwise
//
// Notes:
//
DWORD
AddUserRightToAccount(
PWSTR AccountName )
{
DWORD Error;
NTSTATUS Status;
PSID AccountSid = NULL;
LSA_HANDLE PolicyHandle;
LSA_UNICODE_STRING UserRightString;
// Get a LSA policy handle to manipulate user rights
Error = OpenPolicy ( &PolicyHandle );
if ( Error )
return Error;
// Get the SID for the account
AccountSid = GetAccountSid(
PolicyHandle,
AccountName );
if (AccountSid == NULL)
{
LsaClose ( &PolicyHandle );
return(ERROR_NOT_ENOUGH_MEMORY);
}
//
// Create a LSA_UNICODE_STRING for the right name
//
InitLsaString(
&UserRightString,
SE_TCB_NAME );
// Grant the right
Status = LsaAddAccountRights(
PolicyHandle,
AccountSid,
&UserRightString,
1 );
Error = LsaNtStatusToWinError(Status);
LocalFree( AccountSid );
LsaClose ( &PolicyHandle );
return(Error);
}
//+---------------------------------------------------------------------------
//
// Function: AddUserRightToAccount
//
// Purpose: This routine removes the SE_TCB_NAME right to the specified user
// account on the local machine
//
// Arguments: PolicyHandle
// AccountName
//
// Returns: ERROR_SUCCESS if the right was rmoved successfully
// Win32 error otherwise
//
// Notes:
//
DWORD
RemoveUserRightFromAccount(
PWSTR AccountName )
{
NTSTATUS Status;
DWORD Error;
PSID AccountSid;
LSA_HANDLE PolicyHandle;
LSA_UNICODE_STRING UserRightString;
// Get a LSA policy handle to manipulate user rights
Error = OpenPolicy ( &PolicyHandle );
if ( Error )
return Error;
AccountSid = GetAccountSid(
PolicyHandle,
AccountName );
if (AccountSid == NULL)
{
LsaClose ( &PolicyHandle );
return(ERROR_NOT_ENOUGH_MEMORY);
}
//
// Create a LSA_UNICODE_STRING for the right name
//
InitLsaString(
&UserRightString,
SE_TCB_NAME );
Status = LsaRemoveAccountRights(
PolicyHandle,
AccountSid,
FALSE, // don't remove all rights
&UserRightString,
1 );
Error = LsaNtStatusToWinError(Status);
LocalFree(AccountSid);
LsaClose ( &PolicyHandle );
return(Error);
}
//+---------------------------------------------------------------------------
//
// Function: HrGetAcsServiceAccountName
//
// Purpose: This routine returns the AcsService account name in the
// DomainName\UserName format. DomainName is obtained from
// the current logon domain.
//
// Arguments: lpwNtAccountName - Buffer to return the account name.
//
// Returns: S_OK If the account name was generated
// Win32 error otherwise
//
// Notes:
//
HRESULT HrGetAcsServiceAccountName (
PWSTR lpwNtAccountName )
{
DWORD dwErr;
HRESULT hr;
PWSTR lpwDomain = NULL;
PWSTR lpwDcName = NULL;
LPBYTE lpbUserInfo = NULL;
NETSETUP_JOIN_STATUS js;
lpwNtAccountName[0] = 0;
// Get the name of the DC for the logged on domain
dwErr = NetGetDCName (
NULL,
NULL,
(LPBYTE *) &lpwDcName );
if ( dwErr ) {
hr = HRESULT_FROM_WIN32(dwErr);
goto Exit;
}
// Next get user info to verify that there is a user
// account for AcsService
dwErr = NetUserGetInfo (
lpwDcName,
c_szAcsService,
2,
&lpbUserInfo );
if ( dwErr ) {
hr = HRESULT_FROM_WIN32(dwErr);
goto Exit;
}
// Find out the name of the domain into which this compter
// is currently logged on to
dwErr = NetGetJoinInformation (
NULL,
&lpwDomain,
&js );
if ( dwErr ) {
hr = HRESULT_FROM_WIN32(dwErr);
goto Exit;
}
if ( js != NetSetupDomainName ) {
hr = NETCFG_E_NOT_JOINED;
goto Exit;
}
// Generate the account name by concatenating domain name and "AcsService"
wcscpy ( lpwNtAccountName, lpwDomain );
wcscat ( lpwNtAccountName, L"\\" );
wcscat ( lpwNtAccountName, c_szAcsService );
hr = S_OK;
Exit:
if ( lpwDcName )
NetApiBufferFree ( lpwDcName );
if ( lpbUserInfo )
NetApiBufferFree ( lpbUserInfo );
if ( lpwDomain )
NetApiBufferFree ( lpwDomain );
TraceError("HrGetAcsServiceAccountName", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrSetAcsServiceRights
//
// Purpose: This routine adds the AcsService account to the administrators group
// on the local computer and grants SE_TCB_NAME right also
//
// Arguments:
//
// Returns: S_OK Success
// Win32 error otherwise
//
// Notes:
//
HRESULT HrSetAcsServiceRights( )
{
DWORD dwErr;
HRESULT hr;
WCHAR szAcsUserName[UNLEN+GNLEN+2];
PWSTR lpwAcsUserName;
LOCALGROUP_MEMBERS_INFO_3 localgroup_members;
// First get the user name of AcsService in the format
// DomainName\UserName
hr = ::HrGetAcsServiceAccountName ( szAcsUserName );
if ( hr ) {
hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME);
goto Exit;
}
if ( !szAcsUserName[0] ) {
hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME);
goto Exit;
}
// Add AcsService account to be a local administrator
localgroup_members.lgrmi3_domainandname = szAcsUserName;
dwErr = NetLocalGroupAddMembers(
NULL, // PDC name
L"Administrators", // group name
3, // passing in name
(LPBYTE)&localgroup_members, // Buffer
1 ); // count passed in
if ( dwErr ) {
if ( dwErr == ERROR_MEMBER_IN_ALIAS ) {
hr = S_OK;
dwErr = 0;
}
else {
hr = HRESULT_FROM_WIN32(dwErr);
goto Exit;
}
}
// Grant SE_TCB_NAME "Act as part of Operating system" right to AcsService
dwErr = AddUserRightToAccount(
szAcsUserName );
if ( dwErr ) {
hr = HRESULT_FROM_WIN32( dwErr );
goto Exit;
}
hr = S_OK;
Exit:
TraceError ( "HrSetAcsServiceRights", hr );
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRemoveAcsServiceRights
//
// Purpose: This routine removes the AcsService account from the administrators group
// on the local computer and removes SE_TCB_NAME right.
//
// Arguments:
//
// Returns: S_OK Success
// Win32 error otherwise
//
// Notes:
//
HRESULT HrRemoveAcsServiceRights( )
{
DWORD dwErr;
HRESULT hr;
WCHAR szAcsUserName[UNLEN+GNLEN+2];
LOCALGROUP_MEMBERS_INFO_3 localgroup_members;
// First get the user name of AcsService in the format
// DomainName\UserName
hr = ::HrGetAcsServiceAccountName ( szAcsUserName );
if ( hr ) {
hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME);
goto Exit;
}
if ( !szAcsUserName[0] ) {
hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME);
goto Exit;
}
// Remove AcsService account to be a local administrator
localgroup_members.lgrmi3_domainandname = szAcsUserName;
dwErr = NetLocalGroupDelMembers(
NULL, // PDC name
L"Administrators", // group name
3, // passing in name
(LPBYTE)&localgroup_members, // Buffer
1 ); // count passed in
if ( dwErr ) {
if ( dwErr == ERROR_MEMBER_NOT_IN_ALIAS ) {
hr = S_OK;
dwErr = 0;
}
else {
hr = HRESULT_FROM_WIN32(dwErr);
goto Exit;
}
}
// Grant "Act as part of Operating system" right to AcsService
dwErr = RemoveUserRightFromAccount(
szAcsUserName );
if ( dwErr ) {
hr = HRESULT_FROM_WIN32( dwErr );
goto Exit;
}
hr = S_OK;
Exit:
TraceError ( "HrRemoveAcsServiceRights", hr );
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrGetIpAddrTable
//
// Purpose: Gets the address table of the subnets that machine can see
//
// Arguments: ppmiat - Where to return the allocated address table
//
// Returns: S_OK if successful, Win32 error otherwise.
//
// Notes: The result must be freed by the caller
//
HRESULT HrGetIpAddrTable(MIB_IPADDRTABLE** ppmiat)
{
HRESULT hr = S_OK;
DWORD dwErr = NO_ERROR;
HMODULE hIpHelpApi = NULL;
GETIPADDRTABLE pfnGetIpAddrTable = NULL;
AssertSz(ppmiat , "HrGetIpAddrTable doesn't have a ppmiat");
// Make sure we have our function loaded
//
hr = ::HrLoadLibAndGetProc(
c_szIpHlpApiDllName,
c_szaGetIpAddrTable,
&hIpHelpApi,
(FARPROC*)&pfnGetIpAddrTable);
if (SUCCEEDED(hr))
{
DWORD dwAddrCount = 0;
AssertSz(pfnGetIpAddrTable, "We should have a pfnGetIpAddrTable");
// Find out how big a buffer we need.
//
dwErr = pfnGetIpAddrTable(*ppmiat, &dwAddrCount, FALSE);
hr = HRESULT_FROM_WIN32(dwErr);
// Allocate the buffer of the correct size
//
if ((NO_ERROR == dwErr)
|| (ERROR_INSUFFICIENT_BUFFER == dwErr))
{
UINT cbTable = 0;
// Create the buffer
//
cbTable = (sizeof(MIB_IPADDRTABLE)
+ (sizeof(MIB_IPADDRROW) * (dwAddrCount)));
*ppmiat = reinterpret_cast<MIB_IPADDRTABLE*>(new BYTE [cbTable]);
// Try a second time with the correct buffer
//
dwErr = pfnGetIpAddrTable(*ppmiat, &dwAddrCount, FALSE);
hr = HRESULT_FROM_WIN32(dwErr);
}
// Unload the DLL
//
(VOID)::FreeLibrary(hIpHelpApi);
}
TraceErrorOptional("HrGetIpAddrTable", hr,
(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED) == hr));
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrFindFirstSubnet
//
// Purpose: Finds the first available subnet on the system to be used as
// the default entry in the registry. If a subnet cannot be found
// 000.000.000.000 is used.
//
// Arguments: pdwSubnet - Where to return the subnet
//
// Returns: Error code
//
// Notes:
//
HRESULT HrFindFirstSubnet(DWORD* pdwSubnet)
{
HRESULT hr = S_OK;
MIB_IPADDRTABLE* ppmiat = NULL;
// Get our list of address entries
//
hr = HrGetIpAddrTable(&ppmiat);
if (SUCCEEDED(hr))
{
MIB_IPADDRROW* pmiarTemp = ppmiat->table;
DWORD dwIpAddrCount = ppmiat->dwNumEntries;
DWORD dwSubnet = 0x0;
while (dwIpAddrCount--)
{
// Find out what the sub net is
//
dwSubnet = (pmiarTemp->dwAddr & pmiarTemp->dwMask);
// The APIs return the value in network order, and we want to
// store the data in host order, so we have to convert the
// address
//
dwSubnet = ntohl(dwSubnet);
// Don't add invalid subnets to the list
//
if ((c_dwLocalSubnet != dwSubnet)
&& (c_dwNullSubnet != dwSubnet))
{
// We found one!!
//
*pdwSubnet = dwSubnet;
break;
}
// Look at the next entry
//
pmiarTemp++;
}
// Free the allocated memory
//
delete ppmiat;
}
TraceError("HrFindFirstSubnet", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrWriteAcsSubnetDataToReg
//
// Purpose: Writes out the subnet information to the registry
//
// Arguments: pasrdSubnet - The data that has to be written
//
// Returns: Error code
//
// Notes:
//
HRESULT HrWriteAcsSubnetDataToReg(ACS_SUBNET_REG_DATA* pasrdSubnet)
{
HRESULT hr = S_OK;
HKEY hkeySubnet = NULL;
DWORD dwDisposition = 0x0;
hr = ::HrRegCreateKeyEx(
HKEY_LOCAL_MACHINE,
c_szRegKeyRsvpSubnet,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkeySubnet,
&dwDisposition);
if (SUCCEEDED(hr))
{
// Write out the parameters
//
hr = ::HrRegWriteValueTable(
hkeySubnet,
celems(c_avtAcsSubnet),
c_avtAcsSubnet,
reinterpret_cast<BYTE*>(pasrdSubnet),
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS);
::RegSafeCloseKey(hkeySubnet);
}
TraceError("HrWriteAcsSubnetDataToReg", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrWriteAcsRegistryData
//
// Purpose: Writes to the registry all of ACS's default parameters
//
// Arguments: pnocd - The option component information that is
// needed to get an INetCfg instance
// pasrdSubnet - The subnet information
// palrdLog - The logging information
//
// Returns: Error code
//
// Notes:
//
HRESULT HrWriteAcsRegistryData(
PNETOCDATA pnocd )
{
HRESULT hr = S_OK;
ACS_SUBNET_REG_DATA asrdSubnet = { 0 };
// See if we can find a subnet
//
hr = ::HrFindFirstSubnet(&(asrdSubnet.dwSubnetIpAddress));
if (SUCCEEDED(hr))
{
// Default subnet values
//
asrdSubnet.dwDSBMPriority = c_dwDSBMPriorityDef;
asrdSubnet.dwMaxPeakRatePerFlow = c_dwMaxPeakRateDef;
asrdSubnet.dwMaxRSVPBandwidth = c_dwMaxRSVPBandwidthDef;
asrdSubnet.dwMaxTokenBucketRatePerFlow = c_dwMaxTokenBucketDef;
asrdSubnet.dwMaxTotalPeakRate = c_dwMaxTotalPeakRateDef;
asrdSubnet.dwIAmDsbmRefreshInterval = c_dwIAmDsbmRefreshDef;
asrdSubnet.dwDSBMDeadInterval = c_dwDSBMDeadIntervalDef;
asrdSubnet.fRunAsDSBM = c_fRunAsDSBMDef;
hr = ::HrWriteAcsSubnetDataToReg(&asrdSubnet);
if (SUCCEEDED(hr))
{
::HrWriteAcsRegistryData(pnocd);
}
}
TraceError("HrWriteAcsRegistryData", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrChangeRsvpService
//
// Purpose: Change some RSVP service parameters
//
// Arguments: szDisplayName - The new display name
// dwStartType - The new start type
// fStartService - If the service should be started
//
// Returns: Error code
//
// Notes:
//
HRESULT HrChangeRsvpService(
const WCHAR* szDisplayName,
DWORD dwStartType,
BOOL fStartService)
{
HRESULT hr = S_OK;
CServiceManager scm;
CService svc;
// Open the RSVP service with a lock on the service controller.
//
hr = scm.HrOpenService(&svc, c_szSvcRsvp, NO_LOCK);
if (SUCCEEDED(hr))
{
hr = scm.HrAddServiceDependency ( c_szSvcRsvp, c_szTcpIp );
if (SUCCEEDED(hr))
{
hr = scm.HrAddServiceDependency ( c_szSvcRsvp, c_szAfd );
if (SUCCEEDED(hr))
{
// Set the new start type
//
hr = svc.HrSetStartType(dwStartType);
if (SUCCEEDED(hr))
{
// Change the display name
//
hr = svc.HrSetDisplayName(szDisplayName);
if (SUCCEEDED(hr) && fStartService)
{
// Unlock the Service Control Manager so that we can
// start the service.
//
// scm.Unlock();
// Start up the service
//
hr = scm.HrStartServiceNoWait(c_szSvcRsvp);
}
}
}
}
}
TraceError("HrChangeRsvpService", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInstallACS
//
// Purpose: Called when ACS service is being installed. Handles all of the
// additional installation for ACS beyond that of the INF file.
//
// Arguments:
// pnocd [in] Pointer to NETOC data.
//
// Returns: S_OK if successful, Win32 error otherwise.
//
// Notes:
//
HRESULT HrInstallACS(PNETOCDATA pnocd)
{
HRESULT hr = S_OK;
#ifdef NEVER
// For NT 5.0 beta 2, setting rights for AcsService user name will not be done as this
// is introducing significant delay.
// Make AcsService to be local admin and grant SE_TCB_NAME right
hr = ::HrSetAcsServiceRights();
if (SUCCEEDED(hr)) {
// Display a message box asking the user to change the logon name
NcMsgBox( g_ocmData.hwnd,
IDS_OC_CAPTION,
IDS_OC_ACS_CHG_LOGON,
MB_ICONSTOP | MB_OK);
}
#endif // NEVER
// Ignoring any error from changing rights and continue with the
// setup so that ACS will run in Resouce only mode.
// Change the RSVP service parameters
hr = ::HrChangeRsvpService(
::SzLoadIds(IDS_OC_ACS_SERVICE_NAME),
SERVICE_AUTO_START,
TRUE);
TraceError("HrInstallACS", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRemoveACS
//
// Purpose: Handles additional removal requirements for ACS Service
// component.
//
// hwnd [in] Parent window for displaying UI.
// poc [in] Pointer to optional component being installed.
//
// Returns: S_OK if successful, Win32 error otherwise.
//
// Notes:
//
HRESULT HrRemoveACS(PNETOCDATA pnocd)
{
HRESULT hr = S_OK;
#ifdef NEVER
// For NT 5.0 beta 2, Removing AcsService user right will not be done as this
// is introducing significant delay.
// Drop the membership from local admins and remove SE_TCB_NAME right
(VOID)::HrRemoveAcsServiceRights ();
#endif // NEVER
//
// Clean out the adapters and subnet reg keys (if present)
//
(VOID)::HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, c_szRegKeyRsvpAdapters);
(VOID)::HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, c_szRegKeyRsvpSubnet1);
(VOID)::HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, c_szRegKeyRsvpSubnet);
// Put the name back the way it should be
//
(VOID)::HrChangeRsvpService(
::SzLoadIds(IDS_OC_RSVP_SERVICE_NAME),
SERVICE_DEMAND_START,
FALSE);
TraceError("HrRemoveACS", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrOcExtACS
//
// Purpose: NetOC external message handler
//
// Arguments:
// pnocd []
// uMsg []
// wParam []
// lParam []
//
// Returns:
//
// Author: danielwe 17 Sep 1998
//
// Notes:
//
HRESULT HrOcExtACS(PNETOCDATA pnocd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
HRESULT hr = S_OK;
Assert(pnocd);
switch (uMsg)
{
case NETOCM_POST_INSTALL:
hr = HrOcAcsOnInstall(pnocd);
break;
case NETOCM_QUERY_CHANGE_SEL_STATE:
hr = HrOcAcsOnQueryChangeSelState(pnocd, static_cast<BOOL>(wParam));
break;
}
TraceError("HrOcExtACS", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrOcAcsOnInstall
//
// Purpose: Called by optional components installer code to handle
// additional installation requirements for ACS Server
//
// Arguments:
// pnocd [in] Pointer to NETOC data
//
// Returns: S_OK if successful, Win32 error otherwise.
//
// Notes:
//
HRESULT HrOcAcsOnInstall(PNETOCDATA pnocd)
{
HRESULT hr = S_OK;
if (IT_INSTALL == pnocd->eit)
{
hr = HrInstallACS(pnocd);
}
else if (IT_REMOVE == pnocd->eit)
{
hr = HrRemoveACS(pnocd);
}
TraceError("HrOcAcsOnInstall", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrOcAcsOnQueryChangeSelState
//
// Purpose: Handles the request of the OC framework of whether or not
// the user should be allowed to install ACS on this host.
//
// Arguments:
// pnocd [in] NetOC Data
// fShowUi [in] TRUE if UI should be shown, FALSE if not
//
// Returns: S_OK if install is allowed, S_FALSE if not, Win32 error
// otherwise
//
// Author: rameshpa 23 April 1998
//
// Notes:
//
HRESULT HrOcAcsOnQueryChangeSelState(PNETOCDATA pnocd, BOOL fShowUi)
{
HRESULT hr = S_OK;
#ifdef NEVER
// For NT 5.0 beta 2, checking for user name will not be done as this
// is introducing significant delay.
WCHAR szAcsUserName[UNLEN+GNLEN+2];
Assert(pnocd);
Assert(g_ocmData.hwnd);
// See if AcsService account exists in this domain or not
hr = HrGetAcsServiceAccountName(szAcsUserName);
if ( FAILED(hr)
|| !szAcsUserName[0] )
{
if (fShowUi)
{
NcMsgBox( g_ocmData.hwnd,
IDS_OC_CAPTION,
IDS_OC_NO_ACS_USER_ACCOUNT,
MB_ICONSTOP | MB_OK);
}
// Allow ACS setup to continue, as ACS will default to
// Resource only
hr = S_FALSE;
}
TraceError("HrOcAcsOnQueryChangeSelState", hr);
#endif // NEVER
return hr;
}