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