mirror of
https://github.com/reactos/reactos.git
synced 2025-06-27 17:39:47 +00:00
[WDMAUD] Fix race condition bug with USE_MMIXER_LIB defined (#3148)
Remove misuse of multithreading and use NtDeviceIoContol with completion apc callback instead (mirrors usage of WriteFileEx in WdmAudCommitWaveBufferByLegacy). This fixes a crash caused by race condition. Code was simulating completion callback using a thread, this resulted in single threaded code being executed simultaneously by multiple threads. CORE-17214
This commit is contained in:
parent
4aeb45ce0c
commit
b8e936a57b
1 changed files with 47 additions and 46 deletions
|
@ -12,19 +12,14 @@
|
||||||
#include <winreg.h>
|
#include <winreg.h>
|
||||||
#include <setupapi.h>
|
#include <setupapi.h>
|
||||||
#include <mmixer.h>
|
#include <mmixer.h>
|
||||||
|
#define NTOS_MODE_USER
|
||||||
|
#include <ndk/rtlfuncs.h>
|
||||||
|
#include <ndk/iofuncs.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <mmebuddy_debug.h>
|
#include <mmebuddy_debug.h>
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
KSSTREAM_HEADER Header;
|
|
||||||
HANDLE hDevice;
|
|
||||||
PSOUND_OVERLAPPED Overlap;
|
|
||||||
LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine;
|
|
||||||
DWORD IoCtl;
|
|
||||||
}IO_PACKET, *LPIO_PACKET;
|
|
||||||
|
|
||||||
BOOL MMixerLibraryInitialized = FALSE;
|
BOOL MMixerLibraryInitialized = FALSE;
|
||||||
|
|
||||||
|
@ -785,27 +780,25 @@ WdmAudGetWavePositionByMMixer(
|
||||||
return MMSYSERR_NOTSUPPORTED;
|
return MMSYSERR_NOTSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
static
|
||||||
WINAPI
|
VOID WINAPI
|
||||||
IoStreamingThread(
|
CommitWaveBufferApc(PVOID ApcContext,
|
||||||
LPVOID lpParameter)
|
PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
|
ULONG Reserved)
|
||||||
{
|
{
|
||||||
DWORD Length;
|
DWORD dwErrorCode;
|
||||||
//MMRESULT Result;
|
PSOUND_OVERLAPPED Overlap;
|
||||||
LPIO_PACKET Packet = (LPIO_PACKET)lpParameter;
|
KSSTREAM_HEADER* lpHeader;
|
||||||
|
|
||||||
/*Result = */ SyncOverlappedDeviceIoControl(Packet->hDevice,
|
dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status);
|
||||||
Packet->IoCtl,
|
Overlap = (PSOUND_OVERLAPPED)IoStatusBlock;
|
||||||
NULL,
|
lpHeader = Overlap->CompletionContext;
|
||||||
0,
|
|
||||||
&Packet->Header,
|
|
||||||
sizeof(KSSTREAM_HEADER),
|
|
||||||
&Length);
|
|
||||||
|
|
||||||
Packet->CompletionRoutine(ERROR_SUCCESS, Packet->Header.DataUsed, (LPOVERLAPPED)Packet->Overlap);
|
/* Call mmebuddy overlap routine */
|
||||||
|
Overlap->OriginalCompletionRoutine(dwErrorCode,
|
||||||
|
lpHeader->DataUsed, &Overlap->Standard);
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, Packet);
|
HeapFree(GetProcessHeap(), 0, lpHeader);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MMRESULT
|
MMRESULT
|
||||||
|
@ -819,8 +812,9 @@ WdmAudCommitWaveBufferByMMixer(
|
||||||
PSOUND_DEVICE SoundDevice;
|
PSOUND_DEVICE SoundDevice;
|
||||||
MMDEVICE_TYPE DeviceType;
|
MMDEVICE_TYPE DeviceType;
|
||||||
MMRESULT Result;
|
MMRESULT Result;
|
||||||
LPIO_PACKET Packet;
|
ULONG IoCtl;
|
||||||
HANDLE hThread;
|
KSSTREAM_HEADER* lpHeader;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
|
Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
|
||||||
|
|
||||||
|
@ -832,37 +826,44 @@ WdmAudCommitWaveBufferByMMixer(
|
||||||
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
|
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
|
||||||
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
||||||
|
|
||||||
Packet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IO_PACKET));
|
lpHeader = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KSSTREAM_HEADER));
|
||||||
if ( ! Packet )
|
if ( ! lpHeader )
|
||||||
{
|
{
|
||||||
/* no memory */
|
/* no memory */
|
||||||
return MMSYSERR_NOMEM;
|
return MMSYSERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* setup stream packet */
|
/* setup stream packet */
|
||||||
Packet->Header.Size = sizeof(KSSTREAM_HEADER);
|
lpHeader->Size = sizeof(KSSTREAM_HEADER);
|
||||||
Packet->Header.PresentationTime.Numerator = 1;
|
lpHeader->PresentationTime.Numerator = 1;
|
||||||
Packet->Header.PresentationTime.Denominator = 1;
|
lpHeader->PresentationTime.Denominator = 1;
|
||||||
Packet->Header.Data = OffsetPtr;
|
lpHeader->Data = OffsetPtr;
|
||||||
Packet->Header.FrameExtent = Length;
|
lpHeader->FrameExtent = Length;
|
||||||
Packet->hDevice = SoundDeviceInstance->Handle;
|
Overlap->CompletionContext = lpHeader;
|
||||||
Packet->Overlap = Overlap;
|
Overlap->OriginalCompletionRoutine = CompletionRoutine;
|
||||||
Packet->CompletionRoutine = CompletionRoutine;
|
IoCtl = (DeviceType == WAVE_OUT_DEVICE_TYPE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM);
|
||||||
Packet->IoCtl = (DeviceType == WAVE_OUT_DEVICE_TYPE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM);
|
|
||||||
|
|
||||||
if (DeviceType == WAVE_OUT_DEVICE_TYPE)
|
if (DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||||
{
|
{
|
||||||
Packet->Header.DataUsed = Length;
|
lpHeader->DataUsed = Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
hThread = CreateThread(NULL, 0, IoStreamingThread, (LPVOID)Packet, 0, NULL);
|
Status = NtDeviceIoControlFile(SoundDeviceInstance->Handle,
|
||||||
if (hThread == NULL)
|
NULL,
|
||||||
|
CommitWaveBufferApc,
|
||||||
|
NULL,
|
||||||
|
(PIO_STATUS_BLOCK)Overlap,
|
||||||
|
IoCtl,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
lpHeader,
|
||||||
|
sizeof(KSSTREAM_HEADER));
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* error */
|
DPRINT1("NtDeviceIoControlFile() failed with status %08lx\n", Status);
|
||||||
return MMSYSERR_ERROR;
|
return MMSYSERR_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(hThread);
|
|
||||||
|
|
||||||
return MMSYSERR_NOERROR;
|
return MMSYSERR_NOERROR;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue