4 * Copyright 2014 Austin English
5 * Copyright 2016 André Hentschel
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
26 #define WIN32_NO_STATUS
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(ndis
);
42 static void query_global_stats(IRP
*irp
, const MIB_IF_ROW2
*netdev
)
44 IO_STACK_LOCATION
*irpsp
= IoGetCurrentIrpStackLocation( irp
);
45 void *response
= MmGetSystemAddressForMdlSafe( irp
->MdlAddress
, NormalPagePriority
);
46 DWORD len
= irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
49 if (irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
!= sizeof(oid
))
51 irp
->IoStatus
.u
.Status
= STATUS_INVALID_PARAMETER
;
54 oid
= *(DWORD
*)irp
->AssociatedIrp
.SystemBuffer
;
58 case OID_GEN_MEDIA_SUPPORTED
:
59 case OID_GEN_MEDIA_IN_USE
:
61 if (len
< sizeof(NDIS_MEDIUM
))
63 irp
->IoStatus
.u
.Status
= STATUS_INVALID_PARAMETER
;
66 *(NDIS_MEDIUM
*)response
= netdev
->MediaType
;
67 irp
->IoStatus
.Information
= sizeof(netdev
->MediaType
);
68 irp
->IoStatus
.u
.Status
= STATUS_SUCCESS
;
71 case OID_802_3_PERMANENT_ADDRESS
:
73 irp
->IoStatus
.Information
= netdev
->PhysicalAddressLength
;
74 if (len
< netdev
->PhysicalAddressLength
)
75 irp
->IoStatus
.u
.Status
= STATUS_INVALID_PARAMETER
;
77 memcpy( response
, netdev
->PermanentPhysicalAddress
, sizeof(netdev
->PermanentPhysicalAddress
) );
80 case OID_802_3_CURRENT_ADDRESS
:
82 irp
->IoStatus
.Information
= netdev
->PhysicalAddressLength
;
83 if (len
< netdev
->PhysicalAddressLength
)
84 irp
->IoStatus
.u
.Status
= STATUS_INVALID_PARAMETER
;
86 memcpy( response
, netdev
->PhysicalAddress
, sizeof(netdev
->PhysicalAddress
) );
91 FIXME( "Unsupported OID %lx\n", oid
);
92 irp
->IoStatus
.u
.Status
= STATUS_INVALID_PARAMETER
;
97 static NTSTATUS WINAPI
ndis_ioctl(DEVICE_OBJECT
*device
, IRP
*irp
)
99 IO_STACK_LOCATION
*irpsp
= IoGetCurrentIrpStackLocation( irp
);
100 MIB_IF_ROW2
*netdev
= device
->DeviceExtension
;
103 TRACE( "ioctl %lx insize %lu outsize %lu\n",
104 irpsp
->Parameters
.DeviceIoControl
.IoControlCode
,
105 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
,
106 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
);
108 switch (irpsp
->Parameters
.DeviceIoControl
.IoControlCode
)
110 case IOCTL_NDIS_QUERY_GLOBAL_STATS
:
111 query_global_stats(irp
, netdev
);
114 FIXME( "ioctl %lx not supported\n", irpsp
->Parameters
.DeviceIoControl
.IoControlCode
);
115 irp
->IoStatus
.u
.Status
= STATUS_NOT_SUPPORTED
;
119 status
= irp
->IoStatus
.u
.Status
;
120 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
124 static void add_key(const WCHAR
*guidstrW
, const MIB_IF_ROW2
*netdev
)
129 swprintf( keynameW
, ARRAY_SIZE(keynameW
), L
"Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards\\%d", netdev
->InterfaceIndex
);
130 if (RegCreateKeyExW( HKEY_LOCAL_MACHINE
, keynameW
, 0, NULL
,
131 REG_OPTION_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &card_key
, NULL
) == ERROR_SUCCESS
)
133 RegSetValueExW( card_key
, L
"Description", 0, REG_SZ
, (BYTE
*)netdev
->Description
, (lstrlenW(netdev
->Description
) + 1) * sizeof(WCHAR
) );
134 RegSetValueExW( card_key
, L
"ServiceName", 0, REG_SZ
, (BYTE
*)guidstrW
, (lstrlenW(guidstrW
) + 1) * sizeof(WCHAR
) );
135 RegCloseKey( card_key
);
139 static int add_device(DRIVER_OBJECT
*driver
, const WCHAR
*guidstrW
, MIB_IF_ROW2
*netdev
)
141 WCHAR nameW
[47], linkW
[51];
142 UNICODE_STRING name
, link
;
143 DEVICE_OBJECT
*device
;
146 swprintf( nameW
, ARRAY_SIZE(nameW
), L
"\\Device\\%s", guidstrW
);
147 RtlInitUnicodeString( &name
, nameW
);
149 swprintf( linkW
, ARRAY_SIZE(linkW
), L
"\\DosDevices\\%s", guidstrW
);
150 RtlInitUnicodeString( &link
, linkW
);
152 if (!(status
= IoCreateDevice( driver
, sizeof(*netdev
), &name
, 0, 0, FALSE
, &device
)))
153 status
= IoCreateSymbolicLink( &link
, &name
);
156 FIXME( "failed to create device error %lx\n", status
);
160 memcpy( device
->DeviceExtension
, netdev
, sizeof(*netdev
) );
165 static void create_network_devices(DRIVER_OBJECT
*driver
)
167 MIB_IF_TABLE2
*table
;
170 if (GetIfTable2( &table
) != NO_ERROR
)
173 for (i
= 0; i
< table
->NumEntries
; i
++)
175 GUID
*guid
= &table
->Table
[i
].InterfaceGuid
;
178 swprintf( guidstrW
, ARRAY_SIZE(guidstrW
), L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
179 guid
->Data1
, guid
->Data2
, guid
->Data3
, guid
->Data4
[0], guid
->Data4
[1],
180 guid
->Data4
[2], guid
->Data4
[3], guid
->Data4
[4], guid
->Data4
[5],
181 guid
->Data4
[6], guid
->Data4
[7] );
183 if (add_device( driver
, guidstrW
, &table
->Table
[i
] ))
184 add_key( guidstrW
, &table
->Table
[i
] );
187 FreeMibTable( table
);
190 NTSTATUS WINAPI
DriverEntry(DRIVER_OBJECT
*driver
, UNICODE_STRING
*path
)
192 TRACE("(%p, %s)\n", driver
, debugstr_w(path
->Buffer
));
194 driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ndis_ioctl
;
196 create_network_devices( driver
);
198 return STATUS_SUCCESS
;
201 NDIS_STATUS WINAPI
NdisAllocateMemoryWithTag(void **address
, UINT length
, ULONG tag
)
203 FIXME("(%p, %u, %lu): stub\n", address
, length
, tag
);
204 return NDIS_STATUS_FAILURE
;
207 void WINAPI
NdisAllocateSpinLock(NDIS_SPIN_LOCK
*lock
)
209 FIXME("(%p): stub\n", lock
);
212 void WINAPI
NdisRegisterProtocol(NDIS_STATUS
*status
, NDIS_HANDLE
*handle
,
213 NDIS_PROTOCOL_CHARACTERISTICS
*prot
, UINT len
)
215 FIXME("(%p, %p, %p, %u): stub\n", status
, handle
, prot
, len
);
216 *status
= NDIS_STATUS_FAILURE
;
219 CCHAR WINAPI
NdisSystemProcessorCount(void)
226 return si
.dwNumberOfProcessors
;