From aed088df11990ee3bbe7a7c14dded16a9a5f2c2e Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Tue, 19 Nov 2019 14:45:00 +0100 Subject: [PATCH] dhcpcsvc: Implement DhcpRequestParams. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- configure | 1 + configure.ac | 1 + dlls/dhcpcsvc/Makefile.in | 1 + dlls/dhcpcsvc/dhcpcsvc.c | 78 +++++++++++++++-- dlls/dhcpcsvc/tests/Makefile.in | 5 ++ dlls/dhcpcsvc/tests/dhcpcsvc.c | 143 ++++++++++++++++++++++++++++++++ 6 files changed, 223 insertions(+), 6 deletions(-) create mode 100644 dlls/dhcpcsvc/tests/Makefile.in create mode 100644 dlls/dhcpcsvc/tests/dhcpcsvc.c diff --git a/configure b/configure index fb29dcfae5d..4de04f3575f 100755 --- a/configure +++ b/configure @@ -20345,6 +20345,7 @@ wine_fn_config_makefile dlls/ddrawex/tests enable_tests wine_fn_config_makefile dlls/devenum enable_devenum wine_fn_config_makefile dlls/devenum/tests enable_tests wine_fn_config_makefile dlls/dhcpcsvc enable_dhcpcsvc +wine_fn_config_makefile dlls/dhcpcsvc/tests enable_tests wine_fn_config_makefile dlls/dhtmled.ocx enable_dhtmled_ocx wine_fn_config_makefile dlls/difxapi enable_difxapi wine_fn_config_makefile dlls/dinput enable_dinput diff --git a/configure.ac b/configure.ac index 22ce5f33a38..93a74a27c86 100644 --- a/configure.ac +++ b/configure.ac @@ -3192,6 +3192,7 @@ WINE_CONFIG_MAKEFILE(dlls/ddrawex/tests) WINE_CONFIG_MAKEFILE(dlls/devenum) WINE_CONFIG_MAKEFILE(dlls/devenum/tests) WINE_CONFIG_MAKEFILE(dlls/dhcpcsvc) +WINE_CONFIG_MAKEFILE(dlls/dhcpcsvc/tests) WINE_CONFIG_MAKEFILE(dlls/dhtmled.ocx) WINE_CONFIG_MAKEFILE(dlls/difxapi) WINE_CONFIG_MAKEFILE(dlls/dinput) diff --git a/dlls/dhcpcsvc/Makefile.in b/dlls/dhcpcsvc/Makefile.in index 435cbfa410d..47ab04c690c 100644 --- a/dlls/dhcpcsvc/Makefile.in +++ b/dlls/dhcpcsvc/Makefile.in @@ -1,4 +1,5 @@ MODULE = dhcpcsvc.dll +IMPORTLIB = dhcpcsvc EXTRADLLFLAGS = -mno-cygwin diff --git a/dlls/dhcpcsvc/dhcpcsvc.c b/dlls/dhcpcsvc/dhcpcsvc.c index 95a467151b6..d5df635012b 100644 --- a/dlls/dhcpcsvc/dhcpcsvc.c +++ b/dlls/dhcpcsvc/dhcpcsvc.c @@ -1,5 +1,6 @@ /* * Copyright 2011 Stefan Leichter + * Copyright 2019 Hans Leidekker for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,7 +21,12 @@ #include "windef.h" #include "winbase.h" #include "dhcpcsdk.h" +#include "winioctl.h" +#define WINE_MOUNTMGR_EXTENSIONS +#include "ddk/mountmgr.h" + #include "wine/debug.h" +#include "wine/heap.h" WINE_DEFAULT_DEBUG_CHANNEL(dhcpcsvc); @@ -51,11 +57,71 @@ DWORD WINAPI DhcpCApiInitialize(LPDWORD version) return ERROR_SUCCESS; } -DWORD WINAPI DhcpRequestParams( DWORD flags, void *reserved, WCHAR *adaptername, DHCPCAPI_CLASSID *classid, - DHCPCAPI_PARAMS_ARRAY sendparams, DHCPCAPI_PARAMS_ARRAY recdparams, - BYTE *buffer, DWORD *size, WCHAR *requestidstr ) +DWORD WINAPI DhcpRequestParams( DWORD flags, void *reserved, WCHAR *adapter, DHCPCAPI_CLASSID *class_id, + DHCPCAPI_PARAMS_ARRAY send_params, DHCPCAPI_PARAMS_ARRAY recv_params, BYTE *buf, + DWORD *buflen, WCHAR *request_id ) { - FIXME("(%08x, %p, %s, %p, %u, %u, %p, %p, %s): stub\n", flags, reserved, debugstr_w(adaptername), classid, - sendparams.nParams, recdparams.nParams, buffer, size, debugstr_w(requestidstr)); - return ERROR_SUCCESS; + struct mountmgr_dhcp_request_params *query; + DWORD i, size, err = ERROR_OUTOFMEMORY; + BYTE *src, *dst; + HANDLE mgr; + + TRACE( "(%08x, %p, %s, %p, %u, %u, %p, %p, %s)\n", flags, reserved, debugstr_w(adapter), class_id, + send_params.nParams, recv_params.nParams, buf, buflen, debugstr_w(request_id) ); + + if (!adapter || lstrlenW(adapter) > IF_MAX_STRING_SIZE || !buflen) return ERROR_INVALID_PARAMETER; + if (flags != DHCPCAPI_REQUEST_SYNCHRONOUS) FIXME( "unsupported flags %08x\n", flags ); + + for (i = 0; i < send_params.nParams; i++) + FIXME( "send option %u not supported\n", send_params.Params->OptionId ); + + mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, 0, 0 ); + if (mgr == INVALID_HANDLE_VALUE) return GetLastError(); + + size = FIELD_OFFSET(struct mountmgr_dhcp_request_params, params[recv_params.nParams]) + *buflen; + if (!(query = heap_alloc_zero( size ))) goto done; + + for (i = 0; i < recv_params.nParams; i++) query->params[i].id = recv_params.Params[i].OptionId; + query->count = recv_params.nParams; + lstrcpyW( query->adapter, adapter ); + + if (!DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_DHCP_REQUEST_PARAMS, query, size, query, size, NULL, NULL )) + { + err = GetLastError(); + if (err == ERROR_MORE_DATA) *buflen = query->size - (size - *buflen); + goto done; + } + + dst = buf; + for (i = 0; i < query->count; i++) + { + if (buf) + { + recv_params.Params[i].OptionId = query->params[i].id; + recv_params.Params[i].IsVendor = FALSE; /* FIXME */ + if (query->params[i].size) + { + src = (BYTE *)query + query->params[i].offset; + memcpy( dst, src, query->params[i].size ); + + recv_params.Params[i].Data = dst; + recv_params.Params[i].nBytesData = query->params[i].size; + } + else + { + recv_params.Params[i].Data = NULL; + recv_params.Params[i].nBytesData = 0; + } + } + dst += query->params[i].size; + } + + *buflen = dst - buf; + err = ERROR_SUCCESS; + +done: + heap_free( query ); + CloseHandle( mgr ); + return err; } diff --git a/dlls/dhcpcsvc/tests/Makefile.in b/dlls/dhcpcsvc/tests/Makefile.in new file mode 100644 index 00000000000..47440eb2cd4 --- /dev/null +++ b/dlls/dhcpcsvc/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = dhcpcsvc.dll +IMPORTS = dhcpcsvc iphlpapi + +C_SRCS = \ + dhcpcsvc.c diff --git a/dlls/dhcpcsvc/tests/dhcpcsvc.c b/dlls/dhcpcsvc/tests/dhcpcsvc.c new file mode 100644 index 00000000000..8b47fe57d55 --- /dev/null +++ b/dlls/dhcpcsvc/tests/dhcpcsvc.c @@ -0,0 +1,143 @@ +/* + * Copyright 2019 Hans Leidekker for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include "winsock2.h" +#include "windef.h" +#include "winbase.h" +#include "iphlpapi.h" +#include "dhcpcsdk.h" +#include "wine/test.h" + +static IP_ADAPTER_ADDRESSES *get_adapters(void) +{ + ULONG err, size = 1024; + IP_ADAPTER_ADDRESSES *ret = HeapAlloc( GetProcessHeap(), 0, size ); + for (;;) + { + err = GetAdaptersAddresses( AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, + NULL, ret, &size ); + if (err != ERROR_BUFFER_OVERFLOW) break; + ret = HeapReAlloc( GetProcessHeap(), 0, ret, size ); + } + if (err == ERROR_SUCCESS) return ret; + HeapFree( GetProcessHeap(), 0, ret ); + return NULL; +} + +static void test_DhcpRequestParams(void) +{ + static WCHAR nosuchW[] = {'n','o','s','u','c','h','a','d','a','p','t','e','r',0}; + DHCPCAPI_PARAMS params[6]; + DHCPCAPI_PARAMS_ARRAY send_params, recv_params; + IP_ADAPTER_ADDRESSES *adapters, *ptr; + BYTE *buf; + WCHAR name[MAX_ADAPTER_NAME_LENGTH + 1]; + DWORD err, size, i; + + if (!(adapters = get_adapters())) return; + + for (ptr = adapters; ptr; ptr = ptr->Next) + { + MultiByteToWideChar( CP_ACP, 0, ptr->AdapterName, -1, name, ARRAY_SIZE(name) ); + trace( "adapter '%s' type %u dhcpv4 enabled %d\n", wine_dbgstr_w(ptr->Description), ptr->IfType, ptr->Dhcpv4Enabled ); + + if (ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK) continue; + + memset( &send_params, 0, sizeof(send_params) ); + memset( &recv_params, 0, sizeof(recv_params) ); + err = DhcpRequestParams( DHCPCAPI_REQUEST_SYNCHRONOUS, NULL, NULL, NULL, send_params, recv_params, NULL, NULL, NULL ); + ok( err == ERROR_INVALID_PARAMETER, "got %u\n", err ); + + err = DhcpRequestParams( DHCPCAPI_REQUEST_SYNCHRONOUS, NULL, nosuchW, NULL, send_params, recv_params, NULL, NULL, NULL ); + ok( err == ERROR_INVALID_PARAMETER, "got %u\n", err ); + + err = DhcpRequestParams( DHCPCAPI_REQUEST_SYNCHRONOUS, NULL, name, NULL, send_params, recv_params, NULL, NULL, NULL ); + ok( err == ERROR_INVALID_PARAMETER, "got %u\n", err ); + + size = 0; + err = DhcpRequestParams( DHCPCAPI_REQUEST_SYNCHRONOUS, NULL, name, NULL, send_params, recv_params, NULL, &size, NULL ); + ok( err == ERROR_INVALID_PARAMETER, "got %u\n", err ); + + memset( params, 0, sizeof(params) ); + params[0].OptionId = OPTION_SUBNET_MASK; + params[1].OptionId = OPTION_ROUTER_ADDRESS; + params[2].OptionId = OPTION_HOST_NAME; + params[3].OptionId = OPTION_DOMAIN_NAME; + params[4].OptionId = OPTION_BROADCAST_ADDRESS; + params[5].OptionId = OPTION_MSFT_IE_PROXY; + recv_params.nParams = 6; + recv_params.Params = params; + + size = 0; + buf = HeapAlloc( GetProcessHeap(), 0, size ); + err = DhcpRequestParams( DHCPCAPI_REQUEST_SYNCHRONOUS, NULL, name, NULL, send_params, recv_params, + buf, &size, NULL ); + while (err == ERROR_MORE_DATA) + { + buf = HeapReAlloc( GetProcessHeap(), 0, buf, size ); + err = DhcpRequestParams( DHCPCAPI_REQUEST_SYNCHRONOUS, NULL, name, NULL, send_params, recv_params, + buf, &size, NULL ); + } + if (err == ERROR_SUCCESS) + { + for (i = 0; i < ARRAY_SIZE(params); i++) + { + switch( params[i].OptionId ) + { + case OPTION_SUBNET_MASK: + case OPTION_ROUTER_ADDRESS: + case OPTION_BROADCAST_ADDRESS: + if (params[i].Data) + { + ok( params[i].nBytesData == sizeof(DWORD), "got %u\n", params[i].nBytesData ); + trace( "%u: Data %p (%08x) nBytesData %u OptionId %u Flags %08x IsVendor %d\n", + i, params[i].Data, *(DWORD *)params[i].Data, params[i].nBytesData, params[i].OptionId, + params[i].Flags, params[i].IsVendor ); + } + break; + case OPTION_HOST_NAME: + case OPTION_DOMAIN_NAME: + case OPTION_MSFT_IE_PROXY: + if (params[i].Data) + { + char *str = HeapAlloc( GetProcessHeap(), 0, params[i].nBytesData + 1 ); + memcpy( str, params[i].Data, params[i].nBytesData ); + str[params[i].nBytesData] = 0; + trace( "%u: Data %p (%s) nBytesData %u OptionId %u Flags %08x IsVendor %d\n", + i, params[i].Data, str, params[i].nBytesData, params[i].OptionId, + params[i].Flags, params[i].IsVendor ); + HeapFree( GetProcessHeap(), 0, str ); + } + break; + default: + ok( 0, "unexpected option %u\n", params[i].OptionId ); + break; + } + } + } + HeapFree( GetProcessHeap(), 0, buf ); + } + HeapFree( GetProcessHeap(), 0, adapters ); +} + +START_TEST(dhcpcsvc) +{ + test_DhcpRequestParams(); +}