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.

2938 lines
70 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. DWORD_DWORD dwdwValue;
  610. dwdwValue.DWord1 = 0;
  611. dwdwValue.DWord2 = 0;
  612. m_dhcpOptionValue.paDwordDword->SetAtGrow( 0, dwdwValue );
  613. }
  614. break;
  615. case DhcpBinaryDataOption:
  616. case DhcpEncapsulatedDataOption:
  617. m_dhcpOptionValue.paBinary = new CByteArray;
  618. if ( bProvideDefaultValue )
  619. {
  620. m_dhcpOptionValue.paBinary->SetAtGrow( 0, 0 );
  621. }
  622. break;
  623. default:
  624. err = IDS_INVALID_OPTION_DATA;
  625. break;
  626. }
  627. }
  628. END_MEM_EXCEPTION(err)
  629. return err;
  630. }
  631. void CDhcpOptionValue::RemoveAll()
  632. {
  633. // Remove all the entries for this option value
  634. LONG err = 0;
  635. err = InitValue( QueryDataType(), QueryUpperBound(), TRUE );
  636. ASSERT( err == 0 );
  637. } // CDhcpOptionValue::RemoveAll()
  638. LONG
  639. CDhcpOptionValue::SetData
  640. (
  641. const DHCP_OPTION_DATA * podData
  642. )
  643. {
  644. LONG err = 0;
  645. if ( err = InitValue( podData->Elements[0].OptionType,
  646. podData->NumElements,
  647. FALSE ) )
  648. {
  649. return err;
  650. }
  651. CATCH_MEM_EXCEPTION
  652. {
  653. for ( INT i = 0; i < m_nUpperBound; i++ )
  654. {
  655. const DHCP_OPTION_DATA_ELEMENT * pElem = &podData->Elements[i];
  656. switch ( m_dhcpOptionDataType )
  657. {
  658. case DhcpByteOption:
  659. m_dhcpOptionValue.paDword->SetAtGrow(i, pElem->Element.ByteOption );
  660. break;
  661. case DhcpWordOption:
  662. m_dhcpOptionValue.paDword->SetAtGrow(i, pElem->Element.WordOption );
  663. break;
  664. case DhcpDWordOption:
  665. m_dhcpOptionValue.paDword->SetAtGrow(i, pElem->Element.DWordOption );
  666. break;
  667. case DhcpIpAddressOption:
  668. m_dhcpOptionValue.paDword->Add(pElem->Element.IpAddressOption );
  669. break;
  670. case DhcpDWordDWordOption:
  671. {
  672. /*
  673. CByteArray * paByte = m_dhcpOptionValue.paBinary;
  674. paByte->SetSize( (sizeof (DWORD) / sizeof (BYTE)) * 2 );
  675. DWORD dw = pElem->Element.DWordDWordOption.DWord1;
  676. for ( INT j = 0; j < 4; j++ )
  677. {
  678. paByte->SetAtGrow(j, (UCHAR)(dw & 0xff) );
  679. dw >>= 8;
  680. }
  681. dw = pElem->Element.DWordDWordOption.DWord2;
  682. for ( ; j < 8; j++ )
  683. {
  684. paByte->SetAtGrow(j, (UCHAR)(dw & 0xff) );
  685. dw >>= 8;
  686. }
  687. */
  688. m_dhcpOptionValue.paDwordDword->SetAtGrow(i, pElem->Element.DWordDWordOption);
  689. }
  690. break;
  691. case DhcpStringDataOption:
  692. {
  693. CString strTemp;
  694. if ( pElem->Element.StringDataOption == NULL )
  695. {
  696. strTemp = _T("");
  697. }
  698. else
  699. {
  700. strTemp = pElem->Element.StringDataOption;
  701. }
  702. m_dhcpOptionValue.paString->SetAtGrow(i, strTemp);
  703. }
  704. break;
  705. case DhcpBinaryDataOption:
  706. case DhcpEncapsulatedDataOption:
  707. {
  708. CByteArray * paByte = m_dhcpOptionValue.paBinary;
  709. INT c = pElem->Element.BinaryDataOption.DataLength;
  710. paByte->SetSize( c );
  711. for ( INT j = 0; j < c; j++ )
  712. {
  713. paByte->SetAtGrow(j, pElem->Element.BinaryDataOption.Data[j] );
  714. }
  715. }
  716. break;
  717. default:
  718. err = IDS_INVALID_OPTION_DATA;
  719. } // End switch
  720. if ( err )
  721. {
  722. break;
  723. }
  724. } // End for
  725. }
  726. END_MEM_EXCEPTION(err)
  727. return err;
  728. }
  729. LONG
  730. CDhcpOptionValue::SetData
  731. (
  732. const CDhcpOptionValue * pOptionValue
  733. )
  734. {
  735. LONG err = 0;
  736. if ( err = InitValue( pOptionValue->QueryDataType(),
  737. pOptionValue->QueryUpperBound(),
  738. FALSE ) )
  739. {
  740. return err;
  741. }
  742. CATCH_MEM_EXCEPTION
  743. {
  744. for ( INT i = 0; i < m_nUpperBound; i++ )
  745. {
  746. switch ( m_dhcpOptionDataType )
  747. {
  748. case DhcpByteOption:
  749. m_dhcpOptionValue.paDword->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paDword->GetAt(i));
  750. break;
  751. case DhcpWordOption:
  752. m_dhcpOptionValue.paDword->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paDword->GetAt(i));
  753. break;
  754. case DhcpDWordOption:
  755. m_dhcpOptionValue.paDword->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paDword->GetAt(i));
  756. break;
  757. case DhcpIpAddressOption:
  758. m_dhcpOptionValue.paDword->Add(pOptionValue->m_dhcpOptionValue.paDword->GetAt(i));
  759. break;
  760. case DhcpDWordDWordOption:
  761. {
  762. /*
  763. CByteArray * paByte = m_dhcpOptionValue.paBinary;
  764. paByte->SetSize( (sizeof (DWORD) / sizeof (BYTE)) * 2 );
  765. for ( INT j = 0; j < 8; j++ )
  766. {
  767. paByte->SetAtGrow(j, pOptionValue->m_dhcpOptionValue.paBinary->GetAt(j));
  768. }
  769. */
  770. m_dhcpOptionValue.paDwordDword->Add(pOptionValue->m_dhcpOptionValue.paDwordDword->GetAt(i));
  771. }
  772. break;
  773. case DhcpStringDataOption:
  774. {
  775. m_dhcpOptionValue.paString->SetAtGrow(i, pOptionValue->m_dhcpOptionValue.paString->GetAt(i));
  776. }
  777. break;
  778. case DhcpBinaryDataOption:
  779. case DhcpEncapsulatedDataOption:
  780. {
  781. CByteArray * paByte = m_dhcpOptionValue.paBinary;
  782. INT_PTR c = pOptionValue->m_dhcpOptionValue.paBinary->GetSize();
  783. paByte->SetSize( c );
  784. for ( INT_PTR j = 0; j < c; j++ )
  785. {
  786. paByte->SetAtGrow(j, pOptionValue->m_dhcpOptionValue.paBinary->GetAt(j));
  787. }
  788. }
  789. break;
  790. default:
  791. err = IDS_INVALID_OPTION_DATA;
  792. } // End switch
  793. if ( err )
  794. {
  795. break;
  796. }
  797. } // End for
  798. }
  799. END_MEM_EXCEPTION(err)
  800. return err;
  801. }
  802. INT
  803. CDhcpOptionValue::QueryBinary
  804. (
  805. INT index
  806. ) const
  807. {
  808. if ( m_dhcpOptionValue.paBinary->GetUpperBound() < index )
  809. {
  810. return -1;
  811. }
  812. return m_dhcpOptionValue.paBinary->GetAt( index );
  813. }
  814. const CByteArray *
  815. CDhcpOptionValue::QueryBinaryArray () const
  816. {
  817. return m_dhcpOptionValue.paBinary;
  818. }
  819. //
  820. // Return a string representation of the current value.
  821. //
  822. // If fLineFeed is true, seperate each individual value
  823. // by a linefeed. Otherwise, by a comma.
  824. //
  825. LONG
  826. CDhcpOptionValue::QueryDisplayString
  827. (
  828. CString & strResult,
  829. BOOL fLineFeed
  830. ) const
  831. {
  832. CString strBuf;
  833. INT i, c;
  834. LONG err = 0;
  835. LPCTSTR pszDwordDwordMask = _T("0x%08lX%08lX");
  836. LPCTSTR pszMaskDec = _T("%ld");
  837. LPCTSTR pszMaskHex = _T("0x%x");
  838. LPCTSTR pszMaskStr1 = _T("%s");
  839. LPCTSTR pszMaskStr2 = _T("\"%s\"");
  840. LPCTSTR pszMaskBin = _T("%2.2x");
  841. LPCTSTR pszMask;
  842. LPCTSTR pszMaskEllipsis = _T("...");
  843. LPCTSTR pszSepComma = _T(", ");
  844. LPCTSTR pszSepLF = _T("\r\n");
  845. CATCH_MEM_EXCEPTION {
  846. strResult.Empty();
  847. for ( i = 0; i < m_nUpperBound; i++ ) {
  848. strBuf.Empty();
  849. if ( i ) {
  850. strResult += fLineFeed ? pszSepLF : pszSepComma;
  851. }
  852. switch ( QueryDataType()) {
  853. case DhcpByteOption:
  854. case DhcpWordOption:
  855. case DhcpDWordOption:
  856. pszMask = pszMaskHex;
  857. strBuf.Format(pszMask, QueryNumber(i));
  858. break;
  859. case DhcpStringDataOption:
  860. pszMask = m_nUpperBound > 1
  861. ? pszMaskStr2
  862. : pszMaskStr1;
  863. strBuf.Format( pszMask, m_dhcpOptionValue.paString->ElementAt( i ));
  864. break;
  865. case DhcpIpAddressOption:
  866. if (!QueryIpAddr(i)) {
  867. // Set the string to "<None>" iff the list is empty
  868. if (!i)
  869. strResult.LoadString (IDS_INFO_FORMAT_IP_NONE);
  870. break;
  871. }
  872. ::UtilCvtIpAddrToWstr(QueryIpAddr(i), &strBuf);
  873. break;
  874. case DhcpDWordDWordOption: {
  875. DWORD_DWORD dwdwValue = QueryDwordDword(i);
  876. pszMask = pszDwordDwordMask;
  877. strBuf.Format(pszMask, dwdwValue.DWord1, dwdwValue.DWord2);
  878. }
  879. break;
  880. case DhcpBinaryDataOption:
  881. case DhcpEncapsulatedDataOption:
  882. for ( c = 0; c < m_dhcpOptionValue.paBinary->GetSize(); c++ ) {
  883. if (c) {
  884. strBuf += _T(" ");
  885. }
  886. DWORD dwValue = (BYTE) m_dhcpOptionValue.paBinary->GetAt( c );
  887. CString strTemp;
  888. strTemp.Format(pszMaskBin, dwValue);
  889. strBuf += strTemp;
  890. } // for
  891. break;
  892. default:
  893. strResult.LoadString(IDS_INFO_TYPNAM_INVALID);
  894. break;
  895. } // switch
  896. strResult += strBuf;
  897. } // for
  898. } // CATCH....
  899. END_MEM_EXCEPTION(err)
  900. return err;
  901. }
  902. //
  903. // Return a string representation of the current value.
  904. //
  905. //
  906. LONG
  907. CDhcpOptionValue::QueryRouteArrayDisplayString
  908. (
  909. CString & strResult
  910. ) const
  911. {
  912. BOOL fLineFeed = FALSE;
  913. CString strBuf;
  914. INT i, c;
  915. LONG err = 0;
  916. LPCTSTR pszDwordDwordMask = _T("0x%08lX%08lX");
  917. LPCTSTR pszMaskDec = _T("%ld");
  918. LPCTSTR pszMaskHex = _T("0x%x");
  919. LPCTSTR pszMaskStr1 = _T("%s");
  920. LPCTSTR pszMaskStr2 = _T("\"%s\"");
  921. LPCTSTR pszMaskBin = _T("%2.2x");
  922. LPCTSTR pszMask;
  923. LPCTSTR pszMaskEllipsis = _T("...");
  924. LPCTSTR pszSepComma = _T(", ");
  925. LPCTSTR pszSepLF = _T("\r\n");
  926. CATCH_MEM_EXCEPTION
  927. {
  928. strResult.Empty();
  929. int bEmpty = TRUE;
  930. for ( i = 0; i < m_nUpperBound; i++ )
  931. {
  932. if ( i )
  933. {
  934. strResult += fLineFeed ? pszSepLF : pszSepComma;
  935. }
  936. int nDataSize = (int)m_dhcpOptionValue.paBinary->GetSize();
  937. LPBYTE pData = (LPBYTE) m_dhcpOptionValue.paBinary->GetData();
  938. // convert pData to list of ip addresses as per RFC
  939. while( nDataSize > sizeof(DWORD) )
  940. {
  941. // first 1 byte contains the # of bits in subnetmask
  942. nDataSize --;
  943. BYTE nBitsMask = *pData ++;
  944. DWORD Mask = (~0);
  945. if( nBitsMask < 32 ) Mask <<= (32-nBitsMask);
  946. // based on the # of bits, the next few bytes contain
  947. // the subnet address for the 1-bits of subnet mask
  948. int nBytesDest = (nBitsMask+7)/8;
  949. if( nBytesDest > 4 ) nBytesDest = 4;
  950. DWORD Dest = 0;
  951. memcpy( &Dest, pData, nBytesDest );
  952. pData += nBytesDest;
  953. nDataSize -= nBytesDest;
  954. // subnet address is obviously in network order.
  955. Dest = ntohl(Dest);
  956. // now the four bytes would be the router address
  957. DWORD Router = 0;
  958. if( nDataSize < sizeof(DWORD) )
  959. {
  960. Assert( FALSE ); break;
  961. }
  962. memcpy(&Router, pData, sizeof(DWORD));
  963. Router = ntohl( Router );
  964. pData += sizeof(DWORD);
  965. nDataSize -= sizeof(DWORD);
  966. // now fill the list box..
  967. CString strDest, strMask, strRouter;
  968. ::UtilCvtIpAddrToWstr(Dest, &strDest);
  969. ::UtilCvtIpAddrToWstr(Mask, &strMask);
  970. ::UtilCvtIpAddrToWstr(Router, &strRouter);
  971. strBuf += strDest;
  972. strBuf += fLineFeed ? pszSepLF : pszSepComma;
  973. strBuf += strMask;
  974. strBuf += fLineFeed ? pszSepLF : pszSepComma;
  975. strBuf += strRouter;
  976. bEmpty = FALSE;
  977. strBuf += pszSepLF;
  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. if ( NULL != pAllOptions ) {
  2026. ::DhcpRpcFreeMemory( pAllOptions );
  2027. }
  2028. return err;
  2029. }
  2030. //
  2031. // Discard all the old data
  2032. //
  2033. RemoveAll() ;
  2034. if (pAllOptions == NULL)
  2035. {
  2036. // This happens when stressing the server. Perhaps when server is OOM.
  2037. return ERROR_OUTOFMEMORY;
  2038. }
  2039. try
  2040. {
  2041. // first pull out the non-vendor options
  2042. if (pAllOptions->NonVendorOptions != NULL)
  2043. {
  2044. Options = pAllOptions->NonVendorOptions->Options;
  2045. dwNumOptions = pAllOptions->NonVendorOptions->NumElements;
  2046. }
  2047. if ((dwNumOptions > 0) && (Options == NULL))
  2048. {
  2049. ASSERT(FALSE && _T("Data Inconsistency"));
  2050. ::DhcpRpcFreeMemory( pAllOptions );
  2051. return ERROR_OUTOFMEMORY; // Just in case
  2052. }
  2053. for (i = 0; i < dwNumOptions; i++)
  2054. {
  2055. //
  2056. // Create the new type object.
  2057. //
  2058. pCurOption = Options + i;
  2059. CDhcpOption * pdhcpOption = new CDhcpOption(*pCurOption);
  2060. //
  2061. // Add the new host to the list.
  2062. //
  2063. m_listOptions.AddTail(pdhcpOption);
  2064. }
  2065. // now the vendor options
  2066. for (i = 0; i < pAllOptions->NumVendorOptions; i++)
  2067. {
  2068. pCurOption = &pAllOptions->VendorOptions[i].Option;
  2069. CDhcpOption * pdhcpOption = new CDhcpOption(*pCurOption);
  2070. pdhcpOption->SetVendor(pAllOptions->VendorOptions[i].VendorName);
  2071. //
  2072. // Add the new host to the list.
  2073. //
  2074. m_listOptions.AddTail(pdhcpOption);
  2075. }
  2076. }
  2077. catch (...)
  2078. {
  2079. err = ERROR_NOT_ENOUGH_MEMORY;
  2080. }
  2081. if (pAllOptions)
  2082. ::DhcpRpcFreeMemory(pAllOptions);
  2083. SortById();
  2084. Reset();
  2085. return err;
  2086. }
  2087. /////////////////////////////////////////////////////////////////////
  2088. //
  2089. // CDhcpDefaultOptionsMasterList implementation
  2090. //
  2091. /////////////////////////////////////////////////////////////////////
  2092. CDhcpDefaultOptionsMasterList::CDhcpDefaultOptionsMasterList()
  2093. {
  2094. m_pos = NULL;
  2095. }
  2096. CDhcpDefaultOptionsMasterList::~CDhcpDefaultOptionsMasterList()
  2097. {
  2098. //
  2099. // Delete all entries in the list
  2100. //
  2101. while (!m_listOptions.IsEmpty())
  2102. {
  2103. delete m_listOptions.RemoveHead();
  2104. }
  2105. }
  2106. CDhcpOption *
  2107. CDhcpDefaultOptionsMasterList::First()
  2108. {
  2109. Reset();
  2110. return Next();
  2111. }
  2112. CDhcpOption *
  2113. CDhcpDefaultOptionsMasterList::Next()
  2114. {
  2115. return m_pos == NULL ? NULL : m_listOptions.GetNext( m_pos ) ;
  2116. }
  2117. void
  2118. CDhcpDefaultOptionsMasterList::Reset()
  2119. {
  2120. m_pos = m_listOptions.GetCount() ? m_listOptions.GetHeadPosition() : NULL ;
  2121. }
  2122. int
  2123. CDhcpDefaultOptionsMasterList::GetCount()
  2124. {
  2125. return (int)m_listOptions.GetCount();
  2126. }
  2127. long
  2128. CDhcpDefaultOptionsMasterList::BuildList()
  2129. {
  2130. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2131. LONG err = 0 ;
  2132. CDhcpOption * pOption;
  2133. HRSRC hRes = NULL ;
  2134. HGLOBAL hText = NULL ;
  2135. LPTSTR pszText = NULL ;
  2136. LPCTSTR pcszText ;
  2137. size_t cchText = 0;
  2138. UINT uBufSize = 0;
  2139. LPTSTR * szParms;
  2140. TCHAR szUnknown[] = _T("(Unknown)"); // This is just to prevent a GP fault (should not be in resource)
  2141. CATCH_MEM_EXCEPTION
  2142. {
  2143. do
  2144. {
  2145. //
  2146. // IMPORTANT!!! There is no way to determine from the .mc file how many
  2147. // options are defined. This number is therefore hard-coded
  2148. // here, and should reflect the highest parameter number in
  2149. // the .mc file.
  2150. //
  2151. // The extra 16 entries are for safety
  2152. // when calling FormatMessage().
  2153. szParms = new LPTSTR[IDS_OPTION_MAX + 16];
  2154. Trace0("BuildList - Now building list of option parameters\n");
  2155. CString strOptionText;
  2156. // Initialize the extra entries to something that will not GP fault.
  2157. for (int i = 0; i < 16; i++)
  2158. {
  2159. szParms[IDS_OPTION_MAX+i] = szUnknown;
  2160. }
  2161. //
  2162. // Don't mess with the order of the ID definitions!!!
  2163. //
  2164. for (i = 0; i < IDS_OPTION_MAX; ++i)
  2165. {
  2166. if (strOptionText.LoadString(IDS_OPTION1 + i))
  2167. {
  2168. ASSERT(strOptionText.GetLength() > 0);
  2169. uBufSize += strOptionText.GetLength();
  2170. szParms[i] = new TCHAR[strOptionText.GetLength()+1];
  2171. ::_tcscpy(szParms[i], (LPCTSTR)strOptionText);
  2172. }
  2173. else
  2174. {
  2175. //
  2176. // Failed to load the string from the resource
  2177. // for some reason.
  2178. //
  2179. CString strTemp;
  2180. strTemp.LoadString(IDS_OPTION1 + i);
  2181. Trace1("BuildList - WARNING: Failed to load option text %s\n", strTemp);
  2182. err = ::GetLastError();
  2183. szParms[i] = szUnknown; // Prevent from GP faulting
  2184. break;
  2185. }
  2186. }
  2187. if (err != ERROR_SUCCESS)
  2188. {
  2189. break;
  2190. }
  2191. // allocate a buffer big enough to hold the data
  2192. uBufSize *= sizeof(TCHAR);
  2193. uBufSize *= 2;
  2194. pszText = (LPTSTR) malloc(uBufSize);
  2195. if (pszText == NULL)
  2196. {
  2197. err = ERROR_OUTOFMEMORY;
  2198. break;
  2199. }
  2200. //
  2201. // Since we are a COM object, get our instance handle to use so that FormatMessage
  2202. // looks in the right place for our resources.
  2203. //
  2204. HINSTANCE hInst = _Module.GetModuleInstance();
  2205. while (cchText == 0)
  2206. {
  2207. cchText = ::FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
  2208. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  2209. (HMODULE) hInst, // hModule
  2210. DHCP_OPTIONS, // dwMessageId loaded from a system dll
  2211. 0L, // dwLanguageId
  2212. OUT (LPTSTR)pszText,
  2213. uBufSize/sizeof(TCHAR),
  2214. (va_list *)szParms);
  2215. if (cchText == 0)
  2216. {
  2217. err = ::GetLastError();
  2218. Trace1("BuildList - FormatMessage failed - error %d\n", err);
  2219. // grow the buffer and try again
  2220. uBufSize += uBufSize/2;
  2221. LPTSTR pTemp = (LPTSTR) realloc(pszText, uBufSize);
  2222. if ( NULL == pTemp )
  2223. {
  2224. err = ERROR_OUTOFMEMORY;
  2225. break;
  2226. }
  2227. else {
  2228. pszText = pTemp;
  2229. }
  2230. }
  2231. else
  2232. {
  2233. // done
  2234. break;
  2235. }
  2236. }
  2237. //
  2238. // Walk the resource, parsing each line. If the line converts
  2239. // to a tangible type, add it to the list.
  2240. //
  2241. for ( pcszText = pszText ; pcszText ; )
  2242. {
  2243. scanNextParamType( &pcszText, &pOption);
  2244. if ( pOption )
  2245. {
  2246. m_listOptions.AddTail(pOption) ;
  2247. }
  2248. }
  2249. } while ( FALSE ) ;
  2250. }
  2251. END_MEM_EXCEPTION( err )
  2252. for (int i = 0; i < IDS_OPTION_MAX; ++i)
  2253. {
  2254. if (szParms[i] != szUnknown)
  2255. delete[] szParms[i];
  2256. }
  2257. delete[] szParms;
  2258. free(pszText);
  2259. Reset();
  2260. return NOERROR;
  2261. }
  2262. BOOL
  2263. CDhcpDefaultOptionsMasterList::scanNextParamType
  2264. (
  2265. LPCTSTR * ppszText,
  2266. CDhcpOption * * ppOption
  2267. )
  2268. {
  2269. TCHAR szField [ cchFieldMax ] ;
  2270. TCHAR szName [ cchFieldMax ] ;
  2271. TCHAR szComment [ cchFieldMax ] ;
  2272. BOOL bResult = TRUE ;
  2273. BOOL bArray = FALSE ;
  2274. int eofld, cch, itype, cbLgt ;
  2275. LPCTSTR pszText = *ppszText ;
  2276. CDhcpOption * pOption = NULL ;
  2277. const DWORD INVALID_OPTION_ID = 0xFFFF;
  2278. DHCP_OPTION_ID did = INVALID_OPTION_ID;
  2279. DHCP_OPTION_DATA_TYPE dtype = (DHCP_OPTION_DATA_TYPE)0;
  2280. for ( eofld = OPTF_OPTION ;
  2281. pszText = scanNextField( pszText, szField, sizeof szField ) ;
  2282. eofld++ )
  2283. {
  2284. cch = ::_tcslen( szField ) ;
  2285. switch ( eofld )
  2286. {
  2287. case OPTF_OPTION:
  2288. if ( cch > 0 && allDigits( szField ) )
  2289. {
  2290. did = (DHCP_OPTION_ID) ::_ttoi( szField ) ;
  2291. }
  2292. else {
  2293. bResult = FALSE;
  2294. }
  2295. break ;
  2296. case OPTF_NAME:
  2297. if ( ::_tcslen( szField ) == 0 )
  2298. {
  2299. bResult = FALSE;
  2300. break ;
  2301. }
  2302. ::_tcscpy( szName, szField ) ;
  2303. break ;
  2304. case OPTF_TYPE:
  2305. if ( (itype = recognizeToken( aOptToken, szField )) < 0 )
  2306. {
  2307. Trace2("options CSV ID %d, cannot reconize type %s\n", did, szField);
  2308. bResult = FALSE ;
  2309. break ;
  2310. }
  2311. dtype = (DHCP_OPTION_DATA_TYPE) itype ;
  2312. break ;
  2313. case OPTF_ARRAY_FLAG:
  2314. bArray = szField[0] == 'y' || szField[0] == 'Y' ;
  2315. break ;
  2316. case OPTF_LENGTH:
  2317. cbLgt = ::_ttoi( szField ) ;
  2318. break ;
  2319. case OPTF_DESCRIPTION:
  2320. ::_tcscpy( szComment, szField ) ;
  2321. break ;
  2322. case OPTF_REMARK:
  2323. case OPTF_MAX:
  2324. break ;
  2325. }
  2326. if ( eofld == OPTF_REMARK || ! bResult )
  2327. {
  2328. pszText = skipToNextLine( pszText ) ;
  2329. if ( *pszText == 0 )
  2330. {
  2331. pszText = NULL ;
  2332. }
  2333. break;
  2334. }
  2335. }
  2336. if (( bResult ) && ( INVALID_OPTION_ID != did ))
  2337. {
  2338. pOption = new CDhcpOption( did,
  2339. dtype,
  2340. szName,
  2341. szComment,
  2342. bArray ? DhcpArrayTypeOption :
  2343. DhcpUnaryElementTypeOption ) ;
  2344. }
  2345. if ( bResult )
  2346. {
  2347. *ppOption = pOption ;
  2348. }
  2349. else
  2350. {
  2351. delete pOption ;
  2352. *ppOption = NULL ;
  2353. }
  2354. *ppszText = pszText ;
  2355. return pszText != NULL ;
  2356. }
  2357. LPCTSTR
  2358. CDhcpDefaultOptionsMasterList::scanNextField
  2359. (
  2360. LPCTSTR pszLine,
  2361. LPTSTR pszOut,
  2362. int cFieldSize
  2363. )
  2364. {
  2365. //
  2366. // Skip junk; return NULL if end-of-buffer.
  2367. //
  2368. if ( ! skipWs( & pszLine ) )
  2369. {
  2370. return NULL ;
  2371. }
  2372. int cch = 0 ;
  2373. BOOL bDone = FALSE ;
  2374. LPTSTR pszField = pszOut ;
  2375. TCHAR ch ;
  2376. if ( *pszLine == '\"' )
  2377. {
  2378. //
  2379. // Quoted string.
  2380. //
  2381. while ( ch = *++pszLine )
  2382. {
  2383. if ( ch == '\r' )
  2384. {
  2385. continue ;
  2386. }
  2387. if ( ch == '\n' || ch == '\"' || cch == cFieldSize )
  2388. {
  2389. break ;
  2390. }
  2391. *pszField++ = ch ;
  2392. cch++ ;
  2393. }
  2394. if ( ch == '\"' )
  2395. {
  2396. pszLine++ ;
  2397. }
  2398. }
  2399. else
  2400. while ( ! bDone )
  2401. {
  2402. ch = *pszLine++ ;
  2403. ASSERT( ch != 0 ) ;
  2404. switch ( ch )
  2405. {
  2406. case '\n':
  2407. pszLine-- ; // Don't scan past the NL
  2408. case ',':
  2409. case '\r':
  2410. bDone = TRUE ;
  2411. break ;
  2412. default:
  2413. if ( cch < cFieldSize )
  2414. {
  2415. *pszField++ = ch ;
  2416. cch++ ;
  2417. }
  2418. break ;
  2419. }
  2420. }
  2421. //
  2422. // Trim spaces off the end of the field.
  2423. //
  2424. while ( pszField > pszOut && *(pszField-1) == ' ' )
  2425. {
  2426. pszField-- ;
  2427. }
  2428. *pszField = 0 ;
  2429. return pszLine ;
  2430. }
  2431. BOOL
  2432. CDhcpDefaultOptionsMasterList::allDigits
  2433. (
  2434. LPCTSTR psz
  2435. )
  2436. {
  2437. for ( ; *psz ; psz++ )
  2438. {
  2439. if ( ! isdigit( *psz ) )
  2440. {
  2441. return FALSE ;
  2442. }
  2443. }
  2444. return TRUE ;
  2445. }
  2446. int
  2447. CDhcpDefaultOptionsMasterList::recognizeToken
  2448. (
  2449. OPT_TOKEN * apToken,
  2450. LPCTSTR pszToken
  2451. )
  2452. {
  2453. int i ;
  2454. for ( i = 0 ;
  2455. apToken[i].pszOptTypeName && ::lstrcmpi( apToken[i].pszOptTypeName, pszToken ) != 0 ;
  2456. i++ ) ;
  2457. return apToken[i].eOptType ;
  2458. }
  2459. LPCTSTR
  2460. CDhcpDefaultOptionsMasterList::skipToNextLine
  2461. (
  2462. LPCTSTR pszLine
  2463. )
  2464. {
  2465. for ( ; *pszLine && *pszLine != '\n' ; pszLine++ ) ;
  2466. if ( *pszLine )
  2467. {
  2468. pszLine++ ; // Don't overscan buffer delimiter.
  2469. }
  2470. return pszLine ;
  2471. }
  2472. BOOL
  2473. CDhcpDefaultOptionsMasterList::skipWs
  2474. (
  2475. LPCTSTR * ppszLine
  2476. )
  2477. {
  2478. LPCTSTR pszLine ;
  2479. BOOL bResult = FALSE ;
  2480. for ( pszLine = *ppszLine ; *pszLine ; pszLine++ )
  2481. {
  2482. switch ( *pszLine )
  2483. {
  2484. case ' ':
  2485. case '\r':
  2486. case '\t':
  2487. break ;
  2488. default:
  2489. bResult = TRUE ;
  2490. break ;
  2491. }
  2492. if ( bResult )
  2493. {
  2494. break ;
  2495. }
  2496. }
  2497. *ppszLine = pszLine ;
  2498. return *pszLine != 0 ;
  2499. }