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.
228 lines
5.2 KiB
228 lines
5.2 KiB
#include <windows.h>
|
|
#include <svcguid.h>
|
|
#include <winsock2.h>
|
|
#include <dbgtrace.h>
|
|
#include <dnsapi.h>
|
|
#include <dbgtrace.h>
|
|
#include <cpool.h>
|
|
#include <address.hxx>
|
|
#include <rwnew.h>
|
|
#include <dnsreci.h>
|
|
#include <listmacr.h>
|
|
|
|
//shamelessy stolen from the NT winsock code....
|
|
|
|
GUID HostnameGuid = SVCID_INET_HOSTADDRBYNAME;
|
|
GUID AddressGuid = SVCID_INET_HOSTADDRBYINETSTRING;
|
|
GUID IANAGuid = SVCID_INET_SERVICEBYNAME;
|
|
//
|
|
// Utility to turn a list of offsets into a list of addresses. Used
|
|
// to convert structures returned as BLOBs.
|
|
//
|
|
|
|
VOID
|
|
FixList(PCHAR ** List, PCHAR Base)
|
|
{
|
|
if(*List)
|
|
{
|
|
PCHAR * Addr;
|
|
|
|
Addr = *List = (PCHAR *)( ((ULONG_PTR)*List + Base) );
|
|
while(*Addr)
|
|
{
|
|
*Addr = (PCHAR)(((ULONG_PTR)*Addr + Base));
|
|
Addr++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Routine to convert a hostent returned in a BLOB to one with
|
|
// usable pointers. The structure is converted in-place.
|
|
//
|
|
VOID
|
|
UnpackHostEnt(struct hostent * hostent)
|
|
{
|
|
PCHAR pch;
|
|
|
|
pch = (PCHAR)hostent;
|
|
|
|
if(hostent->h_name)
|
|
{
|
|
hostent->h_name = (PCHAR)((ULONG_PTR)hostent->h_name + pch);
|
|
}
|
|
FixList(&hostent->h_aliases, pch);
|
|
FixList(&hostent->h_addr_list, pch);
|
|
}
|
|
//
|
|
// The protocol restrictions list for all emulation operations. This should
|
|
// limit the invoked providers to the set that know about hostents and
|
|
// servents. If not, then the special SVCID_INET GUIDs should take care
|
|
// of the remainder.
|
|
//
|
|
AFPROTOCOLS afp[2] = {
|
|
{AF_INET, IPPROTO_UDP},
|
|
{AF_INET, IPPROTO_TCP}
|
|
};
|
|
|
|
LPBLOB GetGostByNameI(PCHAR pResults,
|
|
DWORD dwLength,
|
|
LPSTR lpszName,
|
|
LPGUID lpType,
|
|
LPSTR * lppName)
|
|
{
|
|
PWSAQUERYSETA pwsaq = (PWSAQUERYSETA)pResults;
|
|
int err;
|
|
HANDLE hRnR;
|
|
LPBLOB pvRet = 0;
|
|
INT Err = 0;
|
|
|
|
//
|
|
// create the query
|
|
//
|
|
ZeroMemory(pwsaq,sizeof(*pwsaq));
|
|
pwsaq->dwSize = sizeof(*pwsaq);
|
|
pwsaq->lpszServiceInstanceName = lpszName;
|
|
pwsaq->lpServiceClassId = lpType;
|
|
pwsaq->dwNameSpace = NS_ALL;
|
|
pwsaq->dwNumberOfProtocols = 2;
|
|
pwsaq->lpafpProtocols = &afp[0];
|
|
|
|
//don't go though the cache
|
|
err = WSALookupServiceBeginA(pwsaq,
|
|
LUP_RETURN_BLOB | LUP_RETURN_NAME | LUP_FLUSHCACHE,
|
|
&hRnR);
|
|
|
|
if(err == NO_ERROR)
|
|
{
|
|
//
|
|
// The query was accepted, so execute it via the Next call.
|
|
//
|
|
err = WSALookupServiceNextA(
|
|
hRnR,
|
|
0,
|
|
&dwLength,
|
|
pwsaq);
|
|
//
|
|
// if NO_ERROR was returned and a BLOB is present, this
|
|
// worked, just return the requested information. Otherwise,
|
|
// invent an error or capture the transmitted one.
|
|
//
|
|
|
|
if(err == NO_ERROR)
|
|
{
|
|
if(pvRet = pwsaq->lpBlob)
|
|
{
|
|
if(lppName)
|
|
{
|
|
*lppName = pwsaq->lpszServiceInstanceName;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
err = WSANO_DATA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// WSALookupServiceEnd clobbers LastError so save
|
|
// it before closing the handle.
|
|
//
|
|
|
|
err = GetLastError();
|
|
}
|
|
WSALookupServiceEnd(hRnR);
|
|
|
|
//
|
|
// if an error happened, stash the value in LastError
|
|
//
|
|
|
|
if(err != NO_ERROR)
|
|
{
|
|
SetLastError(err);
|
|
}
|
|
}
|
|
return(pvRet);
|
|
}
|
|
|
|
|
|
struct hostent FAR * GetHostByName(PCHAR Buffer, DWORD BuffSize, DWORD dwFlags, char * HostName)
|
|
{
|
|
struct hostent * hent = NULL;
|
|
LPBLOB pBlob = NULL;
|
|
|
|
pBlob = GetGostByNameI(Buffer, BuffSize, HostName, &HostnameGuid, 0);
|
|
|
|
if(pBlob)
|
|
{
|
|
hent = (struct hostent *) pBlob;
|
|
UnpackHostEnt(hent);
|
|
}
|
|
else
|
|
{
|
|
if(GetLastError() == WSASERVICE_NOT_FOUND)
|
|
{
|
|
SetLastError(WSAHOST_NOT_FOUND);
|
|
}
|
|
}
|
|
return hent;
|
|
}
|
|
|
|
|
|
|
|
BOOL GetIpAddressFromDns(char * HostName, PSMTPDNS_RECS pDnsRec, DWORD Index)
|
|
{
|
|
TraceFunctEnter("GetIpAddressFromDns");
|
|
|
|
PDNS_RECORD pDnsRecord = NULL;
|
|
MXIPLIST_ENTRY * pEntry = NULL;
|
|
PDNS_RECORD pTempDnsRecord;
|
|
DNS_STATUS DnsStatus = 0;
|
|
DWORD Error = NO_ERROR;
|
|
BOOL fReturn = TRUE;
|
|
|
|
DnsStatus = DnsQuery_A(HostName, DNS_TYPE_A, DNS_QUERY_BYPASS_CACHE, NULL, &pDnsRecord, NULL);
|
|
|
|
pTempDnsRecord = pDnsRecord;
|
|
|
|
while ( pTempDnsRecord )
|
|
{
|
|
if(pTempDnsRecord->wType == DNS_TYPE_A)
|
|
{
|
|
pEntry = new MXIPLIST_ENTRY;
|
|
if(pEntry != NULL)
|
|
{
|
|
pDnsRec->DnsArray[Index]->NumEntries++;
|
|
pEntry->IpAddress = pTempDnsRecord->Data.A.ipAddress;
|
|
InsertTailList(&pDnsRec->DnsArray[Index]->IpListHead, &pEntry->ListEntry);
|
|
}
|
|
else
|
|
{
|
|
fReturn = FALSE;
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pTempDnsRecord = pTempDnsRecord->pNext;
|
|
}
|
|
|
|
DnsFreeRRSet( pDnsRecord, TRUE );
|
|
|
|
if(Error)
|
|
{
|
|
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
TraceFunctLeave();
|
|
return fReturn;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|