?? pindevice.cpp.svn-base
字號:
m_pStreamDescriptorList[ m_dwBufferCount ].pCsStreamDescriptorExternal = NULL;
m_pStreamDescriptorList[ m_dwBufferCount ].m_fBusy = TRUE;
m_dwBufferCount++;
}
else if( GetCurrentMemoryModel() == CSPROPERTY_BUFFER_CLIENT_LIMITED )
{
// The software is allocated by the software, let's copy the descriptor and generate a handle
ASSERT( m_pStreamDescriptorList[ m_dwBufferCount ].m_fBusy == FALSE );
if( !CeSafeCopyMemory( &( m_pStreamDescriptorList[ m_dwBufferCount ].csStreamDescriptorShadow ), pOutBuf, sizeof( CS_STREAM_DESCRIPTOR )))
{
dwError = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// Let's populate the handle and the buffer field.
dwError = SwSetupStreamDescriptor( m_dwBufferCount, &( m_pStreamDescriptorList[ m_dwBufferCount ].csStreamDescriptorShadow ), pOutBuf );
if( dwError != ERROR_SUCCESS )
{
goto Cleanup;
}
m_pStreamDescriptorList[ m_dwBufferCount ].pCsStreamDescriptorExternal = NULL;
m_pStreamDescriptorList[ m_dwBufferCount ].m_fBusy = TRUE;
m_dwBufferCount++;
}
else if( GetCurrentMemoryModel() == CSPROPERTY_BUFFER_CLIENT_UNLIMITED )
{
// let's find a slot available
DWORD dwAvailableRow = -1;
for( DWORD i = 0; ( i < m_ulMaxNumOfBuffers ) && ( dwAvailableRow == -1 ); i++ )
{
if( m_pStreamDescriptorList[ i ].m_fBusy == FALSE )
{
dwAvailableRow = i;
}
}
if( dwAvailableRow == -1 )
{
goto Cleanup;
}
if( !CeSafeCopyMemory( &( m_pStreamDescriptorList[ dwAvailableRow ].csStreamDescriptorShadow ), pOutBuf, sizeof( CS_STREAM_DESCRIPTOR )))
{
dwError = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
dwError = SwSetupStreamDescriptor( dwAvailableRow, &( m_pStreamDescriptorList[ dwAvailableRow ].csStreamDescriptorShadow ), pOutBuf );
if( dwError != ERROR_SUCCESS )
{
goto Cleanup;
}
m_pStreamDescriptorList[ dwAvailableRow ].pCsStreamDescriptorExternal = NULL;
m_pStreamDescriptorList[ dwAvailableRow ].m_fBusy = TRUE;
m_dwBufferCount++;
}
Cleanup:
LeaveCriticalSection( &m_csStreamBuffer );
return dwError;
}
DWORD
CPinDevice::DeallocateBuffer( LPVOID pOutBuf )
{
LPVOID lpBuffer;
DWORD dwHandle;
DWORD dwIndex;
DWORD dwError = ERROR_SUCCESS;
PCS_STREAM_DESCRIPTOR pCsDescriptor;
pCsDescriptor = (PCS_STREAM_DESCRIPTOR) pOutBuf;
lpBuffer = pCsDescriptor->CsStreamHeader.Data;
dwHandle = pCsDescriptor->CsStreamHeader.Handle;
// Get the entry for this buffer in the internal list
EnterCriticalSection( &m_csStreamBuffer );
dwIndex = GetIndexFromHandle( dwHandle, lpBuffer );
if( dwIndex == -1 )
{
dwError = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// If the row is not in use, let's make it available
if( m_pStreamDescriptorList[ dwIndex ].pCsStreamDescriptorExternal != NULL )
{
dwError = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
ASSERT( m_pStreamDescriptorList[ dwIndex ].m_fBusy == TRUE );
m_pStreamDescriptorList[ dwIndex ].m_fBusy = FALSE;
m_dwBufferCount--;
DEBUGMSG(ZONE_INIT, (_T("DeallocateBuffer (%s): Index = %d\r\n"), STILL == m_ulPinId ? L"Still" : L"Preview/Capture", dwIndex));
if( GetCurrentMemoryModel() == CSPROPERTY_BUFFER_DRIVER )
{
// We release the buffer.
RemoteLocalFree( m_pStreamDescriptorList[ dwIndex ].csStreamDescriptorShadow.CsStreamHeader.Data );
m_pStreamDescriptorList[ dwIndex ].csStreamDescriptorShadow.CsStreamHeader.Data = NULL;
pCsDescriptor->CsStreamHeader.Data = NULL;
}
Cleanup:
LeaveCriticalSection( &m_csStreamBuffer );
return dwError;
}
DWORD
CPinDevice::SwSetupStreamDescriptor(
DWORD dwIndex,
PCS_STREAM_DESCRIPTOR pCsStreamDesc,
LPVOID pBuffer // Warning: This is an unsafe buffer, use with caution
)
{
DWORD dwHandle;
PCS_STREAM_DESCRIPTOR pCsStreamDescExt = ( PCS_STREAM_DESCRIPTOR ) pBuffer;
if(( pCsStreamDesc == NULL ) || ( pBuffer == NULL ))
{
return ERROR_INVALID_PARAMETER;
}
dwHandle = CreateHandle( dwIndex, pBuffer );
__try
{
pCsStreamDescExt->CsStreamHeader.Handle = dwHandle;
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return ERROR_INVALID_PARAMETER;
}
pCsStreamDesc->CsStreamHeader.Handle = dwHandle;
return ERROR_SUCCESS;
}
DWORD
CPinDevice::HwSetupStreamDescriptor(
DWORD dwIndex
)
{
PCSSTREAM_HEADER pCsStreamHeader;
PCS_FRAME_INFO pCsFrameInfo;
if( dwIndex > m_dwBufferCount )
{
return ERROR_INVALID_PARAMETER;
}
m_ulFrameSize = CS__DIBSIZE (m_CsDataRangeVideo.VideoInfoHeader.bmiHeader);
pCsStreamHeader = &( m_pStreamDescriptorList[ dwIndex ].csStreamDescriptorShadow.CsStreamHeader );
pCsFrameInfo = &( m_pStreamDescriptorList[ dwIndex ].csStreamDescriptorShadow.CsFrameInfo );
pCsStreamHeader->Size = sizeof(CSSTREAM_HEADER);
pCsStreamHeader->TypeSpecificFlags = 0;
pCsStreamHeader->PresentationTime.Time = 0;
pCsStreamHeader->PresentationTime.Numerator = 1;
pCsStreamHeader->PresentationTime.Denominator = 1;
pCsStreamHeader->Duration = 0;
pCsStreamHeader->FrameExtent = m_ulFrameSize;
pCsStreamHeader->DataUsed = m_ulFrameSize;
pCsStreamHeader->OptionsFlags = CSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
pCsFrameInfo->ExtendedHeaderSize = sizeof(CS_FRAME_INFO);
pCsFrameInfo->dwFrameFlags = CS_VIDEO_FLAG_FRAME;
pCsFrameInfo->PictureNumber = 0;
pCsFrameInfo->DropCount = 0;
// Note: RemoteLocalAlloc can't really trigger an exception, the __try/__except block is here
// to highlight the fact that this call has to be protected in the case of a hardware access.
__try
{
pCsStreamHeader->Data = RemoteLocalAlloc( LPTR, m_ulFrameSize );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return ERROR_INTERNAL_ERROR;
}
if( NULL == pCsStreamHeader->Data )
{
return ERROR_OUTOFMEMORY;
}
// And setup the handle
pCsStreamHeader->Handle = CreateHandle( dwIndex, pCsStreamHeader->Data );
return ERROR_SUCCESS;
}
DWORD
CPinDevice::CreateHandle(
DWORD dwIndex,
LPVOID pBuffer
)
{
DWORD dwHandle;
HANDLE hProcess = GetCallerProcess();
dwHandle = (DWORD) hProcess ^ (( dwIndex << 16 ) + ( (DWORD)pBuffer & 0xFFFF ));
return dwHandle;
}
DWORD
CPinDevice::GetIndexFromHandle(
DWORD dwHandle,
LPVOID pBuffer // Warning: This is an unsafe buffer, use with caution
)
{
DWORD dwIndex = -1;
HANDLE hProcess = GetCallerProcess();
// TODO: let's retrieve the index from the handle table and make sure we have a match
dwIndex = ( dwHandle ^ (DWORD)hProcess ) >> 16;
if( dwIndex >= m_ulMaxNumOfBuffers )
{
// Invalid index, bail out
return -1;
}
if( ( m_pStreamDescriptorList[ dwIndex ].csStreamDescriptorShadow.CsStreamHeader.Data != pBuffer )
||( m_pStreamDescriptorList[ dwIndex ].csStreamDescriptorShadow.CsStreamHeader.Handle != dwHandle ))
{
// Something's wrong, bail out
return -1;
}
return dwIndex;
}
DWORD
CPinDevice::EnqueueDescriptor( LPVOID pOutBuf )
{
LPVOID lpBuffer, lpMappedBuffer;
DWORD dwHandle;
DWORD dwIndex;
DWORD dwSize;
DWORD dwError = ERROR_INVALID_PARAMETER;
PCS_VIDEOINFOHEADER pCsVideoInfoHdr;
PCS_STREAM_DESCRIPTOR pCsDescriptor;
DEBUGMSG( ZONE_IOCTL, ( _T("PIN_IOControl(%08x): EnqueueDescriptor\r\n"), this ) );
if( m_CsState == CSSTATE_STOP )
{
return ERROR_SERVICE_NOT_ACTIVE;
}
pCsDescriptor = (PCS_STREAM_DESCRIPTOR) pOutBuf;
// First, let's use the handle and the buffer to retrieve the shadow copy
// If an exception happens during the following 2 lines, it will be trapped by the upper level
lpBuffer = pCsDescriptor->CsStreamHeader.Data;
dwHandle = pCsDescriptor->CsStreamHeader.Handle;
EnterCriticalSection( &m_csStreamBuffer );
// Get the entry for this buffer in the internal list
dwIndex = GetIndexFromHandle( dwHandle, lpBuffer );
if( dwIndex == -1 )
{
goto Cleanup;
}
// Is the row in use?
if( m_pStreamDescriptorList[ dwIndex ].m_fBusy == FALSE )
{
DEBUGMSG( ZONE_IOCTL|ZONE_ERROR, ( _T("PIN_IOControl(%08x): The buffer has not be prepared. Call CS_ALLOCATE first.\r\n"), this ) );
goto Cleanup;
}
if( m_pStreamDescriptorList[ dwIndex ].pCsStreamDescriptorExternal != NULL )
{
DEBUGMSG( ZONE_IOCTL|ZONE_ERROR, ( _T("PIN_IOControl(%08x): This buffer has already be enqueued.\r\n"), this ) );
goto Cleanup;
}
// Now, let's probe the incoming buffer
pCsVideoInfoHdr = reinterpret_cast<PCS_VIDEOINFOHEADER>( &m_CsDataRangeVideo.VideoInfoHeader );
dwSize = abs( pCsVideoInfoHdr->bmiHeader.biHeight ) * CS_DIBWIDTHBYTES( pCsVideoInfoHdr->bmiHeader );
lpMappedBuffer = (LPVOID) MapCallerPtr( lpBuffer, dwSize );
if( lpMappedBuffer == NULL )
{
DEBUGMSG( ZONE_IOCTL|ZONE_ERROR, ( _T("PIN_IOControl(%08x): MapCallerPtr failed for incoming pointer \r\n"), this ) );
goto Cleanup;
}
// Finally, set the internal table
m_pStreamDescriptorList[ dwIndex ].csStreamDescriptorShadow.CsStreamHeader.Data = lpMappedBuffer;
m_pStreamDescriptorList[ dwIndex ].pCsStreamDescriptorExternal = pCsDescriptor;
dwError = ERROR_SUCCESS;
Cleanup:
LeaveCriticalSection( &m_csStreamBuffer );
return dwError;
}
bool
CPinDevice::RemoveBufferFromList(
PCS_STREAM_DESCRIPTOR * ppCsStreamDesc,
PVOID * ppMappedData,
PVOID * ppUnmappedData
)
{
DWORD dwCounter = 0;
// Let's look in the list of buffers for the first buffer that has a non null external stream descriptor
DEBUGMSG( ZONE_IOCTL, ( _T("PIN_IOControl(%08x): RemoveBufferFromList\r\n"), this ) );
if(( ppCsStreamDesc == NULL ) || ( ppMappedData == NULL ) || ( ppUnmappedData == NULL ))
{
DEBUGMSG( ZONE_IOCTL|ZONE_ERROR, ( _T("PIN_IOControl(%08x): RemoveBufferFromList - Null pointer has been passed in.\r\n"), this ) );
return false;
}
*ppCsStreamDesc = NULL;
EnterCriticalSection( &m_csStreamBuffer );
while(( dwCounter < m_dwBufferCount ) && ( *ppCsStreamDesc == NULL ))
{
if( m_pStreamDescriptorList[ dwCounter ].pCsStreamDescriptorExternal != NULL )
{
// We found one registered buffer. Let's return it.
*ppCsStreamDesc = m_pStreamDescriptorList[ dwCounter ].pCsStreamDescriptorExternal;
*ppMappedData = m_pStreamDescriptorList[ dwCounter ].csStreamDescriptorShadow.CsStreamHeader.Data;
*ppUnmappedData = m_pStreamDescriptorList[ dwCounter ].pCsStreamDescriptorExternal->CsStreamHeader.Data;
m_pStreamDescriptorList[ dwCounter ].pCsStreamDescriptorExternal = NULL;
m_pStreamDescriptorList[ dwCounter ].csStreamDescriptorShadow.CsStreamHeader.Data = *ppUnmappedData;
}
dwCounter++;
}
LeaveCriticalSection( &m_csStreamBuffer );
return true;
}
bool
CPinDevice::ResetBufferList()
{
EnterCriticalSection( &m_csStreamBuffer );
for( DWORD i = 0; i < m_dwBufferCount; i++ )
{
m_pStreamDescriptorList[ i ].pCsStreamDescriptorExternal = NULL;
m_pStreamDescriptorList[ i ].m_fBusy = FALSE;
}
LeaveCriticalSection( &m_csStreamBuffer );
return true;
}
bool
CPinDevice::ReadMemoryModelFromRegistry()
{
HKEY hKey = 0;
DWORD dwType = 0;
DWORD dwSize = sizeof ( DWORD );
DWORD dwValue = -1;
if( ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"Drivers\\Capture\\NullCam", 0, 0, &hKey ))
{
false;
}
if( ERROR_SUCCESS == RegQueryValueEx( hKey, L"MemoryModel", 0, &dwType, (BYTE *)&dwValue, &dwSize ) )
{
if( ( REG_DWORD == dwType )
&& ( sizeof( DWORD ) == dwSize )
&& (( dwValue == CSPROPERTY_BUFFER_DRIVER ) || ( dwValue == CSPROPERTY_BUFFER_CLIENT_LIMITED ) || ( dwValue == CSPROPERTY_BUFFER_CLIENT_UNLIMITED )))
{
m_dwMemoryModel = (CSPROPERTY_BUFFER_MODE) dwValue;
}
}
RegCloseKey( hKey );
return true;
}
CSPROPERTY_BUFFER_MODE CPinDevice::GetCurrentMemoryModel()
{
return CSPROPERTY_BUFFER_CLIENT_LIMITED;
return m_dwMemoryModel;
}
DWORD CPinDevice::GetMaxBufferCount()
{
return MAX_BUFFER_COUNT;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -