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; }
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; }
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; }