diff --git a/Package.mk b/Package.mk index 3c51378..05fbc75 100644 --- a/Package.mk +++ b/Package.mk @@ -19,6 +19,21 @@ $(BUILD_DIR_ZIP)/siva.zip: $(BUILD_DIR_ZIP)/siva/DEVICE $(V)strip $(BUILD_DIR_ZIP)/siva/*.{exe,dll} $(V)cd $(BUILD_DIR_ZIP)/siva ; zip -r ../siva.zip * + +$(BUILD_DIR_ZIP)/ll3.zip: + $(V)echo ... $@ + $(V)mkdir -p $(BUILD_DIR_ZIP)/ll3 + $(V)mkdir -p $(BUILD_DIR_ZIP)/ll3/DEVICE + $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ + $(BUILD_DIR_64)/ll3hook/ll3hook.dll \ + $(DIST_DIR)/ll3/taitools.ini \ + $(DIST_DIR)/ll3/start.bat \ + $(BUILD_DIR_ZIP)/ll3 + $(V)cp pki/billing.pub \ + pki/ca.crt \ + $(BUILD_DIR_ZIP)/ll3/DEVICE + $(V)strip $(BUILD_DIR_ZIP)/ll3/*.{exe,dll} + $(V)cd $(BUILD_DIR_ZIP)/ll3 ; zip -r ../ll3.zip * $(BUILD_DIR_ZIP)/doc.zip: \ $(DOC_DIR)/config \ @@ -28,6 +43,7 @@ $(BUILD_DIR_ZIP)/doc.zip: \ $(BUILD_DIR_ZIP)/taitools.zip: \ $(BUILD_DIR_ZIP)/siva.zip \ + $(BUILD_DIR_ZIP)/ll3.zip \ CHANGELOG.md \ README.md \ diff --git a/dist/ll3/start.bat b/dist/ll3/start.bat new file mode 100644 index 0000000..0d50837 --- /dev/null +++ b/dist/ll3/start.bat @@ -0,0 +1,13 @@ +@echo off + +pushd %~dp0 + +REM chcp 932 +start inject.exe -d -k ll3hook.dll d_drive\Service\NesysService.exe -app +inject.exe -d -k ll3hook.dll ll3.exe -singlemonitor -windowmode -highquality +REM Comment above and uncomment below for terminal mode +REM inject.exe -d -k ll3hook.dll ll3.exe -singlemonitor -windowmode -highquality -centralmode + +echo. +echo The game process has terminated +pause \ No newline at end of file diff --git a/dist/ll3/taitools.ini b/dist/ll3/taitools.ini new file mode 100644 index 0000000..fe5e484 --- /dev/null +++ b/dist/ll3/taitools.ini @@ -0,0 +1,5 @@ +[vfs] +d_drive=d_drive + +[netenv] +enable=1 diff --git a/hooklib/dns.c b/hooklib/dns.c index f4aef96..d392c15 100644 --- a/hooklib/dns.c +++ b/hooklib/dns.c @@ -520,8 +520,9 @@ static WINHTTPAPI BOOL hook_WinHttpCrackUrl( } else { wcscat_s(bfr, _countof(bfr), pos->to); wcscat_s(bfr, _countof(bfr), path); + //dprintf("DNS: Replaced cracked url %S (%d) -> %S\n", lpUrlComponents->lpszHostName, (int)lpUrlComponents->dwHostNameLength, bfr); lpUrlComponents->lpszHostName = bfr; - lpUrlComponents->dwHostNameLength = wcslen(bfr); + lpUrlComponents->dwHostNameLength = wcslen(pos->to); } break; } diff --git a/hooklib/reg.c b/hooklib/reg.c index bc18dbb..6765ae7 100644 --- a/hooklib/reg.c +++ b/hooklib/reg.c @@ -37,6 +37,11 @@ static LSTATUS reg_hook_open_locked( const wchar_t *name, HKEY *out); +static LSTATUS reg_hook_open_locked_a( + HKEY parent, + const char *name, + HKEY *out); + static LSTATUS reg_hook_query_val_locked( struct reg_hook_key *key, const wchar_t *name, @@ -53,6 +58,13 @@ static LSTATUS WINAPI hook_RegOpenKeyExW( uint32_t access, HKEY *out); +static LSTATUS WINAPI hook_RegOpenKeyExA( + HKEY parent, + const char *name, + uint32_t flags, + uint32_t access, + HKEY *out); + static LSTATUS WINAPI hook_RegCreateKeyExW( HKEY parent, const wchar_t *name, @@ -132,6 +144,13 @@ static LSTATUS (WINAPI *next_RegOpenKeyExW)( uint32_t access, HKEY *out); +static LSTATUS (WINAPI *next_RegOpenKeyExA)( + HKEY parent, + const char *name, + uint32_t flags, + uint32_t access, + HKEY *out); + static LSTATUS (WINAPI *next_RegCreateKeyExW)( HKEY parent, const wchar_t *name, @@ -208,6 +227,10 @@ static const struct hook_symbol reg_hook_syms[] = { .name = "RegOpenKeyExW", .patch = hook_RegOpenKeyExW, .link = (void **) &next_RegOpenKeyExW, + }, { + .name = "RegOpenKeyExA", + .patch = hook_RegOpenKeyExA, + .link = (void **) &next_RegOpenKeyExA, }, { .name = "RegCreateKeyExW", .patch = hook_RegCreateKeyExW, @@ -403,6 +426,7 @@ static LSTATUS reg_hook_open_locked( //dprintf("Reg: %ls vs %ls\n", name, key->name); if (key->root == parent && wstr_ieq(key->name, name)) { + dprintf("Reg: Replace key %S\n", name); break; } } @@ -417,6 +441,7 @@ static LSTATUS reg_hook_open_locked( /* Assume only one handle will be open at a time */ if (key->handle != NULL) { + dprintf("Reg: Fake handle already open: %p\n", key->handle); return ERROR_SHARING_VIOLATION; } @@ -431,6 +456,67 @@ static LSTATUS reg_hook_open_locked( 0, KEY_READ, out); + + + if (err == ERROR_SUCCESS) { + key->handle = *out; + } + + return err; +} + +static LSTATUS reg_hook_open_locked_a( + HKEY parent, + const char *name, + HKEY *out) +{ + struct reg_hook_key *key; + LSTATUS err; + size_t i; + + wchar_t wide_str[MAX_PATH]; + int cvt_num = mbstowcs(wide_str, name, MAX_PATH); + + *out = NULL; + + for (i = 0 ; i < reg_hook_nkeys ; i++) { + /* Assume reg keys are referenced from a root key and not from some + intermediary key */ + key = ®_hook_keys[i]; + //dprintf("Reg: %ls vs %ls\n", name, key->name); + + if (key->root == parent && wstr_ieq(key->name, wide_str)) { + dprintf("Reg: Replace key %S\n", wide_str); + break; + } + } + + /* (Bail out if we didn't find anything; this causes the open/create call + to be passed onward down the hook chain) */ + + if (i >= reg_hook_nkeys) { + return ERROR_SUCCESS; + } + + /* Assume only one handle will be open at a time */ + + if (key->handle != NULL) { + dprintf("Reg: Fake handle already open: %p\n", key->handle); + return ERROR_SHARING_VIOLATION; + } + + /* Open a unique HKEY handle that we can use to identify accesses to + this virtual registry key. We open a read-only handle to an arbitrary + registry key that we can reliably assume exists and isn't one of the + hardcoded root handles. HKLM\SOFTWARE will suffice for this purpose. */ + + err = next_RegOpenKeyExA( + HKEY_LOCAL_MACHINE, + "SOFTWARE", + 0, + KEY_READ, + out); + if (err == ERROR_SUCCESS) { key->handle = *out; @@ -467,6 +553,35 @@ static LSTATUS WINAPI hook_RegOpenKeyExW( return err; } + +static LSTATUS WINAPI hook_RegOpenKeyExA( + HKEY parent, + const char *name, + uint32_t flags, + uint32_t access, + HKEY *out) +{ + LSTATUS err; + + if (out == NULL) { + return ERROR_INVALID_PARAMETER; + } + + EnterCriticalSection(®_hook_lock); + err = reg_hook_open_locked_a(parent, name, out); + LeaveCriticalSection(®_hook_lock); + + if (err == ERROR_SUCCESS) { + if (*out != NULL) { + //dprintf("Registry: Opened virtual key %s\n", name); + } else { + err = next_RegOpenKeyExA(parent, name, flags, access, out); + } + } + + return err; +} + static LSTATUS WINAPI hook_RegCreateKeyExW( HKEY parent, const wchar_t *name, diff --git a/ll3hook/config.c b/ll3hook/config.c new file mode 100644 index 0000000..d96cb0c --- /dev/null +++ b/ll3hook/config.c @@ -0,0 +1,34 @@ +#include +#include + +#include "ll3hook/config.h" + +#include "platform/config.h" + +void ll3_dll_config_load( + struct ll3_dll_config *cfg, + const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + GetPrivateProfileStringW( + L"ll3io", + L"path", + L"", + cfg->path, + _countof(cfg->path), + filename); +} + +void ll3_hook_config_load( + struct ll3_hook_config *cfg, + const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + platform_config_load(&cfg->platform, filename); + ll3_dll_config_load(&cfg->dll, filename); + gfx_config_load(&cfg->gfx, filename); +} \ No newline at end of file diff --git a/ll3hook/config.h b/ll3hook/config.h new file mode 100644 index 0000000..6f33ad6 --- /dev/null +++ b/ll3hook/config.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include "ll3hook/ll3-dll.h" + +#include "platform/config.h" +#include "gfxhook/config.h" +#include "board/config.h" + +struct ll3_hook_config { + struct platform_config platform; + struct ll3_dll_config dll; + struct gfx_config gfx; +}; + +void ll3_hook_config_load( + struct ll3_hook_config *cfg, + const wchar_t *filename); diff --git a/ll3hook/dllmain.c b/ll3hook/dllmain.c index 9b15ffa..56fbdfa 100644 --- a/ll3hook/dllmain.c +++ b/ll3hook/dllmain.c @@ -50,35 +50,12 @@ static DWORD CALLBACK ll3_pre_startup(void) goto fail; } - hr = sg_reader_hook_init(&ll3_hook_cfg.aime, 1, ll3_hook_mod); - - if (FAILED(hr)) { - goto fail; - } - - hr = vfd_hook_init(2); - - if (FAILED(hr)) { - goto fail; - } - hr = ll3_dll_init(&ll3_hook_cfg.dll, ll3_hook_mod); if (FAILED(hr)) { goto fail; } - hr = ll3_io4_hook_init(&ll3_hook_cfg.io4); - - if (FAILED(hr)) { - goto fail; - } - - /* Start elisabeth Hooks for the LED and IO Board DLLs */ - elisabeth_hook_init(&ll3_hook_cfg.elisabeth); - - touch_hook_init(&ll3_hook_cfg.touch); - /* Initialize debug helpers */ spike_hook_init(L".\\taitools.ini"); @@ -97,6 +74,10 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) { HRESULT hr; + if (cause == DLL_THREAD_ATTACH && sizeof(uint64_t) == 4) { + dprintf("Connected\n"); + } + if (cause != DLL_PROCESS_ATTACH) { return TRUE; } diff --git a/ll3hook/ll3-dll.c b/ll3hook/ll3-dll.c new file mode 100644 index 0000000..0fe4665 --- /dev/null +++ b/ll3hook/ll3-dll.c @@ -0,0 +1,100 @@ +#include + +#include +#include + +#include "ll3hook/ll3-dll.h" + +#include "util/dll-bind.h" +#include "util/dprintf.h" + +const struct dll_bind_sym ll3_dll_syms[] = { + { + .sym = "ll3_io_init", + .off = offsetof(struct ll3_dll, init), + }, { + .sym = "ll3_io_read_coin_counter", + .off = offsetof(struct ll3_dll, read_coin_counter), + }, { + .sym = "ll3_io_get_btns", + .off = offsetof(struct ll3_dll, get_btns), + }, +}; + +struct ll3_dll ll3_dll; + +HRESULT ll3_dll_init(const struct ll3_dll_config *cfg, HINSTANCE self) +{ + uint16_t (*get_api_version)(void); + const struct dll_bind_sym *sym; + HINSTANCE owned; + HINSTANCE src; + HRESULT hr; + + assert(cfg != NULL); + assert(self != NULL); + + if (cfg->path[0] != L'\0') { + owned = LoadLibraryW(cfg->path); + + if (owned == NULL) { + hr = HRESULT_FROM_WIN32(GetLastError()); + dprintf("ll3 IO: Failed to load IO DLL: %lx: %S\n", + hr, + cfg->path); + + goto end; + } + + dprintf("ll3 IO: Using custom IO DLL: %S\n", cfg->path); + src = owned; + } else { + owned = NULL; + src = self; + } + + get_api_version = (void *) GetProcAddress(src, "ll3_io_get_api_version"); + + if (get_api_version != NULL) { + ll3_dll.api_version = get_api_version(); + } else { + ll3_dll.api_version = 0x0100; + dprintf("Custom IO DLL does not expose ll3_io_get_api_version, " + "assuming API version 1.0.\n" + "Please ask the developer to update their DLL.\n"); + } + + if (ll3_dll.api_version >= 0x0200) { + hr = E_NOTIMPL; + dprintf("ll3 IO: Custom IO DLL implements an unsupported " + "API version (%#04x). Please update Segatools.\n", + ll3_dll.api_version); + + goto end; + } + + sym = ll3_dll_syms; + hr = dll_bind(&ll3_dll, src, &sym, _countof(ll3_dll_syms)); + + if (FAILED(hr)) { + if (src != self) { + dprintf("ll3 IO: Custom IO DLL does not provide function " + "\"%s\". Please contact your IO DLL's developer for " + "further assistance.\n", + sym->sym); + + goto end; + } else { + dprintf("Internal error: could not reflect \"%s\"\n", sym->sym); + } + } + + owned = NULL; + +end: + if (owned != NULL) { + FreeLibrary(owned); + } + + return hr; +} \ No newline at end of file diff --git a/ll3hook/ll3-dll.h b/ll3hook/ll3-dll.h new file mode 100644 index 0000000..34febd8 --- /dev/null +++ b/ll3hook/ll3-dll.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "ll3io/ll3io.h" + +struct ll3_dll { + uint16_t api_version; + HRESULT (*init)(void); + void (*read_coin_counter)(uint16_t *coins, uint16_t *services); + void (*get_btns)(uint8_t *btn, uint8_t *stick); +}; + +struct ll3_dll_config { + wchar_t path[MAX_PATH]; +}; + +extern struct ll3_dll ll3_dll; + +HRESULT ll3_dll_init(const struct ll3_dll_config *cfg, HINSTANCE self); diff --git a/ll3hook/ll3hook.def b/ll3hook/ll3hook.def new file mode 100644 index 0000000..aee1cd5 --- /dev/null +++ b/ll3hook/ll3hook.def @@ -0,0 +1,7 @@ +LIBRARY ll3hook + +EXPORTS + ll3_io_get_api_version + ll3_io_init + ll3_io_read_coin_counter + ll3_io_get_btns \ No newline at end of file diff --git a/ll3io/config.c b/ll3io/config.c new file mode 100644 index 0000000..2ebc3d1 --- /dev/null +++ b/ll3io/config.c @@ -0,0 +1,30 @@ +#include + +#include +#include +#include + +#include "ll3io/config.h" + +void ll3_io_config_load(struct ll3_input_config *cfg, const wchar_t *filename) +{ + cfg->test = GetPrivateProfileIntW(L"jvs", L"test", VK_HOME, filename); + cfg->service = GetPrivateProfileIntW(L"jvs", L"service", VK_DELETE, filename); + cfg->coin = GetPrivateProfileIntW(L"jvs", L"coin", VK_INSERT, filename); + + cfg->is_xinput = GetPrivateProfileIntW(L"deck", L"deck", 0, filename); + cfg->xinput_player = GetPrivateProfileIntW(L"deck", L"controller_num", 0, filename); + + cfg->btn_l = GetPrivateProfileIntW(L"deck", L"left_button", 'C', filename); + cfg->btn_r = GetPrivateProfileIntW(L"deck", L"right_button", 'N', filename); + + cfg->stick_l_up = GetPrivateProfileIntW(L"deck", L"left_stick_up", 'W', filename); + cfg->stick_l_right = GetPrivateProfileIntW(L"deck", L"left_stick_right", 'D', filename); + cfg->stick_l_down = GetPrivateProfileIntW(L"deck", L"left_stick_down", 'S', filename); + cfg->stick_l_left = GetPrivateProfileIntW(L"deck", L"left_stick_left", 'A', filename); + + cfg->stick_r_up = GetPrivateProfileIntW(L"deck", L"right_stick_up", 'I', filename); + cfg->stick_r_right = GetPrivateProfileIntW(L"deck", L"right_stick_right", 'L', filename); + cfg->stick_r_down = GetPrivateProfileIntW(L"deck", L"right_stick_down", 'K', filename); + cfg->stick_r_left = GetPrivateProfileIntW(L"deck", L"right_stick_left", 'J', filename); +} \ No newline at end of file diff --git a/ll3io/config.h b/ll3io/config.h new file mode 100644 index 0000000..475f1e5 --- /dev/null +++ b/ll3io/config.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#pragma pack(push, 1) +struct ll3_input_config { + uint8_t is_xinput; + uint8_t xinput_player; + + uint8_t test; + uint8_t service; + uint8_t coin; + uint8_t btn_l; + uint8_t btn_r; + + uint8_t stick_l_up; + uint8_t stick_l_right; + uint8_t stick_l_down; + uint8_t stick_l_left; + uint8_t stick_r_up; + uint8_t stick_r_right; + uint8_t stick_r_down; + uint8_t stick_r_left; +}; +#pragma pack(pop) + +void ll3_io_config_load(struct ll3_input_config *cfg, const wchar_t *filename); \ No newline at end of file diff --git a/ll3io/ll3io.c b/ll3io/ll3io.c new file mode 100644 index 0000000..906c800 --- /dev/null +++ b/ll3io/ll3io.c @@ -0,0 +1,64 @@ +#include +#include + +#include +#include +#include + +#include "ll3io/ll3io.h" +#include "ll3io/config.h" + +#include "util/dprintf.h" + +static bool ll3_io_coin = false; +static bool ll3_io_service = false; +static uint16_t ll3_coin_ct = 0; +static uint16_t ll3_service_ct = 0; +static struct ll3_input_config cfg; + +uint16_t ll3_io_get_api_version(void) +{ + return 0x0100; +} + +HRESULT ll3_io_init(void) +{ + dprintf("ll3 IO: Init\n"); + ll3_io_config_load(&cfg, L".\\bananatools.ini"); + return S_OK; +} + +void ll3_io_get_btns(uint8_t *btn, uint8_t *stick) +{ + if (GetAsyncKeyState(cfg.test) & 0x8000) { + *btn |= ll3_BTN_TEST; + } + + if (GetAsyncKeyState(cfg.service) & 0x8000) { + *btn |= ll3_BTN_SERVICE; + } +} + +void ll3_io_read_coin_counter(uint16_t *coins, uint16_t *services) +{ + if (GetAsyncKeyState(cfg.coin) & 0x8000) { + if (!ll3_io_coin) { + ll3_io_coin = true; + ll3_coin_ct++; + } + } else { + ll3_io_coin = false; + } + + if (GetAsyncKeyState(cfg.service) & 0x8000) { + if (!ll3_io_service) { + ll3_io_service = true; + ll3_service_ct++; + } + } else { + ll3_io_service = false; + } + + *coins = ll3_coin_ct; + *services = ll3_service_ct; +} \ No newline at end of file diff --git a/ll3io/ll3io.h b/ll3io/ll3io.h new file mode 100644 index 0000000..cf320bf --- /dev/null +++ b/ll3io/ll3io.h @@ -0,0 +1,57 @@ +#pragma once + +#include + +#include + +enum { + ll3_BTN_TEST = 0x01, + ll3_BTN_SERVICE = 0x02, + ll3_BTN_COIN = 0x03, + ll3_BTN_LEFT = 0x04, + ll3_BTN_RIGHT = 0x05, +}; + +enum { + ll3_STICK_L_UP = 0x01, + ll3_STICK_L_RIGHT = 0x02, + ll3_STICK_L_DOWN = 0x03, + ll3_STICK_L_LEFT = 0x04, + ll3_STICK_R_UP = 0x05, + ll3_STICK_R_RIGHT = 0x06, + ll3_STICK_R_DOWN = 0x07, + ll3_STICK_R_LEFT = 0x08, +}; + +/* Get the version of the Theatrhythm IO API that this DLL supports. This + function should return a positive 16-bit integer, where the high byte is + the major version and the low byte is the minor version (as defined by the + Semantic Versioning standard). + + The latest API version as of this writing is 0x0100. */ + +uint16_t ll3_io_get_api_version(void); + +/* Initialize the IO DLL. This is the second function that will be called on + your DLL, after ll3_io_get_api_version. + + All subsequent calls to this API may originate from arbitrary threads. + + Minimum API version: 0x0100 */ + +HRESULT ll3_io_init(void); + + +/* Get the state of the cabinet's gameplay buttons as of the last poll. See + ll3_IO_GAMEBTN enum above for bit mask definitions. Inputs are split into + a left hand side set of inputs and a right hand side set of inputs: the bit + mappings are the same in both cases. + + All buttons are active-high, even though some buttons' electrical signals + on a real cabinet are active-low. + + Minimum API version: 0x0100 */ + +void ll3_io_get_btns(uint8_t *btn, uint8_t *stick); + +void ll3_io_read_coin_counter(uint16_t *coins, uint16_t *services); \ No newline at end of file diff --git a/ll3io/meson.build b/ll3io/meson.build new file mode 100644 index 0000000..1e48d4e --- /dev/null +++ b/ll3io/meson.build @@ -0,0 +1,16 @@ +ll3io_lib = static_library( + 'll3io', + name_prefix : '', + include_directories : inc, + implicit_include_directories : false, + c_pch : '../precompiled.h', + dependencies : [ + xinput_lib, + ], + sources : [ + 'll3io.c', + 'll3io.h', + 'config.c', + 'config.h', + ], +) diff --git a/meson.build b/meson.build index d1d341d..531bb88 100644 --- a/meson.build +++ b/meson.build @@ -55,6 +55,8 @@ subdir('util') subdir('gfxhook') subdir('sivaio') +subdir('ll3io') subdir('minihook') subdir('sivahook') +subdir('ll3hook') diff --git a/platform/netenv.c b/platform/netenv.c index f05f6a3..3be7b3a 100644 --- a/platform/netenv.c +++ b/platform/netenv.c @@ -67,6 +67,8 @@ static uint32_t WINAPI hook_IcmpSendEcho2( uint32_t ReplySize, uint32_t Timeout); +static uint32_t WINAPI hook_FlushIpNetTable(DWORD dwIfIndex); + /* Link pointers */ static uint32_t (WINAPI *next_GetAdaptersAddresses)( @@ -124,6 +126,9 @@ static const struct hook_symbol netenv_hook_syms[] = { .name = "IcmpSendEcho2", .patch = hook_IcmpSendEcho2, .link = (void **) &next_IcmpSendEcho2, + }, { + .name = "FlushIpNetTable", + .patch = hook_FlushIpNetTable, } }; @@ -294,7 +299,8 @@ static uint32_t WINAPI hook_GetAdaptersInfo( return ERROR_BUFFER_OVERFLOW; } - dprintf("Netenv: GetAdaptersInfo: Virtualized LAN configuration:\n"); + // This spams console on NesysService.exe, comment out for now + /*dprintf("Netenv: GetAdaptersInfo: Virtualized LAN configuration:\n"); dprintf("Netenv: Interface IP : %3i.%3i.%3i.%3i\n", (uint8_t) (netenv_ip_iface >> 24), (uint8_t) (netenv_ip_iface >> 16), @@ -311,7 +317,7 @@ static uint32_t WINAPI hook_GetAdaptersInfo( netenv_mac_addr[2], netenv_mac_addr[3], netenv_mac_addr[4], - netenv_mac_addr[5]); + netenv_mac_addr[5]);*/ memset(&iface, 0, sizeof(iface)); memset(&router, 0, sizeof(router)); @@ -410,7 +416,7 @@ static uint32_t WINAPI hook_GetIfTable( *pdwSize = sizeof(*row) + sizeof(DWORD); if (pIfTable == NULL || nbytes < sizeof(*row) + sizeof(DWORD)) { - return ERROR_BUFFER_OVERFLOW; + return ERROR_INSUFFICIENT_BUFFER; // was ERROR_BUFFER_OVERFLOW } pIfTable->dwNumEntries = 1; @@ -499,3 +505,8 @@ static uint32_t WINAPI hook_IcmpSendEcho2( return 1; } + +static uint32_t WINAPI hook_FlushIpNetTable(DWORD dwIfIndex) +{ + return 0; +}