minor corrections by M.Taguchi
[reactos.git] / reactos / drivers / net / packet / packet.c
1 /*
2 * Copyright (c) 1999, 2000
3 * Politecnico di Torino. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the Politecnico
13 * di Torino, and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifdef _MSC_VER
23 #include "stdarg.h"
24 #include "ntddk.h"
25 #include "ntiologc.h"
26 #include "ndis.h"
27 #else
28 #include <ddk/ntddk.h>
29 #include <net/ndis.h>
30 #endif
31
32 #include "ntddpack.h"
33
34 #include "debug.h"
35 #include "packet.h"
36 #include "win_bpf.h"
37 #include "win_bpf_filter_init.h"
38
39 #include "tme.h"
40
41 #if DBG
42 // Declare the global debug flag for this driver.
43 //ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
44 ULONG PacketDebugFlag = PACKET_DEBUG_LOUD + PACKET_DEBUG_VERY_LOUD + PACKET_DEBUG_INIT;
45
46 #endif
47
48 PDEVICE_EXTENSION GlobalDeviceExtension;
49
50 ////////////////////////////////////////////////////////////////////////////////
51 #define ROBERTS_PATCH
52 #ifdef ROBERTS_PATCH
53
54 #define NDIS_STRING_CONST(x) {sizeof(L##x)-2, sizeof(L##x), L##x}
55
56 //void __moddi3(void) {}
57 //void __divdi3(void) {}
58
59 #endif // ROBERTS_PATCH
60 ////////////////////////////////////////////////////////////////////////////////
61 //
62 // Global strings
63 //
64 NDIS_STRING NPF_Prefix = NDIS_STRING_CONST("NPF_");
65 NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
66 NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
67 NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System"
68 L"\\CurrentControlSet\\Services\\Tcpip\\Linkage");
69 NDIS_STRING AdapterListKey = NDIS_STRING_CONST("\\Registry\\Machine\\System"
70 L"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
71 NDIS_STRING bindValueName = NDIS_STRING_CONST("Bind");
72
73
74 /// Global variable that points to the names of the bound adapters
75 WCHAR* bindP = NULL;
76
77 extern struct time_conv G_Start_Time; // from openclos.c
78
79 extern NDIS_SPIN_LOCK Opened_Instances_Lock;
80
81 //
82 // Packet Driver's entry routine.
83 //
84 NTSTATUS
85 #ifdef __GNUC__
86 STDCALL
87 #endif
88 DriverEntry(
89 IN PDRIVER_OBJECT DriverObject,
90 IN PUNICODE_STRING RegistryPath
91 )
92 {
93
94 NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar;
95 UNICODE_STRING MacDriverName;
96 UNICODE_STRING UnicodeDeviceName;
97 PDEVICE_OBJECT DeviceObject = NULL;
98 PDEVICE_EXTENSION DeviceExtension = NULL;
99 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
100 NTSTATUS ErrorCode = STATUS_SUCCESS;
101 NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver");
102 ULONG DevicesCreated=0;
103 PWSTR BindString;
104 PWSTR ExportString;
105 PWSTR BindStringSave;
106 PWSTR ExportStringSave;
107 NDIS_HANDLE NdisProtocolHandle;
108 WCHAR* bindT;
109 PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
110 UNICODE_STRING macName;
111
112 // This driver at the moment works only on single processor machines
113 if(NdisSystemProcessorCount() != 1){
114 return STATUS_IMAGE_MP_UP_MISMATCH;
115 }
116
117 IF_LOUD(DbgPrint("Packet: DriverEntry\n");)
118
119 RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
120
121 #ifdef NDIS50
122 ProtocolChar.MajorNdisVersion = 5;
123 #else
124 ProtocolChar.MajorNdisVersion = 3;
125 #endif
126 ProtocolChar.MinorNdisVersion = 0;
127 #ifndef __GNUC__
128 ProtocolChar.Reserved = 0;
129 #else
130 ProtocolChar.u1.Reserved = 0;
131 #endif
132 ProtocolChar.OpenAdapterCompleteHandler = NPF_OpenAdapterComplete;
133 ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
134 #ifndef __GNUC__
135 ProtocolChar.SendCompleteHandler = NPF_SendComplete;
136 ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
137 #else
138 ProtocolChar.u2.SendCompleteHandler = NPF_SendComplete;
139 ProtocolChar.u3.TransferDataCompleteHandler = NPF_TransferDataComplete;
140 #endif
141 ProtocolChar.ResetCompleteHandler = NPF_ResetComplete;
142 ProtocolChar.RequestCompleteHandler = NPF_RequestComplete;
143 #ifndef __GNUC__
144 ProtocolChar.ReceiveHandler = NPF_tap;
145 #else
146 ProtocolChar.u4.ReceiveHandler = NPF_tap;
147 #endif
148 ProtocolChar.ReceiveCompleteHandler = NPF_ReceiveComplete;
149 ProtocolChar.StatusHandler = NPF_Status;
150 ProtocolChar.StatusCompleteHandler = NPF_StatusComplete;
151 #ifdef NDIS50
152 ProtocolChar.BindAdapterHandler = NPF_BindAdapter;
153 ProtocolChar.UnbindAdapterHandler = NPF_UnbindAdapter;
154 ProtocolChar.PnPEventHandler = NPF_PowerChange;
155 ProtocolChar.ReceivePacketHandler = NULL;
156 #endif
157 ProtocolChar.Name = ProtoName;
158
159 NdisRegisterProtocol(
160 &Status,
161 &NdisProtocolHandle,
162 &ProtocolChar,
163 sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
164
165 if (Status != NDIS_STATUS_SUCCESS) {
166
167 IF_LOUD(DbgPrint("NPF: Failed to register protocol with NDIS\n");)
168
169 return Status;
170
171 }
172
173 NdisAllocateSpinLock(&Opened_Instances_Lock);
174
175 // Set up the device driver entry points.
176 DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open;
177 DriverObject->MajorFunction[IRP_MJ_CLOSE] = NPF_Close;
178 DriverObject->MajorFunction[IRP_MJ_READ] = NPF_Read;
179 DriverObject->MajorFunction[IRP_MJ_WRITE] = NPF_Write;
180 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NPF_IoControl;
181 DriverObject->DriverUnload = NPF_Unload;
182
183 /*
184 // Get the name of the Packet driver and the name of the NIC driver
185 // to bind to from the registry
186 Status=NPF_ReadRegistry(
187 &BindString,
188 &ExportString,
189 RegistryPath
190 );
191
192 if (Status != STATUS_SUCCESS) {
193
194 IF_LOUD(DbgPrint("Trying dynamic binding\n");)
195 */
196 bindP = getAdaptersList();
197
198 if (bindP == NULL) {
199 IF_LOUD(DbgPrint("Adapters not found in the registry, try to copy the bindings of TCP-IP.\n");)
200
201 tcpBindingsP = getTcpBindings();
202
203 if (tcpBindingsP == NULL){
204 IF_LOUD(DbgPrint("TCP-IP not found, quitting.\n");)
205 goto RegistryError;
206 }
207
208 bindP = (WCHAR*)tcpBindingsP;
209 bindT = (WCHAR*)(tcpBindingsP->Data);
210 } else {
211 bindT = bindP;
212 }
213
214 for (; *bindT != UNICODE_NULL; bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR)) {
215 RtlInitUnicodeString(&macName, bindT);
216 createDevice(DriverObject, &macName, NdisProtocolHandle);
217 }
218
219 return STATUS_SUCCESS;
220 /*
221 }
222 BindStringSave = BindString;
223 ExportStringSave = ExportString;
224 //
225 // create a device object for each entry
226 //
227 while (*BindString!= UNICODE_NULL && *ExportString!= UNICODE_NULL) {
228 //
229 // Create a counted unicode string for both null terminated strings
230 //
231 RtlInitUnicodeString(
232 &MacDriverName,
233 BindString);
234 RtlInitUnicodeString(
235 &UnicodeDeviceName,
236 ExportString);
237 //
238 // Advance to the next string of the MULTI_SZ string
239 //
240 BindString += (MacDriverName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
241 ExportString += (UnicodeDeviceName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
242 IF_LOUD(DbgPrint("NPF: DeviceName=%ws MacName=%ws\n",UnicodeDeviceName.Buffer,MacDriverName.Buffer);)
243 //
244 // Create the device object
245 //
246 Status = IoCreateDevice(
247 DriverObject,
248 sizeof(DEVICE_EXTENSION),
249 &UnicodeDeviceName,
250 FILE_DEVICE_PROTOCOL,
251 0,
252 FALSE,
253 &DeviceObject);
254 if (Status != STATUS_SUCCESS) {
255 IF_LOUD(DbgPrint("NPF: IoCreateDevice() failed:\n");)
256 break;
257 }
258 DevicesCreated++;
259 DeviceObject->Flags |= DO_DIRECT_IO;
260 DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
261 DeviceExtension->DeviceObject = DeviceObject;
262 //
263 // Save the the name of the MAC driver to open in the Device Extension
264 //
265 DeviceExtension->AdapterName=MacDriverName;
266 if (DevicesCreated == 1) {
267 DeviceExtension->BindString = NULL;
268 DeviceExtension->ExportString = NULL;
269 }
270 DeviceExtension->NdisProtocolHandle=NdisProtocolHandle;
271 }
272 if (DevicesCreated > 0) {
273 //
274 // Managed to create at least one device.
275 //
276 IF_LOUD(DbgPrint("NPF: Managed to create at least one device.\n");)
277 return STATUS_SUCCESS;
278 }
279 ExFreePool(BindStringSave);
280 ExFreePool(ExportStringSave);
281 */
282
283 RegistryError:
284 IF_LOUD(DbgPrint("NPF: RegistryError: calling NdisDeregisterProtocol()\n");)
285 NdisDeregisterProtocol(
286 &Status,
287 NdisProtocolHandle
288 );
289
290 Status=STATUS_UNSUCCESSFUL;
291
292 return(Status);
293
294 }
295
296 //-------------------------------------------------------------------
297
298 PWCHAR getAdaptersList(void)
299 {
300 PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
301 OBJECT_ATTRIBUTES objAttrs;
302 NTSTATUS status;
303 HANDLE keyHandle;
304 UINT BufPos=0;
305
306 #define NPF_TAG_DEVICENAME TAG('0', 'P', 'W', 'A')
307 PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, 4096, NPF_TAG_DEVICENAME);
308
309 if (DeviceNames == NULL) {
310 IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
311 return NULL;
312 }
313
314 InitializeObjectAttributes(&objAttrs, &AdapterListKey,
315 OBJ_CASE_INSENSITIVE, NULL, NULL);
316 status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
317 if (!NT_SUCCESS(status)) {
318
319 //IF_LOUD(DbgPrint("Status of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
320 IF_LOUD(DbgPrint("Status of %x opening %ws\n", status, AdapterListKey.Buffer);)
321
322 } else { //OK
323 ULONG resultLength;
324 KEY_VALUE_PARTIAL_INFORMATION valueInfo;
325 CHAR AdapInfo[1024];
326 UINT i=0;
327
328 IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%x\n",DeviceNames);)
329
330 // Scan the list of the devices
331 while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS) {
332 WCHAR ExportKeyName [512];
333 PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
334 UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
335 PWCHAR LinkageKeyPrefix = L"\\Linkage";
336 UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage");
337 NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export");
338 PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo;
339 UNICODE_STRING AdapterKeyName;
340 HANDLE ExportKeyHandle;
341 KEY_VALUE_PARTIAL_INFORMATION valueInfo;
342 ULONG resultLength;
343
344 RtlCopyMemory(ExportKeyName,
345 ExportKeyPrefix,
346 ExportKeyPrefixSize);
347
348 RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,
349 tInfo->Name,
350 tInfo->NameLength+2);
351
352 RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,
353 LinkageKeyPrefix,
354 LinkageKeyPrefixSize);
355
356 IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);)
357
358 RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);
359
360 InitializeObjectAttributes(&objAttrs, &AdapterKeyName,
361 OBJ_CASE_INSENSITIVE, NULL, NULL);
362
363 status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);
364
365 if (!NT_SUCCESS(status)) {
366 DbgPrint("OpenKey Failed, %d!\n",status);
367 i++;
368 continue;
369 }
370
371 status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
372 KeyValuePartialInformation, &valueInfo,
373 sizeof(valueInfo), &resultLength);
374
375 if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
376 IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
377 } else { // We know how big it needs to be.
378 ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
379 #define NPF_TAG_KEYVALUE TAG('1', 'P', 'W', 'A')
380 PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, NPF_TAG_KEYVALUE);
381 if (valueInfoP != NULL) {
382 status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
383 KeyValuePartialInformation,
384 valueInfoP,
385 valueInfoLength, &resultLength);
386 if (!NT_SUCCESS(status)) {
387 IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
388 } else {
389 IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
390 RtlCopyMemory((PCHAR)DeviceNames+BufPos,
391 valueInfoP->Data,
392 valueInfoP->DataLength);
393 BufPos+=valueInfoP->DataLength-2;
394 }
395
396 ExFreePool(valueInfoP);
397 } else {
398 IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
399 }
400
401 }
402
403 // terminate the buffer
404 DeviceNames[BufPos/2]=0;
405 DeviceNames[BufPos/2+1]=0;
406
407 ZwClose (ExportKeyHandle);
408 i++;
409
410 }
411
412 ZwClose (keyHandle);
413
414 }
415 if(BufPos==0){
416 ExFreePool(DeviceNames);
417 return NULL;
418 }
419 return DeviceNames;
420 }
421
422 //-------------------------------------------------------------------
423
424 PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
425 {
426 PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
427 OBJECT_ATTRIBUTES objAttrs;
428 NTSTATUS status;
429 HANDLE keyHandle;
430
431 InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName,
432 OBJ_CASE_INSENSITIVE, NULL, NULL);
433 status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
434 if (!NT_SUCCESS(status)) {
435 IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
436 } else {
437 ULONG resultLength;
438 KEY_VALUE_PARTIAL_INFORMATION valueInfo;
439
440 IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);)
441
442 status = ZwQueryValueKey(keyHandle, &bindValueName,
443 KeyValuePartialInformation, &valueInfo,
444 sizeof(valueInfo), &resultLength);
445 if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
446 IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
447 } else { // We know how big it needs to be.
448 ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
449 #define NPF_TAG_KEYVALUE2 TAG('2', 'P', 'W', 'A')
450 PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
451 (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, NPF_TAG_KEYVALUE2);
452
453 if (valueInfoP != NULL) {
454 status = ZwQueryValueKey(keyHandle, &bindValueName,
455 KeyValuePartialInformation,
456 valueInfoP,
457 valueInfoLength, &resultLength);
458
459 if (!NT_SUCCESS(status)) {
460 IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
461 }
462 else if (valueInfoLength != resultLength) {
463 IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
464 "but previous len = %u\n",
465 resultLength, valueInfoLength);)
466 }
467 else if (valueInfoP->Type != REG_MULTI_SZ) {
468 IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
469 valueInfoP->Type);)
470 }
471 else { // It's OK
472 #if DBG
473 ULONG i;
474 WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]);
475 IF_LOUD(DbgPrint("\n\nBind value:\n");)
476 for (i = 0; *dataP != UNICODE_NULL; i++) {
477 UNICODE_STRING macName;
478 RtlInitUnicodeString(&macName, dataP);
479 IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);)
480 dataP +=
481 (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
482 }
483 #endif // DBG
484 result = valueInfoP;
485 }
486 }
487 }
488 ZwClose(keyHandle);
489 }
490 return result;
491 }
492
493 //-------------------------------------------------------------------
494
495 BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
496 IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle)
497 {
498 NTSTATUS status;
499 PDEVICE_OBJECT devObjP;
500 UNICODE_STRING deviceName;
501 UNICODE_STRING deviceSymLink;
502
503 IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer););
504 if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
505 devicePrefix.Length) < devicePrefix.Length) {
506 return FALSE;
507 }
508
509 deviceName.Length = 0;
510 deviceName.MaximumLength = (USHORT)(amacNameP->Length + NPF_Prefix.Length + sizeof(UNICODE_NULL));
511 #define NPF_TAG_DEVICENAMEBUF TAG('3', 'P', 'W', 'A')
512 deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, NPF_TAG_DEVICENAMEBUF);
513
514 if (deviceName.Buffer == NULL)
515 return FALSE;
516
517 deviceSymLink.Length = 0;
518 deviceSymLink.MaximumLength =(USHORT)(amacNameP->Length-devicePrefix.Length
519 + symbolicLinkPrefix.Length
520 + NPF_Prefix.Length
521 + sizeof(UNICODE_NULL));
522
523 #define NPF_TAG_SYMLINKBUF TAG('3', 'P', 'W', 'A')
524 deviceSymLink.Buffer = ExAllocatePoolWithTag(NonPagedPool, deviceSymLink.MaximumLength, NPF_TAG_SYMLINKBUF);
525
526 if (deviceSymLink.Buffer == NULL)
527 {
528 ExFreePool(deviceName.Buffer);
529 return FALSE;
530 }
531
532 RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
533 RtlAppendUnicodeStringToString(&deviceName, &NPF_Prefix);
534 RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer +
535 devicePrefix.Length / sizeof(WCHAR));
536
537 RtlAppendUnicodeStringToString(&deviceSymLink, &symbolicLinkPrefix);
538 RtlAppendUnicodeStringToString(&deviceSymLink, &NPF_Prefix);
539 RtlAppendUnicodeToString(&deviceSymLink, amacNameP->Buffer +
540 devicePrefix.Length / sizeof(WCHAR));
541
542 IF_LOUD(DbgPrint("Creating device name: %ws\n", deviceName.Buffer);)
543
544 status = IoCreateDevice(adriverObjectP,
545 sizeof(PDEVICE_EXTENSION),
546 &deviceName,
547 FILE_DEVICE_TRANSPORT,
548 0,
549 FALSE,
550 &devObjP);
551
552 if (NT_SUCCESS(status)) {
553 PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension;
554
555 IF_LOUD(DbgPrint("Device created successfully\n"););
556
557 devObjP->Flags |= DO_DIRECT_IO;
558 RtlInitUnicodeString(&devExtP->AdapterName,amacNameP->Buffer);
559 devExtP->NdisProtocolHandle=aProtoHandle;
560
561 IF_LOUD(DbgPrint("Trying to create SymLink %ws\n",deviceSymLink.Buffer););
562
563 if (IoCreateSymbolicLink(&deviceSymLink,&deviceName) != STATUS_SUCCESS) {
564 IF_LOUD(DbgPrint("\n\nError creating SymLink %ws\nn", deviceSymLink.Buffer););
565
566 ExFreePool(deviceName.Buffer);
567 ExFreePool(deviceSymLink.Buffer);
568
569 devExtP->ExportString = NULL;
570
571 return FALSE;
572 }
573
574 IF_LOUD(DbgPrint("SymLink %ws successfully created.\n\n", deviceSymLink.Buffer););
575
576 devExtP->ExportString = deviceSymLink.Buffer;
577
578 ExFreePool(deviceName.Buffer);
579
580 return TRUE;
581 }
582
583 else
584 {
585 IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
586
587 ExFreePool(deviceName.Buffer);
588 ExFreePool(deviceSymLink.Buffer);
589
590 return FALSE;
591 }
592 }
593
594 //-------------------------------------------------------------------
595
596 VOID
597 STDCALL_FUNC
598 NPF_Unload(IN PDRIVER_OBJECT DriverObject)
599 {
600 PDEVICE_OBJECT DeviceObject;
601 PDEVICE_OBJECT OldDeviceObject;
602 PDEVICE_EXTENSION DeviceExtension;
603
604 NDIS_HANDLE NdisProtocolHandle;
605 NDIS_STATUS Status;
606
607 NDIS_STRING SymLink;
608
609 IF_LOUD(DbgPrint("NPF: Unload\n"););
610
611 DeviceObject = DriverObject->DeviceObject;
612
613 while (DeviceObject != NULL) {
614 OldDeviceObject=DeviceObject;
615
616 DeviceObject=DeviceObject->NextDevice;
617
618 DeviceExtension = OldDeviceObject->DeviceExtension;
619
620 NdisProtocolHandle=DeviceExtension->NdisProtocolHandle;
621
622 IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n",
623 DeviceExtension->AdapterName.Buffer,
624 NdisProtocolHandle,
625 DeviceObject,
626 OldDeviceObject););
627
628 if (DeviceExtension->ExportString)
629 {
630 RtlInitUnicodeString(&SymLink , DeviceExtension->ExportString);
631
632 IF_LOUD(DbgPrint("Deleting SymLink at %p\n", SymLink.Buffer););
633
634 IoDeleteSymbolicLink(&SymLink);
635 ExFreePool(DeviceExtension->ExportString);
636 }
637
638 IoDeleteDevice(OldDeviceObject);
639 }
640
641 NdisDeregisterProtocol(
642 &Status,
643 NdisProtocolHandle
644 );
645
646 // Free the adapters names
647 ExFreePool( bindP );
648 }
649
650 //-------------------------------------------------------------------
651
652 NTSTATUS
653 NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
654 {
655 POPEN_INSTANCE Open;
656 PIO_STACK_LOCATION IrpSp;
657 PLIST_ENTRY RequestListEntry;
658 PINTERNAL_REQUEST pRequest;
659 ULONG FunctionCode;
660 NDIS_STATUS Status;
661 PLIST_ENTRY PacketListEntry;
662 UINT i;
663 PUCHAR tpointer;
664 ULONG dim,timeout;
665 PUCHAR prog;
666 PPACKET_OID_DATA OidData;
667 int *StatsBuf;
668 PNDIS_PACKET pPacket;
669 ULONG mode;
670 PWSTR DumpNameBuff;
671 PUCHAR TmpBPFProgram;
672 INT WriteRes;
673 BOOLEAN SyncWrite = FALSE;
674 struct bpf_insn *initprogram;
675 ULONG insns;
676 ULONG cnt;
677 BOOLEAN IsExtendedFilter=FALSE;
678
679 IF_LOUD(DbgPrint("NPF: IoControl\n");)
680
681 IrpSp = IoGetCurrentIrpStackLocation(Irp);
682 FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
683 Open=IrpSp->FileObject->FsContext;
684
685 Irp->IoStatus.Status = STATUS_SUCCESS;
686
687 IF_LOUD(DbgPrint("NPF: Function code is %08lx buff size=%08lx %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);)
688
689
690 switch (FunctionCode){
691
692 case BIOCGSTATS: //function to get the capture stats
693
694 if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4*sizeof(INT)){
695 EXIT_FAILURE(0);
696 }
697
698 *(((PUINT)Irp->UserBuffer)+3) = Open->Accepted;
699 *(((PUINT)Irp->UserBuffer)) = Open->Received;
700 *(((PUINT)Irp->UserBuffer)+1) = Open->Dropped;
701 *(((PUINT)Irp->UserBuffer)+2) = 0; // Not yet supported
702
703 EXIT_SUCCESS(4*sizeof(INT));
704
705 break;
706
707 case BIOCGEVNAME: //function to get the name of the event associated with the current instance
708
709 if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength<26){
710 EXIT_FAILURE(0);
711 }
712
713 RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26);
714
715 EXIT_SUCCESS(26);
716
717 break;
718
719 case BIOCSENDPACKETSSYNC:
720
721 SyncWrite = TRUE;
722
723 case BIOCSENDPACKETSNOSYNC:
724
725 WriteRes = NPF_BufferedWrite(Irp,
726 (PUCHAR)Irp->AssociatedIrp.SystemBuffer,
727 IrpSp->Parameters.DeviceIoControl.InputBufferLength,
728 SyncWrite);
729
730 if( WriteRes != -1)
731 {
732 EXIT_SUCCESS(WriteRes);
733 }
734
735 EXIT_FAILURE(WriteRes);
736
737 break;
738
739 case BIOCSETF:
740
741 // Free the previous buffer if it was present
742 if(Open->bpfprogram!=NULL){
743 TmpBPFProgram=Open->bpfprogram;
744 Open->bpfprogram = NULL;
745 ExFreePool(TmpBPFProgram);
746 }
747
748 if (Open->Filter!=NULL)
749 {
750 JIT_BPF_Filter *OldFilter=Open->Filter;
751 Open->Filter=NULL;
752 BPF_Destroy_JIT_Filter(OldFilter);
753 }
754
755 // Get the pointer to the new program
756 prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
757
758 if(prog==NULL){
759 IF_LOUD(DbgPrint("0001");)
760
761 EXIT_FAILURE(0);
762 }
763
764 insns=(IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn);
765
766 //count the number of operative instructions
767 for (cnt=0;(cnt<insns) &&(((struct bpf_insn*)prog)[cnt].code!=BPF_SEPARATION); cnt++);
768
769 IF_LOUD(DbgPrint("Operative instructions=%u\n",cnt);)
770
771 if (((struct bpf_insn*)prog)[cnt].code==BPF_SEPARATION && (insns-cnt-1)!=0)
772 {
773 IF_LOUD(DbgPrint("Initialization instructions=%u\n",insns-cnt-1);)
774
775 IsExtendedFilter=TRUE;
776
777 initprogram=&((struct bpf_insn*)prog)[cnt+1];
778
779 if(bpf_filter_init(initprogram,&(Open->mem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK)
780 {
781
782 IF_LOUD(DbgPrint("Error initializing NPF machine (bpf_filter_init)\n");)
783
784 EXIT_FAILURE(0);
785 }
786 }
787
788 //the NPF processor has been initialized, we have to validate the operative instructions
789 insns=cnt;
790
791 if(bpf_validate((struct bpf_insn*)prog,cnt,Open->mem_ex.size)==0)
792 {
793 IF_LOUD(DbgPrint("Error validating program");)
794 //FIXME: the machine has been initialized(?), but the operative code is wrong.
795 //we have to reset the machine!
796 //something like: reallocate the mem_ex, and reset the tme_core
797 EXIT_FAILURE(0);
798 }
799
800 // Allocate the memory to contain the new filter program
801 // We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers()
802 #define NPF_TAG_BPFPROG TAG('4', 'P', 'W', 'A')
803 TmpBPFProgram=(PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), NPF_TAG_BPFPROG);
804 if (TmpBPFProgram==NULL){
805 IF_LOUD(DbgPrint("Error - No memory for filter");)
806 // no memory
807 EXIT_FAILURE(0);
808 }
809
810 //copy the program in the new buffer
811 RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn));
812 Open->bpfprogram=TmpBPFProgram;
813
814 // Create the new JIT filter function
815 if(!IsExtendedFilter)
816 if((Open->Filter=BPF_jitter((struct bpf_insn*)Open->bpfprogram,cnt)) == NULL) {
817 IF_LOUD(DbgPrint("Error jittering filter");)
818 EXIT_FAILURE(0);
819 }
820
821 //return
822 Open->Bhead = 0;
823 Open->Btail = 0;
824 (INT)Open->BLastByte = -1;
825 Open->Received = 0;
826 Open->Dropped = 0;
827 Open->Accepted = 0;
828
829 EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
830
831 break;
832
833 case BIOCSMODE: //set the capture mode
834
835 mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
836
837 if(mode == MODE_CAPT){
838 Open->mode=MODE_CAPT;
839
840 EXIT_SUCCESS(0);
841 }
842 else if (mode==MODE_MON){
843 Open->mode=MODE_MON;
844
845 EXIT_SUCCESS(0);
846 }
847 else{
848 if(mode & MODE_STAT){
849 Open->mode = MODE_STAT;
850 Open->Nbytes.QuadPart=0;
851 Open->Npackets.QuadPart=0;
852
853 if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart=-10000000;
854
855 }
856
857 if(mode & MODE_DUMP){
858
859 Open->mode |= MODE_DUMP;
860 Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000;
861
862 }
863 EXIT_SUCCESS(0);
864 }
865
866 EXIT_FAILURE(0);
867
868 break;
869
870 case BIOCSETDUMPFILENAME:
871
872 if(Open->mode & MODE_DUMP)
873 {
874
875 // Close current dump file
876 if(Open->DumpFileHandle != NULL){
877 NPF_CloseDumpFile(Open);
878 Open->DumpFileHandle = NULL;
879 }
880
881 if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){
882 EXIT_FAILURE(0);
883 }
884
885 // Allocate the buffer that will contain the string
886 #define NPF_TAG_DUMPNAMEBUF TAG('5', 'P', 'W', 'A')
887 DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, NPF_TAG_DUMPNAMEBUF);
888 if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){
889 IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)
890 EXIT_FAILURE(0);
891 }
892
893 // Copy the buffer
894 RtlCopyBytes((PVOID)DumpNameBuff,
895 Irp->AssociatedIrp.SystemBuffer,
896 IrpSp->Parameters.DeviceIoControl.InputBufferLength);
897
898 // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system
899 ((SHORT*)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0;
900
901 // Create the unicode string
902 RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff);
903
904 IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",
905 Open->DumpFileName.Buffer,
906 IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
907
908 // Try to create the file
909 if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) &&
910 NT_SUCCESS( NPF_StartDump(Open))){
911
912 EXIT_SUCCESS(0);
913 }
914 }
915
916 EXIT_FAILURE(0);
917
918 break;
919
920 case BIOCSETDUMPLIMITS:
921
922 Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
923 Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1);
924
925 IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);)
926
927 EXIT_SUCCESS(0);
928
929 break;
930
931 case BIOCISDUMPENDED:
932 if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4){
933 EXIT_FAILURE(0);
934 }
935
936 *((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
937
938 EXIT_SUCCESS(4);
939
940 break;
941
942 case BIOCSETBUFFERSIZE:
943
944 // Get the number of bytes to allocate
945 dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
946
947 // Free the old buffer
948 tpointer = Open->Buffer;
949 if(tpointer != NULL){
950 Open->BufSize = 0;
951 Open->Buffer = NULL;
952 ExFreePool(tpointer);
953 }
954 // Allocate the new buffer
955 if(dim!=0){
956 #define NPF_TAG_TPOINTER TAG('6', 'P', 'W', 'A')
957 tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, NPF_TAG_TPOINTER);
958 if (tpointer==NULL) {
959 // no memory
960 Open->BufSize = 0;
961 Open->Buffer = NULL;
962 EXIT_FAILURE(0);
963 }
964 }
965 else
966 tpointer = NULL;
967
968 Open->Buffer = tpointer;
969 Open->Bhead = 0;
970 Open->Btail = 0;
971 (INT)Open->BLastByte = -1;
972
973 Open->BufSize = (UINT)dim;
974 EXIT_SUCCESS(dim);
975
976 break;
977
978 case BIOCSRTIMEOUT: //set the timeout on the read calls
979
980 timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
981 if((int)timeout==-1)
982 Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;
983 else {
984 Open->TimeOut.QuadPart=(LONGLONG)timeout;
985 Open->TimeOut.QuadPart*=10000;
986 Open->TimeOut.QuadPart=-Open->TimeOut.QuadPart;
987 }
988
989 //IF_LOUD(DbgPrint("NPF: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);)
990 EXIT_SUCCESS(timeout);
991
992 break;
993
994 case BIOCSWRITEREP: //set the writes repetition number
995
996 Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
997
998 EXIT_SUCCESS(Open->Nwrites);
999
1000 break;
1001
1002 case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
1003
1004 Open->MinToCopy = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
1005
1006 EXIT_SUCCESS(Open->MinToCopy);
1007
1008 break;
1009
1010 case IOCTL_PROTOCOL_RESET:
1011
1012 IF_LOUD(DbgPrint("NPF: IoControl - Reset request\n");)
1013
1014 IoMarkIrpPending(Irp);
1015 Irp->IoStatus.Status = STATUS_SUCCESS;
1016
1017 ExInterlockedInsertTailList(&Open->ResetIrpList,&Irp->Tail.Overlay.ListEntry,&Open->RequestSpinLock);
1018 NdisReset(&Status,Open->AdapterHandle);
1019 if (Status != NDIS_STATUS_PENDING) {
1020 IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)
1021 NPF_ResetComplete(Open,Status);
1022 }
1023
1024 break;
1025
1026
1027 case BIOCSETOID:
1028 case BIOCQUERYOID:
1029
1030 // Extract a request from the list of free ones
1031 RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);
1032 if (RequestListEntry == NULL)
1033 {
1034 EXIT_FAILURE(0);
1035 }
1036
1037 pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);
1038 pRequest->Irp=Irp;
1039 pRequest->Internal = FALSE;
1040
1041
1042 //
1043 // See if it is an Ndis request
1044 //
1045 OidData=Irp->AssociatedIrp.SystemBuffer;
1046
1047 if (((FunctionCode == BIOCSETOID) || (FunctionCode == BIOCQUERYOID))
1048 &&
1049 (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)
1050 &&
1051 (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
1052 &&
1053 (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {
1054
1055 IF_LOUD(DbgPrint("NPF: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);)
1056
1057 //
1058 // The buffer is valid
1059 //
1060 if (FunctionCode == BIOCSETOID){
1061
1062 pRequest->Request.RequestType=NdisRequestSetInformation;
1063 pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid;
1064
1065 pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data;
1066 pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length;
1067 } else{
1068 pRequest->Request.RequestType=NdisRequestQueryInformation;
1069 pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid;
1070
1071 pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data;
1072 pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length;
1073
1074 }
1075
1076 NdisResetEvent(&Open->IOEvent);
1077 //
1078 // submit the request
1079 //
1080 NdisRequest(
1081 &Status,
1082 Open->AdapterHandle,
1083 &pRequest->Request
1084 );
1085
1086 } else {
1087 //
1088 // buffer too small
1089 //
1090 Status=NDIS_STATUS_FAILURE;
1091 pRequest->Request.DATA.SET_INFORMATION.BytesRead=0;
1092 pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0;
1093
1094 }
1095
1096 if (Status != NDIS_STATUS_PENDING) {
1097 IF_LOUD(DbgPrint("NPF: Calling RequestCompleteHandler\n");)
1098
1099 NPF_RequestComplete(Open, &pRequest->Request, Status);
1100 return Status;
1101
1102 }
1103
1104 NdisWaitEvent(&Open->IOEvent, 5000);
1105
1106 return(Open->IOStatus);
1107
1108 break;
1109
1110
1111 default:
1112
1113 EXIT_FAILURE(0);
1114 }
1115
1116 return Status;
1117 }
1118
1119 //-------------------------------------------------------------------
1120
1121 VOID
1122 NPF_RequestComplete(
1123 IN NDIS_HANDLE ProtocolBindingContext,
1124 IN PNDIS_REQUEST NdisRequest,
1125 IN NDIS_STATUS Status
1126 )
1127
1128 {
1129 POPEN_INSTANCE Open;
1130 PIO_STACK_LOCATION IrpSp;
1131 PIRP Irp;
1132 PINTERNAL_REQUEST pRequest;
1133 UINT FunctionCode;
1134 KIRQL OldIrq;
1135
1136 PPACKET_OID_DATA OidData;
1137
1138 IF_LOUD(DbgPrint("NPF: RequestComplete\n");)
1139
1140 Open= (POPEN_INSTANCE)ProtocolBindingContext;
1141
1142 pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
1143 Irp=pRequest->Irp;
1144
1145 if(pRequest->Internal == TRUE){
1146
1147 // Put the request in the list of the free ones
1148 ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
1149
1150 if(Status != NDIS_STATUS_SUCCESS)
1151 Open->MaxFrameSize = 1514; // Assume Ethernet
1152
1153 // We always return success, because the adapter has been already opened
1154 Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
1155 Irp->IoStatus.Information = 0;
1156 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1157 return;
1158 }
1159
1160 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1161
1162 FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
1163
1164 OidData=Irp->AssociatedIrp.SystemBuffer;
1165
1166 if (FunctionCode == BIOCSETOID) {
1167
1168 OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead;
1169
1170 } else {
1171
1172 if (FunctionCode == BIOCQUERYOID) {
1173
1174 OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
1175
1176 IF_LOUD(DbgPrint("RequestComplete: BytesWritten=%d\n",pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten);)
1177 }
1178
1179 }
1180
1181 Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1182
1183 IF_LOUD(DbgPrint("RequestComplete: BytesReturned=%d\n",IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
1184
1185 ExInterlockedInsertTailList(
1186 &Open->RequestList,
1187 &pRequest->ListElement,
1188 &Open->RequestSpinLock);
1189
1190 Irp->IoStatus.Status = Status;
1191
1192 Open->IOStatus = Status;
1193
1194 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1195
1196 // Unlock the caller
1197 NdisSetEvent(&Open->IOEvent);
1198
1199 return;
1200
1201
1202 }
1203
1204 //-------------------------------------------------------------------
1205
1206 VOID
1207 NPF_Status(
1208 IN NDIS_HANDLE ProtocolBindingContext,
1209 IN NDIS_STATUS Status,
1210 IN PVOID StatusBuffer,
1211 IN UINT StatusBufferSize
1212 )
1213
1214 {
1215
1216 IF_LOUD(DbgPrint("NPF: Status Indication\n");)
1217
1218 return;
1219
1220 }
1221
1222 //-------------------------------------------------------------------
1223
1224 VOID
1225 NPF_StatusComplete(
1226 IN NDIS_HANDLE ProtocolBindingContext
1227 )
1228
1229 {
1230
1231 IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
1232
1233 return;
1234
1235 }
1236
1237 //-------------------------------------------------------------------
1238
1239 NTSTATUS
1240 NPF_ReadRegistry(
1241 IN PWSTR *MacDriverName,
1242 IN PWSTR *PacketDriverName,
1243 IN PUNICODE_STRING RegistryPath
1244 )
1245
1246 {
1247 NTSTATUS Status;
1248
1249 RTL_QUERY_REGISTRY_TABLE ParamTable[4];
1250
1251 PWSTR Bind = L"Bind";
1252 PWSTR Export = L"Export";
1253 PWSTR Parameters = L"Parameters";
1254 PWSTR Linkage = L"Linkage";
1255
1256 PWCHAR Path;
1257
1258 #define NPF_TAG_PATH TAG('7', 'P', 'W', 'A')
1259 Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), NPF_TAG_PATH);
1260
1261 if (Path == NULL) {
1262 IF_LOUD(DbgPrint("\nPacketReadRegistry: returing STATUS_INSUFFICIENT_RESOURCES\n");)
1263 return STATUS_INSUFFICIENT_RESOURCES;
1264 }
1265
1266 RtlZeroMemory(
1267 Path,
1268 RegistryPath->Length+sizeof(WCHAR)
1269 );
1270
1271 RtlCopyMemory(
1272 Path,
1273 RegistryPath->Buffer,
1274 RegistryPath->Length
1275 );
1276
1277 IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath->Buffer);)
1278
1279 RtlZeroMemory(
1280 ParamTable,
1281 sizeof(ParamTable)
1282 );
1283
1284
1285
1286 //
1287 // change to the linkage key
1288 //
1289 //ParamTable[0].QueryRoutine = NULL;
1290 ParamTable[0].QueryRoutine = NPF_QueryRegistryRoutine;
1291 ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
1292 ParamTable[0].Name = Linkage;
1293
1294
1295 //
1296 // Get the name of the mac driver we should bind to
1297 //
1298
1299 ParamTable[1].QueryRoutine = NPF_QueryRegistryRoutine;
1300 ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED |
1301 RTL_QUERY_REGISTRY_NOEXPAND;
1302
1303 ParamTable[1].Name = Bind;
1304 ParamTable[1].EntryContext = (PVOID)MacDriverName;
1305 ParamTable[1].DefaultType = REG_MULTI_SZ;
1306
1307 //
1308 // Get the name that we should use for the driver object
1309 //
1310
1311 ParamTable[2].QueryRoutine = NPF_QueryRegistryRoutine;
1312 ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED |
1313 RTL_QUERY_REGISTRY_NOEXPAND;
1314
1315 ParamTable[2].Name = Export;
1316 ParamTable[2].EntryContext = (PVOID)PacketDriverName;
1317 ParamTable[2].DefaultType = REG_MULTI_SZ;
1318
1319
1320 Status=RtlQueryRegistryValues(
1321 RTL_REGISTRY_ABSOLUTE,
1322 Path,
1323 ParamTable,
1324 NULL,
1325 NULL
1326 );
1327
1328 if (Status != STATUS_SUCCESS) {
1329 // insert hard coded parameters here while registry on ROS is not working...
1330 IF_LOUD(DbgPrint("PacketReadRegistry() RtlQueryRegistryValues failed - returing fixed parameters\n");)
1331
1332 *MacDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
1333 //memcpy(*MacDriverName, L"\\Device\\ne2000", 15 * sizeof(WCHAR));
1334 memcpy(*MacDriverName, L"\\Device\\ne2000", 15 * sizeof(WCHAR));
1335
1336 *PacketDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
1337 memcpy(*PacketDriverName, L"\\Device\\NPF_ne2000", 19 * sizeof(WCHAR));
1338 Status = STATUS_SUCCESS;
1339
1340 }
1341
1342 ExFreePool(Path);
1343 return Status;
1344 }
1345
1346 //-------------------------------------------------------------------
1347
1348 NTSTATUS
1349 NPF_QueryRegistryRoutine(
1350 IN PWSTR ValueName,
1351 IN ULONG ValueType,
1352 IN PVOID ValueData,
1353 IN ULONG ValueLength,
1354 IN PVOID Context,
1355 IN PVOID EntryContext
1356 )
1357
1358 {
1359
1360 PUCHAR Buffer;
1361
1362 IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");)
1363
1364 if (ValueType != REG_MULTI_SZ) {
1365
1366 return STATUS_OBJECT_NAME_NOT_FOUND;
1367
1368 }
1369
1370 #define NPF_TAG_REGBUF TAG('8', 'P', 'W', 'A')
1371 Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, NPF_TAG_REGBUF);
1372
1373 if (Buffer==NULL) {
1374
1375 return STATUS_INSUFFICIENT_RESOURCES;
1376
1377 }
1378
1379 RtlCopyMemory(
1380 Buffer,
1381 ValueData,
1382 ValueLength
1383 );
1384
1385 *((PUCHAR *)EntryContext)=Buffer;
1386
1387 return STATUS_SUCCESS;
1388
1389 }