Пример #1
0
BOOL
STREAMAPI
AdapterFormatFromRange(
    IN PHW_STREAM_REQUEST_BLOCK pSrb
    )
{
    PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
    PKSDATARANGE                DataRange;
    BOOL                        OnlyWantsSize;
    BOOL                        MatchFound = FALSE;
    ULONG                       FormatSize;
    ULONG                       StreamNumber;
    ULONG                       j;
    ULONG                       NumberOfFormatArrayEntries;
    PKSDATAFORMAT               *pAvailableFormats;

DbgLogInfo(("TestCap: Enter AdapterFormatFromRange\n"));	


    IntersectInfo = pSrb->CommandData.IntersectInfo;
    StreamNumber = IntersectInfo->StreamNumber;
    DataRange = IntersectInfo->DataRange;

    //
    // Check that the stream number is valid
    //

    if (StreamNumber >= DRIVER_STREAM_COUNT) {
        pSrb->Status = STATUS_NOT_IMPLEMENTED;
        TRAP;
        return FALSE;
    }

    NumberOfFormatArrayEntries =
            Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;

    //
    // Get the pointer to the array of available formats
    //

    pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;

    //
    // Is the caller trying to get the format, or the size of the format?
    //

    OnlyWantsSize = (IntersectInfo->SizeOfDataFormatBuffer == sizeof(ULONG));

    //
    // Walk the formats supported by the stream searching for a match
    // of the three GUIDs which together define a DATARANGE
    //

    for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) {


        if (!AdapterCompareGUIDsAndFormatSize(
                        DataRange,
                        *pAvailableFormats,
                        TRUE /* CompareFormatSize */)) {
            continue;
        }

        //
        // Now that the three GUIDs match, do a further type-specific check
        //

        // -------------------------------------------------------------------
        // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
        // -------------------------------------------------------------------

        if (IsEqualGUID (&DataRange->Specifier,
                &KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {

            PKS_DATARANGE_VIDEO DataRangeVideoToVerify =
                    (PKS_DATARANGE_VIDEO) DataRange;
            PKS_DATARANGE_VIDEO DataRangeVideo =
                    (PKS_DATARANGE_VIDEO) *pAvailableFormats;
            PKS_DATAFORMAT_VIDEOINFOHEADER DataFormatVideoInfoHeaderOut;

            //
            // Check that the other fields match
            //
            if ((DataRangeVideoToVerify->bFixedSizeSamples != DataRangeVideo->bFixedSizeSamples) ||
                (DataRangeVideoToVerify->bTemporalCompression != DataRangeVideo->bTemporalCompression) ||
                (DataRangeVideoToVerify->StreamDescriptionFlags != DataRangeVideo->StreamDescriptionFlags) ||
                (DataRangeVideoToVerify->MemoryAllocationFlags != DataRangeVideo->MemoryAllocationFlags) ||
                (RtlCompareMemory (&DataRangeVideoToVerify->ConfigCaps,
                        &DataRangeVideo->ConfigCaps,
                        sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
                        sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)))
            {
                continue;
            }

            // MATCH FOUND!
            MatchFound = TRUE;
			if(MatchFound)
				{
				DbgLogInfo(("TestCap: MatchFound!!!!\n"));	
				}
				
            FormatSize = sizeof (KSDATAFORMAT) +
                KS_SIZE_VIDEOHEADER (&DataRangeVideoToVerify->VideoInfoHeader);

            if (OnlyWantsSize) {
                break;
            }

            // Caller wants the full data format
            if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
                pSrb->Status = STATUS_BUFFER_TOO_SMALL;
                return FALSE;
            }

            // Copy over the KSDATAFORMAT, followed by the
            // actual VideoInfoHeader

            DataFormatVideoInfoHeaderOut = (PKS_DATAFORMAT_VIDEOINFOHEADER) IntersectInfo->DataFormatBuffer;

            // Copy over the KSDATAFORMAT
            RtlCopyMemory(
                &DataFormatVideoInfoHeaderOut->DataFormat,
                &DataRangeVideoToVerify->DataRange,
                sizeof (KSDATARANGE));

            DataFormatVideoInfoHeaderOut->DataFormat.FormatSize = FormatSize;

            // Copy over the callers requested VIDEOINFOHEADER

            RtlCopyMemory(
                &DataFormatVideoInfoHeaderOut->VideoInfoHeader,
                &DataRangeVideoToVerify->VideoInfoHeader,
                KS_SIZE_VIDEOHEADER (&DataRangeVideoToVerify->VideoInfoHeader));

            // Calculate biSizeImage for this request, and put the result in both
            // the biSizeImage field of the bmiHeader AND in the SampleSize field
            // of the DataFormat.
            //
            // Note that for compressed sizes, this calculation will probably not
            // be just width * height * bitdepth

            DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader.biSizeImage =
                DataFormatVideoInfoHeaderOut->DataFormat.SampleSize =
                KS_DIBSIZE(DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader);

            //
            // Perform other validation such as cropping and scaling checks
            //

            break;

        } // End of VIDEOINFOHEADER specifier

        // -------------------------------------------------------------------
        // Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
        // -------------------------------------------------------------------

        else if (IsEqualGUID (&DataRange->Specifier,
                &KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)) {

            //
            // For analog video, the DataRange and DataFormat
            // are identical, so just copy the whole structure
            //

            PKS_DATARANGE_ANALOGVIDEO DataRangeVideo =
                    (PKS_DATARANGE_ANALOGVIDEO) *pAvailableFormats;

            // MATCH FOUND!
            MatchFound = TRUE;
            FormatSize = sizeof (KS_DATARANGE_ANALOGVIDEO);

            if (OnlyWantsSize) {
                break;
            }

            // Caller wants the full data format
            if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
                pSrb->Status = STATUS_BUFFER_TOO_SMALL;
                return FALSE;
            }

            RtlCopyMemory(
                IntersectInfo->DataFormatBuffer,
                DataRangeVideo,
                sizeof (KS_DATARANGE_ANALOGVIDEO));

            ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;

            break;

        } // End of KS_ANALOGVIDEOINFO specifier

        // -------------------------------------------------------------------
        // Specifier FORMAT_VBI for KS_VIDEO_VBI
        // -------------------------------------------------------------------

        else if (IsEqualGUID (&DataRange->Specifier,
                &KSDATAFORMAT_SPECIFIER_VBI))
        {
            PKS_DATARANGE_VIDEO_VBI pDataRangeVBI =
                (PKS_DATARANGE_VIDEO_VBI)*pAvailableFormats;
            PKS_DATAFORMAT_VBIINFOHEADER InterVBIHdr =
                (PKS_DATAFORMAT_VBIINFOHEADER)IntersectInfo->DataFormatBuffer;

            // MATCH FOUND!
            MatchFound = TRUE;

            FormatSize = sizeof (KS_DATAFORMAT_VBIINFOHEADER);

            // Is the caller trying to get the format, or the size of it?
            if (OnlyWantsSize)
                break;

            // Verify that there is enough room in the supplied buffer
            //   for the whole thing
            if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize)
            {
                if (IntersectInfo->SizeOfDataFormatBuffer > 0) {
                    DbgLogError(
                        ("Testcap::AdapterFormatFromRange: "
                         "Specifier==VBI, Buffer too small=%d vs. %d\n",
                         IntersectInfo->SizeOfDataFormatBuffer,
                         FormatSize));
                }
                pSrb->Status = STATUS_BUFFER_TOO_SMALL;
                return FALSE;
            }

            // If there is room, go ahead...

            RtlCopyMemory(&InterVBIHdr->DataFormat,
                          &pDataRangeVBI->DataRange,
                          sizeof (KSDATARANGE));

            ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;

            RtlCopyMemory(&InterVBIHdr->VBIInfoHeader,
                          &pDataRangeVBI->VBIInfoHeader,
                          sizeof(KS_VBIINFOHEADER));

            break;

        } // End of KS_VIDEO_VBI specifier

        // -------------------------------------------------------------------
        // Type FORMAT_NABTS for NABTS pin
        // -------------------------------------------------------------------

        else if (IsEqualGUID (&DataRange->SubFormat,
                &KSDATAFORMAT_SUBTYPE_NABTS))
        {
            PKSDATARANGE pDataRange = (PKSDATARANGE)*pAvailableFormats;

            // MATCH FOUND!
            MatchFound = TRUE;

            FormatSize = sizeof (KSDATAFORMAT);

            // Is the caller trying to get the format, or the size of it?
            if (OnlyWantsSize)
                break;

            // Verify that there is enough room in the supplied buffer
            //   for the whole thing
            if (IntersectInfo->SizeOfDataFormatBuffer >= FormatSize)
            {
                RtlCopyMemory(IntersectInfo->DataFormatBuffer,
                              pDataRange,
                              FormatSize);

                ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
            }
            else
            {
                if (IntersectInfo->SizeOfDataFormatBuffer > 0) {
                    DbgLogError(
                        ("Testcap::AdapterFormatFromRange: "
                         "SubFormat==NABTS, Buffer too small=%d vs. %d\n",
                         IntersectInfo->SizeOfDataFormatBuffer,
                         FormatSize));
                }
                pSrb->Status = STATUS_BUFFER_TOO_SMALL;
                return FALSE;
            }

            break;

        } // End of KS_SUBTYPE_NABTS

        // -------------------------------------------------------------------
        // for CC pin
        // -------------------------------------------------------------------

        else if (IsEqualGUID (&DataRange->SubFormat,
                &KSDATAFORMAT_SUBTYPE_CC))
        {
            PKSDATARANGE pDataRange = (PKSDATARANGE)*pAvailableFormats;

            // MATCH FOUND!
            MatchFound = TRUE;

            FormatSize = sizeof (KSDATAFORMAT);

            // Is the caller trying to get the format, or the size of it?
            if (OnlyWantsSize)
                break;

            // Verify that there is enough room in the supplied buffer
            //   for the whole thing
            if (IntersectInfo->SizeOfDataFormatBuffer >= FormatSize)
            {
                RtlCopyMemory(IntersectInfo->DataFormatBuffer,
                              pDataRange,
                              FormatSize);

                ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
            }
            else
            {
                if (IntersectInfo->SizeOfDataFormatBuffer > 0) {
                    DbgLogError(
                        ("Testcap::AdapterFormatFromRange: "
                         "SubFormat==CC, Buffer too small=%d vs. %d\n",
                         IntersectInfo->SizeOfDataFormatBuffer,
                         FormatSize));
                }
                pSrb->Status = STATUS_BUFFER_TOO_SMALL;
                return FALSE;
            }

            break;

        } // End of CC pin format check

        else {
            pSrb->Status = STATUS_NO_MATCH;
            return FALSE;
        }

    } // End of loop on all formats for this stream

    if (!MatchFound) {
        pSrb->Status = STATUS_NO_MATCH;
        return FALSE;
    }

    if (OnlyWantsSize) {
        *(PULONG) IntersectInfo->DataFormatBuffer = FormatSize;
        FormatSize = sizeof(ULONG);
    }
    pSrb->ActualBytesTransferred = FormatSize;
    return TRUE;
}
Пример #2
0
NTSTATUS
CStillPin::
IntersectHandler (
    IN PKSFILTER Filter,
    IN PIRP Irp,
    IN PKSP_PIN PinInstance,
    IN PKSDATARANGE CallerDataRange,
    IN PKSDATARANGE DescriptorDataRange,
    IN ULONG BufferSize,
    OUT PVOID Data OPTIONAL,
    OUT PULONG DataSize
)

/*++

Routine Description:

    This routine handles video pin intersection queries by determining the
    intersection between two data ranges.

Arguments:

    Filter -
        Contains a void pointer to the  filter structure.

    Irp -
        Contains a pointer to the data intersection property request.

    PinInstance -
        Contains a pointer to a structure indicating the pin in question.

    CallerDataRange -
        Contains a pointer to one of the data ranges supplied by the client
        in the data intersection request.  The format type, subtype and
        specifier are compatible with the DescriptorDataRange.

    DescriptorDataRange -
        Contains a pointer to one of the data ranges from the pin descriptor
        for the pin in question.  The format type, subtype and specifier are
        compatible with the CallerDataRange.

    BufferSize -
        Contains the size in bytes of the buffer pointed to by the Data
        argument.  For size queries, this value will be zero.

    Data -
        Optionally contains a pointer to the buffer to contain the data
        format structure representing the best format in the intersection
        of the two data ranges.  For size queries, this pointer will be
        NULL.

    DataSize -
        Contains a pointer to the location at which to deposit the size
        of the data format.  This information is supplied by the function
        when the format is actually delivered and in response to size
        queries.

Return Value:

    STATUS_SUCCESS if there is an intersection and it fits in the supplied
    buffer, STATUS_BUFFER_OVERFLOW for successful size queries,
    STATUS_NO_MATCH if the intersection is empty, or
    STATUS_BUFFER_TOO_SMALL if the supplied buffer is too small.

--*/

{
    PAGED_CODE();
    DBGU_TRACE("Enter CStillPin::IntersectHandler\n");

    const GUID VideoInfoSpecifier =
    {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};

    ASSERT(Filter);
    ASSERT(Irp);
    ASSERT(PinInstance);
    ASSERT(CallerDataRange);
    ASSERT(DescriptorDataRange);
    ASSERT(DataSize);

    ULONG DataFormatSize;

    //
    // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER2
    //
    if (IsEqualGUID(CallerDataRange->Specifier, VideoInfoSpecifier) &&
            CallerDataRange -> FormatSize >= sizeof (KS_DATARANGE_VIDEO)) {

        PKS_DATARANGE_VIDEO callerDataRange =
            reinterpret_cast <PKS_DATARANGE_VIDEO> (CallerDataRange);

        PKS_DATARANGE_VIDEO descriptorDataRange =
            reinterpret_cast <PKS_DATARANGE_VIDEO> (DescriptorDataRange);

        PKS_DATAFORMAT_VIDEOINFOHEADER FormatVideoInfoHeader;

        //
        // Check that the other fields match
        //
        if ((callerDataRange->bFixedSizeSamples !=
                descriptorDataRange->bFixedSizeSamples) ||
                (callerDataRange->bTemporalCompression !=
                 descriptorDataRange->bTemporalCompression) ||
                (callerDataRange->StreamDescriptionFlags !=
                 descriptorDataRange->StreamDescriptionFlags) ||
                (callerDataRange->MemoryAllocationFlags !=
                 descriptorDataRange->MemoryAllocationFlags) ||
                (RtlCompareMemory (&callerDataRange->ConfigCaps,
                                   &descriptorDataRange->ConfigCaps,
                                   sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
                 sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)))
        {
            DBGU_TRACE("Check that the other fields match, return STATUS_NO_MATCH\n");
            return STATUS_NO_MATCH;
        }

        //
        // KS_SIZE_VIDEOHEADER() below is relying on bmiHeader.biSize from
        // the caller's data range.  This **MUST** be validated; the
        // extended bmiHeader size (biSize) must not extend past the end
        // of the range buffer.  Possible arithmetic overflow is also
        // checked for.
        //
        {
            ULONG VideoHeaderSize = KS_SIZE_VIDEOHEADER (
                                        &callerDataRange->VideoInfoHeader
                                    );

            ULONG DataRangeSize =
                FIELD_OFFSET (KS_DATARANGE_VIDEO, VideoInfoHeader) +
                VideoHeaderSize;

            DBGU_TRACE("X=%d, Y=%d, BI=%d\n",callerDataRange->VideoInfoHeader.bmiHeader.biWidth,
                       callerDataRange->VideoInfoHeader.bmiHeader.biHeight,
                       callerDataRange->VideoInfoHeader.bmiHeader.biBitCount);
            //
            // Check that biSize does not extend past the buffer.  The
            // first two checks are for arithmetic overflow on the
            // operations to compute the alleged size.  (On unsigned
            // math, a+b < a iff an arithmetic overflow occurred).
            //
            if (VideoHeaderSize < callerDataRange->VideoInfoHeader.bmiHeader.biSize ||
                    DataRangeSize < VideoHeaderSize ||
                    DataRangeSize > callerDataRange -> DataRange.FormatSize
               ) {
                DBGU_TRACE("Check that biSize, return STATUS_INVALID_PARAMETER\n");
                return STATUS_INVALID_PARAMETER;
            }
        }

        DataFormatSize =
            sizeof (KSDATAFORMAT) +
            KS_SIZE_VIDEOHEADER (&callerDataRange->VideoInfoHeader);

        //
        // If the passed buffer size is 0, it indicates that this is a size
        // only query.  Return the size of the intersecting data format and
        // pass back STATUS_BUFFER_OVERFLOW.
        //
        if (BufferSize == 0) {
            *DataSize = DataFormatSize;
            DBGU_TRACE("the passed buffer size is 0, return STATUS_BUFFER_OVERFLOW\n");
            return STATUS_BUFFER_OVERFLOW;
        }

        //
        // Verify that the provided structure is large enough to
        // accept the result.
        //
        if (BufferSize < DataFormatSize)
        {
            DBGU_TRACE("Verify buffer large enough, return STATUS_BUFFER_TOO_SMALL\n");
            return STATUS_BUFFER_TOO_SMALL;
        }

        //
        // Copy over the KSDATAFORMAT, followed by the actual VideoInfoHeader
        //
        *DataSize = DataFormatSize;

        FormatVideoInfoHeader = PKS_DATAFORMAT_VIDEOINFOHEADER( Data );

        //
        // Copy over the KSDATAFORMAT.  This is precisely the same as the
        // KSDATARANGE (it's just the GUIDs, etc...  not the format information
        // following any data format.
        //
        RtlCopyMemory (
            &FormatVideoInfoHeader->DataFormat,
            DescriptorDataRange,
            sizeof (KSDATAFORMAT));

        FormatVideoInfoHeader->DataFormat.FormatSize = DataFormatSize;

        //
        // Copy over the callers requested VIDEOINFOHEADER
        //

        RtlCopyMemory (
            &FormatVideoInfoHeader->VideoInfoHeader,
            &callerDataRange->VideoInfoHeader,
            KS_SIZE_VIDEOHEADER (&callerDataRange->VideoInfoHeader)
        );

        //
        // Calculate biSizeImage for this request, and put the result in both
        // the biSizeImage field of the bmiHeader AND in the SampleSize field
        // of the DataFormat.
        //
        // Note that for compressed sizes, this calculation will probably not
        // be just width * height * bitdepth
        //
        FormatVideoInfoHeader->VideoInfoHeader.bmiHeader.biSizeImage =
            FormatVideoInfoHeader->DataFormat.SampleSize =
                KS_DIBSIZE (FormatVideoInfoHeader->VideoInfoHeader.bmiHeader);

        //
        // REVIEW - Perform other validation such as cropping and scaling checks
        //
        DBGU_TRACE("REVIEW - Perform other validation such as cropping and scaling checks\n");
        return STATUS_SUCCESS;

    } // End of VIDEOINFOHEADER specifier

    DBGU_TRACE("End of VIDEOINFOHEADER specifier, return STATUS_NO_MATCH\n");
    return STATUS_NO_MATCH;
}
Пример #3
0
static
NTSTATUS
VideoOutIntersectDataFormat(
    IN PVOID piKSFilter,                    //Pointer to KS filter structure.
    IN PIRP pIrp,                           //Pointer to data intersection
                                            //property request.
    IN PKSP_PIN pPinInstance,               //Pinter to structure indicating
                                            //pin in question.
    IN PKSDATARANGE pCallerDataRange,       //Pointer to the caller data
                                            //structure that should be
                                            //intersected.
    IN PKSDATARANGE pDescriptorDataRange,   //Pointer to the descriptor data

    IN DWORD dwBufferSize,                  //Size in bytes of the target
                                            //buffer structure. For size
                                            //queries, this value will be zero.
    OUT OPTIONAL PVOID pData,               //Pointer to the target data
                                            //structure representing the best
                                            //format in the intersection.
    OUT PDWORD pdwDataSize                  //Pointer to size of target data
                                            //format structure.
     )
{

	PKSFILTER pKSFilter = (PKSFILTER) piKSFilter;

	//invalid parameters?
    if( !pKSFilter || !pIrp || !pPinInstance ||
        !pCallerDataRange || !pDescriptorDataRange || !pdwDataSize )
    {
		DbgPrint("SWTANALOG-Capture VideoOut UNSUCCESSFUL");
        return STATUS_UNSUCCESSFUL;
    }

    NTSTATUS Status = STATUS_UNSUCCESSFUL;

    //set output data size
    if (IsEqualGUID(pDescriptorDataRange->Specifier,
		    KSDATAFORMAT_SPECIFIER_VIDEOINFO)) 
	{    

		//*** start intersection ***//

		//check if given datarange GUID matches to our datarange information
		if( pCallerDataRange->FormatSize != sizeof(KS_DATARANGE_VIDEO) )
		{
			DbgPrint("SWTANALOG-Capture VideoOut NO_MATCH 1");
			return STATUS_NO_MATCH;
		}

		//map given data ranges on video information structures
		//for some reason only a subpart of the KS_DATARANGE_VIDEO is used for intersection
		//this subpart is casted to KS_DATAFORMAT_VIDEOINFOHEADER and contains only
		//KSDATAFORMAT and KS_VIDEOINFOHEADER, see pTargetVideoDataRange
		PKS_DATARANGE_VIDEO pCallerVideoDataRange =
			reinterpret_cast <PKS_DATARANGE_VIDEO> (pCallerDataRange);
		PKS_DATARANGE_VIDEO pDescriptorVideoDataRange =
			reinterpret_cast <PKS_DATARANGE_VIDEO> (pDescriptorDataRange);
		PKS_DATAFORMAT_VIDEOINFOHEADER pTargetVideoDataRange =
			reinterpret_cast <PKS_DATAFORMAT_VIDEOINFOHEADER> (pData);

		//check if all other important fields match
		if( pCallerVideoDataRange->bFixedSizeSamples        !=
			pDescriptorVideoDataRange->bFixedSizeSamples        ||
			pCallerVideoDataRange->bTemporalCompression     !=
			pDescriptorVideoDataRange->bTemporalCompression     ||
			pCallerVideoDataRange->StreamDescriptionFlags   !=
			pDescriptorVideoDataRange->StreamDescriptionFlags   ||
			pCallerVideoDataRange->MemoryAllocationFlags    !=
			pDescriptorVideoDataRange->MemoryAllocationFlags    ||

			(RtlCompareMemory(&pCallerVideoDataRange->ConfigCaps,
			&pDescriptorVideoDataRange->ConfigCaps,
			sizeof(KS_VIDEO_STREAM_CONFIG_CAPS))) !=
			sizeof(KS_VIDEO_STREAM_CONFIG_CAPS)    )
		{
			DbgPrint("SWTANALOG-Capture VideoOut NO_MATCH 2");
			return STATUS_NO_MATCH;
		}

		{
			ULONG VideoHeaderSize = KS_SIZE_VIDEOHEADER(
				&pCallerVideoDataRange->VideoInfoHeader
				);
			ULONG DataRangeSize = 
				FIELD_OFFSET(KS_DATARANGE_VIDEO, VideoInfoHeader) +
				VideoHeaderSize;
			if (
				VideoHeaderSize < pCallerVideoDataRange->
				VideoInfoHeader.bmiHeader.biSize ||
				DataRangeSize < VideoHeaderSize ||
				DataRangeSize > pCallerVideoDataRange->
				DataRange.FormatSize
				)
			{
				DbgPrint("SWTANALOG-Capture VideoOut INVALID_PARAMETER 1");
				return STATUS_INVALID_PARAMETER;
			}
		}

		ULONG FormatSize;
		FormatSize = sizeof(KSDATAFORMAT) + 
			KS_SIZE_VIDEOHEADER (&pCallerVideoDataRange->VideoInfoHeader);

		*pdwDataSize = FormatSize;

		DbgPrint("SWTANALOG-Capture VideoOut DataSize %d", FormatSize);

		//check for size only query
		if( dwBufferSize == 0 )
		{
			DbgPrint("SWTANALOG-Capture VideoOut BUFFER_OVERFLOW 1 ");
			return STATUS_BUFFER_OVERFLOW;
		}


		//check if output buffer size is sufficient
		if( dwBufferSize < *pdwDataSize )
		{
			DbgPrint("SWTANALOG-Capture VideoOut TOO_SMALL 1");
			return STATUS_BUFFER_TOO_SMALL;
		}

		//copy the data range structure from our decriptor into the target format buffer,
		//for some reason two different names where given to the same structure
		//KSDATARANGE equals exactly KSDATAFORMAT
		pTargetVideoDataRange->DataFormat =
			static_cast <KSDATAFORMAT> (pDescriptorVideoDataRange->DataRange);

		//as mentioned above the target data range structure differs from the
		//caller and the descriptor structures, so the size is also different
		//and has to be set correctly
		pTargetVideoDataRange->DataFormat.FormatSize = *pdwDataSize;

		//copy the video info header structure from the caller into the target
		//buffer,we have to check at this time whether the requested caller
		//video format fits our capabilities (not implemented right now)
		RtlCopyMemory(
			&pTargetVideoDataRange->VideoInfoHeader,
			&pCallerVideoDataRange->VideoInfoHeader,
			KS_SIZE_VIDEOHEADER (&pCallerVideoDataRange->VideoInfoHeader));

		//If there is a format change (e.g. a new resolution) the size is not updated
		//automatically, so we have to calculate it here. There is a macro that multiplies
		//the width and height and that also aligns the size to DWORDs
		pTargetVideoDataRange->VideoInfoHeader.bmiHeader.biSizeImage =
			pTargetVideoDataRange->DataFormat.SampleSize =
			KS_DIBSIZE(pTargetVideoDataRange->VideoInfoHeader.bmiHeader);

		DbgPrint("SWTANALOG-Capture VideoOut success 1");
		Status = STATUS_SUCCESS;
	} else if (IsEqualGUID(pDescriptorDataRange->Specifier,
	     KSDATAFORMAT_SPECIFIER_VIDEOINFO2)) {

        //*** start intersection ***//

        //check if given datarange GUID matches to our datarange information
        if( pCallerDataRange->FormatSize != sizeof(KS_DATARANGE_VIDEO2) )
        {
			DbgPrint("SWTANALOG-Capture VideoOut NO_MATCH 3");
            return STATUS_NO_MATCH;
        }

        //map given data ranges on video information structures
        //for some reason only a subpart of the KS_DATARANGE_VIDEO is
        //used for intersection this subpart is casted to
        //KS_DATAFORMAT_VIDEOINFOHEADER and contains only
        //KSDATAFORMAT and KS_VIDEOINFOHEADER, see pTargetVideoDataRange
        PKS_DATARANGE_VIDEO2 pCallerVideoDataRange =
            reinterpret_cast <PKS_DATARANGE_VIDEO2> (pCallerDataRange);
        PKS_DATARANGE_VIDEO2 pDescriptorVideoDataRange =
            reinterpret_cast <PKS_DATARANGE_VIDEO2> (pDescriptorDataRange);
        PKS_DATAFORMAT_VIDEOINFOHEADER2 pTargetVideoDataRange =
            reinterpret_cast <PKS_DATAFORMAT_VIDEOINFOHEADER2> (pData);

        //check if all other important fields match
        if( pCallerVideoDataRange->bFixedSizeSamples        !=
                pDescriptorVideoDataRange->bFixedSizeSamples        ||
            pCallerVideoDataRange->bTemporalCompression     !=
                pDescriptorVideoDataRange->bTemporalCompression     ||
            pCallerVideoDataRange->StreamDescriptionFlags   !=
                pDescriptorVideoDataRange->StreamDescriptionFlags   ||
            pCallerVideoDataRange->MemoryAllocationFlags    !=
                pDescriptorVideoDataRange->MemoryAllocationFlags    ||

           (RtlCompareMemory(&pCallerVideoDataRange->ConfigCaps,
                             &pDescriptorVideoDataRange->ConfigCaps,
                             sizeof(KS_VIDEO_STREAM_CONFIG_CAPS))) !=
                             sizeof(KS_VIDEO_STREAM_CONFIG_CAPS)    )
        {
			DbgPrint("SWTANALOG-Capture VideoOut NO_MATCH 4");
            return STATUS_NO_MATCH;
        }

	{
	    ULONG VideoHeaderSize = KS_SIZE_VIDEOHEADER(
		  &pCallerVideoDataRange->VideoInfoHeader
		  );
	    ULONG DataRangeSize = 
		FIELD_OFFSET(KS_DATARANGE_VIDEO, VideoInfoHeader) +
		VideoHeaderSize;
	    if (
		VideoHeaderSize < pCallerVideoDataRange->
		   VideoInfoHeader.bmiHeader.biSize ||
		DataRangeSize < VideoHeaderSize ||
		DataRangeSize > pCallerVideoDataRange->
		   DataRange.FormatSize
		) 
		{
			DbgPrint("SWTANALOG-Capture VideoOut INVALID_PARAMETER 2");
		return STATUS_INVALID_PARAMETER;
	    }
	}

	ULONG FormatSize;
	FormatSize = sizeof(KSDATAFORMAT) + 
	    KS_SIZE_VIDEOHEADER (&pCallerVideoDataRange->VideoInfoHeader);


        *pdwDataSize = FormatSize;

        //check for size only query
        if( dwBufferSize == 0 )
        {
			DbgPrint("SWTANALOG-Capture VideoOut BUFFER_OVERFLOW 2");
            return STATUS_BUFFER_OVERFLOW;
        }

        //check if output buffer size is sufficient
        if( dwBufferSize < *pdwDataSize )
        {
			DbgPrint("SWTANALOG-Capture VideoOut TOO_SMALL 2");
            return STATUS_BUFFER_TOO_SMALL;
        }

        //copy the data range structure from our decriptor into the target
        //format buffer, for some reason two different names where given
        //to the same structure KSDATARANGE equals exactly KSDATAFORMAT
        pTargetVideoDataRange->DataFormat =
            static_cast <KSDATAFORMAT> (pDescriptorVideoDataRange->DataRange);
        //as mentioned above the target data range structure differs from the
        //caller and the descriptor structures, so the size is also different
        //and has to be set correctly
        pTargetVideoDataRange->DataFormat.FormatSize = *pdwDataSize;

        //copy the video info header structure from the caller into the target
        //buffer, we have to check at this time whether the requested caller
        //video formatfits our capabilities (not implemented right now)
	RtlCopyMemory(
	    &pTargetVideoDataRange->VideoInfoHeader2,
	    &pCallerVideoDataRange->VideoInfoHeader,
	    KS_SIZE_VIDEOHEADER (&pCallerVideoDataRange->VideoInfoHeader));

        //If there is a format change (e.g. a new resolution) the size is
        //not updated automatically, so we have to calculate it here.
        //There is a macro that multiplies the width and height and that
        //also aligns the size to DWORDs
        pTargetVideoDataRange->VideoInfoHeader2.bmiHeader.biSizeImage =
            pTargetVideoDataRange->DataFormat.SampleSize =
            KS_DIBSIZE(pTargetVideoDataRange->VideoInfoHeader2.bmiHeader);

		DbgPrint("SWTANALOG-Capture VideoOut success 2");
        Status = STATUS_SUCCESS;
    } 
	else 
	{
		*pdwDataSize = 0;
		DbgPrint("SWTANALOG-Capture VideoOut NO_MATCH 5");
		Status = STATUS_NO_MATCH;
    }

    return Status;
}