/**********************************************************************/ /** Microsoft Windows NT **/ /** Copyright(c) Microsoft Corporation, 1991 - 1999 **/ /**********************************************************************/ /* utils.cpp Utility routines for the DHCP admin snapin FILE HISTORY: DavidHov 6/15/93 Created */ #include "stdafx.h" //#include "svcguid.h" #define NUM_OPTION_TYPES 3 #define NUM_OPTION_POSS NUM_OPTION_TYPES * NUM_OPTION_TYPES int g_OptionPriorityMap[NUM_OPTION_POSS][NUM_OPTION_TYPES] = { {ICON_IDX_CLIENT_OPTION_LEAF, ICON_IDX_CLIENT_OPTION_LEAF, 0}, {ICON_IDX_CLIENT_OPTION_LEAF, ICON_IDX_SCOPE_OPTION_LEAF, -1}, {ICON_IDX_CLIENT_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF, -1}, {ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_CLIENT_OPTION_LEAF, 1}, {ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_SCOPE_OPTION_LEAF, 0}, {ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF, -1}, {ICON_IDX_SERVER_OPTION_LEAF, ICON_IDX_CLIENT_OPTION_LEAF, 1}, {ICON_IDX_SERVER_OPTION_LEAF, ICON_IDX_SCOPE_OPTION_LEAF, 1}, {ICON_IDX_SERVER_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF, 0} }; int UtilGetOptionPriority(int nOpt1, int nOpt2) { int nRet = 0; for (int i = 0; i < NUM_OPTION_POSS; i++) { if ( (nOpt1 == g_OptionPriorityMap[i][0]) && (nOpt2 == g_OptionPriorityMap[i][1]) ) { nRet = g_OptionPriorityMap[i][2]; break; } } return nRet; } int ServerBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) { int i; switch (uMsg) { case BFFM_INITIALIZED: SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData); break; } return 0; } /*--------------------------------------------------------------------------- UtilGetFolderName() Gets the folder name for backup/restore. Author: EricDav ---------------------------------------------------------------------------*/ BOOL UtilGetFolderName(CString & strInitialPath, CString& strHelpText, CString& strSelectedPath) { BOOL fOk = FALSE; TCHAR szBuffer[MAX_PATH]; TCHAR szExpandedPath[MAX_PATH * 2]; HRESULT hr; CString strStartingPath = strInitialPath; if (strStartingPath.IsEmpty()) { strStartingPath = _T("%SystemDrive%\\"); } ExpandEnvironmentStrings(strStartingPath, szExpandedPath, sizeof(szExpandedPath) / sizeof(TCHAR)); LPITEMIDLIST pidlPrograms = NULL; hr = SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlPrograms); if ( FAILED( hr ) ) { return fOk; } BROWSEINFO browseInfo; browseInfo.hwndOwner = ::FindMMCMainWindow(); browseInfo.pidlRoot = pidlPrograms; browseInfo.pszDisplayName = szBuffer; browseInfo.lpszTitle = strHelpText; browseInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS ; browseInfo.lpfn = ServerBrowseCallbackProc; browseInfo.lParam = (LPARAM) szExpandedPath; LPITEMIDLIST pidlBrowse = SHBrowseForFolder(&browseInfo); fOk = SHGetPathFromIDList(pidlBrowse, szBuffer); CString strPath(szBuffer); strSelectedPath = strPath; LPMALLOC pMalloc = NULL; if (pidlPrograms && SUCCEEDED(SHGetMalloc(&pMalloc))) { if (pMalloc) pMalloc->Free(pidlPrograms); } return fOk; } /*--------------------------------------------------------------------------- UtilConvertLeaseTime Converts the lease time from a dword to its day, hour and minute values Author: EricDav ---------------------------------------------------------------------------*/ void UtilConvertLeaseTime ( DWORD dwLeaseTime, int * pnDays, int * pnHours, int * pnMinutes ) { *pnDays = dwLeaseTime / (60 * 60 * 24); dwLeaseTime = (dwLeaseTime % (60 * 60 * 24)); *pnHours = dwLeaseTime / (60 * 60); dwLeaseTime = (dwLeaseTime % (60 * 60)); *pnMinutes = dwLeaseTime / 60; } /*--------------------------------------------------------------------------- UtilConvertLeaseTime Converts the lease time from its day, hour and minute values to a dword Author: EricDav ---------------------------------------------------------------------------*/ DWORD UtilConvertLeaseTime ( int nDays, int nHours, int nMinutes ) { return (DWORD) (nDays * 60 * 60 * 24) + (nHours * 60 * 60) + (nMinutes * 60); } /*--------------------------------------------------------------------------- UtilCvtStringToIpAddr Description Author: EricDav ---------------------------------------------------------------------------*/ ENUM_HOST_NAME_TYPE UtilCategorizeName ( LPCTSTR pszName ) { // assume a NetBios name ENUM_HOST_NAME_TYPE enResult = HNM_TYPE_NB ; const TCHAR chDash = '-'; const TCHAR chDot = '.' ; const TCHAR chSlash = '\\' ; CString strName( pszName ) ; int cch = strName.GetLength() ; // Does the name begin with two slashes?? if ( cch > 2 && strName.GetAt(0) == chSlash && strName.GetAt(1) == chSlash ) { enResult = HNM_TYPE_NB ; } else { // // Scan the name looking for DNS name or IP address // int i = 0, cDots = 0, cAlpha = 0, cDash = 0; TCHAR ch ; BOOL bOk = TRUE ; for ( ; i < cch ; i++ ) { switch ( ch = strName.GetAt( i ) ) { case chDot: if ( ++cDots > 3 ) { // we keep track of the number of dots, // but we need to be able to handle fully // qualified domain names (FQDN) so more than // 3 dots is ok. //bOk = FALSE ; } break; default: if ( _istalpha( ch ) ) { cAlpha++; } else if ( ch == chDash ) { cDash++; } else if ( !_istdigit(ch) ) { bOk = FALSE; } break; } if ( ! bOk ) { break ; } } if ( bOk ) { if ( cAlpha ) { enResult = HNM_TYPE_DNS ; } else if ( cDots == 3 ) { enResult = HNM_TYPE_IP ; } } } return enResult ; } /*--------------------------------------------------------------------------- UtilCvtStringToIpAddr Description Author: EricDav ---------------------------------------------------------------------------*/ DHCP_IP_ADDRESS UtilCvtStringToIpAddr ( const CHAR * pszString ) { // // Convert the string to network byte order, then to host byte order. // return (DHCP_IP_ADDRESS) ::ntohl( ::inet_addr( pszString ) ) ; } /*--------------------------------------------------------------------------- UtilCvtWstrToIpAddr Description Author: EricDav ---------------------------------------------------------------------------*/ DHCP_IP_ADDRESS UtilCvtWstrToIpAddr ( const LPCWSTR pcwString ) { CHAR szString [ MAX_PATH ] = {0}; ::WideCharToMultiByte(CP_OEMCP, 0, pcwString, -1, szString, sizeof(szString), NULL, NULL); // // Convert the string to network byte order, then to host byte order. // return (DHCP_IP_ADDRESS) ::ntohl( ::inet_addr( szString ) ); } /*--------------------------------------------------------------------------- UtilCvtIpAddrToString Description Author: EricDav ---------------------------------------------------------------------------*/ void UtilCvtIpAddrToString ( DHCP_IP_ADDRESS dhipa, CHAR * pszString, UINT cBuffSize ) { struct in_addr ipaddr ; // // Convert the unsigned long to network byte order // ipaddr.s_addr = ::htonl( (u_long) dhipa ) ; // // Convert the IP address value to a string // CHAR * pszAddr = inet_ntoa( ipaddr ) ; // Copy the string to the caller's buffer. ASSERT(cBuffSize > ::strlen(pszAddr)); ASSERT(pszString); if (pszAddr) { ::strcpy( pszString, pszAddr ) ; } } /*--------------------------------------------------------------------------- UtilCvtIpAddrToWstr Description Author: EricDav ---------------------------------------------------------------------------*/ BOOL UtilCvtIpAddrToWstr ( DHCP_IP_ADDRESS dhipa, CString * pstrIpAddress ) { CHAR szString [ MAX_PATH ] ; LPCTSTR pbuf; ::UtilCvtIpAddrToString( dhipa, szString, MAX_PATH ); INT cch = ::strlen( szString ) ; LPTSTR pBuf = pstrIpAddress->GetBuffer(IP_ADDDRESS_LENGTH_MAX); ZeroMemory(pBuf, IP_ADDDRESS_LENGTH_MAX); ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, szString, -1, pBuf, IP_ADDDRESS_LENGTH_MAX); pstrIpAddress->ReleaseBuffer(); return TRUE; } /*--------------------------------------------------------------------------- UtilCvtIpAddrToWstr Description Author: EricDav ---------------------------------------------------------------------------*/ BOOL UtilCvtIpAddrToWstr ( DHCP_IP_ADDRESS dhipa, WCHAR * pwcszString, INT cBuffCount ) { CHAR szString [ MAX_PATH ] ; if ( cBuffCount > sizeof szString - 1 ) { cBuffCount = sizeof szString - 1 ; } ::UtilCvtIpAddrToString( dhipa, szString, cBuffCount ); #ifdef FE_SB INT cch; cch = ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, szString, -1, pwcszString, cBuffCount); pwcszString[cch] = L'\0'; #else INT cch = ::strlen( szString ) ; //::mbstowcs( pwcszString, szString, cch ) ; ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, szString, cch, pwcszString, cBuffCount); pwcszString[cch] = 0 ; #endif return TRUE ; } /*--------------------------------------------------------------------------- UtilDupIpAddrToWstr Description Author: EricDav ---------------------------------------------------------------------------*/ WCHAR * UtilDupIpAddrToWstr ( DHCP_IP_ADDRESS dhipa ) { WCHAR wcszString [ MAX_PATH ] ; if ( ! ::UtilCvtIpAddrToWstr( dhipa, wcszString, ( sizeof ( wcszString ) / sizeof( WCHAR ) ) ) ) { return NULL ; } return ::UtilWcstrDup( wcszString ) ; } /*--------------------------------------------------------------------------- validateNetbiosName Simplistic routine to check to see if the given name is viable as a NetBIOS name. Author: EricDav ---------------------------------------------------------------------------*/ static BOOL validateNetbiosName ( const CHAR * pchName ) { INT nChars = ::strlen( pchName ) ; if ( nChars > MAX_COMPUTERNAME_LENGTH || nChars == 0 ) { return FALSE ; } for ( ; *pchName ; pchName++ ) { if ( *pchName == '.' ) { break ; } } return *pchName == 0 ; } /*--------------------------------------------------------------------------- UtilGetHostInfo Description Author: EricDav ---------------------------------------------------------------------------*/ DWORD UtilGetHostInfo ( DHCP_IP_ADDRESS dhipa, DHC_HOST_INFO_STRUCT * pdhsrvi ) { ZeroMemory(pdhsrvi, sizeof(DHC_HOST_INFO_STRUCT)); pdhsrvi->_dhipa = dhipa ; // // Call the Winsock API to get host name and alias information. // u_long ulAddrInNetOrder = ::htonl( (u_long) dhipa ) ; HOSTENT * pHostInfo = ::gethostbyaddr( (CHAR *) & ulAddrInNetOrder, sizeof ulAddrInNetOrder, PF_INET ) ; if ( pHostInfo == NULL ) { return ::WSAGetLastError(); } CHAR * * ppchAlias = pHostInfo->h_aliases ; // // Check and copy the host name. // if ( sizeof (pdhsrvi->_chNetbiosName) <= ::strlen( pHostInfo->h_name ) ) { return ERROR_INVALID_NAME ; } ZeroMemory(pdhsrvi->_chNetbiosName, sizeof(pdhsrvi->_chNetbiosName)); ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pHostInfo->h_name, lstrlenA(pHostInfo->h_name), pdhsrvi->_chNetbiosName, sizeof(pdhsrvi->_chNetbiosName) / sizeof( pdhsrvi->_chNetbiosName[ 0 ])); // remove any periods at the end while (pdhsrvi->_chHostName[lstrlen(pdhsrvi->_chNetbiosName) - 1] == '.') { pdhsrvi->_chHostName[lstrlen(pdhsrvi->_chNetbiosName) - 1] = 0; } // gethostbyaddr is returning the hostname only in some cases. // Make another call to get the fqdn CString strTemp = pdhsrvi->_chNetbiosName; if (strTemp.Find('.') == -1) { // this is not a FQDN strTemp.Empty(); UtilGetHostAddressFQDN(pdhsrvi->_chNetbiosName, &strTemp, &dhipa); } // copy the data into the buffer strTemp.MakeLower(); memset(pdhsrvi->_chHostName, 0, sizeof(pdhsrvi->_chHostName)); lstrcpy(pdhsrvi->_chHostName, strTemp); // // Find the first acceptable NetBIOS name among the aliases; // i.e., the first name without a period // /* for ( ; *ppchAlias ; ppchAlias++ ) { if ( validateNetbiosName( *ppchAlias ) ) { break ; } } // // Empty the NetBIOS name in case we didn't get one. // pdhsrvi->_chNetbiosName[0] = 0 ; if ( *ppchAlias ) { // // We found a usable name; copy it to output structure. // ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, *ppchAlias, lstrlenA(*ppchAlias), pdhsrvi->_chNetbiosName, sizeof(pdhsrvi->_chNetbiosName)); } */ return NOERROR ; } /*--------------------------------------------------------------------------- addrFromHostent Description Author: EricDav ---------------------------------------------------------------------------*/ static DHCP_IP_ADDRESS addrFromHostent ( const HOSTENT * pHostent, INT index = 0 ) { return (DHCP_IP_ADDRESS) ::ntohl( *((u_long *) pHostent->h_addr_list[index]) ) ; } /*--------------------------------------------------------------------------- UtilGetHostAddress Description Author: EricDav ---------------------------------------------------------------------------*/ HRESULT UtilGetHostAddressFQDN ( LPCTSTR pszHostName, CString * pstrFQDN, DHCP_IP_ADDRESS * pdhipa ) { HRESULT hr = NOERROR; CHAR szString [ MAX_PATH ] = {0}; ::WideCharToMultiByte(CP_ACP, 0, pszHostName, -1, szString, sizeof(szString), NULL, NULL); HOSTENT * pHostent = ::gethostbyname( szString ) ; if ( pHostent ) { *pdhipa = addrFromHostent( pHostent ) ; LPTSTR pName = pstrFQDN->GetBuffer(DHCPSNAP_STRING_MAX * sizeof( WCHAR )); ZeroMemory(pName, DHCPSNAP_STRING_MAX * sizeof( WCHAR )); ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pHostent->h_name, strlen(pHostent->h_name), pName, DHCPSNAP_STRING_MAX ); pstrFQDN->ReleaseBuffer(); } else { hr = ::WSAGetLastError() ; } return hr; } /*--------------------------------------------------------------------------- UtilGetHostAddress Description Author: EricDav ---------------------------------------------------------------------------*/ HRESULT UtilGetHostAddress ( LPCTSTR pszHostName, DHCP_IP_ADDRESS * pdhipa ) { HRESULT hr = NOERROR; CHAR szString [ MAX_PATH ] = {0}; ::WideCharToMultiByte(CP_ACP, 0, pszHostName, -1, szString, sizeof(szString), NULL, NULL); HOSTENT * pHostent = ::gethostbyname( szString ) ; if ( pHostent ) { *pdhipa = addrFromHostent( pHostent ) ; } else { hr = ::WSAGetLastError() ; } return hr ; } /*--------------------------------------------------------------------------- UtilGetLocalHostAddress Description Author: EricDav ---------------------------------------------------------------------------*/ HRESULT UtilGetLocalHostAddress ( DHCP_IP_ADDRESS * pdhipa ) { CHAR chHostName [ DHCPSNAP_STRING_MAX ] ; HRESULT hr = NOERROR; if ( ::gethostname( chHostName, sizeof chHostName ) == 0 ) { CString strTemp = chHostName; hr = ::UtilGetHostAddress( strTemp, pdhipa ) ; } else { //err = ::WSAGetLastError() ; hr = E_FAIL; } return hr; } /*--------------------------------------------------------------------------- UtilGetLocalHostName Description Author: EricDav ---------------------------------------------------------------------------*/ HRESULT UtilGetLocalHostName ( CString * pstrName ) { CHAR chHostName [ DHCPSNAP_STRING_MAX * 2 ] ; HRESULT hr = NOERROR; if ( ::gethostname( chHostName, sizeof (chHostName) ) == 0 ) { LPTSTR pName = pstrName->GetBuffer(DHCPSNAP_STRING_MAX * sizeof( WCHAR )); ZeroMemory(pName, DHCPSNAP_STRING_MAX * sizeof( WCHAR )); ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, chHostName, strlen(chHostName), pName, DHCPSNAP_STRING_MAX ); pstrName->ReleaseBuffer(); } else { //err = ::WSAGetLastError() ; hr = E_FAIL; } return hr; } /*--------------------------------------------------------------------------- UtilGetNetbiosAddress Description Author: EricDav ---------------------------------------------------------------------------*/ HRESULT UtilGetNetbiosAddress ( LPCTSTR pszNetbiosName, DHCP_IP_ADDRESS * pdhipa ) { // // This code presupposes that the "hosts" file maps NetBIOS names // and DNS names identically. THIS IS NOT A VALID SUPPOSITION, but is // expedient for the on-campus work. // return UtilGetHostAddress( pszNetbiosName, pdhipa ) ; } /*--------------------------------------------------------------------------- UtilWcstrDup "strdup" a WC string Author: EricDav ---------------------------------------------------------------------------*/ WCHAR * UtilWcstrDup ( const WCHAR * pwcsz, INT * pccwLength ) { WCHAR szwchEmpty [2] = { 0 } ; if ( pwcsz == NULL ) { pwcsz = szwchEmpty ; } INT ccw = ::wcslen( pwcsz ); WCHAR * pwcszNew = new WCHAR [ ccw + 1 ] ; if ( pwcszNew == NULL ) { return NULL ; } ::wcscpy( pwcszNew, pwcsz ) ; if ( pccwLength ) { *pccwLength = ccw ; } return pwcszNew ; } /*--------------------------------------------------------------------------- UtilWcstrDup Description Author: EricDav ---------------------------------------------------------------------------*/ WCHAR * UtilWcstrDup ( const CHAR * psz, INT * pccwLength ) { INT ccw = ::strlen( psz ) ; WCHAR * pwcszNew = new WCHAR [ ccw + 1 ] ; if ( pwcszNew == NULL ) { return NULL ; } //::mbstowcs( pwcszNew, psz, ccw ) ; #ifdef FE_SB ccw = ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, psz, -1, pwcszNew, ccw+1); if ( pccwLength ) { *pccwLength = ccw ; } pwcszNew[ccw] = L'\0'; #else ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, psz, ccw, pwcszNew, ccw+1); if ( pccwLength ) { *pccwLength = ccw ; } pwcszNew[ccw] = 0 ; #endif return pwcszNew ; } /*--------------------------------------------------------------------------- UtilCstrDup Description Author: EricDav ---------------------------------------------------------------------------*/ CHAR * UtilCstrDup ( const WCHAR * pwcsz ) { INT ccw = ::wcslen( pwcsz ), cch = (ccw + 1) * 2 ; CHAR * psz = new CHAR [ cch ] ; if ( psz == NULL ) { return NULL ; } //::wcstombs( psz, pwcsz, cch ) ; ::WideCharToMultiByte( CP_OEMCP, WC_COMPOSITECHECK, pwcsz, -1, psz, cch, NULL, NULL ) ; return psz ; } /*--------------------------------------------------------------------------- UtilCstrDup Description Author: EricDav ---------------------------------------------------------------------------*/ CHAR * UtilCstrDup ( const CHAR * psz ) { CHAR * pszNew = new CHAR [ ::strlen( psz ) + 1 ] ; if ( pszNew == NULL ) { return NULL ; } ::strcpy( pszNew, psz ) ; return pszNew ; } /*--------------------------------------------------------------------------- cvtWcStrToStr Description Author: EricDav ---------------------------------------------------------------------------*/ static HRESULT cvtWcStrToStr ( char * psz, size_t cch, const WCHAR * pwcsz, size_t cwch ) { #ifdef FE_SB int cchResult = ::WideCharToMultiByte( CP_ACP, 0, pwcsz, -1, psz, cch, NULL, NULL ) ; #else int cchResult = ::WideCharToMultiByte( CP_ACP, 0, pwcsz, cwch, psz, cwch, NULL, NULL ) ; #endif psz[ cchResult ] = 0 ; //return cchResult ? 0 : ::GetLastError(); return cchResult ? NOERROR : E_FAIL; } wchar_t rgchHex[] = L"00112233445566778899aAbBcCdDeEfF"; /*--------------------------------------------------------------------------- UtilCvtHexString Convert a string of hex digits to a byte array Author: EricDav ---------------------------------------------------------------------------*/ BOOL UtilCvtHexString ( LPCTSTR pszNum, CByteArray & cByte ) { int i = 0, iDig, iByte, cDig ; int iBase = 16 ; BOOL bByteBoundary ; // // Skip leading blanks // for ( ; *pszNum == L' ' ; pszNum++ ) ; // // Skip a leading zero // if ( *pszNum == L'0' ) { pszNum++ ; } // // Look for hexadecimal marker // if ( *pszNum == L'x' || *pszNum == L'X' ) { pszNum++ ; } bByteBoundary = ::wcslen( pszNum ) % 2 ; for ( iByte = cDig = 0 ; *pszNum ; ) { wchar_t * pszDig = ::wcschr( rgchHex, *pszNum++ ) ; if ( pszDig == NULL ) { break; // return FALSE; } iDig = ((int) (pszDig - rgchHex)) / 2 ; if ( iDig >= iBase ) { break ; // return FALSE; } iByte = (iByte * 16) + iDig ; if ( bByteBoundary ) { cByte.SetAtGrow( cDig++, (UCHAR) iByte ) ; iByte = 0 ; } bByteBoundary = ! bByteBoundary ; } cByte.SetSize( cDig ) ; // // Return TRUE if we reached the end of the string. // return *pszNum == 0 ; } /*--------------------------------------------------------------------------- UtilCvtByteArrayToString Description Author: EricDav ---------------------------------------------------------------------------*/ BOOL UtilCvtByteArrayToString ( const CByteArray & abAddr, CString & str ) { int i ; DWORD err = 0 ; // TRY { str.Empty() ; // // The hex conversion string has two characters per nibble, // to allow for upper case. // for ( i = 0 ; i < abAddr.GetSize() ; i++ ) { int i1 = ((abAddr.GetAt(i) & 0xF0) >> 4) * 2 , i2 = (abAddr.GetAt(i) & 0x0F) * 2 ; str += rgchHex[ i1 ] ; str += rgchHex[ i2 ] ; } } // CATCH(CMemoryException, pMemException) // if ( pMemException ) // { // str.Empty() ; // err = 1; // } return err == 0 ; } /*--------------------------------------------------------------------------- PchParseUnicodeString Parse a unicode string by copying its content into a CString object. The parsing ends when the null-terminator ('\0')is reached or the comma (',') is reached. Return pointer to the character where parsing ended('\0') or (',') Author: EricDav ---------------------------------------------------------------------------*/ WCHAR * PchParseUnicodeString ( CONST WCHAR * szwString, // IN: String to parse DWORD dwLength, CString& rString // OUT: Content of the substring ) { ASSERT(szwString != NULL); ASSERT(BOOT_FILE_STRING_DELIMITER_W == L','); // Just in case WCHAR szwBufferT[1024]; // Temporary buffer WCHAR * pchwDst = szwBufferT; while (*szwString != L'\0') { if (*szwString == BOOT_FILE_STRING_DELIMITER_W) break; *pchwDst++ = *szwString++; if ((DWORD) (pchwDst - szwBufferT) > dwLength) { // we've gone past the end of our buffer!! ouch Panic0("PchParseUnicodeString: Gone past end of buffer"); break; } ASSERT((pchwDst - szwBufferT < sizeof(szwBufferT)) && "Buffer overflow"); } // while *pchwDst = L'\0'; rString = szwBufferT; // Copy the string into the CString object return const_cast(szwString); } // PchParseUnicodeString() ///////////////////////////////////////////////////////////////////////////// // FGetCtrlDWordValue() // // Return a 32-bit unsigned integer from an edit control // // This function is like GetDlgItemInt() except it accepts hexadecimal values, // has range checking and/or overflow checking. // If value is out of range, function will display a friendly message and will // set the focus to control. // Range: dwMin to dwMax inclusive // - If both dwMin and dwMax are zero, no range checking is performed // - Return TRUE if successful, otherwise FALSE // - On error, pdwValue remains unchanged. // BOOL FGetCtrlDWordValue(HWND hwndEdit, DWORD * pdwValue, DWORD dwMin, DWORD dwMax) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); TCHAR szT[256]; DWORD Len, dwResult; BOOL Success; ASSERT(IsWindow(hwndEdit)); ASSERT(pdwValue); ASSERT(dwMin <= dwMax); ::GetWindowText(hwndEdit, szT, (sizeof(szT)-1)/sizeof(TCHAR)); szT[ 255 ] = _T('\0'); Success = FCvtAsciiToInteger( szT, OUT &dwResult ); *pdwValue = dwResult; if (( !Success ) || (dwResult < dwMin) || (dwResult > dwMax)) { CString strBuffer; strBuffer.LoadString( IDS_ERR_INVALID_INTEGER ); ::wsprintf( szT, strBuffer, dwMin, dwMax, dwMin, dwMax ); ASSERT( wcslen( szT ) < sizeof( szT )); ::SetFocus( hwndEdit ); ::AfxMessageBox( szT ); ::SetFocus( hwndEdit ); return FALSE; } // if return TRUE; } // FGetCtrlDWordValue ///////////////////////////////////////////////////////////////////////////// // // Convert a string to a binary integer // - String is allowed to be decimal or hexadecimal // - Minus sign is not allowed // If successful, set *pdwValue to the integer and return TRUE. // If not successful (overflow or illegal integer) return FALSE. // BOOL FCvtAsciiToInteger( IN const TCHAR * pszNum, OUT DWORD * pdwValue ) { DWORD dwResult = 0; DWORD Res = 0; BOOL IsHex = FALSE; LPWSTR Format; const TCHAR *pBuf; ASSERT(pszNum != NULL); ASSERT(pdwValue != NULL); pBuf = pszNum; // Skip leading blanks and/or zeroes while (( *pszNum == _T(' ')) || ( *pszNum == _T('\t')) || ( *pszNum == _T('0'))) { pszNum++; } // If there is just '0' in the buffer, make sure we don't ignore it // Check if we are using hexadecimal base if (( *pszNum == _T('x')) || ( *pszNum == _T('X'))) { IsHex = TRUE; pszNum++; } else if (( pszNum != pBuf ) && ( *(pszNum - 1) == _T('0'))) { // back track the 0 we skipped pszNum--; } // -ve numbers are not valid if ( *pszNum == L'-' ) { *pdwValue = 0; return FALSE; } // if we are the end of the string, then return success if ( *pszNum == L'\0' ) { *pdwValue = 0; return TRUE; } Format = ( IsHex ) ? L"%lx" : L"%lu"; Res = swscanf( pszNum, Format, &dwResult ); if ( Res == 0 ) { *pdwValue = 0; return FALSE; } ASSERT( Res == 1 ); *pdwValue = dwResult; return TRUE; } // FCvtAsciiToInteger void UtilConvertStringToDwordDword(LPCTSTR pszString, DWORD_DWORD * pdwdw) { ULARGE_INTEGER value; BOOL hex = FALSE; value.QuadPart = 0; // skip white spaces while (( *pszString == L' ' ) || ( *pszString == L'\t' )) { pszString++; } hex = (( pszString[ 0 ] == L'0' ) && ( pszString[ 1 ] == L'x' )) ? TRUE : FALSE; if ( hex ) { if ( 1 != _stscanf( pszString + 2, _T( "%I64x" ), &value.QuadPart )) { value.QuadPart = 0; } } else { // decimal if ( 1 != _stscanf( pszString, _T( "%I64u" ), &value.QuadPart )) { value.QuadPart = 0; } } // Use 0 for all -ve numbers if ( *pszString == L'-' ) { value.QuadPart = 0; } pdwdw->DWord1 = value.HighPart; pdwdw->DWord2 = value.LowPart; } // UtilConvertStringToDwordDword() void UtilConvertDwordDwordToString(DWORD_DWORD * pdwdw, CString * pstrString, BOOL bDecimal) { TCHAR szNum [ STRING_LENGTH_MAX ] ; ULARGE_INTEGER Temp; Temp.HighPart = pdwdw->DWord1; Temp.LowPart = pdwdw->DWord2; if (bDecimal) { ::wsprintf( szNum, L"%I64u", Temp.QuadPart ); } else { ::wsprintf( szNum, L"0x%I64x", Temp.QuadPart ); } *pstrString = szNum ; } // End of DHCPUTIL.CPP