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