1113 lines
21 KiB
C
1113 lines
21 KiB
C
/*++
|
||
|
||
Copyright (c) 1997-2001 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
rrcopy.c
|
||
|
||
Abstract:
|
||
|
||
Domain Name System (DNS) Library
|
||
|
||
Copy resource record routines.
|
||
|
||
Author:
|
||
|
||
Jim Gilroy (jamesg) February, 1997
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "local.h"
|
||
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
ARecordCopy(
|
||
IN PDNS_RECORD pRR,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy A record data from packet.
|
||
|
||
Arguments:
|
||
|
||
pRR - RR to copy
|
||
|
||
Return Value:
|
||
|
||
Ptr to new record if successful.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD precord;
|
||
|
||
precord = Dns_AllocateRecord( sizeof(IP_ADDRESS) );
|
||
if ( !precord )
|
||
{
|
||
return NULL;
|
||
}
|
||
precord->Data.A.IpAddress = pRR->Data.A.IpAddress;
|
||
|
||
return precord;
|
||
}
|
||
|
||
|
||
PDNS_RECORD
|
||
PtrRecordCopy(
|
||
IN PDNS_RECORD pRR,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy PTR compatible record.
|
||
Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
|
||
|
||
Arguments:
|
||
|
||
pRR - RR to copy
|
||
|
||
Return Value:
|
||
|
||
Ptr to new record if successful.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD precord;
|
||
|
||
precord = Dns_AllocateRecord( sizeof( DNS_PTR_DATA ) );
|
||
if ( !precord )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
precord->Data.PTR.pNameHost = Dns_NameCopyAllocate(
|
||
pRR->Data.PTR.pNameHost,
|
||
0, // length unknown
|
||
CharSetIn,
|
||
CharSetOut
|
||
);
|
||
if ( ! precord->Data.PTR.pNameHost )
|
||
{
|
||
FREE_HEAP( precord );
|
||
return NULL;
|
||
}
|
||
|
||
FLAG_FreeData( precord ) = TRUE;
|
||
|
||
return precord;
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
SoaRecordCopy(
|
||
IN PDNS_RECORD pRR,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy SOA record.
|
||
|
||
Arguments:
|
||
|
||
pRR - RR to copy
|
||
|
||
Return Value:
|
||
|
||
Ptr to new record if successful.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD precord;
|
||
LPSTR pname;
|
||
|
||
precord = Dns_AllocateRecord( sizeof( DNS_SOA_DATA ) );
|
||
if ( !precord )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// copy integer data
|
||
//
|
||
|
||
memcpy(
|
||
& precord->Data.SOA.dwSerialNo,
|
||
& pRR->Data.SOA.dwSerialNo,
|
||
SIZEOF_SOA_FIXED_DATA );
|
||
|
||
//
|
||
// create copy of primary and admin
|
||
//
|
||
|
||
pname = Dns_NameCopyAllocate(
|
||
pRR->Data.SOA.pNamePrimaryServer,
|
||
0, // length unknown
|
||
CharSetIn,
|
||
CharSetOut
|
||
);
|
||
if ( !pname )
|
||
{
|
||
FREE_HEAP( precord );
|
||
return NULL;
|
||
}
|
||
precord->Data.SOA.pNamePrimaryServer = pname;
|
||
|
||
pname = Dns_NameCopyAllocate(
|
||
pRR->Data.SOA.pNameAdministrator,
|
||
0, // length unknown
|
||
CharSetIn,
|
||
CharSetOut
|
||
);
|
||
if ( !pname )
|
||
{
|
||
FREE_HEAP( precord->Data.SOA.pNamePrimaryServer );
|
||
FREE_HEAP( precord );
|
||
return NULL;
|
||
}
|
||
precord->Data.SOA.pNameAdministrator = pname;
|
||
|
||
FLAG_FreeData( precord ) = TRUE;
|
||
|
||
return precord;
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
MinfoRecordCopy(
|
||
IN PDNS_RECORD pRR,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy MINFO and RP records from wire.
|
||
|
||
Arguments:
|
||
|
||
pRR - RR to copy
|
||
|
||
Return Value:
|
||
|
||
Ptr to new record if successful.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD precord;
|
||
LPSTR pname;
|
||
|
||
precord = Dns_AllocateRecord( sizeof( DNS_MINFO_DATA ) );
|
||
if ( !precord )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// create copy of name fields
|
||
//
|
||
|
||
pname = Dns_NameCopyAllocate(
|
||
pRR->Data.MINFO.pNameMailbox,
|
||
0, // length unknown
|
||
CharSetIn,
|
||
CharSetOut
|
||
);
|
||
if ( !pname )
|
||
{
|
||
FREE_HEAP( precord );
|
||
return NULL;
|
||
}
|
||
precord->Data.MINFO.pNameMailbox = pname;
|
||
|
||
pname = Dns_NameCopyAllocate(
|
||
pRR->Data.MINFO.pNameErrorsMailbox,
|
||
0, // length unknown
|
||
CharSetIn,
|
||
CharSetOut
|
||
);
|
||
if ( !pname )
|
||
{
|
||
FREE_HEAP( precord->Data.MINFO.pNameMailbox );
|
||
FREE_HEAP( precord );
|
||
return NULL;
|
||
}
|
||
precord->Data.MINFO.pNameErrorsMailbox = pname;
|
||
|
||
FLAG_FreeData( precord ) = TRUE;
|
||
|
||
return precord;
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
MxRecordCopy(
|
||
IN PDNS_RECORD pRR,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy MX compatible record from wire.
|
||
Includes: MX, RT, AFSDB
|
||
|
||
Arguments:
|
||
|
||
pRR - RR to copy
|
||
|
||
Return Value:
|
||
|
||
Ptr to new record if successful.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD precord;
|
||
PCHAR pname;
|
||
|
||
precord = Dns_AllocateRecord( sizeof( DNS_MX_DATA ) );
|
||
if ( !precord )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
// MX preference value
|
||
// RT preference
|
||
// AFSDB subtype
|
||
|
||
precord->Data.MX.wPreference = pRR->Data.MX.wPreference;
|
||
|
||
// MX exchange
|
||
// RT exchange
|
||
// AFSDB hostname
|
||
// - name immediately follows MX data struct
|
||
|
||
pname = Dns_NameCopyAllocate(
|
||
pRR->Data.MX.pNameExchange,
|
||
0, // length unknown
|
||
CharSetIn,
|
||
CharSetOut
|
||
);
|
||
if ( !pname )
|
||
{
|
||
FREE_HEAP( precord );
|
||
return NULL;
|
||
}
|
||
precord->Data.MX.pNameExchange = pname;
|
||
|
||
FLAG_FreeData( precord ) = TRUE;
|
||
|
||
return precord;
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
TxtRecordCopy(
|
||
IN PDNS_RECORD pRR,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy TXT compatible records.
|
||
Includes: TXT, X25, HINFO, ISDN
|
||
|
||
Arguments:
|
||
|
||
pRR - RR to copy
|
||
|
||
Return Value:
|
||
|
||
Ptr to new record if successful.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD precord;
|
||
WORD bufLength = sizeof( DNS_TXT_DATA );
|
||
INT count = pRR->Data.TXT.dwStringCount;
|
||
LPSTR * ppstringIn;
|
||
LPSTR * ppstringNew;
|
||
LPSTR pstring;
|
||
|
||
bufLength += (WORD)(sizeof(LPSTR) * count);
|
||
|
||
precord = Dns_AllocateRecord( bufLength );
|
||
if ( !precord )
|
||
{
|
||
return NULL;
|
||
}
|
||
precord->Data.TXT.dwStringCount = 0;
|
||
|
||
//
|
||
// copy each string
|
||
// - first string written immediately after string ptr list
|
||
// - each string written immediately after previous
|
||
//
|
||
|
||
ppstringIn = (LPSTR *) pRR->Data.TXT.pStringArray;
|
||
ppstringNew = (LPSTR *) precord->Data.TXT.pStringArray;
|
||
|
||
FLAG_FreeData( precord ) = TRUE;
|
||
|
||
while ( count-- )
|
||
{
|
||
pstring = Dns_StringCopyAllocate(
|
||
*ppstringIn,
|
||
0, // length unknown
|
||
CharSetIn,
|
||
CharSetOut
|
||
);
|
||
if ( ! pstring )
|
||
{
|
||
Dns_RecordFree( precord );
|
||
return NULL;
|
||
}
|
||
*ppstringNew = pstring;
|
||
|
||
precord->Data.TXT.dwStringCount += 1;
|
||
|
||
ppstringIn++;
|
||
ppstringNew++;
|
||
}
|
||
|
||
return precord;
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
FlatRecordCopy(
|
||
IN PDNS_RECORD pRR,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy flat data compatible record.
|
||
Includes: AAAA
|
||
|
||
Arguments:
|
||
|
||
pRR - RR to copy
|
||
|
||
Return Value:
|
||
|
||
Ptr to new record if successful.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD precord;
|
||
|
||
//
|
||
// allocate given datalength
|
||
//
|
||
|
||
precord = Dns_AllocateRecord( pRR->wDataLength );
|
||
if ( !precord )
|
||
{
|
||
return( NULL );
|
||
}
|
||
|
||
//
|
||
// flat copy of data
|
||
//
|
||
|
||
memcpy(
|
||
& precord->Data,
|
||
& pRR->Data,
|
||
pRR->wDataLength );
|
||
|
||
return( precord );
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
SrvRecordCopy(
|
||
IN PDNS_RECORD pRR,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy SRV compatible record from wire.
|
||
Includes: SRV, RT, AFSDB
|
||
|
||
Arguments:
|
||
|
||
pRR - RR to copy
|
||
|
||
Return Value:
|
||
|
||
Ptr to new record if successful.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD precord;
|
||
PCHAR pname;
|
||
|
||
precord = Dns_AllocateRecord( sizeof( DNS_SRV_DATA ) );
|
||
if ( !precord )
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
// copy integer data
|
||
|
||
precord->Data.SRV.wPriority = pRR->Data.SRV.wPriority;
|
||
precord->Data.SRV.wWeight = pRR->Data.SRV.wWeight;
|
||
precord->Data.SRV.wPort = pRR->Data.SRV.wPort;
|
||
|
||
// copy target name
|
||
|
||
pname = Dns_NameCopyAllocate(
|
||
pRR->Data.SRV.pNameTarget,
|
||
0, // length unknown
|
||
CharSetIn,
|
||
CharSetOut
|
||
);
|
||
if ( !pname )
|
||
{
|
||
FREE_HEAP( precord );
|
||
return NULL;
|
||
}
|
||
precord->Data.SRV.pNameTarget = pname;
|
||
|
||
SET_FREE_DATA( precord );
|
||
|
||
return precord;
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
AtmaRecordCopy(
|
||
IN PDNS_RECORD pRR,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy Atma compatible record from wire.
|
||
Includes:
|
||
|
||
Arguments:
|
||
|
||
pRR - RR to copy
|
||
|
||
Return Value:
|
||
|
||
Ptr to new record if successful.
|
||
NULL on failure.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD precord;
|
||
WORD bufLength;
|
||
|
||
//
|
||
// determine required buffer length and allocate
|
||
//
|
||
|
||
bufLength = sizeof(DNS_ATMA_DATA) + DNS_ATMA_MAX_ADDR_LENGTH ;
|
||
|
||
precord = Dns_AllocateRecord( bufLength );
|
||
if ( !precord )
|
||
{
|
||
return( NULL );
|
||
}
|
||
|
||
// copy integer data
|
||
|
||
precord->Data.ATMA.AddressType = pRR->Data.ATMA.AddressType;
|
||
|
||
if ( precord->Data.ATMA.AddressType == DNS_ATMA_FORMAT_E164 )
|
||
{
|
||
precord->wDataLength = (WORD) strlen(pRR->Data.ATMA.Address);
|
||
|
||
if ( precord->wDataLength > DNS_ATMA_MAX_ADDR_LENGTH )
|
||
{
|
||
precord->wDataLength = DNS_ATMA_MAX_ADDR_LENGTH;
|
||
}
|
||
strncpy(
|
||
precord->Data.ATMA.Address,
|
||
pRR->Data.ATMA.Address,
|
||
precord->wDataLength );
|
||
}
|
||
else
|
||
{
|
||
precord->wDataLength = DNS_ATMA_MAX_ADDR_LENGTH;
|
||
|
||
memcpy(
|
||
precord->Data.ATMA.Address,
|
||
pRR->Data.ATMA.Address,
|
||
precord->wDataLength );
|
||
}
|
||
|
||
return( precord );
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// RR copy jump table
|
||
//
|
||
|
||
RR_COPY_FUNCTION RRCopyTable[] =
|
||
{
|
||
NULL, // ZERO
|
||
ARecordCopy, // A
|
||
PtrRecordCopy, // NS
|
||
PtrRecordCopy, // MD
|
||
PtrRecordCopy, // MF
|
||
PtrRecordCopy, // CNAME
|
||
SoaRecordCopy, // SOA
|
||
PtrRecordCopy, // MB
|
||
PtrRecordCopy, // MG
|
||
PtrRecordCopy, // MR
|
||
NULL, // NULL
|
||
NULL, //WksRecordCopy, // WKS
|
||
PtrRecordCopy, // PTR
|
||
TxtRecordCopy, // HINFO
|
||
MinfoRecordCopy, // MINFO
|
||
MxRecordCopy, // MX
|
||
TxtRecordCopy, // TXT
|
||
MinfoRecordCopy, // RP
|
||
MxRecordCopy, // AFSDB
|
||
TxtRecordCopy, // X25
|
||
TxtRecordCopy, // ISDN
|
||
MxRecordCopy, // RT
|
||
NULL, // NSAP
|
||
NULL, // NSAPPTR
|
||
NULL, // SIG
|
||
NULL, // KEY
|
||
NULL, // PX
|
||
NULL, // GPOS
|
||
FlatRecordCopy, // AAAA
|
||
NULL, // LOC
|
||
NULL, // NXT
|
||
NULL, // EID
|
||
NULL, // NIMLOC
|
||
SrvRecordCopy, // SRV
|
||
AtmaRecordCopy, // ATMA
|
||
NULL, // NAPTR
|
||
NULL, // KX
|
||
NULL, // CERT
|
||
NULL, // A6
|
||
NULL, // DNAME
|
||
NULL, // SINK
|
||
NULL, // OPT
|
||
NULL, // 42
|
||
NULL, // 43
|
||
NULL, // 44
|
||
NULL, // 45
|
||
NULL, // 46
|
||
NULL, // 47
|
||
NULL, // 48
|
||
|
||
//
|
||
// NOTE: last type indexed by type ID MUST be set
|
||
// as MAX_SELF_INDEXED_TYPE #define in record.h
|
||
// (see note above in record info table)
|
||
|
||
//
|
||
// Pseudo record types
|
||
//
|
||
|
||
NULL, // TKEY
|
||
NULL, // TSIG
|
||
|
||
//
|
||
// MS only types
|
||
//
|
||
|
||
FlatRecordCopy, // WINS
|
||
NULL, // WINSR
|
||
|
||
};
|
||
|
||
|
||
|
||
|
||
//
|
||
// Generic copy functions
|
||
//
|
||
|
||
PDNS_RECORD
|
||
privateRecordCopy(
|
||
IN PDNS_RECORD pRecord,
|
||
IN PDNS_RECORD pPrevIn,
|
||
IN PDNS_RECORD pPrevCopy,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy record to as member of record set.
|
||
|
||
The previous records allow suppression of owner name copy when copying
|
||
RR set.
|
||
|
||
Arguments:
|
||
|
||
pRecord - record to copy
|
||
|
||
pPrevIn - previous incoming record copied
|
||
|
||
pPrevCopy - copy of pPrevIn in new set
|
||
|
||
CharSetIn - input record character set; OPTIONAL
|
||
if zero, pRecord must have CharSet;
|
||
if non-zero, pRecord must have zero or matching CharSet;
|
||
allow this to be specified independently of pRecord, to handle
|
||
conversion of user supplied records, which we do not want to
|
||
modify
|
||
|
||
CharSetOut - desired record character set
|
||
|
||
Return Value:
|
||
|
||
Ptr to copy of record in desired character set.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD prr;
|
||
WORD index;
|
||
DNS_CHARSET recordCharSet;
|
||
|
||
DNSDBG( TRACE, ( "privateRecordCopy( %p )\n", pRecord ));
|
||
|
||
//
|
||
// input character set
|
||
// allow specification of input character set to handle case
|
||
// of user created records, but if input record has a set
|
||
// then it's assumed to be valid
|
||
// so validity check:
|
||
// - CharSetIn == 0 => use record's != 0 set
|
||
// - record's set == 0 => use CharSetIn != 0
|
||
// - CharSetIn == record's set
|
||
//
|
||
|
||
recordCharSet = RECORD_CHARSET( pRecord );
|
||
|
||
if ( recordCharSet )
|
||
{
|
||
ASSERT( CharSetIn == 0 || CharSetIn == recordCharSet );
|
||
CharSetIn = recordCharSet;
|
||
}
|
||
else // record has no charset
|
||
{
|
||
if ( CharSetIn == 0 )
|
||
{
|
||
ASSERT( FALSE );
|
||
goto Failed;
|
||
}
|
||
}
|
||
|
||
//
|
||
// copy record data
|
||
//
|
||
|
||
if ( pRecord->wDataLength != 0 )
|
||
{
|
||
index = INDEX_FOR_TYPE( pRecord->wType );
|
||
DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
|
||
|
||
if ( !index || !RRCopyTable[ index ] )
|
||
{
|
||
DNS_PRINT((
|
||
"WARNING: No copy routine for type = %d\n"
|
||
"\tdoing flat copy of record at %p\n",
|
||
pRecord->wType,
|
||
pRecord ));
|
||
prr = FlatRecordCopy(
|
||
pRecord,
|
||
CharSetIn,
|
||
CharSetOut );
|
||
}
|
||
else
|
||
{
|
||
prr = RRCopyTable[ index ](
|
||
pRecord,
|
||
CharSetIn,
|
||
CharSetOut );
|
||
}
|
||
}
|
||
else // no data record
|
||
{
|
||
prr = FlatRecordCopy(
|
||
pRecord,
|
||
CharSetIn,
|
||
CharSetOut );
|
||
}
|
||
|
||
if ( !prr )
|
||
{
|
||
goto Failed;
|
||
}
|
||
|
||
//
|
||
// copy record structure fields
|
||
// - type
|
||
// - TTL
|
||
// - flags
|
||
//
|
||
|
||
prr->dwTtl = pRecord->dwTtl;
|
||
prr->wType = pRecord->wType;
|
||
|
||
prr->Flags.S.Section = pRecord->Flags.S.Section;
|
||
prr->Flags.S.Delete = pRecord->Flags.S.Delete;
|
||
prr->Flags.S.CharSet = CharSetOut;
|
||
|
||
//
|
||
// copy name
|
||
//
|
||
|
||
if ( pRecord->pName )
|
||
{
|
||
//
|
||
// - if incoming name has FreeOwner set, then always copy
|
||
// as never know when incoming set will be tossed
|
||
//
|
||
// - then check if incoming name same as previous incoming
|
||
// name in which case we can use previous copied name
|
||
//
|
||
// - otherwise full copy of name
|
||
//
|
||
|
||
if ( !FLAG_FreeOwner( pRecord ) &&
|
||
pPrevIn && pPrevCopy &&
|
||
pRecord->pName == pPrevIn->pName )
|
||
{
|
||
prr->pName = pPrevCopy->pName;
|
||
}
|
||
else
|
||
{
|
||
prr->pName = Dns_NameCopyAllocate(
|
||
pRecord->pName,
|
||
0, // unknown length
|
||
CharSetIn,
|
||
CharSetOut
|
||
);
|
||
if ( !prr->pName )
|
||
{
|
||
FREE_HEAP( prr );
|
||
goto Failed;
|
||
}
|
||
FLAG_FreeOwner( prr ) = TRUE;
|
||
}
|
||
}
|
||
|
||
DNSDBG( TRACE, (
|
||
"Leaving privateRecordCopy(%p) = %p.\n",
|
||
pRecord,
|
||
prr ));
|
||
return( prr );
|
||
|
||
|
||
Failed:
|
||
|
||
DNSDBG( TRACE, (
|
||
"privateRecordCopy(%p) failed\n",
|
||
pRecord ));
|
||
return( NULL );
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
WINAPI
|
||
Dns_RecordCopyEx(
|
||
IN PDNS_RECORD pRecord,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy record.
|
||
|
||
Arguments:
|
||
|
||
pRecord - record to copy
|
||
|
||
CharSetIn - incoming record's character set
|
||
|
||
CharSetOut -- char set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to copy of record in desired character set.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
|
||
DNSDBG( TRACE, ( "Dns_RecordCopyEx( %p )\n", pRecord ));
|
||
|
||
//
|
||
// call private copy routine
|
||
// - set optional ptrs to cause full owner name copy
|
||
//
|
||
|
||
return privateRecordCopy(
|
||
pRecord,
|
||
NULL,
|
||
NULL,
|
||
CharSetIn,
|
||
CharSetOut );
|
||
}
|
||
|
||
|
||
PDNS_RECORD
|
||
WINAPI
|
||
Dns_RecordCopy_W(
|
||
IN PDNS_RECORD pRecord
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy record.
|
||
|
||
Arguments:
|
||
|
||
pRecord - unicode record to copy to unicode
|
||
|
||
Return Value:
|
||
|
||
Ptr to copy of record in desired character set.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
DNSDBG( TRACE, ( "Dns_RecordCopy( %p )\n", pRecord ));
|
||
|
||
//
|
||
// call private copy routine
|
||
// - set optional ptrs to cause full owner name copy
|
||
//
|
||
|
||
return privateRecordCopy(
|
||
pRecord,
|
||
NULL,
|
||
NULL,
|
||
DnsCharSetUnicode,
|
||
DnsCharSetUnicode );
|
||
}
|
||
|
||
|
||
PDNS_RECORD
|
||
WINAPI
|
||
Dns_RecordCopy_A(
|
||
IN PDNS_RECORD pRecord
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy record.
|
||
|
||
Arguments:
|
||
|
||
pRecord - ANSI record to copy to ANSI
|
||
|
||
Return Value:
|
||
|
||
Ptr to copy of record in desired character set.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
DNSDBG( TRACE, ( "Dns_RecordCopy( %p )\n", pRecord ));
|
||
|
||
//
|
||
// call private copy routine
|
||
// - set optional ptrs to cause full owner name copy
|
||
//
|
||
|
||
return privateRecordCopy(
|
||
pRecord,
|
||
NULL,
|
||
NULL,
|
||
DnsCharSetAnsi,
|
||
DnsCharSetAnsi );
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Record set copy
|
||
//
|
||
|
||
PDNS_RECORD
|
||
Dns_RecordSetCopyEx(
|
||
IN PDNS_RECORD pRR,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Copy record set, converting to UTF8 if necessary.
|
||
|
||
Arguments:
|
||
|
||
pRR - incoming record set
|
||
|
||
CharSetIn - incoming record's character set
|
||
|
||
CharSetOut -- char set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to new record set, if successful.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
return Dns_RecordListCopyEx(
|
||
pRR,
|
||
0, // no screening flags
|
||
CharSetIn,
|
||
CharSetOut
|
||
);
|
||
}
|
||
|
||
|
||
|
||
PDNS_RECORD
|
||
Dns_RecordListCopyEx(
|
||
IN PDNS_RECORD pRR,
|
||
IN DWORD ScreenFlag,
|
||
IN DNS_CHARSET CharSetIn,
|
||
IN DNS_CHARSET CharSetOut
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Screened copy of record set.
|
||
|
||
Arguments:
|
||
|
||
pRR - incoming record set
|
||
|
||
ScreenFlag - flag with record screening parameters
|
||
|
||
CharSetIn - incoming record's character set
|
||
|
||
CharSetOut -- char set for resulting record
|
||
|
||
Return Value:
|
||
|
||
Ptr to new record set, if successful.
|
||
NULL on error.
|
||
|
||
--*/
|
||
{
|
||
PDNS_RECORD prr; // most recent copied
|
||
PDNS_RECORD prevIn; // previous in set being copied
|
||
DNS_RRSET rrset;
|
||
|
||
DNSDBG( TRACE, (
|
||
"Dns_RecordListCopyEx( %p, %08x, %d, %d )\n",
|
||
pRR,
|
||
ScreenFlag,
|
||
CharSetIn,
|
||
CharSetOut ));
|
||
|
||
// init copy rrset
|
||
|
||
DNS_RRSET_INIT( rrset );
|
||
|
||
//
|
||
// loop through RR set, add records to either match or diff sets
|
||
//
|
||
|
||
prevIn = NULL;
|
||
prr = NULL;
|
||
|
||
while ( pRR )
|
||
{
|
||
// skip copy on record not matching copy criteria
|
||
|
||
if ( ScreenFlag )
|
||
{
|
||
if ( !Dns_ScreenRecord( pRR, ScreenFlag ) )
|
||
{
|
||
pRR = pRR->pNext;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
prr = privateRecordCopy(
|
||
pRR,
|
||
prevIn,
|
||
prr, // previous rr copied
|
||
CharSetIn,
|
||
CharSetOut
|
||
);
|
||
if ( prr )
|
||
{
|
||
DNS_RRSET_ADD( rrset, prr );
|
||
prevIn = pRR;
|
||
pRR = pRR->pNext;
|
||
continue;
|
||
}
|
||
|
||
// if fail, toss entire new set
|
||
|
||
Dns_RecordListFree( rrset.pFirstRR );
|
||
return( NULL );
|
||
}
|
||
|
||
return( rrset.pFirstRR );
|
||
}
|
||
|
||
//
|
||
// End rrcopy.c
|
||
//
|