https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b8e936a57b4770e133772…
commit b8e936a57b4770e133772cf2dd66f30671a1524b
Author: Michael Stamper <michaelstamper1(a)gmail.com>
AuthorDate: Tue Sep 8 21:59:09 2020 +0000
Commit: Stanislav Motylkov <x86corez(a)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;
}