Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1226 lines
30 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corporation, 1991 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. utils.cpp
  7. Utility routines for the DHCP admin snapin
  8. FILE HISTORY:
  9. DavidHov 6/15/93 Created
  10. */
  11. #include "stdafx.h"
  12. //#include "svcguid.h"
  13. #define NUM_OPTION_TYPES 3
  14. #define NUM_OPTION_POSS NUM_OPTION_TYPES * NUM_OPTION_TYPES
  15. int g_OptionPriorityMap[NUM_OPTION_POSS][NUM_OPTION_TYPES] =
  16. {
  17. {ICON_IDX_CLIENT_OPTION_LEAF, ICON_IDX_CLIENT_OPTION_LEAF, 0},
  18. {ICON_IDX_CLIENT_OPTION_LEAF, ICON_IDX_SCOPE_OPTION_LEAF, -1},
  19. {ICON_IDX_CLIENT_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF, -1},
  20. {ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_CLIENT_OPTION_LEAF, 1},
  21. {ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_SCOPE_OPTION_LEAF, 0},
  22. {ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF, -1},
  23. {ICON_IDX_SERVER_OPTION_LEAF, ICON_IDX_CLIENT_OPTION_LEAF, 1},
  24. {ICON_IDX_SERVER_OPTION_LEAF, ICON_IDX_SCOPE_OPTION_LEAF, 1},
  25. {ICON_IDX_SERVER_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF, 0}
  26. };
  27. int
  28. UtilGetOptionPriority(int nOpt1, int nOpt2)
  29. {
  30. int nRet = 0;
  31. for (int i = 0; i < NUM_OPTION_POSS; i++)
  32. {
  33. if ( (nOpt1 == g_OptionPriorityMap[i][0]) &&
  34. (nOpt2 == g_OptionPriorityMap[i][1]) )
  35. {
  36. nRet = g_OptionPriorityMap[i][2];
  37. break;
  38. }
  39. }
  40. return nRet;
  41. }
  42. int ServerBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  43. {
  44. int i;
  45. switch (uMsg)
  46. {
  47. case BFFM_INITIALIZED:
  48. SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
  49. break;
  50. }
  51. return 0;
  52. }
  53. /*---------------------------------------------------------------------------
  54. UtilGetFolderName()
  55. Gets the folder name for backup/restore.
  56. Author: EricDav
  57. ---------------------------------------------------------------------------*/
  58. BOOL
  59. UtilGetFolderName(CString & strInitialPath, CString& strHelpText, CString& strSelectedPath)
  60. {
  61. BOOL fOk = FALSE;
  62. TCHAR szBuffer[MAX_PATH];
  63. TCHAR szExpandedPath[MAX_PATH * 2];
  64. HRESULT hr;
  65. CString strStartingPath = strInitialPath;
  66. if (strStartingPath.IsEmpty())
  67. {
  68. strStartingPath = _T("%SystemDrive%\\");
  69. }
  70. ExpandEnvironmentStrings(strStartingPath, szExpandedPath, sizeof(szExpandedPath) / sizeof(TCHAR));
  71. LPITEMIDLIST pidlPrograms = NULL;
  72. hr = SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlPrograms);
  73. if ( FAILED( hr ) )
  74. {
  75. return fOk;
  76. }
  77. BROWSEINFO browseInfo;
  78. browseInfo.hwndOwner = ::FindMMCMainWindow();
  79. browseInfo.pidlRoot = pidlPrograms;
  80. browseInfo.pszDisplayName = szBuffer;
  81. browseInfo.lpszTitle = strHelpText;
  82. browseInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS ;
  83. browseInfo.lpfn = ServerBrowseCallbackProc;
  84. browseInfo.lParam = (LPARAM) szExpandedPath;
  85. LPITEMIDLIST pidlBrowse = SHBrowseForFolder(&browseInfo);
  86. fOk = SHGetPathFromIDList(pidlBrowse, szBuffer);
  87. CString strPath(szBuffer);
  88. strSelectedPath = strPath;
  89. LPMALLOC pMalloc = NULL;
  90. if (pidlPrograms && SUCCEEDED(SHGetMalloc(&pMalloc)))
  91. {
  92. if (pMalloc)
  93. pMalloc->Free(pidlPrograms);
  94. }
  95. return fOk;
  96. }
  97. /*---------------------------------------------------------------------------
  98. UtilConvertLeaseTime
  99. Converts the lease time from a dword to its day, hour and minute
  100. values
  101. Author: EricDav
  102. ---------------------------------------------------------------------------*/
  103. void
  104. UtilConvertLeaseTime
  105. (
  106. DWORD dwLeaseTime,
  107. int * pnDays,
  108. int * pnHours,
  109. int * pnMinutes
  110. )
  111. {
  112. *pnDays = dwLeaseTime / (60 * 60 * 24);
  113. dwLeaseTime = (dwLeaseTime % (60 * 60 * 24));
  114. *pnHours = dwLeaseTime / (60 * 60);
  115. dwLeaseTime = (dwLeaseTime % (60 * 60));
  116. *pnMinutes = dwLeaseTime / 60;
  117. }
  118. /*---------------------------------------------------------------------------
  119. UtilConvertLeaseTime
  120. Converts the lease time from its day, hour and minute values to
  121. a dword
  122. Author: EricDav
  123. ---------------------------------------------------------------------------*/
  124. DWORD
  125. UtilConvertLeaseTime
  126. (
  127. int nDays,
  128. int nHours,
  129. int nMinutes
  130. )
  131. {
  132. return (DWORD) (nDays * 60 * 60 * 24) +
  133. (nHours * 60 * 60) +
  134. (nMinutes * 60);
  135. }
  136. /*---------------------------------------------------------------------------
  137. UtilCvtStringToIpAddr
  138. Description
  139. Author: EricDav
  140. ---------------------------------------------------------------------------*/
  141. ENUM_HOST_NAME_TYPE
  142. UtilCategorizeName
  143. (
  144. LPCTSTR pszName
  145. )
  146. {
  147. // assume a NetBios name
  148. ENUM_HOST_NAME_TYPE enResult = HNM_TYPE_NB ;
  149. const TCHAR chDash = '-';
  150. const TCHAR chDot = '.' ;
  151. const TCHAR chSlash = '\\' ;
  152. CString strName( pszName ) ;
  153. int cch = strName.GetLength() ;
  154. // Does the name begin with two slashes??
  155. if ( cch > 2
  156. && strName.GetAt(0) == chSlash
  157. && strName.GetAt(1) == chSlash )
  158. {
  159. enResult = HNM_TYPE_NB ;
  160. }
  161. else
  162. {
  163. //
  164. // Scan the name looking for DNS name or IP address
  165. //
  166. int i = 0,
  167. cDots = 0,
  168. cAlpha = 0,
  169. cDash = 0;
  170. TCHAR ch ;
  171. BOOL bOk = TRUE ;
  172. for ( ; i < cch ; i++ )
  173. {
  174. switch ( ch = strName.GetAt( i ) )
  175. {
  176. case chDot:
  177. if ( ++cDots > 3 )
  178. {
  179. // we keep track of the number of dots,
  180. // but we need to be able to handle fully
  181. // qualified domain names (FQDN) so more than
  182. // 3 dots is ok.
  183. //bOk = FALSE ;
  184. }
  185. break;
  186. default:
  187. if ( _istalpha( ch ) )
  188. {
  189. cAlpha++;
  190. }
  191. else if ( ch == chDash )
  192. {
  193. cDash++;
  194. }
  195. else if ( !_istdigit(ch) )
  196. {
  197. bOk = FALSE;
  198. }
  199. break;
  200. }
  201. if ( ! bOk )
  202. {
  203. break ;
  204. }
  205. }
  206. if ( bOk )
  207. {
  208. if ( cAlpha )
  209. {
  210. enResult = HNM_TYPE_DNS ;
  211. }
  212. else if ( cDots == 3 )
  213. {
  214. enResult = HNM_TYPE_IP ;
  215. }
  216. }
  217. }
  218. return enResult ;
  219. }
  220. /*---------------------------------------------------------------------------
  221. UtilCvtStringToIpAddr
  222. Description
  223. Author: EricDav
  224. ---------------------------------------------------------------------------*/
  225. DHCP_IP_ADDRESS
  226. UtilCvtStringToIpAddr
  227. (
  228. const CHAR * pszString
  229. )
  230. {
  231. //
  232. // Convert the string to network byte order, then to host byte order.
  233. //
  234. return (DHCP_IP_ADDRESS) ::ntohl( ::inet_addr( pszString ) ) ;
  235. }
  236. /*---------------------------------------------------------------------------
  237. UtilCvtWstrToIpAddr
  238. Description
  239. Author: EricDav
  240. ---------------------------------------------------------------------------*/
  241. DHCP_IP_ADDRESS
  242. UtilCvtWstrToIpAddr
  243. (
  244. const LPCWSTR pcwString
  245. )
  246. {
  247. CHAR szString [ MAX_PATH ] = {0};
  248. ::WideCharToMultiByte(CP_OEMCP, 0, pcwString, -1, szString, sizeof(szString), NULL, NULL);
  249. //
  250. // Convert the string to network byte order, then to host byte order.
  251. //
  252. return (DHCP_IP_ADDRESS) ::ntohl( ::inet_addr( szString ) );
  253. }
  254. /*---------------------------------------------------------------------------
  255. UtilCvtIpAddrToString
  256. Description
  257. Author: EricDav
  258. ---------------------------------------------------------------------------*/
  259. void
  260. UtilCvtIpAddrToString
  261. (
  262. DHCP_IP_ADDRESS dhipa,
  263. CHAR * pszString,
  264. UINT cBuffSize
  265. )
  266. {
  267. struct in_addr ipaddr ;
  268. //
  269. // Convert the unsigned long to network byte order
  270. //
  271. ipaddr.s_addr = ::htonl( (u_long) dhipa ) ;
  272. //
  273. // Convert the IP address value to a string
  274. //
  275. CHAR * pszAddr = inet_ntoa( ipaddr ) ;
  276. // Copy the string to the caller's buffer.
  277. ASSERT(cBuffSize > ::strlen(pszAddr));
  278. ASSERT(pszString);
  279. if (pszAddr)
  280. {
  281. ::strcpy( pszString, pszAddr ) ;
  282. }
  283. }
  284. /*---------------------------------------------------------------------------
  285. UtilCvtIpAddrToWstr
  286. Description
  287. Author: EricDav
  288. ---------------------------------------------------------------------------*/
  289. BOOL
  290. UtilCvtIpAddrToWstr
  291. (
  292. DHCP_IP_ADDRESS dhipa,
  293. CString * pstrIpAddress
  294. )
  295. {
  296. CHAR szString [ MAX_PATH ] ;
  297. LPCTSTR pbuf;
  298. ::UtilCvtIpAddrToString( dhipa, szString, MAX_PATH );
  299. INT cch = ::strlen( szString ) ;
  300. LPTSTR pBuf = pstrIpAddress->GetBuffer(IP_ADDDRESS_LENGTH_MAX);
  301. ZeroMemory(pBuf, IP_ADDDRESS_LENGTH_MAX);
  302. ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, szString, -1, pBuf, IP_ADDDRESS_LENGTH_MAX);
  303. pstrIpAddress->ReleaseBuffer();
  304. return TRUE;
  305. }
  306. /*---------------------------------------------------------------------------
  307. UtilCvtIpAddrToWstr
  308. Description
  309. Author: EricDav
  310. ---------------------------------------------------------------------------*/
  311. BOOL
  312. UtilCvtIpAddrToWstr
  313. (
  314. DHCP_IP_ADDRESS dhipa,
  315. WCHAR * pwcszString,
  316. INT cBuffCount
  317. )
  318. {
  319. CHAR szString [ MAX_PATH ] ;
  320. if ( cBuffCount > sizeof szString - 1 )
  321. {
  322. cBuffCount = sizeof szString - 1 ;
  323. }
  324. ::UtilCvtIpAddrToString( dhipa, szString, cBuffCount );
  325. #ifdef FE_SB
  326. INT cch;
  327. cch = ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, szString, -1, pwcszString, cBuffCount);
  328. pwcszString[cch] = L'\0';
  329. #else
  330. INT cch = ::strlen( szString ) ;
  331. //::mbstowcs( pwcszString, szString, cch ) ;
  332. ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, szString, cch, pwcszString, cBuffCount);
  333. pwcszString[cch] = 0 ;
  334. #endif
  335. return TRUE ;
  336. }
  337. /*---------------------------------------------------------------------------
  338. UtilDupIpAddrToWstr
  339. Description
  340. Author: EricDav
  341. ---------------------------------------------------------------------------*/
  342. WCHAR *
  343. UtilDupIpAddrToWstr
  344. (
  345. DHCP_IP_ADDRESS dhipa
  346. )
  347. {
  348. WCHAR wcszString [ MAX_PATH ] ;
  349. if ( ! ::UtilCvtIpAddrToWstr( dhipa, wcszString, ( sizeof ( wcszString ) / sizeof( WCHAR ) ) ) )
  350. {
  351. return NULL ;
  352. }
  353. return ::UtilWcstrDup( wcszString ) ;
  354. }
  355. /*---------------------------------------------------------------------------
  356. validateNetbiosName
  357. Simplistic routine to check to see if the given name is viable
  358. as a NetBIOS name.
  359. Author: EricDav
  360. ---------------------------------------------------------------------------*/
  361. static BOOL
  362. validateNetbiosName
  363. (
  364. const CHAR * pchName
  365. )
  366. {
  367. INT nChars = ::strlen( pchName ) ;
  368. if ( nChars > MAX_COMPUTERNAME_LENGTH || nChars == 0 )
  369. {
  370. return FALSE ;
  371. }
  372. for ( ; *pchName ; pchName++ )
  373. {
  374. if ( *pchName == '.' )
  375. {
  376. break ;
  377. }
  378. }
  379. return *pchName == 0 ;
  380. }
  381. /*---------------------------------------------------------------------------
  382. UtilGetHostInfo
  383. Description
  384. Author: EricDav
  385. ---------------------------------------------------------------------------*/
  386. DWORD
  387. UtilGetHostInfo
  388. (
  389. DHCP_IP_ADDRESS dhipa,
  390. DHC_HOST_INFO_STRUCT * pdhsrvi
  391. )
  392. {
  393. ZeroMemory(pdhsrvi, sizeof(DHC_HOST_INFO_STRUCT));
  394. pdhsrvi->_dhipa = dhipa ;
  395. //
  396. // Call the Winsock API to get host name and alias information.
  397. //
  398. u_long ulAddrInNetOrder = ::htonl( (u_long) dhipa ) ;
  399. HOSTENT * pHostInfo = ::gethostbyaddr( (CHAR *) & ulAddrInNetOrder,
  400. sizeof ulAddrInNetOrder,
  401. PF_INET ) ;
  402. if ( pHostInfo == NULL )
  403. {
  404. return ::WSAGetLastError();
  405. }
  406. CHAR * * ppchAlias = pHostInfo->h_aliases ;
  407. //
  408. // Check and copy the host name.
  409. //
  410. if ( sizeof (pdhsrvi->_chNetbiosName) <= ::strlen( pHostInfo->h_name ) )
  411. {
  412. return ERROR_INVALID_NAME ;
  413. }
  414. ZeroMemory(pdhsrvi->_chNetbiosName, sizeof(pdhsrvi->_chNetbiosName));
  415. ::MultiByteToWideChar(CP_ACP,
  416. MB_PRECOMPOSED,
  417. pHostInfo->h_name,
  418. lstrlenA(pHostInfo->h_name),
  419. pdhsrvi->_chNetbiosName,
  420. sizeof(pdhsrvi->_chNetbiosName) / sizeof( pdhsrvi->_chNetbiosName[ 0 ]));
  421. // remove any periods at the end
  422. while (pdhsrvi->_chHostName[lstrlen(pdhsrvi->_chNetbiosName) - 1] == '.')
  423. {
  424. pdhsrvi->_chHostName[lstrlen(pdhsrvi->_chNetbiosName) - 1] = 0;
  425. }
  426. // gethostbyaddr is returning the hostname only in some cases.
  427. // Make another call to get the fqdn
  428. CString strTemp = pdhsrvi->_chNetbiosName;
  429. if (strTemp.Find('.') == -1)
  430. {
  431. // this is not a FQDN
  432. strTemp.Empty();
  433. UtilGetHostAddressFQDN(pdhsrvi->_chNetbiosName, &strTemp, &dhipa);
  434. }
  435. // copy the data into the buffer
  436. strTemp.MakeLower();
  437. memset(pdhsrvi->_chHostName, 0, sizeof(pdhsrvi->_chHostName));
  438. lstrcpy(pdhsrvi->_chHostName, strTemp);
  439. //
  440. // Find the first acceptable NetBIOS name among the aliases;
  441. // i.e., the first name without a period
  442. //
  443. /*
  444. for ( ; *ppchAlias ; ppchAlias++ )
  445. {
  446. if ( validateNetbiosName( *ppchAlias ) )
  447. {
  448. break ;
  449. }
  450. }
  451. //
  452. // Empty the NetBIOS name in case we didn't get one.
  453. //
  454. pdhsrvi->_chNetbiosName[0] = 0 ;
  455. if ( *ppchAlias )
  456. {
  457. //
  458. // We found a usable name; copy it to output structure.
  459. //
  460. ::MultiByteToWideChar(CP_ACP,
  461. MB_PRECOMPOSED,
  462. *ppchAlias,
  463. lstrlenA(*ppchAlias),
  464. pdhsrvi->_chNetbiosName,
  465. sizeof(pdhsrvi->_chNetbiosName));
  466. }
  467. */
  468. return NOERROR ;
  469. }
  470. /*---------------------------------------------------------------------------
  471. addrFromHostent
  472. Description
  473. Author: EricDav
  474. ---------------------------------------------------------------------------*/
  475. static DHCP_IP_ADDRESS
  476. addrFromHostent
  477. (
  478. const HOSTENT * pHostent,
  479. INT index = 0
  480. )
  481. {
  482. return (DHCP_IP_ADDRESS) ::ntohl( *((u_long *) pHostent->h_addr_list[index]) ) ;
  483. }
  484. /*---------------------------------------------------------------------------
  485. UtilGetHostAddress
  486. Description
  487. Author: EricDav
  488. ---------------------------------------------------------------------------*/
  489. HRESULT
  490. UtilGetHostAddressFQDN
  491. (
  492. LPCTSTR pszHostName,
  493. CString * pstrFQDN,
  494. DHCP_IP_ADDRESS * pdhipa
  495. )
  496. {
  497. HRESULT hr = NOERROR;
  498. CHAR szString [ MAX_PATH ] = {0};
  499. ::WideCharToMultiByte(CP_ACP, 0, pszHostName, -1, szString, sizeof(szString), NULL, NULL);
  500. HOSTENT * pHostent = ::gethostbyname( szString ) ;
  501. if ( pHostent )
  502. {
  503. *pdhipa = addrFromHostent( pHostent ) ;
  504. LPTSTR pName = pstrFQDN->GetBuffer(DHCPSNAP_STRING_MAX * sizeof( WCHAR ));
  505. ZeroMemory(pName, DHCPSNAP_STRING_MAX * sizeof( WCHAR ));
  506. ::MultiByteToWideChar(CP_ACP,
  507. MB_PRECOMPOSED,
  508. pHostent->h_name,
  509. strlen(pHostent->h_name),
  510. pName,
  511. DHCPSNAP_STRING_MAX );
  512. pstrFQDN->ReleaseBuffer();
  513. }
  514. else
  515. {
  516. hr = ::WSAGetLastError() ;
  517. }
  518. return hr;
  519. }
  520. /*---------------------------------------------------------------------------
  521. UtilGetHostAddress
  522. Description
  523. Author: EricDav
  524. ---------------------------------------------------------------------------*/
  525. HRESULT
  526. UtilGetHostAddress
  527. (
  528. LPCTSTR pszHostName,
  529. DHCP_IP_ADDRESS * pdhipa
  530. )
  531. {
  532. HRESULT hr = NOERROR;
  533. CHAR szString [ MAX_PATH ] = {0};
  534. ::WideCharToMultiByte(CP_ACP, 0, pszHostName, -1, szString, sizeof(szString), NULL, NULL);
  535. HOSTENT * pHostent = ::gethostbyname( szString ) ;
  536. if ( pHostent )
  537. {
  538. *pdhipa = addrFromHostent( pHostent ) ;
  539. }
  540. else
  541. {
  542. hr = ::WSAGetLastError() ;
  543. }
  544. return hr ;
  545. }
  546. /*---------------------------------------------------------------------------
  547. UtilGetLocalHostAddress
  548. Description
  549. Author: EricDav
  550. ---------------------------------------------------------------------------*/
  551. HRESULT
  552. UtilGetLocalHostAddress
  553. (
  554. DHCP_IP_ADDRESS * pdhipa
  555. )
  556. {
  557. CHAR chHostName [ DHCPSNAP_STRING_MAX ] ;
  558. HRESULT hr = NOERROR;
  559. if ( ::gethostname( chHostName, sizeof chHostName ) == 0 )
  560. {
  561. CString strTemp = chHostName;
  562. hr = ::UtilGetHostAddress( strTemp, pdhipa ) ;
  563. }
  564. else
  565. {
  566. //err = ::WSAGetLastError() ;
  567. hr = E_FAIL;
  568. }
  569. return hr;
  570. }
  571. /*---------------------------------------------------------------------------
  572. UtilGetLocalHostName
  573. Description
  574. Author: EricDav
  575. ---------------------------------------------------------------------------*/
  576. HRESULT
  577. UtilGetLocalHostName
  578. (
  579. CString * pstrName
  580. )
  581. {
  582. CHAR chHostName [ DHCPSNAP_STRING_MAX * 2 ] ;
  583. HRESULT hr = NOERROR;
  584. if ( ::gethostname( chHostName, sizeof (chHostName) ) == 0 )
  585. {
  586. LPTSTR pName = pstrName->GetBuffer(DHCPSNAP_STRING_MAX * sizeof( WCHAR ));
  587. ZeroMemory(pName, DHCPSNAP_STRING_MAX * sizeof( WCHAR ));
  588. ::MultiByteToWideChar(CP_ACP,
  589. MB_PRECOMPOSED,
  590. chHostName,
  591. strlen(chHostName),
  592. pName,
  593. DHCPSNAP_STRING_MAX );
  594. pstrName->ReleaseBuffer();
  595. }
  596. else
  597. {
  598. //err = ::WSAGetLastError() ;
  599. hr = E_FAIL;
  600. }
  601. return hr;
  602. }
  603. /*---------------------------------------------------------------------------
  604. UtilGetNetbiosAddress
  605. Description
  606. Author: EricDav
  607. ---------------------------------------------------------------------------*/
  608. HRESULT
  609. UtilGetNetbiosAddress
  610. (
  611. LPCTSTR pszNetbiosName,
  612. DHCP_IP_ADDRESS * pdhipa
  613. )
  614. {
  615. //
  616. // This code presupposes that the "hosts" file maps NetBIOS names
  617. // and DNS names identically. THIS IS NOT A VALID SUPPOSITION, but is
  618. // expedient for the on-campus work.
  619. //
  620. return UtilGetHostAddress( pszNetbiosName, pdhipa ) ;
  621. }
  622. /*---------------------------------------------------------------------------
  623. UtilWcstrDup
  624. "strdup" a WC string
  625. Author: EricDav
  626. ---------------------------------------------------------------------------*/
  627. WCHAR *
  628. UtilWcstrDup
  629. (
  630. const WCHAR * pwcsz,
  631. INT * pccwLength
  632. )
  633. {
  634. WCHAR szwchEmpty [2] = { 0 } ;
  635. if ( pwcsz == NULL )
  636. {
  637. pwcsz = szwchEmpty ;
  638. }
  639. INT ccw = ::wcslen( pwcsz );
  640. WCHAR * pwcszNew = new WCHAR [ ccw + 1 ] ;
  641. if ( pwcszNew == NULL )
  642. {
  643. return NULL ;
  644. }
  645. ::wcscpy( pwcszNew, pwcsz ) ;
  646. if ( pccwLength )
  647. {
  648. *pccwLength = ccw ;
  649. }
  650. return pwcszNew ;
  651. }
  652. /*---------------------------------------------------------------------------
  653. UtilWcstrDup
  654. Description
  655. Author: EricDav
  656. ---------------------------------------------------------------------------*/
  657. WCHAR *
  658. UtilWcstrDup
  659. (
  660. const CHAR * psz,
  661. INT * pccwLength
  662. )
  663. {
  664. INT ccw = ::strlen( psz ) ;
  665. WCHAR * pwcszNew = new WCHAR [ ccw + 1 ] ;
  666. if ( pwcszNew == NULL )
  667. {
  668. return NULL ;
  669. }
  670. //::mbstowcs( pwcszNew, psz, ccw ) ;
  671. #ifdef FE_SB
  672. ccw = ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, psz, -1, pwcszNew, ccw+1);
  673. if ( pccwLength )
  674. {
  675. *pccwLength = ccw ;
  676. }
  677. pwcszNew[ccw] = L'\0';
  678. #else
  679. ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, psz, ccw, pwcszNew, ccw+1);
  680. if ( pccwLength )
  681. {
  682. *pccwLength = ccw ;
  683. }
  684. pwcszNew[ccw] = 0 ;
  685. #endif
  686. return pwcszNew ;
  687. }
  688. /*---------------------------------------------------------------------------
  689. UtilCstrDup
  690. Description
  691. Author: EricDav
  692. ---------------------------------------------------------------------------*/
  693. CHAR *
  694. UtilCstrDup
  695. (
  696. const WCHAR * pwcsz
  697. )
  698. {
  699. INT ccw = ::wcslen( pwcsz ),
  700. cch = (ccw + 1) * 2 ;
  701. CHAR * psz = new CHAR [ cch ] ;
  702. if ( psz == NULL )
  703. {
  704. return NULL ;
  705. }
  706. //::wcstombs( psz, pwcsz, cch ) ;
  707. ::WideCharToMultiByte( CP_OEMCP, WC_COMPOSITECHECK, pwcsz, -1, psz, cch, NULL, NULL ) ;
  708. return psz ;
  709. }
  710. /*---------------------------------------------------------------------------
  711. UtilCstrDup
  712. Description
  713. Author: EricDav
  714. ---------------------------------------------------------------------------*/
  715. CHAR *
  716. UtilCstrDup
  717. (
  718. const CHAR * psz
  719. )
  720. {
  721. CHAR * pszNew = new CHAR [ ::strlen( psz ) + 1 ] ;
  722. if ( pszNew == NULL )
  723. {
  724. return NULL ;
  725. }
  726. ::strcpy( pszNew, psz ) ;
  727. return pszNew ;
  728. }
  729. /*---------------------------------------------------------------------------
  730. cvtWcStrToStr
  731. Description
  732. Author: EricDav
  733. ---------------------------------------------------------------------------*/
  734. static HRESULT
  735. cvtWcStrToStr
  736. (
  737. char * psz,
  738. size_t cch,
  739. const WCHAR * pwcsz,
  740. size_t cwch
  741. )
  742. {
  743. #ifdef FE_SB
  744. int cchResult = ::WideCharToMultiByte( CP_ACP, 0,
  745. pwcsz, -1,
  746. psz, cch,
  747. NULL, NULL ) ;
  748. #else
  749. int cchResult = ::WideCharToMultiByte( CP_ACP, 0,
  750. pwcsz, cwch,
  751. psz, cwch,
  752. NULL, NULL ) ;
  753. #endif
  754. psz[ cchResult ] = 0 ;
  755. //return cchResult ? 0 : ::GetLastError();
  756. return cchResult ? NOERROR : E_FAIL;
  757. }
  758. wchar_t rgchHex[] = L"00112233445566778899aAbBcCdDeEfF";
  759. /*---------------------------------------------------------------------------
  760. UtilCvtHexString
  761. Convert a string of hex digits to a byte array
  762. Author: EricDav
  763. ---------------------------------------------------------------------------*/
  764. BOOL
  765. UtilCvtHexString
  766. (
  767. LPCTSTR pszNum,
  768. CByteArray & cByte
  769. )
  770. {
  771. int i = 0,
  772. iDig,
  773. iByte,
  774. cDig ;
  775. int iBase = 16 ;
  776. BOOL bByteBoundary ;
  777. //
  778. // Skip leading blanks
  779. //
  780. for ( ; *pszNum == L' ' ; pszNum++ ) ;
  781. //
  782. // Skip a leading zero
  783. //
  784. if ( *pszNum == L'0' )
  785. {
  786. pszNum++ ;
  787. }
  788. //
  789. // Look for hexadecimal marker
  790. //
  791. if ( *pszNum == L'x' || *pszNum == L'X' )
  792. {
  793. pszNum++ ;
  794. }
  795. bByteBoundary = ::wcslen( pszNum ) % 2 ;
  796. for ( iByte = cDig = 0 ; *pszNum ; )
  797. {
  798. wchar_t * pszDig = ::wcschr( rgchHex, *pszNum++ ) ;
  799. if ( pszDig == NULL )
  800. {
  801. break;
  802. // return FALSE;
  803. }
  804. iDig = ((int) (pszDig - rgchHex)) / 2 ;
  805. if ( iDig >= iBase )
  806. {
  807. break ;
  808. // return FALSE;
  809. }
  810. iByte = (iByte * 16) + iDig ;
  811. if ( bByteBoundary )
  812. {
  813. cByte.SetAtGrow( cDig++, (UCHAR) iByte ) ;
  814. iByte = 0 ;
  815. }
  816. bByteBoundary = ! bByteBoundary ;
  817. }
  818. cByte.SetSize( cDig ) ;
  819. //
  820. // Return TRUE if we reached the end of the string.
  821. //
  822. return *pszNum == 0 ;
  823. }
  824. /*---------------------------------------------------------------------------
  825. UtilCvtByteArrayToString
  826. Description
  827. Author: EricDav
  828. ---------------------------------------------------------------------------*/
  829. BOOL
  830. UtilCvtByteArrayToString
  831. (
  832. const CByteArray & abAddr,
  833. CString & str
  834. )
  835. {
  836. int i ;
  837. DWORD err = 0 ;
  838. // TRY
  839. {
  840. str.Empty() ;
  841. //
  842. // The hex conversion string has two characters per nibble,
  843. // to allow for upper case.
  844. //
  845. for ( i = 0 ; i < abAddr.GetSize() ; i++ )
  846. {
  847. int i1 = ((abAddr.GetAt(i) & 0xF0) >> 4) * 2 ,
  848. i2 = (abAddr.GetAt(i) & 0x0F) * 2 ;
  849. str += rgchHex[ i1 ] ;
  850. str += rgchHex[ i2 ] ;
  851. }
  852. }
  853. // CATCH(CMemoryException, pMemException)
  854. // if ( pMemException )
  855. // {
  856. // str.Empty() ;
  857. // err = 1;
  858. // }
  859. return err == 0 ;
  860. }
  861. /*---------------------------------------------------------------------------
  862. PchParseUnicodeString
  863. Parse a unicode string by copying its content
  864. into a CString object.
  865. The parsing ends when the null-terminator ('\0')is
  866. reached or the comma (',') is reached.
  867. Return pointer to the character where parsing
  868. ended('\0') or (',')
  869. Author: EricDav
  870. ---------------------------------------------------------------------------*/
  871. WCHAR *
  872. PchParseUnicodeString
  873. (
  874. CONST WCHAR * szwString, // IN: String to parse
  875. DWORD dwLength,
  876. CString& rString // OUT: Content of the substring
  877. )
  878. {
  879. ASSERT(szwString != NULL);
  880. ASSERT(BOOT_FILE_STRING_DELIMITER_W == L','); // Just in case
  881. WCHAR szwBufferT[1024]; // Temporary buffer
  882. WCHAR * pchwDst = szwBufferT;
  883. while (*szwString != L'\0')
  884. {
  885. if (*szwString == BOOT_FILE_STRING_DELIMITER_W)
  886. break;
  887. *pchwDst++ = *szwString++;
  888. if ((DWORD) (pchwDst - szwBufferT) > dwLength)
  889. {
  890. // we've gone past the end of our buffer!! ouch
  891. Panic0("PchParseUnicodeString: Gone past end of buffer");
  892. break;
  893. }
  894. ASSERT((pchwDst - szwBufferT < sizeof(szwBufferT)) && "Buffer overflow");
  895. } // while
  896. *pchwDst = L'\0';
  897. rString = szwBufferT; // Copy the string into the CString object
  898. return const_cast<WCHAR *>(szwString);
  899. } // PchParseUnicodeString()
  900. /////////////////////////////////////////////////////////////////////////////
  901. // FGetCtrlDWordValue()
  902. //
  903. // Return a 32-bit unsigned integer from an edit control
  904. //
  905. // This function is like GetDlgItemInt() except it accepts hexadecimal values,
  906. // has range checking and/or overflow checking.
  907. // If value is out of range, function will display a friendly message and will
  908. // set the focus to control.
  909. // Range: dwMin to dwMax inclusive
  910. // - If both dwMin and dwMax are zero, no range checking is performed
  911. // - Return TRUE if successful, otherwise FALSE
  912. // - On error, pdwValue remains unchanged.
  913. //
  914. BOOL FGetCtrlDWordValue(HWND hwndEdit, DWORD * pdwValue, DWORD dwMin, DWORD dwMax)
  915. {
  916. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  917. TCHAR szT[256];
  918. DWORD Len, dwResult;
  919. BOOL Success;
  920. ASSERT(IsWindow(hwndEdit));
  921. ASSERT(pdwValue);
  922. ASSERT(dwMin <= dwMax);
  923. ::GetWindowText(hwndEdit, szT, (sizeof(szT)-1)/sizeof(TCHAR));
  924. szT[ 255 ] = _T('\0');
  925. Success = FCvtAsciiToInteger( szT, OUT &dwResult );
  926. *pdwValue = dwResult;
  927. if (( !Success ) || (dwResult < dwMin) || (dwResult > dwMax)) {
  928. CString strBuffer;
  929. strBuffer.LoadString( IDS_ERR_INVALID_INTEGER );
  930. ::wsprintf( szT, strBuffer, dwMin, dwMax, dwMin, dwMax );
  931. ASSERT( wcslen( szT ) < sizeof( szT ));
  932. ::SetFocus( hwndEdit );
  933. ::AfxMessageBox( szT );
  934. ::SetFocus( hwndEdit );
  935. return FALSE;
  936. } // if
  937. return TRUE;
  938. } // FGetCtrlDWordValue
  939. /////////////////////////////////////////////////////////////////////////////
  940. //
  941. // Convert a string to a binary integer
  942. // - String is allowed to be decimal or hexadecimal
  943. // - Minus sign is not allowed
  944. // If successful, set *pdwValue to the integer and return TRUE.
  945. // If not successful (overflow or illegal integer) return FALSE.
  946. //
  947. BOOL
  948. FCvtAsciiToInteger(
  949. IN const TCHAR * pszNum,
  950. OUT DWORD * pdwValue
  951. )
  952. {
  953. DWORD dwResult = 0;
  954. DWORD Res = 0;
  955. BOOL IsHex = FALSE;
  956. LPWSTR Format;
  957. const TCHAR *pBuf;
  958. ASSERT(pszNum != NULL);
  959. ASSERT(pdwValue != NULL);
  960. pBuf = pszNum;
  961. // Skip leading blanks and/or zeroes
  962. while (( *pszNum == _T(' ')) ||
  963. ( *pszNum == _T('\t')) ||
  964. ( *pszNum == _T('0'))) {
  965. pszNum++;
  966. }
  967. // If there is just '0' in the buffer, make sure we don't ignore it
  968. // Check if we are using hexadecimal base
  969. if (( *pszNum == _T('x')) || ( *pszNum == _T('X'))) {
  970. IsHex = TRUE;
  971. pszNum++;
  972. }
  973. else if (( pszNum != pBuf ) &&
  974. ( *(pszNum - 1) == _T('0'))) {
  975. // back track the 0 we skipped
  976. pszNum--;
  977. }
  978. // -ve numbers are not valid
  979. if ( *pszNum == L'-' ) {
  980. *pdwValue = 0;
  981. return FALSE;
  982. }
  983. // if we are the end of the string, then return success
  984. if ( *pszNum == L'\0' ) {
  985. *pdwValue = 0;
  986. return TRUE;
  987. }
  988. Format = ( IsHex ) ? L"%lx" : L"%lu";
  989. Res = swscanf( pszNum, Format, &dwResult );
  990. if ( Res == 0 ) {
  991. *pdwValue = 0;
  992. return FALSE;
  993. }
  994. ASSERT( Res == 1 );
  995. *pdwValue = dwResult;
  996. return TRUE;
  997. } // FCvtAsciiToInteger
  998. void UtilConvertStringToDwordDword(LPCTSTR pszString, DWORD_DWORD * pdwdw)
  999. {
  1000. ULARGE_INTEGER value;
  1001. BOOL hex = FALSE;
  1002. value.QuadPart = 0;
  1003. // skip white spaces
  1004. while (( *pszString == L' ' ) ||
  1005. ( *pszString == L'\t' )) {
  1006. pszString++;
  1007. }
  1008. hex = (( pszString[ 0 ] == L'0' ) &&
  1009. ( pszString[ 1 ] == L'x' ))
  1010. ? TRUE : FALSE;
  1011. if ( hex ) {
  1012. if ( 1 != _stscanf( pszString + 2, _T( "%I64x" ), &value.QuadPart )) {
  1013. value.QuadPart = 0;
  1014. }
  1015. }
  1016. else { // decimal
  1017. if ( 1 != _stscanf( pszString, _T( "%I64u" ), &value.QuadPart )) {
  1018. value.QuadPart = 0;
  1019. }
  1020. }
  1021. // Use 0 for all -ve numbers
  1022. if ( *pszString == L'-' ) {
  1023. value.QuadPart = 0;
  1024. }
  1025. pdwdw->DWord1 = value.HighPart;
  1026. pdwdw->DWord2 = value.LowPart;
  1027. } // UtilConvertStringToDwordDword()
  1028. void UtilConvertDwordDwordToString(DWORD_DWORD * pdwdw, CString * pstrString, BOOL bDecimal)
  1029. {
  1030. TCHAR szNum [ STRING_LENGTH_MAX ] ;
  1031. ULARGE_INTEGER Temp;
  1032. Temp.HighPart = pdwdw->DWord1;
  1033. Temp.LowPart = pdwdw->DWord2;
  1034. if (bDecimal)
  1035. {
  1036. ::wsprintf( szNum, L"%I64u", Temp.QuadPart );
  1037. }
  1038. else
  1039. {
  1040. ::wsprintf( szNum, L"0x%I64x", Temp.QuadPart );
  1041. }
  1042. *pstrString = szNum ;
  1043. }
  1044. // End of DHCPUTIL.CPP