windows-nt/Source/XPSP1/NT/net/dhcp/dhcpprov/dll/snetfn.cpp
2020-09-26 16:20:57 +08:00

567 lines
17 KiB
C++

/******************************************************************
SNetFn.cpp -- Properties action functions (GET/SET)
MODULE:
DhcpProv.dll
DESCRIPTION:
Contains the definition for the action functions associated to
each manageable property from the class CDHCP_Server
REVISION:
08/03/98 - created
******************************************************************/
#include <stdafx.h>
#include "SNetScal.h" // needed for DHCP_Subnet_Property[] (for retrieving the property's name, for SET's)
#include "SNetFn.h" // own header
/*****************************************************************
* The definition of the class CDHCP_Subnet_Parameters
*****************************************************************/
// by default, all the data structures are NULL (and dw variables are 0'ed)
// those values indicates that no data is cached from the server.
CDHCP_Subnet_Parameters::CDHCP_Subnet_Parameters(DHCP_IP_ADDRESS dwSubnetAddress)
{
m_dwSubnetAddress = dwSubnetAddress;
m_pMibInfo = NULL;
m_pScopeMibInfo = NULL;
m_pSubnetInfo = NULL;
}
CDHCP_Subnet_Parameters::CDHCP_Subnet_Parameters(DHCP_IP_ADDRESS dwSubnetAddress, DHCP_IP_ADDRESS dwSubnetMask)
{
m_dwSubnetAddress = dwSubnetAddress;
m_pMibInfo = NULL;
m_pScopeMibInfo = NULL;
m_pSubnetInfo = NULL;
CheckExistsInfoPtr();
if (m_pSubnetInfo != NULL)
m_pSubnetInfo->SubnetMask = dwSubnetMask;
}
// the DHCP API calls are allocating memory for which the caller is responsible
// to release. We are releasing this memory upon the destruction of this object's instance.
CDHCP_Subnet_Parameters::~CDHCP_Subnet_Parameters()
{
if (m_pMibInfo != NULL)
{
if (m_pMibInfo->ScopeInfo != NULL)
DhcpRpcFreeMemory(m_pMibInfo->ScopeInfo);
DhcpRpcFreeMemory(m_pMibInfo);
}
// LPDHCP_CONFIG_INFO_V4 contains pointers to memory allocated by the DHCP server and
// which should be released by the caller.
if (m_pSubnetInfo!= NULL)
{
if (m_pSubnetInfo->SubnetName != NULL)
DhcpRpcFreeMemory(m_pSubnetInfo->SubnetName);
if (m_pSubnetInfo->SubnetComment != NULL)
DhcpRpcFreeMemory(m_pSubnetInfo->SubnetComment);
DhcpRpcFreeMemory(m_pSubnetInfo);
}
}
// DESCRIPTION:
// Checks the m_pConfigInfoV4 pointer to insure it points to a valid buffer.
// It allocates the DHCP_SUBNET_INFO if needed.
BOOL CDHCP_Subnet_Parameters::CheckExistsInfoPtr()
{
if (m_pSubnetInfo != NULL)
return TRUE;
m_pSubnetInfo = (LPDHCP_SUBNET_INFO)MIDL_user_allocate(sizeof(DHCP_SUBNET_INFO));
if (m_pSubnetInfo != NULL)
{
m_pSubnetInfo->SubnetAddress = m_dwSubnetAddress;
return TRUE;
}
return FALSE;
}
// DESCRIPTION:
// Provides the data structure filled in through the DhcpGetMibInfo API
// If this data is cached and the caller is not forcing the refresh,
// returns the internal cache.
BOOL CDHCP_Subnet_Parameters::GetMibInfo(LPDHCP_MIB_INFO& pMibInfo, LPSCOPE_MIB_INFO& pScopeMibInfo, BOOL fRefresh)
{
if (m_pMibInfo == NULL)
fRefresh = TRUE;
if (fRefresh)
{
pMibInfo = NULL;
if (DhcpGetMibInfo(SERVER_IP_ADDRESS, &pMibInfo) != ERROR_SUCCESS)
return FALSE;
if (m_pMibInfo != NULL)
DhcpRpcFreeMemory(m_pMibInfo);
m_pMibInfo = pMibInfo;
pScopeMibInfo = NULL;
for (int i=0; i<pMibInfo->Scopes; i++)
{
LPSCOPE_MIB_INFO pLocal = &pMibInfo->ScopeInfo[i];
if (pLocal != NULL && pLocal->Subnet == m_dwSubnetAddress)
{
pScopeMibInfo = pLocal;
break;
}
}
m_pScopeMibInfo = pScopeMibInfo;
}
else
{
pMibInfo = m_pMibInfo;
pScopeMibInfo = m_pScopeMibInfo;
}
return TRUE;
}
// DESCRIPTION:
// Provides the data structure filled in through the DhcpSubnetInfo API
// If this data is cached and the caller is not forcing the refresh,
// return the internal cache. Otherwise, the internal cache is refreshed as well.
BOOL CDHCP_Subnet_Parameters::GetSubnetInfo(LPDHCP_SUBNET_INFO& pSubnetInfo, BOOL fRefresh)
{
if (m_pSubnetInfo == NULL)
fRefresh = TRUE;
if (fRefresh)
{
pSubnetInfo = NULL;
if (DhcpGetSubnetInfo(SERVER_IP_ADDRESS, m_dwSubnetAddress, &pSubnetInfo) != ERROR_SUCCESS)
return FALSE;
if (m_pSubnetInfo != NULL)
DhcpRpcFreeMemory(m_pSubnetInfo);
m_pSubnetInfo = pSubnetInfo;
}
else
pSubnetInfo = m_pSubnetInfo;
return TRUE;
}
// DESCRIPTION:
// Creates a new subnet.
// Assumes that all the fields from the DHCP_SUBNET_INFO structure are valid, and filled with
// the data to be set. Calls the underlying API and returns TRUE (on success) or FALSE (on failure)
BOOL CDHCP_Subnet_Parameters::CommitNew(DWORD &returnCode)
{
if (m_pSubnetInfo == NULL)
return FALSE;
returnCode = DhcpCreateSubnet(
SERVER_IP_ADDRESS,
m_pSubnetInfo->SubnetAddress,
m_pSubnetInfo );
return returnCode == ERROR_SUCCESS;
}
// DESCRIPTION:
// Modifies info on an existing subnet.
// Assumes that all the fields from the DHCP_SUBNET_INFO structure are valid, and filled with
// the data to be set. Calls the underlying API and returns TRUE (on success) or FALSE (on failure)
BOOL CDHCP_Subnet_Parameters::CommitSet(DWORD &returnCode)
{
if (m_pSubnetInfo == NULL)
return FALSE;
returnCode = DhcpSetSubnetInfo(
SERVER_IP_ADDRESS,
m_pSubnetInfo->SubnetAddress,
m_pSubnetInfo );
return returnCode == ERROR_SUCCESS;
}
// DESCRIPTION:
// Assumes the m_dwSubnet is initialized, case in which it calls the DHCPAPI to delete that subnet
// from the server.
BOOL CDHCP_Subnet_Parameters::DeleteSubnet()
{
if (DhcpDeleteSubnet(SERVER_IP_ADDRESS, m_dwSubnetAddress, DhcpFullForce) == ERROR_SUCCESS)
{
m_dwSubnetAddress = 0;
// don't look below :o)
// It's only an exotic way of calling the destructor without destroying the object itself
this->~CDHCP_Subnet_Parameters();
m_pSubnetInfo = NULL;
m_pScopeMibInfo = NULL;
m_pMibInfo = NULL;
return TRUE;
}
return FALSE;
}
/*------------------------Property Action Functions below-----------------------*/
// unlike for SrvScal, we expect the pParams to be not-null, or otherwise this call fails.
// we do this because pParams is the one holding the subnet address which must be known
// in order to call the DHCP api (it has to be filled in by the caller).
// This applies to all 'GET' functions.
MFN_PROPERTY_ACTION_DEFN(fnSNetGetAddress, pParams, pIn, pOut)
{
BOOL fRefresh;
CDHCP_Subnet_Parameters *pSubnetParams;
LPDHCP_SUBNET_INFO pSubnetInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pSubnetParams = (CDHCP_Subnet_Parameters *)pParams;
fRefresh = pSubnetParams->m_pSubnetInfo == NULL;
if (pSubnetParams->GetSubnetInfo(pSubnetInfo, fRefresh) &&
pSubnetInfo != NULL)
{
// nothing special to do here, the property (Address) should be just there!
return TRUE;
}
// the API call failed
return FALSE;
}
MFN_PROPERTY_ACTION_DEFN(fnSNetGetMask, pParams, pIn, pOut)
{
BOOL fRefresh;
CDHCP_Subnet_Parameters *pSubnetParams;
LPDHCP_SUBNET_INFO pSubnetInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pSubnetParams = (CDHCP_Subnet_Parameters *)pParams;
fRefresh = pSubnetParams->m_pSubnetInfo == NULL;
if (pSubnetParams->GetSubnetInfo(pSubnetInfo, fRefresh) &&
pSubnetInfo != NULL)
{
WCHAR szMask[16]; // should be enough for holding 'xxx.yyy.zzz.uuu\0'
swprintf(szMask, L"%u.%u.%u.%u",(pSubnetInfo->SubnetMask & 0xff000000) >> 24,
(pSubnetInfo->SubnetMask & 0x00ff0000) >> 16,
(pSubnetInfo->SubnetMask & 0x0000ff00) >> 8,
(pSubnetInfo->SubnetMask & 0x000000ff));
pOut->SetCHString(DHCP_Subnet_Property[IDX_SNET_Mask].m_wsPropName, szMask);
return TRUE;
}
// the API call failed
return FALSE;
}
MFN_PROPERTY_ACTION_DEFN(fnSNetGetName, pParams, pIn, pOut)
{
BOOL fRefresh;
CDHCP_Subnet_Parameters *pSubnetParams;
LPDHCP_SUBNET_INFO pSubnetInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pSubnetParams = (CDHCP_Subnet_Parameters *)pParams;
fRefresh = pSubnetParams->m_pSubnetInfo == NULL;
if (pSubnetParams->GetSubnetInfo(pSubnetInfo, fRefresh) &&
pSubnetInfo != NULL)
{
pOut->SetCHString(DHCP_Subnet_Property[IDX_SNET_Name].m_wsPropName, pSubnetInfo->SubnetName);
return TRUE;
}
// the API call failed
return FALSE;
}
// Set functions require the SubnetAddress which can be taken only from pParams.
// The changes are applied instantly only if pOut is not NULL (so the caller wants and
// gets a return code)
MFN_PROPERTY_ACTION_DEFN(fnSNetSetName, pParams, pIn, pOut)
{
CDHCP_Subnet_Parameters *pSubnetParams;
CHString wsName;
// pParams and pIn have to be valid to provide the SubnetAddress and the Name to set
if (pParams == NULL || pIn == NULL)
return FALSE;
// get the CDHCP_Subnet_Parameters out of pParams
pSubnetParams = (CDHCP_Subnet_Parameters *)pParams;
// make sure there is a buffer for holding all this info.
pSubnetParams->CheckExistsInfoPtr();
// get the value to set from the pIn parameter
if (!pIn->GetCHString(DHCP_Subnet_Property[IDX_SNET_Name].m_wsPropName, wsName))
return FALSE;
// release any old buffer
if (pSubnetParams->m_pSubnetInfo->SubnetName != NULL)
DhcpRpcFreeMemory(pSubnetParams->m_pSubnetInfo->SubnetName);
// allocate a new buffer able to hold this new name
pSubnetParams->m_pSubnetInfo->SubnetName = (WCHAR*)MIDL_user_allocate(sizeof(WCHAR)*wsName.GetLength()+sizeof(WCHAR));
// make sure the allocation succeeded
if (pSubnetParams->m_pSubnetInfo->SubnetName == NULL)
return FALSE;
// copy the name to the new buffer
#ifdef _UNICODE
wcscpy(pSubnetParams->m_pSubnetInfo->SubnetName, wsName);
#else
swprintf(pSubnetParams->m_pSubnetInfo->SubnetName, L"%S", wsName);
#endif
// if this is a request for 'instant apply', do it now
if (pOut != NULL)
{
DWORD errCode;
pSubnetParams->CommitSet(errCode);
// fill back the code returned by the underlying level
if (pOut != NULL)
pOut->SetDWORD(RETURN_CODE_PROPERTY_NAME, errCode);
}
// the API call succeeded
return TRUE;
}
MFN_PROPERTY_ACTION_DEFN(fnSNetGetComment, pParams, pIn, pOut)
{
BOOL fRefresh;
CDHCP_Subnet_Parameters *pSubnetParams;
LPDHCP_SUBNET_INFO pSubnetInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pSubnetParams = (CDHCP_Subnet_Parameters *)pParams;
fRefresh = pSubnetParams->m_pSubnetInfo == NULL;
if (pSubnetParams->GetSubnetInfo(pSubnetInfo, fRefresh) &&
pSubnetInfo != NULL)
{
pOut->SetCHString(DHCP_Subnet_Property[IDX_SNET_Comment].m_wsPropName, pSubnetInfo->SubnetComment);
return TRUE;
}
// the API call failed
return FALSE;
}
// Set functions require the SubnetAddress which can be taken only from pParams.
// The changes are applied instantly only if pOut is not NULL (so the caller wants and
// gets a return code)
MFN_PROPERTY_ACTION_DEFN(fnSNetSetComment, pParams, pIn, pOut)
{
CDHCP_Subnet_Parameters *pSubnetParams;
CHString wsComment;
// pIn has to be not-null to provide the comment
if (pParams == NULL || pIn == NULL)
return FALSE;
// get the pSubnetParams out of pParams
pSubnetParams = (CDHCP_Subnet_Parameters *)pParams;
// make sure there is a buffer for holding all this info.
pSubnetParams->CheckExistsInfoPtr();
// get the value to set from the pIn parameter
if (!pIn->GetCHString(DHCP_Subnet_Property[IDX_SNET_Comment].m_wsPropName, wsComment))
return FALSE;
// release any old buffer
if (pSubnetParams->m_pSubnetInfo->SubnetComment != NULL)
DhcpRpcFreeMemory(pSubnetParams->m_pSubnetInfo->SubnetComment);
// allocate a new buffer able to hold the new comment
pSubnetParams->m_pSubnetInfo->SubnetComment = (WCHAR*)MIDL_user_allocate(sizeof(WCHAR)*wsComment.GetLength()+sizeof(WCHAR));
if (pSubnetParams->m_pSubnetInfo->SubnetComment == NULL)
return FALSE;
// copy the comment to the new buffer
#ifdef _UNICODE
wcscpy(pSubnetParams->m_pSubnetInfo->SubnetComment, wsComment);
#else
swprintf(pSubnetParams->m_pSubnetInfo->SubnetComment, L"%S", wsComment);
#endif
// if this is a request for 'instant apply', do it now
if (pOut != NULL)
{
DWORD errCode;
pSubnetParams->CommitSet(errCode);
// fill back the code returned by the underlying level
if (pOut != NULL)
pOut->SetDWORD(RETURN_CODE_PROPERTY_NAME, errCode);
}
// the API call succeeded
return TRUE;
}
MFN_PROPERTY_ACTION_DEFN(fnSNetGetState, pParams, pIn, pOut)
{
BOOL fRefresh;
CDHCP_Subnet_Parameters *pSubnetParams;
LPDHCP_SUBNET_INFO pSubnetInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pSubnetParams = (CDHCP_Subnet_Parameters *)pParams;
fRefresh = pSubnetParams->m_pSubnetInfo == NULL;
if (pSubnetParams->GetSubnetInfo(pSubnetInfo, fRefresh) &&
pSubnetInfo != NULL)
{
pOut->SetDWORD(DHCP_Subnet_Property[IDX_SNET_State].m_wsPropName, pSubnetInfo->SubnetState);
return TRUE;
}
// the API call failed
return FALSE;
}
// Set functions require the SubnetAddress which can be taken only from pParams.
// The changes are applied instantly only if pOut is not NULL (so the caller wants and
// gets a return code)
MFN_PROPERTY_ACTION_DEFN(fnSNetSetState, pParams, pIn, pOut)
{
CDHCP_Subnet_Parameters *pSubnetParams;
DWORD dwState;
// pIn has to be not-null to provide the new State
if (pParams == NULL || pIn == NULL)
return FALSE;
// get pSubnetParams out of pParams
pSubnetParams = (CDHCP_Subnet_Parameters *)pParams;
// make sure there is a buffer for holding all this info.
pSubnetParams->CheckExistsInfoPtr();
// get the value to set from the pIn parameter
if (!pIn->GetDWORD(DHCP_Subnet_Property[IDX_SNET_State].m_wsPropName, dwState))
return FALSE;
// test roughly if the new value matches the range of admissible values
switch((DHCP_SUBNET_STATE)dwState)
{
case DhcpSubnetEnabled:
pSubnetParams->m_pSubnetInfo->SubnetState = DhcpSubnetEnabled;
break;
case DhcpSubnetDisabled:
pSubnetParams->m_pSubnetInfo->SubnetState = DhcpSubnetDisabled;
break;
default:
return FALSE;
}
// if the request is for an 'instant apply', do it now
if (pOut != NULL)
{
DWORD errCode;
pSubnetParams->CommitSet(errCode);
// fill back the code returned by the underlying level
if (pOut != NULL)
pOut->SetDWORD(RETURN_CODE_PROPERTY_NAME, errCode);
}
// the API call succeeded
return TRUE;
}
MFN_PROPERTY_ACTION_DEFN(fnSNetGetNumberOfAddressesInUse, pParams, pIn, pOut)
{
BOOL fRefresh;
CDHCP_Subnet_Parameters *pSubnetParams;
LPDHCP_MIB_INFO pMibInfo;
LPSCOPE_MIB_INFO pScopeMibInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pSubnetParams = (CDHCP_Subnet_Parameters *)pParams;
fRefresh = pSubnetParams->m_pMibInfo == NULL;
if (pSubnetParams->GetMibInfo(pMibInfo, pScopeMibInfo, fRefresh) &&
pScopeMibInfo != NULL)
{
pOut->SetDWORD(DHCP_Subnet_Property[IDX_SNET_NbAddrInUse].m_wsPropName, pScopeMibInfo->NumAddressesInuse);
return TRUE;
}
// the API call failed
return FALSE;
}
MFN_PROPERTY_ACTION_DEFN(fnSNetGetNumberOfAddressesFree, pParams, pIn, pOut)
{
BOOL fRefresh;
CDHCP_Subnet_Parameters *pSubnetParams;
LPDHCP_MIB_INFO pMibInfo;
LPSCOPE_MIB_INFO pScopeMibInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pSubnetParams = (CDHCP_Subnet_Parameters *)pParams;
fRefresh = pSubnetParams->m_pMibInfo == NULL;
if (pSubnetParams->GetMibInfo(pMibInfo, pScopeMibInfo, fRefresh) &&
pScopeMibInfo != NULL)
{
pOut->SetDWORD(DHCP_Subnet_Property[IDX_SNET_NbAddrFree].m_wsPropName, pScopeMibInfo->NumAddressesFree);
return TRUE;
}
// the API call failed
return FALSE;
}
MFN_PROPERTY_ACTION_DEFN(fnSNetGetNumberOfPendingOffers, pParams, pIn, pOut)
{
BOOL fRefresh;
CDHCP_Subnet_Parameters *pSubnetParams;
LPDHCP_MIB_INFO pMibInfo;
LPSCOPE_MIB_INFO pScopeMibInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pSubnetParams = (CDHCP_Subnet_Parameters *)pParams;
fRefresh = pSubnetParams->m_pMibInfo == NULL;
if (pSubnetParams->GetMibInfo(pMibInfo, pScopeMibInfo, fRefresh) &&
pScopeMibInfo != NULL)
{
pOut->SetDWORD(DHCP_Subnet_Property[IDX_SNET_NbPendingOffers].m_wsPropName, pScopeMibInfo->NumPendingOffers);
return TRUE;
}
// the API call failed
return FALSE;
}