1 |
/* |
2 |
* b2ether driver -- derived from DDK packet driver sample |
3 |
* |
4 |
* Basilisk II (C) 1997-1999 Christian Bauer |
5 |
* |
6 |
* Windows platform specific code copyright (C) Lauri Pesonen |
7 |
* |
8 |
* This program is free software; you can redistribute it and/or modify |
9 |
* it under the terms of the GNU General Public License as published by |
10 |
* the Free Software Foundation; either version 2 of the License, or |
11 |
* (at your option) any later version. |
12 |
* |
13 |
* This program is distributed in the hope that it will be useful, |
14 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
* GNU General Public License for more details. |
17 |
* |
18 |
* You should have received a copy of the GNU General Public License |
19 |
* along with this program; if not, write to the Free Software |
20 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 |
*/ |
22 |
|
23 |
|
24 |
#include "ntddk.h" |
25 |
#include "ndis.h" |
26 |
#include "ntddpack.h" |
27 |
#include "b2ether.h" |
28 |
#include "stdio.h" |
29 |
|
30 |
|
31 |
|
32 |
NTSTATUS |
33 |
DriverEntry( |
34 |
IN PDRIVER_OBJECT DriverObject, |
35 |
IN PUNICODE_STRING RegistryPath |
36 |
) |
37 |
{ |
38 |
NDIS_PROTOCOL_CHARACTERISTICS protocolChar; |
39 |
NTSTATUS status = STATUS_SUCCESS; |
40 |
NDIS_STRING protoName = NDIS_STRING_CONST("B2ether"); |
41 |
UNICODE_STRING ntDeviceName; |
42 |
UNICODE_STRING win32DeviceName; |
43 |
BOOLEAN fSymbolicLink = FALSE; |
44 |
PDEVICE_OBJECT deviceObject; |
45 |
|
46 |
// DebugPrint(("\n\nDriverEntry\n")); |
47 |
|
48 |
Globals.DriverObject = DriverObject; |
49 |
Globals.RegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL); |
50 |
Globals.RegistryPath.Length = RegistryPath->Length; |
51 |
Globals.RegistryPath.Buffer = ExAllocatePool( PagedPool, Globals.RegistryPath.MaximumLength ); |
52 |
if (!Globals.RegistryPath.Buffer) { |
53 |
// DebugPrint (("Couldn't allocate pool for registry path.")); |
54 |
return STATUS_INSUFFICIENT_RESOURCES; |
55 |
} |
56 |
|
57 |
RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath); |
58 |
RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME); |
59 |
|
60 |
status = IoCreateDevice (DriverObject, |
61 |
0, |
62 |
&ntDeviceName, |
63 |
FILE_DEVICE_UNKNOWN, |
64 |
0, |
65 |
FALSE, |
66 |
&deviceObject); |
67 |
|
68 |
|
69 |
if (!NT_SUCCESS (status)) { |
70 |
// Either not enough memory to create a deviceobject or another |
71 |
// deviceobject with the same name exits. This could happen |
72 |
// if you install another instance of this device. |
73 |
goto ERROR; |
74 |
} |
75 |
|
76 |
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); |
77 |
|
78 |
status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName ); |
79 |
if (!NT_SUCCESS(status)) goto ERROR; |
80 |
|
81 |
fSymbolicLink = TRUE; |
82 |
|
83 |
deviceObject->Flags |= DO_BUFFERED_IO; |
84 |
Globals.ControlDeviceObject = deviceObject; |
85 |
|
86 |
InitializeListHead(&Globals.AdapterList); |
87 |
KeInitializeSpinLock(&Globals.GlobalLock); |
88 |
|
89 |
NdisZeroMemory(&protocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); |
90 |
|
91 |
protocolChar.MajorNdisVersion = 5; |
92 |
protocolChar.MinorNdisVersion = 0; |
93 |
protocolChar.Name = protoName; |
94 |
protocolChar.OpenAdapterCompleteHandler = PacketOpenAdapterComplete; |
95 |
protocolChar.CloseAdapterCompleteHandler = PacketCloseAdapterComplete; |
96 |
protocolChar.SendCompleteHandler = PacketSendComplete; |
97 |
protocolChar.TransferDataCompleteHandler = PacketTransferDataComplete; |
98 |
protocolChar.ResetCompleteHandler = PacketResetComplete; |
99 |
protocolChar.RequestCompleteHandler = PacketRequestComplete; |
100 |
protocolChar.ReceiveHandler = PacketReceiveIndicate; |
101 |
protocolChar.ReceiveCompleteHandler = PacketReceiveComplete; |
102 |
protocolChar.StatusHandler = PacketStatus; |
103 |
protocolChar.StatusCompleteHandler = PacketStatusComplete; |
104 |
protocolChar.BindAdapterHandler = PacketBindAdapter; |
105 |
protocolChar.UnbindAdapterHandler = PacketUnbindAdapter; |
106 |
protocolChar.UnloadHandler = NULL; |
107 |
protocolChar.ReceivePacketHandler = PacketReceivePacket; |
108 |
protocolChar.PnPEventHandler = PacketPNPHandler; |
109 |
|
110 |
NdisRegisterProtocol( |
111 |
&status, |
112 |
&Globals.NdisProtocolHandle, |
113 |
&protocolChar, |
114 |
sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); |
115 |
|
116 |
if (status != NDIS_STATUS_SUCCESS) { |
117 |
// DebugPrint(("Failed to register protocol with NDIS\n")); |
118 |
status = STATUS_UNSUCCESSFUL; |
119 |
goto ERROR; |
120 |
} |
121 |
|
122 |
DriverObject->MajorFunction[IRP_MJ_CREATE] = PacketOpen; |
123 |
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PacketClose; |
124 |
DriverObject->MajorFunction[IRP_MJ_READ] = PacketRead; |
125 |
DriverObject->MajorFunction[IRP_MJ_WRITE] = PacketWrite; |
126 |
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = PacketCleanup; |
127 |
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PacketIoControl; |
128 |
DriverObject->DriverUnload = PacketUnload; |
129 |
|
130 |
return(STATUS_SUCCESS); |
131 |
|
132 |
ERROR: |
133 |
if(deviceObject) |
134 |
IoDeleteDevice(deviceObject); |
135 |
if(fSymbolicLink) |
136 |
IoDeleteSymbolicLink(&win32DeviceName); |
137 |
if(Globals.RegistryPath.Buffer) |
138 |
ExFreePool(Globals.RegistryPath.Buffer); |
139 |
return status; |
140 |
} |
141 |
|
142 |
|
143 |
VOID PacketUnload( IN PDRIVER_OBJECT DriverObject ) |
144 |
{ |
145 |
NDIS_STATUS status; |
146 |
UNICODE_STRING win32DeviceName; |
147 |
|
148 |
// DebugPrint(("Unload Enter\n")); |
149 |
|
150 |
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); |
151 |
IoDeleteSymbolicLink(&win32DeviceName); |
152 |
|
153 |
if(Globals.ControlDeviceObject) |
154 |
IoDeleteDevice(Globals.ControlDeviceObject); |
155 |
|
156 |
// Unbind from all the adapters. The system removes the driver code |
157 |
// pages from the memory as soon as the unload returns. So you |
158 |
// must wait for all the CloseAdapterCompleteHandler to finish |
159 |
// before returning from the unload routine. You don't any callbacks |
160 |
// to trigger after the driver is unloaded. |
161 |
|
162 |
while(DriverObject->DeviceObject) { |
163 |
PacketUnbindAdapter(&status, DriverObject->DeviceObject->DeviceExtension,NULL); |
164 |
} |
165 |
|
166 |
if(Globals.RegistryPath.Buffer) |
167 |
ExFreePool(Globals.RegistryPath.Buffer); |
168 |
|
169 |
// DebugPrint(("Deregister\n")); |
170 |
|
171 |
NdisDeregisterProtocol( &status, Globals.NdisProtocolHandle ); |
172 |
// DebugPrint(("Unload Exit\n")); |
173 |
} |
174 |
|
175 |
|
176 |
|
177 |
NTSTATUS PacketIoControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) |
178 |
{ |
179 |
POPEN_INSTANCE open; |
180 |
PIO_STACK_LOCATION irpSp; |
181 |
PINTERNAL_REQUEST pRequest; |
182 |
ULONG functionCode; |
183 |
NDIS_STATUS status; |
184 |
ULONG dataLength =0; |
185 |
|
186 |
// DebugPrint(("IoControl\n")); |
187 |
|
188 |
irpSp = IoGetCurrentIrpStackLocation(Irp); |
189 |
|
190 |
functionCode=irpSp->Parameters.DeviceIoControl.IoControlCode; |
191 |
|
192 |
if (functionCode == IOCTL_ENUM_ADAPTERS) { |
193 |
// If the request is not made to the controlobject, fail the request. |
194 |
|
195 |
if(DeviceObject != Globals.ControlDeviceObject) { |
196 |
status = STATUS_INVALID_DEVICE_REQUEST; |
197 |
} else { |
198 |
status = PacketGetAdapterList( |
199 |
Irp->AssociatedIrp.SystemBuffer, |
200 |
irpSp->Parameters.DeviceIoControl.OutputBufferLength, |
201 |
&dataLength |
202 |
); |
203 |
} |
204 |
Irp->IoStatus.Status = status; |
205 |
Irp->IoStatus.Information = dataLength; |
206 |
IoCompleteRequest(Irp, IO_NO_INCREMENT); |
207 |
return status; |
208 |
} |
209 |
|
210 |
open = DeviceObject->DeviceExtension; |
211 |
IoIncrement(open); |
212 |
|
213 |
if(!open->Bound) { |
214 |
Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL; |
215 |
IoCompleteRequest(Irp, IO_NO_INCREMENT); |
216 |
IoDecrement(open); |
217 |
return status; |
218 |
} |
219 |
|
220 |
// DebugPrint(("Function code is %08lx buff size=%08lx %08lx\n", |
221 |
// functionCode,irpSp->Parameters.DeviceIoControl.InputBufferLength, |
222 |
// irpSp->Parameters.DeviceIoControl.OutputBufferLength)); |
223 |
|
224 |
// Important: Since we have marked the IRP pending, we must return |
225 |
// STATUS_PENDING even we happen to complete the IRP synchronously. |
226 |
|
227 |
IoMarkIrpPending(Irp); |
228 |
|
229 |
if (functionCode == IOCTL_PROTOCOL_RESET) { |
230 |
// DebugPrint(("IoControl - Reset request\n")); |
231 |
|
232 |
// |
233 |
// Since NDIS doesn't have an interface to cancel a request |
234 |
// pending at miniport, we cannot set a cancel routine. |
235 |
// As a result if the application that made the request |
236 |
// terminates, we wait in the Cleanup routine for all pending |
237 |
// NDIS requests to complete. |
238 |
|
239 |
ExInterlockedInsertTailList( |
240 |
&open->ResetIrpList, |
241 |
&Irp->Tail.Overlay.ListEntry, |
242 |
&open->ResetQueueLock); |
243 |
|
244 |
NdisReset( &status, open->AdapterHandle ); |
245 |
|
246 |
if (status != NDIS_STATUS_PENDING) { |
247 |
// DebugPrint(("IoControl - ResetComplete being called\n")); |
248 |
PacketResetComplete( open, status ); |
249 |
} |
250 |
} else { |
251 |
// See if it is an Ndis request |
252 |
PPACKET_OID_DATA OidData=Irp->AssociatedIrp.SystemBuffer; |
253 |
|
254 |
pRequest = ExAllocatePool(NonPagedPool, sizeof(INTERNAL_REQUEST)); |
255 |
|
256 |
if(!pRequest) { |
257 |
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; |
258 |
IoCompleteRequest (Irp, IO_NO_INCREMENT); |
259 |
IoDecrement(open); |
260 |
return STATUS_PENDING; |
261 |
} |
262 |
pRequest->Irp=Irp; |
263 |
|
264 |
if (((functionCode == IOCTL_PROTOCOL_SET_OID) || (functionCode == IOCTL_PROTOCOL_QUERY_OID)) |
265 |
&& |
266 |
(irpSp->Parameters.DeviceIoControl.InputBufferLength == irpSp->Parameters.DeviceIoControl.OutputBufferLength) |
267 |
&& |
268 |
(irpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)) |
269 |
&& |
270 |
(irpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) |
271 |
{ |
272 |
// DebugPrint(("IoControl: Request: Oid=%08lx, Length=%08lx\n", OidData->Oid,OidData->Length)); |
273 |
|
274 |
if (functionCode == IOCTL_PROTOCOL_SET_OID) { |
275 |
pRequest->Request.RequestType = NdisRequestSetInformation; |
276 |
pRequest->Request.DATA.SET_INFORMATION.Oid = OidData->Oid; |
277 |
pRequest->Request.DATA.SET_INFORMATION.InformationBuffer = OidData->Data; |
278 |
pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = OidData->Length; |
279 |
} else { |
280 |
pRequest->Request.RequestType=NdisRequestQueryInformation; |
281 |
pRequest->Request.DATA.QUERY_INFORMATION.Oid = OidData->Oid; |
282 |
pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = OidData->Data; |
283 |
pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = OidData->Length; |
284 |
} |
285 |
NdisRequest( &status, open->AdapterHandle, &pRequest->Request ); |
286 |
} else { |
287 |
status=NDIS_STATUS_FAILURE; |
288 |
pRequest->Request.DATA.SET_INFORMATION.BytesRead=0; |
289 |
pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0; |
290 |
} |
291 |
|
292 |
if (status != NDIS_STATUS_PENDING) { |
293 |
// DebugPrint(("Calling RequestCompleteHandler\n")); |
294 |
PacketRequestComplete( open, &pRequest->Request, status ); |
295 |
} |
296 |
} |
297 |
return STATUS_PENDING; |
298 |
} |
299 |
|
300 |
|
301 |
VOID |
302 |
PacketRequestComplete( |
303 |
IN NDIS_HANDLE ProtocolBindingContext, |
304 |
IN PNDIS_REQUEST NdisRequest, |
305 |
IN NDIS_STATUS Status |
306 |
) |
307 |
{ |
308 |
POPEN_INSTANCE open; |
309 |
PIO_STACK_LOCATION irpSp; |
310 |
PIRP irp; |
311 |
PINTERNAL_REQUEST pRequest; |
312 |
UINT functionCode; |
313 |
|
314 |
PPACKET_OID_DATA OidData; |
315 |
|
316 |
// DebugPrint(("RequestComplete\n")); |
317 |
|
318 |
open = (POPEN_INSTANCE)ProtocolBindingContext; |
319 |
|
320 |
pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request); |
321 |
irp = pRequest->Irp; |
322 |
|
323 |
if(Status == NDIS_STATUS_SUCCESS) { |
324 |
irpSp = IoGetCurrentIrpStackLocation(irp); |
325 |
functionCode=irpSp->Parameters.DeviceIoControl.IoControlCode; |
326 |
OidData = irp->AssociatedIrp.SystemBuffer; |
327 |
if (functionCode == IOCTL_PROTOCOL_SET_OID) { |
328 |
OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead; |
329 |
} else { |
330 |
if (functionCode == IOCTL_PROTOCOL_QUERY_OID) { |
331 |
OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten; |
332 |
} |
333 |
} |
334 |
irp->IoStatus.Status = STATUS_SUCCESS; |
335 |
irp->IoStatus.Information=irpSp->Parameters.DeviceIoControl.InputBufferLength; |
336 |
} else { |
337 |
irp->IoStatus.Status = STATUS_UNSUCCESSFUL; |
338 |
irp->IoStatus.Information = 0; |
339 |
} |
340 |
|
341 |
ExFreePool(pRequest); |
342 |
IoCompleteRequest(irp, IO_NO_INCREMENT); |
343 |
IoDecrement(open); |
344 |
} |
345 |
|
346 |
|
347 |
VOID |
348 |
PacketStatus( |
349 |
IN NDIS_HANDLE ProtocolBindingContext, |
350 |
IN NDIS_STATUS Status, |
351 |
IN PVOID StatusBuffer, |
352 |
IN UINT StatusBufferSize |
353 |
) |
354 |
{ |
355 |
// DebugPrint(("Indication Status: %0x, StatusBufferSize: %d\n", Status, StatusBufferSize)); |
356 |
} |
357 |
|
358 |
|
359 |
VOID PacketStatusComplete( IN NDIS_HANDLE ProtocolBindingContext ) |
360 |
{ |
361 |
// DebugPrint(("StatusIndicationComplete\n")); |
362 |
} |
363 |
|
364 |
|
365 |
NTSTATUS |
366 |
PacketGetAdapterList( |
367 |
IN PVOID Buffer, |
368 |
IN ULONG Length, |
369 |
IN OUT PULONG DataLength |
370 |
) |
371 |
{ |
372 |
ULONG requiredLength = 0, numOfAdapters = 0; |
373 |
KIRQL oldIrql; |
374 |
PLIST_ENTRY thisEntry, listHead; |
375 |
POPEN_INSTANCE open; |
376 |
|
377 |
// DebugPrint(("Enter PacketGetAdapterList\n")); |
378 |
|
379 |
KeAcquireSpinLock(&Globals.GlobalLock, &oldIrql); |
380 |
|
381 |
// Walks the list to find out total space required for AdapterName and Symbolic Link. |
382 |
|
383 |
listHead = &Globals.AdapterList; |
384 |
|
385 |
for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink) { |
386 |
open = CONTAINING_RECORD(thisEntry, OPEN_INSTANCE, AdapterListEntry); |
387 |
requiredLength += open->AdapterName.Length + sizeof(UNICODE_NULL); |
388 |
requiredLength += open->SymbolicLink.Length + sizeof(UNICODE_NULL); |
389 |
numOfAdapters++; |
390 |
} |
391 |
|
392 |
// |
393 |
// We will return the data in the following format: |
394 |
// numOfAdapters + One_Or_More("AdapterName\0" + "SymbolicLink\0") + UNICODE_NULL |
395 |
// So let's include the numOfAdapters and UNICODE_NULL size |
396 |
// to the total length. |
397 |
// |
398 |
|
399 |
requiredLength += sizeof(ULONG) + sizeof(UNICODE_NULL); |
400 |
*DataLength = requiredLength; |
401 |
|
402 |
if(requiredLength > Length) { |
403 |
KeReleaseSpinLock(&Globals.GlobalLock, oldIrql); |
404 |
return STATUS_BUFFER_TOO_SMALL; |
405 |
} |
406 |
|
407 |
*(PULONG)Buffer = numOfAdapters; |
408 |
(PCHAR)Buffer += sizeof(ULONG); |
409 |
|
410 |
for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink ) { |
411 |
open = CONTAINING_RECORD(thisEntry, OPEN_INSTANCE, AdapterListEntry); |
412 |
RtlCopyMemory( Buffer, open->AdapterName.Buffer, open->AdapterName.Length+sizeof(WCHAR) ); |
413 |
(PCHAR)Buffer += open->AdapterName.Length+sizeof(WCHAR); |
414 |
RtlCopyMemory( Buffer, open->SymbolicLink.Buffer, open->SymbolicLink.Length+sizeof(WCHAR) ); |
415 |
(PCHAR)Buffer += open->SymbolicLink.Length+sizeof(WCHAR); |
416 |
} |
417 |
|
418 |
*(PWCHAR)Buffer = UNICODE_NULL; |
419 |
KeReleaseSpinLock(&Globals.GlobalLock, oldIrql); |
420 |
return STATUS_SUCCESS; |
421 |
} |
422 |
|
423 |
VOID |
424 |
PacketBindAdapter( |
425 |
OUT PNDIS_STATUS Status, |
426 |
IN NDIS_HANDLE BindContext, |
427 |
IN PNDIS_STRING DeviceName, |
428 |
IN PVOID SystemSpecific1, |
429 |
IN PVOID SystemSpecific2 |
430 |
) |
431 |
{ |
432 |
NDIS_STATUS status; |
433 |
UINT mediumIndex; |
434 |
USHORT length; |
435 |
POPEN_INSTANCE open = NULL; |
436 |
UNICODE_STRING unicodeDeviceName; |
437 |
PDEVICE_OBJECT deviceObject = NULL; |
438 |
PWSTR symbolicLink = NULL, deviceNameStr = NULL; |
439 |
NDIS_MEDIUM mediumArray = NdisMedium802_3; // Ethernet medium |
440 |
|
441 |
// DebugPrint(("Binding DeviceName %ws\n", DeviceName->Buffer)); |
442 |
|
443 |
do { |
444 |
// Create a deviceobject for every adapter we bind to. |
445 |
// To make a name for the deviceObject, we will append Packet_ |
446 |
// to the name portion of the input DeviceName. |
447 |
|
448 |
unicodeDeviceName.Buffer = NULL; |
449 |
length = DeviceName->Length + 7 * sizeof(WCHAR) + sizeof(UNICODE_NULL); |
450 |
|
451 |
deviceNameStr = ExAllocatePool(NonPagedPool, length); |
452 |
if (!deviceNameStr) { |
453 |
// DebugPrint(("Memory allocation for create symbolic failed\n")); |
454 |
*Status = NDIS_STATUS_FAILURE; |
455 |
break; |
456 |
} |
457 |
swprintf(deviceNameStr, L"\\Device\\B2ether_%ws", &DeviceName->Buffer[8]); |
458 |
RtlInitUnicodeString(&unicodeDeviceName, deviceNameStr); |
459 |
|
460 |
// DebugPrint(("Exported DeviceName %ws\n", unicodeDeviceName.Buffer)); |
461 |
|
462 |
status = IoCreateDevice( |
463 |
Globals.DriverObject, |
464 |
sizeof(OPEN_INSTANCE), |
465 |
&unicodeDeviceName, |
466 |
FILE_DEVICE_PROTOCOL, |
467 |
0, |
468 |
TRUE, // only one handle to the device at a time. |
469 |
&deviceObject |
470 |
); |
471 |
|
472 |
if (status != STATUS_SUCCESS) { |
473 |
// DebugPrint(("CreateDevice Failed: %x\n", status)); |
474 |
*Status = NDIS_STATUS_FAILURE; |
475 |
break; |
476 |
} |
477 |
|
478 |
deviceObject->Flags |= DO_DIRECT_IO; |
479 |
open = (POPEN_INSTANCE) deviceObject->DeviceExtension; |
480 |
open->DeviceObject = deviceObject; |
481 |
|
482 |
// Create a symbolic link. |
483 |
// We need to replace Device from \Device\Packet_{GUID} with DosDevices |
484 |
// to create a symbolic link of the form \DosDevices\Packet_{GUID} |
485 |
// There is a four character difference between these two |
486 |
// strings. |
487 |
|
488 |
length = unicodeDeviceName.Length + sizeof(UNICODE_NULL) + (4 * sizeof(WCHAR)); |
489 |
|
490 |
symbolicLink = ExAllocatePool(NonPagedPool, length); |
491 |
if (!symbolicLink) { |
492 |
// DebugPrint(("Memory allocation for create symbolic failed\n")); |
493 |
*Status = NDIS_STATUS_FAILURE; |
494 |
break; |
495 |
} |
496 |
|
497 |
swprintf( symbolicLink, L"\\DosDevices\\%ws", &unicodeDeviceName.Buffer[8]); |
498 |
|
499 |
RtlInitUnicodeString(&open->SymbolicLink,symbolicLink); |
500 |
|
501 |
// DebugPrint(("Symbolic Link: %ws\n", open->SymbolicLink.Buffer)); |
502 |
|
503 |
status = IoCreateSymbolicLink( |
504 |
(PUNICODE_STRING) &open->SymbolicLink, |
505 |
(PUNICODE_STRING) &unicodeDeviceName |
506 |
); |
507 |
if (status != STATUS_SUCCESS) { |
508 |
// DebugPrint(("Create symbolic failed\n")); |
509 |
*Status = NDIS_STATUS_FAILURE; |
510 |
break; |
511 |
} |
512 |
|
513 |
ExFreePool(unicodeDeviceName.Buffer); |
514 |
unicodeDeviceName.Buffer = NULL; |
515 |
|
516 |
NdisAllocatePacketPool( |
517 |
&status, |
518 |
&open->PacketPool, |
519 |
TRANSMIT_PACKETS, |
520 |
sizeof(PACKET_RESERVED)); |
521 |
|
522 |
if (status != NDIS_STATUS_SUCCESS) { |
523 |
// DebugPrint(("B2ether: Failed to allocate packet pool\n")); |
524 |
break; |
525 |
} |
526 |
|
527 |
NdisInitializeEvent(&open->Event); |
528 |
InitializeListHead(&open->ResetIrpList); |
529 |
KeInitializeSpinLock(&open->ResetQueueLock); |
530 |
KeInitializeSpinLock(&open->RcvQSpinLock); |
531 |
InitializeListHead(&open->RcvList); |
532 |
|
533 |
NdisOpenAdapter(Status, |
534 |
&status, |
535 |
&open->AdapterHandle, |
536 |
&mediumIndex, |
537 |
&mediumArray, |
538 |
sizeof(mediumArray)/sizeof(NDIS_MEDIUM), |
539 |
Globals.NdisProtocolHandle, |
540 |
open, |
541 |
DeviceName, |
542 |
0, |
543 |
NULL); |
544 |
|
545 |
if(*Status == NDIS_STATUS_PENDING) { |
546 |
NdisWaitEvent(&open->Event, 0); |
547 |
*Status = open->Status; |
548 |
} |
549 |
if(*Status != NDIS_STATUS_SUCCESS) { |
550 |
// DebugPrint(("Failed to openAdapter\n")); |
551 |
break; |
552 |
} |
553 |
|
554 |
open->IrpCount = 0; |
555 |
InterlockedExchange( (PLONG)&open->Bound, TRUE ); |
556 |
NdisInitializeEvent(&open->CleanupEvent); |
557 |
|
558 |
NdisSetEvent(&open->CleanupEvent); |
559 |
|
560 |
NdisQueryAdapterInstanceName( &open->AdapterName, open->AdapterHandle ); |
561 |
// DebugPrint(("Bound AdapterName %ws\n", open->AdapterName.Buffer)); |
562 |
|
563 |
open->Medium = mediumArray; |
564 |
|
565 |
InitializeListHead(&open->AdapterListEntry); |
566 |
|
567 |
ExInterlockedInsertTailList(&Globals.AdapterList, |
568 |
&open->AdapterListEntry, |
569 |
&Globals.GlobalLock); |
570 |
|
571 |
// Clear the DO_DEVICE_INITIALIZING flag. This is required |
572 |
// if you create deviceobjects outside of DriverEntry. |
573 |
// Untill you do this, application cannot send I/O request. |
574 |
|
575 |
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; |
576 |
} while (FALSE); |
577 |
|
578 |
if (*Status != NDIS_STATUS_SUCCESS) { |
579 |
if (open && open->PacketPool) NdisFreePacketPool(open->PacketPool); |
580 |
if (deviceObject) IoDeleteDevice(deviceObject); |
581 |
if(unicodeDeviceName.Buffer) ExFreePool(unicodeDeviceName.Buffer); |
582 |
if(symbolicLink) { |
583 |
IoDeleteSymbolicLink(&open->SymbolicLink); |
584 |
ExFreePool(open->SymbolicLink.Buffer); |
585 |
} |
586 |
} |
587 |
// DebugPrint(("Return BindAdapter :0x%x\n", *Status)); |
588 |
} |
589 |
|
590 |
|
591 |
VOID |
592 |
PacketUnbindAdapter( |
593 |
OUT PNDIS_STATUS Status, |
594 |
IN NDIS_HANDLE ProtocolBindingContext, |
595 |
IN NDIS_HANDLE UnbindContext |
596 |
) |
597 |
{ |
598 |
POPEN_INSTANCE open =(POPEN_INSTANCE)ProtocolBindingContext; |
599 |
KIRQL oldIrql; |
600 |
|
601 |
// DebugPrint(("PacketUnbindAdapter :%ws\n", open->AdapterName.Buffer)); |
602 |
|
603 |
if(open->AdapterHandle) { |
604 |
NdisResetEvent(&open->Event); |
605 |
InterlockedExchange( (PLONG) &open->Bound, FALSE ); |
606 |
PacketCancelReadIrps(open->DeviceObject); |
607 |
|
608 |
// DebugPrint(("Waiting on CleanupEvent\n")); |
609 |
NdisWaitEvent(&open->CleanupEvent, 0); |
610 |
|
611 |
NdisCloseAdapter(Status, open->AdapterHandle); |
612 |
|
613 |
// Wait for it to complete |
614 |
if(*Status == NDIS_STATUS_PENDING) { |
615 |
NdisWaitEvent(&open->Event, 0); |
616 |
*Status = open->Status; |
617 |
} else { |
618 |
*Status = NDIS_STATUS_FAILURE; |
619 |
// ASSERT(0); |
620 |
} |
621 |
|
622 |
KeAcquireSpinLock(&Globals.GlobalLock, &oldIrql); |
623 |
RemoveEntryList(&open->AdapterListEntry); |
624 |
KeReleaseSpinLock(&Globals.GlobalLock, oldIrql); |
625 |
|
626 |
NdisFreePacketPool(open->PacketPool); |
627 |
|
628 |
NdisFreeMemory(open->AdapterName.Buffer, open->AdapterName.Length, 0); |
629 |
|
630 |
IoDeleteSymbolicLink(&open->SymbolicLink); |
631 |
ExFreePool(open->SymbolicLink.Buffer); |
632 |
|
633 |
IoDeleteDevice(open->DeviceObject); |
634 |
} |
635 |
|
636 |
// DebugPrint(("Exit PacketUnbindAdapter\n")); |
637 |
} |
638 |
|
639 |
VOID |
640 |
PacketOpenAdapterComplete( |
641 |
IN NDIS_HANDLE ProtocolBindingContext, |
642 |
IN NDIS_STATUS Status, |
643 |
IN NDIS_STATUS OpenErrorStatus |
644 |
) |
645 |
{ |
646 |
POPEN_INSTANCE open = ProtocolBindingContext; |
647 |
|
648 |
// DebugPrint(("B2ether: OpenAdapterComplete\n")); |
649 |
|
650 |
open->Status = Status; |
651 |
NdisSetEvent(&open->Event); |
652 |
} |
653 |
|
654 |
VOID |
655 |
PacketCloseAdapterComplete( |
656 |
IN NDIS_HANDLE ProtocolBindingContext, |
657 |
IN NDIS_STATUS Status |
658 |
) |
659 |
{ |
660 |
POPEN_INSTANCE open = ProtocolBindingContext; |
661 |
|
662 |
// DebugPrint(("CloseAdapterComplete\n")); |
663 |
|
664 |
open->Status = Status; |
665 |
NdisSetEvent(&open->Event); |
666 |
} |
667 |
|
668 |
|
669 |
NDIS_STATUS |
670 |
PacketPNPHandler( |
671 |
IN NDIS_HANDLE ProtocolBindingContext, |
672 |
IN PNET_PNP_EVENT NetPnPEvent |
673 |
) |
674 |
{ |
675 |
POPEN_INSTANCE open =(POPEN_INSTANCE)ProtocolBindingContext; |
676 |
NDIS_STATUS Status = NDIS_STATUS_SUCCESS; |
677 |
PNET_DEVICE_POWER_STATE powerState; |
678 |
|
679 |
// DebugPrint(("PacketPNPHandler\n")); |
680 |
|
681 |
powerState = (PNET_DEVICE_POWER_STATE)NetPnPEvent->Buffer; |
682 |
|
683 |
// This will happen when all entities in the system need to be notified |
684 |
// |
685 |
//if(open == NULL) |
686 |
//{ |
687 |
// return Status; |
688 |
//} |
689 |
|
690 |
switch(NetPnPEvent->NetEvent) { |
691 |
case NetEventSetPower : |
692 |
// DebugPrint(("NetEventSetPower\n")); |
693 |
switch (*powerState) { |
694 |
case NetDeviceStateD0: |
695 |
Status = NDIS_STATUS_SUCCESS; |
696 |
break; |
697 |
default: |
698 |
// We can't suspend, so we ask NDIS to Unbind us by |
699 |
// returning this status: |
700 |
Status = NDIS_STATUS_NOT_SUPPORTED; |
701 |
break; |
702 |
} |
703 |
break; |
704 |
case NetEventQueryPower : |
705 |
// DebugPrint(("NetEventQueryPower\n")); |
706 |
break; |
707 |
case NetEventQueryRemoveDevice : |
708 |
// DebugPrint(("NetEventQueryRemoveDevice \n")); |
709 |
break; |
710 |
case NetEventCancelRemoveDevice : |
711 |
// DebugPrint(("NetEventCancelRemoveDevice \n")); |
712 |
break; |
713 |
case NetEventReconfigure : |
714 |
// The protocol should always succeed this event by returning NDIS_STATUS_SUCCESS |
715 |
// DebugPrint(("NetEventReconfigure\n")); |
716 |
break; |
717 |
case NetEventBindsComplete : |
718 |
// DebugPrint(("NetEventBindsComplete \n")); |
719 |
break; |
720 |
case NetEventPnPCapabilities : |
721 |
// DebugPrint(("NetEventPnPCapabilities \n")); |
722 |
case NetEventBindList: |
723 |
// DebugPrint(("NetEventBindList \n")); |
724 |
default: |
725 |
Status = NDIS_STATUS_NOT_SUPPORTED; |
726 |
break; |
727 |
} |
728 |
return Status; |
729 |
} |
730 |
|
731 |
|
732 |
VOID IoIncrement( IN OUT POPEN_INSTANCE Open ) |
733 |
{ |
734 |
LONG result = InterlockedIncrement(&Open->IrpCount); |
735 |
|
736 |
//DebugPrint(("IoIncrement %d\n", result)); |
737 |
|
738 |
// Need to clear event (when IrpCount bumps from 0 to 1) |
739 |
if (result == 1) { |
740 |
NdisResetEvent(&Open->CleanupEvent); |
741 |
} |
742 |
} |
743 |
|
744 |
|
745 |
VOID IoDecrement ( IN OUT POPEN_INSTANCE Open ) |
746 |
{ |
747 |
LONG result = InterlockedDecrement(&Open->IrpCount); |
748 |
|
749 |
//DebugPrint(("IoDecrement %d\n", result)); |
750 |
|
751 |
if (result == 0) { |
752 |
// Set the event when the count transition from 1 to 0. |
753 |
NdisSetEvent (&Open->CleanupEvent); |
754 |
} |
755 |
} |