Skip to content

Commit 757f093

Browse files
Fea, Qt 6 适配 Windows 7 所需改动(添加 DnsQueryEx, DnsCancelQuery)
1 parent b8b454f commit 757f093

File tree

6 files changed

+623
-1
lines changed

6 files changed

+623
-1
lines changed

ThunksList.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@
209209
| SymSetSearchPathW | 调用SymSetSearchPath。
210210
| SymGetSearchPathW | 调用SymGetSearchPath。
211211

212+
## Dnsapi.dll
213+
| 函数 | Fallback
214+
| ---- | -----------
215+
| DnsQueryEx | 调用DnsQuery_W。
216+
| DnsCancelQuery | 内部实现。
217+
212218
## dwmapi.dll
213219
| 函数 | Fallback
214220
| ---- | -----------

src/Thunks/YY_Thunks.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ YY-Thunks支持的控制宏:
3535
_APPLY(d3d11, "d3d11" , 0 ) \
3636
_APPLY(d3d12, "d3d12" , 0 ) \
3737
_APPLY(dbghelp, "dbghelp" , USING_UNSAFE_LOAD ) \
38+
_APPLY(dnsapi, "dnsapi" , 0 ) \
3839
_APPLY(dxgi, "dxgi" , 0 ) \
3940
_APPLY(dwrite, "dwrite" , 0 ) \
4041
_APPLY(dxva2, "dxva2" , 0 ) \

src/Thunks/dnsapi.hpp

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
#if (YY_Thunks_Target < __WindowsNT6_2)
2+
#include <windns.h>
3+
#endif
4+
5+
#if (YY_Thunks_Target < __WindowsNT6_2) && !defined(__Comment_Lib_dnsapi)
6+
#define __Comment_Lib_dnsapi
7+
#pragma comment(lib, "Dnsapi.lib")
8+
#endif
9+
10+
#if defined(YY_Thunks_Implemented) && (YY_Thunks_Target < __WindowsNT6_2)
11+
namespace YY::Thunks::Fallback
12+
{
13+
namespace
14+
{
15+
union DnsQueryCancel
16+
{
17+
DNS_QUERY_CANCEL CancelHandle;
18+
19+
struct
20+
{
21+
volatile LSTATUS lStatus;
22+
};
23+
};
24+
25+
struct DnsExtraInfo
26+
{
27+
uint32_t Version = 0x80000001ul;
28+
uint32_t Size;
29+
void* pNext = nullptr;
30+
uint32_t Id = 10;
31+
uint32_t Reserved = 0;
32+
PDNS_ADDR_ARRAY pDnsServerList = nullptr;
33+
};
34+
35+
struct DnsQuerySharedData
36+
{
37+
_In_opt_ PWSTR szQueryName;
38+
_In_ WORD QueryType;
39+
_In_ ULONG64 QueryOptions;
40+
_In_opt_ void* pExtra;
41+
_In_ PVOID pQueryContext;
42+
_In_opt_ PDNS_QUERY_COMPLETION_ROUTINE pQueryCompletionCallback;
43+
PDNS_QUERY_RESULT pQueryResults;
44+
_In_opt_ DnsQueryCancel* pCancelHandle;
45+
BYTE Buffer[0];
46+
};
47+
48+
IP4_ARRAY* __fastcall DNS_ADDR_ARRAY_To_IP4_ARRAY(PDNS_ADDR_ARRAY _pDnsServerList, IP4_ARRAY* _pIpv4DnsServerList)
49+
{
50+
if (_pDnsServerList == nullptr || _pDnsServerList->AddrCount == 0)
51+
return nullptr;
52+
53+
_pIpv4DnsServerList->AddrCount = _pDnsServerList->AddrCount;
54+
55+
for (DWORD i = 0; i < _pDnsServerList->AddrCount; ++i)
56+
{
57+
_pIpv4DnsServerList->AddrArray[i] = reinterpret_cast<sockaddr_in*>(_pDnsServerList->AddrArray[i].MaxSa)->sin_addr.S_un.S_addr;
58+
}
59+
60+
return _pIpv4DnsServerList;
61+
}
62+
63+
bool __fastcall IsAsyncDnsQuery(_In_ PDNS_QUERY_REQUEST _pQueryRequest)
64+
{
65+
if (!_pQueryRequest->pQueryCompletionCallback)
66+
{
67+
return false;
68+
}
69+
70+
// 微软规定,查询本地名称的 DNS_TYPE_A/DNS_TYPE_AAAA,接口是同步的
71+
if (_pQueryRequest->QueryName[0] == L'\0' && (_pQueryRequest->QueryType == DNS_TYPE_A || _pQueryRequest->QueryType == DNS_TYPE_AAAA))
72+
{
73+
return false;
74+
}
75+
76+
return true;
77+
}
78+
}
79+
}
80+
#endif
81+
82+
namespace YY::Thunks
83+
{
84+
#if (YY_Thunks_Target < __WindowsNT6_2)
85+
86+
// Minimum supported client Windows 8 [desktop apps only]
87+
// Minimum supported server Windows Server 2012[desktop apps only]
88+
__DEFINE_THUNK(
89+
dnsapi,
90+
12,
91+
DNS_STATUS,
92+
WINAPI,
93+
DnsQueryEx,
94+
_In_ PDNS_QUERY_REQUEST _pQueryRequest,
95+
_Inout_ PDNS_QUERY_RESULT _pQueryResults,
96+
_Inout_opt_ PDNS_QUERY_CANCEL _pCancelHandle
97+
)
98+
{
99+
if (const auto _pfnDnsQueryEx = try_get_DnsQueryEx())
100+
{
101+
return _pfnDnsQueryEx(_pQueryRequest, _pQueryResults, _pCancelHandle);
102+
}
103+
104+
if (_pQueryRequest == nullptr || _pQueryResults == nullptr)
105+
{
106+
return ERROR_INVALID_PARAMETER;
107+
}
108+
109+
if (_pQueryRequest->Version != DNS_QUERY_REQUEST_VERSION1)
110+
{
111+
return ERROR_INVALID_PARAMETER;
112+
}
113+
114+
if (_pQueryResults->Version != DNS_QUERY_RESULTS_VERSION1)
115+
{
116+
return ERROR_INVALID_PARAMETER;
117+
}
118+
119+
if (auto _pDnsServerList = _pQueryRequest->pDnsServerList)
120+
{
121+
if (_pDnsServerList->Family == AF_INET)
122+
{
123+
// IPv4 Dns
124+
for (DWORD i = 0; i != _pDnsServerList->AddrCount; ++i)
125+
{
126+
auto _pSockAddr = reinterpret_cast<SOCKADDR_IN*>(_pDnsServerList->AddrArray[i].MaxSa);
127+
if (_pSockAddr->sin_family != AF_INET)
128+
{
129+
return ERROR_INVALID_PARAMETER;
130+
}
131+
132+
if(_pSockAddr->sin_port != 0)
133+
{
134+
// 端口号必须为0,为啥你问微软去吧……
135+
return ERROR_INVALID_PARAMETER;
136+
}
137+
}
138+
}
139+
else if (_pDnsServerList->Family == AF_INET6)
140+
{
141+
// IPv6 Dns
142+
for (DWORD i = 0; i != _pDnsServerList->AddrCount; ++i)
143+
{
144+
auto _pSockAddr = reinterpret_cast<sockaddr_in6*>(_pDnsServerList->AddrArray[i].MaxSa);
145+
if (_pSockAddr->sin6_family != AF_INET6)
146+
{
147+
return ERROR_INVALID_PARAMETER;
148+
}
149+
150+
if (_pSockAddr->sin6_port != 0)
151+
{
152+
// 端口号必须为0,为啥你问微软去吧……
153+
return ERROR_INVALID_PARAMETER;
154+
}
155+
}
156+
}
157+
else
158+
{
159+
return ERROR_INVALID_PARAMETER;
160+
}
161+
}
162+
163+
if(_pQueryRequest->QueryName == nullptr)
164+
{
165+
// 文档虽然说QueryName可以为nullptr,但实际测试发现此时会返回失败
166+
return ERROR_INVALID_PARAMETER;
167+
}
168+
169+
_pQueryResults->pQueryRecords = nullptr;
170+
_pQueryResults->QueryOptions = _pQueryRequest->QueryOptions;
171+
172+
if (!Fallback::IsAsyncDnsQuery(_pQueryRequest))
173+
{
174+
void* _pExtra = nullptr;
175+
BYTE _DnsServerListStaticBuffer[sizeof(IP4_ARRAY) + (128 - 1) * sizeof(IP4_ADDRESS)];
176+
if (_pQueryRequest->pDnsServerList && _pQueryRequest->pDnsServerList->AddrCount)
177+
{
178+
if (_pQueryRequest->pDnsServerList->Family == AF_INET)
179+
{
180+
const auto _cbIpv4DnsServerList = sizeof(IP4_ARRAY) + (_pQueryRequest->pDnsServerList->AddrCount - 1) * sizeof(IP4_ADDRESS);
181+
if (sizeof(_DnsServerListStaticBuffer) < _cbIpv4DnsServerList)
182+
{
183+
_pExtra = internal::Alloc(_cbIpv4DnsServerList);
184+
if (!_pExtra)
185+
{
186+
return ERROR_OUTOFMEMORY;
187+
}
188+
}
189+
else
190+
{
191+
_pExtra = _DnsServerListStaticBuffer;
192+
}
193+
194+
Fallback::DNS_ADDR_ARRAY_To_IP4_ARRAY(_pQueryRequest->pDnsServerList, (IP4_ARRAY*)_pExtra);
195+
}
196+
else
197+
{
198+
auto _pDnsExtraInfo = (Fallback::DnsExtraInfo*)_DnsServerListStaticBuffer;
199+
_pExtra = _pDnsExtraInfo;
200+
201+
new(_pDnsExtraInfo) Fallback::DnsExtraInfo();
202+
_pDnsExtraInfo->pDnsServerList = _pQueryRequest->pDnsServerList;
203+
}
204+
}
205+
206+
_pQueryResults->QueryStatus = DnsQuery_W(_pQueryRequest->QueryName, _pQueryRequest->QueryType, _pQueryRequest->QueryOptions, _pExtra, &_pQueryResults->pQueryRecords, nullptr);
207+
208+
if (_pExtra != _DnsServerListStaticBuffer)
209+
{
210+
internal::Free(_pExtra);
211+
}
212+
return _pQueryResults->QueryStatus;
213+
}
214+
215+
const auto _cbName = (wcslen(_pQueryRequest->QueryName) + 1) * sizeof(wchar_t);
216+
auto _pDnsQueryCancel = reinterpret_cast<Fallback::DnsQueryCancel*>(_pCancelHandle);
217+
218+
uint32_t _cbDnsServerList = 0;
219+
if (_pQueryRequest->pDnsServerList && _pQueryRequest->pDnsServerList->AddrCount)
220+
{
221+
if (_pQueryRequest->pDnsServerList->Family == AF_INET)
222+
{
223+
_cbDnsServerList = sizeof(IP4_ARRAY) + (_pQueryRequest->pDnsServerList->AddrCount - 1) * sizeof(IP4_ADDRESS);
224+
}
225+
else
226+
{
227+
// IPv6 Dns,必须使用DnsExtraInfo
228+
_cbDnsServerList = sizeof(Fallback::DnsExtraInfo) + sizeof(_DnsAddrArray) + (_pQueryRequest->pDnsServerList->AddrCount - 1) * sizeof(DNS_ADDR);
229+
}
230+
}
231+
232+
auto _pSharedData = (Fallback::DnsQuerySharedData*)internal::Alloc(sizeof(Fallback::DnsQuerySharedData) + _cbDnsServerList + _cbName);
233+
if (!_pSharedData)
234+
{
235+
return ERROR_OUTOFMEMORY;
236+
}
237+
238+
auto _pBuffer = _pSharedData->Buffer;
239+
_pSharedData->szQueryName = nullptr;
240+
if (_cbName)
241+
{
242+
_pSharedData->szQueryName = reinterpret_cast<PWSTR>(_pBuffer);
243+
memcpy(_pSharedData->szQueryName, _pQueryRequest->QueryName, _cbName);
244+
_pBuffer += _cbName;
245+
}
246+
247+
_pSharedData->QueryType = _pQueryRequest->QueryType;
248+
_pSharedData->QueryOptions = _pQueryRequest->QueryOptions;
249+
250+
_pSharedData->pExtra = nullptr;
251+
if (_cbDnsServerList)
252+
{
253+
if (_pQueryRequest->pDnsServerList->Family == AF_INET)
254+
{
255+
_pSharedData->pExtra = Fallback::DNS_ADDR_ARRAY_To_IP4_ARRAY(_pQueryRequest->pDnsServerList, (IP4_ARRAY*)_pBuffer);
256+
}
257+
else
258+
{
259+
// IPv6 Dns,必须使用DnsExtraInfo
260+
auto _pDnsExtraInfo = reinterpret_cast<Fallback::DnsExtraInfo*>(_pBuffer);
261+
_pSharedData->pExtra = _pDnsExtraInfo;
262+
263+
new(_pDnsExtraInfo) Fallback::DnsExtraInfo();
264+
_pDnsExtraInfo->pDnsServerList = reinterpret_cast<PDNS_ADDR_ARRAY>(&_pDnsExtraInfo[1]);
265+
memcpy(_pDnsExtraInfo->pDnsServerList, _pQueryRequest->pDnsServerList, _cbDnsServerList - sizeof(Fallback::DnsExtraInfo));
266+
}
267+
268+
_pBuffer += _cbDnsServerList;
269+
}
270+
271+
_pSharedData->pQueryContext = _pQueryRequest->pQueryContext;
272+
_pSharedData->pQueryCompletionCallback = _pQueryRequest->pQueryCompletionCallback;
273+
274+
_pSharedData->pQueryResults = _pQueryResults;
275+
_pSharedData->pCancelHandle = _pDnsQueryCancel;
276+
277+
if (_pDnsQueryCancel)
278+
{
279+
_pDnsQueryCancel->lStatus = DNS_REQUEST_PENDING;
280+
}
281+
282+
#if (YY_Thunks_Target < __WindowsNT6)
283+
auto _bRet = QueueUserWorkItem(
284+
[](LPVOID Context) -> DWORD
285+
#else
286+
auto _bRet = TrySubmitThreadpoolCallback(
287+
[](_Inout_ PTP_CALLBACK_INSTANCE Instance, _Inout_opt_ PVOID Context)
288+
#endif
289+
{
290+
auto _pSharedData = reinterpret_cast<Fallback::DnsQuerySharedData*>(Context);
291+
auto _pQueryResults = _pSharedData->pQueryResults;
292+
293+
do
294+
{
295+
if (_pSharedData->pCancelHandle)
296+
{
297+
if (_pSharedData->pCancelHandle->lStatus != DNS_REQUEST_PENDING)
298+
{
299+
_pSharedData->pQueryResults->QueryStatus = _pSharedData->pCancelHandle->lStatus;
300+
break;
301+
}
302+
}
303+
304+
auto _QueryStatus = DnsQuery_W(_pSharedData->szQueryName, _pSharedData->QueryType, _pSharedData->QueryOptions, _pSharedData->pExtra, &_pQueryResults->pQueryRecords, nullptr);
305+
if (_pSharedData->pCancelHandle)
306+
{
307+
InterlockedExchange(&_pSharedData->pCancelHandle->lStatus, _QueryStatus);
308+
}
309+
310+
_pSharedData->pQueryResults->QueryStatus = _QueryStatus;
311+
312+
} while (false);
313+
314+
_pSharedData->pQueryCompletionCallback(_pSharedData->pQueryContext, _pQueryResults);
315+
internal::Free(_pSharedData);
316+
317+
#if (YY_Thunks_Target < __WindowsNT6)
318+
return 0ul;
319+
},
320+
_pSharedData,
321+
0);
322+
#else
323+
},
324+
_pSharedData,
325+
nullptr);
326+
#endif
327+
328+
if(_bRet)
329+
return DNS_REQUEST_PENDING;
330+
331+
internal::Free(_pSharedData);
332+
return ERROR_FUNCTION_FAILED;
333+
}
334+
#endif
335+
336+
337+
#if (YY_Thunks_Target < __WindowsNT6_2)
338+
339+
// Minimum supported client Windows 8 [desktop apps only]
340+
// Minimum supported server Windows Server 2012[desktop apps only]
341+
__DEFINE_THUNK(
342+
dnsapi,
343+
4,
344+
DNS_STATUS,
345+
WINAPI,
346+
DnsCancelQuery,
347+
_In_ PDNS_QUERY_CANCEL _pCancelHandle
348+
)
349+
{
350+
if (const auto _pfnDnsCancelQuery = try_get_DnsCancelQuery())
351+
{
352+
return _pfnDnsCancelQuery(_pCancelHandle);
353+
}
354+
355+
auto _pDnsQueryCancel = reinterpret_cast<Fallback::DnsQueryCancel*>(_pCancelHandle);
356+
357+
auto _Status = InterlockedCompareExchange(&_pDnsQueryCancel->lStatus, ERROR_CANCELLED, DNS_REQUEST_PENDING);
358+
return ERROR_SUCCESS;
359+
}
360+
#endif
361+
}

0 commit comments

Comments
 (0)