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.

971 lines
24 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. queue.c
  5. Abstract:
  6. Domain Name System (DNS) Server
  7. Queue functionality specific to Dynamic DNS registration.
  8. Author:
  9. Ram Viswanathan (ramv) March 27 1997
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. extern DWORD g_MainQueueCount;
  14. //
  15. // Queue allocations in dnslib heap
  16. //
  17. #define QUEUE_ALLOC_HEAP(Size) Dns_Alloc(Size)
  18. #define QUEUE_ALLOC_HEAP_ZERO(Size) Dns_AllocZero(Size)
  19. #define QUEUE_FREE_HEAP(pMem) Dns_Free(pMem)
  20. //
  21. // helper functions
  22. //
  23. PQELEMENT
  24. DequeueNoCrit(
  25. PDYNDNSQUEUE pQueue
  26. );
  27. DWORD
  28. AddToTimedOutQueueNoCrit(
  29. PQELEMENT pNewElement,
  30. PDYNDNSQUEUE pRetryQueue,
  31. DWORD dwRetryTime
  32. );
  33. DWORD
  34. HostAddrCmp(
  35. REGISTER_HOST_ENTRY HostAddr1,
  36. REGISTER_HOST_ENTRY HostAddr2
  37. )
  38. {
  39. //
  40. // DCR: Ram's HostAddrCmp will need update for IPv6
  41. //
  42. // returns 0 if the two hostaddresses are the same. Else we simply
  43. // return (DWORD)-1
  44. //
  45. if ( (HostAddr1.dwOptions == HostAddr2.dwOptions) &&
  46. (HostAddr1.Addr.ipAddr == HostAddr2.Addr.ipAddr))
  47. {
  48. return(0);
  49. } else {
  50. return( (DWORD)-1);
  51. }
  52. return ( (DWORD) -1);
  53. }
  54. VOID
  55. DeleteListEntry(
  56. PDYNDNSQUEUE pQueue,
  57. PQELEMENT* ppQElement
  58. );
  59. DWORD
  60. InitializeQueues(
  61. PDYNDNSQUEUE * ppQueue,
  62. PDYNDNSQUEUE * ppTimedOutQueue
  63. )
  64. /*
  65. InitializeQueue()
  66. This function initializes the queue system. This is invoked for the first
  67. time when you create the main queue and timed out queue
  68. Allocates appropriate memory etc
  69. */
  70. {
  71. DWORD dwRetval = ERROR_SUCCESS;
  72. *ppQueue = (PDYNDNSQUEUE) QUEUE_ALLOC_HEAP_ZERO( sizeof(DYNDNSQUEUE) );
  73. if (!*ppQueue){
  74. dwRetval = GetLastError();
  75. goto Exit;
  76. }
  77. *ppTimedOutQueue = (PDYNDNSQUEUE) QUEUE_ALLOC_HEAP_ZERO( sizeof(DYNDNSQUEUE) );
  78. if (!*ppTimedOutQueue){
  79. dwRetval = GetLastError();
  80. goto Exit;
  81. }
  82. (*ppQueue)->pHead = NULL;
  83. (*ppQueue)->pTail = NULL;
  84. (*ppTimedOutQueue)->pHead = NULL;
  85. (*ppTimedOutQueue)->pTail = NULL;
  86. Exit:
  87. if (dwRetval)
  88. {
  89. if ( *ppQueue )
  90. QUEUE_FREE_HEAP( *ppQueue );
  91. if ( *ppTimedOutQueue )
  92. QUEUE_FREE_HEAP( *ppTimedOutQueue );
  93. }
  94. return(dwRetval);
  95. }
  96. DWORD
  97. FreeQueue(
  98. PDYNDNSQUEUE pQueue
  99. )
  100. /*
  101. FreeQueue()
  102. Frees the queue object. If there exist any entries in the queue, we
  103. just blow them away
  104. */
  105. {
  106. PQELEMENT pQElement;
  107. DWORD dwRetval = ERROR_SUCCESS;
  108. EnterCriticalSection(&g_QueueCS);
  109. if (!pQueue){
  110. dwRetval = ERROR_SUCCESS;
  111. goto Exit;
  112. }
  113. while (pQueue->pHead){
  114. pQElement = DequeueNoCrit(pQueue);
  115. DNS_ASSERT(pQElement);
  116. if ( pQElement->pszName )
  117. QUEUE_FREE_HEAP( pQElement->pszName );
  118. if ( pQElement->DnsServerList )
  119. QUEUE_FREE_HEAP( pQElement->DnsServerList );
  120. QUEUE_FREE_HEAP( pQElement );
  121. pQElement = NULL;
  122. }
  123. QUEUE_FREE_HEAP( pQueue );
  124. Exit:
  125. LeaveCriticalSection(&g_QueueCS);
  126. return(ERROR_SUCCESS);
  127. }
  128. DWORD
  129. Enqueue(
  130. PQELEMENT pNewElement,
  131. PDYNDNSQUEUE pQueue,
  132. PDYNDNSQUEUE pTimedOutQueue
  133. )
  134. /*
  135. Enqueue()
  136. Adds new element to queue
  137. Arguments:
  138. Return Value:
  139. is 0 if Success. and (DWORD)-1 if failure.
  140. */
  141. {
  142. // add to tail of queue
  143. PQELEMENT pIterator = NULL;
  144. DWORD dwRetval = 0;
  145. DWORD dwRetryTime = 0;
  146. pNewElement->pFLink = NULL;
  147. pNewElement->pBLink = NULL;
  148. pNewElement->dwRetryTime = 0; // unnecessary for this queue
  149. pNewElement->dwRetryCount = 0;
  150. EnterCriticalSection(&g_QueueCS);
  151. if (!pQueue || !pTimedOutQueue){
  152. dwRetval = (DWORD)-1;
  153. goto Exit;
  154. }
  155. dwRetryTime = ProcessQDependencies(pTimedOutQueue, pNewElement);
  156. if (dwRetryTime){
  157. //
  158. // we have dependents in timed out queue. Add to timed out queue
  159. // insert this element at the appropriate position
  160. //
  161. AddToTimedOutQueueNoCrit(pNewElement, pTimedOutQueue, dwRetryTime+1);
  162. } else {
  163. ProcessQDependencies(pQueue, pNewElement);
  164. if ( pQueue->pTail )
  165. {
  166. DNS_ASSERT(!pQueue->pTail->pBLink);
  167. pQueue->pTail->pBLink = pNewElement;
  168. pNewElement->pFLink = pQueue->pTail;
  169. pNewElement->pBLink = NULL;
  170. pQueue->pTail = pNewElement;
  171. }
  172. else
  173. {
  174. //
  175. // no tail element means no head element either
  176. //
  177. pQueue->pTail = pNewElement;
  178. pQueue->pHead = pNewElement;
  179. pNewElement->pBLink = NULL;
  180. pNewElement->pFLink = NULL;
  181. }
  182. g_MainQueueCount++;
  183. }
  184. Exit:
  185. LeaveCriticalSection(&g_QueueCS);
  186. return (dwRetval);
  187. }
  188. PQELEMENT
  189. DequeueNoCrit(
  190. PDYNDNSQUEUE pQueue
  191. )
  192. /*
  193. DequeueNoCrit()
  194. Removes an element from a queue. No Critical Section Used by freequeue
  195. and by Dequeue
  196. Arguments:
  197. Return Value:
  198. is the element at head of queue if Success. and NULL if failure.
  199. */
  200. {
  201. PQELEMENT pQueuePtr = NULL;
  202. PQELEMENT pRet = NULL;
  203. if (!pQueue || !pQueue->pHead){
  204. goto Exit;
  205. }
  206. pRet = pQueue->pHead;
  207. pQueuePtr= pRet->pBLink;
  208. if (pQueuePtr){
  209. pQueuePtr->pFLink = NULL;
  210. pQueue->pHead = pQueuePtr;
  211. } else {
  212. //
  213. // no more elements in the Queue
  214. //
  215. pQueue->pHead = pQueue->pTail = NULL;
  216. }
  217. pRet->pFLink = NULL;
  218. pRet->pBLink = NULL;
  219. Exit:
  220. return (pRet);
  221. }
  222. PQELEMENT
  223. Dequeue(
  224. PDYNDNSQUEUE pQueue
  225. )
  226. /*
  227. Dequeue()
  228. Removes an element from a queue.
  229. Arguments:
  230. Return Value:
  231. is the element at head of queue if Success. and NULL if failure.
  232. */
  233. {
  234. PQELEMENT pQElement = NULL;
  235. EnterCriticalSection(&g_QueueCS);
  236. pQElement = DequeueNoCrit(pQueue);
  237. LeaveCriticalSection(&g_QueueCS);
  238. return (pQElement);
  239. }
  240. DWORD
  241. AddToTimedOutQueueNoCrit(
  242. PQELEMENT pNewElement,
  243. PDYNDNSQUEUE pRetryQueue,
  244. DWORD dwRetryTime
  245. )
  246. /*
  247. AddToTimedOutQueueNoCrit()
  248. Adds new element to timedout queue. Now the new element is added in a list
  249. of elements sorted according to decreasing order of Retry Times. An
  250. insertion sort type of algorithm is used.
  251. Arguments:
  252. Return Value:
  253. is 0 if Success. and (DWORD)-1 if failure.
  254. */
  255. {
  256. DWORD dwRetval = ERROR_SUCCESS;
  257. PQELEMENT pTraverse = NULL;
  258. DWORD dwVal = 0;
  259. //
  260. // parameter validation
  261. //
  262. if(!pNewElement || !pRetryQueue){
  263. dwRetval = (DWORD)-1;
  264. goto Exit;
  265. }
  266. // retry again in dwRetryTime
  267. pNewElement->dwRetryTime = dwRetryTime;
  268. pNewElement->dwRetryCount++;
  269. //
  270. // check to see if there are any dependencies
  271. //
  272. dwVal = ProcessQDependencies (
  273. pRetryQueue,
  274. pNewElement
  275. );
  276. //
  277. // ignore return values because we are inserting in the new queue
  278. // at a position determined by dwRetryTime
  279. //
  280. if (!pRetryQueue->pTail){
  281. //
  282. // the queue has no elements
  283. // no tail element means no head element either
  284. //
  285. pRetryQueue->pTail = pNewElement;
  286. pRetryQueue->pHead = pNewElement;
  287. dwRetval = 0;
  288. goto Exit;
  289. }
  290. //
  291. // elements must be added in decreasing order of timeouts.
  292. // go in and scan the list from the head.
  293. //
  294. pTraverse = pRetryQueue->pHead;
  295. while ( pTraverse !=NULL &&
  296. pTraverse->dwRetryTime <= pNewElement->dwRetryTime){
  297. pTraverse = pTraverse->pBLink;
  298. }
  299. if (pTraverse == NULL){
  300. // Now adding to the tail of the list
  301. pNewElement->pFLink = pRetryQueue->pTail;
  302. pNewElement->pBLink = NULL;
  303. pRetryQueue->pTail->pBLink = pNewElement;
  304. pRetryQueue->pTail = pNewElement;
  305. } else {
  306. //
  307. // insert in place
  308. //
  309. pNewElement->pBLink = pTraverse;
  310. pNewElement->pFLink = pTraverse->pFLink;
  311. if (pTraverse->pFLink){
  312. pTraverse->pFLink->pBLink = pNewElement;
  313. }
  314. pTraverse->pFLink = pNewElement;
  315. }
  316. Exit:
  317. return (dwRetval);
  318. }
  319. DWORD
  320. AddToTimedOutQueue(
  321. PQELEMENT pNewElement,
  322. PDYNDNSQUEUE pRetryQueue,
  323. DWORD dwRetryTime
  324. )
  325. {
  326. DWORD dwRetval = ERROR_SUCCESS;
  327. EnterCriticalSection(&g_QueueCS);
  328. dwRetval = AddToTimedOutQueueNoCrit(
  329. pNewElement,
  330. pRetryQueue,
  331. dwRetryTime
  332. );
  333. LeaveCriticalSection(&g_QueueCS);
  334. return (dwRetval);
  335. }
  336. DWORD
  337. GetEarliestRetryTime(
  338. PDYNDNSQUEUE pRetryQueue
  339. )
  340. /*
  341. GetEarliestRetryTime()
  342. Checks to see if there is any element at the head of the queue
  343. and gets the retry time for this element
  344. Arguments:
  345. Return Value:
  346. is retrytime if success and DWORD(-1) if there is no element or other
  347. failure
  348. */
  349. {
  350. DWORD dwRetryTime ;
  351. EnterCriticalSection(&g_QueueCS);
  352. dwRetryTime = pRetryQueue && pRetryQueue->pHead ?
  353. (pRetryQueue->pHead->dwRetryTime):
  354. (DWORD)-1;
  355. LeaveCriticalSection(&g_QueueCS);
  356. return dwRetryTime;
  357. }
  358. /*
  359. VOID
  360. ProcessMainQDependencies(
  361. PDYNDNSQUEUE pQueue,
  362. PQELEMENT pQElement
  363. )
  364. {
  365. //
  366. // when you are adding an element to a main queue, you
  367. // just care about the case where all elements aren't
  368. // FORWARD_ONLY
  369. //
  370. BOOL fDelThisTime = FALSE;
  371. PQELEMENT pIterator = pQueue->pTail;
  372. while (pIterator!= NULL){
  373. fDelThisTime = FALSE;
  374. if (!HostAddrCmp(pIterator->HostAddr, pQElement->HostAddr)){
  375. //
  376. // ip addresses matched
  377. //
  378. if ((pIterator->dwOperation & DYNDNS_ADD_ENTRY) &&
  379. (pQElement->dwOperation & DYNDNS_DELETE_ENTRY)) {
  380. if ( pIterator->pszName &&
  381. pQElement->pszName &&
  382. !wcsicmp_ThatWorks( pIterator->pszName,
  383. pQElement->pszName ) )
  384. {
  385. //
  386. // blow away earlier entry entirely
  387. //
  388. DeleteListEntry(pQueue, &pIterator);
  389. fDelThisTime = TRUE;
  390. }
  391. //
  392. // if names are not the same do nothing.
  393. // Issue: Will we hit this code at all? Put
  394. // soft ASSERTS in this.
  395. //
  396. }
  397. else if ((pIterator->dwOperation & DYNDNS_DELETE_ENTRY) &&
  398. (pQElement->dwOperation & DYNDNS_ADD_ENTRY)) {
  399. if ( pIterator->pszName &&
  400. pQElement->pszName &&
  401. !wcsicmp_ThatWorks( pIterator->pszName,
  402. pQElement->pszName ) )
  403. {
  404. //
  405. // blow away earlier entry entirely
  406. //
  407. DeleteListEntry(pQueue, &pIterator);
  408. fDelThisTime = TRUE;
  409. } else {
  410. //
  411. // replace iterator element with just the forward
  412. // delete
  413. if (!pIterator->fDoForward) {
  414. //
  415. // there is no forward that is requested
  416. // blow away this entry
  417. //
  418. DeleteListEntry(pQueue, &pIterator);
  419. fDelThisTime = TRUE;
  420. } else {
  421. //
  422. // if you want to do a forward. Then just do
  423. // the forward. Ignore reverses
  424. //
  425. pIterator ->fDoForwardOnly = TRUE;
  426. }
  427. }
  428. }
  429. else if ((pIterator->dwOperation & DYNDNS_ADD_ENTRY) &&
  430. (pQElement->dwOperation & DYNDNS_ADD_ENTRY)) {
  431. // replace the old entry with a forward delete.
  432. // this is an error. Need to replace earlier add
  433. // forward with an explicit Delete
  434. //
  435. if ( pIterator->pszName &&
  436. pQElement->pszName &&
  437. !wcsicmp_ThatWorks( pIterator->pszName,
  438. pQElement->pszName ) )
  439. {
  440. DeleteListEntry(pQueue, &pIterator);
  441. fDelThisTime = TRUE;
  442. } else {
  443. //
  444. // Log entries into this area. This should
  445. // be a soft assert if you are here
  446. // Names dont match, so you need to replace earlier
  447. // add with a delete forward only
  448. //
  449. if (!pIterator->fDoForward) {
  450. //
  451. // there is no forward add requested
  452. // blow away this entry
  453. //
  454. DeleteListEntry(pQueue, &pIterator);
  455. fDelThisTime = TRUE;
  456. } else {
  457. //
  458. // if you want to *explicitly* delete old
  459. // forward and then add the new forward/reverse.
  460. //
  461. pIterator ->fDoForwardOnly = TRUE;
  462. pIterator ->dwOperation &=
  463. ~(DYNDNS_ADD_ENTRY) & DYNDNS_DELETE_ENTRY;
  464. }
  465. }
  466. }
  467. else if ((pIterator->dwOperation & DYNDNS_DELETE_ENTRY) &&
  468. (pQElement->dwOperation & DYNDNS_DELETE_ENTRY)) {
  469. //
  470. // if both are deletes.
  471. //
  472. if ( pIterator->pszName &&
  473. pQElement->pszName &&
  474. !wcsicmp_ThatWorks( pIterator->pszName,
  475. pQElement->pszName ) )
  476. {
  477. //
  478. // blow away earlier entry. An optimization
  479. //
  480. DeleteListEntry(pQueue, &pIterator);
  481. fDelThisTime = TRUE;
  482. }
  483. //
  484. // if names dont match, do nothing. (To paraphrase,
  485. // the DNS Server needs to do both!!
  486. //
  487. }
  488. }
  489. if (pIterator && !fDelThisTime) {
  490. // pIterator may have changed because of blowing away an entry
  491. pIterator = pIterator->pFLink;
  492. }
  493. }
  494. }
  495. */
  496. DWORD
  497. ProcessQDependencies(
  498. PDYNDNSQUEUE pTimedOutQueue,
  499. PQELEMENT pQElement
  500. )
  501. /*
  502. This function returns the retry time of the last element that you
  503. needed to blow out, 0 if no element needed to be removed
  504. */
  505. {
  506. PQELEMENT pIterator = pTimedOutQueue->pTail;
  507. DWORD dwRetryTime = 0;
  508. BOOL fDelThisTime = FALSE;
  509. while (pIterator) {
  510. fDelThisTime = FALSE;
  511. if (!pIterator->fDoForwardOnly && !pQElement->fDoForwardOnly){
  512. //
  513. // both elements are not forward only, check on ip addresses
  514. //
  515. if (!HostAddrCmp(pIterator->HostAddr, pQElement->HostAddr)){
  516. //
  517. // ip addresses matched
  518. //
  519. if ((pIterator->dwOperation & DYNDNS_ADD_ENTRY) &&
  520. (pQElement->dwOperation & DYNDNS_DELETE_ENTRY)) {
  521. if ( pIterator->pszName &&
  522. pQElement->pszName &&
  523. !wcsicmp_ThatWorks( pIterator->pszName,
  524. pQElement->pszName ) )
  525. {
  526. //
  527. // blow away earlier entry entirely
  528. //
  529. dwRetryTime = pIterator -> dwRetryTime;
  530. DeleteListEntry(pTimedOutQueue, &pIterator);
  531. fDelThisTime = TRUE;
  532. }
  533. //
  534. // if names are not the same do nothing.
  535. //
  536. // Issue: Will we hit this code at all? Put
  537. // soft ASSERTS in this.
  538. //
  539. }else if ((pIterator->dwOperation & DYNDNS_DELETE_ENTRY) &&
  540. (pQElement->dwOperation & DYNDNS_ADD_ENTRY)) {
  541. if ( pIterator->pszName &&
  542. pQElement->pszName &&
  543. !wcsicmp_ThatWorks( pIterator->pszName,
  544. pQElement->pszName ) )
  545. {
  546. //
  547. // blow away earlier entry entirely
  548. //
  549. dwRetryTime = pIterator -> dwRetryTime;
  550. DeleteListEntry(pTimedOutQueue, &pIterator);
  551. fDelThisTime = TRUE;
  552. } else {
  553. // replace iterator element with just the forward
  554. dwRetryTime = pIterator -> dwRetryTime;
  555. pIterator -> fDoForwardOnly = TRUE;
  556. }
  557. }else if ((pIterator->dwOperation & DYNDNS_ADD_ENTRY) &&
  558. (pQElement->dwOperation & DYNDNS_ADD_ENTRY)) {
  559. // replace the old entry with a forward delete.
  560. // this is an error. Need to replace earlier add
  561. // forward with an explicit Delete
  562. //
  563. if ( pIterator->pszName &&
  564. pQElement->pszName &&
  565. !wcsicmp_ThatWorks( pIterator->pszName,
  566. pQElement->pszName ) )
  567. {
  568. DeleteListEntry(pTimedOutQueue, &pIterator);
  569. fDelThisTime = TRUE;
  570. } else {
  571. //
  572. // Log entries into this area. This should
  573. // be a soft assert if you are here
  574. // Names dont match, so you need to replace earlier
  575. // add with a delete forward only
  576. //
  577. if (!pIterator->fDoForward) {
  578. //
  579. // there is no forward add requested
  580. // blow away this entry
  581. //
  582. DeleteListEntry(pTimedOutQueue, &pIterator);
  583. fDelThisTime = TRUE;
  584. } else {
  585. //
  586. // if you want to *explicitly* delete old
  587. // forward and then add the new forward/reverse.
  588. //
  589. pIterator ->fDoForwardOnly = TRUE;
  590. pIterator ->dwOperation &=
  591. ~(DYNDNS_ADD_ENTRY) & DYNDNS_DELETE_ENTRY;
  592. }
  593. }
  594. }
  595. else if ((pIterator->dwOperation & DYNDNS_DELETE_ENTRY) &&
  596. (pQElement->dwOperation & DYNDNS_DELETE_ENTRY)) {
  597. //
  598. // if both are deletes.
  599. //
  600. if ( pIterator->pszName &&
  601. pQElement->pszName &&
  602. !wcsicmp_ThatWorks( pIterator->pszName,
  603. pQElement->pszName ) )
  604. {
  605. //
  606. // blow away earlier entry. An optimization
  607. //
  608. DeleteListEntry(pTimedOutQueue, &pIterator);
  609. fDelThisTime = TRUE;
  610. }
  611. //
  612. // if names dont match, do nothing. (To paraphrase,
  613. // the DNS Server needs to do both!!
  614. //
  615. }
  616. }
  617. } else if (pIterator->fDoForwardOnly) {
  618. if ( pIterator->pszName &&
  619. pQElement->pszName &&
  620. !wcsicmp_ThatWorks( pIterator->pszName,
  621. pQElement->pszName ) )
  622. {
  623. if ((pIterator->dwOperation & DYNDNS_ADD_ENTRY) &&
  624. (pQElement->dwOperation & DYNDNS_ADD_ENTRY)) {
  625. if (!HostAddrCmp(pIterator->HostAddr, pQElement->HostAddr))
  626. {
  627. //
  628. // optimization blow away earlier entry
  629. //
  630. DeleteListEntry(pTimedOutQueue, &pIterator);
  631. fDelThisTime = TRUE;
  632. }
  633. //
  634. // if names dont match, do nothing
  635. //
  636. }
  637. else if ((pIterator->dwOperation & DYNDNS_ADD_ENTRY) &&
  638. (pQElement->dwOperation & DYNDNS_DELETE_ENTRY)) {
  639. if (!HostAddrCmp(pIterator->HostAddr, pQElement->HostAddr)){
  640. //
  641. // blow away earlier entry
  642. //
  643. dwRetryTime = pIterator -> dwRetryTime;
  644. DeleteListEntry(pTimedOutQueue, &pIterator);
  645. fDelThisTime = TRUE;
  646. }
  647. //
  648. // if addresses dont match, do nothing
  649. //
  650. } else if ((pIterator->dwOperation & DYNDNS_DELETE_ENTRY) &&
  651. (pQElement->dwOperation & DYNDNS_ADD_ENTRY)) {
  652. if (!HostAddrCmp(pIterator->HostAddr, pQElement->HostAddr)){
  653. //
  654. // blow away earlier entry
  655. //
  656. dwRetryTime = pIterator -> dwRetryTime;
  657. DeleteListEntry(pTimedOutQueue, &pIterator);
  658. fDelThisTime = TRUE;
  659. }
  660. //
  661. // if addresses dont match, then dont do anything
  662. //
  663. } else {
  664. // both are deletes
  665. // do nothing here. i.e. DNS Server does both
  666. }
  667. }
  668. } else if (!pIterator->fDoForwardOnly && pQElement->fDoForwardOnly) {
  669. //
  670. // new element is forward only
  671. //
  672. //
  673. // if both elements are forwards, we cannot whack anything
  674. // out in any case, do nothing
  675. //
  676. }
  677. if (!fDelThisTime && pIterator){
  678. pIterator = pIterator ->pFLink;
  679. }
  680. }
  681. return (dwRetryTime);
  682. }
  683. VOID
  684. DeleteListEntry(
  685. PDYNDNSQUEUE pQueue,
  686. PQELEMENT* ppIterator
  687. )
  688. {
  689. PQELEMENT pPrev, pNext;
  690. PQELEMENT pIterator = *ppIterator;
  691. DHCP_CALLBACK_FN pfnDhcpCallBack = NULL;
  692. PVOID pvData = NULL;
  693. pPrev = pIterator ->pBLink;
  694. pNext = pIterator ->pFLink;
  695. if (pPrev) {
  696. pPrev->pFLink = pNext;
  697. }
  698. if (pNext) {
  699. pNext ->pBLink = pPrev;
  700. }
  701. if (pIterator == pQueue ->pHead) {
  702. pQueue->pHead = pIterator ->pBLink;
  703. }
  704. if (pIterator == pQueue ->pTail) {
  705. pQueue->pTail = pIterator ->pFLink;
  706. }
  707. *ppIterator = pIterator ->pFLink;
  708. pfnDhcpCallBack = pIterator->pfnDhcpCallBack;
  709. pvData = pIterator->pvData;
  710. // blow away entry
  711. if ( pIterator -> pszName )
  712. QUEUE_FREE_HEAP( pIterator->pszName );
  713. if ( pIterator -> DnsServerList )
  714. QUEUE_FREE_HEAP( pIterator->DnsServerList );
  715. if ( pfnDhcpCallBack )
  716. (*pfnDhcpCallBack)(DNSDHCP_SUPERCEDED, pvData);
  717. QUEUE_FREE_HEAP( pIterator );
  718. }