www.pudn.com > ntsniff.zip > OPENCLOS.C


/* 
 *  NtSniff by Davide Libenzi ( To rebuild NtSniff You need Microsoft SDK & DDK ) 
 *  Copyright (C) 1999  Davide Libenzi 
 * 
 *  This program is free software; you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation; either version 2 of the License, or 
 *  (at your option) any later version. 
 * 
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details. 
 * 
 *  You should have received a copy of the GNU General Public License 
 *  along with this program; if not, write to the Free Software 
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 * 
 *  Davide Libenzi  
 * 
 */ 
 
 
#include "ntddk.h" 
#include "ntiologc.h" 
#include "ndis.h" 
 
#include "debug.h" 
#include "packet.h" 
 
 
NTSTATUS 
PacketOpen( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
 
/*++ 
 
Routine Description: 
 
    This is the dispatch routine for create/open and close requests. 
    These requests complete successfully. 
 
Arguments: 
 
    DeviceObject - Pointer to the device object. 
 
    Irp - Pointer to the request packet. 
 
Return Value: 
 
    Status is returned. 
 
--*/ 
 
{ 
 
    PDEVICE_EXTENSION DeviceExtension; 
 
    POPEN_INSTANCE    Open; 
 
    PIO_STACK_LOCATION  IrpSp; 
 
    NDIS_STATUS     Status; 
    NDIS_STATUS     ErrorStatus; 
    UINT            Medium; 
    NDIS_MEDIUM     MediumArray=NdisMedium802_3; 
 
    UINT            i; 
 
    IF_LOUD(DbgPrint("Packet: OpenAdapter\n");) 
 
    DeviceExtension = DeviceObject->DeviceExtension; 
 
    IrpSp = IoGetCurrentIrpStackLocation(Irp); 
 
    // 
    //  allocate some memory for the open structure 
    // 
    Open=ExAllocatePool(NonPagedPool,sizeof(OPEN_INSTANCE)); 
 
    if (Open==NULL) { 
        // 
        // no memory 
        // 
        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 
        IoCompleteRequest(Irp, IO_NO_INCREMENT); 
        return STATUS_INSUFFICIENT_RESOURCES; 
    } 
 
    RtlZeroMemory( 
        Open, 
        sizeof(OPEN_INSTANCE) 
        ); 
 
    // 
    //  Save or open here 
    // 
    IrpSp->FileObject->FsContext=Open; 
 
    Open->DeviceExtension=DeviceExtension; 
 
    // 
    //  Save the Irp here for the completion routine to retrieve 
    // 
    Open->OpenCloseIrp=Irp; 
 
    Open->IrpCount = 0; 
    NdisInitializeEvent(&Open->CleanupEvent); 
 
    // 
    //  Allocate a packet pool for our xmit and receive packets 
    // 
    NdisAllocatePacketPool( 
        &Status, 
        &Open->PacketPool, 
        TRANSMIT_PACKETS, 
        sizeof(PACKET_RESERVED)); 
 
    if (Status != NDIS_STATUS_SUCCESS) { 
        IF_LOUD(DbgPrint("Packet: Failed to allocate packet pool\n");) 
 
        ExFreePool(Open); 
        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 
        IoCompleteRequest(Irp, IO_NO_INCREMENT); 
        return STATUS_INSUFFICIENT_RESOURCES; 
    } 
 
    // 
    //  list to hold irp's want to reset the adapter 
    // 
    InitializeListHead(&Open->ResetIrpList); 
 
 
    // 
    //  Initialize list for holding pending read requests 
    // 
    KeInitializeSpinLock(&Open->RcvQSpinLock); 
    InitializeListHead(&Open->RcvList); 
 
    // 
    //  Initialize the request list 
    // 
    KeInitializeSpinLock(&Open->RequestSpinLock); 
    InitializeListHead(&Open->RequestList); 
 
 
    // 
    //  link up the request stored in our open block 
    // 
    for (i=0;iRequestList, 
            &Open->Requests[i].ListElement, 
            &Open->RequestSpinLock); 
 
    } 
 
    // 
    // Important: Since we have marked the IRP pending, we must return  
    // STATUS_PENDING even we happen to complete the IRP synchronously. 
    //  
     
    IoMarkIrpPending(Irp); 
 
    // 
    //  Try to open the MAC 
    // 
    NdisOpenAdapter( 
        &Status, 
        &ErrorStatus, 
        &Open->AdapterHandle, 
        &Medium, 
        &MediumArray, 
        1, 
        DeviceExtension->NdisProtocolHandle, 
        Open, 
        &DeviceExtension->AdapterName, 
        0, 
        NULL); 
 
 
    if (Status != NDIS_STATUS_PENDING) { 
 
        PacketOpenAdapterComplete( 
            Open, 
            Status, 
            NDIS_STATUS_SUCCESS 
            ); 
 
    } 
 
    return(STATUS_PENDING); 
 
} 
 
 
VOID 
PacketOpenAdapterComplete( 
    IN NDIS_HANDLE  ProtocolBindingContext, 
    IN NDIS_STATUS  Status, 
    IN NDIS_STATUS  OpenErrorStatus 
    ) 
 
{ 
 
    PIRP              Irp; 
    POPEN_INSTANCE    Open; 
 
    IF_LOUD(DbgPrint("Packet: OpenAdapterComplete\n");) 
 
    Open= (POPEN_INSTANCE)ProtocolBindingContext; 
 
    // 
    //  get the open irp 
    // 
    Irp=Open->OpenCloseIrp; 
 
    if (Status != NDIS_STATUS_SUCCESS) { 
 
        IF_LOUD(DbgPrint("Packet: OpenAdapterComplete-FAILURE\n");) 
 
        NdisFreePacketPool(Open->PacketPool); 
 
        ExFreePool(Open); 
 
    } 
 
    Irp->IoStatus.Status = Status; 
    Irp->IoStatus.Information = 0; 
    IoCompleteRequest(Irp, IO_NO_INCREMENT); 
 
    return; 
 
} 
 
NTSTATUS 
PacketClose( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
 
/*++ 
 
Routine Description: 
 
    This is the dispatch routine for create/open and close requests. 
    These requests complete successfully. 
 
Arguments: 
 
    DeviceObject - Pointer to the device object. 
 
    Irp - Pointer to the request packet. 
 
Return Value: 
 
    Status is returned. 
 
--*/ 
 
{ 
 
    POPEN_INSTANCE    Open; 
    NDIS_STATUS     Status; 
    PIO_STACK_LOCATION  IrpSp; 
 
    IF_LOUD(DbgPrint("Packet: CloseAdapter\n");) 
 
    IrpSp = IoGetCurrentIrpStackLocation(Irp); 
 
    Open=IrpSp->FileObject->FsContext; 
 
    // 
    //  Save the IRP 
    // 
    Open->OpenCloseIrp=Irp; 
 
    // 
    // Important: Since we have marked the IRP pending, we must return  
    // STATUS_PENDING even we happen to complete the IRP synchronously. 
    //  
 
    IoMarkIrpPending(Irp); 
 
    // 
    //  close the adapter 
    // 
    NdisCloseAdapter( 
        &Status, 
        Open->AdapterHandle 
        ); 
 
 
    if (Status != NDIS_STATUS_PENDING) { 
 
        PacketCloseAdapterComplete( 
            Open, 
            Status 
            ); 
    } 
 
    return(STATUS_PENDING); 
 
} 
 
 
VOID 
PacketCloseAdapterComplete( 
    IN NDIS_HANDLE  ProtocolBindingContext, 
    IN NDIS_STATUS  Status 
    ) 
 
{ 
    POPEN_INSTANCE    Open; 
    PIRP              Irp; 
 
    IF_LOUD(DbgPrint("Packet: CloseAdapterComplete\n");) 
 
    Open= (POPEN_INSTANCE)ProtocolBindingContext; 
 
    Irp=Open->OpenCloseIrp; 
 
    NdisFreePacketPool(Open->PacketPool); 
 
    ExFreePool(Open); 
 
    Irp->IoStatus.Status = STATUS_SUCCESS; 
    Irp->IoStatus.Information = 0; 
    IoCompleteRequest(Irp, IO_NO_INCREMENT); 
 
    return; 
 
} 
 
 
NTSTATUS 
PacketCleanup( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
 
/*++ 
 
Routine Description: 
 
    This is the dispatch routine for cleanup requests. 
    This routine is called whenever a handle to the device 
    is closed. 
     
Arguments: 
 
    DeviceObject - Pointer to the device object. 
 
    Irp - Pointer to the request packet. 
 
Return Value: 
 
    Status is returned. 
 
--*/ 
 
{ 
 
    POPEN_INSTANCE      open; 
    NTSTATUS            status = STATUS_SUCCESS; 
    PIO_STACK_LOCATION  irpSp; 
 
    IF_LOUD(DbgPrint("Packet: Cleanup\n");) 
 
    irpSp = IoGetCurrentIrpStackLocation(Irp); 
 
    open=irpSp->FileObject->FsContext; 
 
    // 
    // Cancel all the pending reads. 
    //  
     
    PacketCancelReadIrps(open); 
 
    if(open->IrpCount) { 
        // 
        // We might have pending Reset, Oid or Send requests. Since 
        // we cannot cancel them we must here until they  
        // complete. 
        // 
        NdisWaitEvent(&open->CleanupEvent, 0); 
    } 
     
    Irp->IoStatus.Information = 0;     
    Irp->IoStatus.Status = status; 
    IoCompleteRequest (Irp, IO_NO_INCREMENT); 
    return status; 
 
}