https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b8e936a57b4770e133772c...
commit b8e936a57b4770e133772cf2dd66f30671a1524b Author: Michael Stamper michaelstamper1@gmail.com AuthorDate: Tue Sep 8 21:59:09 2020 +0000 Commit: Stanislav Motylkov x86corez@gmail.com CommitDate: Sun Sep 13 01:56:34 2020 +0300
[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 --- dll/win32/wdmaud.drv/mmixer.c | 93 ++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 46 deletions(-)
diff --git a/dll/win32/wdmaud.drv/mmixer.c b/dll/win32/wdmaud.drv/mmixer.c index 9f5810628fe..0f2805f37c6 100644 --- a/dll/win32/wdmaud.drv/mmixer.c +++ b/dll/win32/wdmaud.drv/mmixer.c @@ -12,19 +12,14 @@ #include <winreg.h> #include <setupapi.h> #include <mmixer.h> +#define NTOS_MODE_USER +#include <ndk/rtlfuncs.h> +#include <ndk/iofuncs.h>
#define NDEBUG #include <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;
@@ -785,27 +780,25 @@ WdmAudGetWavePositionByMMixer( return MMSYSERR_NOTSUPPORTED; }
-DWORD -WINAPI -IoStreamingThread( - LPVOID lpParameter) +static +VOID WINAPI +CommitWaveBufferApc(PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG Reserved) { - DWORD Length; - //MMRESULT Result; - LPIO_PACKET Packet = (LPIO_PACKET)lpParameter; - - /*Result = */ SyncOverlappedDeviceIoControl(Packet->hDevice, - Packet->IoCtl, - NULL, - 0, - &Packet->Header, - sizeof(KSSTREAM_HEADER), - &Length); + DWORD dwErrorCode; + PSOUND_OVERLAPPED Overlap; + KSSTREAM_HEADER* lpHeader; + + dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status); + Overlap = (PSOUND_OVERLAPPED)IoStatusBlock; + lpHeader = Overlap->CompletionContext;
- 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); - return 0; + HeapFree(GetProcessHeap(), 0, lpHeader); }
MMRESULT @@ -819,8 +812,9 @@ WdmAudCommitWaveBufferByMMixer( PSOUND_DEVICE SoundDevice; MMDEVICE_TYPE DeviceType; MMRESULT Result; - LPIO_PACKET Packet; - HANDLE hThread; + ULONG IoCtl; + KSSTREAM_HEADER* lpHeader; + NTSTATUS Status;
Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
@@ -832,37 +826,44 @@ WdmAudCommitWaveBufferByMMixer( Result = GetSoundDeviceType(SoundDevice, &DeviceType); SND_ASSERT( Result == MMSYSERR_NOERROR );
- Packet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IO_PACKET)); - if ( ! Packet ) + lpHeader = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KSSTREAM_HEADER)); + if ( ! lpHeader ) { /* no memory */ return MMSYSERR_NOMEM; }
/* setup stream packet */ - Packet->Header.Size = sizeof(KSSTREAM_HEADER); - Packet->Header.PresentationTime.Numerator = 1; - Packet->Header.PresentationTime.Denominator = 1; - Packet->Header.Data = OffsetPtr; - Packet->Header.FrameExtent = Length; - Packet->hDevice = SoundDeviceInstance->Handle; - Packet->Overlap = Overlap; - Packet->CompletionRoutine = CompletionRoutine; - Packet->IoCtl = (DeviceType == WAVE_OUT_DEVICE_TYPE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM); + lpHeader->Size = sizeof(KSSTREAM_HEADER); + lpHeader->PresentationTime.Numerator = 1; + lpHeader->PresentationTime.Denominator = 1; + lpHeader->Data = OffsetPtr; + lpHeader->FrameExtent = Length; + Overlap->CompletionContext = lpHeader; + Overlap->OriginalCompletionRoutine = CompletionRoutine; + IoCtl = (DeviceType == WAVE_OUT_DEVICE_TYPE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM);
if (DeviceType == WAVE_OUT_DEVICE_TYPE) { - Packet->Header.DataUsed = Length; + lpHeader->DataUsed = Length; }
- hThread = CreateThread(NULL, 0, IoStreamingThread, (LPVOID)Packet, 0, NULL); - if (hThread == NULL) + Status = NtDeviceIoControlFile(SoundDeviceInstance->Handle, + 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; } - - CloseHandle(hThread); - + return MMSYSERR_NOERROR; }