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 %x\n", oid
);
92 irp
->IoStatus
.u
.Status
= STATUS_NOT_SUPPORTED
;
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
;
102 TRACE( "ioctl %x insize %u outsize %u\n",
103 irpsp
->Parameters
.DeviceIoControl
.IoControlCode
,
104 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
,
105 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
);
107 switch (irpsp
->Parameters
.DeviceIoControl
.IoControlCode
)
109 case IOCTL_NDIS_QUERY_GLOBAL_STATS
:
110 query_global_stats(irp
, netdev
);
113 FIXME( "ioctl %x not supported\n", irpsp
->Parameters
.DeviceIoControl
.IoControlCode
);
114 irp
->IoStatus
.u
.Status
= STATUS_NOT_SUPPORTED
;
118 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
119 return STATUS_SUCCESS
;
122 static void add_key(const WCHAR
*guidstrW
, const MIB_IF_ROW2
*netdev
)
127 swprintf( keynameW
, ARRAY_SIZE(keynameW
), L
"Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards\\%d", netdev
->InterfaceIndex
);
128 if (RegCreateKeyExW( HKEY_LOCAL_MACHINE
, keynameW
, 0, NULL
,
129 REG_OPTION_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &card_key
, NULL
) == ERROR_SUCCESS
)
131 RegSetValueExW( card_key
, L
"Description", 0, REG_SZ
, (BYTE
*)netdev
->Description
, (lstrlenW(netdev
->Description
) + 1) * sizeof(WCHAR
) );
132 RegSetValueExW( card_key
, L
"ServiceName", 0, REG_SZ
, (BYTE
*)guidstrW
, (lstrlenW(guidstrW
) + 1) * sizeof(WCHAR
) );
133 RegCloseKey( card_key
);
137 static int add_device(DRIVER_OBJECT
*driver
, const WCHAR
*guidstrW
, MIB_IF_ROW2
*netdev
)
139 WCHAR nameW
[47], linkW
[51];
140 UNICODE_STRING name
, link
;
141 DEVICE_OBJECT
*device
;
144 swprintf( nameW
, ARRAY_SIZE(nameW
), L
"\\Device\\%s", guidstrW
);
145 RtlInitUnicodeString( &name
, nameW
);
147 swprintf( linkW
, ARRAY_SIZE(linkW
), L
"\\DosDevices\\%s", guidstrW
);
148 RtlInitUnicodeString( &link
, linkW
);
150 if (!(status
= IoCreateDevice( driver
, sizeof(*netdev
), &name
, 0, 0, FALSE
, &device
)))
151 status
= IoCreateSymbolicLink( &link
, &name
);
154 FIXME( "failed to create device error %x\n", status
);
158 memcpy( device
->DeviceExtension
, netdev
, sizeof(*netdev
) );
163 static void create_network_devices(DRIVER_OBJECT
*driver
)
165 MIB_IF_TABLE2
*table
;
168 if (GetIfTable2( &table
) != NO_ERROR
)
171 for (i
= 0; i
< table
->NumEntries
; i
++)
173 GUID
*guid
= &table
->Table
[i
].InterfaceGuid
;
176 swprintf( guidstrW
, ARRAY_SIZE(guidstrW
), L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
177 guid
->Data1
, guid
->Data2
, guid
->Data3
, guid
->Data4
[0], guid
->Data4
[1],
178 guid
->Data4
[2], guid
->Data4
[3], guid
->Data4
[4], guid
->Data4
[5],
179 guid
->Data4
[6], guid
->Data4
[7] );
181 if (add_device( driver
, guidstrW
, &table
->Table
[i
] ))
182 add_key( guidstrW
, &table
->Table
[i
] );
185 FreeMibTable( table
);
188 NTSTATUS WINAPI
DriverEntry(DRIVER_OBJECT
*driver
, UNICODE_STRING
*path
)
190 TRACE("(%p, %s)\n", driver
, debugstr_w(path
->Buffer
));
192 driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ndis_ioctl
;
194 create_network_devices( driver
);
196 return STATUS_SUCCESS
;
199 NDIS_STATUS WINAPI
NdisAllocateMemoryWithTag(void **address
, UINT length
, ULONG tag
)
201 FIXME("(%p, %u, %u): stub\n", address
, length
, tag
);
202 return NDIS_STATUS_FAILURE
;
205 void WINAPI
NdisAllocateSpinLock(NDIS_SPIN_LOCK
*lock
)
207 FIXME("(%p): stub\n", lock
);
210 void WINAPI
NdisRegisterProtocol(NDIS_STATUS
*status
, NDIS_HANDLE
*handle
,
211 NDIS_PROTOCOL_CHARACTERISTICS
*prot
, UINT len
)
213 FIXME("(%p, %p, %p, %u): stub\n", status
, handle
, prot
, len
);
214 *status
= NDIS_STATUS_FAILURE
;
217 CCHAR WINAPI
NdisSystemProcessorCount(void)
224 return si
.dwNumberOfProcessors
;