Source code of Windows XP (NT5)
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.

2929 lines
67 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. general.cpp
  7. General classes for the DHCP snapin
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "options.h"
  12. #include "nodes.h"
  13. const TCHAR g_szDefaultHelpTopic[] = _T("\\help\\dhcpconcepts.chm::/sag_dhcptopnode.htm");
  14. /////////////////////////////////////////////////////////////////////
  15. //
  16. // CTimerArray implementation
  17. //
  18. /////////////////////////////////////////////////////////////////////
  19. CTimerMgr::CTimerMgr()
  20. {
  21. }
  22. CTimerMgr::~CTimerMgr()
  23. {
  24. CTimerDesc * pTimerDesc;
  25. for (INT_PTR i = GetUpperBound(); i >= 0; --i)
  26. {
  27. pTimerDesc = GetAt(i);
  28. if (pTimerDesc->uTimer != 0)
  29. FreeTimer(i);
  30. delete pTimerDesc;
  31. }
  32. }
  33. int
  34. CTimerMgr::AllocateTimer
  35. (
  36. ITFSNode * pNode,
  37. CDhcpServer * pServer,
  38. UINT uTimerValue,
  39. TIMERPROC TimerProc
  40. )
  41. {
  42. CSingleLock slTimerMgr(&m_csTimerMgr);
  43. // get a lock on the timer mgr for the scope of this
  44. // function.
  45. slTimerMgr.Lock();
  46. CTimerDesc * pTimerDesc = NULL;
  47. // look for an empty slot
  48. for (INT_PTR i = GetUpperBound(); i >= 0; --i)
  49. {
  50. pTimerDesc = GetAt(i);
  51. if (pTimerDesc->uTimer == 0)
  52. break;
  53. }
  54. // did we find one? if not allocate one
  55. if (i < 0)
  56. {
  57. pTimerDesc = new CTimerDesc;
  58. Add(pTimerDesc);
  59. i = GetUpperBound();
  60. }
  61. //
  62. // fix null pointer dereference
  63. //
  64. if ( pTimerDesc == NULL )
  65. {
  66. return -1;
  67. }
  68. pTimerDesc->uTimer = SetTimer(NULL, (UINT) i, uTimerValue, TimerProc);
  69. if (pTimerDesc->uTimer == 0)
  70. return -1;
  71. pTimerDesc->spNode.Set(pNode);
  72. pTimerDesc->pServer = pServer;
  73. pTimerDesc->timerProc = TimerProc;
  74. return (int)i;
  75. }
  76. void
  77. CTimerMgr::FreeTimer
  78. (
  79. UINT_PTR uEventId
  80. )
  81. {
  82. CSingleLock slTimerMgr(&m_csTimerMgr);
  83. // get a lock on the timer mgr for the scope of this
  84. // function.
  85. slTimerMgr.Lock();
  86. CTimerDesc * pTimerDesc;
  87. Assert(uEventId <= (UINT) GetUpperBound());
  88. if (uEventId > (UINT) GetUpperBound())
  89. return;
  90. pTimerDesc = GetAt((int) uEventId);
  91. ::KillTimer(NULL, pTimerDesc->uTimer);
  92. pTimerDesc->spNode.Release();
  93. pTimerDesc->pServer = NULL;
  94. pTimerDesc->uTimer = 0;
  95. }
  96. CTimerDesc *
  97. CTimerMgr::GetTimerDesc
  98. (
  99. UINT_PTR uEventId
  100. )
  101. {
  102. CSingleLock slTimerMgr(&m_csTimerMgr);
  103. // the caller of this function should lock the timer mgr
  104. // while accessing this pointer
  105. CTimerDesc * pTimerDesc;
  106. for (INT_PTR i = GetUpperBound(); i >= 0; --i)
  107. {
  108. pTimerDesc = GetAt(i);
  109. if (pTimerDesc->uTimer == uEventId)
  110. return pTimerDesc;
  111. }
  112. return NULL;
  113. }
  114. void
  115. CTimerMgr::ChangeInterval
  116. (
  117. UINT_PTR uEventId,
  118. UINT uNewInterval
  119. )
  120. {
  121. CSingleLock slTimerMgr(&m_csTimerMgr);
  122. // get a lock on the timer mgr for the scope of this
  123. // function.
  124. slTimerMgr.Lock();
  125. Assert(uEventId <= (UINT) GetUpperBound());
  126. if (uEventId > (UINT) GetUpperBound())
  127. return;
  128. CTimerDesc tempTimerDesc;
  129. CTimerDesc * pTimerDesc;
  130. pTimerDesc = GetAt((int) uEventId);
  131. // kill the old timer
  132. ::KillTimer(NULL, pTimerDesc->uTimer);
  133. // set a new one with the new interval
  134. pTimerDesc->uTimer = ::SetTimer(NULL, (UINT) uEventId, uNewInterval, pTimerDesc->timerProc);
  135. }
  136. /////////////////////////////////////////////////////////////////////
  137. //
  138. // CDhcpClient implementation
  139. //
  140. /////////////////////////////////////////////////////////////////////
  141. CDhcpClient::CDhcpClient
  142. (
  143. const DHCP_CLIENT_INFO * pdhcClientInfo
  144. )
  145. : m_bReservation( FALSE )
  146. {
  147. Assert(pdhcClientInfo);
  148. InitializeData(pdhcClientInfo);
  149. m_bClientType = CLIENT_TYPE_UNSPECIFIED;
  150. }
  151. CDhcpClient::CDhcpClient
  152. (
  153. const DHCP_CLIENT_INFO_V4 * pdhcClientInfo
  154. )
  155. : m_bReservation( FALSE )
  156. {
  157. Assert(pdhcClientInfo);
  158. InitializeData(reinterpret_cast<const DHCP_CLIENT_INFO *>(pdhcClientInfo));
  159. m_bClientType = pdhcClientInfo->bClientType;
  160. }
  161. void
  162. CDhcpClient::InitializeData
  163. (
  164. const DHCP_CLIENT_INFO * pdhcClientInfo
  165. )
  166. {
  167. DWORD err = 0;
  168. CATCH_MEM_EXCEPTION
  169. {
  170. m_dhcpIpAddress = pdhcClientInfo->ClientIpAddress;
  171. m_dhcpIpMask = pdhcClientInfo->SubnetMask;
  172. m_dtExpires = pdhcClientInfo->ClientLeaseExpires;
  173. if ( pdhcClientInfo->ClientName )
  174. {
  175. m_strName = pdhcClientInfo->ClientName;
  176. }
  177. if ( pdhcClientInfo->ClientComment )
  178. {
  179. m_strComment = pdhcClientInfo->ClientComment;
  180. }
  181. if ( pdhcClientInfo->OwnerHost.HostName )
  182. {
  183. m_strHostName = pdhcClientInfo->OwnerHost.HostName;
  184. }
  185. if ( pdhcClientInfo->OwnerHost.NetBiosName )
  186. {
  187. m_strHostNetbiosName = pdhcClientInfo->OwnerHost.NetBiosName;
  188. }
  189. //
  190. // Convert the hardware addres
  191. //
  192. for ( DWORD i = 0 ; i < pdhcClientInfo->ClientHardwareAddress.DataLength ; i++ )
  193. {
  194. m_baHardwareAddress.SetAtGrow( i, pdhcClientInfo->ClientHardwareAddress.Data[i] ) ;
  195. }
  196. }
  197. END_MEM_EXCEPTION( err ) ;
  198. }
  199. CDhcpClient::~CDhcpClient()
  200. {
  201. }
  202. CDhcpClient::CDhcpClient()
  203. : m_dhcpIpAddress( 0 ),
  204. m_dhcpIpMask( 0 ),
  205. m_dhcpIpHost( 0 ),
  206. m_bReservation( FALSE )
  207. {
  208. m_dtExpires.dwLowDateTime = DHCP_DATE_TIME_ZERO_LOW ;
  209. m_dtExpires.dwHighDateTime = DHCP_DATE_TIME_ZERO_HIGH ;
  210. }
  211. void
  212. CDhcpClient::SetHardwareAddress
  213. (
  214. const CByteArray & caByte
  215. )
  216. {
  217. INT_PTR cMax = caByte.GetSize();
  218. m_baHardwareAddress.SetSize( cMax );
  219. for ( int i = 0 ; i < cMax ; i++ )
  220. {
  221. m_baHardwareAddress.SetAt( i, caByte.GetAt( i ) );
  222. }
  223. }
  224. /////////////////////////////////////////////////////////////////////
  225. //
  226. // CDhcpIpRange implementation
  227. //
  228. /////////////////////////////////////////////////////////////////////
  229. CDhcpIpRange::CDhcpIpRange
  230. (
  231. DHCP_IP_RANGE dhcpIpRange
  232. )
  233. {
  234. *this = dhcpIpRange;
  235. m_RangeType = DhcpIpRanges;
  236. }
  237. CDhcpIpRange::CDhcpIpRange()
  238. {
  239. m_dhcpIpRange.StartAddress = DHCP_IP_ADDRESS_INVALID;
  240. m_dhcpIpRange.EndAddress = DHCP_IP_ADDRESS_INVALID;
  241. m_RangeType = DhcpIpRanges;
  242. }
  243. CDhcpIpRange::~CDhcpIpRange()
  244. {
  245. }
  246. //
  247. // Sort helper function
  248. //
  249. /*int
  250. CDhcpIpRange::OrderByAddress
  251. (
  252. const CObjectPlus * pobIpRange
  253. ) const
  254. {
  255. const CDhcpIpRange * pipr = (CDhcpIpRange *) pobIpRange;
  256. //
  257. // Derive a comparison result for the end address
  258. //
  259. int iEndResult = QueryAddr( FALSE ) < QueryAddr( FALSE )
  260. ? -1
  261. : QueryAddr( FALSE ) != QueryAddr( FALSE );
  262. //
  263. // Use start address as major sort key, end address as minor.
  264. //
  265. return QueryAddr( TRUE ) < pipr->QueryAddr( TRUE )
  266. ? -1
  267. : ( QueryAddr( TRUE ) != pipr->QueryAddr( TRUE )
  268. ? 1
  269. : iEndResult );
  270. }
  271. */
  272. CDhcpIpRange &
  273. CDhcpIpRange::operator =
  274. (
  275. const DHCP_IP_RANGE dhcpIpRange
  276. )
  277. {
  278. m_dhcpIpRange = dhcpIpRange;
  279. return *this;
  280. }
  281. DHCP_IP_ADDRESS
  282. CDhcpIpRange::SetAddr
  283. (
  284. DHCP_IP_ADDRESS dhcpIpAddress,
  285. BOOL bStart
  286. )
  287. {
  288. DHCP_IP_ADDRESS dhcpIpAddressOld;
  289. if ( bStart )
  290. {
  291. dhcpIpAddressOld = m_dhcpIpRange.StartAddress;
  292. m_dhcpIpRange.StartAddress = dhcpIpAddress;
  293. }
  294. else
  295. {
  296. dhcpIpAddressOld = m_dhcpIpRange.EndAddress;
  297. m_dhcpIpRange.EndAddress = dhcpIpAddress;
  298. }
  299. return dhcpIpAddressOld;
  300. }
  301. BOOL
  302. CDhcpIpRange::IsOverlap
  303. (
  304. DHCP_IP_RANGE dhcpIpRange
  305. )
  306. {
  307. BOOL bOverlap = FALSE;
  308. if (m_dhcpIpRange.StartAddress <= dhcpIpRange.StartAddress)
  309. {
  310. if (m_dhcpIpRange.StartAddress == dhcpIpRange.StartAddress)
  311. {
  312. bOverlap = TRUE;
  313. }
  314. else
  315. if (m_dhcpIpRange.EndAddress >= dhcpIpRange.StartAddress)
  316. {
  317. bOverlap = TRUE;
  318. }
  319. }
  320. else
  321. if (m_dhcpIpRange.StartAddress <= dhcpIpRange.EndAddress)
  322. {
  323. bOverlap = TRUE;
  324. }
  325. return bOverlap;
  326. }
  327. //
  328. // Return TRUE if this range is an improper subset of the given range.
  329. //
  330. BOOL
  331. CDhcpIpRange::IsSubset
  332. (
  333. DHCP_IP_RANGE dhcpIpRange
  334. )
  335. {
  336. return (dhcpIpRange.StartAddress <= m_dhcpIpRange.StartAddress) &&
  337. (dhcpIpRange.EndAddress >= m_dhcpIpRange.EndAddress);
  338. }
  339. //
  340. // Return TRUE if this range is an improper superset of the given range.
  341. //
  342. BOOL
  343. CDhcpIpRange::IsSuperset
  344. (
  345. DHCP_IP_RANGE dhcpIpRange
  346. )
  347. {
  348. return (dhcpIpRange.StartAddress >= m_dhcpIpRange.StartAddress) &&
  349. (dhcpIpRange.EndAddress <= m_dhcpIpRange.EndAddress);
  350. }
  351. void
  352. CDhcpIpRange::SetRangeType(UINT uRangeType)
  353. {
  354. m_RangeType = uRangeType;
  355. }
  356. UINT
  357. CDhcpIpRange::GetRangeType()
  358. {
  359. return m_RangeType;
  360. }
  361. /////////////////////////////////////////////////////////////////////
  362. //
  363. // CDhcpOptionValue implementation
  364. //
  365. /////////////////////////////////////////////////////////////////////
  366. CDhcpOptionValue::CDhcpOptionValue
  367. (
  368. DHCP_OPTION_DATA_TYPE dhcpOptionDataType,
  369. INT cUpperBound
  370. )
  371. : m_dhcpOptionDataType( dhcpOptionDataType ),
  372. m_nUpperBound( -1 ),
  373. m_pdhcpOptionDataStruct(NULL)
  374. {
  375. m_dhcpOptionValue.pCObj = NULL;
  376. LONG err = InitValue( dhcpOptionDataType, cUpperBound );
  377. if ( err )
  378. {
  379. ASSERT(FALSE);
  380. //ReportError( err );
  381. }
  382. }
  383. //
  384. // Copy constructor.
  385. //
  386. CDhcpOptionValue::CDhcpOptionValue
  387. (
  388. const CDhcpOptionValue & cOptionValue
  389. )
  390. : m_dhcpOptionDataType( DhcpByteOption ),
  391. m_nUpperBound( -1 ),
  392. m_pdhcpOptionDataStruct(NULL)
  393. {
  394. DWORD err = 0;
  395. m_dhcpOptionValue.pCObj = NULL;
  396. err = SetData(&cOptionValue);
  397. if ( err )
  398. {
  399. ASSERT(FALSE);
  400. //ReportError( err );
  401. }
  402. }
  403. CDhcpOptionValue::CDhcpOptionValue
  404. (
  405. const CDhcpOptionValue * pdhcpValue
  406. )
  407. : m_dhcpOptionDataType( DhcpByteOption ),
  408. m_nUpperBound( -1 ),
  409. m_pdhcpOptionDataStruct(NULL)
  410. {
  411. LONG err = 0;
  412. m_dhcpOptionValue.pCObj = NULL;
  413. ASSERT( pdhcpValue != NULL );
  414. err = SetData(pdhcpValue);
  415. if (err)
  416. {
  417. ASSERT(FALSE);
  418. //ReportError( err );
  419. }
  420. }
  421. CDhcpOptionValue::CDhcpOptionValue
  422. (
  423. const DHCP_OPTION & dhpType
  424. )
  425. : m_dhcpOptionDataType( DhcpByteOption ),
  426. m_nUpperBound( -1 ),
  427. m_pdhcpOptionDataStruct(NULL)
  428. {
  429. LONG err = 0;
  430. m_dhcpOptionValue.pCObj = NULL;
  431. err = SetData((const LPDHCP_OPTION_DATA) &dhpType.DefaultValue);
  432. if ( err )
  433. {
  434. ASSERT(FALSE);
  435. //ReportError( err );
  436. }
  437. }
  438. CDhcpOptionValue::CDhcpOptionValue
  439. (
  440. const DHCP_OPTION_VALUE & dhpOptionValue
  441. )
  442. : m_dhcpOptionDataType( DhcpByteOption ),
  443. m_nUpperBound( -1 ),
  444. m_pdhcpOptionDataStruct(NULL)
  445. {
  446. LONG err = 0;
  447. m_dhcpOptionValue.pCObj = NULL;
  448. err = SetData((const LPDHCP_OPTION_DATA) &dhpOptionValue.Value);
  449. if ( err )
  450. {
  451. ASSERT(FALSE);
  452. //ReportError( err );
  453. }
  454. }
  455. CDhcpOptionValue::~ CDhcpOptionValue ()
  456. {
  457. FreeValue();
  458. if (m_pdhcpOptionDataStruct)
  459. FreeOptionDataStruct();
  460. }
  461. CDhcpOptionValue & CDhcpOptionValue::operator =
  462. (
  463. const CDhcpOptionValue & dhpValue
  464. )
  465. {
  466. SetData(&dhpValue);
  467. return *this;
  468. }
  469. BOOL
  470. CDhcpOptionValue::SetDataType
  471. (
  472. DHCP_OPTION_DATA_TYPE dhcType,
  473. INT cUpperBound
  474. )
  475. {
  476. if ( dhcType > DhcpEncapsulatedDataOption )
  477. {
  478. return FALSE;
  479. }
  480. InitValue( dhcType, cUpperBound );
  481. return TRUE;
  482. }
  483. void
  484. CDhcpOptionValue::SetUpperBound
  485. (
  486. INT cNewBound
  487. )
  488. {
  489. if (cNewBound <= 0)
  490. cNewBound = 1;
  491. if (m_dhcpOptionDataType != DhcpBinaryDataOption &&
  492. m_dhcpOptionDataType != DhcpEncapsulatedDataOption)
  493. {
  494. m_nUpperBound = cNewBound;
  495. }
  496. switch ( m_dhcpOptionDataType )
  497. {
  498. case DhcpByteOption:
  499. case DhcpWordOption:
  500. case DhcpDWordOption:
  501. case DhcpIpAddressOption:
  502. m_dhcpOptionValue.paDword->SetSize( cNewBound );
  503. break;
  504. case DhcpStringDataOption:
  505. m_dhcpOptionValue.paString->SetSize( cNewBound );
  506. break;
  507. case DhcpDWordDWordOption:
  508. m_dhcpOptionValue.paDwordDword->SetSize( cNewBound );
  509. break;
  510. case DhcpBinaryDataOption:
  511. case DhcpEncapsulatedDataOption:
  512. m_dhcpOptionValue.paBinary->SetSize( cNewBound );
  513. break;
  514. default:
  515. Trace0("CDhcpOptionValue: attempt to set upper bound on invalid value type");
  516. ASSERT( FALSE );
  517. break;
  518. }
  519. }
  520. BOOL
  521. CDhcpOptionValue::IsValid () const
  522. {
  523. return m_nUpperBound > 0;
  524. }
  525. void
  526. CDhcpOptionValue::FreeValue ()
  527. {
  528. //
  529. // If there's not a value, return now.
  530. //
  531. if ( m_dhcpOptionValue.pCObj == NULL || m_nUpperBound < 0 )
  532. {
  533. m_dhcpOptionValue.pCObj = NULL;
  534. return;
  535. }
  536. switch ( m_dhcpOptionDataType )
  537. {
  538. case DhcpByteOption:
  539. case DhcpWordOption:
  540. case DhcpDWordOption:
  541. case DhcpIpAddressOption:
  542. delete m_dhcpOptionValue.paDword;
  543. break;
  544. case DhcpStringDataOption:
  545. delete m_dhcpOptionValue.paString;
  546. break;
  547. case DhcpDWordDWordOption:
  548. delete m_dhcpOptionValue.paDwordDword;
  549. break;
  550. case DhcpBinaryDataOption:
  551. case DhcpEncapsulatedDataOption:
  552. delete m_dhcpOptionValue.paBinary;
  553. break;
  554. default:
  555. ASSERT( FALSE );
  556. delete m_dhcpOptionValue.pCObj;
  557. break;
  558. }
  559. m_nUpperBound = -1;
  560. m_dhcpOptionDataType = DhcpByteOption;
  561. m_dhcpOptionValue.pCObj = NULL;
  562. }
  563. //
  564. // Initialize the data value properly
  565. //
  566. LONG
  567. CDhcpOptionValue::InitValue
  568. (
  569. DHCP_OPTION_DATA_TYPE dhcDataType, // The type of value
  570. INT cUpperBound, // Maximum upper bound
  571. BOOL bProvideDefaultValue // Should an empty default value be provided?
  572. )
  573. {
  574. LONG err = 0;
  575. //
  576. // Release any older value.
  577. //
  578. FreeValue();
  579. //
  580. // Initialize the new value
  581. //
  582. m_dhcpOptionDataType = dhcDataType;
  583. m_nUpperBound = cUpperBound <= 0 ? 1 : cUpperBound;
  584. CATCH_MEM_EXCEPTION
  585. {
  586. switch ( m_dhcpOptionDataType )
  587. {
  588. case DhcpByteOption:
  589. case DhcpWordOption:
  590. case DhcpDWordOption:
  591. case DhcpIpAddressOption:
  592. m_dhcpOptionValue.paDword = new CDWordArray;
  593. if ( bProvideDefaultValue)
  594. {
  595. m_dhcpOptionValue.paDword->SetAtGrow( 0, 0 );
  596. }
  597. break;
  598. case DhcpStringDataOption:
  599. m_dhcpOptionValue.paString = new CStringArray;
  600. if ( bProvideDefaultValue )
  601. {
  602. m_dhcpOptionValue.paString->SetAtGrow( 0, _T("") );
  603. }
  604. break;
  605. case DhcpDWordDWordOption:
  606. m_dhcpOptionValue.paDwordDword = new CDWordDWordArray;
  607. if ( bProvideDefaultValue )
  608. {
  609. m_dhcpOptionValue.paBinary->SetAtGrow( 0, 0 );
  610. }
  611. break;
  612. case DhcpBinaryDataOption:
  613. case DhcpEncapsulatedDataOption:
  614. m_dhcpOptionValue.paBinary = new CByteArray;
  615. if ( bProvideDefaultValue )
  616. {
  617. m_dhcpOptionValue.paBinary->SetAtGrow( 0, 0 );
  618. }
  619. break;
  620. default:
  621. err = IDS_INVALID_OPTION_DATA;
  622. break;
  623. }
  624. }
  625. END_MEM_EXCEPTION(err)
  626. return err;
  627. }
  628. LONG
  629. CDhcpOptionValue::SetData
  630. (
  631. const DHCP_OPTION_DATA * podData
  632. )
  633. {
  634. LONG err = 0;
  635. if ( err = InitValue( podData->Elements[0].OptionType,
  636. podData->NumElements,
  637. FALSE ) )
  638. {
  639. return err;
  640. }
  641. CATCH_MEM_EXCEPTION
  642. {
  643. for ( INT i = 0; i < m_nUpperBound; i++ )
  644. {
  645. const DHCP_OPTION_DATA_ELEMENT * pElem = &podData->Elements[i];
  646. switch ( m_dhcpOptionDataType )
  647. {
  648. case DhcpByteOption:
  649. m_dhcpOptionValue.paDword->SetAtGrow(i, pElem->Element.ByteOption );
  650. break;
  651. case DhcpWordOption:
  652. m_dhcpOptionValue.paDword->SetAtGrow(i, pElem->Element.WordOption );
  653. break;
  654. case DhcpDWordOption:
  655. m_dhcpOptionValue.paDword->SetAtGrow(i, pElem->Element.DWordOption );
  656. break;
  657. case DhcpIpAddressOption:
  658. m_dhcpOptionValue.paDword->Add(pElem->Element.IpAddressOption );
  659. break;
  660. case DhcpDWordDWordOption:
  661. {
  662. /*
  663. CByteArray * paByte = m_dhcpOptionValue.paBinary;
  664. paByte->SetSize( (sizeof (DWORD) / sizeof (BYTE)) * 2 );
  665. DWORD dw = pElem->Element.DWordDWordOption.DWord1;
  666. for ( INT j = 0; j < 4; j++ )
  667. {
  668. paByte->SetAtGrow(j, (UCHAR)(dw & 0xff) );
  669. dw >>= 8;
  670. }
  671. dw = pElem->Element.DWordDWordOption.DWord2;
  672. for ( ; j < 8; j++ )
  673. {
  674. paByte->SetAtGrow(j, (UCHAR)(dw & 0xff) );
  675. dw >>= 8;
  676. }
  677. */
  678. m_dhcpOptionValue.paDwordDword->SetAtGrow(i, pElem->Element.DWordDWordOption);
  679. }
  680. break;
  681. case DhcpStringDataOption:
  682. {
  683. CString strTemp;
  684. if ( pElem->Element.StringDataOption == NULL )
  685. {
  686. strTemp = _T("");
  687. }
  688. else
  689. {
  690. strTemp = pElem->Element.StringDataOption;
  691. }
  692. m_dhcpOptionValue.paString->SetAtGrow(i, strTemp);
  693. }
  694. break;
  695. case DhcpBinaryDataOption:
  696. case DhcpEncapsulatedDataOption:
  697. {
  698. CByteArray * paByte = m_dhcpOptionValue.paBinary;
  699. INT c = pElem->Element.BinaryDataOption.DataLength;
  700. paByte->SetSize( c );
  701. for ( INT j = 0; j < c; j++ )
  702. {
  703. paByte->SetAtGrow(j, pElem->Element.BinaryDataOption.Data[j] );
  704. }
  705. }
  706. break;
  707. default:
  708. err = IDS_INVALID_OPTION_DATA;
  709. } // End switch
  710. if ( err )
  711. {
  712. break;
  713. }
  714. } // End for
  715. }
  716. END_MEM_EXCEPTION(err)
  717. return err;
  718. }
  719. LONG
  720. CDhcpOptionValue::SetData
  721. (
  722. const CDhcpOptionValue * pOptionValue
  723. )
  724. {
  725. LONG err = 0;
  726. if ( err = InitValue( pOptionValue->QueryDataType(),
  727. pOptionValue->QueryUpperBound(),
  728. FALSE ) )
  729. {
  730. return err;
  731. }
  732. CATCH_MEM_EXCEPTION
  733. {
  734. for ( INT i = 0; i < m_nUpperBound; i++ )
  735. {
  736. switch ( m_dhcpOptionDataType )
  737. {
  738. case DhcpByteOption:
  739. m_dhcpOptionValue.paDword->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paDword->GetAt(i));
  740. break;
  741. case DhcpWordOption:
  742. m_dhcpOptionValue.paDword->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paDword->GetAt(i));
  743. break;
  744. case DhcpDWordOption:
  745. m_dhcpOptionValue.paDword->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paDword->GetAt(i));
  746. break;
  747. case DhcpIpAddressOption:
  748. m_dhcpOptionValue.paDword->Add(pOptionValue->m_dhcpOptionValue.paDword->GetAt(i));
  749. break;
  750. case DhcpDWordDWordOption:
  751. {
  752. /*
  753. CByteArray * paByte = m_dhcpOptionValue.paBinary;
  754. paByte->SetSize( (sizeof (DWORD) / sizeof (BYTE)) * 2 );
  755. for ( INT j = 0; j < 8; j++ )
  756. {
  757. paByte->SetAtGrow(j, pOptionValue->m_dhcpOptionValue.paBinary->GetAt(j));
  758. }
  759. */
  760. m_dhcpOptionValue.paDwordDword->Add(pOptionValue->m_dhcpOptionValue.paDwordDword->GetAt(i));
  761. }
  762. break;
  763. case DhcpStringDataOption:
  764. {
  765. m_dhcpOptionValue.paString->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paString->GetAt(i));
  766. }
  767. break;
  768. case DhcpBinaryDataOption:
  769. case DhcpEncapsulatedDataOption:
  770. {
  771. CByteArray * paByte = m_dhcpOptionValue.paBinary;
  772. INT_PTR c = pOptionValue->m_dhcpOptionValue.paBinary->GetSize();
  773. paByte->SetSize( c );
  774. for ( INT_PTR j = 0; j < c; j++ )
  775. {
  776. paByte->SetAtGrow(j, pOptionValue->m_dhcpOptionValue.paBinary->GetAt(j));
  777. }
  778. }
  779. break;
  780. default:
  781. err = IDS_INVALID_OPTION_DATA;
  782. } // End switch
  783. if ( err )
  784. {
  785. break;
  786. }
  787. } // End for
  788. }
  789. END_MEM_EXCEPTION(err)
  790. return err;
  791. }
  792. INT
  793. CDhcpOptionValue::QueryBinary
  794. (
  795. INT index
  796. ) const
  797. {
  798. if ( m_dhcpOptionValue.paBinary->GetUpperBound() < index )
  799. {
  800. return -1;
  801. }
  802. return m_dhcpOptionValue.paBinary->GetAt( index );
  803. }
  804. const CByteArray *
  805. CDhcpOptionValue::QueryBinaryArray () const
  806. {
  807. return m_dhcpOptionValue.paBinary;
  808. }
  809. //
  810. // Return a string representation of the current value.
  811. //
  812. // If fLineFeed is true, seperate each individual value
  813. // by a linefeed. Otherwise, by a comma.
  814. //
  815. LONG
  816. CDhcpOptionValue::QueryDisplayString
  817. (
  818. CString & strResult,
  819. BOOL fLineFeed
  820. ) const
  821. {
  822. CString strBuf;
  823. INT i, c;
  824. LONG err = 0;
  825. LPCTSTR pszDwordDwordMask = _T("0x%08lX%08lX");
  826. LPCTSTR pszMaskDec = _T("%ld");
  827. LPCTSTR pszMaskHex = _T("0x%x");
  828. LPCTSTR pszMaskStr1 = _T("%s");
  829. LPCTSTR pszMaskStr2 = _T("\"%s\"");
  830. LPCTSTR pszMaskBin = _T("%2.2x");
  831. LPCTSTR pszMask;
  832. LPCTSTR pszMaskEllipsis = _T("...");
  833. LPCTSTR pszSepComma = _T(", ");
  834. LPCTSTR pszSepLF = _T("\r\n");
  835. CATCH_MEM_EXCEPTION
  836. {
  837. strResult.Empty();
  838. for ( i = 0; i < m_nUpperBound; i++ )
  839. {
  840. strBuf.Empty();
  841. if ( i )
  842. {
  843. strResult += fLineFeed ? pszSepLF : pszSepComma;
  844. }
  845. switch ( QueryDataType() )
  846. {
  847. case DhcpByteOption:
  848. case DhcpWordOption:
  849. case DhcpDWordOption:
  850. pszMask = pszMaskHex;
  851. strBuf.Format(pszMask, QueryNumber(i));
  852. break;
  853. case DhcpStringDataOption:
  854. pszMask = m_nUpperBound > 1
  855. ? pszMaskStr2
  856. : pszMaskStr1;
  857. strBuf.Format(pszMask, m_dhcpOptionValue.paString->ElementAt(0));
  858. break;
  859. case DhcpIpAddressOption:
  860. if (!QueryIpAddr(i))
  861. {
  862. // Set the string to "<None>" iff the list is empty
  863. if (!i)
  864. strResult.LoadString (IDS_INFO_FORMAT_IP_NONE);
  865. break;
  866. }
  867. ::UtilCvtIpAddrToWstr(QueryIpAddr(i), &strBuf);
  868. break;
  869. case DhcpDWordDWordOption:
  870. {
  871. DWORD_DWORD dwdwValue = QueryDwordDword(i);
  872. pszMask = pszDwordDwordMask;
  873. strBuf.Format(pszMask, dwdwValue.DWord1, dwdwValue.DWord2);
  874. }
  875. break;
  876. case DhcpBinaryDataOption:
  877. case DhcpEncapsulatedDataOption:
  878. for ( c = 0; c < m_dhcpOptionValue.paBinary->GetSize(); c++ )
  879. {
  880. if (c)
  881. strBuf += _T(" ");
  882. DWORD dwValue = (BYTE) m_dhcpOptionValue.paBinary->GetAt( c );
  883. CString strTemp;
  884. strTemp.Format(pszMaskBin, dwValue);
  885. strBuf += strTemp;
  886. }
  887. //pszMask = pszMaskHex;
  888. //strBuf.Format(pszMask, QueryNumber(i));
  889. break;
  890. default:
  891. strResult.LoadString(IDS_INFO_TYPNAM_INVALID);
  892. break;
  893. }
  894. strResult += strBuf;
  895. }
  896. }
  897. END_MEM_EXCEPTION(err)
  898. return err;
  899. }
  900. //
  901. // Return a string representation of the current value.
  902. //
  903. //
  904. LONG
  905. CDhcpOptionValue::QueryRouteArrayDisplayString
  906. (
  907. CString & strResult
  908. ) const
  909. {
  910. BOOL fLineFeed = FALSE;
  911. CString strBuf;
  912. INT i, c;
  913. LONG err = 0;
  914. LPCTSTR pszDwordDwordMask = _T("0x%08lX%08lX");
  915. LPCTSTR pszMaskDec = _T("%ld");
  916. LPCTSTR pszMaskHex = _T("0x%x");
  917. LPCTSTR pszMaskStr1 = _T("%s");
  918. LPCTSTR pszMaskStr2 = _T("\"%s\"");
  919. LPCTSTR pszMaskBin = _T("%2.2x");
  920. LPCTSTR pszMask;
  921. LPCTSTR pszMaskEllipsis = _T("...");
  922. LPCTSTR pszSepComma = _T(", ");
  923. LPCTSTR pszSepLF = _T("\r\n");
  924. CATCH_MEM_EXCEPTION
  925. {
  926. strResult.Empty();
  927. int bEmpty = TRUE;
  928. for ( i = 0; i < m_nUpperBound; i++ )
  929. {
  930. if ( i )
  931. {
  932. strResult += fLineFeed ? pszSepLF : pszSepComma;
  933. }
  934. int nDataSize = (int)m_dhcpOptionValue.paBinary->GetSize();
  935. LPBYTE pData = (LPBYTE) m_dhcpOptionValue.paBinary->GetData();
  936. // convert pData to list of ip addresses as per RFC
  937. while( nDataSize > sizeof(DWORD) )
  938. {
  939. // first 1 byte contains the # of bits in subnetmask
  940. nDataSize --;
  941. BYTE nBitsMask = *pData ++;
  942. DWORD Mask = (~0);
  943. if( nBitsMask < 32 ) Mask <<= (32-nBitsMask);
  944. // based on the # of bits, the next few bytes contain
  945. // the subnet address for the 1-bits of subnet mask
  946. int nBytesDest = (nBitsMask+7)/8;
  947. if( nBytesDest > 4 ) nBytesDest = 4;
  948. DWORD Dest = 0;
  949. memcpy( &Dest, pData, nBytesDest );
  950. pData += nBytesDest;
  951. nDataSize -= nBytesDest;
  952. // subnet address is obviously in network order.
  953. Dest = ntohl(Dest);
  954. // now the four bytes would be the router address
  955. DWORD Router = 0;
  956. if( nDataSize < sizeof(DWORD) )
  957. {
  958. Assert( FALSE ); break;
  959. }
  960. memcpy(&Router, pData, sizeof(DWORD));
  961. Router = ntohl( Router );
  962. pData += sizeof(DWORD);
  963. nDataSize -= sizeof(DWORD);
  964. // now fill the list box..
  965. CString strDest, strMask, strRouter;
  966. ::UtilCvtIpAddrToWstr(Dest, &strDest);
  967. ::UtilCvtIpAddrToWstr(Mask, &strMask);
  968. ::UtilCvtIpAddrToWstr(Router, &strRouter);
  969. strBuf += strDest;
  970. strBuf += fLineFeed ? pszSepLF : pszSepComma;
  971. strBuf += strMask;
  972. strBuf += fLineFeed ? pszSepLF : pszSepComma;
  973. strBuf += strRouter;
  974. if( nDataSize > sizeof(DWORD) ) {
  975. strBuf += fLineFeed ? pszSepLF : pszSepComma;
  976. }
  977. bEmpty = FALSE;
  978. }
  979. strResult += strBuf;
  980. }
  981. if( bEmpty )
  982. {
  983. strResult.LoadString( IDS_INFO_FORMAT_IP_NONE );
  984. }
  985. }
  986. END_MEM_EXCEPTION(err)
  987. return err;
  988. }
  989. LONG
  990. CDhcpOptionValue::SetString
  991. (
  992. LPCTSTR pszNewValue,
  993. INT index
  994. )
  995. {
  996. if ( m_dhcpOptionDataType != DhcpStringDataOption )
  997. {
  998. return ERROR_INVALID_PARAMETER;
  999. }
  1000. ASSERT( m_dhcpOptionValue.paString != NULL );
  1001. LONG err = 0;
  1002. CATCH_MEM_EXCEPTION
  1003. {
  1004. m_dhcpOptionValue.paString->SetAtGrow( index, pszNewValue );
  1005. }
  1006. END_MEM_EXCEPTION(err)
  1007. return err;
  1008. }
  1009. LONG
  1010. CDhcpOptionValue::RemoveString
  1011. (
  1012. INT index
  1013. )
  1014. {
  1015. if ( m_dhcpOptionDataType != DhcpStringDataOption )
  1016. {
  1017. return ERROR_INVALID_PARAMETER;
  1018. }
  1019. ASSERT( m_dhcpOptionValue.paString != NULL );
  1020. LONG err = 0;
  1021. CATCH_MEM_EXCEPTION
  1022. {
  1023. m_dhcpOptionValue.paString->RemoveAt( index );
  1024. }
  1025. END_MEM_EXCEPTION(err)
  1026. return err;
  1027. }
  1028. LONG
  1029. CDhcpOptionValue::SetNumber
  1030. (
  1031. INT nValue,
  1032. INT index
  1033. )
  1034. {
  1035. if ( m_dhcpOptionDataType != DhcpByteOption
  1036. && m_dhcpOptionDataType != DhcpWordOption
  1037. && m_dhcpOptionDataType != DhcpDWordOption
  1038. && m_dhcpOptionDataType != DhcpIpAddressOption
  1039. && m_dhcpOptionDataType != DhcpBinaryDataOption
  1040. && m_dhcpOptionDataType != DhcpEncapsulatedDataOption
  1041. )
  1042. {
  1043. return ERROR_INVALID_PARAMETER;
  1044. }
  1045. ASSERT( m_dhcpOptionValue.paDword != NULL );
  1046. LONG err = 0;
  1047. CATCH_MEM_EXCEPTION
  1048. {
  1049. if ( m_dhcpOptionDataType != DhcpBinaryDataOption &&
  1050. m_dhcpOptionDataType != DhcpEncapsulatedDataOption)
  1051. {
  1052. m_dhcpOptionValue.paDword->SetAtGrow( index, (DWORD) nValue );
  1053. }
  1054. else
  1055. {
  1056. m_dhcpOptionValue.paBinary->SetAtGrow( index, (BYTE) nValue );
  1057. }
  1058. }
  1059. END_MEM_EXCEPTION(err)
  1060. return err;
  1061. }
  1062. LONG
  1063. CDhcpOptionValue::RemoveNumber
  1064. (
  1065. INT index
  1066. )
  1067. {
  1068. if ( m_dhcpOptionDataType != DhcpByteOption
  1069. && m_dhcpOptionDataType != DhcpWordOption
  1070. && m_dhcpOptionDataType != DhcpDWordOption
  1071. && m_dhcpOptionDataType != DhcpIpAddressOption
  1072. && m_dhcpOptionDataType != DhcpBinaryDataOption
  1073. && m_dhcpOptionDataType != DhcpEncapsulatedDataOption
  1074. )
  1075. {
  1076. return ERROR_INVALID_PARAMETER;
  1077. }
  1078. ASSERT( m_dhcpOptionValue.paDword != NULL );
  1079. LONG err = 0;
  1080. CATCH_MEM_EXCEPTION
  1081. {
  1082. if ( m_dhcpOptionDataType != DhcpBinaryDataOption &&
  1083. m_dhcpOptionDataType != DhcpEncapsulatedDataOption )
  1084. {
  1085. m_dhcpOptionValue.paDword->RemoveAt( index );
  1086. }
  1087. else
  1088. {
  1089. m_dhcpOptionValue.paBinary->RemoveAt( index );
  1090. }
  1091. }
  1092. END_MEM_EXCEPTION(err)
  1093. return err;
  1094. }
  1095. LONG
  1096. CDhcpOptionValue::QueryNumber
  1097. (
  1098. INT index
  1099. ) const
  1100. {
  1101. if ( m_dhcpOptionDataType != DhcpByteOption
  1102. && m_dhcpOptionDataType != DhcpWordOption
  1103. && m_dhcpOptionDataType != DhcpDWordOption
  1104. && m_dhcpOptionDataType != DhcpIpAddressOption
  1105. && m_dhcpOptionDataType != DhcpBinaryDataOption
  1106. && m_dhcpOptionDataType != DhcpEncapsulatedDataOption
  1107. )
  1108. {
  1109. return -1;
  1110. }
  1111. LONG cResult;
  1112. if ( m_dhcpOptionDataType == DhcpBinaryDataOption ||
  1113. m_dhcpOptionDataType == DhcpEncapsulatedDataOption )
  1114. {
  1115. ASSERT( m_dhcpOptionValue.paBinary != NULL );
  1116. cResult = index < m_dhcpOptionValue.paBinary->GetSize()
  1117. ? m_dhcpOptionValue.paBinary->GetAt( index )
  1118. : -1;
  1119. }
  1120. else
  1121. {
  1122. ASSERT( m_dhcpOptionValue.paDword != NULL );
  1123. cResult = index < m_dhcpOptionValue.paDword->GetSize()
  1124. ? m_dhcpOptionValue.paDword->GetAt( index )
  1125. : -1;
  1126. }
  1127. return cResult;
  1128. }
  1129. LPCTSTR
  1130. CDhcpOptionValue::QueryString
  1131. (
  1132. INT index
  1133. ) const
  1134. {
  1135. if ( m_dhcpOptionDataType != DhcpStringDataOption )
  1136. {
  1137. return NULL;
  1138. }
  1139. const CString & str = m_dhcpOptionValue.paString->ElementAt( index );
  1140. return str;
  1141. }
  1142. DHCP_IP_ADDRESS
  1143. CDhcpOptionValue::QueryIpAddr
  1144. (
  1145. INT index
  1146. ) const
  1147. {
  1148. return (DHCP_IP_ADDRESS) QueryNumber( index );
  1149. }
  1150. LONG
  1151. CDhcpOptionValue::SetIpAddr
  1152. (
  1153. DHCP_IP_ADDRESS dhcIpAddr,
  1154. INT index
  1155. )
  1156. {
  1157. return SetNumber( (INT) dhcIpAddr, index );
  1158. }
  1159. LONG
  1160. CDhcpOptionValue::RemoveIpAddr
  1161. (
  1162. INT index
  1163. )
  1164. {
  1165. return RemoveNumber( index );
  1166. }
  1167. BOOL
  1168. CDhcpOptionValue :: CreateBinaryData
  1169. (
  1170. const DHCP_BINARY_DATA * podBin,
  1171. DHCP_BINARY_DATA * pobData
  1172. )
  1173. {
  1174. //
  1175. // Note: CObject::operator new asserts if data length is zero
  1176. //
  1177. pobData->Data = new BYTE [ podBin->DataLength + 1 ] ;
  1178. if ( pobData == NULL )
  1179. {
  1180. return FALSE ;
  1181. }
  1182. pobData->DataLength = podBin->DataLength ;
  1183. ::memcpy( pobData->Data, podBin->Data, pobData->DataLength ) ;
  1184. return TRUE ;
  1185. }
  1186. BOOL
  1187. CDhcpOptionValue :: CreateBinaryData
  1188. (
  1189. const CByteArray * paByte,
  1190. DHCP_BINARY_DATA * pobData
  1191. )
  1192. {
  1193. //
  1194. // Note: CObject::operator new asserts if data length is zero
  1195. //
  1196. pobData->Data = new BYTE [ (UINT) (paByte->GetSize() + 1) ] ;
  1197. if ( pobData == NULL )
  1198. {
  1199. return NULL ;
  1200. }
  1201. pobData->DataLength = (DWORD) paByte->GetSize() ;
  1202. for ( INT i = 0 ; i < paByte->GetSize() ; i++ )
  1203. {
  1204. pobData->Data[i] = paByte->GetAt( i ) ;
  1205. }
  1206. return TRUE ;
  1207. }
  1208. DWORD_DWORD
  1209. CDhcpOptionValue::QueryDwordDword
  1210. (
  1211. int index
  1212. ) const
  1213. {
  1214. return m_dhcpOptionValue.paDwordDword->ElementAt( index );
  1215. }
  1216. LONG
  1217. CDhcpOptionValue::SetDwordDword
  1218. (
  1219. DWORD_DWORD dwdwValue,
  1220. int index
  1221. )
  1222. {
  1223. LONG err = 0;
  1224. CATCH_MEM_EXCEPTION
  1225. {
  1226. m_dhcpOptionValue.paDwordDword->SetAtGrow( index, dwdwValue );
  1227. }
  1228. END_MEM_EXCEPTION(err)
  1229. return err;
  1230. }
  1231. LONG
  1232. CDhcpOptionValue::RemoveDwordDword
  1233. (
  1234. int index
  1235. )
  1236. {
  1237. LONG err = 0;
  1238. CATCH_MEM_EXCEPTION
  1239. {
  1240. m_dhcpOptionValue.paDwordDword->RemoveAt( index );
  1241. }
  1242. END_MEM_EXCEPTION(err)
  1243. return err;
  1244. }
  1245. LONG
  1246. CDhcpOptionValue::CreateOptionDataStruct
  1247. (
  1248. // const CDhcpOptionValue * pdhcpOptionValue,
  1249. LPDHCP_OPTION_DATA * ppOptionData,
  1250. BOOL bForceType
  1251. )
  1252. {
  1253. DHCP_OPTION_DATA * podNew = NULL ;
  1254. DHCP_OPTION_DATA_ELEMENT * podeNew ;
  1255. LONG err = 0 ;
  1256. FreeOptionDataStruct() ;
  1257. INT cElem = QueryUpperBound();
  1258. INT cElemMin = cElem ? cElem : 1;
  1259. INT i, cBytes ;
  1260. TCHAR * pwcsz ;
  1261. if ( cElem < 0 || (cElem < 1 && ! bForceType) )
  1262. {
  1263. //ASSERT( FALSE ) ;
  1264. return ERROR_INVALID_PARAMETER ;
  1265. }
  1266. CATCH_MEM_EXCEPTION
  1267. {
  1268. //
  1269. // Allocate the base structure and the array of elements.
  1270. //
  1271. cBytes = sizeof *podNew + (cElemMin * sizeof *podeNew) ;
  1272. podNew = (DHCP_OPTION_DATA *) new BYTE [ cBytes ] ;
  1273. podeNew = (DHCP_OPTION_DATA_ELEMENT *) ( ((BYTE *) podNew) + sizeof *podNew ) ;
  1274. ::ZeroMemory(podNew, cBytes);
  1275. podNew->NumElements = cElem;
  1276. podNew->Elements = podeNew;
  1277. //
  1278. // Initialize each element. If we're forcing an option type def,
  1279. // just initialize to empty data.
  1280. //
  1281. if ( cElem == 0 && bForceType )
  1282. {
  1283. podNew->NumElements = 1 ;
  1284. podeNew[0].OptionType = QueryDataType() ;
  1285. switch ( podeNew[0].OptionType )
  1286. {
  1287. case DhcpByteOption:
  1288. case DhcpWordOption:
  1289. case DhcpDWordOption:
  1290. case DhcpIpAddressOption:
  1291. case DhcpDWordDWordOption:
  1292. podeNew[0].Element.DWordDWordOption.DWord1 = 0 ;
  1293. podeNew[0].Element.DWordDWordOption.DWord2 = 0 ;
  1294. break ;
  1295. case DhcpStringDataOption:
  1296. podeNew[0].Element.StringDataOption = new WCHAR [1] ;
  1297. podeNew[0].Element.StringDataOption[0] = 0 ;
  1298. break ;
  1299. case DhcpBinaryDataOption:
  1300. case DhcpEncapsulatedDataOption:
  1301. podeNew[0].Element.BinaryDataOption.DataLength = 0 ;
  1302. podeNew[0].Element.BinaryDataOption.Data = new BYTE [1] ;
  1303. break ;
  1304. default:
  1305. err = IDS_INVALID_OPTION_DATA ;
  1306. }
  1307. }
  1308. else
  1309. for ( i = 0 ; i < cElem ; i++ )
  1310. {
  1311. podeNew[i].OptionType = QueryDataType() ;
  1312. switch ( podeNew[i].OptionType )
  1313. {
  1314. case DhcpByteOption:
  1315. podeNew[i].Element.ByteOption = (BYTE) QueryNumber( i ) ;
  1316. break ;
  1317. case DhcpWordOption:
  1318. podeNew[i].Element.WordOption = (WORD) QueryNumber( i ) ;
  1319. break ;
  1320. case DhcpDWordOption:
  1321. podeNew[i].Element.DWordOption = QueryNumber( i ) ;
  1322. break ;
  1323. case DhcpDWordDWordOption:
  1324. podeNew[i].Element.DWordDWordOption = QueryDwordDword( i );
  1325. break ;
  1326. case DhcpIpAddressOption:
  1327. podeNew[i].Element.IpAddressOption = QueryIpAddr( i ) ;
  1328. break ;
  1329. case DhcpStringDataOption:
  1330. {
  1331. //CString * pstrTemp = new CString (QueryString(i));
  1332. CString strTemp = QueryString(i);
  1333. int nLength = strTemp.GetLength() + 1;
  1334. TCHAR * pString = new TCHAR[nLength];
  1335. ::ZeroMemory(pString, nLength * sizeof(TCHAR));
  1336. ::CopyMemory(pString, strTemp, strTemp.GetLength() * sizeof(TCHAR));
  1337. podeNew[i].Element.StringDataOption = pString;
  1338. break;
  1339. }
  1340. case DhcpBinaryDataOption:
  1341. case DhcpEncapsulatedDataOption:
  1342. podNew->NumElements = 1;
  1343. if ( !CreateBinaryData(QueryBinaryArray(),
  1344. &podeNew[i].Element.BinaryDataOption) )
  1345. {
  1346. err = ERROR_NOT_ENOUGH_MEMORY ;
  1347. break ;
  1348. }
  1349. break ;
  1350. default:
  1351. err = IDS_INVALID_OPTION_DATA ;
  1352. }
  1353. if ( err )
  1354. {
  1355. break ;
  1356. }
  1357. }
  1358. }
  1359. END_MEM_EXCEPTION(err)
  1360. if ( err == 0 )
  1361. {
  1362. m_pdhcpOptionDataStruct = podNew;
  1363. *ppOptionData = podNew;
  1364. }
  1365. return err ;
  1366. }
  1367. LONG
  1368. CDhcpOptionValue::FreeOptionDataStruct()
  1369. {
  1370. LONG err = 0;
  1371. if ( m_pdhcpOptionDataStruct == NULL )
  1372. {
  1373. return 0 ;
  1374. }
  1375. //
  1376. // We must deconstruct the struct build in CreateData()
  1377. //
  1378. INT cElem = m_pdhcpOptionDataStruct->NumElements ;
  1379. for ( INT i = 0 ; i < cElem ; i++ )
  1380. {
  1381. switch ( m_pdhcpOptionDataStruct->Elements[i].OptionType )
  1382. {
  1383. case DhcpByteOption:
  1384. case DhcpWordOption:
  1385. case DhcpDWordOption:
  1386. case DhcpDWordDWordOption:
  1387. case DhcpIpAddressOption:
  1388. break;
  1389. case DhcpStringDataOption:
  1390. delete m_pdhcpOptionDataStruct->Elements[i].Element.StringDataOption ;
  1391. break ;
  1392. case DhcpBinaryDataOption:
  1393. case DhcpEncapsulatedDataOption:
  1394. delete m_pdhcpOptionDataStruct->Elements[i].Element.BinaryDataOption.Data ;
  1395. break ;
  1396. default:
  1397. err = IDS_INVALID_OPTION_DATA ;
  1398. break;
  1399. }
  1400. if ( err )
  1401. {
  1402. break ;
  1403. }
  1404. }
  1405. //
  1406. // Finally, delete the main structure
  1407. //
  1408. delete m_pdhcpOptionDataStruct ;
  1409. m_pdhcpOptionDataStruct = NULL ;
  1410. return err ;
  1411. }
  1412. /////////////////////////////////////////////////////////////////////
  1413. //
  1414. // CDhcpOption implementation
  1415. //
  1416. /////////////////////////////////////////////////////////////////////
  1417. //
  1418. // Normal constructor: just wrapper the data given
  1419. //
  1420. CDhcpOption::CDhcpOption
  1421. (
  1422. const DHCP_OPTION & dhpOption
  1423. )
  1424. : m_dhcpOptionValue( dhpOption ),
  1425. m_dhcpOptionId( dhpOption.OptionID ),
  1426. m_dhcpOptionType( dhpOption.OptionType ),
  1427. m_bDirty(FALSE),
  1428. m_dwErr(0)
  1429. {
  1430. LONG err = 0 ;
  1431. CATCH_MEM_EXCEPTION
  1432. {
  1433. if ( !(SetName(dhpOption.OptionName) &&
  1434. SetComment(dhpOption.OptionComment) ) )
  1435. {
  1436. err = ERROR_NOT_ENOUGH_MEMORY ;
  1437. }
  1438. }
  1439. END_MEM_EXCEPTION(err)
  1440. if ( err )
  1441. {
  1442. ASSERT(FALSE);
  1443. //ReportError( err ) ;
  1444. }
  1445. }
  1446. //
  1447. // Constructor taking just a value structure. We must query
  1448. // the scope for the name, etc.
  1449. //
  1450. CDhcpOption::CDhcpOption
  1451. (
  1452. const DHCP_OPTION_VALUE & dhcpOptionValue,
  1453. LPCTSTR pszVendor,
  1454. LPCTSTR pszUserClass
  1455. )
  1456. : m_dhcpOptionValue( dhcpOptionValue ),
  1457. m_dhcpOptionId( dhcpOptionValue.OptionID ),
  1458. m_bDirty(FALSE),
  1459. m_dwErr(0),
  1460. m_strVendor(pszVendor),
  1461. m_strClassName(pszUserClass)
  1462. {
  1463. }
  1464. //
  1465. // Copy constructor
  1466. //
  1467. CDhcpOption::CDhcpOption
  1468. (
  1469. const CDhcpOption & dhcpOption
  1470. )
  1471. : m_dhcpOptionId( dhcpOption.m_dhcpOptionId ),
  1472. m_dhcpOptionType( dhcpOption.m_dhcpOptionType ),
  1473. m_strName( dhcpOption.m_strName ),
  1474. m_strComment( dhcpOption.m_strComment ),
  1475. m_dhcpOptionValue( dhcpOption.QueryDataType() ),
  1476. m_bDirty(FALSE),
  1477. m_dwErr(0),
  1478. m_strVendor( dhcpOption.m_strVendor ),
  1479. m_strClassName ( dhcpOption.m_strClassName )
  1480. {
  1481. m_dhcpOptionValue = dhcpOption.QueryValue();
  1482. }
  1483. //
  1484. // Constructor using a base type and an overriding value.
  1485. //
  1486. CDhcpOption::CDhcpOption
  1487. (
  1488. const CDhcpOption & dhpType,
  1489. const DHCP_OPTION_VALUE & dhcOptionValue
  1490. )
  1491. : m_dhcpOptionId( dhpType.m_dhcpOptionId ),
  1492. m_dhcpOptionType( dhpType.QueryOptType() ),
  1493. m_strName( dhpType.m_strName ),
  1494. m_strComment( dhpType.m_strComment ),
  1495. m_dhcpOptionValue( dhcOptionValue ),
  1496. m_bDirty(FALSE),
  1497. m_dwErr(0),
  1498. m_strVendor(dhpType.m_strVendor),
  1499. m_strClassName(dhpType.m_strClassName)
  1500. {
  1501. }
  1502. //
  1503. // Constructor for dynamic instances
  1504. //
  1505. CDhcpOption::CDhcpOption
  1506. (
  1507. DHCP_OPTION_ID nId,
  1508. DHCP_OPTION_DATA_TYPE dhcType,
  1509. LPCTSTR pszOptionName,
  1510. LPCTSTR pszComment,
  1511. DHCP_OPTION_TYPE dhcOptType
  1512. )
  1513. : m_dhcpOptionId( nId ),
  1514. m_dhcpOptionType( dhcOptType ),
  1515. m_dhcpOptionValue( dhcType, TRUE ),
  1516. m_strName( pszOptionName ),
  1517. m_strComment( pszComment ),
  1518. m_bDirty(FALSE),
  1519. m_dwErr(0)
  1520. {
  1521. }
  1522. CDhcpOption::~ CDhcpOption ()
  1523. {
  1524. }
  1525. INT
  1526. CDhcpOption::MaxSizeOfType
  1527. (
  1528. DHCP_OPTION_DATA_TYPE dhcType
  1529. )
  1530. {
  1531. INT nResult = -1 ;
  1532. switch ( dhcType )
  1533. {
  1534. case DhcpByteOption:
  1535. nResult = sizeof(CHAR) ;
  1536. break ;
  1537. case DhcpWordOption:
  1538. nResult = sizeof(WORD) ;
  1539. break ;
  1540. case DhcpDWordOption:
  1541. nResult = sizeof(DWORD) ;
  1542. break ;
  1543. case DhcpIpAddressOption:
  1544. nResult = sizeof(DHCP_IP_ADDRESS) ;
  1545. break ;
  1546. case DhcpDWordDWordOption:
  1547. nResult = sizeof(DWORD_DWORD);
  1548. break ;
  1549. case DhcpBinaryDataOption:
  1550. case DhcpEncapsulatedDataOption:
  1551. case DhcpStringDataOption:
  1552. nResult = STRING_LENGTH_MAX ;
  1553. break ;
  1554. default:
  1555. break;
  1556. }
  1557. return nResult ;
  1558. }
  1559. void
  1560. CDhcpOption::SetOptType
  1561. (
  1562. DHCP_OPTION_TYPE dhcOptType
  1563. )
  1564. {
  1565. m_dhcpOptionType = dhcOptType;
  1566. }
  1567. LONG
  1568. CDhcpOption::Update
  1569. (
  1570. const CDhcpOptionValue & dhpOptionValue
  1571. )
  1572. {
  1573. m_dhcpOptionValue = dhpOptionValue;
  1574. return 0;
  1575. }
  1576. BOOL
  1577. CDhcpOption::SetName
  1578. (
  1579. LPCTSTR pszName
  1580. )
  1581. {
  1582. m_strName = pszName;
  1583. return TRUE;
  1584. }
  1585. BOOL
  1586. CDhcpOption::SetComment
  1587. (
  1588. LPCTSTR pszComment
  1589. )
  1590. {
  1591. m_strComment = pszComment;
  1592. return TRUE;
  1593. }
  1594. void
  1595. CDhcpOption::QueryDisplayName
  1596. (
  1597. CString & cStr
  1598. ) const
  1599. {
  1600. cStr.Format(_T("%3.3d %s"), (int) QueryId(), (LPCTSTR) m_strName);
  1601. }
  1602. /*---------------------------------------------------------------------------
  1603. Class COptionValueEnum
  1604. Enumerates the options for a given level. Generates a list of
  1605. nodes.
  1606. Author: EricDav
  1607. ---------------------------------------------------------------------------*/
  1608. COptionValueEnum::COptionValueEnum()
  1609. {
  1610. }
  1611. /*---------------------------------------------------------------------------
  1612. COptionValueEnum::Init()
  1613. -
  1614. Author: EricDav
  1615. ---------------------------------------------------------------------------*/
  1616. DWORD
  1617. COptionValueEnum::Init
  1618. (
  1619. LPCTSTR pServer,
  1620. LARGE_INTEGER & liVersion,
  1621. DHCP_OPTION_SCOPE_INFO & dhcpOptionScopeInfo
  1622. )
  1623. {
  1624. m_strServer = pServer;
  1625. m_liVersion.QuadPart = liVersion.QuadPart;
  1626. m_dhcpOptionScopeInfo = dhcpOptionScopeInfo;
  1627. return 0;
  1628. }
  1629. /*---------------------------------------------------------------------------
  1630. COptionValueEnum::Copy()
  1631. Copies another value enum
  1632. Author: EricDav
  1633. ---------------------------------------------------------------------------*/
  1634. void
  1635. COptionValueEnum::Copy(COptionValueEnum * pEnum)
  1636. {
  1637. CDhcpOption * pOption = NULL;
  1638. pEnum->Reset();
  1639. while (pOption = pEnum->Next())
  1640. {
  1641. AddTail(pOption);
  1642. }
  1643. m_liVersion.QuadPart = pEnum->m_liVersion.QuadPart;
  1644. m_dhcpOptionScopeInfo = pEnum->m_dhcpOptionScopeInfo;
  1645. }
  1646. /*---------------------------------------------------------------------------
  1647. COptionValueEnum::Remove()
  1648. removes an option from the list
  1649. Author: EricDav
  1650. ---------------------------------------------------------------------------*/
  1651. void
  1652. COptionValueEnum::Remove(DHCP_OPTION_ID optionId, LPCTSTR pszVendor, LPCTSTR pszClass)
  1653. {
  1654. CDhcpOption * pOption = NULL;
  1655. Reset();
  1656. while (pOption = Next())
  1657. {
  1658. if ( pOption->QueryId() == optionId &&
  1659. (lstrcmp(pOption->GetVendor(), pszVendor) == 0) &&
  1660. (lstrcmp(pOption->GetClassName(), pszClass) == 0) )
  1661. {
  1662. COptionList::Remove(pOption);
  1663. delete pOption;
  1664. break;
  1665. }
  1666. }
  1667. }
  1668. /*---------------------------------------------------------------------------
  1669. COptionValueEnum::Enum()
  1670. Calls the appropriate enum function depending upon version
  1671. Author: EricDav
  1672. ---------------------------------------------------------------------------*/
  1673. DWORD
  1674. COptionValueEnum::Enum()
  1675. {
  1676. DWORD dwErr;
  1677. RemoveAll();
  1678. if (m_liVersion.QuadPart >= DHCP_NT5_VERSION)
  1679. {
  1680. // enumerate standard plus the vendor and class ID based options
  1681. dwErr = EnumOptionsV5();
  1682. }
  1683. else
  1684. {
  1685. // Enumerate the standard options
  1686. dwErr = EnumOptions();
  1687. }
  1688. // reset our position pointer to the head
  1689. Reset();
  1690. return dwErr;
  1691. }
  1692. /*---------------------------------------------------------------------------
  1693. COptionValueEnum::EnumOptions()
  1694. Description
  1695. Author: EricDav
  1696. ---------------------------------------------------------------------------*/
  1697. DWORD
  1698. COptionValueEnum::EnumOptions()
  1699. {
  1700. LPDHCP_OPTION_VALUE_ARRAY pOptionValues = NULL;
  1701. DWORD dwOptionsRead = 0, dwOptionsTotal = 0;
  1702. DWORD err = ERROR_SUCCESS;
  1703. HRESULT hr = hrOK;
  1704. DHCP_RESUME_HANDLE dhcpResumeHandle = NULL;
  1705. err = ::DhcpEnumOptionValues((LPWSTR) ((LPCTSTR) m_strServer),
  1706. &m_dhcpOptionScopeInfo,
  1707. &dhcpResumeHandle,
  1708. 0xFFFFFFFF,
  1709. &pOptionValues,
  1710. &dwOptionsRead,
  1711. &dwOptionsTotal);
  1712. Trace4("Server %s - DhcpEnumOptionValues returned %lx, read %d, Total %d.\n", m_strServer, err, dwOptionsRead, dwOptionsTotal);
  1713. if (dwOptionsRead && dwOptionsTotal && pOptionValues)
  1714. {
  1715. for (DWORD i = 0; i < dwOptionsRead; i++)
  1716. {
  1717. //
  1718. // Filter out the "special" option values that we don't want the
  1719. // user to see.
  1720. //
  1721. // CODEWORK: don't filter vendor specifc options... all vendor
  1722. // specifc options are visible.
  1723. //
  1724. if (FilterOption(pOptionValues->Values[i].OptionID))
  1725. continue;
  1726. //
  1727. // Create the result pane item for this element
  1728. //
  1729. CDhcpOption * pOption = new CDhcpOption(pOptionValues->Values[i], NULL, NULL);
  1730. AddTail(pOption);
  1731. }
  1732. ::DhcpRpcFreeMemory(pOptionValues);
  1733. }
  1734. if (err == ERROR_NO_MORE_ITEMS)
  1735. err = ERROR_SUCCESS;
  1736. return err;
  1737. }
  1738. /*---------------------------------------------------------------------------
  1739. COptionValueEnum::EnumOptionsV5()
  1740. Description
  1741. Author: EricDav
  1742. ---------------------------------------------------------------------------*/
  1743. DWORD
  1744. COptionValueEnum::EnumOptionsV5()
  1745. {
  1746. LPDHCP_OPTION_VALUE_ARRAY pOptionValues = NULL;
  1747. LPDHCP_ALL_OPTION_VALUES pAllOptions = NULL;
  1748. DWORD dwNumOptions, err, i;
  1749. err = ::DhcpGetAllOptionValues((LPWSTR) ((LPCTSTR) m_strServer),
  1750. 0,
  1751. &m_dhcpOptionScopeInfo,
  1752. &pAllOptions);
  1753. Trace2("Server %s - DhcpGetAllOptionValues (Global) returned %lx\n", m_strServer, err);
  1754. if (err == ERROR_NO_MORE_ITEMS || err == ERROR_SUCCESS)
  1755. {
  1756. if (pAllOptions == NULL)
  1757. {
  1758. // This happens when stressing the server. Perhaps when server is OOM.
  1759. err = ERROR_OUTOFMEMORY;
  1760. return err;
  1761. }
  1762. // get the list of options (vendor and non-vendor) defined for
  1763. // the NULL class (no class)
  1764. for (i = 0; i < pAllOptions->NumElements; i++)
  1765. {
  1766. CreateOptions(pAllOptions->Options[i].OptionsArray,
  1767. pAllOptions->Options[i].ClassName,
  1768. pAllOptions->Options[i].VendorName);
  1769. }
  1770. if (pAllOptions)
  1771. ::DhcpRpcFreeMemory(pAllOptions);
  1772. }
  1773. if (err == ERROR_NO_MORE_ITEMS)
  1774. err = ERROR_SUCCESS;
  1775. return err;
  1776. }
  1777. /*---------------------------------------------------------------------------
  1778. COptionValueEnum::CreateOptions()
  1779. Description
  1780. Author: EricDav
  1781. ---------------------------------------------------------------------------*/
  1782. HRESULT
  1783. COptionValueEnum::CreateOptions
  1784. (
  1785. LPDHCP_OPTION_VALUE_ARRAY pOptionValues,
  1786. LPCTSTR pClassName,
  1787. LPCTSTR pszVendor
  1788. )
  1789. {
  1790. HRESULT hr = hrOK;
  1791. SPITFSNode spNode;
  1792. CDhcpOptionItem * pOptionItem;
  1793. CString strDynBootpClassName;
  1794. if (pOptionValues == NULL)
  1795. return hr;
  1796. Trace1("COptionValueEnum::CreateOptions - Creating %d options\n", pOptionValues->NumElements);
  1797. COM_PROTECT_TRY
  1798. {
  1799. for (DWORD i = 0; i < pOptionValues->NumElements; i++)
  1800. {
  1801. //
  1802. // Filter out the "special" option values that we don't want the
  1803. // user to see.
  1804. //
  1805. // don't filter vendor specifc options... all vendor
  1806. // specifc options are visible.
  1807. //
  1808. // also don't filter out class based options
  1809. // except for dynamic bootp class
  1810. if ( (FilterOption(pOptionValues->Values[i].OptionID) &&
  1811. pClassName == NULL &&
  1812. !pszVendor) ||
  1813. (FilterOption(pOptionValues->Values[i].OptionID) &&
  1814. (pClassName && m_strDynBootpClassName.CompareNoCase(pClassName) == 0) &&
  1815. !pszVendor) )
  1816. {
  1817. continue;
  1818. }
  1819. //
  1820. // Create the option
  1821. //
  1822. CDhcpOption * pOption = new CDhcpOption(pOptionValues->Values[i], pszVendor, pClassName);
  1823. AddTail(pOption);
  1824. }
  1825. }
  1826. COM_PROTECT_CATCH
  1827. return hr;
  1828. }
  1829. /////////////////////////////////////////////////////////////////////
  1830. //
  1831. // CDhcpDefaultOptionsOnServer implementation
  1832. //
  1833. /////////////////////////////////////////////////////////////////////
  1834. LPCTSTR pszResourceName = _T("DHCPOPT") ;
  1835. LPCTSTR pszResourceType = _T("TEXT") ;
  1836. const int cchFieldMax = 500 ;
  1837. OPT_TOKEN aOptToken [] =
  1838. {
  1839. { DhcpIpAddressOption, _T("IP Addr") },
  1840. { DhcpIpAddressOption, _T("IPAddr") },
  1841. { DhcpIpAddressOption, _T("IP Address") },
  1842. { DhcpIpAddressOption, _T("IP Pairs") },
  1843. { DhcpByteOption, _T("byte") },
  1844. { DhcpByteOption, _T("boolean") },
  1845. { DhcpByteOption, _T("octet") },
  1846. { DhcpWordOption, _T("short") },
  1847. { DhcpDWordOption, _T("long") },
  1848. { DhcpDWordDWordOption, _T("double") },
  1849. { DhcpStringDataOption, _T("string") },
  1850. { DhcpBinaryDataOption, _T("binary") },
  1851. { DhcpEncapsulatedDataOption, _T("encapsulated") },
  1852. { -1, _T("generated") },
  1853. { -1, NULL }
  1854. };
  1855. CDhcpDefaultOptionsOnServer::CDhcpDefaultOptionsOnServer()
  1856. {
  1857. m_pos = NULL;
  1858. }
  1859. CDhcpDefaultOptionsOnServer::~CDhcpDefaultOptionsOnServer()
  1860. {
  1861. RemoveAll();
  1862. }
  1863. LONG
  1864. CDhcpDefaultOptionsOnServer::RemoveAll()
  1865. {
  1866. //
  1867. // Clean the list of all old entries
  1868. //
  1869. while (!m_listOptions.IsEmpty())
  1870. {
  1871. delete m_listOptions.RemoveHead();
  1872. }
  1873. return 0;
  1874. }
  1875. CDhcpOption *
  1876. CDhcpDefaultOptionsOnServer::First()
  1877. {
  1878. Reset();
  1879. return Next();
  1880. }
  1881. CDhcpOption *
  1882. CDhcpDefaultOptionsOnServer::Next()
  1883. {
  1884. return m_pos == NULL ? NULL : m_listOptions.GetNext( m_pos ) ;
  1885. }
  1886. void
  1887. CDhcpDefaultOptionsOnServer::Reset()
  1888. {
  1889. m_pos = m_listOptions.GetCount() ? m_listOptions.GetHeadPosition() : NULL ;
  1890. }
  1891. CDhcpOption *
  1892. CDhcpDefaultOptionsOnServer::Find
  1893. (
  1894. DHCP_OPTION_ID dhcpOptionId,
  1895. LPCTSTR pszVendor
  1896. )
  1897. {
  1898. POSITION pos = m_listOptions.GetHeadPosition();
  1899. CDhcpOption* pCurrent;
  1900. CDhcpOption* pFound = NULL;
  1901. CString strVendor = pszVendor;
  1902. while (pos != NULL)
  1903. {
  1904. pCurrent = m_listOptions.GetNext(pos);
  1905. // check the options IDs and the vendor classes match
  1906. if ( (pCurrent->QueryId() == dhcpOptionId) &&
  1907. ( (!pszVendor && !pCurrent->GetVendor()) ||
  1908. (pCurrent->GetVendor() && (strVendor.CompareNoCase(pCurrent->GetVendor()) == 0) ) ) )
  1909. {
  1910. pFound = pCurrent;
  1911. break;
  1912. }
  1913. }
  1914. return pFound;
  1915. }
  1916. // Sorts the options by ID
  1917. LONG
  1918. CDhcpDefaultOptionsOnServer::SortById()
  1919. {
  1920. return m_listOptions.SortById();
  1921. }
  1922. LONG
  1923. CDhcpDefaultOptionsOnServer::Enumerate
  1924. (
  1925. LPCWSTR pServer,
  1926. LARGE_INTEGER liVersion
  1927. )
  1928. {
  1929. if (liVersion.QuadPart >= DHCP_NT5_VERSION)
  1930. {
  1931. return EnumerateV5(pServer);
  1932. }
  1933. else
  1934. {
  1935. return EnumerateV4(pServer);
  1936. }
  1937. }
  1938. LONG
  1939. CDhcpDefaultOptionsOnServer::EnumerateV4
  1940. (
  1941. LPCWSTR pServer
  1942. )
  1943. {
  1944. //
  1945. // Use new API to get the param types
  1946. //
  1947. LPDHCP_OPTION_ARRAY pOptionsArray = NULL;
  1948. DHCP_RESUME_HANDLE dhcpResumeHandle = NULL;
  1949. LPDHCP_OPTION Options, pCurOption;
  1950. DWORD i;
  1951. DWORD dwNumOptions;
  1952. DWORD dwOptionsRead;
  1953. LONG err;
  1954. err = ::DhcpEnumOptions(pServer,
  1955. &dhcpResumeHandle,
  1956. 0xFFFFFFFF, // get all.
  1957. &pOptionsArray,
  1958. &dwOptionsRead,
  1959. &m_dwOptionsTotal );
  1960. if ( err )
  1961. {
  1962. return err;
  1963. }
  1964. //
  1965. // Discard all the old data
  1966. //
  1967. RemoveAll() ;
  1968. if (pOptionsArray == NULL)
  1969. {
  1970. // This happens when stressing the server. Perhaps when server is OOM.
  1971. return ERROR_OUTOFMEMORY;
  1972. }
  1973. try
  1974. {
  1975. Options = pOptionsArray->Options;
  1976. dwNumOptions = pOptionsArray->NumElements;
  1977. if ((dwNumOptions > 0) && (Options == NULL))
  1978. {
  1979. ASSERT(FALSE && _T("Data Inconsistency"));
  1980. return ERROR_OUTOFMEMORY; // Just in case
  1981. }
  1982. for(i = 0; i < dwNumOptions; i++)
  1983. {
  1984. //
  1985. // Create the new type object.
  1986. //
  1987. pCurOption = Options + i;
  1988. CDhcpOption * pdhcpOption = new CDhcpOption(*pCurOption);
  1989. //
  1990. // Add the new host to the list.
  1991. //
  1992. m_listOptions.AddTail(pdhcpOption);
  1993. }
  1994. }
  1995. catch (...)
  1996. {
  1997. err = ERROR_NOT_ENOUGH_MEMORY;
  1998. }
  1999. ::DhcpRpcFreeMemory(pOptionsArray);
  2000. pOptionsArray = NULL;
  2001. Reset();
  2002. return err;
  2003. }
  2004. LONG
  2005. CDhcpDefaultOptionsOnServer::EnumerateV5
  2006. (
  2007. LPCWSTR pServer
  2008. )
  2009. {
  2010. //
  2011. // Use new API to get the param types
  2012. //
  2013. LPDHCP_OPTION Options, pCurOption;
  2014. DWORD i;
  2015. DWORD dwNumOptions = 0;
  2016. DWORD dwOptionsRead = 0;
  2017. DWORD dwFlags = 0;
  2018. LONG err = 0;
  2019. LPDHCP_ALL_OPTIONS pAllOptions = NULL;
  2020. err = ::DhcpGetAllOptions((LPWSTR) pServer,
  2021. dwFlags,
  2022. &pAllOptions);
  2023. if ( err )
  2024. {
  2025. return err;
  2026. }
  2027. //
  2028. // Discard all the old data
  2029. //
  2030. RemoveAll() ;
  2031. if (pAllOptions == NULL)
  2032. {
  2033. // This happens when stressing the server. Perhaps when server is OOM.
  2034. return ERROR_OUTOFMEMORY;
  2035. }
  2036. try
  2037. {
  2038. // first pull out the non-vendor options
  2039. if (pAllOptions->NonVendorOptions != NULL)
  2040. {
  2041. Options = pAllOptions->NonVendorOptions->Options;
  2042. dwNumOptions = pAllOptions->NonVendorOptions->NumElements;
  2043. }
  2044. if ((dwNumOptions > 0) && (Options == NULL))
  2045. {
  2046. ASSERT(FALSE && _T("Data Inconsistency"));
  2047. return ERROR_OUTOFMEMORY; // Just in case
  2048. }
  2049. for (i = 0; i < dwNumOptions; i++)
  2050. {
  2051. //
  2052. // Create the new type object.
  2053. //
  2054. pCurOption = Options + i;
  2055. CDhcpOption * pdhcpOption = new CDhcpOption(*pCurOption);
  2056. //
  2057. // Add the new host to the list.
  2058. //
  2059. m_listOptions.AddTail(pdhcpOption);
  2060. }
  2061. // now the vendor options
  2062. for (i = 0; i < pAllOptions->NumVendorOptions; i++)
  2063. {
  2064. pCurOption = &pAllOptions->VendorOptions[i].Option;
  2065. CDhcpOption * pdhcpOption = new CDhcpOption(*pCurOption);
  2066. pdhcpOption->SetVendor(pAllOptions->VendorOptions[i].VendorName);
  2067. //
  2068. // Add the new host to the list.
  2069. //
  2070. m_listOptions.AddTail(pdhcpOption);
  2071. }
  2072. }
  2073. catch (...)
  2074. {
  2075. err = ERROR_NOT_ENOUGH_MEMORY;
  2076. }
  2077. if (pAllOptions)
  2078. ::DhcpRpcFreeMemory(pAllOptions);
  2079. SortById();
  2080. Reset();
  2081. return err;
  2082. }
  2083. /////////////////////////////////////////////////////////////////////
  2084. //
  2085. // CDhcpDefaultOptionsMasterList implementation
  2086. //
  2087. /////////////////////////////////////////////////////////////////////
  2088. CDhcpDefaultOptionsMasterList::CDhcpDefaultOptionsMasterList()
  2089. {
  2090. m_pos = NULL;
  2091. }
  2092. CDhcpDefaultOptionsMasterList::~CDhcpDefaultOptionsMasterList()
  2093. {
  2094. //
  2095. // Delete all entries in the list
  2096. //
  2097. while (!m_listOptions.IsEmpty())
  2098. {
  2099. delete m_listOptions.RemoveHead();
  2100. }
  2101. }
  2102. CDhcpOption *
  2103. CDhcpDefaultOptionsMasterList::First()
  2104. {
  2105. Reset();
  2106. return Next();
  2107. }
  2108. CDhcpOption *
  2109. CDhcpDefaultOptionsMasterList::Next()
  2110. {
  2111. return m_pos == NULL ? NULL : m_listOptions.GetNext( m_pos ) ;
  2112. }
  2113. void
  2114. CDhcpDefaultOptionsMasterList::Reset()
  2115. {
  2116. m_pos = m_listOptions.GetCount() ? m_listOptions.GetHeadPosition() : NULL ;
  2117. }
  2118. int
  2119. CDhcpDefaultOptionsMasterList::GetCount()
  2120. {
  2121. return (int)m_listOptions.GetCount();
  2122. }
  2123. long
  2124. CDhcpDefaultOptionsMasterList::BuildList()
  2125. {
  2126. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2127. LONG err = 0 ;
  2128. CDhcpOption * pOption;
  2129. HRSRC hRes = NULL ;
  2130. HGLOBAL hText = NULL ;
  2131. LPTSTR pszText = NULL ;
  2132. LPCTSTR pcszText ;
  2133. size_t cchText = 0;
  2134. UINT uBufSize = 0;
  2135. LPTSTR * szParms;
  2136. TCHAR szUnknown[] = _T("(Unknown)"); // This is just to prevent a GP fault (should not be in resource)
  2137. CATCH_MEM_EXCEPTION
  2138. {
  2139. do
  2140. {
  2141. //
  2142. // IMPORTANT!!! There is no way to determine from the .mc file how many
  2143. // options are defined. This number is therefore hard-coded
  2144. // here, and should reflect the highest parameter number in
  2145. // the .mc file.
  2146. //
  2147. // The extra 16 entries are for safety
  2148. // when calling FormatMessage().
  2149. szParms = new LPTSTR[IDS_OPTION_MAX + 16];
  2150. Trace0("BuildList - Now building list of option parameters\n");
  2151. CString strOptionText;
  2152. // Initialize the extra entries to something that will not GP fault.
  2153. for (int i = 0; i < 16; i++)
  2154. {
  2155. szParms[IDS_OPTION_MAX+i] = szUnknown;
  2156. }
  2157. //
  2158. // Don't mess with the order of the ID definitions!!!
  2159. //
  2160. for (i = 0; i < IDS_OPTION_MAX; ++i)
  2161. {
  2162. if (strOptionText.LoadString(IDS_OPTION1 + i))
  2163. {
  2164. ASSERT(strOptionText.GetLength() > 0);
  2165. uBufSize += strOptionText.GetLength();
  2166. szParms[i] = new TCHAR[strOptionText.GetLength()+1];
  2167. ::_tcscpy(szParms[i], (LPCTSTR)strOptionText);
  2168. }
  2169. else
  2170. {
  2171. //
  2172. // Failed to load the string from the resource
  2173. // for some reason.
  2174. //
  2175. CString strTemp;
  2176. strTemp.LoadString(IDS_OPTION1 + i);
  2177. Trace1("BuildList - WARNING: Failed to load option text %s\n", strTemp);
  2178. err = ::GetLastError();
  2179. szParms[i] = szUnknown; // Prevent from GP faulting
  2180. break;
  2181. }
  2182. }
  2183. if (err != ERROR_SUCCESS)
  2184. {
  2185. break;
  2186. }
  2187. // allocate a buffer big enough to hold the data
  2188. uBufSize *= sizeof(TCHAR);
  2189. uBufSize *= 2;
  2190. pszText = (LPTSTR) malloc(uBufSize);
  2191. if (pszText == NULL)
  2192. {
  2193. err = ERROR_OUTOFMEMORY;
  2194. break;
  2195. }
  2196. //
  2197. // Since we are a COM object, get our instance handle to use so that FormatMessage
  2198. // looks in the right place for our resources.
  2199. //
  2200. HINSTANCE hInst = _Module.GetModuleInstance();
  2201. while (cchText == 0)
  2202. {
  2203. cchText = ::FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
  2204. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  2205. (HMODULE) hInst, // hModule
  2206. DHCP_OPTIONS, // dwMessageId loaded from a system dll
  2207. 0L, // dwLanguageId
  2208. OUT (LPTSTR)pszText,
  2209. uBufSize/sizeof(TCHAR),
  2210. (va_list *)szParms);
  2211. if (cchText == 0)
  2212. {
  2213. err = ::GetLastError();
  2214. Trace1("BuildList - FormatMessage failed - error %d\n", err);
  2215. // grow the buffer and try again
  2216. uBufSize += uBufSize/2;
  2217. pszText = (LPTSTR) realloc(pszText, uBufSize);
  2218. if (pszText == NULL)
  2219. {
  2220. err = ERROR_OUTOFMEMORY;
  2221. break;
  2222. }
  2223. }
  2224. else
  2225. {
  2226. // done
  2227. break;
  2228. }
  2229. }
  2230. //
  2231. // Walk the resource, parsing each line. If the line converts
  2232. // to a tangible type, add it to the list.
  2233. //
  2234. for ( pcszText = pszText ; pcszText ; )
  2235. {
  2236. scanNextParamType( &pcszText, &pOption);
  2237. if ( pOption )
  2238. {
  2239. m_listOptions.AddTail(pOption) ;
  2240. }
  2241. }
  2242. } while ( FALSE ) ;
  2243. }
  2244. END_MEM_EXCEPTION( err )
  2245. for (int i = 0; i < IDS_OPTION_MAX; ++i)
  2246. {
  2247. if (szParms[i] != szUnknown)
  2248. delete[] szParms[i];
  2249. }
  2250. delete[] szParms;
  2251. free(pszText);
  2252. Reset();
  2253. return NOERROR;
  2254. }
  2255. BOOL
  2256. CDhcpDefaultOptionsMasterList::scanNextParamType
  2257. (
  2258. LPCTSTR * ppszText,
  2259. CDhcpOption * * ppOption
  2260. )
  2261. {
  2262. TCHAR szField [ cchFieldMax ] ;
  2263. TCHAR szName [ cchFieldMax ] ;
  2264. TCHAR szComment [ cchFieldMax ] ;
  2265. BOOL bResult = TRUE ;
  2266. BOOL bArray = FALSE ;
  2267. int eofld, cch, itype, cbLgt ;
  2268. LPCTSTR pszText = *ppszText ;
  2269. CDhcpOption * pOption = NULL ;
  2270. DHCP_OPTION_ID did ;
  2271. DHCP_OPTION_DATA_TYPE dtype = (DHCP_OPTION_DATA_TYPE)0;
  2272. for ( eofld = OPTF_OPTION ;
  2273. pszText = scanNextField( pszText, szField, sizeof szField ) ;
  2274. eofld++ )
  2275. {
  2276. cch = ::_tcslen( szField ) ;
  2277. switch ( eofld )
  2278. {
  2279. case OPTF_OPTION:
  2280. if ( cch > 0 && allDigits( szField ) )
  2281. {
  2282. did = (DHCP_OPTION_ID) ::_ttoi( szField ) ;
  2283. }
  2284. else
  2285. {
  2286. bResult = FALSE ;
  2287. }
  2288. break ;
  2289. case OPTF_NAME:
  2290. if ( ::_tcslen( szField ) == 0 )
  2291. {
  2292. bResult = FALSE ;
  2293. break ;
  2294. }
  2295. ::_tcscpy( szName, szField ) ;
  2296. break ;
  2297. case OPTF_TYPE:
  2298. if ( (itype = recognizeToken( aOptToken, szField )) < 0 )
  2299. {
  2300. Trace2("options CSV ID %d, cannot reconize type %s\n", did, szField);
  2301. bResult = FALSE ;
  2302. break ;
  2303. }
  2304. dtype = (DHCP_OPTION_DATA_TYPE) itype ;
  2305. break ;
  2306. case OPTF_ARRAY_FLAG:
  2307. bArray = szField[0] == 'y' || szField[0] == 'Y' ;
  2308. break ;
  2309. case OPTF_LENGTH:
  2310. cbLgt = ::_ttoi( szField ) ;
  2311. break ;
  2312. case OPTF_DESCRIPTION:
  2313. ::_tcscpy( szComment, szField ) ;
  2314. break ;
  2315. case OPTF_REMARK:
  2316. case OPTF_MAX:
  2317. break ;
  2318. }
  2319. if ( eofld == OPTF_REMARK || ! bResult )
  2320. {
  2321. pszText = skipToNextLine( pszText ) ;
  2322. if ( *pszText == 0 )
  2323. {
  2324. pszText = NULL ;
  2325. }
  2326. break;
  2327. }
  2328. }
  2329. if ( bResult )
  2330. {
  2331. pOption = new CDhcpOption( did,
  2332. dtype,
  2333. szName,
  2334. szComment,
  2335. bArray ? DhcpArrayTypeOption :
  2336. DhcpUnaryElementTypeOption ) ;
  2337. }
  2338. if ( bResult )
  2339. {
  2340. *ppOption = pOption ;
  2341. }
  2342. else
  2343. {
  2344. delete pOption ;
  2345. *ppOption = NULL ;
  2346. }
  2347. *ppszText = pszText ;
  2348. return pszText != NULL ;
  2349. }
  2350. LPCTSTR
  2351. CDhcpDefaultOptionsMasterList::scanNextField
  2352. (
  2353. LPCTSTR pszLine,
  2354. LPTSTR pszOut,
  2355. int cFieldSize
  2356. )
  2357. {
  2358. //
  2359. // Skip junk; return NULL if end-of-buffer.
  2360. //
  2361. if ( ! skipWs( & pszLine ) )
  2362. {
  2363. return NULL ;
  2364. }
  2365. int cch = 0 ;
  2366. BOOL bDone = FALSE ;
  2367. LPTSTR pszField = pszOut ;
  2368. TCHAR ch ;
  2369. if ( *pszLine == '\"' )
  2370. {
  2371. //
  2372. // Quoted string.
  2373. //
  2374. while ( ch = *++pszLine )
  2375. {
  2376. if ( ch == '\r' )
  2377. {
  2378. continue ;
  2379. }
  2380. if ( ch == '\n' || ch == '\"' || cch == cFieldSize )
  2381. {
  2382. break ;
  2383. }
  2384. *pszField++ = ch ;
  2385. cch++ ;
  2386. }
  2387. if ( ch == '\"' )
  2388. {
  2389. pszLine++ ;
  2390. }
  2391. }
  2392. else
  2393. while ( ! bDone )
  2394. {
  2395. ch = *pszLine++ ;
  2396. ASSERT( ch != 0 ) ;
  2397. switch ( ch )
  2398. {
  2399. case '\n':
  2400. pszLine-- ; // Don't scan past the NL
  2401. case ',':
  2402. case '\r':
  2403. bDone = TRUE ;
  2404. break ;
  2405. default:
  2406. if ( cch < cFieldSize )
  2407. {
  2408. *pszField++ = ch ;
  2409. cch++ ;
  2410. }
  2411. break ;
  2412. }
  2413. }
  2414. //
  2415. // Trim spaces off the end of the field.
  2416. //
  2417. while ( pszField > pszOut && *(pszField-1) == ' ' )
  2418. {
  2419. pszField-- ;
  2420. }
  2421. *pszField = 0 ;
  2422. return pszLine ;
  2423. }
  2424. BOOL
  2425. CDhcpDefaultOptionsMasterList::allDigits
  2426. (
  2427. LPCTSTR psz
  2428. )
  2429. {
  2430. for ( ; *psz ; psz++ )
  2431. {
  2432. if ( ! isdigit( *psz ) )
  2433. {
  2434. return FALSE ;
  2435. }
  2436. }
  2437. return TRUE ;
  2438. }
  2439. int
  2440. CDhcpDefaultOptionsMasterList::recognizeToken
  2441. (
  2442. OPT_TOKEN * apToken,
  2443. LPCTSTR pszToken
  2444. )
  2445. {
  2446. int i ;
  2447. for ( i = 0 ;
  2448. apToken[i].pszOptTypeName && ::lstrcmpi( apToken[i].pszOptTypeName, pszToken ) != 0 ;
  2449. i++ ) ;
  2450. return apToken[i].eOptType ;
  2451. }
  2452. LPCTSTR
  2453. CDhcpDefaultOptionsMasterList::skipToNextLine
  2454. (
  2455. LPCTSTR pszLine
  2456. )
  2457. {
  2458. for ( ; *pszLine && *pszLine != '\n' ; pszLine++ ) ;
  2459. if ( *pszLine )
  2460. {
  2461. pszLine++ ; // Don't overscan buffer delimiter.
  2462. }
  2463. return pszLine ;
  2464. }
  2465. BOOL
  2466. CDhcpDefaultOptionsMasterList::skipWs
  2467. (
  2468. LPCTSTR * ppszLine
  2469. )
  2470. {
  2471. LPCTSTR pszLine ;
  2472. BOOL bResult = FALSE ;
  2473. for ( pszLine = *ppszLine ; *pszLine ; pszLine++ )
  2474. {
  2475. switch ( *pszLine )
  2476. {
  2477. case ' ':
  2478. case '\r':
  2479. case '\t':
  2480. break ;
  2481. default:
  2482. bResult = TRUE ;
  2483. break ;
  2484. }
  2485. if ( bResult )
  2486. {
  2487. break ;
  2488. }
  2489. }
  2490. *ppszLine = pszLine ;
  2491. return *pszLine != 0 ;
  2492. }