Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

Packet.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1999 - 2003
00003  * NetGroup, Politecnico di Torino (Italy)
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  * notice, this list of conditions and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright
00013  * notice, this list of conditions and the following disclaimer in the
00014  * documentation and/or other materials provided with the distribution.
00015  * 3. Neither the name of the Politecnico di Torino nor the names of its
00016  * contributors may be used to endorse or promote products derived from
00017  * this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00022  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00023  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00024  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00025  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00026  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00027  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00029  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  *
00031  */
00032 
00033 #include "stdarg.h"
00034 #include "ntddk.h"
00035 #include "ntiologc.h"
00036 #include "ndis.h"
00037 
00038 #include "ntddpack.h"
00039 
00040 #include "debug.h"
00041 #include "packet.h"
00042 #include "win_bpf.h"
00043 #include "win_bpf_filter_init.h"
00044 
00045 #include "tme.h"
00046 
00047 #if DBG
00048 // Declare the global debug flag for this driver.
00049 ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
00050 
00051 #endif
00052 
00053 PDEVICE_EXTENSION GlobalDeviceExtension;
00054 
00055 //
00056 // Global strings
00057 //
00058 NDIS_STRING NPF_Prefix = NDIS_STRING_CONST("NPF_");
00059 NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
00060 NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
00061 NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System"
00062                                 L"\\CurrentControlSet\\Services\\Tcpip\\Linkage");
00063 NDIS_STRING AdapterListKey = NDIS_STRING_CONST("\\Registry\\Machine\\System"
00064                                 L"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
00065 NDIS_STRING bindValueName = NDIS_STRING_CONST("Bind");
00066 
00067 
00069 WCHAR* bindP = NULL;
00070 
00071 extern struct time_conv G_Start_Time; // from openclos.c
00072 
00073 extern NDIS_SPIN_LOCK Opened_Instances_Lock;
00074 
00075 ULONG NCpu;
00076 
00077 //
00078 //  Packet Driver's entry routine.
00079 //
00080 NTSTATUS
00081 DriverEntry(
00082     IN PDRIVER_OBJECT DriverObject,
00083     IN PUNICODE_STRING RegistryPath
00084     )
00085 {
00086 
00087     NDIS_PROTOCOL_CHARACTERISTICS  ProtocolChar;
00088     UNICODE_STRING MacDriverName;
00089     UNICODE_STRING UnicodeDeviceName;
00090     PDEVICE_OBJECT DeviceObject = NULL;
00091     PDEVICE_EXTENSION DeviceExtension = NULL;
00092     NTSTATUS Status = STATUS_SUCCESS;
00093     NTSTATUS ErrorCode = STATUS_SUCCESS;
00094     NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver");
00095     ULONG          DevicesCreated=0;
00096     PWSTR          BindString;
00097     PWSTR          ExportString;
00098     PWSTR          BindStringSave;
00099     PWSTR          ExportStringSave;
00100     NDIS_HANDLE    NdisProtocolHandle;
00101     WCHAR* bindT;
00102     PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
00103     UNICODE_STRING macName;
00104     
00105     NCpu = NdisSystemProcessorCount();
00106 
00107     IF_LOUD(DbgPrint("\n\nPacket: DriverEntry\n");)
00108 
00109     RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
00110 
00111 #ifdef NDIS50
00112     ProtocolChar.MajorNdisVersion            = 5;
00113 #else
00114     ProtocolChar.MajorNdisVersion            = 3;
00115 #endif
00116     ProtocolChar.MinorNdisVersion            = 0;
00117     ProtocolChar.Reserved                    = 0;
00118     ProtocolChar.OpenAdapterCompleteHandler  = NPF_OpenAdapterComplete;
00119     ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
00120     ProtocolChar.SendCompleteHandler         = NPF_SendComplete;
00121     ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
00122     ProtocolChar.ResetCompleteHandler        = NPF_ResetComplete;
00123     ProtocolChar.RequestCompleteHandler      = NPF_RequestComplete;
00124     ProtocolChar.ReceiveHandler              = NPF_tap;
00125     ProtocolChar.ReceiveCompleteHandler      = NPF_ReceiveComplete;
00126     ProtocolChar.StatusHandler               = NPF_Status;
00127     ProtocolChar.StatusCompleteHandler       = NPF_StatusComplete;
00128 #ifdef NDIS50
00129     ProtocolChar.BindAdapterHandler          = NPF_BindAdapter;
00130     ProtocolChar.UnbindAdapterHandler        = NPF_UnbindAdapter;
00131     ProtocolChar.PnPEventHandler             = NPF_PowerChange;
00132     ProtocolChar.ReceivePacketHandler        = NULL;
00133 #endif
00134     ProtocolChar.Name                        = ProtoName;
00135 
00136     NdisRegisterProtocol(
00137         &Status,
00138         &NdisProtocolHandle,
00139         &ProtocolChar,
00140         sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
00141 
00142     if (Status != NDIS_STATUS_SUCCESS) {
00143 
00144         IF_LOUD(DbgPrint("NPF: Failed to register protocol with NDIS\n");)
00145 
00146         return Status;
00147 
00148     }
00149     
00150     NdisAllocateSpinLock(&Opened_Instances_Lock);
00151 
00152     // Set up the device driver entry points.
00153     DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open;
00154     DriverObject->MajorFunction[IRP_MJ_CLOSE]  = NPF_Close;
00155     DriverObject->MajorFunction[IRP_MJ_READ]   = NPF_Read;
00156     DriverObject->MajorFunction[IRP_MJ_WRITE]  = NPF_Write;
00157     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = NPF_IoControl;
00158     DriverObject->DriverUnload = NPF_Unload;
00159 
00160     bindP = getAdaptersList();
00161 
00162     if (bindP == NULL) 
00163     {
00164         IF_LOUD(DbgPrint("Adapters not found in the registry, try to copy the bindings of TCP-IP.\n");)
00165 
00166         tcpBindingsP = getTcpBindings();
00167             
00168         if (tcpBindingsP == NULL)
00169         {
00170             IF_LOUD(DbgPrint("TCP-IP not found, quitting.\n");)
00171             goto RegistryError;
00172         }
00173             
00174         bindP = (WCHAR*)tcpBindingsP;
00175         bindT = (WCHAR*)(tcpBindingsP->Data);
00176             
00177     }
00178     else 
00179     {
00180         bindT = bindP;
00181     }
00182 
00183     for (; *bindT != UNICODE_NULL; bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR)) 
00184     {
00185         RtlInitUnicodeString(&macName, bindT);
00186         createDevice(DriverObject, &macName, NdisProtocolHandle);
00187     }
00188 
00189     return STATUS_SUCCESS;
00190 
00191 RegistryError:
00192 
00193     NdisDeregisterProtocol(
00194         &Status,
00195         NdisProtocolHandle
00196         );
00197 
00198     Status=STATUS_UNSUCCESSFUL;
00199 
00200     return(Status);
00201 
00202 }
00203 
00204 //-------------------------------------------------------------------
00205 
00206 PWCHAR getAdaptersList(void)
00207 {
00208     PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
00209     OBJECT_ATTRIBUTES objAttrs;
00210     NTSTATUS status;
00211     HANDLE keyHandle;
00212     UINT BufPos=0;
00213     
00214     PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, 4096, '0PWA');
00215     
00216     if (DeviceNames == NULL) {
00217         IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
00218             return NULL;
00219     }
00220     
00221     InitializeObjectAttributes(&objAttrs, &AdapterListKey,
00222         OBJ_CASE_INSENSITIVE, NULL, NULL);
00223     status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
00224     if (!NT_SUCCESS(status)) {
00225         IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
00226     }
00227     else { //OK
00228         
00229         ULONG resultLength;
00230         KEY_VALUE_PARTIAL_INFORMATION valueInfo;
00231         CHAR AdapInfo[1024];
00232         UINT i=0;
00233         
00234         IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%x\n",DeviceNames);)
00235             
00236             // Scan the list of the devices
00237             while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS)
00238             {
00239                 WCHAR ExportKeyName [512];
00240                 PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
00241                 UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
00242                 PWCHAR LinkageKeyPrefix = L"\\Linkage";
00243                 UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage");
00244                 NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export");
00245                 PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo;
00246                 UNICODE_STRING AdapterKeyName;
00247                 HANDLE ExportKeyHandle;
00248                 KEY_VALUE_PARTIAL_INFORMATION valueInfo;
00249                 ULONG resultLength;
00250                 
00251                 RtlCopyMemory(ExportKeyName,
00252                     ExportKeyPrefix,
00253                     ExportKeyPrefixSize);
00254                 
00255                 RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,
00256                     tInfo->Name,
00257                     tInfo->NameLength+2);
00258                 
00259                 RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,
00260                     LinkageKeyPrefix,
00261                     LinkageKeyPrefixSize);
00262                 
00263                 IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);)
00264                                         
00265                 RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);
00266                 
00267                 InitializeObjectAttributes(&objAttrs, &AdapterKeyName,
00268                     OBJ_CASE_INSENSITIVE, NULL, NULL);
00269                 
00270                 status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);
00271                 
00272                 if (!NT_SUCCESS(status)) {
00273                     DbgPrint("OpenKey Failed, %d!\n",status);
00274                     i++;
00275                     continue;
00276                 }
00277                 
00278                 status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
00279                     KeyValuePartialInformation, &valueInfo,
00280                     sizeof(valueInfo), &resultLength);
00281                 
00282                 if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
00283                     IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
00284                 }
00285                 else {                      // We know how big it needs to be.
00286                     ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
00287                     PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, '1PWA');
00288                     if (valueInfoP != NULL) {
00289                         status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
00290                             KeyValuePartialInformation,
00291                             valueInfoP,
00292                             valueInfoLength, &resultLength);
00293                         if (!NT_SUCCESS(status)) {
00294                             IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
00295                         }
00296                         else{
00297                             IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
00298                                 RtlCopyMemory((PCHAR)DeviceNames+BufPos,
00299                                 valueInfoP->Data,
00300                                 valueInfoP->DataLength);
00301                             BufPos+=valueInfoP->DataLength-2;
00302                         }
00303                         
00304                         ExFreePool(valueInfoP);
00305                     }
00306                     else {
00307                         IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
00308                     }
00309                     
00310                 }
00311                 
00312                 // terminate the buffer
00313                 DeviceNames[BufPos/2]=0;
00314                 DeviceNames[BufPos/2+1]=0;
00315                 
00316                 ZwClose (ExportKeyHandle);
00317                 i++;
00318                 
00319             }
00320             
00321             ZwClose (keyHandle);
00322             
00323     }
00324     if(BufPos==0){
00325         ExFreePool(DeviceNames);
00326         return NULL;
00327     }
00328     return DeviceNames;
00329 }
00330 
00331 //-------------------------------------------------------------------
00332 
00333 PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
00334 {
00335   PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
00336   OBJECT_ATTRIBUTES objAttrs;
00337   NTSTATUS status;
00338   HANDLE keyHandle;
00339 
00340   InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName,
00341                              OBJ_CASE_INSENSITIVE, NULL, NULL);
00342   status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
00343   if (!NT_SUCCESS(status)) {
00344     IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
00345   }
00346   else {
00347     ULONG resultLength;
00348     KEY_VALUE_PARTIAL_INFORMATION valueInfo;
00349 
00350     IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);)
00351 
00352     status = ZwQueryValueKey(keyHandle, &bindValueName,
00353                              KeyValuePartialInformation, &valueInfo,
00354                              sizeof(valueInfo), &resultLength);
00355     if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
00356       IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
00357     }
00358     else {                      // We know how big it needs to be.
00359       ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
00360       PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
00361         (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, '2PWA');
00362       
00363       if (valueInfoP != NULL) {
00364         status = ZwQueryValueKey(keyHandle, &bindValueName,
00365                                  KeyValuePartialInformation,
00366                                  valueInfoP,
00367                                  valueInfoLength, &resultLength);
00368       
00369         if (!NT_SUCCESS(status)) {
00370           IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
00371         }
00372         else if (valueInfoLength != resultLength) {
00373           IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
00374                      "but previous len = %u\n",
00375                      resultLength, valueInfoLength);)
00376         }
00377         else if (valueInfoP->Type != REG_MULTI_SZ) {
00378           IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
00379                      valueInfoP->Type);)
00380         }
00381         else {                  // It's OK
00382 #if DBG
00383           ULONG i;
00384           WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]);
00385           IF_LOUD(DbgPrint("\n\nBind value:\n");)
00386           for (i = 0; *dataP != UNICODE_NULL; i++) {
00387             UNICODE_STRING macName;
00388             RtlInitUnicodeString(&macName, dataP);
00389             IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);)
00390             dataP +=
00391               (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
00392           }
00393 #endif // DBG
00394           result = valueInfoP;
00395         }
00396       }
00397     }
00398     ZwClose(keyHandle);
00399   }
00400   return result;
00401 }
00402 
00403 //-------------------------------------------------------------------
00404 
00405 BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
00406                      IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle)
00407 {
00408     NTSTATUS status;
00409     PDEVICE_OBJECT devObjP;
00410     UNICODE_STRING deviceName;
00411     UNICODE_STRING deviceSymLink;
00412 
00413     IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer););
00414     if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
00415         devicePrefix.Length) < devicePrefix.Length) 
00416     {
00417         return FALSE;
00418     }
00419 
00420     deviceName.Length = 0;
00421     deviceName.MaximumLength = (USHORT)(amacNameP->Length + NPF_Prefix.Length + sizeof(UNICODE_NULL));
00422     deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, '3PWA');
00423 
00424     if (deviceName.Buffer == NULL)
00425         return FALSE;
00426 
00427     deviceSymLink.Length = 0;
00428     deviceSymLink.MaximumLength =(USHORT)(amacNameP->Length-devicePrefix.Length 
00429         + symbolicLinkPrefix.Length 
00430         + NPF_Prefix.Length 
00431         + sizeof(UNICODE_NULL));
00432 
00433     deviceSymLink.Buffer = ExAllocatePoolWithTag(NonPagedPool, deviceSymLink.MaximumLength, '3PWA');
00434 
00435     if (deviceSymLink.Buffer  == NULL)
00436     {
00437         ExFreePool(deviceName.Buffer);
00438         return FALSE;
00439     }
00440 
00441     RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
00442     RtlAppendUnicodeStringToString(&deviceName, &NPF_Prefix);
00443     RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer +
00444         devicePrefix.Length / sizeof(WCHAR));
00445 
00446     RtlAppendUnicodeStringToString(&deviceSymLink, &symbolicLinkPrefix);
00447     RtlAppendUnicodeStringToString(&deviceSymLink, &NPF_Prefix);
00448     RtlAppendUnicodeToString(&deviceSymLink, amacNameP->Buffer +
00449         devicePrefix.Length / sizeof(WCHAR));
00450 
00451     IF_LOUD(DbgPrint("Creating device name: %ws\n", deviceName.Buffer);)
00452 
00453         status = IoCreateDevice(adriverObjectP, 
00454         sizeof(DEVICE_EXTENSION),
00455         &deviceName, 
00456         FILE_DEVICE_TRANSPORT, 
00457         0, 
00458         FALSE,
00459         &devObjP);
00460 
00461     if (NT_SUCCESS(status)) 
00462     {
00463         PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension;
00464         
00465         IF_LOUD(DbgPrint("Device created successfully\n"););
00466 
00467         devObjP->Flags |= DO_DIRECT_IO;
00468         RtlInitUnicodeString(&devExtP->AdapterName,amacNameP->Buffer);   
00469         devExtP->NdisProtocolHandle=aProtoHandle;
00470 
00471         IF_LOUD(DbgPrint("Trying to create SymLink %ws\n",deviceSymLink.Buffer););
00472 
00473         if (IoCreateSymbolicLink(&deviceSymLink,&deviceName) != STATUS_SUCCESS)
00474         {
00475             IF_LOUD(DbgPrint("\n\nError creating SymLink %ws\nn", deviceSymLink.Buffer););
00476 
00477             ExFreePool(deviceName.Buffer);
00478             ExFreePool(deviceSymLink.Buffer);
00479 
00480             devExtP->ExportString = NULL;
00481 
00482             return FALSE;
00483         }
00484 
00485         IF_LOUD(DbgPrint("SymLink %ws successfully created.\n\n", deviceSymLink.Buffer););
00486 
00487         devExtP->ExportString = deviceSymLink.Buffer;
00488 
00489         ExFreePool(deviceName.Buffer);
00490 
00491         return TRUE;
00492     }
00493 
00494     else 
00495     {
00496         IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
00497 
00498         ExFreePool(deviceName.Buffer);
00499         ExFreePool(deviceSymLink.Buffer);
00500         
00501         return FALSE;
00502     }
00503 }
00504 //-------------------------------------------------------------------
00505 
00506 VOID NPF_Unload(IN PDRIVER_OBJECT DriverObject)
00507 {
00508     PDEVICE_OBJECT     DeviceObject;
00509     PDEVICE_OBJECT     OldDeviceObject;
00510     PDEVICE_EXTENSION  DeviceExtension;
00511 
00512     NDIS_HANDLE        NdisProtocolHandle;
00513     NDIS_STATUS        Status;
00514 
00515     NDIS_STRING        SymLink;
00516 
00517     IF_LOUD(DbgPrint("NPF: Unload\n"););
00518 
00519     DeviceObject    = DriverObject->DeviceObject;
00520 
00521     while (DeviceObject != NULL) {
00522         OldDeviceObject = DeviceObject;
00523 
00524         DeviceObject = DeviceObject->NextDevice;
00525 
00526         DeviceExtension = OldDeviceObject->DeviceExtension;
00527 
00528         NdisProtocolHandle=DeviceExtension->NdisProtocolHandle;
00529 
00530         IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n",
00531             DeviceExtension->AdapterName.Buffer,
00532             NdisProtocolHandle,
00533             DeviceObject,
00534             OldDeviceObject););
00535 
00536         if (DeviceExtension->ExportString)
00537         {
00538             RtlInitUnicodeString(&SymLink , DeviceExtension->ExportString);
00539 
00540             IF_LOUD(DbgPrint("Deleting SymLink at %p\n", SymLink.Buffer););
00541 
00542             IoDeleteSymbolicLink(&SymLink);
00543             ExFreePool(DeviceExtension->ExportString);
00544         }
00545 
00546         IoDeleteDevice(OldDeviceObject);
00547     }
00548 
00549     NdisDeregisterProtocol(
00550         &Status,
00551         NdisProtocolHandle
00552         );
00553 
00554     // Free the adapters names
00555     ExFreePool( bindP );
00556 }
00557 
00558 //-------------------------------------------------------------------
00559 
00560 NTSTATUS NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
00561 {
00562     POPEN_INSTANCE      Open;
00563     PIO_STACK_LOCATION  IrpSp;
00564     PLIST_ENTRY         RequestListEntry;
00565     PINTERNAL_REQUEST   pRequest;
00566     ULONG               FunctionCode;
00567     NDIS_STATUS         Status;
00568     PLIST_ENTRY         PacketListEntry;
00569     UINT                i;
00570     PUCHAR              tpointer;
00571     ULONG               dim,timeout;
00572     PUCHAR              prog;
00573     PPACKET_OID_DATA    OidData;
00574     int                 *StatsBuf;
00575     PNDIS_PACKET        pPacket;
00576     ULONG               mode;
00577     PWSTR               DumpNameBuff;
00578     PUCHAR              TmpBPFProgram;
00579     INT                 WriteRes;
00580     BOOLEAN             SyncWrite = FALSE;
00581     struct bpf_insn     *initprogram;
00582     ULONG               insns;
00583     ULONG               cnt;
00584     BOOLEAN             IsExtendedFilter=FALSE;
00585 
00586     BOOLEAN             Flag;
00587 
00588     IF_LOUD(DbgPrint("NPF: IoControl\n");)
00589         
00590     IrpSp = IoGetCurrentIrpStackLocation(Irp);
00591     FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
00592     Open=IrpSp->FileObject->FsContext;
00593 
00594     Irp->IoStatus.Status = STATUS_SUCCESS;
00595 
00596     IF_LOUD(DbgPrint("NPF: Function code is %08lx  buff size=%08lx  %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);)
00597 
00598     switch (FunctionCode){
00599         
00600     case BIOCGSTATS: //function to get the capture stats
00601         
00602         if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4*sizeof(INT)){           
00603             EXIT_FAILURE(0);
00604         }
00605 
00606         *(((PUINT)Irp->UserBuffer)+3) = 0;
00607         *(((PUINT)Irp->UserBuffer)+0) = 0;
00608         *(((PUINT)Irp->UserBuffer)+1) = 0;
00609         *(((PUINT)Irp->UserBuffer)+2) = 0;      // Not yet supported
00610 
00611         for(i=0;i<NCpu;i++)
00612         {
00613 
00614             *(((PUINT)Irp->UserBuffer)+3) += Open->CpuData[i].Accepted;
00615             *(((PUINT)Irp->UserBuffer)+0) += Open->CpuData[i].Received;
00616             *(((PUINT)Irp->UserBuffer)+1) += Open->CpuData[i].Dropped;
00617             *(((PUINT)Irp->UserBuffer)+2) += 0;     // Not yet supported
00618         }
00619         EXIT_SUCCESS(4*sizeof(INT));
00620         
00621         break;
00622         
00623     case BIOCGEVNAME: //function to get the name of the event associated with the current instance
00624 
00625         if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength<26){            
00626             EXIT_FAILURE(0);
00627         }
00628 
00629         RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26);
00630 
00631         EXIT_SUCCESS(26);
00632 
00633         break;
00634 
00635     case BIOCSENDPACKETSSYNC:
00636 
00637         SyncWrite = TRUE;
00638 
00639     case BIOCSENDPACKETSNOSYNC:
00640 
00641         WriteRes = NPF_BufferedWrite(Irp,
00642             (PUCHAR)Irp->AssociatedIrp.SystemBuffer,
00643             IrpSp->Parameters.DeviceIoControl.InputBufferLength,
00644             SyncWrite);
00645 
00646         if( WriteRes != -1)
00647         {
00648             EXIT_SUCCESS(WriteRes);
00649         }
00650         
00651         EXIT_FAILURE(WriteRes);
00652 
00653         break;
00654 
00655     case BIOCSETF:  
00656 
00657         Open->SkipProcessing = 1;
00658 
00659         do
00660         {
00661             Flag = FALSE;
00662             for(i=0;i<NCpu;i++)
00663                 if (Open->CpuData[i].Processing == 1)
00664                     Flag = TRUE;
00665         }
00666         while(Flag);  //BUSY FORM WAITING...
00667 
00668 
00669         // Free the previous buffer if it was present
00670         if(Open->bpfprogram!=NULL){
00671             TmpBPFProgram=Open->bpfprogram;
00672             Open->bpfprogram = NULL;
00673             ExFreePool(TmpBPFProgram);
00674         }
00675         
00676         if (Open->Filter!=NULL)
00677         {
00678             JIT_BPF_Filter *OldFilter=Open->Filter;
00679             Open->Filter=NULL;
00680             BPF_Destroy_JIT_Filter(OldFilter);
00681         }
00682         
00683         // Get the pointer to the new program
00684         prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
00685         
00686         if(prog==NULL)
00687         {
00688             IF_LOUD(DbgPrint("0001");)
00689             
00690             Open->SkipProcessing = 0;
00691             EXIT_FAILURE(0);
00692         }
00693         
00694         insns=(IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn);
00695         
00696         //count the number of operative instructions
00697         for (cnt=0;(cnt<insns) &&(((struct bpf_insn*)prog)[cnt].code!=BPF_SEPARATION); cnt++);
00698         
00699         IF_LOUD(DbgPrint("Operative instructions=%u\n",cnt);)
00700 
00701         if (((struct bpf_insn*)prog)[cnt].code==BPF_SEPARATION && (insns-cnt-1)!=0) 
00702         {
00703             IF_LOUD(DbgPrint("Initialization instructions=%u\n",insns-cnt-1);)
00704     
00705             IsExtendedFilter=TRUE;
00706 
00707             initprogram=&((struct bpf_insn*)prog)[cnt+1];
00708             
00709             if(bpf_filter_init(initprogram,&(Open->mem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK)
00710             {
00711             
00712                 IF_LOUD(DbgPrint("Error initializing NPF machine (bpf_filter_init)\n");)
00713                 
00714                 Open->SkipProcessing = 0;
00715                 EXIT_FAILURE(0);
00716             }
00717         }
00718 
00719         //the NPF processor has been initialized, we have to validate the operative instructions
00720         insns=cnt;
00721         
00722         if(bpf_validate((struct bpf_insn*)prog,cnt,Open->mem_ex.size)==0)
00723         {
00724             IF_LOUD(DbgPrint("Error validating program");)
00725             //FIXME: the machine has been initialized(?), but the operative code is wrong. 
00726             //we have to reset the machine!
00727             //something like: reallocate the mem_ex, and reset the tme_core
00728             Open->SkipProcessing = 0;
00729             EXIT_FAILURE(0);
00730         }
00731         
00732         // Allocate the memory to contain the new filter program
00733         // We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers()
00734         TmpBPFProgram=(PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), '4PWA');
00735         if (TmpBPFProgram==NULL)
00736         {
00737             IF_LOUD(DbgPrint("Error - No memory for filter");)
00738             // no memory
00739             Open->SkipProcessing = 0;
00740             EXIT_FAILURE(0);
00741         }
00742         
00743         //copy the program in the new buffer
00744         RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn));
00745         Open->bpfprogram=TmpBPFProgram;
00746         
00747         // Create the new JIT filter function
00748         if(!IsExtendedFilter)
00749             if((Open->Filter=BPF_jitter((struct bpf_insn*)Open->bpfprogram,cnt)) == NULL)
00750             {
00751                 IF_LOUD(DbgPrint("Error jittering filter");)
00752                 Open->SkipProcessing = 0;
00753                 EXIT_FAILURE(0);
00754             }
00755 
00756         //return
00757         for (i=0;i<NCpu;i++)
00758         {
00759             Open->CpuData[i].C=0;
00760             Open->CpuData[i].P=0;
00761             Open->CpuData[i].Free = Open->Size;
00762             Open->CpuData[i].Accepted=0;
00763             Open->CpuData[i].Dropped=0;
00764             Open->CpuData[i].Received = 0;
00765         }
00766 
00767         Open->ReaderSN=0;
00768         Open->WriterSN=0;
00769 
00770         Open->SkipProcessing = 0;
00771         EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
00772         
00773         break;      
00774         
00775     case BIOCSMODE:  //set the capture mode
00776         
00777         if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
00778         {           
00779             EXIT_FAILURE(0);
00780         }
00781 
00782         mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
00783         
00785         if (mode & MODE_DUMP)
00786         {           
00787             EXIT_FAILURE(0);
00788         }
00790 
00791         if(mode == MODE_CAPT){
00792             Open->mode=MODE_CAPT;
00793             
00794             EXIT_SUCCESS(0);
00795         }
00796         else if (mode==MODE_MON){
00797             Open->mode=MODE_MON;
00798 
00799             EXIT_SUCCESS(0);
00800         }   
00801         else{
00802             if(mode & MODE_STAT){
00803                 Open->mode = MODE_STAT;
00804                 NdisAcquireSpinLock(&Open->CountersLock);
00805                 Open->Nbytes.QuadPart=0;
00806                 Open->Npackets.QuadPart=0;
00807                 NdisReleaseSpinLock(&Open->CountersLock);
00808                 
00809                 if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart=-10000000;
00810                 
00811             }
00812             
00813             if(mode & MODE_DUMP){
00814                 
00815                 Open->mode |= MODE_DUMP;
00816 //              Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000;
00817                 
00818             }   
00819             EXIT_SUCCESS(0);
00820         }
00821         
00822         EXIT_FAILURE(0);
00823         
00824         break;
00825 
00826     case BIOCSETDUMPFILENAME:
00827 
00829         EXIT_FAILURE(0);
00831 
00832         if(Open->mode & MODE_DUMP)
00833         {
00834             
00835             // Close current dump file
00836             if(Open->DumpFileHandle != NULL)
00837             {
00838                 NPF_CloseDumpFile(Open);
00839                 Open->DumpFileHandle = NULL;
00840             }
00841             
00842             if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){
00843                 EXIT_FAILURE(0);
00844             }
00845             
00846             // Allocate the buffer that will contain the string
00847             DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, '5PWA');
00848             if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){
00849                 IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)
00850                     EXIT_FAILURE(0);
00851             }
00852             
00853             // Copy the buffer
00854             RtlCopyBytes((PVOID)DumpNameBuff, 
00855                 Irp->AssociatedIrp.SystemBuffer, 
00856                 IrpSp->Parameters.DeviceIoControl.InputBufferLength);
00857             
00858             // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system 
00859             ((PSHORT)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0;
00860             
00861             // Create the unicode string
00862             RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff);
00863             
00864             IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",
00865                 Open->DumpFileName.Buffer,
00866                 IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
00867                 
00868             // Try to create the file
00869             if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) &&
00870                 NT_SUCCESS( NPF_StartDump(Open)))
00871             {
00872                 EXIT_SUCCESS(0);
00873             }
00874         }
00875         
00876         EXIT_FAILURE(0);
00877         
00878         break;
00879                 
00880     case BIOCSETDUMPLIMITS:
00881 
00883         EXIT_FAILURE(0);
00885 
00886         if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 2*sizeof(ULONG))
00887         {
00888             EXIT_FAILURE(0);
00889         }
00890 
00891         Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
00892         Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1);
00893 
00894         IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);)
00895 
00896         EXIT_SUCCESS(0);
00897 
00898         break;
00899 
00900     case BIOCISDUMPENDED:
00901 
00903         EXIT_FAILURE(0);
00905 
00906         if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT))
00907         {           
00908             EXIT_FAILURE(0);
00909         }
00910 
00911         *((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
00912 
00913         EXIT_SUCCESS(4);
00914 
00915         break;
00916 
00917     case BIOCSETBUFFERSIZE:
00918         
00919 
00920         if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
00921         {           
00922             EXIT_FAILURE(0);
00923         }
00924 
00925         // Get the number of bytes to allocate
00926         dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
00927 
00928         Open->SkipProcessing = 1;
00929 
00930         do
00931         {
00932             Flag = FALSE;
00933             for(i=0;i<NCpu;i++)
00934                 if (Open->CpuData[i].Processing == 1)
00935                     Flag = TRUE;
00936         }
00937         while(Flag);  //BUSY FORM WAITING...
00938 
00939         if (dim / NCpu < sizeof(struct PacketHeader))
00940             dim = 0;
00941         else
00942         {
00943             tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, '6PWA');
00944             if (tpointer==NULL)
00945             {
00946                 // no memory
00947                 Open->SkipProcessing = 0;
00948                 EXIT_FAILURE(0);
00949             }
00950         }
00951 
00952         if (Open->CpuData[0].Buffer != NULL)
00953             ExFreePool(Open->CpuData[0].Buffer);
00954 
00955         for (i=0;i<NCpu;i++)
00956         {
00957             if (dim > 0) 
00958                 Open->CpuData[i].Buffer=(PUCHAR)tpointer + (dim/NCpu)*i;
00959             else
00960                 Open->CpuData[i].Buffer = NULL;
00961             IF_LOUD(DbgPrint("Loop %p\n",Open->CpuData[i].Buffer);)
00962             Open->CpuData[i].Free = dim/NCpu;
00963             Open->CpuData[i].P = 0;
00964         }
00965 
00966         Open->Size = dim/NCpu;
00967     
00968         Open->SkipProcessing = 0;
00969         EXIT_SUCCESS(dim);
00970         
00971         break;
00972         
00973     case BIOCSRTIMEOUT: //set the timeout on the read calls
00974         
00975 
00976         if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
00977         {           
00978             EXIT_FAILURE(0);
00979         }
00980 
00981         timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
00982         if((int)timeout==-1)
00983             Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;
00984         else
00985         {
00986             Open->TimeOut.QuadPart=(LONGLONG)timeout;
00987             Open->TimeOut.QuadPart*=10000;
00988             Open->TimeOut.QuadPart=-Open->TimeOut.QuadPart;
00989         }
00990 
00991         IF_LOUD(DbgPrint("NPF: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);)
00992         EXIT_SUCCESS(timeout);
00993         
00994         break;
00995         
00996     case BIOCSWRITEREP: //set the writes repetition number
00997         
00998     if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
00999     {           
01000         EXIT_FAILURE(0);
01001     }
01002 
01003         Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
01004         
01005         EXIT_SUCCESS(Open->Nwrites);
01006         
01007         break;
01008 
01009     case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
01010 
01011         if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
01012         {           
01013             EXIT_FAILURE(0);
01014         }
01015 
01016         Open->MinToCopy = (*((PULONG)Irp->AssociatedIrp.SystemBuffer))/NCpu;  //An hack to make the NCPU-buffers behave like a larger one
01017         
01018         EXIT_SUCCESS(Open->MinToCopy);
01019         
01020         break;
01021         
01022     case IOCTL_PROTOCOL_RESET:
01023         
01024         IF_LOUD(DbgPrint("NPF: IoControl - Reset request\n");)
01025 
01026         IoMarkIrpPending(Irp);
01027         Irp->IoStatus.Status = STATUS_SUCCESS;
01028 
01029         ExInterlockedInsertTailList(&Open->ResetIrpList,&Irp->Tail.Overlay.ListEntry,&Open->RequestSpinLock);
01030         NdisReset(&Status,Open->AdapterHandle);
01031         if (Status != NDIS_STATUS_PENDING)
01032         {
01033             IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)
01034                 NPF_ResetComplete(Open,Status);
01035         }
01036         
01037         break;
01038         
01039         
01040     case BIOCSETOID:
01041     case BIOCQUERYOID:
01042         
01043         // Extract a request from the list of free ones
01044         RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);
01045         if (RequestListEntry == NULL)
01046         {
01047             EXIT_FAILURE(0);
01048         }
01049 
01050         pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);
01051         pRequest->Irp = Irp;
01052         pRequest->Internal = FALSE;
01053 
01054         
01055         //
01056         //  See if it is an Ndis request
01057         //
01058         OidData=Irp->AssociatedIrp.SystemBuffer;
01059         
01060         if (((FunctionCode == BIOCSETOID) || (FunctionCode == BIOCQUERYOID))
01061             &&
01062             (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)
01063             &&
01064             (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
01065             &&
01066             (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {
01067             
01068             IF_LOUD(DbgPrint("NPF: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);)
01069                 
01070                 //
01071                 //  The buffer is valid
01072                 //
01073                 if (FunctionCode == BIOCSETOID){
01074                     
01075                     pRequest->Request.RequestType=NdisRequestSetInformation;
01076                     pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid;
01077                     
01078                     pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data;
01079                     pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length;
01080                     
01081                     
01082                 } 
01083                 else{
01084                                 
01085                     pRequest->Request.RequestType=NdisRequestQueryInformation;
01086                     pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid;
01087                     
01088                     pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data;
01089                     pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length;
01090                     
01091                 }
01092 
01093                 NdisResetEvent(&Open->IOEvent);
01094                 //
01095                 //  submit the request
01096                 //
01097                 NdisRequest(
01098                     &Status,
01099                     Open->AdapterHandle,
01100                     &pRequest->Request
01101                     );
01102                 
01103         } else {
01104             //
01105             //  buffer too small
01106             //
01107             Status=NDIS_STATUS_FAILURE;
01108             pRequest->Request.DATA.SET_INFORMATION.BytesRead=0;
01109             pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0;
01110             
01111         }
01112         
01113         if (Status != NDIS_STATUS_PENDING) {
01114             IF_LOUD(DbgPrint("NPF: Calling RequestCompleteHandler\n");)
01115                 
01116             NPF_RequestComplete(Open, &pRequest->Request, Status);
01117             return Status;
01118             
01119         }
01120 
01121         NdisWaitEvent(&Open->IOEvent, 5000);
01122 
01123         return(Open->IOStatus);
01124         
01125         break;
01126         
01127         
01128     default:
01129         
01130         EXIT_FAILURE(0);
01131     }
01132     
01133     return Status;
01134 }
01135 
01136 //-------------------------------------------------------------------
01137 
01138 VOID
01139 NPF_RequestComplete(
01140     IN NDIS_HANDLE   ProtocolBindingContext,
01141     IN PNDIS_REQUEST NdisRequest,
01142     IN NDIS_STATUS   Status
01143     )
01144 
01145 {
01146     POPEN_INSTANCE      Open;
01147     PIO_STACK_LOCATION  IrpSp;
01148     PIRP                Irp;
01149     PINTERNAL_REQUEST   pRequest;
01150     UINT                FunctionCode;
01151 //  KIRQL               OldIrq;
01152 
01153     PPACKET_OID_DATA    OidData;
01154 
01155     IF_LOUD(DbgPrint("NPF: RequestComplete\n");)
01156 
01157     Open= (POPEN_INSTANCE)ProtocolBindingContext;
01158 
01159     pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
01160     Irp=pRequest->Irp;
01161 
01162     if(pRequest->Internal == TRUE){
01163 
01164         // Put the request in the list of the free ones
01165         ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
01166 
01167         if(Status != NDIS_STATUS_SUCCESS)
01168             Open->MaxFrameSize = 1514;  // Assume Ethernet
01169 
01170         // We always return success, because the adapter has been already opened
01171         Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
01172         Irp->IoStatus.Information = 0;
01173         IoCompleteRequest(Irp, IO_NO_INCREMENT);
01174         return;
01175     }
01176 
01177     IrpSp = IoGetCurrentIrpStackLocation(Irp);
01178 
01179     FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
01180 
01181     OidData=Irp->AssociatedIrp.SystemBuffer;
01182 
01183     if (FunctionCode == BIOCSETOID) {
01184 
01185         OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead;
01186 
01187     } else {
01188 
01189         if (FunctionCode == BIOCQUERYOID) {
01190 
01191             OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
01192 
01193             IF_LOUD(DbgPrint("RequestComplete: BytesWritten=%d\n",pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten);)
01194         }
01195 
01196     }
01197 
01198     Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength;
01199 
01200     IF_LOUD(DbgPrint("RequestComplete: BytesReturned=%d\n",IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
01201 
01202     ExInterlockedInsertTailList(
01203         &Open->RequestList,
01204         &pRequest->ListElement,
01205         &Open->RequestSpinLock);
01206 
01207     Irp->IoStatus.Status = Status;
01208 
01209     Open->IOStatus = Status;
01210 
01211     IoCompleteRequest(Irp, IO_NO_INCREMENT);
01212 
01213     // Unlock the caller
01214     NdisSetEvent(&Open->IOEvent);
01215 
01216     return;
01217 
01218 
01219 }
01220 
01221 //-------------------------------------------------------------------
01222 
01223 VOID
01224 NPF_Status(
01225     IN NDIS_HANDLE   ProtocolBindingContext,
01226     IN NDIS_STATUS   Status,
01227     IN PVOID         StatusBuffer,
01228     IN UINT          StatusBufferSize
01229     )
01230 
01231 {
01232 
01233     IF_LOUD(DbgPrint("NPF: Status Indication\n");)
01234 
01235     return;
01236 
01237 }
01238 
01239 //-------------------------------------------------------------------
01240 
01241 VOID
01242 NPF_StatusComplete(
01243     IN NDIS_HANDLE  ProtocolBindingContext
01244     )
01245 
01246 {
01247 
01248     IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
01249 
01250     return;
01251 
01252 }
01253 
01254 //-------------------------------------------------------------------
01255 
01256 NTSTATUS
01257 NPF_ReadRegistry(
01258     IN  PWSTR              *MacDriverName,
01259     IN  PWSTR              *PacketDriverName,
01260     IN  PUNICODE_STRING     RegistryPath
01261     )
01262 
01263 {
01264     NTSTATUS   Status;
01265 
01266     RTL_QUERY_REGISTRY_TABLE ParamTable[4];
01267 
01268     PWSTR      Bind       = L"Bind";
01269     PWSTR      Export     = L"Export";
01270     PWSTR      Parameters = L"Parameters";
01271     PWSTR      Linkage    = L"Linkage";
01272 
01273     PWCHAR     Path;
01274 
01275 
01276 
01277     Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), '7PWA');
01278 
01279     if (Path == NULL) {
01280         return STATUS_INSUFFICIENT_RESOURCES;
01281     }
01282 
01283     RtlZeroMemory(
01284         Path,
01285         RegistryPath->Length+sizeof(WCHAR)
01286         );
01287 
01288     RtlCopyMemory(
01289         Path,
01290         RegistryPath->Buffer,
01291         RegistryPath->Length
01292         );
01293 
01294     IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath->Buffer);)
01295 
01296     RtlZeroMemory(
01297         ParamTable,
01298         sizeof(ParamTable)
01299         );
01300 
01301 
01302 
01303     //
01304     //  change to the linkage key
01305     //
01306 
01307     ParamTable[0].QueryRoutine = NULL;
01308     ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
01309     ParamTable[0].Name = Linkage;
01310 
01311 
01312     //
01313     //  Get the name of the mac driver we should bind to
01314     //
01315 
01316     ParamTable[1].QueryRoutine = NPF_QueryRegistryRoutine;
01317     ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED |
01318                           RTL_QUERY_REGISTRY_NOEXPAND;
01319 
01320     ParamTable[1].Name = Bind;
01321     ParamTable[1].EntryContext = (PVOID)MacDriverName;
01322     ParamTable[1].DefaultType = REG_MULTI_SZ;
01323 
01324     //
01325     //  Get the name that we should use for the driver object
01326     //
01327 
01328     ParamTable[2].QueryRoutine = NPF_QueryRegistryRoutine;
01329     ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED |
01330                           RTL_QUERY_REGISTRY_NOEXPAND;
01331 
01332     ParamTable[2].Name = Export;
01333     ParamTable[2].EntryContext = (PVOID)PacketDriverName;
01334     ParamTable[2].DefaultType = REG_MULTI_SZ;
01335 
01336 
01337     Status=RtlQueryRegistryValues(
01338                RTL_REGISTRY_ABSOLUTE,
01339                Path,
01340                ParamTable,
01341                NULL,
01342                NULL
01343                );
01344 
01345 
01346     ExFreePool(Path);
01347 
01348     return Status;
01349 }
01350 
01351 //-------------------------------------------------------------------
01352 
01353 NTSTATUS
01354 NPF_QueryRegistryRoutine(
01355     IN PWSTR     ValueName,
01356     IN ULONG     ValueType,
01357     IN PVOID     ValueData,
01358     IN ULONG     ValueLength,
01359     IN PVOID     Context,
01360     IN PVOID     EntryContext
01361     )
01362 
01363 {
01364 
01365     PUCHAR       Buffer;
01366 
01367     IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");)
01368 
01369     if (ValueType != REG_MULTI_SZ) {
01370 
01371         return STATUS_OBJECT_NAME_NOT_FOUND;
01372 
01373     }
01374 
01375     Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, '8PWA');
01376 
01377     if (Buffer==NULL) {
01378 
01379         return STATUS_INSUFFICIENT_RESOURCES;
01380 
01381     }
01382 
01383     RtlCopyMemory(
01384         Buffer,
01385         ValueData,
01386         ValueLength
01387         );
01388 
01389     *((PUCHAR *)EntryContext)=Buffer;
01390 
01391     return STATUS_SUCCESS;
01392 
01393 }

documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.