Main Page   Modules   Data Structures   File List   Data Fields   Globals  

Openclos.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1999, 2000
00003  *  Politecnico di Torino.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that: (1) source code distributions
00007  * retain the above copyright notice and this paragraph in its entirety, (2)
00008  * distributions including binary code include the above copyright notice and
00009  * this paragraph in its entirety in the documentation or other materials
00010  * provided with the distribution, and (3) all advertising materials mentioning
00011  * features or use of this software display the following acknowledgement:
00012  * ``This product includes software developed by the Politecnico
00013  * di Torino, and its contributors.'' Neither the name of
00014  * the University nor the names of its contributors may be used to endorse
00015  * or promote products derived from this software without specific prior
00016  * written permission.
00017  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
00018  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00020  */
00021 
00022 #include "ntddk.h"
00023 #include "ntiologc.h"
00024 #include "ndis.h"
00025 
00026 #include "debug.h"
00027 #include "packet.h"
00028 
00029 static NDIS_MEDIUM MediumArray[] = {
00030     NdisMedium802_3,
00031     NdisMediumWan,
00032     NdisMediumFddi,
00033     NdisMediumArcnet878_2,
00034     NdisMediumAtm,
00035     NdisMedium802_5
00036 };
00037 
00038 #define NUM_NDIS_MEDIA  (sizeof MediumArray / sizeof MediumArray[0])
00039 
00040 ULONG NamedEventsCounter=0;
00041 
00042 //Itoa. Replaces the buggy RtlIntegerToUnicodeString
00043 void PacketItoa(UINT n,PUCHAR buf){
00044 int i;
00045 
00046     for(i=0;i<20;i+=2){
00047         buf[18-i]=(n%10)+48;
00048         buf[19-i]=0;
00049         n/=10;
00050     }
00051 
00052 }
00053 
00055 struct time_conv G_Start_Time = {
00056     0,  
00057     {0, 0}, 
00058 };
00059 
00060 UINT n_Opened_Instances = 0;
00061 
00062 NDIS_SPIN_LOCK Opened_Instances_Lock;
00063 
00064 //-------------------------------------------------------------------
00065 
00066 NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00067 {
00068 
00069     PDEVICE_EXTENSION DeviceExtension;
00070 
00071     POPEN_INSTANCE    Open;
00072 
00073     PIO_STACK_LOCATION  IrpSp;
00074 
00075     NDIS_STATUS     Status;
00076     NDIS_STATUS     ErrorStatus;
00077     UINT            i;
00078     PUCHAR          tpointer;
00079     PLIST_ENTRY     PacketListEntry;
00080     PCHAR           EvName;
00081 
00082 
00083     IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
00084 
00085     DeviceExtension = DeviceObject->DeviceExtension;
00086 
00087 
00088     IrpSp = IoGetCurrentIrpStackLocation(Irp);
00089 
00090     //  allocate some memory for the open structure
00091     Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), '0OWA');
00092 
00093 
00094     if (Open==NULL) {
00095         // no memory
00096         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
00097         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00098         return STATUS_INSUFFICIENT_RESOURCES;
00099     }
00100 
00101     RtlZeroMemory(
00102         Open,
00103         sizeof(OPEN_INSTANCE)
00104         );
00105 
00106 
00107     EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000"), '1OWA');
00108 
00109     if (EvName==NULL) {
00110         // no memory
00111         ExFreePool(Open);
00112         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
00113         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00114         return STATUS_INSUFFICIENT_RESOURCES;
00115     }
00116 
00117     //  Save or open here
00118     IrpSp->FileObject->FsContext=Open;
00119     
00120     Open->DeviceExtension=DeviceExtension;
00121     
00122     
00123     //  Save the Irp here for the completeion routine to retrieve
00124     Open->OpenCloseIrp=Irp;
00125     
00126     //  Allocate a packet pool for our xmit and receive packets
00127     NdisAllocatePacketPool(
00128         &Status,
00129         &Open->PacketPool,
00130         TRANSMIT_PACKETS,
00131         sizeof(PACKET_RESERVED));
00132     
00133     
00134     if (Status != NDIS_STATUS_SUCCESS) {
00135         
00136         IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");)
00137             
00138         ExFreePool(Open);
00139         ExFreePool(EvName);
00140         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
00141         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00142         return STATUS_INSUFFICIENT_RESOURCES;
00143     }
00144 
00145 
00146     RtlCopyBytes(EvName,L"\\BaseNamedObjects\\NPF0000000000",sizeof(L"\\BaseNamedObjects\\NPF0000000000"));
00147 
00148     //Create the string containing the name of the read event
00149     RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName);
00150 
00151     PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21));
00152 
00153     InterlockedIncrement(&NamedEventsCounter);
00154     
00155     IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open->ReadEventName.Buffer,NamedEventsCounter-1);)
00156 
00157     //allocate the event objects
00158     Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle);
00159     if(Open->ReadEvent==NULL){
00160         ExFreePool(Open);
00161         ExFreePool(EvName);
00162         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
00163         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00164         return STATUS_INSUFFICIENT_RESOURCES;
00165     }
00166     
00167     KeInitializeEvent(Open->ReadEvent, NotificationEvent, FALSE);
00168     KeClearEvent(Open->ReadEvent);
00169     NdisInitializeEvent(&Open->WriteEvent);
00170     NdisInitializeEvent(&Open->IOEvent);
00171     NdisInitializeEvent(&Open->DumpEvent);
00172     NdisInitializeEvent(&Open->IOEvent);
00173     NdisAllocateSpinLock(&Open->machine_lock);
00174 
00175 
00176     //  list to hold irp's want to reset the adapter
00177     InitializeListHead(&Open->ResetIrpList);
00178     
00179     
00180     //  Initialize the request list
00181     KeInitializeSpinLock(&Open->RequestSpinLock);
00182     InitializeListHead(&Open->RequestList);
00183 
00184     // Initializes the extended memory of the NPF machine
00185     Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA');
00186     if((Open->mem_ex.buffer) == NULL)
00187     {
00188         // no memory
00189         ExFreePool(Open);
00190         ExFreePool(EvName);
00191         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
00192         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00193         return STATUS_INSUFFICIENT_RESOURCES;
00194     }
00195     
00196     Open->mem_ex.size = DEFAULT_MEM_EX_SIZE;
00197     RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE);
00198     
00199     //
00200     // Initialize the open instance
00201     //
00202     Open->BufSize = 0;
00203     Open->Buffer = NULL;
00204     Open->Bhead = 0;
00205     Open->Btail = 0;
00206     Open->BLastByte = 0;
00207     Open->Dropped = 0;      //reset the dropped packets counter
00208     Open->Received = 0;     //reset the received packets counter
00209     Open->Accepted = 0;     //reset the accepted packets counter
00210     Open->bpfprogram = NULL;    //reset the filter
00211     Open->mode = MODE_CAPT;
00212     Open->Nbytes.QuadPart = 0;
00213     Open->Npackets.QuadPart = 0;
00214     Open->Nwrites = 1;
00215     Open->Multiple_Write_Counter = 0;
00216     Open->MinToCopy = 0;
00217     Open->TimeOut.QuadPart = (LONGLONG)1;
00218     Open->Bound = TRUE;
00219     Open->DumpFileName.Buffer = NULL;
00220     Open->DumpFileHandle = NULL;
00221     Open->tme.active = TME_NONE_ACTIVE;
00222     Open->DumpLimitReached = FALSE;
00223 
00224     //allocate the spinlock for the statistic counters
00225     NdisAllocateSpinLock(&Open->CountersLock);
00226 
00227     //allocate the spinlock for the buffer pointers
00228     NdisAllocateSpinLock(&Open->BufLock);
00229     
00230     //
00231     //  link up the request stored in our open block
00232     //
00233     for (i=0;i<MAX_REQUESTS;i++) {
00234         ExInterlockedInsertTailList(
00235             &Open->RequestList,
00236             &Open->Requests[i].ListElement,
00237             &Open->RequestSpinLock);
00238         
00239     }
00240     
00241 
00242     IoMarkIrpPending(Irp);
00243     
00244     //
00245     //  Try to open the MAC
00246     //
00247     IF_LOUD(DbgPrint("NPF: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
00248 
00249     NdisOpenAdapter(
00250         &Status,
00251         &ErrorStatus,
00252         &Open->AdapterHandle,
00253         &Open->Medium,
00254         MediumArray,
00255         NUM_NDIS_MEDIA,
00256         DeviceExtension->NdisProtocolHandle,
00257         Open,
00258         &DeviceExtension->AdapterName,
00259         0,
00260         NULL);
00261 
00262     IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);)
00263 
00264     if (Status != NDIS_STATUS_PENDING)
00265     {
00266         NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
00267     }
00268     
00269     return(STATUS_PENDING);
00270 }
00271 
00272 //-------------------------------------------------------------------
00273 
00274 VOID NPF_OpenAdapterComplete(
00275     IN NDIS_HANDLE  ProtocolBindingContext,
00276     IN NDIS_STATUS  Status,
00277     IN NDIS_STATUS  OpenErrorStatus)
00278 {
00279 
00280     PIRP              Irp;
00281     POPEN_INSTANCE    Open;
00282 
00283     IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");)
00284 
00285     Open= (POPEN_INSTANCE)ProtocolBindingContext;
00286 
00287     //
00288     //  get the open irp
00289     //
00290     Irp=Open->OpenCloseIrp;
00291 
00292     if (Status != NDIS_STATUS_SUCCESS) {
00293 
00294         IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");)
00295 
00296         NdisFreePacketPool(Open->PacketPool);
00297 
00298         //free mem_ex
00299         Open->mem_ex.size = 0;
00300         if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
00301 
00302         ExFreePool(Open->ReadEventName.Buffer);
00303 
00304         ExFreePool(Open);
00305     }
00306     else {
00307         NdisAcquireSpinLock(&Opened_Instances_Lock);
00308         n_Opened_Instances++;
00309         NdisReleaseSpinLock(&Opened_Instances_Lock);
00310         
00311         IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
00312 
00313         // Get the absolute value of the system boot time.
00314         // This is used for timestamp conversion.
00315         TIME_SYNCHRONIZE(&G_Start_Time);
00316     }
00317 
00318     Irp->IoStatus.Status = Status;
00319     Irp->IoStatus.Information = 0;
00320     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00321 
00322     return;
00323 
00324 }
00325 
00326 //-------------------------------------------------------------------
00327 
00328 NTSTATUS
00329 NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
00330 {
00331 
00332     POPEN_INSTANCE    Open;
00333     NDIS_STATUS     Status;
00334     PIO_STACK_LOCATION  IrpSp;
00335     LARGE_INTEGER ThreadDelay;
00336 
00337     IF_LOUD(DbgPrint("NPF: CloseAdapter\n");)
00338 
00339     IrpSp = IoGetCurrentIrpStackLocation(Irp);
00340 
00341     Open=IrpSp->FileObject->FsContext;
00342 
00343     // Reset the buffer size. This tells the dump thread to stop.
00344     Open->BufSize = 0;
00345 
00346     if( Open->Bound == FALSE){
00347 
00348         NdisWaitEvent(&Open->IOEvent,10000);
00349 
00350         // Free the filter if it's present
00351         if(Open->bpfprogram != NULL)
00352             ExFreePool(Open->bpfprogram);
00353 
00354         // Free the jitted filter if it's present
00355         if(Open->Filter != NULL)
00356             BPF_Destroy_JIT_Filter(Open->Filter);
00357 
00358         //free the buffer
00359         Open->BufSize=0;
00360         if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
00361         
00362         //free mem_ex
00363         Open->mem_ex.size = 0;
00364         if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
00365                 
00366         NdisFreePacketPool(Open->PacketPool);
00367 
00368         // Free the string with the name of the dump file
00369         if(Open->DumpFileName.Buffer!=NULL)
00370             ExFreePool(Open->DumpFileName.Buffer);
00371             
00372         ExFreePool(Open->ReadEventName.Buffer);
00373         ExFreePool(Open);
00374 
00375         Irp->IoStatus.Information = 0;
00376         Irp->IoStatus.Status = STATUS_SUCCESS;
00377         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00378         
00379         return(STATUS_SUCCESS);
00380     }
00381 
00382     // Unfreeze the consumer
00383     if(Open->mode & MODE_DUMP)
00384         NdisSetEvent(&Open->DumpEvent);
00385     else
00386         KeSetEvent(Open->ReadEvent,0,FALSE);
00387 
00388     // Save the IRP
00389     Open->OpenCloseIrp = Irp;
00390 
00391     IoMarkIrpPending(Irp);
00392  
00393     // If this instance is in dump mode, complete the dump and close the file
00394     if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){
00395 
00396         NTSTATUS wres;
00397 
00398         ThreadDelay.QuadPart = -50000000;
00399         // Wait the completion of the thread
00400         wres = KeWaitForSingleObject(Open->DumpThreadObject,
00401                 UserRequest,
00402                 KernelMode,
00403                 TRUE,
00404                 &ThreadDelay);
00405 
00406         ObDereferenceObject(Open->DumpThreadObject);
00407 
00408 
00409         // Flush and close the dump file
00410         NPF_CloseDumpFile(Open);
00411     }
00412 
00413     // Destroy the read Event
00414     ZwClose(Open->ReadEventHandle);
00415 
00416     // Close the adapter
00417     NdisCloseAdapter(
00418         &Status,
00419         Open->AdapterHandle
00420         );
00421 
00422     if (Status != NDIS_STATUS_PENDING) {
00423         
00424         NPF_CloseAdapterComplete(
00425             Open,
00426             Status
00427             );
00428         return STATUS_SUCCESS;
00429         
00430     }
00431     
00432     return(STATUS_PENDING);
00433 }
00434 
00435 //-------------------------------------------------------------------
00436 
00437 VOID
00438 NPF_CloseAdapterComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Status)
00439 {
00440     POPEN_INSTANCE    Open;
00441     PIRP              Irp;
00442 
00443     IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");)
00444 
00445     Open= (POPEN_INSTANCE)ProtocolBindingContext;
00446 
00447     // free the allocated structures only if the instance is still bound to the adapter
00448     if(Open->Bound == TRUE){
00449         
00450         // Free the filter if it's present
00451         if(Open->bpfprogram != NULL)
00452             ExFreePool(Open->bpfprogram);
00453 
00454         // Free the jitted filter if it's present
00455         if(Open->Filter != NULL)
00456             BPF_Destroy_JIT_Filter(Open->Filter);
00457         
00458         //free the buffer
00459         Open->BufSize = 0;
00460         if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
00461         
00462         //free mem_ex
00463         Open->mem_ex.size = 0;
00464         if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
00465         
00466         NdisFreePacketPool(Open->PacketPool);
00467         
00468         Irp=Open->OpenCloseIrp;
00469         
00470         // Free the string with the name of the dump file
00471         if(Open->DumpFileName.Buffer!=NULL)
00472             ExFreePool(Open->DumpFileName.Buffer);
00473 
00474         ExFreePool(Open->ReadEventName.Buffer);
00475         ExFreePool(Open);
00476         
00477         // Complete the request only if the instance is still bound to the adapter
00478         Irp->IoStatus.Status = STATUS_SUCCESS;
00479         Irp->IoStatus.Information = 0;
00480         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00481     }
00482     else
00483         NdisSetEvent(&Open->IOEvent);
00484 
00485     // Decrease the counter of open instances
00486     NdisAcquireSpinLock(&Opened_Instances_Lock);
00487     n_Opened_Instances--;
00488     NdisReleaseSpinLock(&Opened_Instances_Lock);
00489 
00490     IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
00491 
00492     if(n_Opened_Instances == 0){
00493         // Force a synchronization at the next NPF_Open().
00494         // This hopefully avoids the synchronization issues caused by hibernation or standby.
00495         TIME_DESYNCHRONIZE(&G_Start_Time);
00496     }
00497 
00498     return;
00499 
00500 }
00501 //-------------------------------------------------------------------
00502 
00503 #ifdef NDIS50
00504 NDIS_STATUS
00505 NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
00506 {
00507     IF_LOUD(DbgPrint("NPF: PowerChange\n");)
00508 
00509     TIME_DESYNCHRONIZE(&G_Start_Time);
00510 
00511     TIME_SYNCHRONIZE(&G_Start_Time);
00512 
00513     return STATUS_SUCCESS;
00514 }
00515 #endif
00516 
00517 //-------------------------------------------------------------------
00518 
00519 VOID
00520 NPF_BindAdapter(
00521     OUT PNDIS_STATUS            Status,
00522     IN  NDIS_HANDLE             BindContext,
00523     IN  PNDIS_STRING            DeviceName,
00524     IN  PVOID                   SystemSpecific1,
00525     IN  PVOID                   SystemSpecific2
00526     )
00527 {
00528     IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");)
00529 }
00530 
00531 //-------------------------------------------------------------------
00532 
00533 VOID
00534 NPF_UnbindAdapter(
00535     OUT PNDIS_STATUS        Status,
00536     IN  NDIS_HANDLE         ProtocolBindingContext,
00537     IN  NDIS_HANDLE         UnbindContext
00538     )
00539 {
00540     POPEN_INSTANCE   Open =(POPEN_INSTANCE)ProtocolBindingContext;
00541     NDIS_STATUS      lStatus;
00542 
00543     IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");)
00544 
00545     // Reset the buffer size. This tells the dump thread to stop.
00546     Open->BufSize=0;
00547 
00548     NdisResetEvent(&Open->IOEvent);
00549 
00550     // This open instance is no more bound to the adapter, set Bound to False
00551     InterlockedExchange( (PLONG) &Open->Bound, FALSE );
00552 
00553     // Awake a possible pending read on this instance
00554     if(Open->mode & MODE_DUMP)
00555         NdisSetEvent(&Open->DumpEvent);
00556     else
00557         KeSetEvent(Open->ReadEvent,0,FALSE);
00558 
00559     // If this instance is in dump mode, complete the dump and close the file
00560     if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL)
00561         NPF_CloseDumpFile(Open);
00562 
00563     // Destroy the read Event
00564     ZwClose(Open->ReadEventHandle);
00565 
00566     //  close the adapter
00567     NdisCloseAdapter(
00568         &lStatus,
00569         Open->AdapterHandle
00570         );
00571 
00572     if (lStatus != NDIS_STATUS_PENDING) {
00573 
00574         NPF_CloseAdapterComplete(
00575             Open,
00576             lStatus
00577             );
00578 
00579         *Status = NDIS_STATUS_SUCCESS;
00580         return;
00581 
00582     }
00583 
00584     *Status = NDIS_STATUS_SUCCESS;
00585     return;
00586 }
00587 
00588 //-------------------------------------------------------------------
00589 
00590 VOID
00591 NPF_ResetComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Status)
00592 
00593 {
00594     POPEN_INSTANCE      Open;
00595     PIRP                Irp;
00596 
00597     PLIST_ENTRY         ResetListEntry;
00598 
00599     IF_LOUD(DbgPrint("NPF: PacketResetComplte\n");)
00600 
00601     Open= (POPEN_INSTANCE)ProtocolBindingContext;
00602 
00603 
00604     //
00605     //  remove the reset IRP from the list
00606     //
00607     ResetListEntry=ExInterlockedRemoveHeadList(
00608                        &Open->ResetIrpList,
00609                        &Open->RequestSpinLock
00610                        );
00611 
00612 #if DBG
00613     if (ResetListEntry == NULL) {
00614         DbgBreakPoint();
00615         return;
00616     }
00617 #endif
00618 
00619     Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry);
00620 
00621     Irp->IoStatus.Status = STATUS_SUCCESS;
00622     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00623 
00624     IF_LOUD(DbgPrint("NPF: PacketResetComplte exit\n");)
00625 
00626     return;
00627 
00628 }

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