📄 savedata.cpp
字号:
);
if (!m_FileName.Buffer)
{
DPF(D_TERSE, ("[Could not allocate memory for FileName]"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
// Allocate memory for data buffer.
//
if (NT_SUCCESS(ntStatus))
{
wcscpy(m_FileName.Buffer, szTemp);
m_FileName.Length = wcslen(m_FileName.Buffer) * sizeof(WCHAR);
DPF(D_BLAB, ("[New DataFile -- %s", m_FileName.Buffer));
m_pDataBuffer = (PBYTE)
ExAllocatePoolWithTag
(
NonPagedPool,
m_ulBufferSize,
MSVAD_POOLTAG
);
if (!m_pDataBuffer)
{
DPF(D_TERSE, ("[Could not allocate memory for Saving Data]"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
// Allocate memory for frame usage flags and m_pFilePtr.
//
if (NT_SUCCESS(ntStatus))
{
m_fFrameUsed = (PBOOL)
ExAllocatePoolWithTag
(
NonPagedPool,
m_ulFrameCount * sizeof(BOOL) +
sizeof(LARGE_INTEGER),
MSVAD_POOLTAG
);
if (!m_fFrameUsed)
{
DPF(D_TERSE, ("[Could not allocate memory for frame flags]"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
// Initialize the spinlock to synchronize access to the frames
//
KeInitializeSpinLock ( &m_FrameInUseSpinLock ) ;
// Open the data file.
//
if (NT_SUCCESS(ntStatus))
{
// m_fFrameUsed has additional memory to hold m_pFilePtr
//
m_pFilePtr = (PLARGE_INTEGER)
(((PBYTE) m_fFrameUsed) + m_ulFrameCount * sizeof(BOOL));
RtlZeroMemory(m_fFrameUsed, m_ulFrameCount * sizeof(BOOL));
// Create data file.
InitializeObjectAttributes
(
&m_objectAttributes,
&m_FileName,
OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
NULL,
NULL
);
// Write wave header information to data file.
ntStatus = FileOpen(TRUE);
if (NT_SUCCESS(ntStatus))
{
ntStatus = FileWriteHeader();
FileClose();
}
}
return ntStatus;
} // Initialize
//=============================================================================
NTSTATUS
CSaveData::InitializeWorkItems
(
IN PDEVICE_OBJECT DeviceObject
)
{
PAGED_CODE();
ASSERT(DeviceObject);
NTSTATUS ntStatus = STATUS_SUCCESS;
DPF_ENTER(("[CSaveData::InitializeWorkItems]"));
m_pDeviceObject = DeviceObject;
m_pWorkItems = (PSAVEWORKER_PARAM)
ExAllocatePoolWithTag
(
NonPagedPool,
sizeof(SAVEWORKER_PARAM) * MAX_WORKER_ITEM_COUNT,
MSVAD_POOLTAG
);
if (m_pWorkItems)
{
for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++)
{
#ifdef USE_OBSOLETE_FUNCS
ExInitializeWorkItem
(
&m_pWorkItems[i].WorkItem,
SaveFrameWorkerCallback,
&m_pWorkItems[i]
);
#else
m_pWorkItems[i].WorkItem = IoAllocateWorkItem(DeviceObject);
if(m_pWorkItems[i].WorkItem == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
#endif
KeInitializeEvent
(
&m_pWorkItems[i].EventDone,
NotificationEvent,
TRUE
);
}
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
return ntStatus;
} // InitializeWorkItems
//=============================================================================
void
SaveFrameWorkerCallback
#ifdef USE_OBSOLETE_FUNCS
(
IN PVOID Context
)
#else
(
PDEVICE_OBJECT pDeviceObject, IN PVOID Context
)
#endif
{
PAGED_CODE();
ASSERT(Context);
PSAVEWORKER_PARAM pParam = (PSAVEWORKER_PARAM) Context;
PCSaveData pSaveData;
IO_STATUS_BLOCK ioStatusBlock;
DPF(D_VERBOSE, ("[SaveFrameWorkerCallback], %d", pParam->ulFrameNo));
ASSERT(pParam->pSaveData);
ASSERT(pParam->pSaveData->m_fFrameUsed);
if (pParam->WorkItem)
{
pSaveData = pParam->pSaveData;
if (NT_SUCCESS(pSaveData->FileOpen(FALSE)))
{
pSaveData->FileWrite(pParam->pData, pParam->ulDataSize);
pSaveData->FileClose();
}
InterlockedExchange( (LONG *)&(pSaveData->m_fFrameUsed[pParam->ulFrameNo]), FALSE );
}
KeSetEvent(&pParam->EventDone, 0, FALSE);
} // SaveFrameWorkerCallback
//=============================================================================
NTSTATUS
CSaveData::SetDataFormat
(
IN PKSDATAFORMAT pDataFormat
)
{
PAGED_CODE();
NTSTATUS ntStatus = STATUS_SUCCESS;
DPF_ENTER(("[CSaveData::SetDataFormat]"));
ASSERT(pDataFormat);
PWAVEFORMATEX pwfx = NULL;
if (IsEqualGUIDAligned(pDataFormat->Specifier,
KSDATAFORMAT_SPECIFIER_DSOUND))
{
pwfx =
&(((PKSDATAFORMAT_DSOUND) pDataFormat)->BufferDesc.WaveFormatEx);
}
else if (IsEqualGUIDAligned(pDataFormat->Specifier,
KSDATAFORMAT_SPECIFIER_WAVEFORMATEX))
{
pwfx = &((PKSDATAFORMAT_WAVEFORMATEX) pDataFormat)->WaveFormatEx;
}
if (pwfx)
{
// Free the previously allocated waveformat
if (m_waveFormat)
{
ExFreePool(m_waveFormat);
}
m_waveFormat = (PWAVEFORMATEX)
ExAllocatePoolWithTag
(
NonPagedPool,
(pwfx->wFormatTag == WAVE_FORMAT_PCM) ?
sizeof( PCMWAVEFORMAT ) :
sizeof( WAVEFORMATEX ) + pwfx->cbSize,
MSVAD_POOLTAG
);
if(m_waveFormat)
{
RtlCopyMemory( m_waveFormat,
pwfx,
(pwfx->wFormatTag == WAVE_FORMAT_PCM) ?
sizeof( PCMWAVEFORMAT ) :
sizeof( WAVEFORMATEX ) + pwfx->cbSize);
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
return ntStatus;
} // SetDataFormat
//=============================================================================
void
CSaveData::ReadData
(
IN PBYTE pBuffer,
IN ULONG ulByteCount
)
{
// Not implemented yet.
} // ReadData
//=============================================================================
#pragma code_seg()
void
CSaveData::SaveFrame
(
IN ULONG ulFrameNo,
IN ULONG ulDataSize
)
{
PSAVEWORKER_PARAM pParam = NULL;
DPF_ENTER(("[CSaveData::SaveFrame]"));
pParam = GetNewWorkItem();
if (pParam)
{
pParam->pSaveData = this;
pParam->ulFrameNo = ulFrameNo;
pParam->ulDataSize = ulDataSize;
pParam->pData = m_pDataBuffer + ulFrameNo * m_ulFrameSize;
KeResetEvent(&pParam->EventDone);
#ifdef USE_OBSOLETE_FUNCS
ExQueueWorkItem(&pParam->WorkItem, CriticalWorkQueue);
#else
IoQueueWorkItem(pParam->WorkItem, (PIO_WORKITEM_ROUTINE)SaveFrameWorkerCallback,
CriticalWorkQueue, (PVOID)pParam);
#endif
}
} // SaveFrame
#pragma code_seg("PAGE")
//=============================================================================
void
CSaveData::WaitAllWorkItems
(
void
)
{
DPF_ENTER(("[CSaveData::WaitAllWorkItems]"));
// Save the last partially-filled frame
SaveFrame(m_ulFramePtr, m_ulBufferPtr - (m_ulFramePtr * m_ulFrameSize));
for (int i = 0; i < MAX_WORKER_ITEM_COUNT; i++)
{
DPF(D_VERBOSE, ("[Waiting for WorkItem] %d", i));
KeWaitForSingleObject
(
&(m_pWorkItems[i].EventDone),
Executive,
KernelMode,
FALSE,
NULL
);
}
} // WaitAllWorkItems
#pragma code_seg()
//=============================================================================
void
CSaveData::WriteData
(
IN PBYTE pBuffer,
IN ULONG ulByteCount
)
{
ASSERT(pBuffer);
ASSERT(ulByteCount);
BOOL fSaveFrame = FALSE;
ULONG ulSaveFramePtr;
KIRQL OldIrql;
LARGE_INTEGER timeOut = { 0 };
// If stream writing is disabled, then exit.
//
if (m_fWriteDisabled)
{
return;
}
DPF_ENTER(("[CSaveData::WriteData ulByteCount=%lu]", ulByteCount));
// Check to see if this frame is available.
KeAcquireSpinLockAtDpcLevel( &m_FrameInUseSpinLock );
if (!m_fFrameUsed[m_ulFramePtr])
{
KeReleaseSpinLockFromDpcLevel( &m_FrameInUseSpinLock );
ULONG ulWriteBytes =
(ulByteCount + m_ulBufferPtr < m_ulBufferSize) ?
ulByteCount :
(m_ulBufferSize - m_ulBufferPtr);
RtlCopyMemory(m_pDataBuffer + m_ulBufferPtr, pBuffer, ulWriteBytes);
m_ulBufferPtr += ulWriteBytes;
// Check to see if we need to save this frame
if (m_ulBufferPtr >= ((m_ulFramePtr + 1) * m_ulFrameSize))
{
fSaveFrame = TRUE;
}
// Loop the buffer, if we reached the end.
if (m_ulBufferPtr == m_ulBufferSize)
{
fSaveFrame = TRUE;
m_ulBufferPtr = 0;
}
if (fSaveFrame)
{
InterlockedExchange( (LONG *)&(m_fFrameUsed[m_ulFramePtr]), TRUE );
ulSaveFramePtr = m_ulFramePtr;
m_ulFramePtr = (m_ulFramePtr + 1) % m_ulFrameCount;
}
// Write the left over if the next frame is available.
if (ulWriteBytes != ulByteCount)
{
KeAcquireSpinLockAtDpcLevel( &m_FrameInUseSpinLock );
if (!m_fFrameUsed[m_ulFramePtr])
{
KeReleaseSpinLockFromDpcLevel( &m_FrameInUseSpinLock );
RtlCopyMemory
(
m_pDataBuffer + m_ulBufferPtr,
pBuffer,
ulWriteBytes
);
}
else
{
KeReleaseSpinLockFromDpcLevel( &m_FrameInUseSpinLock );
DPF(D_BLAB, ("[Frame overflow, next frame is in use]"));
}
}
if (fSaveFrame)
{
SaveFrame(ulSaveFramePtr, m_ulFrameSize);
}
}
else
{
KeReleaseSpinLockFromDpcLevel( &m_FrameInUseSpinLock );
DPF(D_BLAB, ("[Frame %d is in use]", m_ulFramePtr));
}
} // WriteData
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -