⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ioctl.c

📁 驱动开发,经过测试可以直接编译后使用,编译使用DDK中的build工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1990-1998  Microsoft Corporation, All Rights Reserved.

Module Name:

    ioctl.c

Abstract:

    This module contains the ioctl interface to this driver

Author:

    Anil Francis Thomas (10/98)

Environment:

    Kernel

Revision History:
   DChen    092499   Bug fixes

--*/
#include "precomp.h"
#pragma hdrstop


#define MODULE_ID    MODULE_IOCTL


NTSTATUS AtmSmDispatch(
   IN  PDEVICE_OBJECT  pDeviceObject,
   IN  PIRP            pIrp
   )
/*++

Routine Description:

    This is the common dispath routine for user Ioctls

Arguments:

Return Value:

    None

--*/
{
   NTSTATUS            Status;
   ULONG               ulBytesWritten = 0;
   PIO_STACK_LOCATION  pIrpSp;


   TraceIn(AtmSmDispatch);

   //
   // Get current Irp stack location
   //
   pIrpSp = IoGetCurrentIrpStackLocation(pIrp);

   pIrp->IoStatus.Information = 0;

   switch(pIrpSp->MajorFunction)
   {

      case IRP_MJ_CREATE: {

            DbgLoud(("IRP_MJ_CREATE\n"));

            InterlockedIncrement(&AtmSmGlobal.ulNumCreates);
            Status = STATUS_SUCCESS;

            break;
         }

      case IRP_MJ_CLOSE: {

            DbgLoud(("IRP_MJ_CLOSE\n"));

            Status = STATUS_SUCCESS;

            break;
         }

      case IRP_MJ_CLEANUP: {

            DbgLoud(("IRP_MJ_CLEANUP\n"));

            Status = STATUS_SUCCESS;

            InterlockedDecrement(&AtmSmGlobal.ulNumCreates);

            break;
         }

      case IRP_MJ_DEVICE_CONTROL: {

            ULONG   ulControlCode;
            ULONG   ulControlFunc;

            ulControlCode   = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
            ulControlFunc   = IoGetFunctionCodeFromCtlCode(ulControlCode);

            // verify the IOCTL codes
            if(DEVICE_TYPE_FROM_CTL_CODE(ulControlCode) == FILE_DEVICE_ATMSM &&
               ulControlFunc < ATMSM_NUM_IOCTLS &&
               AtmSmIoctlTable[ulControlFunc] == ulControlCode)
            {
               // set the status to PENDING by default
               pIrp->IoStatus.Status = STATUS_PENDING;
               
               Status = (*AtmSmFuncProcessIoctl[ulControlFunc])(pIrp, pIrpSp);
            }
            else
            {
               DbgErr(("Unknown IRP_MJ_DEVICE_CONTROL code - %x\n",
                  ulControlCode));
               Status = STATUS_INVALID_PARAMETER;
            }

            break;
         }

      default: {

            DbgErr(("Unknown IRP_MJ_XX - %x\n",pIrpSp->MajorFunction));

            Status = STATUS_INVALID_PARAMETER;

            break;
         }
   }


   if(STATUS_PENDING != Status)
   {
      pIrp->IoStatus.Status = Status;

      IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
   }

   TraceOut(AtmSmDispatch);

   return Status;
}


NTSTATUS AtmSmIoctlEnumerateAdapters(
   PIRP                pIrp,
   PIO_STACK_LOCATION  pIrpSp
   )
/*++

Routine Description:

    This routine is called to enumerate the adapters that we are bound to.
    
    NOTE!  This uses buffered I/O

Arguments:

Return Value:

    Status - doesn't pend

--*/
{
   NTSTATUS            Status = STATUS_SUCCESS;
   ULONG               ulNum, ulOutputBufLen, ulNeededSize;
   PADAPTER_INFO       pAdaptInfo = (PADAPTER_INFO)
                                    pIrp->AssociatedIrp.SystemBuffer;
   PATMSM_ADAPTER      pAdapt;


   TraceIn(AtmSmIoctlEnumerateAdapters);

   ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;


   ACQUIRE_GLOBAL_LOCK();

   ulNeededSize = sizeof(ADAPTER_INFO) + 
                  (sizeof(UCHAR) * NSAP_ADDRESS_LEN * 
                     (AtmSmGlobal.ulAdapterCount - 1));


   if(ulOutputBufLen < ulNeededSize)
   {

      DbgErr(("Output length is not sufficient\n"));

      RELEASE_GLOBAL_LOCK();

      TraceOut(AtmSmIoctlEnumerateAdapters);
      return STATUS_BUFFER_TOO_SMALL;
   }

   pAdaptInfo->ulNumAdapters = 0;

   ulNum = 0;
   for(pAdapt = AtmSmGlobal.pAdapterList; pAdapt &&
      ulNum < AtmSmGlobal.ulAdapterCount; 
      pAdapt = pAdapt->pAdapterNext)
   {

      if(AtmSmReferenceAdapter(pAdapt))
      {

         ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);

         if(0 == (pAdapt->ulFlags & ADAPT_ADDRESS_INVALID))
         {
            // this is a good adapter

            RtlCopyMemory(pAdaptInfo->ucLocalATMAddr[ulNum], 
               pAdapt->ConfiguredAddress.Address,
               (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));

            pAdaptInfo->ulNumAdapters++;
            ulNum++;
         }

         RELEASE_ADAPTER_GEN_LOCK(pAdapt);

         AtmSmDereferenceAdapter(pAdapt);
      }

   }

   RELEASE_GLOBAL_LOCK();

   pIrp->IoStatus.Information = ulOutputBufLen;

   TraceOut(AtmSmIoctlEnumerateAdapters);

   return Status;
}

NTSTATUS AtmSmIoctlOpenForRecv(
   PIRP                pIrp,
   PIO_STACK_LOCATION  pIrpSp
   )
/*++

Routine Description:

    This routine is used to open an adapter for receiving all the packets that
    come to our SAP.  We allow only 1 user to open the adapter for recvs.
    
    NOTE!  This uses buffered I/O

Arguments:

Return Value:

    Status - doesn't Pend

--*/
{
   NTSTATUS            Status = STATUS_SUCCESS;
   ULONG               ulInputBufLen, ulOutputBufLen, ulCompareLength;
   POPEN_FOR_RECV_INFO pOpenInfo = (POPEN_FOR_RECV_INFO)
                                   pIrp->AssociatedIrp.SystemBuffer;
   PATMSM_ADAPTER      pAdapt;

#if DBG
   ATM_ADDRESS         AtmAddr;
#endif

   TraceIn(AtmSmIoctlOpenForRecv);

   ulInputBufLen  = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
   ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;


   if(ulInputBufLen < sizeof(OPEN_FOR_RECV_INFO))
   {

      DbgErr(("Input length is invalid\n"));
      TraceOut(AtmSmIoctlOpenForRecv);
      return STATUS_INVALID_PARAMETER;
   }

   if(ulOutputBufLen < sizeof(HANDLE))
   {

      DbgErr(("Output length is not sufficient\n"));
      TraceOut(AtmSmIoctlOpenForRecv);
      return STATUS_BUFFER_TOO_SMALL;
   }


#if DBG
   AtmAddr.AddressType     = ATM_NSAP;
   AtmAddr.NumberOfDigits  = ATM_ADDRESS_LENGTH;
   RtlCopyMemory(AtmAddr.Address, pOpenInfo->ucLocalATMAddr, 
      (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));

   DumpATMAddress(ATMSMD_INFO, "Recv Open - Local AtmAddress - ", &AtmAddr);
#endif

   do
   {    // break off loop

      //
      // grab the global lock and find out which adapter is being refered to.
      //
      ACQUIRE_GLOBAL_LOCK();

      // we don't compare the selector byte
      ulCompareLength = sizeof(UCHAR) * (ATM_ADDRESS_LENGTH - 1);

      for(pAdapt = AtmSmGlobal.pAdapterList; pAdapt; 
         pAdapt = pAdapt->pAdapterNext)
      {

         if(ulCompareLength == RtlCompareMemory(
            pOpenInfo->ucLocalATMAddr, 
            pAdapt->ConfiguredAddress.Address, 
            ulCompareLength))
            break;
      }

      if(NULL == pAdapt)
      {
         RELEASE_GLOBAL_LOCK();

         DbgErr(("Specified adapter address not found.\n"));
         Status = STATUS_OBJECT_NAME_INVALID;
         break;
      }

      // we have found the adapter put a reference on it
      if(!AtmSmReferenceAdapter(pAdapt))
      {
         RELEASE_GLOBAL_LOCK();

         DbgErr(("Couldn't put a reference on the adapter.\n"));
         Status = STATUS_UNSUCCESSFUL;
         break;
      }

      RELEASE_GLOBAL_LOCK();

      // we have a reference on the adapter now
      // check if it is already opened for recv's .  We allow only
      // one receiver.
      ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);

      if(pAdapt->fAdapterOpenedForRecv)
      {
         // we already have an open for recv
         RELEASE_ADAPTER_GEN_LOCK(pAdapt);

         AtmSmDereferenceAdapter(pAdapt);
      
         DbgErr(("Already opened for recvs.\n"));
         Status = STATUS_UNSUCCESSFUL;
         break;
      }

      pAdapt->fAdapterOpenedForRecv = TRUE;

      RELEASE_ADAPTER_GEN_LOCK(pAdapt);
         
      // now set the opencontext
      *(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer) = (HANDLE)pAdapt;
      pIrp->IoStatus.Information = sizeof(HANDLE);

      DbgInfo(("Success! Recv Open Context - 0x%x\n", pAdapt));

      // remove the reference added when opening for recvs
      AtmSmDereferenceAdapter(pAdapt);

   } while(FALSE);

   TraceOut(AtmSmIoctlOpenForRecv);

   return Status;
}

NTSTATUS AtmSmIoctlRecvData(
   PIRP                pIrp,
   PIO_STACK_LOCATION  pIrpSp
   )
/*++

Routine Description:
    
    This routine is used to transfer data from network packets into the user
    buffers.  If a packet is queued up, then we will immediately complete 
    this reuqest.

    NOTE!  This uses Direct I/O for buffer to recv data

Arguments:

Return Value:

    Status - Success, Pending or error

--*/
{
   NTSTATUS            Status = STATUS_SUCCESS;
   ULONG               ulInputBufLen, ulOutputBufLen;
   PATMSM_ADAPTER      pAdapt;
   ULONG               ulControlCode;

   TraceIn(AtmSmIoctlRecvData);

   ulControlCode   = pIrpSp->Parameters.DeviceIoControl.IoControlCode;

   ASSERT(METHOD_OUT_DIRECT == (ulControlCode & 0x3));

   ulInputBufLen  = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;

   if(ulInputBufLen < sizeof(HANDLE))
   {

      DbgErr(("Input length is invalid\n"));
      TraceOut(AtmSmIoctlRecvData);
      return STATUS_INVALID_PARAMETER;
   }

   ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;

   if(0 == ulOutputBufLen)
   {
      DbgErr(("Output buffer length is 0!\n"));
      TraceOut(AtmSmIoctlRecvData);
      return STATUS_INVALID_PARAMETER;
   }

   DbgLoud(("Recv - Output buffer length = %u\n", ulOutputBufLen));

   pAdapt = (PATMSM_ADAPTER)(*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer));

   DbgLoud(("Recv Context is 0x%x\n", pAdapt));

   // Note - VerifyRecvOpenContext adds a reference to the adapter
   // if successful, which we remove when we are done

   if(STATUS_SUCCESS != (Status = VerifyRecvOpenContext(pAdapt)))
   {

      TraceOut(AtmSmIoctlRecvData);
      return Status;
   }

   // we have a valid RecvContext - check if a recv is already queued
   do
   { // break off loop

      ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
      if(pAdapt->pRecvIrp)
      {

         // there is already an Irp pending
         RELEASE_ADAPTER_GEN_LOCK(pAdapt);

         Status = STATUS_UNSUCCESSFUL;
         DbgErr(("There is already a recv pending\n"));

         break;
      }

      // No irps pending, check if a queued packets is there, if so copy
      // else queue ourselves
      if(pAdapt->pRecvPktNext)
      {

         PPROTO_RSVD     pPRsvd;
         PNDIS_PACKET    pPkt;

         pPkt    = pAdapt->pRecvPktNext;
         pPRsvd  = GET_PROTO_RSVD(pPkt);

         pAdapt->pRecvPktNext    = pPRsvd->pPktNext;

         if(pAdapt->pRecvLastPkt == pPkt)
            pAdapt->pRecvLastPkt = NULL;

         pAdapt->ulRecvPktsCount--;

         // release the recv queue lock
         RELEASE_ADAPTER_GEN_LOCK(pAdapt);

         // Copy the packet to the Irp buffer
         // Note this may be partial if the Irp buffer is not large enough
         pIrp->IoStatus.Information = 
            CopyPacketToIrp(pIrp, pPkt);

         // return the packet to the miniport
         NdisReturnPackets(&pPkt, 1);

         // Status success

      }
      else
      {

         // no packets available, queue this Irp

         pAdapt->pRecvIrp = pIrp;

         // release the recv queue lock
         RELEASE_ADAPTER_GEN_LOCK(pAdapt);

         IoMarkIrpPending(pIrp);

         Status = STATUS_PENDING;
      }


   }while(FALSE);

   // remove the reference added while verifying
   AtmSmDereferenceAdapter(pAdapt);


   TraceOut(AtmSmIoctlRecvData);

   return Status;
}

NTSTATUS AtmSmIoctlCloseRecvHandle(
   PIRP                pIrp,
   PIO_STACK_LOCATION  pIrpSp
   )
/*++

Routine Description:

    This routine is used to close a handle that was obtained when the adapter
    was opened for recvs.
    
    NOTE!  This uses buffered I/O

Arguments:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -