Signed-off-by: Isabella Bosia ibosia@codeweavers.com --- dlls/iphlpapi/iphlpapi_main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index c039086229..ddde081950 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -1008,12 +1008,19 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index WCHAR *dst; DWORD buflen, type; INTERNAL_IF_OPER_STATUS status; + NET_LUID luid; + GUID guid;
memset(aa, 0, sizeof(IP_ADAPTER_ADDRESSES)); aa->u.s.Length = sizeof(IP_ADAPTER_ADDRESSES); aa->u.s.IfIndex = index;
- sprintf(ptr, "{%08x-0000-0000-0000-000000000000}", index); + ConvertInterfaceIndexToLuid(index, &luid); + ConvertInterfaceLuidToGuid(&luid, &guid); + sprintf(ptr, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], + guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], + guid.Data4[6], guid.Data4[7]); aa->AdapterName = ptr; ptr += 39;
@@ -1786,7 +1793,7 @@ DWORD WINAPI GetIfEntry2( MIB_IF_ROW2 *row2 ) row2->InterfaceLuid.Info.NetLuidIndex = row.dwIndex; row2->InterfaceLuid.Info.IfType = row.dwType; row2->InterfaceIndex = row.dwIndex; - row2->InterfaceGuid.Data1 = row.dwIndex; + ConvertInterfaceLuidToGuid( &row2->InterfaceLuid, &row2->InterfaceGuid ); row2->Type = row.dwType; row2->Mtu = row.dwMtu; MultiByteToWideChar( CP_UNIXCP, 0, (const char *)row.bDescr, -1, row2->Description, len );
Signed-off-by: Isabella Bosia ibosia@codeweavers.com --- dlls/iphlpapi/iphlpapi_main.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index ddde081950..81c4992ac7 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -3207,6 +3207,7 @@ DWORD WINAPI ConvertInterfaceLuidToGuid(const NET_LUID *luid, GUID *guid)
memset( guid, 0, sizeof(*guid) ); guid->Data1 = luid->Info.NetLuidIndex; + memcpy( guid->Data4+2, "NetDev", 6 ); return NO_ERROR; }
This really belongs to ndis.sys, but it's in mountmgr to reduce the number of winedevice processes.
Signed-off-by: Isabella Bosia ibosia@codeweavers.com --- dlls/mountmgr.sys/Makefile.in | 3 +- dlls/mountmgr.sys/mountmgr.c | 4 ++ dlls/mountmgr.sys/mountmgr.h | 1 + dlls/mountmgr.sys/ndis.c | 98 +++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 dlls/mountmgr.sys/ndis.c
diff --git a/dlls/mountmgr.sys/Makefile.in b/dlls/mountmgr.sys/Makefile.in index e229164280..fe3871366b 100644 --- a/dlls/mountmgr.sys/Makefile.in +++ b/dlls/mountmgr.sys/Makefile.in @@ -9,4 +9,5 @@ C_SRCS = \ dbus.c \ device.c \ diskarb.c \ - mountmgr.c + mountmgr.c \ + ndis.c diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c index 1961eab983..4962e11596 100644 --- a/dlls/mountmgr.sys/mountmgr.c +++ b/dlls/mountmgr.sys/mountmgr.c @@ -583,6 +583,7 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) static const WCHAR harddiskW[] = {'\','D','r','i','v','e','r','\','H','a','r','d','d','i','s','k',0}; static const WCHAR driver_serialW[] = {'\','D','r','i','v','e','r','\','S','e','r','i','a','l',0}; static const WCHAR driver_parallelW[] = {'\','D','r','i','v','e','r','\','P','a','r','a','l','l','e','l',0}; + static const WCHAR driver_ndisW[] = {'\','D','r','i','v','e','r','\','N','D','I','S',0}; static const WCHAR devicemapW[] = {'H','A','R','D','W','A','R','E','\','D','E','V','I','C','E','M','A','P','\','S','c','s','i',0};
#ifdef _WIN64 @@ -643,5 +644,8 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) RtlInitUnicodeString( &nameW, driver_parallelW ); IoCreateDriver( &nameW, parallel_driver_entry );
+ RtlInitUnicodeString( &nameW, driver_ndisW ); + IoCreateDriver( &nameW, ndis_driver_entry ); + return status; } diff --git a/dlls/mountmgr.sys/mountmgr.h b/dlls/mountmgr.sys/mountmgr.h index 5fb43119c6..4ee2ba16e8 100644 --- a/dlls/mountmgr.sys/mountmgr.h +++ b/dlls/mountmgr.sys/mountmgr.h @@ -65,6 +65,7 @@ extern NTSTATUS query_unix_device( ULONGLONG unix_dev, enum device_type *type, extern NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI serial_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI parallel_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN; +extern NTSTATUS WINAPI ndis_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN;
/* SCSI entry functions */
diff --git a/dlls/mountmgr.sys/ndis.c b/dlls/mountmgr.sys/ndis.c new file mode 100644 index 0000000000..0a3f87d410 --- /dev/null +++ b/dlls/mountmgr.sys/ndis.c @@ -0,0 +1,98 @@ +/* + * NDIS Ioctl support + * + * Copyright 2020 Isabella Bosia + * + * 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 <stdarg.h> + +#define NONAMELESSUNION +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "winioctl.h" +#include "ntddndis.h" +#include "ddk/wdm.h" +#include "ddk/ndis.h" +#include "winreg.h" +#include "wine/debug.h" + +#include <winsock2.h> +#include <ws2ipdef.h> +#include <iphlpapi.h> +#include <netioapi.h> + +WINE_DEFAULT_DEBUG_CHANNEL(ndis); + +static void add_key(const char *guidstr, const MIB_IF_ROW2 *netdev) +{ + HKEY card_key; + char keyname[100]; + char description[MAX_ADAPTER_NAME_LENGTH + 4]; + + snprintf( keyname, sizeof(keyname), + "Software\Microsoft\Windows NT\CurrentVersion\NetworkCards\%d", netdev->InterfaceIndex ); + WideCharToMultiByte( CP_ACP, 0, netdev->Description, -1, description, sizeof(description), NULL, NULL ); + + if (RegCreateKeyExA( HKEY_LOCAL_MACHINE, keyname, 0, NULL, + REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &card_key, NULL ) == ERROR_SUCCESS) + { + RegSetValueExA( card_key, "Description", 0, REG_SZ, (unsigned char *)description, strlen(description) ); + RegSetValueExA( card_key, "ServiceName", 0, REG_SZ, (unsigned char *)guidstr, strlen(guidstr) ); + RegCloseKey( card_key ); + } +} + +static int add_device(DRIVER_OBJECT *driver, const char *guidstr, MIB_IF_ROW2 *netdev) +{ + return 1; +} + +static void create_network_devices(DRIVER_OBJECT *driver) +{ + MIB_IF_TABLE2 *table; + ULONG i; + + if (GetIfTable2( &table ) != NO_ERROR) + return; + + for (i = 0; i < table->NumEntries; i++) + { + GUID *guid = &table->Table[i].InterfaceGuid; + char guidstr[39]; + + sprintf( guidstr, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], + guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5], + guid->Data4[6], guid->Data4[7] ); + if (add_device( driver, guidstr, &table->Table[i] )) + add_key( guidstr, &table->Table[i] ); + } + + FreeMibTable( table ); +} + +NTSTATUS WINAPI ndis_driver_entry(DRIVER_OBJECT *driver, UNICODE_STRING *path) +{ + TRACE("(%p, %s)\n", driver, debugstr_w(path->Buffer)); + + create_network_devices( driver ); + + return STATUS_SUCCESS; +}
Hello Isabella, thanks for the patch! I have a few comments inlined.
On 8/25/20 9:32 AM, Isabella Bosia wrote:
This really belongs to ndis.sys, but it's in mountmgr to reduce the number of winedevice processes.
Perhaps a better way to avoid this would be to use service groups? I.e. LoadOrderGroup, set by the service registry information in wine.inf.
Signed-off-by: Isabella Bosia ibosia@codeweavers.com
dlls/mountmgr.sys/Makefile.in | 3 +- dlls/mountmgr.sys/mountmgr.c | 4 ++ dlls/mountmgr.sys/mountmgr.h | 1 + dlls/mountmgr.sys/ndis.c | 98 +++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 dlls/mountmgr.sys/ndis.c
diff --git a/dlls/mountmgr.sys/Makefile.in b/dlls/mountmgr.sys/Makefile.in index e229164280..fe3871366b 100644 --- a/dlls/mountmgr.sys/Makefile.in +++ b/dlls/mountmgr.sys/Makefile.in @@ -9,4 +9,5 @@ C_SRCS = \ dbus.c \ device.c \ diskarb.c \
- mountmgr.c
- mountmgr.c \
- ndis.c
diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c index 1961eab983..4962e11596 100644 --- a/dlls/mountmgr.sys/mountmgr.c +++ b/dlls/mountmgr.sys/mountmgr.c @@ -583,6 +583,7 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) static const WCHAR harddiskW[] = {'\','D','r','i','v','e','r','\','H','a','r','d','d','i','s','k',0}; static const WCHAR driver_serialW[] = {'\','D','r','i','v','e','r','\','S','e','r','i','a','l',0}; static const WCHAR driver_parallelW[] = {'\','D','r','i','v','e','r','\','P','a','r','a','l','l','e','l',0};
- static const WCHAR driver_ndisW[] = {'\','D','r','i','v','e','r','\','N','D','I','S',0}; static const WCHAR devicemapW[] = {'H','A','R','D','W','A','R','E','\','D','E','V','I','C','E','M','A','P','\','S','c','s','i',0};
#ifdef _WIN64 @@ -643,5 +644,8 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) RtlInitUnicodeString( &nameW, driver_parallelW ); IoCreateDriver( &nameW, parallel_driver_entry );
- RtlInitUnicodeString( &nameW, driver_ndisW );
- IoCreateDriver( &nameW, ndis_driver_entry );
- return status;
} diff --git a/dlls/mountmgr.sys/mountmgr.h b/dlls/mountmgr.sys/mountmgr.h index 5fb43119c6..4ee2ba16e8 100644 --- a/dlls/mountmgr.sys/mountmgr.h +++ b/dlls/mountmgr.sys/mountmgr.h @@ -65,6 +65,7 @@ extern NTSTATUS query_unix_device( ULONGLONG unix_dev, enum device_type *type, extern NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI serial_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI parallel_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN; +extern NTSTATUS WINAPI ndis_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN;
/* SCSI entry functions */
diff --git a/dlls/mountmgr.sys/ndis.c b/dlls/mountmgr.sys/ndis.c new file mode 100644 index 0000000000..0a3f87d410 --- /dev/null +++ b/dlls/mountmgr.sys/ndis.c @@ -0,0 +1,98 @@ +/*
- NDIS Ioctl support
- Copyright 2020 Isabella Bosia
- 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 <stdarg.h>
+#define NONAMELESSUNION +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "winioctl.h" +#include "ntddndis.h" +#include "ddk/wdm.h" +#include "ddk/ndis.h" +#include "winreg.h" +#include "wine/debug.h"
+#include <winsock2.h> +#include <ws2ipdef.h> +#include <iphlpapi.h> +#include <netioapi.h>
+WINE_DEFAULT_DEBUG_CHANNEL(ndis);
+static void add_key(const char *guidstr, const MIB_IF_ROW2 *netdev) +{
- HKEY card_key;
- char keyname[100];
- char description[MAX_ADAPTER_NAME_LENGTH + 4];
- snprintf( keyname, sizeof(keyname),
"Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards\\%d", netdev->InterfaceIndex );
- WideCharToMultiByte( CP_ACP, 0, netdev->Description, -1, description, sizeof(description), NULL, NULL );
- if (RegCreateKeyExA( HKEY_LOCAL_MACHINE, keyname, 0, NULL,
REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &card_key, NULL ) == ERROR_SUCCESS)
- {
RegSetValueExA( card_key, "Description", 0, REG_SZ, (unsigned char *)description, strlen(description) );
RegSetValueExA( card_key, "ServiceName", 0, REG_SZ, (unsigned char *)guidstr, strlen(guidstr) );
As annoying as it is, we probably want these to be W APIs. [On the other hand, if we do put this in ndis.sys, it gets probably much less annoying.]
RegCloseKey( card_key );
- }
+}
+static int add_device(DRIVER_OBJECT *driver, const char *guidstr, MIB_IF_ROW2 *netdev) +{
- return 1;
+}
I think this function would be better introduced in the following patch.
+static void create_network_devices(DRIVER_OBJECT *driver) +{
- MIB_IF_TABLE2 *table;
- ULONG i;
- if (GetIfTable2( &table ) != NO_ERROR)
return;
- for (i = 0; i < table->NumEntries; i++)
- {
GUID *guid = &table->Table[i].InterfaceGuid;
char guidstr[39];
sprintf( guidstr, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1],
guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5],
guid->Data4[6], guid->Data4[7] );
if (add_device( driver, guidstr, &table->Table[i] ))
add_key( guidstr, &table->Table[i] );
- }
- FreeMibTable( table );
+}
+NTSTATUS WINAPI ndis_driver_entry(DRIVER_OBJECT *driver, UNICODE_STRING *path) +{
- TRACE("(%p, %s)\n", driver, debugstr_w(path->Buffer));
- create_network_devices( driver );
- return STATUS_SUCCESS;
+}
Signed-off-by: Isabella Bosia ibosia@codeweavers.com --- dlls/mountmgr.sys/ndis.c | 105 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+)
diff --git a/dlls/mountmgr.sys/ndis.c b/dlls/mountmgr.sys/ndis.c index 0a3f87d410..379d70e6d0 100644 --- a/dlls/mountmgr.sys/ndis.c +++ b/dlls/mountmgr.sys/ndis.c @@ -40,6 +40,86 @@
WINE_DEFAULT_DEBUG_CHANNEL(ndis);
+static void query_global_stats(IRP *irp, const MIB_IF_ROW2 *netdev) +{ + IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); + void *response = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority ); + DWORD len = irpsp->Parameters.DeviceIoControl.OutputBufferLength; + DWORD oid; + + if (irpsp->Parameters.DeviceIoControl.InputBufferLength != sizeof(oid)) + { + irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER; + return; + } + oid = *(DWORD *)irp->AssociatedIrp.SystemBuffer; + + switch (oid) + { + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + { + if (len < sizeof(NDIS_MEDIUM)) + { + irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER; + break; + } + *(NDIS_MEDIUM *)response = netdev->MediaType; + irp->IoStatus.Information = sizeof(netdev->MediaType); + irp->IoStatus.u.Status = STATUS_SUCCESS; + break; + } + case OID_802_3_PERMANENT_ADDRESS: + { + irp->IoStatus.Information = netdev->PhysicalAddressLength; + if (len < netdev->PhysicalAddressLength) + irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER; + else + memcpy( response, netdev->PermanentPhysicalAddress, sizeof(netdev->PermanentPhysicalAddress) ); + break; + } + case OID_802_3_CURRENT_ADDRESS: + { + irp->IoStatus.Information = netdev->PhysicalAddressLength; + if (len < netdev->PhysicalAddressLength) + irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER; + else + memcpy( response, netdev->PhysicalAddress, sizeof(netdev->PhysicalAddress) ); + break; + + } + default: + FIXME( "Unsupported OID %x\n", oid ); + irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED; + break; + } +} + +static NTSTATUS WINAPI ndis_ioctl(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); + MIB_IF_ROW2 *netdev = device->DeviceExtension; + + TRACE( "ioctl %x insize %u outsize %u\n", + irpsp->Parameters.DeviceIoControl.IoControlCode, + irpsp->Parameters.DeviceIoControl.InputBufferLength, + irpsp->Parameters.DeviceIoControl.OutputBufferLength ); + + switch (irpsp->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_NDIS_QUERY_GLOBAL_STATS: + query_global_stats(irp, netdev); + break; + default: + FIXME( "ioctl %x not supported\n", irpsp->Parameters.DeviceIoControl.IoControlCode ); + irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED; + break; + } + + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return STATUS_SUCCESS; +} + static void add_key(const char *guidstr, const MIB_IF_ROW2 *netdev) { HKEY card_key; @@ -61,6 +141,29 @@ static void add_key(const char *guidstr, const MIB_IF_ROW2 *netdev)
static int add_device(DRIVER_OBJECT *driver, const char *guidstr, MIB_IF_ROW2 *netdev) { + char data[300]; + ANSI_STRING nameA, linkA; + UNICODE_STRING nameW, linkW; + DEVICE_OBJECT *device; + NTSTATUS status; + + snprintf( data, sizeof(data), "\Device\%s", guidstr ); + RtlInitAnsiString( &nameA, data ); + RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ); + + snprintf( data, sizeof(data), "\DosDevices\%s", guidstr ); + RtlInitAnsiString( &linkA, data ); + RtlAnsiStringToUnicodeString( &linkW, &linkA, TRUE ); + + if (!(status = IoCreateDevice( driver, sizeof(*netdev), &nameW, 0, 0, FALSE, &device ))) + status = IoCreateSymbolicLink( &linkW, &nameW ); + if (status) + { + FIXME( "failed to create device error %x\n", status ); + return 0; + } + + memcpy( device->DeviceExtension, netdev, sizeof(*netdev) ); return 1; }
@@ -92,6 +195,8 @@ NTSTATUS WINAPI ndis_driver_entry(DRIVER_OBJECT *driver, UNICODE_STRING *path) { TRACE("(%p, %s)\n", driver, debugstr_w(path->Buffer));
+ driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ndis_ioctl; + create_network_devices( driver );
return STATUS_SUCCESS;
On 8/25/20 9:32 AM, Isabella Bosia wrote:
Signed-off-by: Isabella Bosia ibosia@codeweavers.com
dlls/mountmgr.sys/ndis.c | 105 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+)
This patch could probably be split up: one patch to create the device, and maybe even split up the rest by individual ioctls.
diff --git a/dlls/mountmgr.sys/ndis.c b/dlls/mountmgr.sys/ndis.c index 0a3f87d410..379d70e6d0 100644 --- a/dlls/mountmgr.sys/ndis.c +++ b/dlls/mountmgr.sys/ndis.c @@ -40,6 +40,86 @@
WINE_DEFAULT_DEBUG_CHANNEL(ndis);
+static void query_global_stats(IRP *irp, const MIB_IF_ROW2 *netdev) +{
- IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
- void *response = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority );
- DWORD len = irpsp->Parameters.DeviceIoControl.OutputBufferLength;
- DWORD oid;
- if (irpsp->Parameters.DeviceIoControl.InputBufferLength != sizeof(oid))
- {
irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER;
return;
- }
- oid = *(DWORD *)irp->AssociatedIrp.SystemBuffer;
- switch (oid)
- {
- case OID_GEN_MEDIA_SUPPORTED:
- case OID_GEN_MEDIA_IN_USE:
- {
if (len < sizeof(NDIS_MEDIUM))
{
irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER;
break;
}
*(NDIS_MEDIUM *)response = netdev->MediaType;
irp->IoStatus.Information = sizeof(netdev->MediaType);
irp->IoStatus.u.Status = STATUS_SUCCESS;
break;
- }
- case OID_802_3_PERMANENT_ADDRESS:
- {
irp->IoStatus.Information = netdev->PhysicalAddressLength;
if (len < netdev->PhysicalAddressLength)
irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER;
else
memcpy( response, netdev->PermanentPhysicalAddress, sizeof(netdev->PermanentPhysicalAddress) );
break;
- }
- case OID_802_3_CURRENT_ADDRESS:
- {
irp->IoStatus.Information = netdev->PhysicalAddressLength;
if (len < netdev->PhysicalAddressLength)
irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER;
else
memcpy( response, netdev->PhysicalAddress, sizeof(netdev->PhysicalAddress) );
break;
- }
- default:
FIXME( "Unsupported OID %x\n", oid );
irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED;
break;
- }
+}
+static NTSTATUS WINAPI ndis_ioctl(DEVICE_OBJECT *device, IRP *irp) +{
- IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
- MIB_IF_ROW2 *netdev = device->DeviceExtension;
- TRACE( "ioctl %x insize %u outsize %u\n",
irpsp->Parameters.DeviceIoControl.IoControlCode,
irpsp->Parameters.DeviceIoControl.InputBufferLength,
irpsp->Parameters.DeviceIoControl.OutputBufferLength );
- switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
- {
- case IOCTL_NDIS_QUERY_GLOBAL_STATS:
query_global_stats(irp, netdev);
break;
- default:
FIXME( "ioctl %x not supported\n", irpsp->Parameters.DeviceIoControl.IoControlCode );
irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED;
break;
- }
- IoCompleteRequest( irp, IO_NO_INCREMENT );
- return STATUS_SUCCESS;
+}
static void add_key(const char *guidstr, const MIB_IF_ROW2 *netdev) { HKEY card_key; @@ -61,6 +141,29 @@ static void add_key(const char *guidstr, const MIB_IF_ROW2 *netdev)
static int add_device(DRIVER_OBJECT *driver, const char *guidstr, MIB_IF_ROW2 *netdev) {
- char data[300];
- ANSI_STRING nameA, linkA;
- UNICODE_STRING nameW, linkW;
- DEVICE_OBJECT *device;
- NTSTATUS status;
- snprintf( data, sizeof(data), "\Device\%s", guidstr );
- RtlInitAnsiString( &nameA, data );
- RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE );
- snprintf( data, sizeof(data), "\DosDevices\%s", guidstr );
- RtlInitAnsiString( &linkA, data );
- RtlAnsiStringToUnicodeString( &linkW, &linkA, TRUE );
- if (!(status = IoCreateDevice( driver, sizeof(*netdev), &nameW, 0, 0, FALSE, &device )))
status = IoCreateSymbolicLink( &linkW, &nameW );
- if (status)
- {
FIXME( "failed to create device error %x\n", status );
return 0;
- }
- memcpy( device->DeviceExtension, netdev, sizeof(*netdev) ); return 1;
}
@@ -92,6 +195,8 @@ NTSTATUS WINAPI ndis_driver_entry(DRIVER_OBJECT *driver, UNICODE_STRING *path) { TRACE("(%p, %s)\n", driver, debugstr_w(path->Buffer));
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ndis_ioctl;
create_network_devices( driver );
return STATUS_SUCCESS;
Signed-off-by: Isabella Bosia ibosia@codeweavers.com --- dlls/iphlpapi/tests/Makefile.in | 6 +- dlls/iphlpapi/tests/ndis.c | 157 ++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 dlls/iphlpapi/tests/ndis.c
diff --git a/dlls/iphlpapi/tests/Makefile.in b/dlls/iphlpapi/tests/Makefile.in index d813101354..2357f033bf 100644 --- a/dlls/iphlpapi/tests/Makefile.in +++ b/dlls/iphlpapi/tests/Makefile.in @@ -1,5 +1,7 @@ TESTDLL = iphlpapi.dll -IMPORTS = iphlpapi +IMPORTS = iphlpapi advapi32 ole32 +
C_SRCS = \ - iphlpapi.c + iphlpapi.c \ + ndis.c diff --git a/dlls/iphlpapi/tests/ndis.c b/dlls/iphlpapi/tests/ndis.c new file mode 100644 index 0000000000..bdefdd6594 --- /dev/null +++ b/dlls/iphlpapi/tests/ndis.c @@ -0,0 +1,157 @@ +/* + * Unit tests for ndis ioctls + * + * Copyright (c) 2020 Isabella Bosia + * + * 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 <windows.h> +#include <winioctl.h> +#include <ntddndis.h> +#include <winsock2.h> +#include <ws2ipdef.h> +#include <iphlpapi.h> +#include <netioapi.h> +#include <shlwapi.h> +#include <stdio.h> +#include <string.h> +#include "wine/test.h" + +static void test_device(const char *service_name, const MIB_IF_ROW2 *row) +{ + DWORD size; + int ret; + NDIS_MEDIUM medium; + UCHAR addr[IF_MAX_PHYS_ADDRESS_LENGTH]; + char target_path[48]; + char file_name[43]; + HANDLE netdev; + int oid; + BOOL device_needs_removing = FALSE; + DWORD err; + + ret = QueryDosDeviceA( service_name, target_path, sizeof(target_path) ); + err = GetLastError(); + ok( ret || err == ERROR_FILE_NOT_FOUND, "Couldn't query the device and can't handle this error\n" ); + + if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) + { + device_needs_removing = TRUE; + snprintf( target_path, sizeof(target_path), "\Device\%s", service_name ); + ok( DefineDosDeviceA( DDD_RAW_TARGET_PATH, service_name, target_path ) != 0, "DDD failed to create\n" ); + } + + snprintf( file_name, sizeof(file_name), "\\.\%s", service_name ); + netdev = CreateFileA( file_name, 0, 1, NULL, 3, 0, NULL ); + if (netdev != INVALID_HANDLE_VALUE) + { + oid = OID_GEN_MEDIA_SUPPORTED; + ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS, + &oid, sizeof(oid), &medium, sizeof(medium), &size, NULL ); + ok( ret && medium == row->MediaType, "OID_GEN_MEDIA_SUPPORTED failed\n" ); + + oid = OID_GEN_MEDIA_IN_USE; + ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS, + &oid, sizeof(oid), &medium, sizeof(medium), &size, NULL ); + ok( ret && medium == row->MediaType, "OID_GEN_MEDIA_IN_USE failed\n" ); + + oid = OID_802_3_PERMANENT_ADDRESS; + ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS, + &oid, sizeof(oid), addr, sizeof(addr), &size, NULL ); + ok( ret, "OID_802_3_PERMANENT_ADDRESS failed\n" ); + ok( row->PhysicalAddressLength == size && !memcmp( row->PermanentPhysicalAddress, addr, size ), + "Wrong permanent address\n" ); + + oid = OID_802_3_CURRENT_ADDRESS; + ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS, + &oid, sizeof(oid), addr, sizeof(addr), &size, NULL ); + ok( ret, "OID_802_3_CURRENT_ADDRESS failed\n" ); + ok( row->PhysicalAddressLength == size && !memcmp( row->PhysicalAddress, addr, size ), + "Wrong current address\n" ); + } + else + skip( "Could not open device\n" ); + + if (device_needs_removing) + ok( DefineDosDeviceA( DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE, + service_name, target_path ) != 0, "DDD failed to remove\n" ); +} + +void test_ndis_ioctl(void) +{ + HKEY nics, sub_key; + LSTATUS ret; + char card[16]; + BYTE data[100]; + WCHAR description[100]; + DWORD size, type, i = 0; + + ret = RegOpenKeyExA( HKEY_LOCAL_MACHINE, + "Software\Microsoft\Windows NT\CurrentVersion\NetworkCards", 0, KEY_READ, &nics ); + ok( ret == ERROR_SUCCESS, "NetworkCards key missing\n" ); + + while (1) + { + MIB_IF_ROW2 row = { 0 }; + char service_name[39] = { 0 }; + WCHAR guidstrW[39]; + GUID guid; + + + size = sizeof(card); + ret = RegEnumKeyExA( nics, i, card, &size, NULL, NULL, NULL, NULL ); + if (ret != ERROR_SUCCESS) + break; + i++; + + ret = RegOpenKeyExA( nics, card, 0, KEY_READ, &sub_key ); + ok( ret == ERROR_SUCCESS, "Could not open network card subkey\n" ); + + size = sizeof(data); + ret = RegQueryValueExA( sub_key, "ServiceName", NULL, &type, data, &size ); + ok( ret == ERROR_SUCCESS && type == REG_SZ, "Wrong ServiceName\n" ); + + memcpy( service_name, data, size ); + MultiByteToWideChar( CP_ACP, 0, (char *)data, -1, guidstrW, ARRAY_SIZE(guidstrW) ); + CLSIDFromString( guidstrW, (LPCLSID)&guid ); + ConvertInterfaceGuidToLuid( &guid, &row.InterfaceLuid ); + + ret = GetIfEntry2(&row); + ok( ret == NO_ERROR, "GetIfEntry2 failed\n" ); + + ok( IsEqualGUID( &guid, &row.InterfaceGuid ), "Wrong ServiceName\n" ); + + size = sizeof(data); + ret = RegQueryValueExA( sub_key, "Description", NULL, &type, data, &size ); + MultiByteToWideChar( CP_ACP, 0, (char *)data, -1, description, ARRAY_SIZE(description) ); + ok( ret == ERROR_SUCCESS && type == REG_SZ, "Wrong Description\n" ); + + trace( "testing device <%s>\n", wine_dbgstr_w(description) ); + test_device( service_name, &row ); + + RegCloseKey( sub_key ); + } + + if (i == 0) + skip( "Network card subkeys missing\n" ); + + RegCloseKey( nics ); +} + +START_TEST(ndis) +{ + test_ndis_ioctl(); +}
On 8/25/20 9:32 AM, Isabella Bosia wrote:
Signed-off-by: Isabella Bosia ibosia@codeweavers.com
dlls/iphlpapi/tests/Makefile.in | 6 +- dlls/iphlpapi/tests/ndis.c | 157 ++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 dlls/iphlpapi/tests/ndis.c
diff --git a/dlls/iphlpapi/tests/Makefile.in b/dlls/iphlpapi/tests/Makefile.in index d813101354..2357f033bf 100644 --- a/dlls/iphlpapi/tests/Makefile.in +++ b/dlls/iphlpapi/tests/Makefile.in @@ -1,5 +1,7 @@ TESTDLL = iphlpapi.dll -IMPORTS = iphlpapi +IMPORTS = iphlpapi advapi32 ole32
C_SRCS = \
- iphlpapi.c
- iphlpapi.c \
- ndis.c
diff --git a/dlls/iphlpapi/tests/ndis.c b/dlls/iphlpapi/tests/ndis.c new file mode 100644 index 0000000000..bdefdd6594 --- /dev/null +++ b/dlls/iphlpapi/tests/ndis.c @@ -0,0 +1,157 @@ +/*
- Unit tests for ndis ioctls
- Copyright (c) 2020 Isabella Bosia
- 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 <windows.h> +#include <winioctl.h> +#include <ntddndis.h> +#include <winsock2.h> +#include <ws2ipdef.h> +#include <iphlpapi.h> +#include <netioapi.h> +#include <shlwapi.h> +#include <stdio.h> +#include <string.h> +#include "wine/test.h"
+static void test_device(const char *service_name, const MIB_IF_ROW2 *row) +{
- DWORD size;
- int ret;
- NDIS_MEDIUM medium;
- UCHAR addr[IF_MAX_PHYS_ADDRESS_LENGTH];
- char target_path[48];
- char file_name[43];
- HANDLE netdev;
- int oid;
- BOOL device_needs_removing = FALSE;
- DWORD err;
- ret = QueryDosDeviceA( service_name, target_path, sizeof(target_path) );
- err = GetLastError();
- ok( ret || err == ERROR_FILE_NOT_FOUND, "Couldn't query the device and can't handle this error\n" );
In general when writing tests you want to print, on failure, the actual returned error or output value, as well as (if appropriate) the value of GetLastError(). [For functions returning BOOL it's of course much less interesting to print the exact return value.]
Incidentally, storing GetLastError() in a local variable is somewhat redundant, especially when you use it directly in the next line...
- if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
- {
device_needs_removing = TRUE;
snprintf( target_path, sizeof(target_path), "\\Device\\%s", service_name );
ok( DefineDosDeviceA( DDD_RAW_TARGET_PATH, service_name, target_path ) != 0, "DDD failed to create\n" );
This is very weird. Have you encountered machines where there are no symlinks in "\GLOBAL??"?
It may be easier just to open the device by device path directly [i.e. with NtOpenFile].
- }
- snprintf( file_name, sizeof(file_name), "\\.\%s", service_name );
- netdev = CreateFileA( file_name, 0, 1, NULL, 3, 0, NULL );
Please use symbolic constants.
- if (netdev != INVALID_HANDLE_VALUE)
- {
oid = OID_GEN_MEDIA_SUPPORTED;
ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS,
&oid, sizeof(oid), &medium, sizeof(medium), &size, NULL );
ok( ret && medium == row->MediaType, "OID_GEN_MEDIA_SUPPORTED failed\n" );
Generally I think it's best to split this into two ok() calls.
oid = OID_GEN_MEDIA_IN_USE;
ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS,
&oid, sizeof(oid), &medium, sizeof(medium), &size, NULL );
ok( ret && medium == row->MediaType, "OID_GEN_MEDIA_IN_USE failed\n" );
oid = OID_802_3_PERMANENT_ADDRESS;
ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS,
&oid, sizeof(oid), addr, sizeof(addr), &size, NULL );
ok( ret, "OID_802_3_PERMANENT_ADDRESS failed\n" );
ok( row->PhysicalAddressLength == size && !memcmp( row->PermanentPhysicalAddress, addr, size ),
"Wrong permanent address\n" );
oid = OID_802_3_CURRENT_ADDRESS;
ret = DeviceIoControl( netdev, IOCTL_NDIS_QUERY_GLOBAL_STATS,
&oid, sizeof(oid), addr, sizeof(addr), &size, NULL );
ok( ret, "OID_802_3_CURRENT_ADDRESS failed\n" );
ok( row->PhysicalAddressLength == size && !memcmp( row->PhysicalAddress, addr, size ),
"Wrong current address\n" );
- }
- else
skip( "Could not open device\n" );
- if (device_needs_removing)
ok( DefineDosDeviceA( DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE,
service_name, target_path ) != 0, "DDD failed to remove\n" );
+}
+void test_ndis_ioctl(void)
Missing 'static'.
+{
- HKEY nics, sub_key;
- LSTATUS ret;
- char card[16];
- BYTE data[100];
- WCHAR description[100];
- DWORD size, type, i = 0;
- ret = RegOpenKeyExA( HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards", 0, KEY_READ, &nics );
- ok( ret == ERROR_SUCCESS, "NetworkCards key missing\n" );
- while (1)
- {
MIB_IF_ROW2 row = { 0 };
char service_name[39] = { 0 };
WCHAR guidstrW[39];
GUID guid;
size = sizeof(card);
ret = RegEnumKeyExA( nics, i, card, &size, NULL, NULL, NULL, NULL );
if (ret != ERROR_SUCCESS)
break;
i++;
ret = RegOpenKeyExA( nics, card, 0, KEY_READ, &sub_key );
ok( ret == ERROR_SUCCESS, "Could not open network card subkey\n" );
size = sizeof(data);
ret = RegQueryValueExA( sub_key, "ServiceName", NULL, &type, data, &size );
ok( ret == ERROR_SUCCESS && type == REG_SZ, "Wrong ServiceName\n" );
memcpy( service_name, data, size );
MultiByteToWideChar( CP_ACP, 0, (char *)data, -1, guidstrW, ARRAY_SIZE(guidstrW) );
You can use wide character string constants in test, so using W APIs would probably be simpler here.
CLSIDFromString( guidstrW, (LPCLSID)&guid );
ConvertInterfaceGuidToLuid( &guid, &row.InterfaceLuid );
ret = GetIfEntry2(&row);
ok( ret == NO_ERROR, "GetIfEntry2 failed\n" );
ok( IsEqualGUID( &guid, &row.InterfaceGuid ), "Wrong ServiceName\n" );
size = sizeof(data);
ret = RegQueryValueExA( sub_key, "Description", NULL, &type, data, &size );
MultiByteToWideChar( CP_ACP, 0, (char *)data, -1, description, ARRAY_SIZE(description) );
ok( ret == ERROR_SUCCESS && type == REG_SZ, "Wrong Description\n" );
trace( "testing device <%s>\n", wine_dbgstr_w(description) );
test_device( service_name, &row );
RegCloseKey( sub_key );
- }
- if (i == 0)
skip( "Network card subkeys missing\n" );
- RegCloseKey( nics );
+}
+START_TEST(ndis) +{
- test_ndis_ioctl();
+}