Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenquery.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS system libraries 00004 * FILE: lib/dnsapi/dnsapi/query.c 00005 * PURPOSE: DNSAPI functions built on the ADNS library. 00006 * PROGRAMER: Art Yerkes 00007 * UPDATE HISTORY: 00008 * 12/15/03 -- Created 00009 */ 00010 00011 #include "precomp.h" 00012 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* DnsQuery **************************** 00017 * Begin a DNS query, and allow the result to be placed in the application 00018 * supplied result pointer. The result can be manipulated with the record 00019 * functions. 00020 * 00021 * Name -- The DNS object to be queried. 00022 * Type -- The type of records to be returned. These are 00023 * listed in windns.h 00024 * Options -- Query options. DNS_QUERY_STANDARD is the base 00025 * state, and every other option takes precedence. 00026 * multiple options can be combined. Listed in 00027 * windns.h 00028 * Servers -- List of alternate servers (optional) 00029 * QueryResultSet -- Pointer to the result pointer that will be filled 00030 * when the response is available. 00031 * Reserved -- Response as it appears on the wire. Optional. 00032 */ 00033 00034 char 00035 *xstrsave(const char *str) 00036 { 00037 char *p; 00038 00039 p = RtlAllocateHeap(RtlGetProcessHeap(), 0, strlen(str) + 1); 00040 00041 if(p) 00042 strcpy(p, str); 00043 00044 return p; 00045 } 00046 00047 DNS_STATUS WINAPI 00048 DnsQuery_A(LPCSTR Name, 00049 WORD Type, 00050 DWORD Options, 00051 PIP4_ARRAY Servers, 00052 PDNS_RECORD *QueryResultSet, 00053 PVOID *Reserved) 00054 { 00055 adns_state astate; 00056 int quflags = 0; 00057 int adns_error; 00058 adns_answer *answer; 00059 LPSTR CurrentName; 00060 unsigned i, CNameLoop; 00061 00062 *QueryResultSet = 0; 00063 00064 switch(Type) 00065 { 00066 case DNS_TYPE_A: 00067 adns_error = adns_init(&astate, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn, 0); 00068 00069 if(adns_error != adns_s_ok) 00070 return DnsIntTranslateAdnsToDNS_STATUS(adns_error); 00071 00072 if (Servers) 00073 { 00074 for(i = 0; i < Servers->AddrCount; i++) 00075 { 00076 adns_addserver(astate, *((struct in_addr *)&Servers->AddrArray[i])); 00077 } 00078 } 00079 00080 /* 00081 * adns doesn't resolve chained CNAME records (a CNAME which points to 00082 * another CNAME pointing to another... pointing to an A record), according 00083 * to a mailing list thread the authors believe that chained CNAME records 00084 * are invalid and the DNS entries should be fixed. That's a nice academic 00085 * standpoint, but there certainly are chained CNAME records out there, 00086 * even some fairly major ones (at the time of this writing 00087 * download.mozilla.org is a chained CNAME). Everyone else seems to resolve 00088 * these fine, so we should too. So we loop here to try to resolve CNAME 00089 * chains ourselves. Of course, there must be a limit to protect against 00090 * CNAME loops. 00091 */ 00092 00093 #define CNAME_LOOP_MAX 16 00094 00095 CurrentName = (LPSTR) Name; 00096 00097 for (CNameLoop = 0; CNameLoop < CNAME_LOOP_MAX; CNameLoop++) 00098 { 00099 adns_error = adns_synchronous(astate, CurrentName, adns_r_addr, quflags, &answer); 00100 00101 if(adns_error != adns_s_ok) 00102 { 00103 adns_finish(astate); 00104 00105 if (CurrentName != Name) 00106 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName); 00107 00108 return DnsIntTranslateAdnsToDNS_STATUS(adns_error); 00109 } 00110 00111 if(answer && answer->rrs.addr) 00112 { 00113 if (CurrentName != Name) 00114 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName); 00115 00116 *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD)); 00117 00118 if (NULL == *QueryResultSet) 00119 { 00120 adns_finish( astate ); 00121 return ERROR_OUTOFMEMORY; 00122 } 00123 00124 (*QueryResultSet)->pNext = NULL; 00125 (*QueryResultSet)->wType = Type; 00126 (*QueryResultSet)->wDataLength = sizeof(DNS_A_DATA); 00127 (*QueryResultSet)->Data.A.IpAddress = answer->rrs.addr->addr.inet.sin_addr.s_addr; 00128 00129 adns_finish(astate); 00130 00131 (*QueryResultSet)->pName = xstrsave( Name ); 00132 00133 return NULL != (*QueryResultSet)->pName ? ERROR_SUCCESS : ERROR_OUTOFMEMORY; 00134 } 00135 00136 if (NULL == answer || adns_s_prohibitedcname != answer->status || NULL == answer->cname) 00137 { 00138 adns_finish(astate); 00139 00140 if (CurrentName != Name) 00141 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName); 00142 00143 return ERROR_FILE_NOT_FOUND; 00144 } 00145 00146 if (CurrentName != Name) 00147 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName); 00148 00149 CurrentName = xstrsave(answer->cname); 00150 00151 if (!CurrentName) 00152 { 00153 adns_finish(astate); 00154 return ERROR_OUTOFMEMORY; 00155 } 00156 } 00157 00158 adns_finish(astate); 00159 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName); 00160 return ERROR_FILE_NOT_FOUND; 00161 00162 default: 00163 return ERROR_OUTOFMEMORY; /* XXX arty: find a better error code. */ 00164 } 00165 } 00166 00167 static PCHAR 00168 DnsWToC(const WCHAR *WideString) 00169 { 00170 int chars = wcstombs(NULL, WideString, 0); 00171 PCHAR out = RtlAllocateHeap(RtlGetProcessHeap(), 0, chars + 1); 00172 00173 wcstombs(out, WideString, chars + 1); 00174 00175 return out; 00176 } 00177 00178 static PWCHAR 00179 DnsCToW(const CHAR *NarrowString) 00180 { 00181 int chars = mbstowcs(NULL, NarrowString, 0); 00182 PWCHAR out = RtlAllocateHeap(RtlGetProcessHeap(), 0, (chars + 1) * sizeof(WCHAR)); 00183 00184 mbstowcs(out, NarrowString, chars + 1); 00185 00186 return out; 00187 } 00188 00189 DNS_STATUS WINAPI 00190 DnsQuery_W(LPCWSTR Name, 00191 WORD Type, 00192 DWORD Options, 00193 PIP4_ARRAY Servers, 00194 PDNS_RECORD *QueryResultSet, 00195 PVOID *Reserved) 00196 { 00197 UINT i; 00198 PCHAR Buffer; 00199 DNS_STATUS Status; 00200 PDNS_RECORD QueryResultWide; 00201 PDNS_RECORD ConvertedRecord = 0, LastRecord = 0; 00202 00203 Buffer = DnsWToC(Name); 00204 00205 Status = DnsQuery_A(Buffer, Type, Options, Servers, &QueryResultWide, Reserved); 00206 00207 while(Status == ERROR_SUCCESS && QueryResultWide) 00208 { 00209 switch(QueryResultWide->wType) 00210 { 00211 case DNS_TYPE_A: 00212 case DNS_TYPE_WKS: 00213 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD)); 00214 ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName); 00215 ConvertedRecord->wType = QueryResultWide->wType; 00216 ConvertedRecord->wDataLength = QueryResultWide->wDataLength; 00217 memcpy(ConvertedRecord, QueryResultWide, QueryResultWide->wDataLength); 00218 break; 00219 00220 case DNS_TYPE_CNAME: 00221 case DNS_TYPE_PTR: 00222 case DNS_TYPE_NS: 00223 case DNS_TYPE_MB: 00224 case DNS_TYPE_MD: 00225 case DNS_TYPE_MF: 00226 case DNS_TYPE_MG: 00227 case DNS_TYPE_MR: 00228 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD)); 00229 ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName); 00230 ConvertedRecord->wType = QueryResultWide->wType; 00231 ConvertedRecord->wDataLength = sizeof(DNS_PTR_DATA); 00232 ConvertedRecord->Data.PTR.pNameHost = (PCHAR)DnsCToW(QueryResultWide->Data.PTR.pNameHost); 00233 break; 00234 00235 case DNS_TYPE_MINFO: 00236 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD)); 00237 ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName); 00238 ConvertedRecord->wType = QueryResultWide->wType; 00239 ConvertedRecord->wDataLength = sizeof(DNS_MINFO_DATA); 00240 ConvertedRecord->Data.MINFO.pNameMailbox = (PCHAR)DnsCToW(QueryResultWide->Data.MINFO.pNameMailbox); 00241 ConvertedRecord->Data.MINFO.pNameErrorsMailbox = (PCHAR)DnsCToW(QueryResultWide->Data.MINFO.pNameErrorsMailbox); 00242 break; 00243 00244 case DNS_TYPE_MX: 00245 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD)); 00246 ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName); 00247 ConvertedRecord->wType = QueryResultWide->wType; 00248 ConvertedRecord->wDataLength = sizeof(DNS_MX_DATA); 00249 ConvertedRecord->Data.MX.pNameExchange = (PCHAR)DnsCToW( QueryResultWide->Data.MX.pNameExchange); 00250 ConvertedRecord->Data.MX.wPreference = QueryResultWide->Data.MX.wPreference; 00251 break; 00252 00253 case DNS_TYPE_HINFO: 00254 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_TXT_DATA) + QueryResultWide->Data.TXT.dwStringCount); 00255 ConvertedRecord->pName = (PCHAR)DnsCToW( QueryResultWide->pName ); 00256 ConvertedRecord->wType = QueryResultWide->wType; 00257 ConvertedRecord->wDataLength = sizeof(DNS_TXT_DATA) + (sizeof(PWCHAR) * QueryResultWide->Data.TXT.dwStringCount); 00258 ConvertedRecord->Data.TXT.dwStringCount = QueryResultWide->Data.TXT.dwStringCount; 00259 00260 for(i = 0; i < ConvertedRecord->Data.TXT.dwStringCount; i++) 00261 ConvertedRecord->Data.TXT.pStringArray[i] = (PCHAR)DnsCToW(QueryResultWide->Data.TXT.pStringArray[i]); 00262 00263 break; 00264 00265 case DNS_TYPE_NULL: 00266 ConvertedRecord = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_NULL_DATA) + QueryResultWide->Data.Null.dwByteCount); 00267 ConvertedRecord->pName = (PCHAR)DnsCToW(QueryResultWide->pName); 00268 ConvertedRecord->wType = QueryResultWide->wType; 00269 ConvertedRecord->wDataLength = sizeof(DNS_NULL_DATA) + QueryResultWide->Data.Null.dwByteCount; 00270 ConvertedRecord->Data.Null.dwByteCount = QueryResultWide->Data.Null.dwByteCount; 00271 memcpy(&ConvertedRecord->Data.Null.Data, &QueryResultWide->Data.Null.Data, QueryResultWide->Data.Null.dwByteCount); 00272 break; 00273 } 00274 00275 if(LastRecord) 00276 { 00277 LastRecord->pNext = ConvertedRecord; 00278 LastRecord = LastRecord->pNext; 00279 } 00280 else 00281 { 00282 LastRecord = *QueryResultSet = ConvertedRecord; 00283 } 00284 } 00285 00286 LastRecord->pNext = 0; 00287 00288 /* The name */ 00289 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 00290 00291 return Status; 00292 } 00293 00294 DNS_STATUS WINAPI 00295 DnsQuery_UTF8(LPCSTR Name, 00296 WORD Type, 00297 DWORD Options, 00298 PIP4_ARRAY Servers, 00299 PDNS_RECORD *QueryResultSet, 00300 PVOID *Reserved) 00301 { 00302 UNIMPLEMENTED; 00303 return ERROR_OUTOFMEMORY; 00304 } 00305 00306 void 00307 DnsIntFreeRecordList(PDNS_RECORD ToDelete) 00308 { 00309 UINT i; 00310 PDNS_RECORD next = 0; 00311 00312 while(ToDelete) 00313 { 00314 if(ToDelete->pName) 00315 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete->pName); 00316 00317 switch(ToDelete->wType) 00318 { 00319 case DNS_TYPE_CNAME: 00320 case DNS_TYPE_PTR: 00321 case DNS_TYPE_NS: 00322 case DNS_TYPE_MB: 00323 case DNS_TYPE_MD: 00324 case DNS_TYPE_MF: 00325 case DNS_TYPE_MG: 00326 case DNS_TYPE_MR: 00327 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete->Data.PTR.pNameHost); 00328 break; 00329 00330 case DNS_TYPE_MINFO: 00331 case DNS_TYPE_MX: 00332 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete->Data.MX.pNameExchange); 00333 break; 00334 00335 case DNS_TYPE_HINFO: 00336 for(i = 0; i < ToDelete->Data.TXT.dwStringCount; i++) 00337 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete->Data.TXT.pStringArray[i]); 00338 00339 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete->Data.TXT.pStringArray); 00340 break; 00341 } 00342 00343 next = ToDelete->pNext; 00344 RtlFreeHeap(RtlGetProcessHeap(), 0, ToDelete); 00345 ToDelete = next; 00346 } 00347 } Generated on Sun May 27 2012 04:17:02 for ReactOS by
1.7.6.1
|