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.

1112 lines
21 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. rrcopy.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. Copy resource record routines.
  8. Author:
  9. Jim Gilroy (jamesg) February, 1997
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. PDNS_RECORD
  14. ARecordCopy(
  15. IN PDNS_RECORD pRR,
  16. IN DNS_CHARSET CharSetIn,
  17. IN DNS_CHARSET CharSetOut
  18. )
  19. /*++
  20. Routine Description:
  21. Copy A record data from packet.
  22. Arguments:
  23. pRR - RR to copy
  24. Return Value:
  25. Ptr to new record if successful.
  26. NULL on failure.
  27. --*/
  28. {
  29. PDNS_RECORD precord;
  30. precord = Dns_AllocateRecord( sizeof(IP_ADDRESS) );
  31. if ( !precord )
  32. {
  33. return NULL;
  34. }
  35. precord->Data.A.IpAddress = pRR->Data.A.IpAddress;
  36. return precord;
  37. }
  38. PDNS_RECORD
  39. PtrRecordCopy(
  40. IN PDNS_RECORD pRR,
  41. IN DNS_CHARSET CharSetIn,
  42. IN DNS_CHARSET CharSetOut
  43. )
  44. /*++
  45. Routine Description:
  46. Copy PTR compatible record.
  47. Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
  48. Arguments:
  49. pRR - RR to copy
  50. Return Value:
  51. Ptr to new record if successful.
  52. NULL on failure.
  53. --*/
  54. {
  55. PDNS_RECORD precord;
  56. precord = Dns_AllocateRecord( sizeof( DNS_PTR_DATA ) );
  57. if ( !precord )
  58. {
  59. return NULL;
  60. }
  61. precord->Data.PTR.pNameHost = Dns_NameCopyAllocate(
  62. pRR->Data.PTR.pNameHost,
  63. 0, // length unknown
  64. CharSetIn,
  65. CharSetOut
  66. );
  67. if ( ! precord->Data.PTR.pNameHost )
  68. {
  69. FREE_HEAP( precord );
  70. return NULL;
  71. }
  72. FLAG_FreeData( precord ) = TRUE;
  73. return precord;
  74. }
  75. PDNS_RECORD
  76. SoaRecordCopy(
  77. IN PDNS_RECORD pRR,
  78. IN DNS_CHARSET CharSetIn,
  79. IN DNS_CHARSET CharSetOut
  80. )
  81. /*++
  82. Routine Description:
  83. Copy SOA record.
  84. Arguments:
  85. pRR - RR to copy
  86. Return Value:
  87. Ptr to new record if successful.
  88. NULL on failure.
  89. --*/
  90. {
  91. PDNS_RECORD precord;
  92. LPSTR pname;
  93. precord = Dns_AllocateRecord( sizeof( DNS_SOA_DATA ) );
  94. if ( !precord )
  95. {
  96. return NULL;
  97. }
  98. //
  99. // copy integer data
  100. //
  101. memcpy(
  102. & precord->Data.SOA.dwSerialNo,
  103. & pRR->Data.SOA.dwSerialNo,
  104. SIZEOF_SOA_FIXED_DATA );
  105. //
  106. // create copy of primary and admin
  107. //
  108. pname = Dns_NameCopyAllocate(
  109. pRR->Data.SOA.pNamePrimaryServer,
  110. 0, // length unknown
  111. CharSetIn,
  112. CharSetOut
  113. );
  114. if ( !pname )
  115. {
  116. FREE_HEAP( precord );
  117. return NULL;
  118. }
  119. precord->Data.SOA.pNamePrimaryServer = pname;
  120. pname = Dns_NameCopyAllocate(
  121. pRR->Data.SOA.pNameAdministrator,
  122. 0, // length unknown
  123. CharSetIn,
  124. CharSetOut
  125. );
  126. if ( !pname )
  127. {
  128. FREE_HEAP( precord->Data.SOA.pNamePrimaryServer );
  129. FREE_HEAP( precord );
  130. return NULL;
  131. }
  132. precord->Data.SOA.pNameAdministrator = pname;
  133. FLAG_FreeData( precord ) = TRUE;
  134. return precord;
  135. }
  136. PDNS_RECORD
  137. MinfoRecordCopy(
  138. IN PDNS_RECORD pRR,
  139. IN DNS_CHARSET CharSetIn,
  140. IN DNS_CHARSET CharSetOut
  141. )
  142. /*++
  143. Routine Description:
  144. Copy MINFO and RP records from wire.
  145. Arguments:
  146. pRR - RR to copy
  147. Return Value:
  148. Ptr to new record if successful.
  149. NULL on failure.
  150. --*/
  151. {
  152. PDNS_RECORD precord;
  153. LPSTR pname;
  154. precord = Dns_AllocateRecord( sizeof( DNS_MINFO_DATA ) );
  155. if ( !precord )
  156. {
  157. return NULL;
  158. }
  159. //
  160. // create copy of name fields
  161. //
  162. pname = Dns_NameCopyAllocate(
  163. pRR->Data.MINFO.pNameMailbox,
  164. 0, // length unknown
  165. CharSetIn,
  166. CharSetOut
  167. );
  168. if ( !pname )
  169. {
  170. FREE_HEAP( precord );
  171. return NULL;
  172. }
  173. precord->Data.MINFO.pNameMailbox = pname;
  174. pname = Dns_NameCopyAllocate(
  175. pRR->Data.MINFO.pNameErrorsMailbox,
  176. 0, // length unknown
  177. CharSetIn,
  178. CharSetOut
  179. );
  180. if ( !pname )
  181. {
  182. FREE_HEAP( precord->Data.MINFO.pNameMailbox );
  183. FREE_HEAP( precord );
  184. return NULL;
  185. }
  186. precord->Data.MINFO.pNameErrorsMailbox = pname;
  187. FLAG_FreeData( precord ) = TRUE;
  188. return precord;
  189. }
  190. PDNS_RECORD
  191. MxRecordCopy(
  192. IN PDNS_RECORD pRR,
  193. IN DNS_CHARSET CharSetIn,
  194. IN DNS_CHARSET CharSetOut
  195. )
  196. /*++
  197. Routine Description:
  198. Copy MX compatible record from wire.
  199. Includes: MX, RT, AFSDB
  200. Arguments:
  201. pRR - RR to copy
  202. Return Value:
  203. Ptr to new record if successful.
  204. NULL on failure.
  205. --*/
  206. {
  207. PDNS_RECORD precord;
  208. PCHAR pname;
  209. precord = Dns_AllocateRecord( sizeof( DNS_MX_DATA ) );
  210. if ( !precord )
  211. {
  212. return NULL;
  213. }
  214. // MX preference value
  215. // RT preference
  216. // AFSDB subtype
  217. precord->Data.MX.wPreference = pRR->Data.MX.wPreference;
  218. // MX exchange
  219. // RT exchange
  220. // AFSDB hostname
  221. // - name immediately follows MX data struct
  222. pname = Dns_NameCopyAllocate(
  223. pRR->Data.MX.pNameExchange,
  224. 0, // length unknown
  225. CharSetIn,
  226. CharSetOut
  227. );
  228. if ( !pname )
  229. {
  230. FREE_HEAP( precord );
  231. return NULL;
  232. }
  233. precord->Data.MX.pNameExchange = pname;
  234. FLAG_FreeData( precord ) = TRUE;
  235. return precord;
  236. }
  237. PDNS_RECORD
  238. TxtRecordCopy(
  239. IN PDNS_RECORD pRR,
  240. IN DNS_CHARSET CharSetIn,
  241. IN DNS_CHARSET CharSetOut
  242. )
  243. /*++
  244. Routine Description:
  245. Copy TXT compatible records.
  246. Includes: TXT, X25, HINFO, ISDN
  247. Arguments:
  248. pRR - RR to copy
  249. Return Value:
  250. Ptr to new record if successful.
  251. NULL on failure.
  252. --*/
  253. {
  254. PDNS_RECORD precord;
  255. WORD bufLength = sizeof( DNS_TXT_DATA );
  256. INT count = pRR->Data.TXT.dwStringCount;
  257. LPSTR * ppstringIn;
  258. LPSTR * ppstringNew;
  259. LPSTR pstring;
  260. bufLength += (WORD)(sizeof(LPSTR) * count);
  261. precord = Dns_AllocateRecord( bufLength );
  262. if ( !precord )
  263. {
  264. return NULL;
  265. }
  266. precord->Data.TXT.dwStringCount = 0;
  267. //
  268. // copy each string
  269. // - first string written immediately after string ptr list
  270. // - each string written immediately after previous
  271. //
  272. ppstringIn = (LPSTR *) pRR->Data.TXT.pStringArray;
  273. ppstringNew = (LPSTR *) precord->Data.TXT.pStringArray;
  274. FLAG_FreeData( precord ) = TRUE;
  275. while ( count-- )
  276. {
  277. pstring = Dns_StringCopyAllocate(
  278. *ppstringIn,
  279. 0, // length unknown
  280. CharSetIn,
  281. CharSetOut
  282. );
  283. if ( ! pstring )
  284. {
  285. Dns_RecordFree( precord );
  286. return NULL;
  287. }
  288. *ppstringNew = pstring;
  289. precord->Data.TXT.dwStringCount += 1;
  290. ppstringIn++;
  291. ppstringNew++;
  292. }
  293. return precord;
  294. }
  295. PDNS_RECORD
  296. FlatRecordCopy(
  297. IN PDNS_RECORD pRR,
  298. IN DNS_CHARSET CharSetIn,
  299. IN DNS_CHARSET CharSetOut
  300. )
  301. /*++
  302. Routine Description:
  303. Copy flat data compatible record.
  304. Includes: AAAA
  305. Arguments:
  306. pRR - RR to copy
  307. Return Value:
  308. Ptr to new record if successful.
  309. NULL on failure.
  310. --*/
  311. {
  312. PDNS_RECORD precord;
  313. //
  314. // allocate given datalength
  315. //
  316. precord = Dns_AllocateRecord( pRR->wDataLength );
  317. if ( !precord )
  318. {
  319. return( NULL );
  320. }
  321. //
  322. // flat copy of data
  323. //
  324. memcpy(
  325. & precord->Data,
  326. & pRR->Data,
  327. pRR->wDataLength );
  328. return( precord );
  329. }
  330. PDNS_RECORD
  331. SrvRecordCopy(
  332. IN PDNS_RECORD pRR,
  333. IN DNS_CHARSET CharSetIn,
  334. IN DNS_CHARSET CharSetOut
  335. )
  336. /*++
  337. Routine Description:
  338. Copy SRV compatible record from wire.
  339. Includes: SRV, RT, AFSDB
  340. Arguments:
  341. pRR - RR to copy
  342. Return Value:
  343. Ptr to new record if successful.
  344. NULL on failure.
  345. --*/
  346. {
  347. PDNS_RECORD precord;
  348. PCHAR pname;
  349. precord = Dns_AllocateRecord( sizeof( DNS_SRV_DATA ) );
  350. if ( !precord )
  351. {
  352. return NULL;
  353. }
  354. // copy integer data
  355. precord->Data.SRV.wPriority = pRR->Data.SRV.wPriority;
  356. precord->Data.SRV.wWeight = pRR->Data.SRV.wWeight;
  357. precord->Data.SRV.wPort = pRR->Data.SRV.wPort;
  358. // copy target name
  359. pname = Dns_NameCopyAllocate(
  360. pRR->Data.SRV.pNameTarget,
  361. 0, // length unknown
  362. CharSetIn,
  363. CharSetOut
  364. );
  365. if ( !pname )
  366. {
  367. FREE_HEAP( precord );
  368. return NULL;
  369. }
  370. precord->Data.SRV.pNameTarget = pname;
  371. SET_FREE_DATA( precord );
  372. return precord;
  373. }
  374. PDNS_RECORD
  375. AtmaRecordCopy(
  376. IN PDNS_RECORD pRR,
  377. IN DNS_CHARSET CharSetIn,
  378. IN DNS_CHARSET CharSetOut
  379. )
  380. /*++
  381. Routine Description:
  382. Copy Atma compatible record from wire.
  383. Includes:
  384. Arguments:
  385. pRR - RR to copy
  386. Return Value:
  387. Ptr to new record if successful.
  388. NULL on failure.
  389. --*/
  390. {
  391. PDNS_RECORD precord;
  392. WORD bufLength;
  393. //
  394. // determine required buffer length and allocate
  395. //
  396. bufLength = sizeof(DNS_ATMA_DATA) + DNS_ATMA_MAX_ADDR_LENGTH ;
  397. precord = Dns_AllocateRecord( bufLength );
  398. if ( !precord )
  399. {
  400. return( NULL );
  401. }
  402. // copy integer data
  403. precord->Data.ATMA.AddressType = pRR->Data.ATMA.AddressType;
  404. if ( precord->Data.ATMA.AddressType == DNS_ATMA_FORMAT_E164 )
  405. {
  406. precord->wDataLength = (WORD) strlen(pRR->Data.ATMA.Address);
  407. if ( precord->wDataLength > DNS_ATMA_MAX_ADDR_LENGTH )
  408. {
  409. precord->wDataLength = DNS_ATMA_MAX_ADDR_LENGTH;
  410. }
  411. strncpy(
  412. precord->Data.ATMA.Address,
  413. pRR->Data.ATMA.Address,
  414. precord->wDataLength );
  415. }
  416. else
  417. {
  418. precord->wDataLength = DNS_ATMA_MAX_ADDR_LENGTH;
  419. memcpy(
  420. precord->Data.ATMA.Address,
  421. pRR->Data.ATMA.Address,
  422. precord->wDataLength );
  423. }
  424. return( precord );
  425. }
  426. //
  427. // RR copy jump table
  428. //
  429. RR_COPY_FUNCTION RRCopyTable[] =
  430. {
  431. NULL, // ZERO
  432. ARecordCopy, // A
  433. PtrRecordCopy, // NS
  434. PtrRecordCopy, // MD
  435. PtrRecordCopy, // MF
  436. PtrRecordCopy, // CNAME
  437. SoaRecordCopy, // SOA
  438. PtrRecordCopy, // MB
  439. PtrRecordCopy, // MG
  440. PtrRecordCopy, // MR
  441. NULL, // NULL
  442. NULL, //WksRecordCopy, // WKS
  443. PtrRecordCopy, // PTR
  444. TxtRecordCopy, // HINFO
  445. MinfoRecordCopy, // MINFO
  446. MxRecordCopy, // MX
  447. TxtRecordCopy, // TXT
  448. MinfoRecordCopy, // RP
  449. MxRecordCopy, // AFSDB
  450. TxtRecordCopy, // X25
  451. TxtRecordCopy, // ISDN
  452. MxRecordCopy, // RT
  453. NULL, // NSAP
  454. NULL, // NSAPPTR
  455. NULL, // SIG
  456. NULL, // KEY
  457. NULL, // PX
  458. NULL, // GPOS
  459. FlatRecordCopy, // AAAA
  460. NULL, // LOC
  461. NULL, // NXT
  462. NULL, // EID
  463. NULL, // NIMLOC
  464. SrvRecordCopy, // SRV
  465. AtmaRecordCopy, // ATMA
  466. NULL, // NAPTR
  467. NULL, // KX
  468. NULL, // CERT
  469. NULL, // A6
  470. NULL, // DNAME
  471. NULL, // SINK
  472. NULL, // OPT
  473. NULL, // 42
  474. NULL, // 43
  475. NULL, // 44
  476. NULL, // 45
  477. NULL, // 46
  478. NULL, // 47
  479. NULL, // 48
  480. //
  481. // NOTE: last type indexed by type ID MUST be set
  482. // as MAX_SELF_INDEXED_TYPE #define in record.h
  483. // (see note above in record info table)
  484. //
  485. // Pseudo record types
  486. //
  487. NULL, // TKEY
  488. NULL, // TSIG
  489. //
  490. // MS only types
  491. //
  492. FlatRecordCopy, // WINS
  493. NULL, // WINSR
  494. };
  495. //
  496. // Generic copy functions
  497. //
  498. PDNS_RECORD
  499. privateRecordCopy(
  500. IN PDNS_RECORD pRecord,
  501. IN PDNS_RECORD pPrevIn,
  502. IN PDNS_RECORD pPrevCopy,
  503. IN DNS_CHARSET CharSetIn,
  504. IN DNS_CHARSET CharSetOut
  505. )
  506. /*++
  507. Routine Description:
  508. Copy record to as member of record set.
  509. The previous records allow suppression of owner name copy when copying
  510. RR set.
  511. Arguments:
  512. pRecord - record to copy
  513. pPrevIn - previous incoming record copied
  514. pPrevCopy - copy of pPrevIn in new set
  515. CharSetIn - input record character set; OPTIONAL
  516. if zero, pRecord must have CharSet;
  517. if non-zero, pRecord must have zero or matching CharSet;
  518. allow this to be specified independently of pRecord, to handle
  519. conversion of user supplied records, which we do not want to
  520. modify
  521. CharSetOut - desired record character set
  522. Return Value:
  523. Ptr to copy of record in desired character set.
  524. NULL on error.
  525. --*/
  526. {
  527. PDNS_RECORD prr;
  528. WORD index;
  529. DNS_CHARSET recordCharSet;
  530. DNSDBG( TRACE, ( "privateRecordCopy( %p )\n", pRecord ));
  531. //
  532. // input character set
  533. // allow specification of input character set to handle case
  534. // of user created records, but if input record has a set
  535. // then it's assumed to be valid
  536. // so validity check:
  537. // - CharSetIn == 0 => use record's != 0 set
  538. // - record's set == 0 => use CharSetIn != 0
  539. // - CharSetIn == record's set
  540. //
  541. recordCharSet = RECORD_CHARSET( pRecord );
  542. if ( recordCharSet )
  543. {
  544. ASSERT( CharSetIn == 0 || CharSetIn == recordCharSet );
  545. CharSetIn = recordCharSet;
  546. }
  547. else // record has no charset
  548. {
  549. if ( CharSetIn == 0 )
  550. {
  551. ASSERT( FALSE );
  552. goto Failed;
  553. }
  554. }
  555. //
  556. // copy record data
  557. //
  558. if ( pRecord->wDataLength != 0 )
  559. {
  560. index = INDEX_FOR_TYPE( pRecord->wType );
  561. DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
  562. if ( !index || !RRCopyTable[ index ] )
  563. {
  564. DNS_PRINT((
  565. "WARNING: No copy routine for type = %d\n"
  566. "\tdoing flat copy of record at %p\n",
  567. pRecord->wType,
  568. pRecord ));
  569. prr = FlatRecordCopy(
  570. pRecord,
  571. CharSetIn,
  572. CharSetOut );
  573. }
  574. else
  575. {
  576. prr = RRCopyTable[ index ](
  577. pRecord,
  578. CharSetIn,
  579. CharSetOut );
  580. }
  581. }
  582. else // no data record
  583. {
  584. prr = FlatRecordCopy(
  585. pRecord,
  586. CharSetIn,
  587. CharSetOut );
  588. }
  589. if ( !prr )
  590. {
  591. goto Failed;
  592. }
  593. //
  594. // copy record structure fields
  595. // - type
  596. // - TTL
  597. // - flags
  598. //
  599. prr->dwTtl = pRecord->dwTtl;
  600. prr->wType = pRecord->wType;
  601. prr->Flags.S.Section = pRecord->Flags.S.Section;
  602. prr->Flags.S.Delete = pRecord->Flags.S.Delete;
  603. prr->Flags.S.CharSet = CharSetOut;
  604. //
  605. // copy name
  606. //
  607. if ( pRecord->pName )
  608. {
  609. //
  610. // - if incoming name has FreeOwner set, then always copy
  611. // as never know when incoming set will be tossed
  612. //
  613. // - then check if incoming name same as previous incoming
  614. // name in which case we can use previous copied name
  615. //
  616. // - otherwise full copy of name
  617. //
  618. if ( !FLAG_FreeOwner( pRecord ) &&
  619. pPrevIn && pPrevCopy &&
  620. pRecord->pName == pPrevIn->pName )
  621. {
  622. prr->pName = pPrevCopy->pName;
  623. }
  624. else
  625. {
  626. prr->pName = Dns_NameCopyAllocate(
  627. pRecord->pName,
  628. 0, // unknown length
  629. CharSetIn,
  630. CharSetOut
  631. );
  632. if ( !prr->pName )
  633. {
  634. FREE_HEAP( prr );
  635. goto Failed;
  636. }
  637. FLAG_FreeOwner( prr ) = TRUE;
  638. }
  639. }
  640. DNSDBG( TRACE, (
  641. "Leaving privateRecordCopy(%p) = %p.\n",
  642. pRecord,
  643. prr ));
  644. return( prr );
  645. Failed:
  646. DNSDBG( TRACE, (
  647. "privateRecordCopy(%p) failed\n",
  648. pRecord ));
  649. return( NULL );
  650. }
  651. PDNS_RECORD
  652. WINAPI
  653. Dns_RecordCopyEx(
  654. IN PDNS_RECORD pRecord,
  655. IN DNS_CHARSET CharSetIn,
  656. IN DNS_CHARSET CharSetOut
  657. )
  658. /*++
  659. Routine Description:
  660. Copy record.
  661. Arguments:
  662. pRecord - record to copy
  663. CharSetIn - incoming record's character set
  664. CharSetOut -- char set for resulting record
  665. Return Value:
  666. Ptr to copy of record in desired character set.
  667. NULL on error.
  668. --*/
  669. {
  670. DNSDBG( TRACE, ( "Dns_RecordCopyEx( %p )\n", pRecord ));
  671. //
  672. // call private copy routine
  673. // - set optional ptrs to cause full owner name copy
  674. //
  675. return privateRecordCopy(
  676. pRecord,
  677. NULL,
  678. NULL,
  679. CharSetIn,
  680. CharSetOut );
  681. }
  682. PDNS_RECORD
  683. WINAPI
  684. Dns_RecordCopy_W(
  685. IN PDNS_RECORD pRecord
  686. )
  687. /*++
  688. Routine Description:
  689. Copy record.
  690. Arguments:
  691. pRecord - unicode record to copy to unicode
  692. Return Value:
  693. Ptr to copy of record in desired character set.
  694. NULL on error.
  695. --*/
  696. {
  697. DNSDBG( TRACE, ( "Dns_RecordCopy( %p )\n", pRecord ));
  698. //
  699. // call private copy routine
  700. // - set optional ptrs to cause full owner name copy
  701. //
  702. return privateRecordCopy(
  703. pRecord,
  704. NULL,
  705. NULL,
  706. DnsCharSetUnicode,
  707. DnsCharSetUnicode );
  708. }
  709. PDNS_RECORD
  710. WINAPI
  711. Dns_RecordCopy_A(
  712. IN PDNS_RECORD pRecord
  713. )
  714. /*++
  715. Routine Description:
  716. Copy record.
  717. Arguments:
  718. pRecord - ANSI record to copy to ANSI
  719. Return Value:
  720. Ptr to copy of record in desired character set.
  721. NULL on error.
  722. --*/
  723. {
  724. DNSDBG( TRACE, ( "Dns_RecordCopy( %p )\n", pRecord ));
  725. //
  726. // call private copy routine
  727. // - set optional ptrs to cause full owner name copy
  728. //
  729. return privateRecordCopy(
  730. pRecord,
  731. NULL,
  732. NULL,
  733. DnsCharSetAnsi,
  734. DnsCharSetAnsi );
  735. }
  736. //
  737. // Record set copy
  738. //
  739. PDNS_RECORD
  740. Dns_RecordSetCopyEx(
  741. IN PDNS_RECORD pRR,
  742. IN DNS_CHARSET CharSetIn,
  743. IN DNS_CHARSET CharSetOut
  744. )
  745. /*++
  746. Routine Description:
  747. Copy record set, converting to UTF8 if necessary.
  748. Arguments:
  749. pRR - incoming record set
  750. CharSetIn - incoming record's character set
  751. CharSetOut -- char set for resulting record
  752. Return Value:
  753. Ptr to new record set, if successful.
  754. NULL on error.
  755. --*/
  756. {
  757. return Dns_RecordListCopyEx(
  758. pRR,
  759. 0, // no screening flags
  760. CharSetIn,
  761. CharSetOut
  762. );
  763. }
  764. PDNS_RECORD
  765. Dns_RecordListCopyEx(
  766. IN PDNS_RECORD pRR,
  767. IN DWORD ScreenFlag,
  768. IN DNS_CHARSET CharSetIn,
  769. IN DNS_CHARSET CharSetOut
  770. )
  771. /*++
  772. Routine Description:
  773. Screened copy of record set.
  774. Arguments:
  775. pRR - incoming record set
  776. ScreenFlag - flag with record screening parameters
  777. CharSetIn - incoming record's character set
  778. CharSetOut -- char set for resulting record
  779. Return Value:
  780. Ptr to new record set, if successful.
  781. NULL on error.
  782. --*/
  783. {
  784. PDNS_RECORD prr; // most recent copied
  785. PDNS_RECORD prevIn; // previous in set being copied
  786. DNS_RRSET rrset;
  787. DNSDBG( TRACE, (
  788. "Dns_RecordListCopyEx( %p, %08x, %d, %d )\n",
  789. pRR,
  790. ScreenFlag,
  791. CharSetIn,
  792. CharSetOut ));
  793. // init copy rrset
  794. DNS_RRSET_INIT( rrset );
  795. //
  796. // loop through RR set, add records to either match or diff sets
  797. //
  798. prevIn = NULL;
  799. prr = NULL;
  800. while ( pRR )
  801. {
  802. // skip copy on record not matching copy criteria
  803. if ( ScreenFlag )
  804. {
  805. if ( !Dns_ScreenRecord( pRR, ScreenFlag ) )
  806. {
  807. pRR = pRR->pNext;
  808. continue;
  809. }
  810. }
  811. prr = privateRecordCopy(
  812. pRR,
  813. prevIn,
  814. prr, // previous rr copied
  815. CharSetIn,
  816. CharSetOut
  817. );
  818. if ( prr )
  819. {
  820. DNS_RRSET_ADD( rrset, prr );
  821. prevIn = pRR;
  822. pRR = pRR->pNext;
  823. continue;
  824. }
  825. // if fail, toss entire new set
  826. Dns_RecordListFree( rrset.pFirstRR );
  827. return( NULL );
  828. }
  829. return( rrset.pFirstRR );
  830. }
  831. //
  832. // End rrcopy.c
  833. //