예제 #1
0
static VOID
UsbhubGetUserBuffers(IN PIRP Irp, IN ULONG IoControlCode, OUT PVOID* BufferIn, OUT PVOID* BufferOut)
{
    ASSERT(Irp);
    ASSERT(BufferIn);
    ASSERT(BufferOut);

    switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
    {
        case METHOD_BUFFERED:
            *BufferIn = *BufferOut = Irp->AssociatedIrp.SystemBuffer;
            break;
        case METHOD_IN_DIRECT:
        case METHOD_OUT_DIRECT:
            *BufferIn = Irp->AssociatedIrp.SystemBuffer;
            *BufferOut = MmGetSystemAddressForMdl(Irp->MdlAddress);
            break;
        case METHOD_NEITHER:
            *BufferIn = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.Type3InputBuffer;
            *BufferOut = Irp->UserBuffer;
            break;
        default:
            /* Should never happen */
            *BufferIn = NULL;
            *BufferOut = NULL;
            break;
    }
}
예제 #2
0
파일: vfdrdwr.c 프로젝트: layerfsd/Work
//
//	Substitute for MmGetSystemAddressForMdlSafe
//	for NT 4.0 DDK does not provide its equivqlent
//	originally written by Bruce Engle for filedisk
//
static PVOID
MmGetSystemAddressForMdlPrettySafe(
	IN PMDL						Mdl,
	IN MM_PAGE_PRIORITY			Priority)
{
#if (VER_PRODUCTBUILD >= 2195)
	if (OsMajorVersion >= 5) {
		return MmGetSystemAddressForMdlSafe(Mdl, Priority);
	}
	else {
#endif	// (VER_PRODUCTBUILD >= 2195)
		CSHORT	MdlMappingCanFail;
		PVOID	MappedSystemVa;

		MdlMappingCanFail = (CSHORT)(Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL);

		Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;

		MappedSystemVa = MmGetSystemAddressForMdl(Mdl);

		if (!MdlMappingCanFail) {
			Mdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;
		}

		return MappedSystemVa;
#if (VER_PRODUCTBUILD >= 2195)
	}
#endif	// (VER_PRODUCTBUILD >= 2195)
}
예제 #3
0
파일: rw.c 프로젝트: RPG-7/reactos
NTSTATUS
NTAPI
NtfsFsdRead(PDEVICE_OBJECT DeviceObject,
            PIRP Irp)
{
    PDEVICE_EXTENSION DeviceExt;
    PIO_STACK_LOCATION Stack;
    PFILE_OBJECT FileObject;
    PVOID Buffer;
    ULONG ReadLength;
    LARGE_INTEGER ReadOffset;
    ULONG ReturnedReadLength = 0;
    NTSTATUS Status = STATUS_SUCCESS;

    DPRINT("NtfsRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);

    DeviceExt = DeviceObject->DeviceExtension;
    Stack = IoGetCurrentIrpStackLocation(Irp);
    FileObject = Stack->FileObject;

    ReadLength = Stack->Parameters.Read.Length;
    ReadOffset = Stack->Parameters.Read.ByteOffset;
    Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);

    Status = NtfsReadFile(DeviceExt,
                          FileObject,
                          Buffer,
                          ReadLength,
                          ReadOffset.u.LowPart,
                          Irp->Flags,
                          &ReturnedReadLength);
    if (NT_SUCCESS(Status))
    {
        if (FileObject->Flags & FO_SYNCHRONOUS_IO)
        {
            FileObject->CurrentByteOffset.QuadPart =
                ReadOffset.QuadPart + ReturnedReadLength;
        }

        Irp->IoStatus.Information = ReturnedReadLength;
    }
    else
    {
        Irp->IoStatus.Information = 0;
    }

    Irp->IoStatus.Status = Status;
    IoCompleteRequest(Irp,IO_NO_INCREMENT);

    return Status;
}
예제 #4
0
파일: block.c 프로젝트: dond2008/ext2fsd
PVOID
Ext2GetUserBuffer (IN PIRP Irp )
{
    ASSERT(Irp != NULL);

    if (Irp->MdlAddress) {

#if (_WIN32_WINNT >= 0x0500)
        return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
#else
        return MmGetSystemAddressForMdl(Irp->MdlAddress);
#endif
    } else {

        return Irp->UserBuffer;
    }
}
예제 #5
0
/*****************************************************************************
 * KernHelpGetSysAddrForMdl()
 *****************************************************************************
 * Safely map the MDL to system address space. This mapping
 * may fail "when the system runs out of system PTEs", and
 * without the flag set below, this condition causes a bugcheck
 * rather than a NULL return.
 */
PVOID KernHelpGetSysAddrForMdl(PMDL pMdl)
{
    PVOID MappedAddress;

#if UNDER_NT

    MappedAddress = MmGetSystemAddressForMdlSafe(pMdl,NormalPagePriority);

#else // !UNDER_NT

    CSHORT LocalCopyOfMdlFlagBit;
    //
    // Note the manipulation of the MDL flags is only done if needed.
    // The driver is responsible for ensuring that it is not simultaneously
    // modifying this field anywhere else and synchronizing if needed.
    //
    LocalCopyOfMdlFlagBit = (pMdl->MdlFlags & MDL_MAPPING_CAN_FAIL);

    if (LocalCopyOfMdlFlagBit == 0)
    {
        pMdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
    }

    MappedAddress = MmGetSystemAddressForMdl(pMdl);

    //
    // Carefully restore only the single "can-fail" bit state.  This is
    // because the call above will change the state of other flag bits and
    // we don't want this restore to wipe out those changes.  Wiping out the
    // other changes will cause not-so-obvious effects like eventually
    // exhausting the system PTE pool and other resources, which will crash
    // the entire system.
    //
    if (LocalCopyOfMdlFlagBit == 0)
    {
        pMdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;
    }

#endif // !UNDER_NT

    return MappedAddress;
}
예제 #6
0
파일: httpdisk.c 프로젝트: mrjrt/winvblock
PVOID
MmGetSystemAddressForMdlPrettySafe (
    PMDL Mdl
    )
{
    CSHORT  MdlMappingCanFail;
    PVOID   MappedSystemVa;

    MdlMappingCanFail = Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL;

    Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;

    MappedSystemVa = MmGetSystemAddressForMdl(Mdl);

    if (MdlMappingCanFail == 0)
    {
        Mdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;
    }

    return MappedSystemVa;
}
예제 #7
0
VOID ZeroPEHeader(
	ULONG ImageBase
	)
{
		PIMAGE_DOS_HEADER pDosHeader;
		char *pNtHeader;
		PIMAGE_OPTIONAL_HEADER pOptinalHeader;
		ULONG HeaderSize=0;
		PMDL pHeaderMdl;
		PVOID NewBuffer;
		__try
		{
			pDosHeader=(PIMAGE_DOS_HEADER)ImageBase;
			pNtHeader=(char*)ImageBase+pDosHeader->e_lfanew;
			pOptinalHeader=(PIMAGE_OPTIONAL_HEADER)(pNtHeader+4+sizeof(IMAGE_FILE_HEADER));
			HeaderSize=pOptinalHeader->SizeOfHeaders;
			dprintf("Image Header Size=0x%X\n",HeaderSize);
			pHeaderMdl=IoAllocateMdl((PVOID)ImageBase,HeaderSize,FALSE,FALSE,NULL);
			dprintf("pHeaderMdl=0x%08X\n",pHeaderMdl);
			NewBuffer=MmGetSystemAddressForMdl(pHeaderMdl);
			dprintf("NewBuffer=0x%08X\n",NewBuffer);
			RtlZeroMemory(NewBuffer,HeaderSize);
			MmUnmapLockedPages(NewBuffer,pHeaderMdl);
			IoFreeMdl(pHeaderMdl);
	
			//若要针对所有进程,可使用以下方法,此时COW将会失效
			/*
			WPOFF();
			RtlZeroMemory((char*)ImageBase,HeaderSize);
			WPON();
			*/
		}
		__except(EXCEPTION_EXECUTE_HANDLER)
		{
			DbgPrint("Error occured while zero pe header.\n");
			return ;
		}
}
예제 #8
0
NDIS_STATUS
NdisuioReceive(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN NDIS_HANDLE                  MacReceiveContext,
    IN PVOID                        pHeaderBuffer,
    IN UINT                         HeaderBufferSize,
    IN PVOID                        pLookaheadBuffer,
    IN UINT                         LookaheadBufferSize,
    IN UINT                         PacketSize
    )
/*++

Routine Description:

    Our protocol receive handler called by NDIS, typically if we have
    a miniport below that doesn't indicate packets.

    We make a local packet/buffer copy of this data, queue it up, and
    kick off the read service routine.

Arguments:

    ProtocolBindingContext - pointer to open context
    MacReceiveContext - for use in NdisTransferData
    pHeaderBuffer - pointer to data header
    HeaderBufferSize - size of the above
    pLookaheadBuffer - pointer to buffer containing lookahead data
    LookaheadBufferSize - size of the above
    PacketSize - size of the entire packet, minus header size.

Return Value:

    NDIS_STATUS_NOT_ACCEPTED - if this packet is uninteresting
    NDIS_STATUS_SUCCESS - if we processed this successfully

--*/
{
    PNDISUIO_OPEN_CONTEXT   pOpenContext;
    NDIS_STATUS             Status;
    PNDISUIO_ETH_HEADER     pEthHeader;
    PNDIS_PACKET            pRcvPacket;
    PUCHAR                  pRcvData;
    UINT                    BytesTransferred;
    PNDIS_BUFFER            pOriginalNdisBuffer, pPartialNdisBuffer;
    PIRP					pIrp;
    PLIST_ENTRY				pIrpEntry;
    ULONG					BytesRemaining; // at pDst
	PPACKET_GROUP			pGroup;

	//ULONG                   pDst;
	
    pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
    NUIO_STRUCT_ASSERT(pOpenContext, oc);
    pRcvPacket = NULL;
    pRcvData = NULL;
    Status = NDIS_STATUS_SUCCESS;

    DEBUGP(DL_LOUD, ("Receive: Open %p, LookaheadBufferSize %d, PacketSize %d\n",
		pOpenContext, LookaheadBufferSize, PacketSize));
    
	NdisInterlockedAddLargeStatistic((PLARGE_INTEGER)&pOpenContext->ReceivedPackets, 1);

	do
    {
        if (HeaderBufferSize != sizeof(NDISUIO_ETH_HEADER))
        {
            Status = NDIS_STATUS_NOT_ACCEPTED;
            break;
        }

        pEthHeader = (PNDISUIO_ETH_HEADER)pHeaderBuffer;

		NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);

		//
		// Someone is reading, and this is the first packet.
		//
		if (!NUIO_IS_LIST_EMPTY(&pOpenContext->PendedReads) &&
			NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
		{
			//
			//  Get the first pended Read IRP
			//
			pIrpEntry = pOpenContext->PendedReads.Flink;
			pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry);
			
			//
			// We don't have to worry about the situation where the IRP is cancelled
			// after we remove it from the queue and before we reset the cancel
			// routine because the cancel routine has been coded to cancel an IRP
			// only if it's in the queue.
			//
			IoSetCancelRoutine(pIrp, NULL);

			NUIO_REMOVE_ENTRY_LIST(pIrpEntry);
			
			pOpenContext->PendedReadCount--;

			NUIO_RELEASE_LOCK(&pOpenContext->Lock);

			NUIO_DEREF_OPEN(pOpenContext);  // Service: dequeue rcv packet

			//
			//  Copy as much data as possible from the receive packet to
			//  the IRP MDL.
			//
#ifndef WIN9X
			pGroup = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
			//NUIO_ASSERT(pDst != NULL);  // since it was already mapped
#else
			pGroup = MmGetSystemAddressForMdl(pIrp->MdlAddress);  // Win9x
#endif
			BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress);
			
			BytesRemaining -= sizeof(PACKET_GROUP);

			//
			//  copy the ethernet header into the actual readbuffer
			//
			NdisMoveMappedMemory(pGroup->Data, pHeaderBuffer, HeaderBufferSize);
			
			if (PacketSize == LookaheadBufferSize)
			{
				BytesTransferred = MIN(LookaheadBufferSize, BytesRemaining);

				NdisCopyLookaheadData(pGroup->Data + HeaderBufferSize,
					pLookaheadBuffer,
					BytesTransferred,
					pOpenContext->MacOptions);

				pGroup->Length = BytesTransferred + HeaderBufferSize;
				
				pIrp->IoStatus.Information = pGroup->Length + sizeof(PACKET_GROUP);
				pIrp->IoStatus.Status = STATUS_SUCCESS;				
		
				DEBUGP(DL_LOUD, ("Receive: %d bytes\n", pIrp->IoStatus.Information));
		
				IoCompleteRequest(pIrp, IO_NO_INCREMENT);
			}
			else
			{
				BytesTransferred = 0;

				NdisAllocatePacket(
					&Status,
					&pRcvPacket,
					pOpenContext->RecvBufferPool
					);
				
				if (Status != NDIS_STATUS_SUCCESS)
					goto ERROR;
				
				//
				//  Allocate an MDL to map the portion of the buffer following the
				//  header
				//
				pPartialNdisBuffer = IoAllocateMdl(pGroup->Data, BytesRemaining, FALSE, FALSE, NULL);
				
				if (pPartialNdisBuffer == NULL)
				{
					NdisFreePacket(pRcvPacket);
					Status = NDIS_STATUS_RESOURCES;
					goto ERROR;
				}
				
				//
				//  Build the mdl to point to the the portion of the buffer following
				//  the header
				//
				IoBuildPartialMdl(
					pIrp->MdlAddress,
					pPartialNdisBuffer,
					pGroup->Data + HeaderBufferSize,
					0);
				
				//
				//  Clear the next link in the new MDL
				//
				
				pPartialNdisBuffer->Next = NULL;
				
				//
				//  Get a pointer to the packet itself.
				//
				
				NUIO_IRP_FROM_RCV_PKT(pRcvPacket) = pIrp;
				NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pRcvPacket) = pPartialNdisBuffer;
				
				//
				//  Attach our partial MDL to the packet
				//
				
				NdisChainBufferAtFront(pRcvPacket, pPartialNdisBuffer);
				
				//
				//  Call the Mac to transfer the packet
				//
				
				NdisTransferData(
					&Status,
					pOpenContext->BindingHandle,
					MacReceiveContext,
					0,  // ByteOffset
					PacketSize,
					pRcvPacket,
					&BytesTransferred);

ERROR:					
				//
				//  If it didn't pend, call the completeion routine now
				//
				if (Status != NDIS_STATUS_PENDING)
				{
					NdisuioTransferDataComplete(
						(NDIS_HANDLE)pOpenContext,
						pRcvPacket,
						Status,
						BytesTransferred);
				}
			}

			break;
		}

		NUIO_RELEASE_LOCK(&pOpenContext->Lock);

		//
        //  Allocate resources for queueing this up.
        //
        pRcvPacket = ndisuioAllocateReceivePacket(
			pOpenContext,
			PacketSize + HeaderBufferSize,
			&pRcvData
			);

        if (pRcvPacket == NULL)
        {
            Status = NDIS_STATUS_NOT_ACCEPTED;
            break;
        }

        NdisMoveMappedMemory(pRcvData, pHeaderBuffer, HeaderBufferSize);

        //
        //  Check if the entire packet is within the lookahead.
        //
        if (PacketSize == LookaheadBufferSize)
        {
            NdisCopyLookaheadData(pRcvData + HeaderBufferSize,
                                  pLookaheadBuffer,
                                  LookaheadBufferSize,
                                  pOpenContext->MacOptions);
            //
            //  Queue this up for receive processing, and
            //  try to complete some read IRPs.
            //
            ndisuioQueueReceivePacket(pOpenContext, pRcvPacket);
        }
        else
        {
            //
            //  Allocate an NDIS buffer to map the receive area
            //  at an offset "HeaderBufferSize" from the current
            //  start. This is so that NdisTransferData can copy
            //  in at the right point in the destination buffer.
            //

            NdisAllocateBuffer(
                &Status,
                &pPartialNdisBuffer,
                pOpenContext->RecvBufferPool,
                pRcvData + HeaderBufferSize,
                PacketSize);
            
            if (Status == NDIS_STATUS_SUCCESS)
            {
                //
                //  Unlink and save away the original NDIS Buffer
                //  that maps the full receive buffer.
                //
                NdisUnchainBufferAtFront(pRcvPacket, &pOriginalNdisBuffer);
                NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pRcvPacket) = pOriginalNdisBuffer;
				NUIO_IRP_FROM_RCV_PKT(pRcvPacket) = NULL;

                //
                //  Link in the partial buffer for NdisTransferData to
                //  operate on.
                //
                NdisChainBufferAtBack(pRcvPacket, pPartialNdisBuffer);

                DEBUGP(DL_LOUD, ("Receive: setting up for TransferData:"
                        " Pkt %p, OriginalBuf %p, PartialBuf %p\n",
                        pRcvPacket, pOriginalNdisBuffer, pPartialNdisBuffer));

                NdisTransferData(
                    &Status,
                    pOpenContext->BindingHandle,
                    MacReceiveContext,
                    0,  // ByteOffset
                    PacketSize,
                    pRcvPacket,
                    &BytesTransferred);
            }
            else
            {
                //
                //  Failure handled below in TransferDataComplete.
                //
                BytesTransferred = 0;
            }
    
            if (Status != NDIS_STATUS_PENDING)
            {
                NdisuioTransferDataComplete(
                    (NDIS_HANDLE)pOpenContext,
                    pRcvPacket,
                    Status,
                    BytesTransferred);
            }
        }
    } while (FALSE);

	if (Status != NDIS_STATUS_SUCCESS && Status != NDIS_STATUS_PENDING)
		NdisInterlockedAddLargeStatistic((PLARGE_INTEGER)&pOpenContext->DroppedPackets, 1);

    return Status;
}
예제 #9
0
파일: loopsub.c 프로젝트: Gaikokujin/WinNT4
VOID
LoopCopyData (
    IN PMDL Destination,
    IN PMDL Source,
    IN ULONG Length
    )

/*++

Routine Description:

    This routine copies data from the storage described by one MDL chain
    into the storage described by another MDL chain.

Arguments:

    Destination - Pointer to first MDL in Destination chain

    Source - Pointer to first MDL in Source chain

    Length - Amount of data to copy.  Caller must ensure that the Source
        and Destination chains are at least this long.

Return Value:

    None.

--*/

{
    PCHAR sourceAddress;
    ULONG sourceLength;

    PCHAR destinationAddress;
    ULONG destinationLength;

    ULONG copyLength;

    //
    // Get the virtual address of the first source buffer, mapping it
    // if necessary.  Also get the length of the buffer.
    //

    sourceAddress = MmGetSystemAddressForMdl( Source );
    sourceLength = MmGetMdlByteCount( Source );

    //
    // Get the virtual address of the first destination buffer, mapping
    // it if necessary.  Also get the length of the buffer.
    //

    destinationAddress = MmGetSystemAddressForMdl( Destination );
    destinationLength = MmGetMdlByteCount( Destination );

    //
    // Loop copying data.
    //

    do {

        //
        // The amount to copy in this pass is the minimum of 1) the
        // amount remaining in the current source buffer, 2) the amount
        // remaining in the current destination buffer, and 3) the
        // amount remaining in the overall copy operation.
        //

        copyLength = sourceLength;
        if ( copyLength > destinationLength ) copyLength = destinationLength;
        if ( copyLength > Length ) copyLength = Length;

        //
        // Copy from the source buffer into the destination buffer.
        //

#ifndef TIMING
        IF_DEBUG(LOOP4) {
            DbgPrint( "      copying %lx bytes from %lx to %lx\n",
                        copyLength, sourceAddress, destinationAddress );
            DbgPrint( "      source data: %lx, %lx\n",
                        *(PULONG)sourceAddress, *((PULONG)sourceAddress + 1) );
        }
        RtlMoveMemory( destinationAddress, sourceAddress, copyLength );
#else
        if ( (NtGlobalFlag & 0x20000000) == 0 ) {
            RtlMoveMemory( destinationAddress, sourceAddress, copyLength );
        } else {
            RtlMoveMemory(
                destinationAddress,
                sourceAddress,
                (copyLength > 200) ? 200 : copyLength
                );
        }
#endif

        //
        // If all of the requested data has been copied, leave.
        //

        Length -= copyLength;

        if ( Length == 0 ) {

            return;

        }

        //
        // If we have used up all of the current source buffer, move to
        // the next buffer.  Get the virtual address of the next buffer,
        // mapping it if necessary.  Also get the length of the buffer.
        // If we haven't used up the current source buffer, simply
        // update the source pointer and the remaining length.
        //

        if ( copyLength == sourceLength ) {

            Source = Source->Next;

            sourceAddress = MmGetSystemAddressForMdl( Source );
            sourceLength = MmGetMdlByteCount( Source );

        } else {

            sourceAddress += copyLength;
            sourceLength -= copyLength;

        }

        //
        // If we have used up all of the current destination buffer,
        // move to the next buffer.  Get the virtual address of the next
        // buffer, mapping it if necessary.  Also get the length of the
        // buffer.  If we haven't used up the current destination
        // buffer, simply update the destination pointer and the
        // remaining length.
        //

        if ( copyLength == destinationLength ) {

            Destination = Destination->Next;

            destinationAddress = MmGetSystemAddressForMdl( Destination );
            destinationLength = MmGetMdlByteCount( Destination );

        } else {

            destinationAddress += copyLength;
            destinationLength -= copyLength;

        }

    } while ( TRUE );

    //
    // Can't get here.
    //

    ASSERTMSG( FALSE, "Can't get here!" );

} // LoopCopyData
예제 #10
0
파일: rcv.c 프로젝트: Gaikokujin/WinNT4
NTSTATUS
NbfTdiReceive(
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the TdiReceive request for the transport provider.

Arguments:

    Irp - I/O Request Packet for this request.

Return Value:

    NTSTATUS - status of operation.

--*/

{
    NTSTATUS status;
    PTP_CONNECTION connection;
    KIRQL oldirql;
    PIO_STACK_LOCATION irpSp;

    //
    // verify that the operation is taking place on a connection. At the same
    // time we do this, we reference the connection. This ensures it does not
    // get removed out from under us. Note also that we do the connection
    // lookup within a try/except clause, thus protecting ourselves against
    // really bogus handles
    //

    irpSp = IoGetCurrentIrpStackLocation (Irp);
    connection = irpSp->FileObject->FsContext;

    //
    // Check that this is really a connection.
    //

    if ((connection->Size != sizeof (TP_CONNECTION)) ||
        (connection->Type != NBF_CONNECTION_SIGNATURE)) {
#if DBG
        NbfPrint2 ("TdiReceive: Invalid Connection %lx Irp %lx\n", connection, Irp);
#endif
        return STATUS_INVALID_CONNECTION;
    }

    //
    // Initialize bytes transferred here.
    //

    Irp->IoStatus.Information = 0;              // reset byte transfer count.

    // This reference is removed by NbfDestroyRequest.

    KeRaiseIrql (DISPATCH_LEVEL, &oldirql);

    ACQUIRE_DPC_C_SPIN_LOCK (&connection->SpinLock);

    if ((connection->Flags & CONNECTION_FLAGS_READY) == 0) {

        RELEASE_DPC_C_SPIN_LOCK (&connection->SpinLock);

        Irp->IoStatus.Status = connection->Status;
        IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);

        status = STATUS_PENDING;

    } else {
        KIRQL cancelIrql;

        //
        // Once the reference is in, LinkSpinLock will be valid.
        //

        NbfReferenceConnection("TdiReceive request", connection, CREF_RECEIVE_IRP);
        RELEASE_DPC_C_SPIN_LOCK (&connection->SpinLock);

        IoAcquireCancelSpinLock(&cancelIrql);
        ACQUIRE_DPC_SPIN_LOCK (connection->LinkSpinLock);

        IRP_RECEIVE_IRP(irpSp) = Irp;
        IRP_RECEIVE_REFCOUNT(irpSp) = 1;

#if DBG
        NbfReceives[NbfReceivesNext].Irp = Irp;
        NbfReceives[NbfReceivesNext].Request = NULL;
        NbfReceives[NbfReceivesNext].Connection = (PVOID)connection;
        NbfReceivesNext = (NbfReceivesNext++) % TRACK_TDI_LIMIT;
#endif

        //
        // If this IRP has been cancelled, complete it now.
        //

        if (Irp->Cancel) {

#if DBG
            NbfCompletedReceives[NbfCompletedReceivesNext].Irp = Irp;
            NbfCompletedReceives[NbfCompletedReceivesNext].Request = NULL;
            NbfCompletedReceives[NbfCompletedReceivesNext].Status = STATUS_CANCELLED;
            {
                ULONG i,j,k;
                PUCHAR va;
                PMDL mdl;

                mdl = Irp->MdlAddress;

                NbfCompletedReceives[NbfCompletedReceivesNext].Contents[0] = (UCHAR)0;

                i = 1;
                while (i<TRACK_TDI_CAPTURE) {
                    if (mdl == NULL) break;
                    va = MmGetSystemAddressForMdl (mdl);
                    j = MmGetMdlByteCount (mdl);

                    for (i=i,k=0;i<TRACK_TDI_CAPTURE&k<j;i++,k++) {
                        NbfCompletedReceives[NbfCompletedReceivesNext].Contents[i] = *va++;
                    }
                    mdl = mdl->Next;
                }
            }

            NbfCompletedReceivesNext = (NbfCompletedReceivesNext++) % TRACK_TDI_LIMIT;
#endif

            //
            // It is safe to do this with locks held.
            //
            NbfCompleteReceiveIrp (Irp, STATUS_CANCELLED, 0);

            RELEASE_DPC_SPIN_LOCK (connection->LinkSpinLock);
            IoReleaseCancelSpinLock(cancelIrql);

        } else {

            //
            // Insert onto the receive queue, and make the IRP
            // cancellable.
            //

            InsertTailList (&connection->ReceiveQueue,&Irp->Tail.Overlay.ListEntry);
            IoSetCancelRoutine(Irp, NbfCancelReceive);

            //
            // Release the cancel spinlock out of order. Since we were
            // already at dpc level when it was acquired, we don't
            // need to swap irqls.
            //
            ASSERT(cancelIrql == DISPATCH_LEVEL);
            IoReleaseCancelSpinLock(cancelIrql);

            //
            // This call releases the link spinlock, and references the
            // connection first if it needs to access it after
            // releasing the lock.
            //

            AwakenReceive (connection);             // awaken if sleeping.

        }

        status = STATUS_PENDING;

    }

    KeLowerIrql (oldirql);

    return status;
} /* TdiReceive */
예제 #11
0
NTSTATUS DispTdiQueryInformation(
  PDEVICE_OBJECT DeviceObject,
  PIRP Irp)
/*
 * FUNCTION: TDI_QUERY_INFORMATION handler
 * ARGUMENTS:
 *     DeviceObject = Pointer to device object structure
 *     Irp          = Pointer to an I/O request packet
 * RETURNS:
 *     Status of operation
 */
{
  PTDI_REQUEST_KERNEL_QUERY_INFORMATION Parameters;
  PTRANSPORT_CONTEXT TranContext;
  PIO_STACK_LOCATION IrpSp;

  TI_DbgPrint(DEBUG_IRP, ("Called.\n"));

  IrpSp = IoGetCurrentIrpStackLocation(Irp);
  Parameters = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters;

  TranContext = IrpSp->FileObject->FsContext;
  if (!TranContext) {
    TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
    return STATUS_INVALID_PARAMETER;
  }

  switch (Parameters->QueryType)
  {
    case TDI_QUERY_ADDRESS_INFO:
      {
        PTDI_ADDRESS_INFO AddressInfo;
        PADDRESS_FILE AddrFile;
        PTA_IP_ADDRESS Address;
        PCONNECTION_ENDPOINT Endpoint = NULL;


        if (MmGetMdlByteCount(Irp->MdlAddress) <
            (FIELD_OFFSET(TDI_ADDRESS_INFO, Address.Address[0].Address) +
             sizeof(TDI_ADDRESS_IP))) {
          TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
          return STATUS_BUFFER_TOO_SMALL;
        }

        AddressInfo = (PTDI_ADDRESS_INFO)MmGetSystemAddressForMdl(Irp->MdlAddress);
		Address = (PTA_IP_ADDRESS)&AddressInfo->Address;

        switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
          case TDI_TRANSPORT_ADDRESS_FILE:
            AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;

			Address->TAAddressCount = 1;
			Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
			Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
			Address->Address[0].Address[0].sin_port = AddrFile->Port;
			Address->Address[0].Address[0].in_addr = AddrFile->Address.Address.IPv4Address;
			RtlZeroMemory(
				&Address->Address[0].Address[0].sin_zero,
				sizeof(Address->Address[0].Address[0].sin_zero));
			return STATUS_SUCCESS;

          case TDI_CONNECTION_FILE:
            Endpoint =
				(PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;

            Address->TAAddressCount = 1;
            Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
            Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
            Address->Address[0].Address[0].sin_port = Endpoint->AddressFile->Port;
            Address->Address[0].Address[0].in_addr = Endpoint->AddressFile->Address.Address.IPv4Address;
			RtlZeroMemory(
				&Address->Address[0].Address[0].sin_zero,
				sizeof(Address->Address[0].Address[0].sin_zero));
            return STATUS_SUCCESS;

          default:
            TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
            return STATUS_INVALID_PARAMETER;
        }
      }

    case TDI_QUERY_CONNECTION_INFO:
      {
        PTDI_CONNECTION_INFO ConnectionInfo;
        //PCONNECTION_ENDPOINT Endpoint;

        if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*ConnectionInfo)) {
          TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
          return STATUS_BUFFER_TOO_SMALL;
        }

        ConnectionInfo = (PTDI_CONNECTION_INFO)
          MmGetSystemAddressForMdl(Irp->MdlAddress);

        switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
          case TDI_CONNECTION_FILE:
            //Endpoint = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
            RtlZeroMemory(ConnectionInfo, sizeof(*ConnectionInfo));
            return STATUS_SUCCESS;

          default:
            TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
            return STATUS_INVALID_PARAMETER;
        }
      }

      case TDI_QUERY_MAX_DATAGRAM_INFO:
      {
          PTDI_MAX_DATAGRAM_INFO MaxDatagramInfo;

          if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*MaxDatagramInfo)) {
              TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
              return STATUS_BUFFER_TOO_SMALL;
          }

          MaxDatagramInfo = (PTDI_MAX_DATAGRAM_INFO)
            MmGetSystemAddressForMdl(Irp->MdlAddress);

          MaxDatagramInfo->MaxDatagramSize = 0xFFFF;

          return STATUS_SUCCESS;
     }
  }

  return STATUS_NOT_IMPLEMENTED;
}
예제 #12
0
파일: rt.c 프로젝트: Gaikokujin/WinNT4
NTSTATUS
RcvIrpFromRt (
    IN  PDEVICE  pDevice,
    IN  PIRP        pIrp
    )
/*++

Routine Description;

    This function takes the rcv irp posted by RT and decides if there are
    any datagram queued waiting to go up to RT.  If so then the datagram
    is copied to the RT buffer and passed back up.  Otherwise the irp is
    held by Netbt until a datagram does come in.

Arguments;

    pDevice  - not used
    pIrp            - Rt Rcv Irp

Return Value;

    STATUS_PENDING if the buffer is to be held on to , the normal case.

Notes;


--*/

{
    NTSTATUS                status;
    PRTRCV_BUFFER            pBuffer;
    PLIST_ENTRY             pEntry;
    CTELockHandle           OldIrq;
    PRT_INFO                pRt;
    PIPX_DATAGRAM_OPTIONS2  pRtBuffer;
    PRT_IRP pRtAF;
    ULONG Index;
#if DBG
    ULONG NoOfRcvIrp;
#endif

   IpxPrint0("RcvIrpfromRt - Entered\n");

   // pRt = REQUEST_OPEN_CONTEXT(pIrp);
   pRt = pRtInfo;

   Index = RT_ADDRESS_INDEX(pIrp);

   IpxPrint1("RcvIrpFromRt: Index = (%d)\n", Index);

   IpxVerifyRt(pRt);
   CTEAssert(pRt && (pRt == pRtInfo));
   CTEAssert(Index < IPX_RT_MAX_ADDRESSES);

   CTEGetLock (&pRt->Lock, &OldIrq);
   do
   {
        pRtAF = &pRt->AddFl[Index];
        if (pRtAF->State != RT_OPEN)
        {
             status = STATUS_INVALID_HANDLE;
             CTEFreeLock (&pRt->Lock, OldIrq);
             break;
        }
        IpxReferenceRt(pRt, RT_IRPIN);

        if (!IsListEmpty(&pRtAF->RcvList))
        {
            PMDL    pMdl;
            ULONG   CopyLength;
            ULONG   UserBufferLengthToPass;
            ULONG   MdlLength;

            //
            // There is at least one datagram waiting to be received
            //
            pEntry = RemoveHeadList(&pRtAF->RcvList);

            pBuffer = (PRTRCV_BUFFER)CONTAINING_RECORD(pEntry,RTRCV_BUFFER,
                                                                  Linkage);

            IpxPrint0("RcvIrpFromRt: Buffer dequeued\n");
            //
            // Copy the datagram and the source address to RT buffer and
            // return to RT
            //
            pMdl = pIrp->MdlAddress;
            IpxPrint2("RcvIrpFromRt: Irp=(%lx); Mdl=(%lx)\n", pIrp, pMdl);
            CTEAssert(pMdl);
            if (!pMdl)
            {
                status = STATUS_BUFFER_TOO_SMALL;
                CTEFreeLock (&pRt->Lock, OldIrq);
                IpxDereferenceRt(pRtInfo, RT_IRPIN);
                break;

            }
            pRtBuffer = MmGetSystemAddressForMdl(pMdl);
            MdlLength = MmGetMdlByteCount(pMdl);

            UserBufferLengthToPass = pBuffer->UserBufferLengthToPass;

            CopyLength = (UserBufferLengthToPass <= MdlLength) ? UserBufferLengthToPass : MdlLength;
            IpxPrint0("RcvIrpFromRt: Copying Options\n");
            RtlCopyMemory((PVOID)pRtBuffer,
                       (PVOID)&pBuffer->Options,
                       CopyLength);

            //
            // subtract from the total amount buffered for RT since we are
            // passing a datagram up to RT now.
            //
            pRtInfo->RcvMemoryAllocated -= pBuffer->TotalAllocSize;
            RtFreeMem(pBuffer, pBuffer->TotalAllocSize);

            CTEAssert(pRtBuffer->DgrmOptions.LocalTarget.NicId);

            //
            // pass the irp up to RT
            //
            if (CopyLength < UserBufferLengthToPass)
            {
                status = STATUS_BUFFER_OVERFLOW;
            }
            else
            {
                status = STATUS_SUCCESS;
            }
#if DBG
            NoOfRcvIrp = pRtAF->NoOfRcvIrps;
#endif

            CTEFreeLock (&pRt->Lock, OldIrq);


            IpxPrint3("Returning Rt rcv Irp immediately with queued dgram, status=%X,pIrp=%X. NoOfRcvIrp=(%d)\n" ,status,pIrp, NoOfRcvIrp);

            pIrp->IoStatus.Information = CopyLength;
            pIrp->IoStatus.Status      = status;
        }
        else
        {

            status = NTCheckSetCancelRoutine(pIrp,RtIrpCancel,pDevice);

            if (!NT_SUCCESS(status))
            {
                CTEFreeLock (&pRt->Lock, OldIrq);
            }
            else
            {
                if (pRtAF->NoOfRcvIrps++ > RT_IRP_MAX)
                {
                     IpxPrint1("RcvIrpFromRt; REACHED LIMIT OF IRPS. NoOfRcvIrp=(%d)\n", pRtAF->NoOfRcvIrps);
                     status = STATUS_INSUFFICIENT_RESOURCES;
                     pRtAF->NoOfRcvIrps--;
                     CTEFreeLock (&pRt->Lock, OldIrq);

                }
                else
                {
                  InsertTailList(&pRtAF->RcvIrpList,REQUEST_LINKAGE(pIrp));
                  IpxPrint2("IpxRt;Holding onto Rt Rcv Irp, pIrp =%Xstatus=%X\n",   status,pIrp);

                  status = STATUS_PENDING;
                  CTEFreeLock(&pRt->Lock,OldIrq);
               }
            }


        }
        IpxDereferenceRt(pRtInfo, RT_IRPIN);
   } while(FALSE);

    IpxPrint0("RcvIrpfromRt - Leaving\n");
    return(status);

}
예제 #13
0
파일: ixhwsup.c 프로젝트: Gaikokujin/WinNT4
VOID
HalpCopyBufferMap(
    IN PMDL Mdl,
    IN PTRANSLATION_ENTRY TranslationEntry,
    IN PVOID CurrentVa,
    IN ULONG Length,
    IN BOOLEAN WriteToDevice
    )

/*++

Routine Description:

    This routine copies the speicific data between the user's buffer and the
    map register buffer.  First a the user buffer is mapped if necessary, then
    the data is copied.  Finally the user buffer will be unmapped if
    neccessary.

Arguments:

    Mdl - Pointer to the MDL that describes the pages of memory that are
        being read or written.

    TranslationEntry - The address of the base map register that has been
        allocated to the device driver for use in mapping the transfer.

    CurrentVa - Current virtual address in the buffer described by the MDL
        that the transfer is being done to or from.

    Length - The length of the transfer.  This determines the number of map
        registers that need to be written to map the transfer.

    WriteToDevice - Boolean value that indicates whether this is a write
        to the device from memory (TRUE), or vice versa.

Return Value:

    None.

--*/
{
    PCCHAR bufferAddress;
    PCCHAR mapAddress;

    //
    // Get the system address of the MDL.
    //

    bufferAddress = MmGetSystemAddressForMdl(Mdl);

    //
    // Calculate the actual start of the buffer based on the system VA and
    // the current VA.
    //

    bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);

    mapAddress = (PCCHAR) TranslationEntry->VirtualAddress +
        BYTE_OFFSET(CurrentVa);

    //
    // Copy the data between the user buffer and map buffer
    //

    if (WriteToDevice) {

        RtlMoveMemory( mapAddress, bufferAddress, Length);

    } else {

        RtlMoveMemory(bufferAddress, mapAddress, Length);

    }

}
예제 #14
0
//this function is called by the hcd's
//dispatch when they have done their job.
NTSTATUS
dev_mgr_dispatch(IN PUSB_DEV_MANAGER dev_mgr, IN PIRP irp)
{
    PIO_STACK_LOCATION irp_stack;
    NTSTATUS status;
    ULONG ctrl_code;
    USE_NON_PENDING_IRQL;

    ASSERT(irp);
    if (dev_mgr == NULL)
    {
        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
    }

    status = STATUS_SUCCESS;
    irp_stack = IoGetCurrentIrpStackLocation(irp);
    ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;

    switch (irp_stack->MajorFunction)
    {
    case IRP_MJ_CREATE:
        {
            InterlockedIncrement(&dev_mgr->open_count);
            EXIT_DISPATCH(STATUS_SUCCESS, irp);
        }
    case IRP_MJ_CLOSE:
        {
            InterlockedDecrement(&dev_mgr->open_count);
            EXIT_DISPATCH(STATUS_SUCCESS, irp);
        }
    case IRP_MJ_INTERNAL_DEVICE_CONTROL:
    case IRP_MJ_DEVICE_CONTROL:
        {
            switch (ctrl_code)
            {
            case IOCTL_GET_DEV_COUNT:
                {
                    LONG dev_count;

                    irp->IoStatus.Information = 0;
                    if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
                    dev_count = usb_count_list(&dev_mgr->dev_list);
                    KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);

                    *((PLONG) irp->AssociatedIrp.SystemBuffer) = dev_count;
                    irp->IoStatus.Information = sizeof(LONG);
                    EXIT_DISPATCH(STATUS_SUCCESS, irp);
                }
            case IOCTL_ENUM_DEVICES:
                {
                    PLIST_ENTRY pthis, pnext;
                    LONG dev_count, array_size, i, j = 0;
                    PUSB_DEV pdev;
                    PENUM_DEV_ARRAY peda;

                    irp->IoStatus.Information = 0;
                    if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(LONG))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }
                    if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ENUM_DEV_ARRAY))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }
                    array_size = *((PULONG) irp->AssociatedIrp.SystemBuffer);

                    KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
                    dev_count = usb_count_list(&dev_mgr->dev_list);
                    dev_count = dev_count > array_size ? array_size : dev_count;
                    peda = (PENUM_DEV_ARRAY) irp->AssociatedIrp.SystemBuffer;
                    RtlZeroMemory(peda, sizeof(ENUM_DEV_ARRAY) + (dev_count - 1) * sizeof(ENUM_DEV_ELEMENT));

                    if (dev_count)
                    {
                        ListFirst(&dev_mgr->dev_list, pthis);
                        for(i = 0, j = 0; i < dev_count; i++)
                        {
                            pdev = struct_ptr(pthis, USB_DEV, dev_link);
                            ListNext(&dev_mgr->dev_list, pthis, pnext);
                            pthis = pnext;

                            lock_dev(pdev, FALSE);
                            if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
                            {
                                unlock_dev(pdev, FALSE);
                                continue;
                            }

                            if (dev_state(pdev) < USB_DEV_STATE_ADDRESSED)
                            {
                                unlock_dev(pdev, FALSE);
                                continue;
                            }

                            peda->dev_arr[i].dev_handle = (pdev->dev_id << 16);
                            //may not get the desc yet
                            if (pdev->pusb_dev_desc)
                            {
                                peda->dev_arr[i].product_id = pdev->pusb_dev_desc->idProduct;
                                peda->dev_arr[i].vendor_id = pdev->pusb_dev_desc->idVendor;
                            }
                            else
                            {
                                peda->dev_arr[i].product_id = 0xffff;
                                peda->dev_arr[i].vendor_id = 0xffff;
                            }
                            peda->dev_arr[i].dev_addr = pdev->dev_addr;
                            unlock_dev(pdev, FALSE);
                            j++;
                        }
                    }
                    peda->dev_count = dev_count ? j : 0;
                    KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);

                    irp->IoStatus.Information =
                        sizeof(ENUM_DEV_ARRAY) + (dev_count - 1) * sizeof(ENUM_DEV_ELEMENT);
                    EXIT_DISPATCH(STATUS_SUCCESS, irp);
                }
            case IOCTL_GET_DEV_DESC:
                {
                    GET_DEV_DESC_REQ gddr;
                    PUSB_DESC_HEADER pusb_desc_header;
                    PUSB_DEV pdev;
                    LONG buf_size;

                    if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(GET_DEV_DESC_REQ))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < 8)
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    status = STATUS_SUCCESS;
                    buf_size = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
                    RtlCopyMemory(&gddr, irp->AssociatedIrp.SystemBuffer, sizeof(GET_DEV_DESC_REQ));
                    pusb_desc_header = irp->AssociatedIrp.SystemBuffer;

                    if (gddr.desc_type != USB_DT_CONFIG && gddr.desc_type != USB_DT_DEVICE)
                    {
                        EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
                    }

                    if (usb_query_and_lock_dev(dev_mgr, gddr.dev_handle, &pdev) != STATUS_SUCCESS)
                    {
                        EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR, irp);
                    }

                    lock_dev(pdev, FALSE);
                    if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
                    {
                        status = STATUS_INVALID_DEVICE_STATE;
                        goto ERROR_OUT;
                    }
                    if (dev_state(pdev) != USB_DEV_STATE_ADDRESSED &&
                        dev_state(pdev) != USB_DEV_STATE_CONFIGURED)
                    {
                        status = STATUS_DEVICE_NOT_READY;
                        goto ERROR_OUT;
                    }

                    if (pdev->pusb_dev_desc == NULL)
                    {
                        status = STATUS_DEVICE_NOT_READY;
                        goto ERROR_OUT;
                    }

                    if (gddr.desc_type == USB_DT_DEVICE)
                    {
                        RtlCopyMemory(pusb_desc_header,
                                      pdev->pusb_dev_desc,
                                      buf_size > sizeof(USB_DEVICE_DESC)
                                      ? sizeof(USB_DEVICE_DESC) : buf_size);

                        irp->IoStatus.Information =
                            buf_size >= sizeof(USB_DEVICE_DESC) ? sizeof(USB_DEVICE_DESC) : buf_size;
                    }
                    else if (gddr.desc_type == USB_DT_CONFIG)
                    {
                        PUSB_CONFIGURATION_DESC pusb_config_desc;
                        if (pdev->pusb_dev_desc->bNumConfigurations <= gddr.desc_idx)
                        {
                            status = STATUS_INVALID_PARAMETER;
                            goto ERROR_OUT;
                        }

                        pusb_config_desc = usb_find_config_desc_by_idx((PUCHAR) & pdev->pusb_dev_desc[1],
                                                                       gddr.desc_idx,
                                                                       pdev->pusb_dev_desc->
                                                                       bNumConfigurations);

                        if (pusb_config_desc == NULL)
                        {
                            status = STATUS_DEVICE_NOT_READY;
                            goto ERROR_OUT;
                        }

                        RtlCopyMemory(pusb_desc_header,
                                      pusb_config_desc,
                                      buf_size >= pusb_config_desc->wTotalLength
                                      ? pusb_config_desc->wTotalLength : buf_size);

                        irp->IoStatus.Information =
                            buf_size >= pusb_config_desc->wTotalLength
                            ? pusb_config_desc->wTotalLength : buf_size;
                    }
                  ERROR_OUT:
                    unlock_dev(pdev, FALSE);
                    usb_unlock_dev(pdev);
                    EXIT_DISPATCH(status, irp);
                }
            case IOCTL_SUBMIT_URB_RD:
            case IOCTL_SUBMIT_URB_WR:
            case IOCTL_SUBMIT_URB_NOIO:
                {
                    PURB purb;
                    ULONG endp_idx, if_idx, user_buffer_length = 0;
                    PUCHAR user_buffer = NULL;
                    PUSB_DEV pdev;
                    DEV_HANDLE endp_handle;
                    PUSB_ENDPOINT pendp;

                    if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    purb = (PURB) irp->AssociatedIrp.SystemBuffer;
                    endp_handle = purb->endp_handle;

                    if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR)
                    {
                        if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
                        {
                            user_buffer_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
                            if (user_buffer_length == 0)
                                EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                            user_buffer = MmGetSystemAddressForMdl(irp->MdlAddress);
                        }
                        else
                        {
                            if (purb->data_buffer == NULL || purb->data_length == 0)
                                EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                            user_buffer_length = purb->data_length;
                            user_buffer = purb->data_buffer;
                        }
                    }

                    if (usb_query_and_lock_dev(dev_mgr, endp_handle & ~0xffff, &pdev) != STATUS_SUCCESS)
                    {
                        EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR, irp);
                    }


                    lock_dev(pdev, FALSE);
                    if (dev_state(pdev) == USB_DEV_STATE_ZOMB || (dev_state(pdev) < USB_DEV_STATE_ADDRESSED))

                    {
                        status = STATUS_INVALID_DEVICE_STATE;
                        goto ERROR_OUT1;
                    }

                    if (dev_state(pdev) == USB_DEV_STATE_ADDRESSED && !default_endp_handle(endp_handle))
                    {
                        status = STATUS_DEVICE_NOT_READY;
                        goto ERROR_OUT1;
                    }

                    if_idx = if_idx_from_handle(endp_handle);
                    endp_idx = endp_idx_from_handle(endp_handle);

                    //if_idx exceeds the upper limit
                    if (pdev->usb_config)
                    {
                        if (if_idx >= pdev->usb_config->if_count
                            || endp_idx >= pdev->usb_config->interf[if_idx].endp_count)
                        {
                            if (!default_endp_handle(endp_handle))
                            {
                                status = STATUS_INVALID_DEVICE_STATE;
                                goto ERROR_OUT1;
                            }
                        }
                    }

                    endp_from_handle(pdev, endp_handle, pendp);
                    // FIXME: don't know what evil will let loose
                    if (endp_type(pendp) != USB_ENDPOINT_XFER_CONTROL)
                    {
                        if (user_buffer_length > 0x100000)
                        {
                            status = STATUS_INVALID_PARAMETER;
                            goto ERROR_OUT1;
                        }
                    }

                    purb->pirp = irp;
                    purb->context = dev_mgr;
                    purb->reference = ctrl_code;

                    if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR)
                    {
                        if (ctrl_code == IOCTL_SUBMIT_URB_RD)
                            KeFlushIoBuffers(irp->MdlAddress, TRUE, TRUE);
                        else
                            KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);

                        purb->data_buffer = user_buffer;
                        purb->data_length = user_buffer_length;
                        purb->completion = disp_urb_completion;
                    }
                    else
                    {
                        purb->completion = disp_noio_urb_completion;
                    }

                    unlock_dev(pdev, FALSE);

                    // we have to mark irp before the urb is scheduled to
                    // avoid race condition
                    IoMarkIrpPending(irp);
                    ASSERT(dev_mgr_register_irp(dev_mgr, irp, purb));
                    status = usb_submit_urb(dev_mgr, purb);
                    if (status != STATUS_PENDING)
                    {
                        IoGetCurrentIrpStackLocation((irp))->Control &= ~SL_PENDING_RETURNED;
                        dev_mgr_remove_irp(dev_mgr, irp);
                    }
                    usb_unlock_dev(pdev);
                    if (status != STATUS_PENDING)
                    {
                        irp->IoStatus.Status = status;
                        IoCompleteRequest(irp, IO_NO_INCREMENT);
                    }
                    return status;
                  ERROR_OUT1:
                    unlock_dev(pdev, FALSE);
                    usb_unlock_dev(pdev);
                    irp->IoStatus.Information = 0;
                    EXIT_DISPATCH(status, irp);
                }
            default:
                {
                    irp->IoStatus.Information = 0;
                    EXIT_DISPATCH(STATUS_NOT_IMPLEMENTED, irp);
                }
            }
        }
    default:
        {
            irp->IoStatus.Information = 0;
            break;
        }
    }
    EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
}
예제 #15
0
VOID
NbfActionQueryIndication(
    IN PDEVICE_CONTEXT DeviceContext,
    IN PNBF_HDR_CONNECTIONLESS UiFrame
)

/*++

Routine Description:

    This routine is called after a UI frame of type NAME_QUERY,
    ADD_NAME_QUERY, or ADD_GROUP_NAME_QUERY has been processed.
    It checks if there is a QUERY.INDICATION IRP waiting to
    be completed, and if so completes it.

Arguments:

    DeviceContext - Pointer to our device context.

    UiFrame - Pointer to the incoming frame. The first byte of
        information is the first byte of the NetBIOS connectionless
        header.

Return Value:

    None

--*/

{
    KIRQL oldirql, cancelirql;
    PTP_REQUEST Request;
    PLIST_ENTRY p;
    PMDL Mdl;
    PACTION_QUERY_INDICATION ActionHeader;
    PQUERY_INDICATION QueryIndication;


    IoAcquireCancelSpinLock (&cancelirql);
    ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);

    if (!IsListEmpty (&DeviceContext->QueryIndicationQueue)) {

        p = RemoveHeadList (&DeviceContext->QueryIndicationQueue);
        RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);

        Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
        IoSetCancelRoutine(Request->IoRequestPacket,NULL);
        IoReleaseCancelSpinLock(cancelirql);

        Mdl = Request->Buffer2;
        ActionHeader = (PACTION_QUERY_INDICATION)
                       (MmGetSystemAddressForMdl(Mdl));
        QueryIndication = &ActionHeader->QueryIndication;

        //
        // Copy over data from frame (note that dest and source
        // address are copied with one call).
        //

        QueryIndication->Command = UiFrame->Command;
        RtlCopyMemory ((PUCHAR)(&QueryIndication->Data2), (PUCHAR)(&UiFrame->Data2Low), 2);
        RtlCopyMemory ((PUCHAR)(QueryIndication->DestinationName),
                       (PUCHAR)(UiFrame->DestinationName),
                       2 * NETBIOS_NAME_LENGTH);

        NbfCompleteRequest (Request, STATUS_SUCCESS, sizeof(ACTION_QUERY_INDICATION));

    } else {

        RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
        IoReleaseCancelSpinLock(cancelirql);

    }
}
예제 #16
0
NTSTATUS
LpxTdiQueryInformation(
    IN PDEVICE_CONTEXT DeviceContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the TdiQueryInformation request for the transport
    provider.

Arguments:

    Irp - the Irp for the requested operation.

Return Value:

    NTSTATUS - status of operation.

--*/

{
    NTSTATUS status;
    PIO_STACK_LOCATION irpSp;
    PTDI_REQUEST_KERNEL_QUERY_INFORMATION query;
    PTA_NETBIOS_ADDRESS broadcastAddress;
    PTDI_PROVIDER_STATISTICS ProviderStatistics;
    PTDI_CONNECTION_INFO ConnectionInfo;
    ULONG TargetBufferLength;
	LARGE_INTEGER timeout = {0,0};
    PTP_CONNECTION Connection;
    PTP_ADDRESS_FILE AddressFile;
    PTP_ADDRESS Address;
    struct {
        ULONG ActivityCount;
        TA_NETBIOS_ADDRESS TaAddressBuffer;
    } AddressInfo;
    PTRANSPORT_ADDRESS TaAddress;
    TDI_DATAGRAM_INFO DatagramInfo;
    BOOLEAN UsedConnection;
    PLIST_ENTRY p;
    KIRQL oldirql;
    ULONG BytesCopied;

    //
    // what type of status do we want?
    //

    irpSp = IoGetCurrentIrpStackLocation (Irp);

    query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&irpSp->Parameters;

    switch (query->QueryType) {

#if 0
    case 0x12345678:

        {
            typedef struct _LPX_CONNECTION_STATUS {
                UCHAR LocalName[16];
                UCHAR RemoteName[16];
                BOOLEAN SendActive;
                BOOLEAN ReceiveQueued;
                BOOLEAN ReceiveActive;
                BOOLEAN ReceiveWakeUp;
                ULONG Flags;
                ULONG Flags2;
            } LPX_CONNECTION_STATUS, *PLPX_CONNECTION_STATUS;

            PLPX_CONNECTION_STATUS CurStatus;
            ULONG TotalStatus;
            ULONG AllowedStatus;
            PLIST_ENRY q;

            CurStatus = MmGetSystemAddressForMdl (Irp->MdlAddress);
            TotalStatus = 0;
            AllowedStatus = MmGetMdlByteCount (Irp->MdlAddress) / sizeof(LPX_CONNECTION_STATUS);

            for (p = DeviceContext->AddressDatabase.Flink;
                 p != &DeviceContext->AddressDatabase;
                 p = p->Flink) {

                Address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);

                if ((Address->Flags & ADDRESS_FLAGS_STOPPING) != 0) {
                    continue;
                }

                for (q = Address->ConnectionDatabase.Flink;
                     q != &Address->ConnectionDatabase;
                     q = q->Flink) {

                    Connection = CONTAINING_RECORD (q, TP_CONNECTION, AddressList);

                    if ((Connection->Flags & CONNECTION_FLAGS_READY) == 0) {
                        continue;
                    }

                    if (TotalStatus >= AllowedStatus) {
                        continue;
                    }

                    RtlMoveMemory (CurStatus->LocalName, Address->NetworkName->NetbiosName, 16);
                    RtlMoveMemory (CurStatus->RemoteName, Connection->RemoteName, 16);

                    CurStatus->Flags = Connection->Flags;
                    CurStatus->Flags2 = Connection->Flags2;
                    CurStatus->SendActive = (BOOLEAN)(!IsListEmpty(&Connection->SendQueue));
                    CurStatus->ReceiveQueued = (BOOLEAN)(!IsListEmpty(&Connection->ReceiveQueue));
                    CurStatus->ReceiveActive = (BOOLEAN)((Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE) != 0);
                    CurStatus->ReceiveWakeUp = (BOOLEAN)((Connection->Flags & CONNECTION_FLAGS_RECEIVE_WAKEUP) != 0);

                    ++CurStatus;
                    ++TotalStatus;

                }
            }

            Irp->IoStatus.Information = TotalStatus * sizeof(LPX_CONNECTION_STATUS);
            status = STATUS_SUCCESS;

        }

        break;
#endif

    case TDI_QUERY_CONNECTION_INFO:

        //
        // Connection info is queried on a connection,
        // verify this.
        //

        if (irpSp->FileObject->FsContext2 != (PVOID) TDI_CONNECTION_FILE) {

			ASSERT( FALSE );
            return STATUS_INVALID_CONNECTION;
        }

        Connection = irpSp->FileObject->FsContext;

        status = LpxVerifyConnectionObject (Connection);

        if (!NT_SUCCESS (status)) {

			ASSERT( FALSE );
#if DBG
            LpxPrint2 ("TdiQueryInfo: Invalid Connection %p Irp %p\n", Connection, Irp);
#endif
            return status;
        }

        ConnectionInfo = ExAllocatePoolWithTag (
                             NonPagedPool,
                             sizeof (TDI_CONNECTION_INFO),
                             LPX_MEM_TAG_TDI_CONNECTION_INFO);

        if (ConnectionInfo == NULL) {

            PANIC ("LpxQueryInfo: Cannot allocate connection info!\n");
            LpxWriteResourceErrorLog(
                DeviceContext,
                EVENT_TRANSPORT_RESOURCE_POOL,
                6,
                sizeof(TDI_CONNECTION_INFO),
                0);
            status = STATUS_INSUFFICIENT_RESOURCES;

#if __LPX__

		} else {

			LARGE_INTEGER	delay;

            RtlZeroMemory ((PVOID)ConnectionInfo, sizeof(TDI_CONNECTION_INFO));

			ConnectionInfo->Event;
			ConnectionInfo->TransmittedTsdus	= Connection->LpxSmp.NumberOfSendPackets; 
			ConnectionInfo->ReceivedTsdus		= Connection->LpxSmp.NumberofRecvPackets; 
			ConnectionInfo->TransmissionErrors	= Connection->LpxSmp.NumberOfSendRetransmission; 
			ConnectionInfo->ReceiveErrors		= Connection->LpxSmp.DropOfReceivePacket; 

			if (Connection->LpxSmp.ResponseTimeOfLargeSendRequests.QuadPart) {

				ConnectionInfo->Throughput.QuadPart	= 
					Connection->LpxSmp.BytesOfLargeSendRequests.QuadPart * 1000 * 1000 * 10 / 
					Connection->LpxSmp.ResponseTimeOfLargeSendRequests.QuadPart; 			
			
			} else if (Connection->LpxSmp.ResponseTimeOfSmallSendRequests.QuadPart) {

				ConnectionInfo->Throughput.QuadPart	= 
					Connection->LpxSmp.BytesOfSmallSendRequests.QuadPart * 1000 * 1000 * 10 / 
					Connection->LpxSmp.ResponseTimeOfSmallSendRequests.QuadPart; 			
			}			

			if (Connection->LpxSmp.NumberofSmallSendRequests) {
		
				delay.QuadPart = Connection->LpxSmp.ResponseTimeOfSmallSendRequests.QuadPart / Connection->LpxSmp.NumberofSmallSendRequests;	
				ConnectionInfo->Delay.HighPart = -1L;
				ConnectionInfo->Delay.LowPart = (ULONG) - ((LONG)(delay.LowPart));	// 100 ns
			}
			ConnectionInfo->SendBufferSize; 
			ConnectionInfo->ReceiveBufferSize; 
			ConnectionInfo->Unreliable; 

			status = TdiCopyBufferToMdl (
                            (PVOID)ConnectionInfo,
                            0L,
                            sizeof(TDI_CONNECTION_INFO),
                            Irp->MdlAddress,
                            0,
                            &BytesCopied);

            Irp->IoStatus.Information = BytesCopied;

            ExFreePool (ConnectionInfo);
		}

#endif

        LpxDereferenceConnection ("query connection info", Connection, CREF_BY_ID);

        break;
	case LPXTDI_QUERY_CONNECTION_TRANSSTAT: {
		TRANS_STAT	transStat;

		//
		// Connection info is queried on a connection,
		// verify this.
		//

		if (irpSp->FileObject->FsContext2 != (PVOID) TDI_CONNECTION_FILE) {

			ASSERT( FALSE );
			return STATUS_INVALID_CONNECTION;
		}

		Connection = irpSp->FileObject->FsContext;

		status = LpxVerifyConnectionObject (Connection);

		if (!NT_SUCCESS (status)) {

			ASSERT( FALSE );
#if DBG
			LpxPrint2 ("TdiTransStat: Invalid Connection %p Irp %p\n", Connection, Irp);
#endif
			return status;
		}

		transStat.PacketLoss = InterlockedExchange(&Connection->LpxSmp.TransportStats.PacketLoss, 0);
		transStat.Retransmits = InterlockedExchange(&Connection->LpxSmp.TransportStats.Retransmits, 0);

		status = TdiCopyBufferToMdl (
                            &transStat,
                            0L,
                            sizeof(TRANS_STAT),
                            Irp->MdlAddress,
                            0,
                            &BytesCopied);

		Irp->IoStatus.Information = BytesCopied;

		LpxDereferenceConnection ("query connection info", Connection, CREF_BY_ID);
		break;
	}
    case TDI_QUERY_ADDRESS_INFO:

        if (irpSp->FileObject->FsContext2 == (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {

            AddressFile = irpSp->FileObject->FsContext;

            status = LpxVerifyAddressObject(AddressFile);

            if (!NT_SUCCESS (status)) {
#if DBG
                LpxPrint2 ("TdiQueryInfo: Invalid AddressFile %p Irp %p\n", AddressFile, Irp);
#endif
                return status;
            }

            UsedConnection = FALSE;

        } else if (irpSp->FileObject->FsContext2 == (PVOID)TDI_CONNECTION_FILE) {

            Connection = irpSp->FileObject->FsContext;

            status = LpxVerifyConnectionObject (Connection);

            if (!NT_SUCCESS (status)) {
#if DBG
                LpxPrint2 ("TdiQueryInfo: Invalid Connection %p Irp %p\n", Connection, Irp);
#endif
                return status;
            }

            AddressFile = Connection->AddressFile;

            UsedConnection = TRUE;

        } else {

            return STATUS_INVALID_ADDRESS;

        }

        Address = AddressFile->Address;
#if 0
        TdiBuildNetbiosAddress(
            Address->NetworkName->NetbiosName,
            (BOOLEAN)(Address->Flags & ADDRESS_FLAGS_GROUP ? TRUE : FALSE),
            &AddressInfo.TaAddressBuffer);
#else
		TdiBuildNetbiosAddress(
            Address->NetworkName->Node,
            FALSE,
            &AddressInfo.TaAddressBuffer);
#endif
        //
        // Count the active addresses.
        //

        AddressInfo.ActivityCount = 0;

        ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);

        for (p = Address->AddressFileDatabase.Flink;
             p != &Address->AddressFileDatabase;
             p = p->Flink) {
            ++AddressInfo.ActivityCount;
        }

        RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);

        status = TdiCopyBufferToMdl (
                    &AddressInfo,
                    0,
                    sizeof(ULONG) + sizeof(TA_NETBIOS_ADDRESS),
                    Irp->MdlAddress,
                    0,                    
                    &BytesCopied);

        Irp->IoStatus.Information = BytesCopied;

        if (UsedConnection) {

            LpxDereferenceConnection ("query address info", Connection, CREF_BY_ID);

        } else {

            LpxDereferenceAddress ("query address info", Address, AREF_VERIFY);

        }

        break;

    case TDI_QUERY_BROADCAST_ADDRESS:

        //
        // for this provider, the broadcast address is a zero byte name,
        // contained in a Transport address structure.
        //

        broadcastAddress = ExAllocatePoolWithTag (
                                NonPagedPool,
                                sizeof (TA_NETBIOS_ADDRESS),
                                LPX_MEM_TAG_TDI_QUERY_BUFFER);
        if (broadcastAddress == NULL) {
            PANIC ("LpxQueryInfo: Cannot allocate broadcast address!\n");
            LpxWriteResourceErrorLog(
                DeviceContext,
                EVENT_TRANSPORT_RESOURCE_POOL,
                2,
                sizeof(TA_NETBIOS_ADDRESS),
                0);
            status = STATUS_INSUFFICIENT_RESOURCES;
        } else {

            broadcastAddress->TAAddressCount = 1;
            broadcastAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
            broadcastAddress->Address[0].AddressLength = 0;

            Irp->IoStatus.Information =
                    sizeof (broadcastAddress->TAAddressCount) +
                    sizeof (broadcastAddress->Address[0].AddressType) +
                    sizeof (broadcastAddress->Address[0].AddressLength);

            BytesCopied = (ULONG)Irp->IoStatus.Information;

            status = TdiCopyBufferToMdl (
                            (PVOID)broadcastAddress,
                            0L,
                            BytesCopied,
                            Irp->MdlAddress,
                            0,
                            &BytesCopied);
                            
            Irp->IoStatus.Information = BytesCopied;

            ExFreePool (broadcastAddress);
        }

        break;

    case TDI_QUERY_PROVIDER_INFO:

        status = TdiCopyBufferToMdl (
                    &(DeviceContext->Information),
                    0,
                    sizeof (TDI_PROVIDER_INFO),
                    Irp->MdlAddress,
                    0,
                    &BytesCopied);

        Irp->IoStatus.Information = BytesCopied;

        break;

    case TDI_QUERY_PROVIDER_STATISTICS:

        //
        // This information is probablt available somewhere else.
        //

        LpxGetMdlChainLength (Irp->MdlAddress, &TargetBufferLength);

        if (TargetBufferLength < sizeof(TDI_PROVIDER_STATISTICS) + ((LPX_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS))) {

            Irp->IoStatus.Information = 0;
            status = STATUS_BUFFER_OVERFLOW;

        } else {

            ProviderStatistics = ExAllocatePoolWithTag(
                                   NonPagedPool,
                                   sizeof(TDI_PROVIDER_STATISTICS) +
                                     ((LPX_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS)),
                                   LPX_MEM_TAG_TDI_PROVIDER_STATS);

            if (ProviderStatistics == NULL) {

                PANIC ("LpxQueryInfo: Cannot allocate provider statistics!\n");
                LpxWriteResourceErrorLog(
                    DeviceContext,
                    EVENT_TRANSPORT_RESOURCE_POOL,
                    7,
                    sizeof(TDI_PROVIDER_STATISTICS),
                    0);
                status = STATUS_INSUFFICIENT_RESOURCES;

            } else {

                LpxStoreProviderStatistics (DeviceContext, ProviderStatistics);

                status = TdiCopyBufferToMdl (
                                (PVOID)ProviderStatistics,
                                0L,
                                sizeof(TDI_PROVIDER_STATISTICS) +
                                  ((LPX_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS)),
                                Irp->MdlAddress,
                                0,
                                &BytesCopied);

                Irp->IoStatus.Information = BytesCopied;

                ExFreePool (ProviderStatistics);
            }

        }

        break;

    case TDI_QUERY_SESSION_STATUS:

        status = STATUS_NOT_IMPLEMENTED;
        break;

    case TDI_QUERY_ADAPTER_STATUS:

		ASSERT( FALSE );
		status = STATUS_NOT_IMPLEMENTED;

		break;

    case TDI_QUERY_FIND_NAME:

		ASSERT( FALSE );
		status = STATUS_NOT_IMPLEMENTED;

        break;

    case TDI_QUERY_DATA_LINK_ADDRESS:
    case TDI_QUERY_NETWORK_ADDRESS:

        TaAddress = (PTRANSPORT_ADDRESS)&AddressInfo.TaAddressBuffer;
        TaAddress->TAAddressCount = 1;
        TaAddress->Address[0].AddressLength = 6;
        if (query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS) {
            TaAddress->Address[0].AddressType =
                DeviceContext->MacInfo.MediumAsync ?
                    NdisMediumWan : DeviceContext->MacInfo.MediumType;
        } else {
            TaAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_UNSPEC;
        }
        RtlCopyMemory (TaAddress->Address[0].Address, DeviceContext->LocalAddress.Address, 6);

        status = TdiCopyBufferToMdl (
                    &AddressInfo.TaAddressBuffer,
                    0,
                    sizeof(TRANSPORT_ADDRESS)+5,
                    Irp->MdlAddress,
                    0,
                    &BytesCopied);
                        
        Irp->IoStatus.Information = BytesCopied;
        break;

    case TDI_QUERY_DATAGRAM_INFO:

        DatagramInfo.MaximumDatagramBytes = 0;
        DatagramInfo.MaximumDatagramCount = 0;

        status = TdiCopyBufferToMdl (
                    &DatagramInfo,
                    0,
                    sizeof(DatagramInfo),
                    Irp->MdlAddress,
                    0,
                    &BytesCopied);
                        
        Irp->IoStatus.Information = BytesCopied;
        break;

    default:
        status = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    return status;

} /* LpxTdiQueryInformation */
예제 #17
0
파일: rt.c 프로젝트: Gaikokujin/WinNT4
//----------------------------------------------------------------------------
NTSTATUS
PassDgToRt (
    IN PDEVICE                  pDevice,
    IN PIPX_DATAGRAM_OPTIONS2   pContext,
    IN ULONG                    Index,
    IN VOID UNALIGNED           *pDgrm,
    IN ULONG                    uNumBytes
    )
/*++

Routine Description;

    This function is used to allow NBT to pass name query service Pdu's to
    RT.  Rt posts a Rcv irp to Netbt.  If the Irp is here then simply
    copy the data to the irp and return it, otherwise buffer the data up
    to a maximum # of bytes. Beyond that limit the datagrams are discarded.

    If Retstatus is not success then the pdu will also be processed by
    nbt. This allows nbt to process packets when wins pauses and
    its list of queued buffers is exceeded.

Arguments;

    pDevice  - card that the request can in on
    pSrcAddress     - source address
    pDgrm        - ptr to the datagram
    uNumBytes       - length of datagram

Return Value;

    STATUS_PENDING if the buffer is to be held on to , the normal case.

Notes;


--*/

{
    NTSTATUS                status;
    PIPX_DATAGRAM_OPTIONS2  pRtBuffer;
    PIRP                    pIrp;
    CTELockHandle           OldIrq;


    IpxPrint0("PassDgToRt - Entered\n");

    //
    // Get the source port and ip address, since RT needs this information.
    //
    IpxPrint1("PassDgToRt: Index = (%d)\n", Index);
    CTEGetLock(&pRtInfo->Lock,&OldIrq);

    do
    {
        PRT_IRP pRtAF = &pRtInfo->AddFl[Index];
        if (pRtAF->State != RT_OPEN)
        {
          CTEFreeLock(&pRtInfo->Lock,OldIrq);
          break;
        }
        IpxReferenceRt(pRtInfo, RT_BUFF);
        if (IsListEmpty(&pRtAF->RcvIrpList))
        {
            IpxPrint0("PassDgToRt: No Rcv Irp\n");
            if (pRtInfo->RcvMemoryAllocated < pRtInfo->RcvMemoryMax)
            {
                PRTRCV_BUFFER    pBuffer;

                pBuffer = RtAllocMem(uNumBytes + sizeof(RTRCV_BUFFER));
                if (pBuffer)
                {
                    pBuffer->TotalAllocSize = uNumBytes + sizeof(RTRCV_BUFFER);

                    //
                    // Copy the user data
                    //
                    RtlCopyMemory(
                      (PUCHAR)((PUCHAR)pBuffer + OFFSET_PKT_IN_RCVBUFF),
                                (PVOID)pDgrm,uNumBytes);


                    pBuffer->Options.DgrmOptions.LocalTarget.NicId =
                             pContext->DgrmOptions.LocalTarget.NicId;
                    pBuffer->Options.LengthOfExtraOpInfo = 0;

                    //
                    // total amount allocated for user
                    //
                    pBuffer->UserBufferLengthToPass = uNumBytes + OFFSET_PKT_IN_OPTIONS;

                    CTEAssert(pContext->DgrmOptions.LocalTarget.NicId);
                    IpxPrint2("PassDgToRt: Nic Id is (%d). BufferLength is (%lx)\n", pContext->DgrmOptions.LocalTarget.NicId, uNumBytes);



                    //
                    // Keep track of the total amount buffered so that we don't
                    // eat up all non-paged pool buffering for RT
                    //
                    pRtInfo->RcvMemoryAllocated += pBuffer->TotalAllocSize;

                    IpxPrint0("IpxRt;Buffering Rt Rcv - no Irp, status=%X\n");
                    InsertTailList(&pRtAF->RcvList,&pBuffer->Linkage);
                    IpxPrint0("PassDgToRt: Buffer Queued\n");
                    status = STATUS_SUCCESS;
                }
                else
                {
                  IpxPrint0("PassDgToRt; Could not allocate buffer\n");
                  status = STATUS_INSUFFICIENT_RESOURCES;
                }
            }
            else
            {
                // this ret status will allow netbt to process the packet.
                //
                IpxPrint0("PassDgToRt; Dropping Pkt\n");
                status = STATUS_INSUFFICIENT_RESOURCES;
            }
            CTEFreeLock(&pRtInfo->Lock,OldIrq);
        }
        else
        {
            PMDL    pMdl;
            ULONG   CopyLength;
            ULONG   DgrmLength;
            ULONG   MdlBufferLength;
            ULONG   BytesToCopy;
            PLIST_ENTRY pLE;

            //
            // The recv irp is here so copy the data to its buffer and
            // pass it up to RT
            //
            pLE = RemoveHeadList(&pRtAF->RcvIrpList);
            pIrp = CONTAINING_RECORD(pLE, IRP, Tail.Overlay.ListEntry);

            (*(REQUEST_LINKAGE(pIrp))).Flink = NULL;
            (*(REQUEST_LINKAGE(pIrp))).Blink = NULL;

            //
            // Copy the datagram and the source address to RT buffer and
            // return to RT
            //
            pMdl = pIrp->MdlAddress;
            IpxPrint2("PassDgToRt: Irp=(%lx); Mdl=(%lx)\n", pIrp, pMdl);
            CTEAssert(pMdl);

            pRtBuffer = MmGetSystemAddressForMdl(pIrp->MdlAddress);

            MdlBufferLength = MmGetMdlByteCount(pMdl);
            DgrmLength  = uNumBytes;
            BytesToCopy = DgrmLength + OFFSET_PKT_IN_OPTIONS;

            CopyLength = (BytesToCopy <= MdlBufferLength) ? BytesToCopy : MdlBufferLength;
            IpxPrint2("PassDgToRt: Copy Length = (%d); Mdl Buffer Length is (%d)\n", CopyLength, MdlBufferLength);

            //
            // Copy user datagram into pRtBuffer
            //
            RtlCopyMemory((PVOID)((PUCHAR)pRtBuffer + OFFSET_PKT_IN_OPTIONS),
                       (PVOID)pDgrm,
                       CopyLength-OFFSET_PKT_IN_OPTIONS);

            IpxPrint1("Data copied is (%.12s)\n", (PUCHAR)((PUCHAR)pRtBuffer + OFFSET_PKT_IN_OPTIONS + sizeof(IPX_HEADER)));

            pRtBuffer->DgrmOptions.LocalTarget.NicId       = pContext->DgrmOptions.LocalTarget.NicId;
            pRtBuffer->LengthOfExtraOpInfo       = 0;

             IpxPrint3("PassDgToRt: Copy to RcvIrp;Nic Id is (%d/%d). BufferLength is (%lx)\n", pContext->DgrmOptions.LocalTarget.NicId, pRtBuffer->DgrmOptions.LocalTarget.NicId, uNumBytes);


            CTEAssert(pContext->DgrmOptions.LocalTarget.NicId);

            //
            // pass the irp up to RT
            //
            if (CopyLength < BytesToCopy)
            {
                status = STATUS_BUFFER_OVERFLOW;
            }
            else
            {
                status = STATUS_SUCCESS;
            }

           InsertTailList(&pRtInfo->CompletedIrps, REQUEST_LINKAGE(pIrp));
           pRtAF->NoOfRcvIrps--;
            IpxPrint4("PassDgToRt;Returning Rt Rcv Irp - data from net, Length=%X,pIrp=%X; status = (%d). NoOfRcvIrp = (%d)\n"  ,uNumBytes,pIrp, status, pRtAF->NoOfRcvIrps);

           pIrp->IoStatus.Status      = status;
           pIrp->IoStatus.Information = CopyLength;
           CTEFreeLock(&pRtInfo->Lock,OldIrq);

        }
        IpxDereferenceRt(pRtInfo, RT_BUFF);
  } while (FALSE);


    IpxPrint0("PassDgToRt - Entered\n");
    return(status);

}
예제 #18
0
NTSTATUS
NdisuioDoFastRead(
    IN PNDISUIO_OPEN_CONTEXT        pOpenContext,
	IN PIRP							pIrp
    )
/*++

Routine Description:

    Utility routine to copy received data into user buffers and
    complete READ IRPs.

Arguments:

    pOpenContext - pointer to open context

Return Value:

    None

--*/
{
    PNDIS_PACKET        pRcvPacket;
    PLIST_ENTRY         pRcvPacketEntry;
    PUCHAR              pSrc, pDst;
    ULONG               BytesRemaining; // at pDst
    PNDIS_BUFFER        pNdisBuffer;
    ULONG               BytesAvailable;
	PPACKET_GROUP		pGroup;
	CCHAR				PriorityBoost = IO_NETWORK_INCREMENT;

    DEBUGP(DL_VERY_LOUD, ("FastRead: open %p/%x\n", pOpenContext, pOpenContext->Flags));

	if (NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
		return STATUS_UNSUCCESSFUL;

	//
	//  Copy as much data as possible from the receive packet to
	//  the IRP MDL.
	//
#ifndef WIN9X
	pGroup = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
	NUIO_ASSERT(pGroup != NULL);  // since it was already mapped
#else
	pGroup = MmGetSystemAddressForMdl(pIrp->MdlAddress);  // Win9x
#endif
	BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress);

	//
	//  Get the first queued receive packet
	//
	pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink;
	pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);

	do
	{
        NUIO_REMOVE_ENTRY_LIST(pRcvPacketEntry);

        pOpenContext->RecvPktCount--;

        NUIO_RELEASE_LOCK(&pOpenContext->Lock);

        NUIO_DEREF_OPEN(pOpenContext);  // Service: dequeue rcv packet

        pNdisBuffer = pRcvPacket->Private.Head;

		pDst = pGroup->Data;

		BytesRemaining -= sizeof(PACKET_GROUP);
		
        while (BytesRemaining && (pNdisBuffer != NULL))
        {
#ifndef WIN9X
            NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority);

            if (pSrc == NULL) 
            {
                DEBUGP(DL_FATAL, ("FastRead: Open %p, QueryBuffer failed for buffer %p\n",
                            pOpenContext, pNdisBuffer));

				break;
            }
#else
            NdisQueryBuffer(pNdisBuffer, &pSrc, &BytesAvailable);
#endif

            if (BytesAvailable)
            {
                ULONG BytesToCopy = MIN(BytesAvailable, BytesRemaining);

                NUIO_COPY_MEM(pDst, pSrc, BytesToCopy);
                BytesRemaining -= BytesToCopy;
                pDst += BytesToCopy;
            }

            NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
        }

		ndisuioFreeReceivePacket(pOpenContext, pRcvPacket);

		pGroup->Length = pDst - pGroup->Data;
		pGroup = (PPACKET_GROUP)pDst;
		
		NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
		
		if (NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue))
		{
			PriorityBoost = IO_NO_INCREMENT;
			break;
		}

		pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink;
		pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);

		NdisQueryPacketLength(pRcvPacket, &BytesAvailable);
		if (BytesRemaining < BytesAvailable + sizeof(PACKET_GROUP))
			break;
	} while (TRUE);
	
	NUIO_RELEASE_LOCK(&pOpenContext->Lock);

	//
	//  Complete the IRP.
	//
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining;
	
	DEBUGP(DL_INFO, ("FastRead: Open %p, IRP %p completed with %d bytes\n",
		pOpenContext, pIrp, pIrp->IoStatus.Information));
	
	IoCompleteRequest(pIrp, PriorityBoost);
	
	return STATUS_SUCCESS;
}
예제 #19
0
VOID
NdisuioTransferDataComplete(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN PNDIS_PACKET                 pNdisPacket,
    IN NDIS_STATUS                  TransferStatus,
    IN UINT                         BytesTransferred
    )
/*++

Routine Description:

    NDIS entry point called to signal completion of a call to
    NdisTransferData that had pended.

Arguments:

    ProtocolBindingContext - pointer to open context
    pNdisPacket - our receive packet into which data is transferred
    TransferStatus - status of the transfer
    BytesTransferred - bytes copied into the packet.

Return Value:

    None

--*/
{
    PNDISUIO_OPEN_CONTEXT   pOpenContext;
    PNDIS_BUFFER            pOriginalBuffer, pPartialBuffer;
	PIRP					pIrp;
	PPACKET_GROUP			pGroup;
	//ULONG                   pDst;

    pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
    NUIO_STRUCT_ASSERT(pOpenContext, oc);

	pIrp = NUIO_IRP_FROM_RCV_PKT(pNdisPacket);
	if (pIrp)
	{
		PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(pIrp);

		pOriginalBuffer = NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pNdisPacket);
		
		//
		//  Free the partial MDL that we allocated
		//
		if (pOriginalBuffer)
			IoFreeMdl(pOriginalBuffer);
		
		//
		//  Put the packet on the free queue
		//
		NdisFreePacket(pNdisPacket);
		
#ifndef WIN9X
		pGroup = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
		//NUIO_ASSERT(pDst != NULL);  // since it was already mapped
#else
		pGroup = MmGetSystemAddressForMdl(pIrp->MdlAddress);  // Win9x
#endif
		pGroup->Length = BytesTransferred + sizeof(NDISUIO_ETH_HEADER);
		if (TransferStatus == NDIS_STATUS_SUCCESS)
		{
			pIrp->IoStatus.Status = STATUS_SUCCESS;
			pIrp->IoStatus.Information = pGroup->Length + sizeof(PACKET_GROUP);
		}
		else
		{
			pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
			pIrp->IoStatus.Information = 0;
		}
		
		DEBUGP(DL_LOUD, ("TransferComp: Pkt %p, OrigBuf %p, BytesTransferred %d\n",
			pNdisPacket, pOriginalBuffer, BytesTransferred));
		
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	}
	else
	{
		//
		//  Check if an NDIS_BUFFER was created to map part of the receive buffer;
		//  if so, free it and link back the original NDIS_BUFFER that maps
		//  the full receive buffer to the packet.
		//
		pOriginalBuffer = NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pNdisPacket);
		if (pOriginalBuffer != NULL)
		{
			//
			//  We had stashed off the NDIS_BUFFER for the full receive
			//  buffer in the packet reserved area. Unlink the partial
			//  buffer and link in the full buffer.
			//
			NdisUnchainBufferAtFront(pNdisPacket, &pPartialBuffer);
			NdisChainBufferAtBack(pNdisPacket, pOriginalBuffer);
			
			DEBUGP(DL_LOUD, ("TransferComp: Pkt %p, OrigBuf %p, PartialBuf %p\n",
                pNdisPacket, pOriginalBuffer, pPartialBuffer));
			
			//
			//  Free up the partial buffer.
			//
			NdisFreeBuffer(pPartialBuffer);
		}
	}

    if (TransferStatus == NDIS_STATUS_SUCCESS)
    {
        //
        //  Queue this up for receive processing, and
        //  try to complete some read IRPs.
        //
        ndisuioQueueReceivePacket(pOpenContext, pNdisPacket);
    }
    else
    {
        ndisuioFreeReceivePacket(pOpenContext, pNdisPacket);

		NdisInterlockedAddLargeStatistic((PLARGE_INTEGER)&pOpenContext->DroppedPackets, 1);
    }
}
예제 #20
0
파일: dirctl.c 프로젝트: Strongc/reactos
static NTSTATUS
CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject,
                   PIRP Irp)
{
    PDEVICE_EXTENSION DeviceExtension;
    LONG BufferLength = 0;
    PUNICODE_STRING SearchPattern = NULL;
    FILE_INFORMATION_CLASS FileInformationClass;
    ULONG FileIndex = 0;
    PUCHAR Buffer = NULL;
    PFILE_NAMES_INFORMATION Buffer0 = NULL;
    PFCB Fcb;
    PCCB Ccb;
    FCB TempFcb;
    BOOLEAN First = FALSE;
    PIO_STACK_LOCATION Stack;
    PFILE_OBJECT FileObject;
    NTSTATUS Status = STATUS_SUCCESS;

    DPRINT("CdfsQueryDirectory() called\n");

    DeviceExtension = DeviceObject->DeviceExtension;
    Stack = IoGetCurrentIrpStackLocation(Irp);
    FileObject = Stack->FileObject;
    RtlInitEmptyUnicodeString(&TempFcb.PathName, TempFcb.PathNameBuffer, sizeof(TempFcb.PathNameBuffer));

    Ccb = (PCCB)FileObject->FsContext2;
    Fcb = (PFCB)FileObject->FsContext;

    /* Obtain the callers parameters */
    BufferLength = Stack->Parameters.QueryDirectory.Length;
    SearchPattern = Stack->Parameters.QueryDirectory.FileName;
    FileInformationClass =
        Stack->Parameters.QueryDirectory.FileInformationClass;
    FileIndex = Stack->Parameters.QueryDirectory.FileIndex;

    /* Determine Buffer for result */
    if (Irp->MdlAddress)
    {
        Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
    }
    else
    {
        Buffer = Irp->UserBuffer;
    }

    /* Allocate search pattern in case:
     * -> We don't have one already in context
     * -> We have been given an input pattern
     * -> The pattern length is not null
     * -> The pattern buffer is not null
     * Otherwise, we'll fall later and allocate a match all (*) pattern
     */
    if (SearchPattern != NULL &&
        SearchPattern->Length != 0 && SearchPattern->Buffer != NULL)
    {
        if (Ccb->DirectorySearchPattern.Buffer == NULL)
        {
            First = TRUE;
            Ccb->DirectorySearchPattern.Buffer =
                ExAllocatePoolWithTag(NonPagedPool, SearchPattern->Length + sizeof(WCHAR), CDFS_SEARCH_PATTERN_TAG);
            if (Ccb->DirectorySearchPattern.Buffer == NULL)
            {
                return STATUS_INSUFFICIENT_RESOURCES;
            }
            Ccb->DirectorySearchPattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR);
            RtlCopyUnicodeString(&Ccb->DirectorySearchPattern, SearchPattern);
            Ccb->DirectorySearchPattern.Buffer[SearchPattern->Length / sizeof(WCHAR)] = 0;
        }
    }
    else if (Ccb->DirectorySearchPattern.Buffer == NULL)
    {
        First = TRUE;
        Ccb->DirectorySearchPattern.Buffer = ExAllocatePoolWithTag(NonPagedPool, 2 * sizeof(WCHAR), CDFS_SEARCH_PATTERN_TAG);
        if (Ccb->DirectorySearchPattern.Buffer == NULL)
        {
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        Ccb->DirectorySearchPattern.Length = sizeof(WCHAR);
        Ccb->DirectorySearchPattern.MaximumLength = 2 * sizeof(WCHAR);
        Ccb->DirectorySearchPattern.Buffer[0] = L'*';
        Ccb->DirectorySearchPattern.Buffer[1] = 0;
    }
    DPRINT("Search pattern '%wZ'\n", &Ccb->DirectorySearchPattern);

    /* Determine directory index */
    if (Stack->Flags & SL_INDEX_SPECIFIED)
    {
        Ccb->Entry = Stack->Parameters.QueryDirectory.FileIndex;
        Ccb->Offset = Ccb->CurrentByteOffset.u.LowPart;
    }
    else if (First || (Stack->Flags & SL_RESTART_SCAN))
    {
        Ccb->Entry = 0;
        Ccb->Offset = 0;
    }
    DPRINT("Buffer = %p  tofind = %wZ\n", Buffer, &Ccb->DirectorySearchPattern);

    TempFcb.ObjectName = TempFcb.PathName.Buffer;
    while (Status == STATUS_SUCCESS && BufferLength > 0)
    {
        Status = CdfsFindFile(DeviceExtension,
            &TempFcb,
            Fcb,
            &Ccb->DirectorySearchPattern,
            &Ccb->Entry,
            &Ccb->Offset);
        DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry);

        if (NT_SUCCESS(Status))
        {
            switch (FileInformationClass)
            {
            case FileNameInformation:
                Status = CdfsGetNameInformation(&TempFcb,
                    DeviceExtension,
                    (PFILE_NAMES_INFORMATION)Buffer,
                    BufferLength);
                break;

            case FileDirectoryInformation:
                Status = CdfsGetDirectoryInformation(&TempFcb,
                    DeviceExtension,
                    (PFILE_DIRECTORY_INFORMATION)Buffer,
                    BufferLength);
                break;

            case FileFullDirectoryInformation:
                Status = CdfsGetFullDirectoryInformation(&TempFcb,
                    DeviceExtension,
                    (PFILE_FULL_DIR_INFORMATION)Buffer,
                    BufferLength);
                break;

            case FileBothDirectoryInformation:
                Status = CdfsGetBothDirectoryInformation(&TempFcb,
                    DeviceExtension,
                    (PFILE_BOTH_DIR_INFORMATION)Buffer,
                    BufferLength);
                break;

            default:
                Status = STATUS_INVALID_INFO_CLASS;
            }

            if (Status == STATUS_BUFFER_OVERFLOW)
            {
                if (Buffer0)
                {
                    Buffer0->NextEntryOffset = 0;
                }
                break;
            }
        }
        else
        {
            if (Buffer0)
            {
                Buffer0->NextEntryOffset = 0;
            }

            if (First)
            {
                Status = STATUS_NO_SUCH_FILE;
            }
            else
            {
                Status = STATUS_NO_MORE_FILES;
            }
            break;
        }

        Buffer0 = (PFILE_NAMES_INFORMATION)Buffer;
        Buffer0->FileIndex = FileIndex++;
        Ccb->Entry++;

        if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
        {
            break;
        }
        BufferLength -= Buffer0->NextEntryOffset;
        Buffer += Buffer0->NextEntryOffset;
    }

    if (Buffer0)
    {
        Buffer0->NextEntryOffset = 0;
    }

    if (FileIndex > 0)
    {
        Status = STATUS_SUCCESS;
    }

    return(Status);
}
예제 #21
0
파일: dma_old.c 프로젝트: Gaikokujin/WinNT4
BOOLEAN
VideoPortDoDma(
    IN PVOID                        HwDeviceExtension,
    IN PVIDEO_REQUEST_PACKET        pVrp
    )
{
    PDEVICE_EXTENSION            deviceExtension =
                                ((PDEVICE_EXTENSION) HwDeviceExtension) - 1;
    PPUBLIC_VIDEO_REQUEST_BLOCK pPVRB;
    PDMA_PARAMETERS             pIoVrb;
    PIRP                        pIrp;

    GET_PVRB_FROM_PVRP(pPVRB, pVrp);

    pIoVrb = pVideoPortGetDmaParameters(deviceExtension, pPVRB);

    if (!pIoVrb) {

        //
        // Can't get DmaParameter storage. set flag and return
        //

        deviceExtension->VRBFlags |= INSUFFICIENT_DMA_RESOURCES;
        return FALSE;
    }

    pIrp                              = pPVRB->pIrp;
    deviceExtension->MapDmaParameters = pIoVrb;

    //
    // Get Mdl for user buffer.
    //

    if (!pPVRB || !IoAllocateMdl(pPVRB->vrp.InputBuffer,
                       pPVRB->vrp.InputBufferLength,
                       FALSE,
                       FALSE,
                       pIrp)) {

            VideoPortDebugPrint(0,
                        "VideoPortIoStartRequest: Can't allocate Mdl\n");

            pPVRB->vrp.StatusBlock->Status = VRB_STATUS_INVALID_REQUEST;

            VideoPortNotification(RequestComplete,
                                 deviceExtension,
                                 pIoVrb);

            VideoPortNotification(NextRequest,
                                 deviceExtension);

            //
            // Queue a DPC to process the work that was just indicated.
            //

            IoRequestDpc(deviceExtension->DeviceObject, NULL, NULL);
            return FALSE;
    }

    //
    // Save the Mdl virtual address
    //

    pIoVrb->DataOffset = MmGetMdlVirtualAddress(pIrp->MdlAddress);

    //
    // Determine if the device needs mapped memory.
    //

    if (deviceExtension->bMapBuffers) {

        if (pIrp->MdlAddress) {
            pIoVrb->DataOffset = MmGetSystemAddressForMdl(pIrp->MdlAddress);

            pPVRB->vrp.InputBuffer  = ((PUCHAR)pIoVrb->DataOffset) +
                                 (ULONG)(((PUCHAR)pPVRB->vrp.InputBuffer) - ((PUCHAR)MmGetMdlVirtualAddress(pIrp->MdlAddress)));
        }
    }

    if (deviceExtension->DmaAdapterObject) {

        //
        // If the buffer is not mapped then the I/O buffer must be flushed
        // to aid in cache coherency.
        //

        KeFlushIoBuffers(pIrp->MdlAddress, TRUE, TRUE);
    }

    //
    // Determine if this adapter needs map registers
    //

    if (deviceExtension->bMasterWithAdapter) {

        //
        // Calculate the number of map registers needed for this transfer.
        // Note that this may be recalculated if the miniport really wants
        // to do DMA
        //

        pIoVrb->NumberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
                pPVRB->vrp.InputBuffer,
                pPVRB->vrp.InputBufferLength
                );
    }

    //
    // The miniport may have requested too big of a buffer, so iteratively
    // chop it in half until we find one we can do. This changes the
    // vrp.InputBufferLength, which the miniport must check to see how much
    // is actually sent and queue up the remainder.
    //

    while (pIoVrb->NumberOfMapRegisters >
        deviceExtension->Capabilities.MaximumPhysicalPages) {

        pPVRB->vrp.InputBufferLength /= 2;

        pIoVrb->NumberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
            pPVRB->vrp.InputBuffer,
            pPVRB->vrp.InputBufferLength
            );

    }

    //
    // Allocate the adapter channel with sufficient map registers
    // for the transfer.
    //

    IoAllocateAdapterChannel(
        deviceExtension->DmaAdapterObject,  // AdapterObject
        deviceExtension->DeviceObject,      // DeviceObject
        pIoVrb->NumberOfMapRegisters,       // NumberOfMapRegisters
        pVideoPortBuildScatterGather,       // ExecutionRoutine (Must return DeallocateObjectKeepRegisters)
        pIoVrb);                            // Context

    //
    // The execution routine called via IoAllocateChannel will do the
    // rest of the work so just return.
    //

    return TRUE;

}
예제 #22
0
BOOLEAN
BowserMapUsersBuffer (
    IN PIRP Irp,
    OUT PVOID *UserBuffer,
    IN ULONG Length
    )

/*++

Routine Description:

    This routine will probe and lock the buffer described by the
    provided Irp.

Arguments:

    IN PIRP Irp - Supplies the IRP that is to be mapped.
    OUT PVOID *Buffer - Returns a buffer that maps the user's buffer in the IRP

Return Value:

    TRUE - The buffer was mapped into the current address space.
    FALSE - The buffer was NOT mapped in, it was already mappable.


--*/

{
    PAGED_CODE();

    if (Irp->MdlAddress) {
        *UserBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
        return FALSE;
    } else {
        if (Irp->AssociatedIrp.SystemBuffer != NULL) {
            *UserBuffer = Irp->AssociatedIrp.SystemBuffer;

        } else if (Irp->RequestorMode != KernelMode) {
            PIO_STACK_LOCATION IrpSp;

            IrpSp = IoGetCurrentIrpStackLocation( Irp );

            if ((Length != 0) && (Irp->UserBuffer != 0)) {

                if ((IrpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) ||
                    (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)) {
                    ULONG ControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;

                    if ((ControlCode & 3) == METHOD_NEITHER) {
                        ProbeForWrite( Irp->UserBuffer,
                                        Length,
                                        sizeof(UCHAR) );
                    } else {
                        ASSERT ((ControlCode & 3) != METHOD_BUFFERED);
                        ASSERT ((ControlCode & 3) != METHOD_IN_DIRECT);
                        ASSERT ((ControlCode & 3) != METHOD_OUT_DIRECT);
                    }

                } else if ((IrpSp->MajorFunction == IRP_MJ_READ) ||
                    (IrpSp->MajorFunction == IRP_MJ_QUERY_INFORMATION) ||
                    (IrpSp->MajorFunction == IRP_MJ_QUERY_VOLUME_INFORMATION) ||
                    (IrpSp->MajorFunction == IRP_MJ_QUERY_SECURITY) ||
                    (IrpSp->MajorFunction == IRP_MJ_DIRECTORY_CONTROL)) {

                    ProbeForWrite( Irp->UserBuffer,
                           Length,
                           sizeof(UCHAR) );
                } else {
                    ProbeForRead( Irp->UserBuffer,
                          Length,
                          sizeof(UCHAR) );
                }
            }

            *UserBuffer = Irp->UserBuffer;
        }

        return FALSE;
    }

}
예제 #23
0
파일: devctrl.c 프로젝트: BuloZB/WinNT4
NTSTATUS
CdCommonDevControl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

Arguments:

Return Value:

--*/

{
    NTSTATUS Status;

    TYPE_OF_OPEN TypeOfOpen;
    PFCB Fcb;
    PCCB Ccb;

    PIO_STACK_LOCATION IrpSp;
    PIO_STACK_LOCATION NextIrpSp;

    PVOID TargetBuffer;

    PAGED_CODE();

    //
    //  Extract and decode the file object.
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    TypeOfOpen = CdDecodeFileObject( IrpContext,
                                     IrpSp->FileObject,
                                     &Fcb,
                                     &Ccb );

    //
    //  The only type of opens we accept are user volume opens.
    //

    if (TypeOfOpen != UserVolumeOpen) {

        CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
        return STATUS_INVALID_PARAMETER;
    }

    //
    //  If we have the TOC in the Vcb then copy it directly to the user's buffer.
    //

    if ((IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) &&
        (Fcb->Vcb->CdromToc != NULL)) {

        //
        //  Verify the Vcb in this case to detect if the volume has changed.
        //

        CdVerifyVcb( IrpContext, Fcb->Vcb );

        if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < Fcb->Vcb->TocLength) {

            CdCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL );
            return STATUS_BUFFER_TOO_SMALL;
        }

        //
        //  Find the buffer for this request.
        //

        if (!FlagOn( Irp->Flags, IRP_ASSOCIATED_IRP ) &&
                   (Irp->AssociatedIrp.SystemBuffer != NULL)) {

            TargetBuffer = Irp->AssociatedIrp.SystemBuffer;

        } else if (Irp->MdlAddress != NULL) {

            TargetBuffer = MmGetSystemAddressForMdl( Irp->MdlAddress );
        }

        //
        //  If we have a buffer then perform the copy and return.
        //

        if (TargetBuffer) {

            RtlCopyMemory( TargetBuffer, Fcb->Vcb->CdromToc, Fcb->Vcb->TocLength );

            Irp->IoStatus.Information = Fcb->Vcb->TocLength;

            CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
            return STATUS_SUCCESS;
        }

    //
    //  Handle the case of the disk type ourselves.
    //

    } else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE) {

        //
        //  Verify the Vcb in this case to detect if the volume has changed.
        //

        CdVerifyVcb( IrpContext, Fcb->Vcb );

        //
        //  Check the size of the output buffer.
        //

        if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( CDROM_DISK_DATA )) {

            CdCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL );
            return STATUS_BUFFER_TOO_SMALL;
        }

        //
        //  Copy the data from the Vcb.
        //

        ((PCDROM_DISK_DATA) Irp->AssociatedIrp.SystemBuffer)->DiskData = Fcb->Vcb->DiskFlags;

        Irp->IoStatus.Information = sizeof( CDROM_DISK_DATA );
        CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
        return STATUS_SUCCESS;
    }

    //
    //  Get the next stack location, and copy over the stack parameter
    //  information.
    //

    NextIrpSp = IoGetNextIrpStackLocation( Irp );

    *NextIrpSp = *IrpSp;

    //
    //  Set up the completion routine
    //

    IoSetCompletionRoutine( Irp,
                            CdDevCtrlCompletionRoutine,
                            NULL,
                            TRUE,
                            TRUE,
                            TRUE );

    //
    //  Send the request.
    //

    Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );

    //
    //  Cleanup our Irp Context.  The driver has completed the Irp.
    //

    CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );

    return Status;
}
예제 #24
0
VOID
NbfActionDatagramIndication(
    IN PDEVICE_CONTEXT DeviceContext,
    IN PNBF_HDR_CONNECTIONLESS UiFrame,
    IN ULONG Length
)

/*++

Routine Description:

    This routine is called after a datagram frame has been
    received. It checks if there is a DATAGRAM.INDICATION IRP
    waiting to be completed, and if so completes it.

Arguments:

    DeviceContext - Pointer to our device context.

    UiFrame - Pointer to the incoming frame. The first byte of
        information is the first byte of the NetBIOS connectionless
        header.

    Length - The length of the frame starting at UiFrame.

Return Value:

    None

--*/

{
    KIRQL oldirql, cancelirql;
    PTP_REQUEST Request;
    PLIST_ENTRY p;
    PACTION_DATAGRAM_INDICATION ActionHeader;
    PDATAGRAM_INDICATION DatagramIndication;
    ULONG CopyLength;
    PMDL Mdl;
    NTSTATUS Status;


    IoAcquireCancelSpinLock (&cancelirql);
    ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);

    if (!IsListEmpty (&DeviceContext->DatagramIndicationQueue)) {

        p = RemoveHeadList (&DeviceContext->DatagramIndicationQueue);
        RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);

        Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
        IoSetCancelRoutine(Request->IoRequestPacket, NULL);
        IoReleaseCancelSpinLock(cancelirql);

        Mdl = Request->Buffer2;
        ActionHeader = (PACTION_DATAGRAM_INDICATION)
                       (MmGetSystemAddressForMdl(Mdl));
        DatagramIndication = &ActionHeader->DatagramIndication;

        //
        // Copy over data from frame (note that dest and source
        // address are copied with one call).
        //

        RtlCopyMemory ((PUCHAR)(DatagramIndication->DestinationName),
                       (PUCHAR)(UiFrame->DestinationName),
                       2 * NETBIOS_NAME_LENGTH);

        if ((Length-sizeof(NBF_HDR_CONNECTIONLESS)) <=
                (ULONG)DatagramIndication->DatagramBufferLength) {

            CopyLength = Length - sizeof(NBF_HDR_CONNECTIONLESS);
            Status = STATUS_SUCCESS;

        } else {

            CopyLength = DatagramIndication->DatagramBufferLength;
            Status = STATUS_BUFFER_OVERFLOW;

        }


        RtlCopyMemory(
            (PUCHAR)DatagramIndication->DatagramBuffer,
            ((PUCHAR)UiFrame) + sizeof(NBF_HDR_CONNECTIONLESS),
            CopyLength);
        DatagramIndication->DatagramBufferLength = (USHORT)CopyLength;

        NbfCompleteRequest (Request, Status, CopyLength +
                            FIELD_OFFSET (ACTION_DATAGRAM_INDICATION, DatagramIndication.DatagramBuffer[0]));

    } else {

        RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
        IoReleaseCancelSpinLock(cancelirql);

    }
}
예제 #25
0
파일: dirctl.c 프로젝트: hoangduit/reactos
NTSTATUS
NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
{
    PIRP Irp;
    PDEVICE_OBJECT DeviceObject;
    PDEVICE_EXTENSION DeviceExtension;
    LONG BufferLength = 0;
    PUNICODE_STRING SearchPattern = NULL;
    FILE_INFORMATION_CLASS FileInformationClass;
    ULONG FileIndex = 0;
    PUCHAR Buffer = NULL;
    PFILE_NAMES_INFORMATION Buffer0 = NULL;
    PNTFS_FCB Fcb;
    PNTFS_CCB Ccb;
    BOOLEAN First = FALSE;
    PIO_STACK_LOCATION Stack;
    PFILE_OBJECT FileObject;
    NTSTATUS Status = STATUS_SUCCESS;
    PFILE_RECORD_HEADER FileRecord;
    PNTFS_ATTR_CONTEXT DataContext;
    ULONGLONG MFTRecord, OldMFTRecord = 0;
    UNICODE_STRING Pattern;

    DPRINT1("NtfsQueryDirectory() called\n");

    ASSERT(IrpContext);
    Irp = IrpContext->Irp;
    DeviceObject = IrpContext->DeviceObject;

    DeviceExtension = DeviceObject->DeviceExtension;
    Stack = IoGetCurrentIrpStackLocation(Irp);
    FileObject = Stack->FileObject;

    Ccb = (PNTFS_CCB)FileObject->FsContext2;
    Fcb = (PNTFS_FCB)FileObject->FsContext;

    /* Obtain the callers parameters */
    BufferLength = Stack->Parameters.QueryDirectory.Length;
    SearchPattern = Stack->Parameters.QueryDirectory.FileName;
    FileInformationClass = Stack->Parameters.QueryDirectory.FileInformationClass;
    FileIndex = Stack->Parameters.QueryDirectory.FileIndex;

    if (SearchPattern != NULL)
    {
        if (!Ccb->DirectorySearchPattern)
        {
            First = TRUE;
            Pattern.Length = 0;
            Pattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR);
            Ccb->DirectorySearchPattern = Pattern.Buffer =
                ExAllocatePoolWithTag(NonPagedPool, Pattern.MaximumLength, TAG_NTFS);
            if (!Ccb->DirectorySearchPattern)
            {
                return STATUS_INSUFFICIENT_RESOURCES;
            }

            memcpy(Ccb->DirectorySearchPattern, SearchPattern->Buffer, SearchPattern->Length);
            Ccb->DirectorySearchPattern[SearchPattern->Length / sizeof(WCHAR)] = 0;
        }
    }
    else if (!Ccb->DirectorySearchPattern)
    {
        First = TRUE;
        Ccb->DirectorySearchPattern = ExAllocatePoolWithTag(NonPagedPool, 2 * sizeof(WCHAR), TAG_NTFS);
        if (!Ccb->DirectorySearchPattern)
        {
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        Ccb->DirectorySearchPattern[0] = L'*';
        Ccb->DirectorySearchPattern[1] = 0;
    }

    RtlInitUnicodeString(&Pattern, Ccb->DirectorySearchPattern);
    DPRINT("Search pattern '%S'\n", Ccb->DirectorySearchPattern);
    DPRINT("In: '%S'\n", Fcb->PathName);

    /* Determine directory index */
    if (Stack->Flags & SL_INDEX_SPECIFIED)
    {
        Ccb->Entry = Ccb->CurrentByteOffset.u.LowPart;
    }
    else if (First || (Stack->Flags & SL_RESTART_SCAN))
    {
        Ccb->Entry = 0;
    }

    /* Determine Buffer for result */
    if (Irp->MdlAddress)
    {
        Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
    }
    else
    {
        Buffer = Irp->UserBuffer;
    }

    DPRINT("Buffer=%p tofind=%S\n", Buffer, Ccb->DirectorySearchPattern);

    while (Status == STATUS_SUCCESS && BufferLength > 0)
    {
        Status = NtfsFindFileAt(DeviceExtension,
                                &Pattern,
                                &Ccb->Entry,
                                &FileRecord,
                                &DataContext,
                                &MFTRecord,
                                Fcb->MFTIndex);

        if (NT_SUCCESS(Status))
        {
            /* HACK: files with both a short name and a long name are present twice in the index.
             * Ignore the second entry, if it is immediately following the first one.
             */
            if (MFTRecord == OldMFTRecord)
            {
                DPRINT("Ignoring duplicate MFT entry 0x%x\n", MFTRecord);
                Ccb->Entry++;
                ExFreePoolWithTag(FileRecord, TAG_NTFS);
                continue;
            }
            OldMFTRecord = MFTRecord;

            switch (FileInformationClass)
            {
                case FileNameInformation:
                    Status = NtfsGetNameInformation(DeviceExtension,
                                                    FileRecord,
                                                    DataContext,
                                                    (PFILE_NAMES_INFORMATION)Buffer,
                                                    BufferLength);
                    break;

                case FileDirectoryInformation:
                    Status = NtfsGetDirectoryInformation(DeviceExtension,
                                                         FileRecord,
                                                         DataContext,
                                                         (PFILE_DIRECTORY_INFORMATION)Buffer,
                                                         BufferLength);
                    break;

                case FileFullDirectoryInformation:
                    Status = NtfsGetFullDirectoryInformation(DeviceExtension,
                                                             FileRecord,
                                                             DataContext,
                                                             MFTRecord,
                                                             (PFILE_FULL_DIRECTORY_INFORMATION)Buffer,
                                                             BufferLength);
                    break;

                case FileBothDirectoryInformation:
                    Status = NtfsGetBothDirectoryInformation(DeviceExtension,
                                                             FileRecord,
                                                             DataContext,
                                                             MFTRecord,
                                                             (PFILE_BOTH_DIR_INFORMATION)Buffer,
                                                             BufferLength);
                    break;

                default:
                    Status = STATUS_INVALID_INFO_CLASS;
            }

            if (Status == STATUS_BUFFER_OVERFLOW)
            {
                if (Buffer0)
                {
                    Buffer0->NextEntryOffset = 0;
                }
                break;
            }
        }
        else
        {
            if (Buffer0)
            {
                Buffer0->NextEntryOffset = 0;
            }

            if (First)
            {
                Status = STATUS_NO_SUCH_FILE;
            }
            else
            {
                Status = STATUS_NO_MORE_FILES;
            }
            break;
        }

        Buffer0 = (PFILE_NAMES_INFORMATION)Buffer;
        Buffer0->FileIndex = FileIndex++;
        Ccb->Entry++;

        if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
        {
            break;
        }
        BufferLength -= Buffer0->NextEntryOffset;
        Buffer += Buffer0->NextEntryOffset;
        ExFreePoolWithTag(FileRecord, TAG_NTFS);
    }

    if (Buffer0)
    {
        Buffer0->NextEntryOffset = 0;
    }

    if (FileIndex > 0)
    {
        Status = STATUS_SUCCESS;
    }

    return Status;
}