/****************************************************************** 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 #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; iNumElements; 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 ; }