From 38f9ba0070f9b72d8c94d8124b488921078f8018 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=B6rg=20H=C3=B6hle?= Date: Thu, 15 Dec 2011 23:07:41 +0100 Subject: [PATCH] mmdevapi: Enforce limits on period and duration. --- dlls/winealsa.drv/mmdevdrv.c | 31 +++++++++++++++++++++---------- dlls/winecoreaudio.drv/mmdevdrv.c | 32 +++++++++++++++++++++----------- dlls/wineoss.drv/mmdevdrv.c | 30 +++++++++++++++++++++--------- 3 files changed, 63 insertions(+), 30 deletions(-) diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c index 359997e67f0..994628e0125 100644 --- a/dlls/winealsa.drv/mmdevdrv.c +++ b/dlls/winealsa.drv/mmdevdrv.c @@ -835,14 +835,28 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, return E_INVALIDARG; } - if(mode == AUDCLNT_SHAREMODE_EXCLUSIVE && flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK){ - FIXME("EXCLUSIVE mode with EVENTCALLBACK\n"); - return AUDCLNT_E_DEVICE_IN_USE; + if(mode == AUDCLNT_SHAREMODE_SHARED){ + period = DefaultPeriod; + if( duration < 3 * period) + duration = 3 * period; + }else{ + if(!period) + period = DefaultPeriod; /* not minimum */ + if(period < MinimumPeriod || period > 5000000) + return AUDCLNT_E_INVALID_DEVICE_PERIOD; + if(duration > 20000000) /* the smaller the period, the lower this limit */ + return AUDCLNT_E_BUFFER_SIZE_ERROR; + if(flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK){ + if(duration != period) + return AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL; + FIXME("EXCLUSIVE mode with EVENTCALLBACK\n"); + return AUDCLNT_E_DEVICE_IN_USE; + }else{ + if( duration < 8 * period) + duration = 8 * period; /* may grow above 2s */ + } } - if(!duration) - duration = 300000; /* 0.03s */ - EnterCriticalSection(&This->lock); if(This->initted){ @@ -1001,10 +1015,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, goto exit; } - if(period) - This->mmdev_period_rt = period; - else - This->mmdev_period_rt = DefaultPeriod; + This->mmdev_period_rt = period; /* Check if the ALSA buffer is so small that it will run out before * the next MMDevAPI period tick occurs. Allow a little wiggle room diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c index a648429e607..a2c72dae13c 100644 --- a/dlls/winecoreaudio.drv/mmdevdrv.c +++ b/dlls/winecoreaudio.drv/mmdevdrv.c @@ -961,9 +961,26 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, return E_INVALIDARG; } - if(mode == AUDCLNT_SHAREMODE_EXCLUSIVE && flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK){ - FIXME("EXCLUSIVE mode with EVENTCALLBACK\n"); - return AUDCLNT_E_DEVICE_IN_USE; + if(mode == AUDCLNT_SHAREMODE_SHARED){ + period = DefaultPeriod; + if( duration < 3 * period) + duration = 3 * period; + }else{ + if(!period) + period = DefaultPeriod; /* not minimum */ + if(period < MinimumPeriod || period > 5000000) + return AUDCLNT_E_INVALID_DEVICE_PERIOD; + if(duration > 20000000) /* the smaller the period, the lower this limit */ + return AUDCLNT_E_BUFFER_SIZE_ERROR; + if(flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK){ + if(duration != period) + return AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL; + FIXME("EXCLUSIVE mode with EVENTCALLBACK\n"); + return AUDCLNT_E_DEVICE_IN_USE; + }else{ + if( duration < 8 * period) + duration = 8 * period; /* may grow above 2s */ + } } OSSpinLockLock(&This->lock); @@ -987,15 +1004,8 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, return E_OUTOFMEMORY; } - if(period){ - This->period_ms = period / 10000; - if(This->period_ms == 0) - This->period_ms = 1; - }else - This->period_ms = MinimumPeriod / 10000; + This->period_ms = period / 10000; - if(!duration) - duration = 300000; /* 0.03s */ This->bufsize_frames = ceil(fmt->nSamplesPerSec * (duration / 10000000.)); if(This->dataflow == eCapture){ diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c index 571495df992..dbbcd9f40ca 100644 --- a/dlls/wineoss.drv/mmdevdrv.c +++ b/dlls/wineoss.drv/mmdevdrv.c @@ -906,9 +906,26 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, return E_INVALIDARG; } - if(mode == AUDCLNT_SHAREMODE_EXCLUSIVE && flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK){ - FIXME("EXCLUSIVE mode with EVENTCALLBACK\n"); - return AUDCLNT_E_DEVICE_IN_USE; + if(mode == AUDCLNT_SHAREMODE_SHARED){ + period = DefaultPeriod; + if( duration < 3 * period) + duration = 3 * period; + }else{ + if(!period) + period = DefaultPeriod; /* not minimum */ + if(period < MinimumPeriod || period > 5000000) + return AUDCLNT_E_INVALID_DEVICE_PERIOD; + if(duration > 20000000) /* the smaller the period, the lower this limit */ + return AUDCLNT_E_BUFFER_SIZE_ERROR; + if(flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK){ + if(duration != period) + return AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL; + FIXME("EXCLUSIVE mode with EVENTCALLBACK\n"); + return AUDCLNT_E_DEVICE_IN_USE; + }else{ + if( duration < 8 * period) + duration = 8 * period; /* may grow above 2s */ + } } EnterCriticalSection(&This->lock); @@ -937,13 +954,8 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, return E_OUTOFMEMORY; } - if(period) - This->period_us = period / 10; - else - This->period_us = DefaultPeriod / 10; + This->period_us = period / 10; - if(!duration) - duration = 300000; /* 0.03s */ This->bufsize_frames = ceil(fmt->nSamplesPerSec * (duration / 10000000.)); This->local_buffer = HeapAlloc(GetProcessHeap(), 0, This->bufsize_frames * fmt->nBlockAlign); -- 2.11.4.GIT