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.

2145 lines
43 KiB

  1. /*++
  2. Copyright (c) 2002-2002 Microsoft Corporation
  3. Module Name:
  4. sablob.c
  5. Abstract:
  6. Domain Name System (DNS) Library
  7. Sockaddr blob routines.
  8. Author:
  9. Jim Gilroy (jamesg) May 25, 2002
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. #include "ws2atm.h" // ATM address
  14. //
  15. // Max number of aliases
  16. //
  17. #define DNS_MAX_ALIAS_COUNT (8)
  18. //
  19. // Min size of sablob address buffer
  20. // - enough for one address of largest type
  21. //
  22. #define MIN_ADDR_BUF_SIZE (sizeof(ATM_ADDRESS))
  23. //
  24. // SockaddrResults utilities
  25. //
  26. BOOL
  27. SaBlob_IsSupportedAddrType(
  28. IN WORD wType
  29. )
  30. /*++
  31. Routine Description:
  32. Is this a supported address type for sablob.
  33. Arguments:
  34. wType -- type in question
  35. Return Value:
  36. TRUE if type supported
  37. FALSE otherwise
  38. --*/
  39. {
  40. return ( wType == DNS_TYPE_A ||
  41. wType == DNS_TYPE_AAAA ||
  42. wType == DNS_TYPE_ATMA );
  43. }
  44. #if 0
  45. DWORD
  46. SaBlob_WriteLocalIp4Array(
  47. IN OUT PSABLOB pBlob,
  48. OUT PCHAR pAddrBuf,
  49. IN DWORD MaxBufCount,
  50. IN PIP4_ARRAY pIpArray
  51. )
  52. /*++
  53. Routine Description:
  54. Write local IP list into sablob.
  55. Arguments:
  56. pBlob -- sablob
  57. pAddrBuf -- buffer to hold addresses
  58. MaxBufCount -- max IPs buffer can hold
  59. pIpArray -- IP4 array of local addresses
  60. Return Value:
  61. Count of addresses written
  62. --*/
  63. {
  64. DWORD count = 0;
  65. //
  66. // write array
  67. //
  68. if ( pIpArray )
  69. {
  70. count = SaBlob_WriteIp4Addrs(
  71. pBlob,
  72. pAddrBuf,
  73. MaxBufCount,
  74. pIpArray->AddrArray,
  75. pIpArray->AddrCount,
  76. TRUE // screen out zeros
  77. );
  78. }
  79. //
  80. // if no addresses written, write loopback
  81. //
  82. if ( count==0 )
  83. {
  84. pBlob->h_addr_list[0] = pAddrBuf;
  85. pBlob->h_addr_list[1] = NULL;
  86. *((IP4_ADDRESS*)pAddrBuf) = DNS_NET_ORDER_LOOPBACK;
  87. count = 1;
  88. }
  89. // count of addresses written
  90. return( count );
  91. }
  92. BOOL
  93. SaBlob_SetToSingleAddress(
  94. IN OUT PSABLOB pBlob,
  95. IN PDNS_ADDR pAddr
  96. )
  97. /*++
  98. Routine Description:
  99. Set address in sablob.
  100. Arguments:
  101. pBlob -- sablob to set to addr
  102. pAddr -- ptr to address
  103. Return Value:
  104. TRUE if address successfully copied into sablob.
  105. FALSE otherwise (no sablob, wrong length, sablob empty)
  106. --*/
  107. {
  108. PCHAR paddrSockaddrResults;
  109. //
  110. // validate
  111. // - must have sablob
  112. // - length must match
  113. //
  114. if ( !pBlob ||
  115. AddrLength != (DWORD)pBlob->h_length )
  116. {
  117. return FALSE;
  118. }
  119. //
  120. // slam address in on top of existing
  121. // - NULL 2nd addr pointer to terminate list
  122. //
  123. paddrSockaddrResults = pBlob->h_addr_list[0];
  124. if ( !paddrSockaddrResults )
  125. {
  126. return FALSE;
  127. }
  128. RtlCopyMemory(
  129. paddrSockaddrResults,
  130. pAddr,
  131. AddrLength );
  132. pBlob->h_addr_list[1] = NULL;
  133. return TRUE;
  134. }
  135. BOOL
  136. SaBlob_IsAddressInSockaddrResults(
  137. IN OUT PSABLOB pBlob,
  138. IN PCHAR pAddr,
  139. IN DWORD AddrLength,
  140. IN INT Family OPTIONAL
  141. )
  142. /*++
  143. Routine Description:
  144. Does sablob contain this address.
  145. Arguments:
  146. pBlob -- sablob to check
  147. pAddr -- ptr to address to check
  148. AddrLength -- address length
  149. Family -- address family
  150. Return Value:
  151. TRUE if address is in sablob.
  152. FALSE otherwise.
  153. --*/
  154. {
  155. BOOL freturn = FALSE;
  156. DWORD i;
  157. PCHAR paddrSockaddrResults;
  158. //
  159. // validate
  160. // - must have sablob
  161. // - must have address
  162. // - if family given, must match
  163. // - length must match
  164. //
  165. if ( !pBlob ||
  166. !pAddr ||
  167. AddrLength != (DWORD)pBlob->h_length ||
  168. ( Family && Family != pBlob->h_addrtype ) )
  169. {
  170. return freturn;
  171. }
  172. //
  173. // search for address -- if found return TRUE
  174. //
  175. i = 0;
  176. while ( paddrSockaddrResults = pBlob->h_addr_list[i++] )
  177. {
  178. freturn = RtlEqualMemory(
  179. paddrSockaddrResults,
  180. pAddr,
  181. AddrLength );
  182. if ( freturn )
  183. {
  184. break;
  185. }
  186. }
  187. return freturn;
  188. }
  189. BOOL
  190. SaBlob_IsIp4AddressInSockaddrResults(
  191. IN OUT PSABLOB pBlob,
  192. IN IP4_ADDRESS Ip4Addr
  193. )
  194. /*++
  195. Routine Description:
  196. Does sablob contain this address.
  197. Arguments:
  198. pBlob -- sablob to check
  199. pAddr -- ptr to address to check
  200. AddrLength -- address length
  201. Family -- address family
  202. Return Value:
  203. TRUE if address is in sablob.
  204. FALSE otherwise.
  205. --*/
  206. {
  207. DWORD i;
  208. PCHAR paddrSockaddrResults;
  209. //
  210. // validate
  211. // - must have sablob
  212. // - length must match
  213. //
  214. if ( !pBlob ||
  215. sizeof(IP4_ADDRESS) != (DWORD)pBlob->h_length )
  216. {
  217. return FALSE;
  218. }
  219. //
  220. // search for address -- if found return TRUE
  221. //
  222. i = 0;
  223. while ( paddrSockaddrResults = pBlob->h_addr_list[i++] )
  224. {
  225. if ( Ip4Addr == *(PIP4_ADDRESS)paddrSockaddrResults )
  226. {
  227. return TRUE;
  228. }
  229. }
  230. return FALSE;
  231. }
  232. #endif
  233. //
  234. // SaBlob routines
  235. //
  236. PSABLOB
  237. SaBlob_Create(
  238. IN DWORD AddrCount
  239. )
  240. /*++
  241. Routine Description:
  242. Create sablob, optionally creating DnsAddrArray for it.
  243. Arguments:
  244. AddrCount -- address count
  245. Return Value:
  246. Ptr to new sablob.
  247. NULL on error, GetLastError() contains error.
  248. --*/
  249. {
  250. PSABLOB pblob;
  251. DNSDBG( SABLOB, ( "SaBlob_Create( %d )\n", AddrCount ));
  252. //
  253. // allocate blob
  254. //
  255. pblob = (PSABLOB) ALLOCATE_HEAP_ZERO( sizeof(SABLOB) );
  256. if ( !pblob )
  257. {
  258. goto Failed;
  259. }
  260. //
  261. // alloc addr array
  262. //
  263. if ( AddrCount )
  264. {
  265. PDNS_ADDR_ARRAY parray = DnsAddrArray_Create( AddrCount );
  266. if ( !parray )
  267. {
  268. goto Failed;
  269. }
  270. pblob->pAddrArray = parray;
  271. }
  272. DNSDBG( SABLOB, ( "SaBlob_Create() successful.\n" ));
  273. return( pblob );
  274. Failed:
  275. SaBlob_Free( pblob );
  276. DNSDBG( SABLOB, ( "SockaddrResults Blob create failed!\n" ));
  277. SetLastError( DNS_ERROR_NO_MEMORY );
  278. return NULL;
  279. }
  280. VOID
  281. SaBlob_Free(
  282. IN OUT PSABLOB pBlob
  283. )
  284. /*++
  285. Routine Description:
  286. Free sablob blob.
  287. Arguments:
  288. pBlob -- blob to free
  289. Return Value:
  290. None
  291. --*/
  292. {
  293. DWORD i;
  294. if ( pBlob )
  295. {
  296. FREE_HEAP( pBlob->pName );
  297. // free every alias as resetting alias count is
  298. // used to ignore them
  299. //for ( i=0; i<pBlob->AliasCount; i++ )
  300. for ( i=0; i<DNS_MAX_ALIAS_COUNT; i++ )
  301. {
  302. FREE_HEAP( pBlob->AliasArray[i] );
  303. }
  304. DnsAddrArray_Free( pBlob->pAddrArray );
  305. FREE_HEAP( pBlob );
  306. }
  307. }
  308. PSABLOB
  309. SaBlob_CreateFromIp4(
  310. IN PWSTR pName,
  311. IN DWORD AddrCount,
  312. IN PIP4_ADDRESS pIpArray
  313. )
  314. /*++
  315. Routine Description:
  316. Create sablob from IP4 addresses.
  317. Use this to build from results of non-DNS queries.
  318. Specifically NBT lookup.
  319. Arguments:
  320. pName -- name for sablob
  321. AddrCount -- address count
  322. pIpArray -- array of addresses
  323. Return Value:
  324. Ptr to blob if successful.
  325. NULL on error; GetLastError() has error.
  326. --*/
  327. {
  328. DNS_STATUS status = DNS_ERROR_NO_MEMORY;
  329. PSABLOB pblob = NULL;
  330. DWORD i;
  331. DNSDBG( SABLOB, (
  332. "SaBlob_CreateFromIp4()\n"
  333. "\tpname = %S\n"
  334. "\tcount = %d\n"
  335. "\tpArray = %p\n",
  336. pName,
  337. AddrCount,
  338. pIpArray ));
  339. //
  340. // create blob
  341. //
  342. pblob = SaBlob_Create( AddrCount );
  343. if ( !pblob )
  344. {
  345. goto Done;
  346. }
  347. //
  348. // copy name
  349. //
  350. if ( pName )
  351. {
  352. PWSTR pname = Dns_CreateStringCopy_W( pName );
  353. if ( !pname )
  354. {
  355. status = DNS_ERROR_NO_MEMORY;
  356. goto Done;
  357. }
  358. pblob->pName = pname;
  359. }
  360. //
  361. // copy addresses
  362. //
  363. for ( i=0; i<AddrCount; i++ )
  364. {
  365. DnsAddrArray_AddIp4(
  366. pblob->pAddrArray,
  367. pIpArray[ i ],
  368. DNSADDR_MATCH_IP
  369. );
  370. }
  371. status = NO_ERROR;
  372. IF_DNSDBG( SABLOB )
  373. {
  374. DnsDbg_SaBlob(
  375. "Leaving SaBlob_CreateFromIp4():",
  376. pblob );
  377. }
  378. Done:
  379. if ( status != NO_ERROR )
  380. {
  381. SaBlob_Free( pblob );
  382. pblob = NULL;
  383. SetLastError( status );
  384. }
  385. DNSDBG( SABLOB, (
  386. "Leave SaBlob_CreateFromIp4() => status = %d\n",
  387. status ));
  388. return( pblob );
  389. }
  390. VOID
  391. SaBlob_AttachHostent(
  392. IN OUT PSABLOB pBlob,
  393. IN PHOSTENT pHostent
  394. )
  395. {
  396. DNSDBG( SABLOB, ( "SaBlob_AttachHostent()\n" ));
  397. //
  398. // attach existing hostent to sablob
  399. //
  400. pBlob->pHostent = pHostent;
  401. }
  402. DNS_STATUS
  403. SaBlob_WriteAddress(
  404. IN OUT PSABLOB pBlob,
  405. IN PDNS_ADDR pAddr
  406. )
  407. /*++
  408. Routine Description:
  409. Write address to sablob.
  410. Arguments:
  411. pBlob -- sablob
  412. pAddr - address to write
  413. Return Value:
  414. ERROR_SUCCESS if successful.
  415. ERROR_MORE_DATA if out of buffer space
  416. ERROR_INVALID_DATA if address doesn't match sablob
  417. --*/
  418. {
  419. PDNS_ADDR_ARRAY parray;
  420. //
  421. // if no address array -- create one
  422. //
  423. parray = pBlob->pAddrArray;
  424. if ( !parray )
  425. {
  426. parray = DnsAddrArray_Create( 1 );
  427. if ( !parray )
  428. {
  429. return DNS_ERROR_NO_MEMORY;
  430. }
  431. pBlob->pAddrArray = parray;
  432. }
  433. //
  434. // slap address into array
  435. // - fail if array too full
  436. //
  437. if ( DnsAddrArray_AddAddr(
  438. parray,
  439. pAddr,
  440. 0, // no family check
  441. 0 // no match flag
  442. ) )
  443. {
  444. return NO_ERROR;
  445. }
  446. return ERROR_MORE_DATA;
  447. }
  448. #if 0
  449. DNS_STATUS
  450. SaBlob_WriteAddressArray(
  451. IN OUT PSABLOB pBlob,
  452. IN PVOID pAddrArray,
  453. IN DWORD AddrCount,
  454. IN DWORD AddrSize,
  455. IN DWORD AddrType
  456. )
  457. /*++
  458. Routine Description:
  459. Write address array to sablob blob.
  460. Arguments:
  461. pBlob -- sablob build blob
  462. pAddrArray - address array to write
  463. AddrCount - address count
  464. AddrSize - address size
  465. AddrType - address type (sablob type, e.g. AF_INET)
  466. Return Value:
  467. ERROR_SUCCESS if successful.
  468. ERROR_MORE_DATA if out of buffer space
  469. ERROR_INVALID_DATA if address doesn't match sablob
  470. --*/
  471. {
  472. DWORD count = AddrCount;
  473. PCHAR pcurrent;
  474. DWORD totalSize;
  475. DWORD i;
  476. DWORD bytesLeft;
  477. // verify type
  478. // - set if empty or no addresses written
  479. if ( phost->h_addrtype != (SHORT)AddrType )
  480. {
  481. if ( phost->h_addrtype != 0 )
  482. {
  483. return( ERROR_INVALID_DATA );
  484. }
  485. phost->h_addrtype = (SHORT) AddrType;
  486. phost->h_length = (SHORT) AddrSize;
  487. }
  488. // verify space
  489. if ( count > pBlob->MaxAddrCount )
  490. {
  491. return( ERROR_MORE_DATA );
  492. }
  493. // align - to DWORD
  494. //
  495. // note: we are assuming that pAddrArray is internally
  496. // aligned adequately, otherwise we wouldn't be
  497. // getting an intact array and would have to add serially
  498. pcurrent = DWORD_ALIGN( pBlob->pCurrent );
  499. bytesLeft = pBlob->BytesLeft;
  500. bytesLeft -= (DWORD)(pcurrent - pBlob->pCurrent);
  501. totalSize = count * AddrSize;
  502. if ( bytesLeft < totalSize )
  503. {
  504. return( ERROR_MORE_DATA );
  505. }
  506. // copy
  507. // - copy address array to buffer
  508. // - set pointer to each address in array
  509. // - NULL following pointer
  510. RtlCopyMemory(
  511. pcurrent,
  512. pAddrArray,
  513. totalSize );
  514. for ( i=0; i<count; i++ )
  515. {
  516. phost->h_addr_list[i] = pcurrent;
  517. pcurrent += AddrSize;
  518. }
  519. phost->h_addr_list[count] = NULL;
  520. pBlob->AddrCount = count;
  521. pBlob->pCurrent = pcurrent;
  522. pBlob->BytesLeft = bytesLeft - totalSize;
  523. return( NO_ERROR );
  524. }
  525. #endif
  526. DNS_STATUS
  527. SaBlob_WriteNameOrAlias(
  528. IN OUT PSABLOB pBlob,
  529. IN PWSTR pszName,
  530. IN BOOL fAlias
  531. )
  532. /*++
  533. Routine Description:
  534. Write name or alias to sablob
  535. Arguments:
  536. pBlob -- sablob build blob
  537. pszName -- name to write
  538. fAlias -- TRUE for alias; FALSE for name
  539. Return Value:
  540. ERROR_SUCCESS if successful.
  541. ERROR_MORE_DATA if out of buffer space
  542. ERROR_INVALID_DATA if address doesn't match sablob
  543. --*/
  544. {
  545. DWORD count = pBlob->AliasCount;
  546. PWSTR pcopy;
  547. //
  548. // verify space
  549. // included ptr space
  550. // - skip if already written name
  551. // or exhausted alias array
  552. //
  553. if ( fAlias )
  554. {
  555. if ( count >= DNS_MAX_ALIAS_COUNT )
  556. {
  557. return( ERROR_MORE_DATA );
  558. }
  559. }
  560. else if ( pBlob->pName )
  561. {
  562. return( ERROR_MORE_DATA );
  563. }
  564. //
  565. // copy
  566. // - copy name
  567. // - set ptr in blob
  568. pcopy = Dns_CreateStringCopy_W( pszName );
  569. if ( !pcopy )
  570. {
  571. return GetLastError();
  572. }
  573. if ( fAlias )
  574. {
  575. pBlob->AliasArray[count++] = pcopy;
  576. pBlob->AliasCount = count;
  577. }
  578. else
  579. {
  580. pBlob->pName = pcopy;
  581. }
  582. return( NO_ERROR );
  583. }
  584. DNS_STATUS
  585. SaBlob_WriteRecords(
  586. IN OUT PSABLOB pBlob,
  587. IN PDNS_RECORD pRecords,
  588. IN BOOL fWriteName
  589. )
  590. /*++
  591. Routine Description:
  592. Write name or alias to sablob
  593. Arguments:
  594. pBlob -- sablob build blob
  595. pRecords -- records to convert to sablob
  596. fWriteName -- write name
  597. Return Value:
  598. ERROR_SUCCESS if successful.
  599. ERROR_MORE_DATA if out of buffer space
  600. ERROR_INVALID_DATA if address doesn't match sablob
  601. --*/
  602. {
  603. DNS_STATUS status = NO_ERROR;
  604. PDNS_RECORD prr = pRecords;
  605. DNS_ADDR dnsAddr;
  606. BOOL fwroteName = FALSE;
  607. DNSDBG( SABLOB, (
  608. "SaBlob_WriteRecords( %p, %p, %d )\n",
  609. pBlob,
  610. pRecords,
  611. fWriteName ));
  612. //
  613. // write each record in turn to sablob
  614. //
  615. while ( prr )
  616. {
  617. WORD wtype;
  618. if ( prr->Flags.S.Section != DNSREC_ANSWER &&
  619. prr->Flags.S.Section != 0 )
  620. {
  621. prr = prr->pNext;
  622. continue;
  623. }
  624. wtype = prr->wType;
  625. switch( wtype )
  626. {
  627. case DNS_TYPE_A:
  628. case DNS_TYPE_AAAA:
  629. case DNS_TYPE_ATMA:
  630. DnsAddr_BuildFromDnsRecord(
  631. & dnsAddr,
  632. prr );
  633. status = SaBlob_WriteAddress(
  634. pBlob,
  635. & dnsAddr );
  636. // write name
  637. if ( fWriteName &&
  638. !fwroteName &&
  639. !pBlob->pName &&
  640. prr->pName )
  641. {
  642. status = SaBlob_WriteNameOrAlias(
  643. pBlob,
  644. (PWSTR) prr->pName,
  645. FALSE // name
  646. );
  647. fwroteName = TRUE;
  648. }
  649. break;
  650. case DNS_TYPE_CNAME:
  651. // record name is an alias
  652. status = SaBlob_WriteNameOrAlias(
  653. pBlob,
  654. (PWSTR) prr->pName,
  655. TRUE // alias
  656. );
  657. break;
  658. case DNS_TYPE_PTR:
  659. // target name is the sablob name
  660. // but if already wrote name, PTR target becomes alias
  661. status = SaBlob_WriteNameOrAlias(
  662. pBlob,
  663. (PWSTR) prr->Data.PTR.pNameHost,
  664. (pBlob->pName != NULL)
  665. );
  666. break;
  667. default:
  668. DNSDBG( ANY, (
  669. "Error record of type = %d while building sablob!\n",
  670. wtype ));
  671. status = ERROR_INVALID_DATA;
  672. }
  673. if ( status != ERROR_SUCCESS )
  674. {
  675. DNSDBG( ANY, (
  676. "ERROR: failed writing record to sablob!\n"
  677. "\tprr = %p\n"
  678. "\ttype = %d\n"
  679. "\tstatus = %d\n",
  680. prr,
  681. wtype,
  682. status ));
  683. }
  684. prr = prr->pNext;
  685. }
  686. IF_DNSDBG( SABLOB )
  687. {
  688. DnsDbg_SaBlob(
  689. "SaBlob after WriteRecords():",
  690. pBlob );
  691. }
  692. return( status );
  693. }
  694. PSABLOB
  695. SaBlob_CreateFromRecords(
  696. IN PDNS_RECORD pRecords,
  697. IN BOOL fWriteName,
  698. IN WORD wType OPTIONAL
  699. )
  700. /*++
  701. Routine Description:
  702. Create sablob from records
  703. Arguments:
  704. pRecords -- records to convert to sablob
  705. fWriteName -- write name to sablob
  706. wType -- query type, if known
  707. Return Value:
  708. Ptr to blob if successful.
  709. NULL on error; GetLastError() has error.
  710. --*/
  711. {
  712. DNS_STATUS status = NO_ERROR;
  713. PDNS_RECORD prrFirstAddr = NULL;
  714. PDNS_RECORD prr;
  715. DWORD addrCount = 0;
  716. WORD addrType = 0;
  717. PSABLOB pblob = NULL;
  718. DNSDBG( SABLOB, (
  719. "SaBlob_CreateFromRecords()\n"
  720. "\tpblob = %p\n"
  721. "\tprr = %p\n",
  722. pblob,
  723. pRecords ));
  724. //
  725. // count addresses
  726. //
  727. // DCR: fix up section hack when hosts file records get ANSWER section
  728. //
  729. prr = pRecords;
  730. while ( prr )
  731. {
  732. if ( ( prr->Flags.S.Section == 0 ||
  733. prr->Flags.S.Section == DNSREC_ANSWER )
  734. &&
  735. SaBlob_IsSupportedAddrType( prr->wType ) )
  736. {
  737. addrCount++;
  738. if ( !prrFirstAddr )
  739. {
  740. prrFirstAddr = prr;
  741. addrType = prr->wType;
  742. }
  743. }
  744. prr = prr->pNext;
  745. }
  746. //
  747. // create sa-blob of desired size
  748. //
  749. pblob = SaBlob_Create( addrCount );
  750. if ( !pblob )
  751. {
  752. status = GetLastError();
  753. goto Done;
  754. }
  755. //
  756. // build sablob from answer records
  757. //
  758. // note: if manage to extract any useful data => continue
  759. // this protects against new unwriteable records breaking us
  760. //
  761. status = SaBlob_WriteRecords(
  762. pblob,
  763. pRecords,
  764. TRUE // write name
  765. );
  766. if ( status != NO_ERROR )
  767. {
  768. if ( pblob->pName ||
  769. pblob->AliasCount ||
  770. ( pblob->pAddrArray &&
  771. pblob->pAddrArray->AddrCount ) )
  772. {
  773. status = NO_ERROR;
  774. }
  775. else
  776. {
  777. goto Done;
  778. }
  779. }
  780. //
  781. // write address from PTR record
  782. // - first record PTR
  783. // OR
  784. // - queried for PTR and got CNAME answer, which can happen
  785. // in classless reverse lookup case
  786. //
  787. // DCR: add PTR address lookup to SaBlob_WriteRecords()
  788. // - natural place
  789. // - but would have to figure out handling of multiple PTRs
  790. //
  791. if ( pRecords &&
  792. ( pRecords->wType == DNS_TYPE_PTR ||
  793. ( wType == DNS_TYPE_PTR &&
  794. pRecords->wType == DNS_TYPE_CNAME &&
  795. pRecords->Flags.S.Section == DNSREC_ANSWER ) ) )
  796. {
  797. DNS_ADDR dnsAddr;
  798. DNSDBG( SABLOB, (
  799. "Writing address for PTR record %S\n",
  800. pRecords->pName ));
  801. // convert reverse name to IP
  802. if ( Dns_ReverseNameToDnsAddr_W(
  803. & dnsAddr,
  804. (PWSTR) pRecords->pName ) )
  805. {
  806. status = SaBlob_WriteAddress(
  807. pblob,
  808. & dnsAddr );
  809. ASSERT( status == NO_ERROR );
  810. status = ERROR_SUCCESS;
  811. }
  812. }
  813. //
  814. // write name?
  815. // - write name from first address record
  816. //
  817. if ( !pblob->pName &&
  818. fWriteName &&
  819. prrFirstAddr )
  820. {
  821. status = SaBlob_WriteNameOrAlias(
  822. pblob,
  823. (PWSTR) prrFirstAddr->pName,
  824. FALSE // name
  825. );
  826. }
  827. IF_DNSDBG( SABLOB )
  828. {
  829. DnsDbg_SaBlob(
  830. "SaBlob after CreateFromRecords():",
  831. pblob );
  832. }
  833. Done:
  834. if ( status != NO_ERROR )
  835. {
  836. DNSDBG( SABLOB, (
  837. "Leave SaBlob_CreateFromRecords() => status=%d\n",
  838. status ));
  839. SaBlob_Free( pblob );
  840. pblob = NULL;
  841. SetLastError( status );
  842. }
  843. else
  844. {
  845. DNSDBG( SABLOB, (
  846. "Leave SaBlob_CreateFromRecords() => %p\n",
  847. pblob ));
  848. }
  849. return( pblob );
  850. }
  851. //
  852. // SockaddrResults Query
  853. //
  854. PSABLOB
  855. SaBlob_Query(
  856. IN PWSTR pwsName,
  857. IN WORD wType,
  858. IN DWORD Flags,
  859. IN OUT PVOID * ppMsg, OPTIONAL
  860. IN INT AddrFamily OPTIONAL
  861. )
  862. /*++
  863. Routine Description:
  864. Query DNS to get sockaddr results.
  865. Arguments:
  866. pwsName -- name to query
  867. wType -- query type
  868. Flags -- query flags
  869. ppResults -- addr to receive pointer to results
  870. AddrType -- address type (family) to reserve space for if querying
  871. for PTR records
  872. Return Value:
  873. Ptr to blob if successful.
  874. NULL on error; GetLastError() has error.
  875. --*/
  876. {
  877. DNS_STATUS status = NO_ERROR;
  878. PDNS_RECORD prrQuery = NULL;
  879. PSABLOB pblob = NULL;
  880. PVOID pmsg = NULL;
  881. DNSDBG( SABLOB, (
  882. "SaBlob_Query()\n"
  883. "\tname = %S\n"
  884. "\ttype = %d\n"
  885. "\tflags = %08x\n",
  886. pwsName,
  887. wType,
  888. Flags ));
  889. //
  890. // query
  891. // - if fails, dump any message before return
  892. //
  893. if ( ppMsg )
  894. {
  895. *ppMsg = NULL;
  896. }
  897. status = DnsQuery_W(
  898. pwsName,
  899. wType,
  900. Flags,
  901. NULL,
  902. & prrQuery,
  903. ppMsg );
  904. // if failed, dump any message
  905. if ( status != NO_ERROR )
  906. {
  907. if ( ppMsg && *ppMsg )
  908. {
  909. DnsApiFree( *ppMsg );
  910. *ppMsg = NULL;
  911. }
  912. if ( status == RPC_S_SERVER_UNAVAILABLE )
  913. {
  914. status = WSATRY_AGAIN;
  915. }
  916. goto Done;
  917. }
  918. if ( !prrQuery )
  919. {
  920. ASSERT( FALSE );
  921. status = DNS_ERROR_RCODE_NAME_ERROR;
  922. goto Done;
  923. }
  924. //
  925. // build sablob
  926. //
  927. pblob = SaBlob_CreateFromRecords(
  928. prrQuery,
  929. TRUE, // write name from first answer
  930. wType
  931. );
  932. if ( !pblob )
  933. {
  934. status = GetLastError();
  935. goto Done;
  936. }
  937. //
  938. // devnote: if don't have these checks
  939. // -- nameless hostent can blow up gethostbyname()
  940. // -- NO_ERROR, no address responses can confuse applications
  941. //
  942. // failed name write
  943. // - queries that CNAME but don't find record of query type can hit here
  944. //
  945. if ( !pblob->pName )
  946. {
  947. status = DNS_INFO_NO_RECORDS;
  948. goto Done;
  949. }
  950. #if 0
  951. // note: because SVCID_HOSTNAME query is currently treated as
  952. // simply A record query, we can't do no-address screening here;
  953. // this screening can be done at higher level for all GUIDs
  954. // except HOSTNAME
  955. //
  956. // for address query must get answer
  957. //
  958. // DCR: DnsQuery() should convert to no-records on empty CNAME chain?
  959. // DCR: should we go ahead and build sablob?
  960. //
  961. if ( !pblob->pAddrArray && SaBlob_IsSupportedAddrType(wType) )
  962. {
  963. status = DNS_INFO_NO_RECORDS;
  964. }
  965. #endif
  966. //
  967. // set returned name to FQDN for loopback lookups
  968. // this is for compatibility with previous OS versions
  969. //
  970. if ( DnsNameCompare_W( pblob->pName, L"localhost" ) ||
  971. DnsNameCompare_W( pblob->pName, L"loopback" ) )
  972. {
  973. PWSTR pname;
  974. PWSTR pnameFqdn;
  975. pname = DnsQueryConfigAlloc(
  976. DnsConfigFullHostName_W,
  977. NULL );
  978. if ( pname )
  979. {
  980. pnameFqdn = Dns_CreateStringCopy_W( pname );
  981. if ( pnameFqdn )
  982. {
  983. FREE_HEAP( pblob->pName );
  984. pblob->pName = pnameFqdn;
  985. }
  986. DnsApiFree( pname );
  987. }
  988. }
  989. Done:
  990. if ( prrQuery )
  991. {
  992. DnsRecordListFree(
  993. prrQuery,
  994. DnsFreeRecordListDeep );
  995. }
  996. if ( status != NO_ERROR && pblob )
  997. {
  998. SaBlob_Free( pblob );
  999. pblob = NULL;
  1000. }
  1001. DNSDBG( SABLOB, (
  1002. "Leave SaBlob_Query()\n"
  1003. "\tpblob = %p\n"
  1004. "\tstatus = %d\n",
  1005. pblob,
  1006. status ));
  1007. SetLastError( status );
  1008. return( pblob );
  1009. }
  1010. //
  1011. // Special sablobs
  1012. //
  1013. #if 0
  1014. PSABLOB
  1015. SaBlob_Localhost(
  1016. IN INT Family
  1017. )
  1018. /*++
  1019. Routine Description:
  1020. Create sablob from records
  1021. Arguments:
  1022. AddrFamily -- address family
  1023. Return Value:
  1024. Ptr to blob if successful.
  1025. NULL on error; GetLastError() has error.
  1026. --*/
  1027. {
  1028. DNS_STATUS status = NO_ERROR;
  1029. PDNS_RECORD prrFirstAddr = NULL;
  1030. PDNS_RECORD prr;
  1031. DWORD addrCount = 0;
  1032. DWORD addrSize;
  1033. CHAR addrBuf[ sizeof(IP6_ADDRESS ) ];
  1034. SABLOB_INIT request;
  1035. PSABLOB pblob = NULL;
  1036. DNSDBG( SABLOB, ( "SaBlob_Localhost()\n" ));
  1037. //
  1038. // create sablob blob
  1039. //
  1040. RtlZeroMemory( &request, sizeof(request) );
  1041. request.AliasCount = 1;
  1042. request.AddrCount = 1;
  1043. request.AddrFamily = Family;
  1044. request.fUnicode = TRUE;
  1045. status = SaBlob_Create(
  1046. & pblob,
  1047. & request );
  1048. if ( status != NO_ERROR )
  1049. {
  1050. goto Done;
  1051. }
  1052. //
  1053. // write in loopback address
  1054. //
  1055. if ( Family == AF_INET )
  1056. {
  1057. * (PIP4_ADDRESS) addrBuf = DNS_NET_ORDER_LOOPBACK;
  1058. addrSize = sizeof(IP4_ADDRESS);
  1059. }
  1060. else if ( Family == AF_INET6 )
  1061. {
  1062. IP6_SET_ADDR_LOOPBACK( (PIP6_ADDRESS)addrBuf );
  1063. addrSize = sizeof(IN6_ADDR);
  1064. }
  1065. else
  1066. {
  1067. status = DNS_ERROR_INVALID_DATA;
  1068. goto Done;
  1069. }
  1070. status = SaBlob_WriteAddress(
  1071. pblob,
  1072. addrBuf,
  1073. addrSize,
  1074. Family );
  1075. if ( status != NO_ERROR )
  1076. {
  1077. goto Done;
  1078. }
  1079. //
  1080. // write localhost
  1081. //
  1082. status = SaBlob_WriteNameOrAlias(
  1083. pblob,
  1084. L"localhost",
  1085. FALSE // name
  1086. );
  1087. IF_DNSDBG( SABLOB )
  1088. {
  1089. DnsDbg_SaBlob(
  1090. "SaBlob after localhost create:",
  1091. pblob );
  1092. }
  1093. Done:
  1094. if ( status != NO_ERROR && pblob )
  1095. {
  1096. SaBlob_Free( pblob );
  1097. pblob = NULL;
  1098. }
  1099. SetLastError( status );
  1100. DNSDBG( SABLOB, (
  1101. "Leave SaBlob_Localhost() => status = %d\n",
  1102. status ));
  1103. return( pblob );
  1104. }
  1105. PSABLOB
  1106. SaBlob_CreateFromIpArray(
  1107. IN INT AddrFamily,
  1108. IN INT AddrSize,
  1109. IN INT AddrCount,
  1110. IN PCHAR pArray,
  1111. IN PSTR pName,
  1112. IN BOOL fUnicode
  1113. )
  1114. /*++
  1115. Routine Description:
  1116. Create sablob from records
  1117. Arguments:
  1118. ppBlob -- ptr with or to recv sablob blob
  1119. AddrFamily -- addr family use if PTR records and no addr
  1120. pArray -- array of addresses
  1121. pName -- name for sablob
  1122. fUnicode --
  1123. TRUE if name is and sablob will be in unicode
  1124. FALSE for narrow name and sablob
  1125. Return Value:
  1126. Ptr to blob if successful.
  1127. NULL on error; GetLastError() has error.
  1128. --*/
  1129. {
  1130. DNS_STATUS status = NO_ERROR;
  1131. SABLOB_INIT request;
  1132. PSABLOB pblob = *ppBlob;
  1133. DNSDBG( SABLOB, (
  1134. "SaBlob_CreateFromIpArray()\n"
  1135. "\tppBlob = %p\n"
  1136. "\tfamily = %d\n"
  1137. "\tsize = %d\n"
  1138. "\tcount = %d\n"
  1139. "\tpArray = %p\n",
  1140. ppBlob,
  1141. AddrFamily,
  1142. AddrSize,
  1143. AddrCount,
  1144. pArray ));
  1145. //
  1146. // create or reinit sablob blob
  1147. //
  1148. RtlZeroMemory( &request, sizeof(request) );
  1149. request.AliasCount = DNS_MAX_ALIAS_COUNT;
  1150. request.AddrCount = AddrCount;
  1151. request.AddrFamily = AddrFamily;
  1152. request.fUnicode = fUnicode;
  1153. request.pName = pName;
  1154. status = SaBlob_Create(
  1155. & pblob,
  1156. & request );
  1157. if ( status != NO_ERROR )
  1158. {
  1159. goto Done;
  1160. }
  1161. //
  1162. // write in array
  1163. //
  1164. if ( AddrCount )
  1165. {
  1166. status = SaBlob_WriteAddressArray(
  1167. pblob,
  1168. pArray,
  1169. AddrCount,
  1170. AddrSize,
  1171. AddrFamily
  1172. );
  1173. if ( status != NO_ERROR )
  1174. {
  1175. goto Done;
  1176. }
  1177. }
  1178. //
  1179. // write name?
  1180. //
  1181. if ( pName )
  1182. {
  1183. status = SaBlob_WriteNameOrAlias(
  1184. pblob,
  1185. pName,
  1186. FALSE, // name not alias
  1187. fUnicode
  1188. );
  1189. }
  1190. IF_DNSDBG( SABLOB )
  1191. {
  1192. DnsDbg_SaBlob(
  1193. "Leaving SaBlob_CreateFromIpArray():",
  1194. pblob );
  1195. }
  1196. Done:
  1197. if ( status != NO_ERROR && pblob )
  1198. {
  1199. SaBlob_Free( pblob );
  1200. pblob = NULL;
  1201. }
  1202. *ppBlob = pblob;
  1203. DNSDBG( SABLOB, (
  1204. "Leave SaBlob_CreateFromIpArray() => status = %d\n",
  1205. status ));
  1206. return( status );
  1207. }
  1208. PSABLOB
  1209. SaBlob_CreateLocal(
  1210. IN INT AddrFamily,
  1211. IN BOOL fLoopback,
  1212. IN BOOL fZero,
  1213. IN BOOL fHostnameOnly
  1214. )
  1215. /*++
  1216. Routine Description:
  1217. Create sablob from records
  1218. Arguments:
  1219. ppBlob -- ptr with or to recv sablob blob
  1220. AddrFamily -- addr family use if PTR records and no addr
  1221. Return Value:
  1222. Ptr to blob if successful.
  1223. NULL on error; GetLastError() has error.
  1224. --*/
  1225. {
  1226. DNS_STATUS status = NO_ERROR;
  1227. PSABLOB pblob = NULL;
  1228. WORD wtype;
  1229. INT size;
  1230. IP6_ADDRESS ip;
  1231. DNSDBG( SABLOB, (
  1232. "SaBlob_CreateLocal()\n"
  1233. "\tppBlob = %p\n"
  1234. "\tfamily = %d\n"
  1235. "\tfLoopback = %d\n"
  1236. "\tfZero = %d\n"
  1237. "\tfHostname = %d\n",
  1238. ppBlob,
  1239. AddrFamily,
  1240. fLoopback,
  1241. fZero,
  1242. fHostnameOnly
  1243. ));
  1244. //
  1245. // get family info
  1246. // - start with override IP = 0
  1247. // - if loopback switch to appropriate loopback
  1248. //
  1249. RtlZeroMemory(
  1250. &ip,
  1251. sizeof(ip) );
  1252. if ( AddrFamily == AF_INET )
  1253. {
  1254. wtype = DNS_TYPE_A;
  1255. size = sizeof(IP4_ADDRESS);
  1256. if ( fLoopback )
  1257. {
  1258. * (PIP4_ADDRESS) &ip = DNS_NET_ORDER_LOOPBACK;
  1259. }
  1260. }
  1261. else if ( AddrFamily == AF_INET6 )
  1262. {
  1263. wtype = DNS_TYPE_AAAA;
  1264. size = sizeof(IP6_ADDRESS);
  1265. if ( fLoopback )
  1266. {
  1267. IP6_SET_ADDR_LOOPBACK( &ip );
  1268. }
  1269. }
  1270. else
  1271. {
  1272. status = ERROR_INVALID_PARAMETER;
  1273. goto Done;
  1274. }
  1275. //
  1276. // query for local host info
  1277. //
  1278. pblob = SaBlob_Query(
  1279. NULL, // NULL name gets local host data
  1280. wtype,
  1281. 0, // standard query
  1282. NULL, // no message
  1283. AddrFamily );
  1284. if ( !pblob )
  1285. {
  1286. DNS_ASSERT( FALSE );
  1287. status = GetLastError();
  1288. goto Done;
  1289. }
  1290. //
  1291. // overwrite with specific address
  1292. //
  1293. if ( fLoopback || fZero )
  1294. {
  1295. if ( ! SaBlob_SetToSingleAddress(
  1296. pblob->pBlob,
  1297. (PCHAR) &ip,
  1298. size ) )
  1299. {
  1300. DNS_ASSERT( pblob->AddrCount == 0 );
  1301. pblob->AddrCount = 0;
  1302. status = SaBlob_WriteAddress(
  1303. pblob,
  1304. & ip,
  1305. size,
  1306. AddrFamily );
  1307. if ( status != NO_ERROR )
  1308. {
  1309. DNS_ASSERT( status!=NO_ERROR );
  1310. goto Done;
  1311. }
  1312. }
  1313. }
  1314. //
  1315. // for gethostname()
  1316. // - chop name down to just hostname
  1317. // - kill off aliases
  1318. //
  1319. if ( fHostnameOnly )
  1320. {
  1321. PWSTR pname = (PWSTR) pblob->pName;
  1322. PWSTR pdomain;
  1323. DNS_ASSERT( pname );
  1324. if ( pname )
  1325. {
  1326. pdomain = Dns_GetDomainNameW( pname );
  1327. if ( pdomain )
  1328. {
  1329. DNS_ASSERT( pdomain > pname+1 );
  1330. DNS_ASSERT( *(pdomain-1) == L'.' );
  1331. *(pdomain-1) = 0;
  1332. }
  1333. }
  1334. pblob->AliasCount = 0;
  1335. }
  1336. IF_DNSDBG( SABLOB )
  1337. {
  1338. DnsDbg_SaBlob(
  1339. "Leaving SaBlob_CreateLocal():",
  1340. pblob );
  1341. }
  1342. Done:
  1343. if ( status != NO_ERROR && pblob )
  1344. {
  1345. SaBlob_Free( pblob );
  1346. pblob = NULL;
  1347. }
  1348. DNSDBG( SABLOB, (
  1349. "Leave SaBlob_CreateLocal() => %p\n"
  1350. "\tstatus = %d\n",
  1351. pblob,
  1352. status ));
  1353. if ( status != NO_ERROR )
  1354. {
  1355. SetLastError( status );
  1356. }
  1357. return( pblob );
  1358. }
  1359. #endif
  1360. PHOSTENT
  1361. SaBlob_CreateHostent(
  1362. IN OUT PBYTE * ppBuffer,
  1363. IN OUT PINT pBufferSize,
  1364. OUT PINT pHostentSize,
  1365. IN PSABLOB pBlob,
  1366. IN DNS_CHARSET CharSetTarget,
  1367. IN BOOL fOffsets,
  1368. IN BOOL fAlloc
  1369. )
  1370. /*++
  1371. Routine Description:
  1372. Copy a hostent.
  1373. Arguments:
  1374. ppBuffer -- addr with ptr to buffer to write to;
  1375. if no buffer then hostent is allocated
  1376. updated with ptr to position in buffer after hostent
  1377. pBufferSize -- addr containing size of buffer;
  1378. updated with bytes left after hostent written
  1379. (even if out of space, it contains missing number of
  1380. bytes as negative number)
  1381. pHostentSize -- addr to recv total size of hostent written
  1382. pBlob -- sockaddr blob to create hostent for
  1383. CharSetTarget -- charset of target hostent
  1384. fOffsets -- write hostent with offsets
  1385. fAlloc -- allocate copy
  1386. Return Value:
  1387. Ptr to new hostent.
  1388. NULL on error. See GetLastError().
  1389. --*/
  1390. {
  1391. PBYTE pch;
  1392. PHOSTENT phost = NULL;
  1393. DWORD sizeTotal;
  1394. DWORD bytesLeft;
  1395. DWORD i;
  1396. DWORD size;
  1397. DWORD family = 0;
  1398. DWORD aliasCount;
  1399. DWORD addrCount = 0;
  1400. DWORD addrLength = 0;
  1401. PCHAR * pptrArrayOut;
  1402. DWORD sizeAliasPtrs;
  1403. DWORD sizeAddrPtrs;
  1404. DWORD sizeAddrs;
  1405. DWORD sizeAliasNames = 0;
  1406. DWORD sizeName = 0;
  1407. PFAMILY_INFO pfamilyInfo = NULL;
  1408. PDNS_ADDR_ARRAY paddrArray;
  1409. DNSDBG( HOSTENT, (
  1410. "SaBlob_CreateHostent( %p )\n",
  1411. pBlob ));
  1412. //
  1413. // get family, count info to size hostent
  1414. //
  1415. #if 0
  1416. if ( pBlob->Family != 0 )
  1417. {
  1418. pfamilyInfo = FamilyInfo_GetForFamily( pBlob->Family );
  1419. }
  1420. #endif
  1421. aliasCount = pBlob->AliasCount;
  1422. paddrArray = pBlob->pAddrArray;
  1423. if ( paddrArray )
  1424. {
  1425. family = paddrArray->AddrArray[0].Sockaddr.sa_family;
  1426. pfamilyInfo = FamilyInfo_GetForFamily( family );
  1427. if ( !pfamilyInfo )
  1428. {
  1429. DNS_ASSERT( FALSE );
  1430. }
  1431. else
  1432. {
  1433. addrCount = paddrArray->AddrCount;
  1434. addrLength = pfamilyInfo->LengthAddr;
  1435. }
  1436. }
  1437. //
  1438. // size hostent
  1439. // - struct
  1440. // - alias and addr ptr arrays (both NULL terminated)
  1441. // - addresses
  1442. // - name
  1443. // - aliases
  1444. //
  1445. // note: only aligning strings to WORD (for unicode) as we'll build
  1446. // them into buffer AFTER the addresses (which require DWORD)
  1447. // alignment
  1448. //
  1449. sizeAliasPtrs = (aliasCount+1) * sizeof(PCHAR);
  1450. sizeAddrPtrs = (addrCount+1) * sizeof(PCHAR);
  1451. sizeAddrs = addrCount * addrLength;
  1452. if ( pBlob->pName )
  1453. {
  1454. sizeName = Dns_GetBufferLengthForStringCopy(
  1455. (PCHAR) pBlob->pName,
  1456. 0,
  1457. DnsCharSetUnicode,
  1458. CharSetTarget );
  1459. sizeName = WORD_ALIGN_DWORD( sizeName );
  1460. }
  1461. for ( i=0; i<aliasCount; i++ )
  1462. {
  1463. sizeAliasNames += Dns_GetBufferLengthForStringCopy(
  1464. (PCHAR) pBlob->AliasArray[i],
  1465. 0,
  1466. DnsCharSetUnicode,
  1467. CharSetTarget );
  1468. sizeAliasNames = WORD_ALIGN_DWORD( sizeAliasNames );
  1469. }
  1470. sizeTotal = POINTER_ALIGN_DWORD( sizeof(HOSTENT) ) +
  1471. sizeAliasPtrs +
  1472. sizeAddrPtrs +
  1473. sizeAddrs +
  1474. sizeName +
  1475. sizeAliasNames;
  1476. DNSDBG( HOSTENT, (
  1477. "SaBlob Hostent create:\n"
  1478. "\tsize = %d\n"
  1479. "\tsizeAliasPtrs = %d\n"
  1480. "\tsizeAddrPtrs = %d\n"
  1481. "\tsizeAddrs = %d\n"
  1482. "\tsizeName = %d\n"
  1483. "\tsizeAliasNames = %d\n",
  1484. sizeTotal,
  1485. sizeAliasPtrs,
  1486. sizeAddrPtrs,
  1487. sizeAddrs,
  1488. sizeName,
  1489. sizeAliasNames ));
  1490. //
  1491. // alloc or reserve size in buffer
  1492. //
  1493. if ( fAlloc )
  1494. {
  1495. pch = ALLOCATE_HEAP( sizeTotal );
  1496. if ( !pch )
  1497. {
  1498. goto Failed;
  1499. }
  1500. }
  1501. else
  1502. {
  1503. pch = FlatBuf_Arg_ReserveAlignPointer(
  1504. ppBuffer,
  1505. pBufferSize,
  1506. sizeTotal
  1507. );
  1508. if ( !pch )
  1509. {
  1510. goto Failed;
  1511. }
  1512. }
  1513. //
  1514. // note: assuming from here on down that we have adequate space
  1515. //
  1516. // reason we aren't building with FlatBuf routines is that
  1517. // a) we believe we have adequate space
  1518. // b) i haven't built FlatBuf string conversion routines
  1519. // which we need below (for RnR unicode to ANSI)
  1520. //
  1521. // we could reset buf pointers here and build directly with FlatBuf
  1522. // routines; this isn't directly necessary
  1523. //
  1524. //
  1525. // init hostent struct
  1526. //
  1527. phost = Hostent_Init(
  1528. & pch,
  1529. family,
  1530. addrLength,
  1531. addrCount,
  1532. aliasCount );
  1533. DNS_ASSERT( pch > (PBYTE)phost );
  1534. //
  1535. // copy addresses
  1536. // - no need to align as previous is address
  1537. //
  1538. pptrArrayOut = phost->h_addr_list;
  1539. if ( paddrArray && pfamilyInfo )
  1540. {
  1541. DWORD offset = pfamilyInfo->OffsetToAddrInSockaddr;
  1542. for ( i=0; i<paddrArray->AddrCount; i++ )
  1543. {
  1544. *pptrArrayOut++ = pch;
  1545. RtlCopyMemory(
  1546. pch,
  1547. ((PBYTE)&paddrArray->AddrArray[i]) + offset,
  1548. addrLength );
  1549. pch += addrLength;
  1550. }
  1551. }
  1552. *pptrArrayOut = NULL;
  1553. //
  1554. // copy the name
  1555. //
  1556. if ( pBlob->pName )
  1557. {
  1558. pch = WORD_ALIGN( pch );
  1559. phost->h_name = pch;
  1560. size = Dns_StringCopy(
  1561. pch,
  1562. NULL, // buffer is adequate
  1563. (PCHAR)pBlob->pName,
  1564. 0, // unknown length
  1565. DnsCharSetUnicode,
  1566. CharSetTarget
  1567. );
  1568. pch += size;
  1569. }
  1570. //
  1571. // copy the aliases
  1572. //
  1573. pptrArrayOut = phost->h_aliases;
  1574. if ( aliasCount )
  1575. {
  1576. for ( i=0; i<aliasCount; i++ )
  1577. {
  1578. pch = WORD_ALIGN( pch );
  1579. *pptrArrayOut++ = pch;
  1580. size = Dns_StringCopy(
  1581. pch,
  1582. NULL, // buffer is adequate
  1583. (PCHAR) pBlob->AliasArray[i],
  1584. 0, // unknown length
  1585. DnsCharSetUnicode,
  1586. CharSetTarget
  1587. );
  1588. pch += size;
  1589. }
  1590. }
  1591. *pptrArrayOut = NULL;
  1592. //
  1593. // copy is complete
  1594. // - verify our write functions work
  1595. //
  1596. ASSERT( (DWORD)(pch-(PBYTE)phost) <= sizeTotal );
  1597. if ( pHostentSize )
  1598. {
  1599. *pHostentSize = (INT)( pch - (PBYTE)phost );
  1600. }
  1601. if ( !fAlloc )
  1602. {
  1603. PBYTE pnext = *ppBuffer;
  1604. // if we sized too small --
  1605. // fix up the buf pointer and bytes left
  1606. if ( pnext < pch )
  1607. {
  1608. ASSERT( FALSE );
  1609. *ppBuffer = pch;
  1610. *pBufferSize -= (INT)(pch - pnext);
  1611. }
  1612. }
  1613. IF_DNSDBG( HOSTENT )
  1614. {
  1615. DnsDbg_Hostent(
  1616. "Sablob Hostent:",
  1617. phost,
  1618. (CharSetTarget == DnsCharSetUnicode) );
  1619. }
  1620. //
  1621. // convert to offsets?
  1622. //
  1623. if ( fOffsets )
  1624. {
  1625. Hostent_ConvertToOffsets( phost );
  1626. }
  1627. Failed:
  1628. DNSDBG( TRACE, (
  1629. "Leave SaBlob_CreateHostent() => %p\n",
  1630. phost ));
  1631. return phost;
  1632. }
  1633. //
  1634. // End sablob.c
  1635. //