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

📄 ioctl.c

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

Return Value:

    Status - doesn't pend

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

   TraceIn(AtmSmIoctlCloseRecvHandle);

   ulInputBufLen  = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;

   if(ulInputBufLen < sizeof(HANDLE))
   {

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


   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)))
   {

      DbgInfo(("Couldn't put a reference on the adapter - pAdapt - 0x%x\n",
         pAdapt));
      TraceOut(AtmSmIoctlCloseRecvHandle);
      return Status;
   }

   // we have a valid RecvContext

   ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);

   if(pAdapt->pRecvIrp)
   {

      PIRP pRecvIrp = pAdapt->pRecvIrp;

      pAdapt->pRecvIrp = NULL;

      // there is an Irp pending, complete it
      pRecvIrp->IoStatus.Status       = STATUS_CANCELLED;
      pRecvIrp->Cancel                = TRUE;
      pRecvIrp->IoStatus.Information  = 0;
      IoCompleteRequest(pRecvIrp, IO_NETWORK_INCREMENT);

   }

   pAdapt->fAdapterOpenedForRecv = FALSE;

   RELEASE_ADAPTER_GEN_LOCK(pAdapt);

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

   pIrp->IoStatus.Information = 0;

   TraceOut(AtmSmIoctlCloseRecvHandle);

   return Status;
}

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

Routine Description:
    This routine is used to initiate a connection to 1 (P-P) or more (PMP)
    destinations.
    
    NOTE!  This uses buffered I/O

Arguments:

Return Value:

    Status - Pending or error

--*/
{
   NTSTATUS            Status          = STATUS_SUCCESS;
   PCONNECT_INFO       pConnectInfo    = (PCONNECT_INFO)
                                         pIrp->AssociatedIrp.SystemBuffer;
   ULONG               ul, ulInputBufLen, ulOutputBufLen, ulCompareLength;
   PATMSM_ADAPTER      pAdapt;
   PATMSM_VC           pVc;

#if DBG
   ATM_ADDRESS         AtmAddr;
#endif

   TraceIn(AtmSmIoctlConnectToDsts);

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

   if(ulInputBufLen < sizeof(CONNECT_INFO))
   {
      DbgErr(("Input length < sizeof(CONNECT_INFO)\n"));
      TraceOut(AtmSmIoctlConnectToDsts);
      return STATUS_INVALID_PARAMETER;
   }
                                       
   if(pConnectInfo->ulNumDsts == 0)
   {
      DbgErr(("Number of destinations is zero\n"));
      TraceOut(AtmSmIoctlConnectToDsts);
      return STATUS_INVALID_PARAMETER;
   }

   if((ulInputBufLen - (sizeof(CONNECT_INFO))/(sizeof(UCHAR)*ATM_ADDRESS_LENGTH)) 
      < pConnectInfo->ulNumDsts -1)
   {
      DbgErr(("Input length is invalid\n"));
      TraceOut(AtmSmIoctlConnectToDsts);
      return STATUS_INVALID_PARAMETER;
   }

   if(ulOutputBufLen < sizeof(HANDLE))
   {
      DbgErr(("Output length is not sufficient\n"));
      TraceOut(AtmSmIoctlConnectToDsts);
      return STATUS_BUFFER_TOO_SMALL;
   }


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

   DumpATMAddress(ATMSMD_INFO, "Connect to Dsts - Local AtmAddress - ", 
      &AtmAddr);

   DbgInfo(("No of destinations - %u\n", pConnectInfo->ulNumDsts));

   for(ul = 0; ul < pConnectInfo->ulNumDsts; ul++)
   {

      RtlCopyMemory(AtmAddr.Address, pConnectInfo->ucDstATMAddrs[ul], 
         (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));

      DumpATMAddress(ATMSMD_INFO, "    Destination 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(
            pConnectInfo->ucLocalATMAddr, 
            pAdapt->ConfiguredAddress.Address, 
            ulCompareLength))
            break;
      }

      RELEASE_GLOBAL_LOCK();

      if(NULL == pAdapt)
      {

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

      // no need to add reference here since the allocation of VC
      // will add the VC

      // create a VC structure and based on whether it is PMP or not
      // we add the party members to the VC and ask it to connect
      Status = AtmSmAllocVc(pAdapt, 
                  &pVc, 
                  (pConnectInfo->bPMP? 
                  VC_TYPE_PMP_OUTGOING : 
               VC_TYPE_PP_OUTGOING), 
                  NULL);

      if(NDIS_STATUS_SUCCESS != Status)
      {

         DbgErr(("Failed to create ougoing VC. Status - 0x%X.\n", Status));

         Status = STATUS_NO_MEMORY;
         break;
      }

      ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);

      if(!pConnectInfo->bPMP)
      {

         // this is P-P
         // copy the destination address
         PATM_ADDRESS pAtmAddr = &pVc->HwAddr.Address;

         pAtmAddr->AddressType     = ATM_NSAP;
         pAtmAddr->NumberOfDigits  = ATM_ADDRESS_LENGTH;
         RtlCopyMemory(pAtmAddr->Address, pConnectInfo->ucDstATMAddrs[0], 
            (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));
         // Note: we don't get the correct selector byte from user mode
         //       we assume the selector byte used by the destination is
         //       the same.
         pAtmAddr->Address[ATM_ADDRESS_LENGTH-1] = pAdapt->SelByte;

      }
      else
      {

         for(ul = 0; ul < pConnectInfo->ulNumDsts; ul++)
         {

            PATMSM_PMP_MEMBER   pMember;
            PATM_ADDRESS        pAtmAddr;

            AtmSmAllocMem(&pMember, PATMSM_PMP_MEMBER, 
               sizeof(ATMSM_PMP_MEMBER));

            if(NULL == pMember)
            {


               DbgErr(("Failed to allocate member. No resources\n"));

               // cleanup the members and VC
               while(NULL != (pMember = pVc->pPMPMembers))
               {
                  AtmSmFreeMem(pMember);
                  pVc->ulRefCount--;
               }

               RELEASE_ADAPTER_GEN_LOCK(pAdapt);

               AtmSmDereferenceVc(pVc);

               Status = STATUS_NO_MEMORY;
               break;
            }

            NdisZeroMemory(pMember, sizeof(ATMSM_PMP_MEMBER));

            pMember->ulSignature = atmsm_member_signature;
            pMember->pVc = pVc;
            ATMSM_SET_MEMBER_STATE(pMember, ATMSM_MEMBER_IDLE);
            pAtmAddr = &pMember->HwAddr.Address;

            pAtmAddr->AddressType     = ATM_NSAP;
            pAtmAddr->NumberOfDigits  = ATM_ADDRESS_LENGTH;
            RtlCopyMemory(pAtmAddr->Address, 
               pConnectInfo->ucDstATMAddrs[ul], 
               (sizeof(UCHAR) * ATM_ADDRESS_LENGTH));

            // Note: we don't get the correct selector byte from user mode
            //       we assume the selector byte used by the destination is
            //       the same.
            pAtmAddr->Address[ATM_ADDRESS_LENGTH-1] = pAdapt->SelByte;

            pMember->pNext = pVc->pPMPMembers;
            pVc->pPMPMembers = pMember;
            pVc->ulNumTotalMembers++;

            // Also add a reference for each members
            pVc->ulRefCount++;
         }

      }

      pVc->pConnectIrp  = pIrp;

      IoMarkIrpPending(pIrp);

      // we will return pending
      Status = STATUS_PENDING;

      RELEASE_ADAPTER_GEN_LOCK(pAdapt);

      DbgInfo(("Initiated a VC connection - Adapter 0x%x VC - 0x%x\n", 
         pAdapt, pVc));
      if(!pConnectInfo->bPMP)
      {

         AtmSmConnectPPVC(pVc);

      }
      else
      {

         AtmSmConnectToPMPDestinations(pVc);
      }


   } while(FALSE);


   TraceOut(AtmSmIoctlConnectToDsts);

   return Status;
}

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

Routine Description:
    This routine is used to send a packet to destination(s) for which we 
    already have a connection.
    
    NOTE!  This uses Direct I/O for buffer to send data

Arguments:

Return Value:

    Status - Pending or error
--*/
{
   NTSTATUS            Status = STATUS_SUCCESS;
   ULONG               ulInputBufLen, ulOutputBufLen;
   PATMSM_VC           pVc;
   ULONG               ulControlCode;

   TraceIn(AtmSmIoctlSendToDsts);

   ulControlCode   = pIrpSp->Parameters.DeviceIoControl.IoControlCode;

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

   ulInputBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;

   if(sizeof(HANDLE) != ulInputBufLen)
   {
      DbgErr(("Input buffer length is invalid!\n"));
      ASSERT(FALSE);
      TraceOut(AtmSmIoctlSendToDsts);
      return STATUS_INVALID_PARAMETER;
   }

   ulOutputBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;

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

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

   pVc  = (PATMSM_VC)(*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer));

   DbgLoud(("Connect Context is 0x%x\n", pVc));

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

   if(STATUS_SUCCESS != (Status = VerifyConnectContext(pVc)))
   {

      TraceOut(AtmSmIoctlSendToDsts);
      return Status;
   }

   // we have a valid ConnectContext
   do
   { // break off loop

      PNDIS_PACKET        pPacket;
      PATMSM_ADAPTER      pAdapt = pVc->pAdapt;
      //
      //  Try to get a packet 
      //

      NdisAllocatePacket(
         &Status,
         &pPacket,
         pAdapt->PacketPoolHandle
         );

      if(NDIS_STATUS_SUCCESS != Status)
      {

         //
         //  No free packets
         //
         Status = STATUS_UNSUCCESSFUL;
         break;
      }

      (GET_PROTO_RSVD(pPacket))->pSendIrp=pIrp;

#ifdef BUG_IN_NEW_DMA

      {
         PNDIS_BUFFER    pBuffer;
         PVOID           pSrcVA    = 
            MmGetSystemAddressForMdl(pIrp->MdlAddress);
         UINT            uiBufSize = 
            MmGetMdlByteCount(pIrp->MdlAddress);

         // allocate the Buffer Descriptor
         NdisAllocateBuffer(&Status,
            &pBuffer,
            pAdapt->BufferPoolHandle,
            pSrcVA,
            uiBufSize);

         if(NDIS_STATUS_SUCCESS != Status)
         {
            NdisFreePacket(pPacket);
            break;
         }

         // add the buffer to the packet
         NdisChainBufferAtFront(pPacket,
            pBuffer);

      }

#else   // BUG_IN_NEW_DMA

      //
      //  Attach the send buffer to the packet
      //
      NdisChainBufferAtFront(pPacket, pIrp->MdlAddress);

#endif  // BUG_IN_NEW_DMA

      IoMarkIrpPending(pIrp);

      Status = STATUS_PENDING;

      // send the packet on the VC
      AtmSmSendPacketOnVc(pVc, pPacket);

   }while(FALSE);

   // remove the reference added to the VC while verifying
   AtmSmDereferenceVc(pVc);

   TraceOut(AtmSmIoctlSendToDsts);

   return Status;
}

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

Routine Description:

    This routine is used to close a handle that was obtained when we established
    a connection to destinations.
    
    NOTE!  This uses buffered I/O

Arguments:

Return Value:

    Status - doesn't pend

--*/
{
   NTSTATUS            Status = STATUS_SUCCESS;
   ULONG               ulInputBufLen;
   PATMSM_VC           pVc;

   TraceIn(AtmSmIoctlCloseSendHandle);

   ulInputBufLen  = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;

   if(ulInputBufLen < sizeof(HANDLE))
   {

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

   pVc = (PATMSM_VC)(*(PHANDLE)(pIrp->AssociatedIrp.SystemBuffer));

   DbgLoud(("Connect Context is 0x%x\n", pVc));

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

   if(STATUS_SUCCESS != (Status = VerifyConnectContext(pVc)))
   {

      TraceOut(AtmSmIoctlCloseSendHandle);
      return Status;
   }

   // we have a valid Connect Context - disconnect it
   AtmSmDisconnectVc(pVc);

   // remove the reference added to the VC while verifying
   AtmSmDereferenceVc(pVc);

   TraceOut(AtmSmIoctlCloseSendHandle);

   return Status;
}



⌨️ 快捷键说明

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