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