forked from Dniel97/segatools
hooklib/dns.c: Add initial WinDNS hook
We'll probably need to intercept the more traditional gethostbyname() API and friends at some point too.
This commit is contained in:
parent
8491aa1fec
commit
8ecbb860d8
327
hooklib/dns.c
Normal file
327
hooklib/dns.c
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
/* Might push this to capnhook, don't add any util dependencies. */
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <windns.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "hook/hr.h"
|
||||||
|
#include "hook/table.h"
|
||||||
|
|
||||||
|
#include "hooklib/dns.h"
|
||||||
|
|
||||||
|
/* Latest w32headers does not include DnsQueryEx, so we'll have to "polyfill"
|
||||||
|
its associated data types here for the time being.
|
||||||
|
|
||||||
|
Results and cancel handle are passed through, so we'll just use void
|
||||||
|
pointers for those args. So are most of the fields in this structure, for
|
||||||
|
that matter. */
|
||||||
|
|
||||||
|
typedef struct POLYFILL_DNS_QUERY_REQUEST {
|
||||||
|
ULONG Version;
|
||||||
|
PCWSTR QueryName;
|
||||||
|
WORD QueryType;
|
||||||
|
ULONG64 QueryOptions;
|
||||||
|
void* pDnsServerList;
|
||||||
|
ULONG InterfaceIndex;
|
||||||
|
void* pQueryCompletionCallback;
|
||||||
|
PVOID pQueryContext;
|
||||||
|
} POLYFILL_DNS_QUERY_REQUEST;
|
||||||
|
|
||||||
|
struct dns_hook_entry {
|
||||||
|
wchar_t *from;
|
||||||
|
wchar_t *to;
|
||||||
|
};
|
||||||
|
|
||||||
|
static DNS_STATUS WINAPI hook_DnsQuery_A(
|
||||||
|
const char *pszName,
|
||||||
|
WORD wType,
|
||||||
|
DWORD Options,
|
||||||
|
void *pExtra,
|
||||||
|
DNS_RECORD **ppQueryResults,
|
||||||
|
void *pReserved);
|
||||||
|
|
||||||
|
static DNS_STATUS WINAPI hook_DnsQuery_W(
|
||||||
|
const wchar_t *pszName,
|
||||||
|
WORD wType,
|
||||||
|
DWORD Options,
|
||||||
|
void *pExtra,
|
||||||
|
DNS_RECORD **ppQueryResults,
|
||||||
|
void *pReserved);
|
||||||
|
|
||||||
|
static DNS_STATUS WINAPI hook_DnsQueryEx(
|
||||||
|
POLYFILL_DNS_QUERY_REQUEST *pRequest,
|
||||||
|
void *pQueryResults,
|
||||||
|
void *pCancelHandle);
|
||||||
|
|
||||||
|
static DNS_STATUS WINAPI (*next_DnsQuery_A)(
|
||||||
|
const char *pszName,
|
||||||
|
WORD wType,
|
||||||
|
DWORD Options,
|
||||||
|
void *pExtra,
|
||||||
|
DNS_RECORD **ppQueryResults,
|
||||||
|
void *pReserved);
|
||||||
|
|
||||||
|
static DNS_STATUS WINAPI (*next_DnsQuery_W)(
|
||||||
|
const wchar_t *pszName,
|
||||||
|
WORD wType,
|
||||||
|
DWORD Options,
|
||||||
|
void *pExtra,
|
||||||
|
DNS_RECORD **ppQueryResults,
|
||||||
|
void *pReserved);
|
||||||
|
|
||||||
|
static DNS_STATUS WINAPI (*next_DnsQueryEx)(
|
||||||
|
POLYFILL_DNS_QUERY_REQUEST *pRequest,
|
||||||
|
void *pQueryResults,
|
||||||
|
void *pCancelHandle);
|
||||||
|
|
||||||
|
static const struct hook_symbol dns_hook_syms[] = {
|
||||||
|
{
|
||||||
|
.name = "DnsQuery_A",
|
||||||
|
.patch = hook_DnsQuery_A,
|
||||||
|
.link = (void **) &next_DnsQuery_A,
|
||||||
|
}, {
|
||||||
|
.name = "DnsQuery_W",
|
||||||
|
.patch = hook_DnsQuery_W,
|
||||||
|
.link = (void **) &next_DnsQuery_W,
|
||||||
|
}, {
|
||||||
|
.name = "DnsQueryEx",
|
||||||
|
.patch = hook_DnsQueryEx,
|
||||||
|
.link = (void **) &next_DnsQueryEx,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool dns_hook_initted;
|
||||||
|
static CRITICAL_SECTION dns_hook_lock;
|
||||||
|
static struct dns_hook_entry *dns_hook_entries;
|
||||||
|
static size_t dns_hook_nentries;
|
||||||
|
|
||||||
|
static void dns_hook_init(void)
|
||||||
|
{
|
||||||
|
if (dns_hook_initted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_hook_initted = true;
|
||||||
|
InitializeCriticalSection(&dns_hook_lock);
|
||||||
|
|
||||||
|
hook_table_apply(
|
||||||
|
NULL,
|
||||||
|
"dnsapi.dll",
|
||||||
|
dns_hook_syms,
|
||||||
|
_countof(dns_hook_syms));
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT dns_hook_push(const wchar_t *from_src, const wchar_t *to_src)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
struct dns_hook_entry *newmem;
|
||||||
|
struct dns_hook_entry *newitem;
|
||||||
|
wchar_t *from;
|
||||||
|
wchar_t *to;
|
||||||
|
|
||||||
|
assert(from_src != NULL);
|
||||||
|
assert(to_src != NULL);
|
||||||
|
|
||||||
|
to = NULL;
|
||||||
|
from = NULL;
|
||||||
|
dns_hook_init();
|
||||||
|
|
||||||
|
EnterCriticalSection(&dns_hook_lock);
|
||||||
|
|
||||||
|
from = _wcsdup(from_src);
|
||||||
|
|
||||||
|
if (from == NULL) {
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
to = _wcsdup(to_src);
|
||||||
|
|
||||||
|
if (to == NULL) {
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
newmem = realloc(
|
||||||
|
dns_hook_entries,
|
||||||
|
(dns_hook_nentries + 1) * sizeof(struct dns_hook_entry));
|
||||||
|
|
||||||
|
if (newmem == NULL) {
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_hook_entries = newmem;
|
||||||
|
newitem = &newmem[dns_hook_nentries++];
|
||||||
|
newitem->from = from;
|
||||||
|
newitem->to = to;
|
||||||
|
|
||||||
|
from = NULL;
|
||||||
|
to = NULL;
|
||||||
|
hr = S_OK;
|
||||||
|
|
||||||
|
end:
|
||||||
|
LeaveCriticalSection(&dns_hook_lock);
|
||||||
|
|
||||||
|
free(to);
|
||||||
|
free(from);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DNS_STATUS WINAPI hook_DnsQuery_A(
|
||||||
|
const char *pszName,
|
||||||
|
WORD wType,
|
||||||
|
DWORD Options,
|
||||||
|
void *pExtra,
|
||||||
|
DNS_RECORD **ppQueryResults,
|
||||||
|
void *pReserved)
|
||||||
|
{
|
||||||
|
const struct dns_hook_entry *pos;
|
||||||
|
size_t i;
|
||||||
|
size_t wstr_c;
|
||||||
|
wchar_t *wstr;
|
||||||
|
size_t str_c;
|
||||||
|
char *str;
|
||||||
|
DNS_STATUS code;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
wstr = NULL;
|
||||||
|
str = NULL;
|
||||||
|
|
||||||
|
if (pszName == NULL) {
|
||||||
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbstowcs_s(&wstr_c, NULL, 0, pszName, 0);
|
||||||
|
wstr = malloc(wstr_c * sizeof(wchar_t));
|
||||||
|
|
||||||
|
if (wstr == NULL) {
|
||||||
|
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbstowcs_s(NULL, wstr, wstr_c, pszName, wstr_c - 1);
|
||||||
|
|
||||||
|
for (i = 0 ; i < dns_hook_nentries ; i++) {
|
||||||
|
pos = &dns_hook_entries[i];
|
||||||
|
|
||||||
|
if (_wcsicmp(wstr, pos->from) == 0) {
|
||||||
|
wcstombs_s(&str_c, NULL, 0, pos->to, 0);
|
||||||
|
str = malloc(str_c * sizeof(char));
|
||||||
|
|
||||||
|
if (str == NULL) {
|
||||||
|
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
wcstombs_s(NULL, str, str_c, pos->to, str_c - 1);
|
||||||
|
pszName = str;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code = next_DnsQuery_A(
|
||||||
|
pszName,
|
||||||
|
wType,
|
||||||
|
Options,
|
||||||
|
pExtra,
|
||||||
|
ppQueryResults,
|
||||||
|
pReserved);
|
||||||
|
|
||||||
|
hr = HRESULT_FROM_WIN32(code);
|
||||||
|
|
||||||
|
end:
|
||||||
|
free(str);
|
||||||
|
free(wstr);
|
||||||
|
|
||||||
|
return hr_to_win32_error(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DNS_STATUS WINAPI hook_DnsQuery_W(
|
||||||
|
const wchar_t *pszName,
|
||||||
|
WORD wType,
|
||||||
|
DWORD Options,
|
||||||
|
void *pExtra,
|
||||||
|
DNS_RECORD **ppQueryResults,
|
||||||
|
void *pReserved)
|
||||||
|
{
|
||||||
|
const struct dns_hook_entry *pos;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (pszName == NULL) {
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0 ; i < dns_hook_nentries ; i++) {
|
||||||
|
pos = &dns_hook_entries[i];
|
||||||
|
|
||||||
|
if (_wcsicmp(pszName, pos->from) == 0) {
|
||||||
|
pszName = pos->to;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return next_DnsQuery_W(
|
||||||
|
pszName,
|
||||||
|
wType,
|
||||||
|
Options,
|
||||||
|
pExtra,
|
||||||
|
ppQueryResults,
|
||||||
|
pReserved);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static DNS_STATUS WINAPI hook_DnsQueryEx(
|
||||||
|
POLYFILL_DNS_QUERY_REQUEST *pRequest,
|
||||||
|
void *pQueryResults,
|
||||||
|
void *pCancelHandle)
|
||||||
|
{
|
||||||
|
const wchar_t *orig;
|
||||||
|
const struct dns_hook_entry *pos;
|
||||||
|
DNS_STATUS code;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (pRequest == NULL) {
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
orig = pRequest->QueryName;
|
||||||
|
|
||||||
|
for (i = 0 ; i < dns_hook_nentries ; i++) {
|
||||||
|
pos = &dns_hook_entries[i];
|
||||||
|
|
||||||
|
if (_wcsicmp(pRequest->QueryName, pos->from) == 0) {
|
||||||
|
pRequest->QueryName = pos->to;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code = next_DnsQueryEx(pRequest, pQueryResults, pCancelHandle);
|
||||||
|
|
||||||
|
/* Caller might not appreciate QueryName changing under its feet. It is
|
||||||
|
strongly implied by MSDN that a copy of *pRequest is taken by WINAPI,
|
||||||
|
so we can change it back after the call has been issued with no ill
|
||||||
|
effect... we hope.
|
||||||
|
|
||||||
|
Hopefully the completion callback is issued from an APC or something
|
||||||
|
(or otherwise happens after this returns) or we're in trouble. */
|
||||||
|
|
||||||
|
pRequest->QueryName = orig;
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
8
hooklib/dns.h
Normal file
8
hooklib/dns.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
HRESULT dns_hook_push(const wchar_t *from_src, const wchar_t *to_src);
|
||||||
|
|
@ -11,6 +11,8 @@ hooklib_lib = static_library(
|
|||||||
'clock.h',
|
'clock.h',
|
||||||
'dll.c',
|
'dll.c',
|
||||||
'dll.h',
|
'dll.h',
|
||||||
|
'dns.c',
|
||||||
|
'dns.h',
|
||||||
'fdshark.c',
|
'fdshark.c',
|
||||||
'fdshark.h',
|
'fdshark.h',
|
||||||
'gfx.c',
|
'gfx.c',
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
#include <setupapi.h>
|
#include <setupapi.h>
|
||||||
#include <unknwn.h>
|
#include <unknwn.h>
|
||||||
|
#include <windns.h>
|
||||||
#include <dinput.h>
|
#include <dinput.h>
|
||||||
#include <xinput.h>
|
#include <xinput.h>
|
||||||
#include <d3d9.h>
|
#include <d3d9.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user