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

681 lines
21 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_Lease
REVISION:
08/14/98 - created
******************************************************************/
#include <stdafx.h>
#include "LsScal.h" // needed for DHCP_Lease_Property[] (for retrieving the property's name)
#include "LsFn.h" // own header
/*****************************************************************
* The definition of the class CDHCP_Lease_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_Lease_Parameters::DeleteClientInfo(LPCLIENT_INFO& pClientInfo)
{
if (pClientInfo != NULL)
{
if (pClientInfo->ClientName)
DhcpRpcFreeMemory(pClientInfo->ClientName);
if (pClientInfo->ClientComment != NULL)
DhcpRpcFreeMemory(pClientInfo->ClientComment);
if (pClientInfo->ClientHardwareAddress.Data != NULL)
DhcpRpcFreeMemory(pClientInfo->ClientHardwareAddress.Data);
if (pClientInfo->OwnerHost.NetBiosName != NULL)
DhcpRpcFreeMemory(pClientInfo->OwnerHost.NetBiosName);
if (pClientInfo->OwnerHost.HostName != NULL)
DhcpRpcFreeMemory(pClientInfo->OwnerHost.HostName);
DhcpRpcFreeMemory(pClientInfo);
}
}
void CDHCP_Lease_Parameters::DeleteClientInfoArray(LPCLIENT_INFO_ARRAY& pClientInfoArray)
{
if (pClientInfoArray)
{
if (pClientInfoArray->Clients)
{
while(pClientInfoArray->NumElements)
{
DeleteClientInfo(pClientInfoArray->Clients[--(pClientInfoArray->NumElements)]);
}
DhcpRpcFreeMemory(pClientInfoArray->Clients);
}
DhcpRpcFreeMemory(pClientInfoArray);
pClientInfoArray = NULL;
}
}
CDHCP_Lease_Parameters::CDHCP_Lease_Parameters(DHCP_IP_ADDRESS dwSubnetAddress, DHCP_IP_ADDRESS dwClientAddress)
{
m_dwSubnetAddress = dwSubnetAddress;
m_dwClientAddress = dwClientAddress;
m_pClientInfoArray = NULL;
m_pClientInfo = NULL;
m_pClientSetInfo = 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_Lease_Parameters::~CDHCP_Lease_Parameters()
{
DeleteClientInfoArray(m_pClientInfoArray);
DeleteClientInfo(m_pClientSetInfo);
m_pClientInfo = NULL;
}
// DESCRIPTION:
// Fills 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).
BOOL CDHCP_Lease_Parameters::NextSubnetClients(DHCP_RESUME_HANDLE ResumeHandle)
{
DWORD Error;
DWORD ClientsRead = 0;
DWORD ClientsTotal = 0;
// each time the API gets called, the previous
// m_pClientInfoArray is useless and should be freed
DeleteClientInfoArray(m_pClientInfoArray);
m_pClientInfo = NULL;
// calls the API.
#ifdef NT5
Error = DhcpEnumSubnetClientsV5 (
#else if NT4
Error = DhcpEnumSubnetClientsV4 (
#endif
SERVER_IP_ADDRESS,
m_dwSubnetAddress,
&ResumeHandle,
(DWORD)(-1),
&m_pClientInfoArray,
&ClientsRead,
&ClientsTotal);
if (Error == ERROR_SUCCESS)
ResumeHandle = 0;
return (Error == ERROR_SUCCESS || Error == ERROR_MORE_DATA);
}
BOOL CDHCP_Lease_Parameters::GetClientInfoFromCache(LPCLIENT_INFO& pClientInfo)
{
if (m_pClientInfo != NULL &&
m_pClientInfo->ClientIpAddress == m_dwClientAddress)
{
pClientInfo = m_pClientInfo;
return TRUE;
}
if (m_pClientInfoArray != NULL)
{
for (int i=0; i<m_pClientInfoArray->NumElements; i++)
{
// match the internal client id with the info from cache
if (m_pClientInfoArray->Clients[i]->ClientIpAddress == m_dwClientAddress)
{
// client found, return info on client, and TRUE.
pClientInfo = m_pClientInfoArray->Clients[i];
m_pClientInfo = pClientInfo;
return TRUE;
}
}
}
return FALSE;
}
// DESCRIPTION:
// Provides the data structure filled in through the DhcpGetClientInfo 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_Lease_Parameters::GetClientInfo(LPCLIENT_INFO& pClientInfo, BOOL fRefresh)
{
if (m_pClientInfoArray == NULL)
fRefresh = TRUE;
if (!fRefresh &&
GetClientInfoFromCache(pClientInfo))
return TRUE;
DHCP_RESUME_HANDLE ResumeHandle = 0;
DWORD i;
// either the caller wants full refresh, or the client was not found into the cache
// do full refresh.
do
{
if (NextSubnetClients(ResumeHandle) &&
GetClientInfoFromCache(pClientInfo) )
return TRUE;
} while (ResumeHandle != 0);
return FALSE;
}
BOOL CDHCP_Lease_Parameters::CheckExistsSetInfoPtr()
{
if (m_pClientSetInfo != NULL)
return TRUE;
m_pClientSetInfo = (LPCLIENT_INFO)MIDL_user_allocate(sizeof(CLIENT_INFO));
if (m_pClientSetInfo == NULL)
return FALSE;
memset(m_pClientSetInfo, 0, sizeof(CLIENT_INFO));
return TRUE;
}
// DESCRIPTION:
// Sets to the server the information available for the client.
// It assumes the info is already filled in. It only calls DhcpSetClientInfoV4()
// and return TRUE on success and FALSE on failure
BOOL CDHCP_Lease_Parameters::CommitSet(DWORD & errCode)
{
LPCLIENT_INFO pClientInfo;
if (m_pClientSetInfo == NULL ||
!GetClientInfo(pClientInfo, FALSE))
{
errCode = ERROR_FILE_NOT_FOUND;
return FALSE;
}
// copies all the info we have to set onto the cache location for the client
// duplicate the hardware address
dupDhcpBinaryData(m_pClientSetInfo->ClientHardwareAddress, pClientInfo->ClientHardwareAddress);
// copy the name
if (pClientInfo->ClientName)
DhcpRpcFreeMemory(pClientInfo->ClientName);
pClientInfo->ClientName = _wcsdup(m_pClientSetInfo->ClientName);
// copy the comment
if (pClientInfo->ClientComment)
DhcpRpcFreeMemory(pClientInfo->ClientComment);
pClientInfo->ClientComment = _wcsdup(m_pClientSetInfo->ClientComment);
// copy the client type
pClientInfo->bClientType = m_pClientSetInfo->bClientType;
// DHCP_CLIENT_INFO_V5 is only a one field extension of DHCP_CLIENT_INFO_V4
errCode = DhcpSetClientInfoV4(
SERVER_IP_ADDRESS,
(LPDHCP_CLIENT_INFO_V4)pClientInfo);
return errCode == ERROR_SUCCESS;
}
// GET function for the (RO)"Subnet" property
MFN_PROPERTY_ACTION_DEFN(fnLsGetSubnet, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
LPCLIENT_INFO pClientInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
if (pLeaseParams->GetClientInfo(pClientInfo, FALSE) &&
pClientInfo != NULL)
{
WCHAR wsSubnet[16]; // should be enough to hold an IP Addr (xxx.xxx.xxx.xxx\0 = 16)
DWORD dwSubnet;
dwSubnet = pClientInfo->ClientIpAddress & pClientInfo->SubnetMask;
swprintf(wsSubnet, L"%u.%u.%u.%u",(dwSubnet & 0xff000000) >> 24,
(dwSubnet & 0x00ff0000) >> 16,
(dwSubnet & 0x0000ff00) >> 8,
(dwSubnet & 0x000000ff));
pOut->SetCHString(DHCP_Lease_Property[IDX_Ls_Subnet].m_wsPropName, wsSubnet);
return TRUE;
}
// the API call failed
return FALSE;
}
// GET function for the (RO)"Address" property
MFN_PROPERTY_ACTION_DEFN(fnLsGetAddress, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
LPCLIENT_INFO pClientInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
if (pLeaseParams->GetClientInfo(pClientInfo, FALSE) &&
pClientInfo != NULL)
{
WCHAR wsAddress[16]; // should be enough to hold an IP Addr (xxx.xxx.xxx.xxx\0 = 16)
swprintf(wsAddress, L"%u.%u.%u.%u",(pClientInfo->ClientIpAddress & 0xff000000) >> 24,
(pClientInfo->ClientIpAddress & 0x00ff0000) >> 16,
(pClientInfo->ClientIpAddress & 0x0000ff00) >> 8,
(pClientInfo->ClientIpAddress & 0x000000ff));
pOut->SetCHString(DHCP_Lease_Property[IDX_Ls_Address].m_wsPropName, wsAddress);
return TRUE;
}
// the API call failed
return FALSE;
}
// GET function for the (RO) "Mask" property
MFN_PROPERTY_ACTION_DEFN(fnLsGetMask, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
LPCLIENT_INFO pClientInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
if (pLeaseParams->GetClientInfo(pClientInfo, FALSE) &&
pClientInfo != NULL)
{
WCHAR wsMask[16]; // should be enough to hold an IP Addr (xxx.xxx.xxx.xxx\0 = 16)
swprintf(wsMask, L"%u.%u.%u.%u",(pClientInfo->SubnetMask & 0xff000000) >> 24,
(pClientInfo->SubnetMask & 0x00ff0000) >> 16,
(pClientInfo->SubnetMask & 0x0000ff00) >> 8,
(pClientInfo->SubnetMask & 0x000000ff));
pOut->SetCHString(DHCP_Lease_Property[IDX_Ls_SubnetMask].m_wsPropName, wsMask);
return TRUE;
}
// the API call failed
return FALSE;
}
// GET function for the (RW)"UniqueClientIdentifier" property
MFN_PROPERTY_ACTION_DEFN(fnLsGetHdwAddress, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
LPCLIENT_INFO pClientInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
if (pLeaseParams->GetClientInfo(pClientInfo, FALSE) &&
pClientInfo != NULL)
{
/*
// -- uncomment the code below if want to change the format of the hdw address (from array of 6 bytes to string)
// -- in this case, remove the 'return' lines below, and change the definition of the variable
// -- DHCP_Lease::UniqueClientIdentifier to string.
WCHAR wsHdwAddress[32]; // should be enough to hold the hardware address (xxyyzzuuvvww)
for (int i = 0; i < pClientInfo->ClientHardwareAddress.DataLength && i < 16; i++)
{
swprintf(wsHdwAddress + 2*i, L"%02x", pClientInfo->ClientHardwareAddress.Data[i]);
}
pOut->SetCHString(DHCP_Lease_Property[IDX_Ls_UniqueClientIdentifier].m_wsPropName, wsHdwAddress);
return TRUE;
*/
return InstanceSetByteArray(
pOut,
DHCP_Lease_Property[IDX_Ls_UniqueClientIdentifier].m_wsPropName,
pClientInfo->ClientHardwareAddress.Data,
pClientInfo->ClientHardwareAddress.DataLength );
}
// the API call failed
return FALSE;
}
// SET function for the (RW)"UniqueClientIdentifier" property
MFN_PROPERTY_ACTION_DEFN(fnLsSetHdwAddress, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
// only some of the client info can be set (Name, Comment, HdwAddress, Type
// therefore, the client has to be present into the cache. We will alter only (one of) the
// parameters above.
if (pLeaseParams == NULL ||
!pLeaseParams->CheckExistsSetInfoPtr() ||
pIn == NULL ||
!InstanceGetByteArray(
pIn,
DHCP_Lease_Property[IDX_Ls_UniqueClientIdentifier].m_wsPropName,
pLeaseParams->m_pClientSetInfo->ClientHardwareAddress.Data,
pLeaseParams->m_pClientSetInfo->ClientHardwareAddress.DataLength)
)
return FALSE;
// if this is a request for 'instant apply', do it now
if (pOut != NULL)
{
DWORD errCode;
pLeaseParams->CommitSet(errCode);
// fill back the code returned by the underlying level
if (pOut != NULL)
pOut->SetDWORD(RETURN_CODE_PROPERTY_NAME, errCode);
}
// the API call succeded
return TRUE;
}
// GET function for the (RW)"Name" property
MFN_PROPERTY_ACTION_DEFN(fnLsGetName, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
LPCLIENT_INFO pClientInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
if (pLeaseParams->GetClientInfo(pClientInfo, FALSE) &&
pClientInfo != NULL)
{
pOut->SetCHString(DHCP_Lease_Property[IDX_Ls_Name].m_wsPropName,
pClientInfo->ClientName);
return TRUE;
}
// the API call failed
return FALSE;
}
// SET function for the (RW)"Name" property
MFN_PROPERTY_ACTION_DEFN(fnLsSetName, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
CHString wsName;
LPCLIENT_INFO pClientInfo;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
// only some of the client info can be set (Name, Comment, HdwAddress, Type
// therefore, the client has to be present into the cache. We will alter only (one of) the
// parameters above.
if (pLeaseParams == NULL ||
!pLeaseParams->CheckExistsSetInfoPtr() ||
pIn == NULL ||
!pIn->GetCHString(DHCP_Lease_Property[IDX_Ls_Name].m_wsPropName, wsName))
return FALSE;
pClientInfo = pLeaseParams->m_pClientSetInfo;
if (pClientInfo->ClientName != NULL)
DhcpRpcFreeMemory(pClientInfo->ClientName);
// allocate a new buffer able to hold this new name
pClientInfo->ClientName = (WCHAR*)MIDL_user_allocate(sizeof(WCHAR)*wsName.GetLength()+sizeof(WCHAR));
// make sure the allocation succeeded
if (pClientInfo->ClientName == NULL)
return FALSE;
// copy the name to the new buffer
#ifdef _UNICODE
wcscpy(pClientInfo->ClientName, wsName);
#else
swprintf(pClientInfo->ClientName, L"%S", wsName);
#endif
// if this is a request for 'instant apply', do it now
if (pOut != NULL)
{
DWORD errCode;
pLeaseParams->CommitSet(errCode);
// fill back the code returned by the underlying level
if (pOut != NULL)
pOut->SetDWORD(RETURN_CODE_PROPERTY_NAME, errCode);
}
// the API call succeded
return TRUE;
}
// GET function for the (RW)"Comment" property
MFN_PROPERTY_ACTION_DEFN(fnLsGetComment, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
LPCLIENT_INFO pClientInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
if (pLeaseParams->GetClientInfo(pClientInfo, FALSE) &&
pClientInfo != NULL)
{
pOut->SetCHString(DHCP_Lease_Property[IDX_Ls_Comment].m_wsPropName,
pClientInfo->ClientComment);
return TRUE;
}
// the API call failed
return FALSE;
}
// SET function for the (RW)"Comment" property
MFN_PROPERTY_ACTION_DEFN(fnLsSetComment, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
CHString wsComment;
LPCLIENT_INFO pClientInfo;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
// only some of the client info can be set (Name, Comment, HdwAddress, Type
// therefore, the client has to be present into the cache. We will alter only (one of) the
// parameters above.
if (pLeaseParams == NULL ||
!pLeaseParams->CheckExistsSetInfoPtr() ||
pIn == NULL ||
!pIn->GetCHString(DHCP_Lease_Property[IDX_Ls_Comment].m_wsPropName, wsComment))
return FALSE;
pClientInfo = pLeaseParams->m_pClientSetInfo;
if (pClientInfo->ClientComment != NULL)
DhcpRpcFreeMemory(pClientInfo->ClientComment);
// allocate a new buffer able to hold this new name
pClientInfo->ClientComment = (WCHAR*)MIDL_user_allocate(sizeof(WCHAR)*wsComment.GetLength()+sizeof(WCHAR));
// make sure the allocation succeeded
if (pClientInfo->ClientComment == NULL)
return FALSE;
// copy the name to the new buffer
#ifdef _UNICODE
wcscpy(pClientInfo->ClientComment, wsComment);
#else
swprintf(pClientInfo->ClientComment, L"%S", wsComment);
#endif
// if this is a request for 'instant apply', do it now
if (pOut != NULL)
{
DWORD errCode;
pLeaseParams->CommitSet(errCode);
// fill back the code returned by the underlying level
if (pOut != NULL)
pOut->SetDWORD(RETURN_CODE_PROPERTY_NAME, errCode);
}
// the API call succeded
return TRUE;
}
// GET function for the (RO)"LeaseExpiryDate" property
MFN_PROPERTY_ACTION_DEFN(fnLsGetExpiry, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
LPCLIENT_INFO pClientInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
if (pLeaseParams->GetClientInfo(pClientInfo, FALSE) &&
pClientInfo != NULL)
{
SYSTEMTIME sysTime;
wchar_t wchBuffer [32];
// convert the server startup time to a string (UTC) representation.
_tzset () ;
// timezone is offset from UTC in seconds, _daylight is 1 or 0 regarding the DST period
LONG t_Offset = _timezone / 60 - _daylight * 60;
char chOffset = t_Offset < 0 ? '+' : '-';
// take the absolute value from t_Offset
LONG t_absOffset = (1 - ((t_Offset < 0)<<1)) * t_Offset;
FileTimeToSystemTime((FILETIME *)&(pClientInfo->ClientLeaseExpires), &sysTime);
// should ensure we have a valid date format (even if inf.)
if (sysTime.wYear > 9999)
{
sysTime.wYear = 9999;
sysTime.wMonth = 12;
sysTime.wDay = 31;
sysTime.wHour = 23;
sysTime.wMinute = 59;
sysTime.wSecond = 59;
sysTime.wMilliseconds = 0;
}
swprintf (
wchBuffer ,
L"%04ld%02ld%02ld%02ld%02ld%02ld.%06ld%c%03ld" ,
sysTime.wYear,
sysTime.wMonth,
sysTime.wDay,
sysTime.wHour,
sysTime.wMinute,
sysTime.wSecond,
sysTime.wMilliseconds,
chOffset,
t_absOffset
);
// set the value of the property into the (CInstance*)pOut
pOut->SetCHString(DHCP_Lease_Property[IDX_Ls_LeaseExpiryDate].m_wsPropName, wchBuffer);
return TRUE;
}
// the API call failed
return FALSE;
}
// GET function for the (RW)"Type" property
MFN_PROPERTY_ACTION_DEFN(fnLsGetType, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
LPCLIENT_INFO pClientInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
if (pLeaseParams->GetClientInfo(pClientInfo, FALSE) &&
pClientInfo != NULL)
{
pOut->SetByte(DHCP_Lease_Property[IDX_Ls_Type].m_wsPropName,
pClientInfo->bClientType);
return TRUE;
}
// the API call failed
return FALSE;
}
// SET function for the (RW)"Type" property
MFN_PROPERTY_ACTION_DEFN(fnLsSetType, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
BYTE bClientType;
LPCLIENT_INFO pClientInfo;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
// only some of the client info can be set (Name, Comment, HdwAddress, Type
// therefore, the client has to be present into the cache. We will alter only (one of) the
// parameters above.
if (pLeaseParams == NULL ||
!pLeaseParams->CheckExistsSetInfoPtr() ||
pIn == NULL ||
!pIn->GetByte(DHCP_Lease_Property[IDX_Ls_Type].m_wsPropName, bClientType))
return FALSE;
pClientInfo = pLeaseParams->m_pClientSetInfo;
pClientInfo->bClientType = bClientType;
// if this is a request for 'instant apply', do it now
if (pOut != NULL)
{
DWORD errCode;
pLeaseParams->CommitSet(errCode);
// fill back the code returned by the underlying level
if (pOut != NULL)
pOut->SetDWORD(RETURN_CODE_PROPERTY_NAME, errCode);
}
// the API call succeded
return TRUE;
}
#ifdef NT5
// GET function for the (RO)"State" property
MFN_PROPERTY_ACTION_DEFN(fnLsGetState, pParams, pIn, pOut)
{
CDHCP_Lease_Parameters *pLeaseParams;
LPCLIENT_INFO pClientInfo;
if (pParams == NULL || pOut == NULL)
return FALSE;
pLeaseParams = (CDHCP_Lease_Parameters *)pParams;
if (pLeaseParams->GetClientInfo(pClientInfo, FALSE) &&
pClientInfo != NULL)
{
pOut->SetByte(DHCP_Lease_Property[IDX_Ls_State].m_wsPropName,
pClientInfo->AddressState);
return TRUE;
}
// the API call failed
return FALSE;
}
#endif