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