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

304 lines
11 KiB
C++

/******************************************************************
LsFn.cpp -- Properties action functions (GET)
MODULE:
DhcpProv.dll
DESCRIPTION:
Contains the definition for the action functions associated to
each manageable property from the class CDHCP_Reservation
REVISION:
08/14/98 - created
******************************************************************/
#include <stdafx.h>
#include "ResScal.h" // needed for DHCP_Reservation_Property[] (for retrieving the property's name)
#include "ResFn.h" // own header
#include "LsFn.h" // for GetKeyInfoFromLease
/*****************************************************************
* The definition of the class CDHCP_Reservation_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.
void CDHCP_Reservation_Parameters::DeleteReservationInfo(LPDHCP_IP_RESERVATION_V4& pReservationInfo)
{
if (pReservationInfo != NULL)
{
if (pReservationInfo->ReservedForClient != NULL)
{
if (pReservationInfo->ReservedForClient->Data != NULL)
DhcpRpcFreeMemory(pReservationInfo->ReservedForClient->Data);
DhcpRpcFreeMemory(pReservationInfo->ReservedForClient);
}
DhcpRpcFreeMemory(pReservationInfo);
}
}
void CDHCP_Reservation_Parameters::DeleteReservationInfoArray(LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4& pReservationInfoArray)
{
if (pReservationInfoArray)
{
if (pReservationInfoArray->Elements)
{
while(pReservationInfoArray->NumElements)
{
DeleteReservationInfo(pReservationInfoArray->Elements[--(pReservationInfoArray->NumElements)].Element.ReservedIp);
}
DhcpRpcFreeMemory(pReservationInfoArray->Elements);
}
DhcpRpcFreeMemory(pReservationInfoArray);
pReservationInfoArray = NULL;
}
if ( m_pReservationInfo )
{
if (m_pReservationInfo->Element.ReservedIp)
DeleteReservationInfo(m_pReservationInfo->Element.ReservedIp);
DhcpRpcFreeMemory(m_pReservationInfo);
m_pReservationInfo = NULL ;
}
}
CDHCP_Reservation_Parameters::CDHCP_Reservation_Parameters(DHCP_IP_ADDRESS dwSubnetAddress, DHCP_IP_ADDRESS dwReservationAddress)
{
m_dwSubnetAddress = dwSubnetAddress;
m_dwReservationAddress = dwReservationAddress;
m_pReservationInfoArray = NULL;
m_pReservationInfo = NULL ;
}
// 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_Reservation_Parameters::~CDHCP_Reservation_Parameters()
{
DeleteReservationInfoArray(m_pReservationInfoArray);
}
BOOL CDHCP_Reservation_Parameters::GetKeyInfoFromLease(CDHCP_Lease_Parameters *pLeaseParams)
{
if (pLeaseParams == NULL ||
pLeaseParams->m_pClientSetInfo == NULL)
return FALSE;
if (!CheckExistsInfoPtr())
return FALSE;
m_pReservationInfo->Element.ReservedIp->ReservedIpAddress = pLeaseParams->m_pClientSetInfo->ClientIpAddress;
return dupDhcpBinaryData(
pLeaseParams->m_pClientSetInfo->ClientHardwareAddress,
*(m_pReservationInfo->Element.ReservedIp->ReservedForClient));
}
// DESCRIPTION:
// Fills in the internal cache with the information from the database, starting
// from the given handle. If the end of the database is reached, the handle is
// reset to 0. Returns TRUE on success (regardless there is more data to be read or not).
LONG CDHCP_Reservation_Parameters::NextSubnetReservation(DHCP_RESUME_HANDLE ResumeHandle)
{
DWORD Error;
DWORD ReservationsRead = 0;
DWORD ReservationsTotal = 0;
// each time the API gets called, the previous
// m_pReservationInfoArray is useless and should be freed
DeleteReservationInfoArray(m_pReservationInfoArray);
// calls the API.
Error = DhcpEnumSubnetElementsV4 (
SERVER_IP_ADDRESS,
m_dwSubnetAddress,
DhcpReservedIps,
&ResumeHandle,
(DWORD)(-1),
&m_pReservationInfoArray,
&ReservationsRead,
&ReservationsTotal);
if (Error == ERROR_SUCCESS)
ResumeHandle = 0;
return (Error == ERROR_SUCCESS || Error == ERROR_MORE_DATA);
}
BOOL CDHCP_Reservation_Parameters::GetReservationInfoFromCache(LPDHCP_IP_RESERVATION_V4& pReservationInfo)
{
if (m_pReservationInfoArray != NULL)
{
for (int i=0; i<m_pReservationInfoArray->NumElements; i++)
{
// match the internal reservation id with the info from cache
if (m_pReservationInfoArray->Elements[i].Element.ReservedIp->ReservedIpAddress == m_dwReservationAddress)
{
DHCP_CLIENT_UID *pClientUid;
// reservation found, return info on client, and TRUE.
pReservationInfo = m_pReservationInfoArray->Elements[i].Element.ReservedIp;
pClientUid = pReservationInfo->ReservedForClient;
if (pClientUid->DataLength >= sizeof(DHCP_IP_ADDRESS) &&
memcmp(pClientUid->Data, &m_dwSubnetAddress, sizeof(DHCP_IP_ADDRESS)) == 0)
{
UINT nPrefix = sizeof(DHCP_IP_ADDRESS) + sizeof(BYTE);
pClientUid->DataLength -= nPrefix;
memmove(pClientUid->Data, pClientUid->Data + nPrefix, pClientUid->DataLength);
}
return TRUE;
}
}
}
return FALSE;
}
// DESCRIPTION:
// Provides the data structure filled in through the DhcpGetReservationInfo 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_Reservation_Parameters::GetReservationInfo(LPDHCP_IP_RESERVATION_V4& pReservationInfo, BOOL fRefresh)
{
if (m_pReservationInfoArray == NULL)
fRefresh = TRUE;
if (!fRefresh &&
GetReservationInfoFromCache(pReservationInfo))
return TRUE;
DHCP_RESUME_HANDLE ResumeHandle = 0;
DWORD i;
// either the caller wants full refresh, or the reservation was not found into the cache
// do full refresh.
do
{
if ( ( NextSubnetReservation(ResumeHandle) > 0 ) &&
GetReservationInfoFromCache(pReservationInfo) )
return TRUE;
} while (ResumeHandle != 0);
return FALSE;
}
// DESCRIPTION:
// Checks the m_pConfigInfoV4 pointer to insure it points to a valid buffer.
// It allocates the DHCP_SUBNET_INFO if needed.
BOOL CDHCP_Reservation_Parameters::CheckExistsInfoPtr()
{
if (m_pReservationInfo != NULL)
return TRUE;
m_pReservationInfo = (LPDHCP_SUBNET_ELEMENT_DATA_V4)MIDL_user_allocate(sizeof(DHCP_SUBNET_ELEMENT_DATA_V4));
if (m_pReservationInfo != NULL)
{
m_pReservationInfo->ElementType = DhcpReservedIps ;
m_pReservationInfo->Element.ReservedIp = (LPDHCP_IP_RESERVATION_V4) MIDL_user_allocate(sizeof(DHCP_IP_RESERVATION_V4));
if (m_pReservationInfo->Element.ReservedIp != NULL)
{
m_pReservationInfo->Element.ReservedIp->ReservedForClient = (DHCP_CLIENT_UID*)MIDL_user_allocate(sizeof(DHCP_CLIENT_UID));
return TRUE;
}
}
return FALSE;
}
// 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_Reservation_Parameters::CommitNew(DWORD &returnCode)
{
if (m_pReservationInfo == NULL ||
m_pReservationInfo->Element.ReservedIp == NULL)
return FALSE;
// fill in the reservation address
m_pReservationInfo->Element.ReservedIp->ReservedIpAddress = m_dwReservationAddress;
// we only add here the reservation info. In order to have the reservation active, a lease record has to be created into
// the database as well.
returnCode = DhcpAddSubnetElementV4(
SERVER_IP_ADDRESS,
m_dwSubnetAddress,
m_pReservationInfo);
return returnCode == ERROR_SUCCESS;
}
// DESCRIPTION:
// Assumes the m_dwSubnetAddress,m_dwReservationAddress is initialized, case in
// which it calls the DHCPAPI to delete that reservation from the server.
BOOL CDHCP_Reservation_Parameters::DeleteReservation()
{
LPDHCP_IP_RESERVATION_V4 pReservationInfo;
if (GetReservationInfo(pReservationInfo, FALSE) &&
pReservationInfo != NULL)
{
DHCP_SUBNET_ELEMENT_DATA_V4 subnetElement;
subnetElement.ElementType = DhcpReservedIps;
subnetElement.Element.ReservedIp = pReservationInfo;
// this removes both the reservation registration and the record from the databse
if (DhcpRemoveSubnetElementV4(SERVER_IP_ADDRESS, m_dwSubnetAddress, &subnetElement, DhcpFullForce) == ERROR_SUCCESS)
{
// don't look below :o)
// It's only an exotic way of calling the destructor without destroying the object itself
this->~CDHCP_Reservation_Parameters();
return TRUE;
}
return FALSE;
}
return FALSE ;
}
// GET function for the (RO)"Type" property
MFN_PROPERTY_ACTION_DEFN(fnResGetReservationType, pParams, pIn, pOut)
{
CDHCP_Reservation_Parameters *pReservationParams;
LPDHCP_IP_RESERVATION_V4 pReservationInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pReservationParams = (CDHCP_Reservation_Parameters *)pParams;
if (pReservationParams->GetReservationInfo(pReservationInfo, FALSE) &&
pReservationInfo != NULL)
{
// get the value to set from the pIn parameter
return pOut->SetByte(DHCP_Reservation_Property[IDX_Res_ReservationType].m_wsPropName, pReservationInfo->bAllowedClientTypes) ;
}
// the API call failed
return FALSE;
}
// SET function for the (CREATE)"Type" property
MFN_PROPERTY_ACTION_DEFN(fnResSetReservationType, pParams, pIn, pOut)
{
CDHCP_Reservation_Parameters *pReservationParams;
BYTE dwClientType;
// 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
pReservationParams = (CDHCP_Reservation_Parameters *)pParams;
// make sure there is a buffer for holding all this info.
pReservationParams->CheckExistsInfoPtr();
// get the value to set from the pIn parameter
if (!pIn->GetByte(DHCP_Reservation_Property[IDX_Res_ReservationType].m_wsPropName, dwClientType))
return FALSE;
pReservationParams->m_pReservationInfo->Element.ReservedIp->bAllowedClientTypes = dwClientType ;
return TRUE ;
}