Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
September 2019
- 76 participants
- 1410 messages
[PATCH] quartz: Don't cast from COM object to interface
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
The second cast should go too but that requires exposing
struct QualityControlImpl in include/wine/strmbase.h .
dlls/quartz/dsoundrender.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c
index 6451f85b5a..3478f95f51 100644
--- a/dlls/quartz/dsoundrender.c
+++ b/dlls/quartz/dsoundrender.c
@@ -394,7 +394,7 @@ static HRESULT WINAPI DSoundRender_DoRenderSample(BaseRenderer *iface, IMediaSam
q.Proportion = 1000;
q.Late = jitter;
q.TimeStamp = tStart;
- IQualityControl_Notify((IQualityControl *)This->renderer.qcimpl, (IBaseFilter*)This, q);
+ IQualityControl_Notify((IQualityControl *)This->renderer.qcimpl, &This->renderer.filter.IBaseFilter_iface, q);
}
return hr;
}
--
2.20.1
Sept. 2, 2019
[PATCH] strmbase: Don't cast from COM object to interface
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/strmbase/transform.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/strmbase/transform.c b/dlls/strmbase/transform.c
index e03874b7d6..fdecc8d0d1 100644
--- a/dlls/strmbase/transform.c
+++ b/dlls/strmbase/transform.c
@@ -351,9 +351,9 @@ HRESULT strmbase_transform_create(LONG filter_size, IUnknown *outer, const CLSID
return E_FAIL;
}
-HRESULT WINAPI TransformFilterImpl_Notify(TransformFilter *iface, IBaseFilter *sender, Quality qm)
+HRESULT WINAPI TransformFilterImpl_Notify(TransformFilter *filter, IBaseFilter *sender, Quality qm)
{
- return QualityControlImpl_Notify((IQualityControl*)iface->qcimpl, sender, qm);
+ return QualityControlImpl_Notify(&filter->qcimpl->IQualityControl_iface, sender, qm);
}
static HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface)
--
2.20.1
Sept. 2, 2019
[PATCH] rpcrt4: Return an exception code from NdrAsyncClientCall.
by Dmitry Timoshkov
Otherwise the caller may decide to wait for the call termination which
will never happen.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/rpcrt4/ndr_stubless.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/rpcrt4/ndr_stubless.c b/dlls/rpcrt4/ndr_stubless.c
index de58a9f22b..90537515ea 100644
--- a/dlls/rpcrt4/ndr_stubless.c
+++ b/dlls/rpcrt4/ndr_stubless.c
@@ -1773,6 +1773,7 @@ static void do_ndr_async_client_call( const MIDL_STUB_DESC *pStubDesc, PFORMAT_S
LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat,
void **stack_top )
{
+ LONG_PTR ret = 0;
const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
@@ -1786,14 +1787,15 @@ LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc,
__EXCEPT_ALL
{
FIXME("exception %x during ndr_async_client_call()\n", GetExceptionCode());
+ ret = GetExceptionCode();
}
__ENDTRY
}
else
do_ndr_async_client_call( pStubDesc, pFormat, stack_top);
- TRACE("returning 0\n");
- return 0;
+ TRACE("returning %ld\n", ret);
+ return ret;
}
RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply)
--
2.20.1
Sept. 2, 2019
Re: [PATCH] dnsapi: Add DnsGetCacheDataTable stub
by Rémi Bernon
On 8/31/19 11:47 AM, Francois Gouget wrote:
> On Fri, 30 Aug 2019, Rémi Bernon wrote:
>
>> On 8/30/19 3:03 PM, Marvin wrote:
>>> Hi,
>>>
>>> While running your changed tests, I think I found new failures.
>>> Being a bot and all I'm not very good at pattern recognition, so I might be
>>> wrong, but could you please double-check?
>>>
>>> Full results can be found at:
>>> https://testbot.winehq.org/JobDetails.pl?Key=56052
>>>
>>> Your paranoid android.
>>>
>>>
>>> === build (build log) ===
>>>
>>> Task errors:
>>> BotError: The VM is not powered on
>>>
>>
>> I did a successful run with the same patch here:
>> https://testbot.winehq.org/JobDetails.pl?Key=56051
>
> Yes, here's what happened:
> * When it has nothing to do the TestBot picks some VMs that it starts up
> in advance in the hope they will be needed by the next job.
>
> * Because the build VM is used to provide the Windows binaries for
> testing on Windows it's needed by almost every job. So its given a
> high priority and ends up being prepared in advance and thus is
> recorded by the TestBot as being in the idle state.
>
> * But then there was a power outage so all the VMs got powered off.
>
> * But the TestBot server is on a separate location and was not powered
> off so it was not aware that the VMs got powered off. The thing is
> these days the Engine never uses libvirt because these calls are
> blocking which means if it tries to communicate with a dead VM host of
> one where libvirt is hosed, these calls can block for a long time (up
> to 10 minutes), which would block the Engine for all that time.
> Instead it assumes the information it has in its database about the VM
> is accurate and forks a process whenever it needs to perform an
> operation on a VM, whether that's running a task, shutting it down or
> reverting it.
>
> * So it just scheduled the taks on the build VM as usual. But the
> child process could not communicate with the VMs, checked its state
> and complained that there was an error because "The VM is not
> powered on".
>
> What's wrong is that it marked the task as failed. A better recovery
> mechanism would have been to either mark the VM as "dirty" or "offline"
> and put the task back in the queued state so the TesBot tries running it
> again.
>
> The risk is that if the reason why the VM is not usable is not caused by
> an external factor (such as here), the next round is likely to produce
> the same result, leading the TestBot to try to run the same highest
> priority task again and again on the one borked VM.
>
>
> Finally the reason why you won't see that job as failed if you look a it
> now is because I restarted it. The user who submitted a job that failed
> due to a TestBot error gets a button to restart it. A user can only
> restart his own jobs and I'm not sure it that would have been possible
> in this case since the job came from a wine-devel email (but the
> administrator gets to restart anyone's jobs ;-).
>
>
> Anyway I'll see about tweaking the task scripts to avoid this situation
> in the future.
>
>
Thanks for the details!
--
Rémi Bernon <rbernon(a)codeweavers.com>
Sept. 2, 2019
[PATCH] dsound/tests: Add effect parameters tests.
by Alistair Leslie-Hughes
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/dsound/tests/dsound8.c | 322 ++++++++++++++++++++++++++++++++++++
1 file changed, 322 insertions(+)
diff --git a/dlls/dsound/tests/dsound8.c b/dlls/dsound/tests/dsound8.c
index fabd8a037e..779529731b 100644
--- a/dlls/dsound/tests/dsound8.c
+++ b/dlls/dsound/tests/dsound8.c
@@ -1375,6 +1375,327 @@ static void test_effects(void)
while (IDirectSound8_Release(dso));
}
+static void test_echo_parameters(LPDIRECTSOUNDBUFFER8 secondary8)
+{
+ HRESULT rc;
+ IDirectSoundFXEcho *echo;
+
+ rc=IDirectSoundBuffer8_GetObjectInPath(secondary8, &GUID_DSFX_STANDARD_ECHO, 0, &IID_IDirectSoundFXEcho,(void**)&echo);
+ ok(rc==DS_OK,"GetObjectInPath failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ DSFXEcho params;
+
+ rc = IDirectSoundFXEcho_GetAllParameters(echo, ¶ms);
+ todo_wine ok(rc==DS_OK,"SetFX failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ ok(params.fWetDryMix == 50.0f, "got %f\n", params.fWetDryMix);
+ ok(params.fFeedback == 50.0f, "got %f\n", params.fFeedback);
+ ok(params.fLeftDelay == 500.0f,"got %f\n", params.fLeftDelay);
+ ok(params.fRightDelay == 500.0f,"got %f\n", params.fRightDelay);
+ ok(params.lPanDelay == 0, "got %d\n", params.lPanDelay);
+ }
+
+ IDirectSoundFXEcho_Release(echo);
+ }
+}
+
+static void test_gargle_parameters(LPDIRECTSOUNDBUFFER8 secondary8)
+{
+ HRESULT rc;
+ IDirectSoundFXGargle *gargle;
+
+ rc=IDirectSoundBuffer8_GetObjectInPath(secondary8, &GUID_DSFX_STANDARD_GARGLE, 0, &IID_IDirectSoundFXGargle,(void**)&gargle);
+ todo_wine ok(rc==DS_OK,"GetObjectInPath failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ DSFXGargle params;
+
+ rc = IDirectSoundFXGargle_GetAllParameters(gargle, ¶ms);
+ todo_wine ok(rc==DS_OK,"SetFX failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ ok(params.dwRateHz == 20, "got %d\n", params.dwRateHz);
+ ok(params.dwWaveShape == DSFXGARGLE_WAVE_TRIANGLE, "got %d\n", params.dwWaveShape);
+ }
+
+ IDirectSoundFXGargle_Release(gargle);
+ }
+}
+
+static void test_chorus_parameters(LPDIRECTSOUNDBUFFER8 secondary8)
+{
+ HRESULT rc;
+ IDirectSoundFXChorus *chorus;
+
+ rc=IDirectSoundBuffer8_GetObjectInPath(secondary8, &GUID_DSFX_STANDARD_CHORUS, 0, &IID_IDirectSoundFXChorus,(void**)&chorus);
+ todo_wine ok(rc==DS_OK,"GetObjectInPath failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ DSFXChorus params;
+
+ rc = IDirectSoundFXChorus_GetAllParameters(chorus, ¶ms);
+ todo_wine ok(rc==DS_OK,"SetFX failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ ok(params.fWetDryMix == 50.0f, "got %f\n", params.fWetDryMix);
+ ok(params.fDepth == 10.0f, "got %f\n", params.fDepth);
+ ok(params.fFeedback == 25.0f, "got %f\n", params.fFeedback);
+ ok(params.fFrequency == 1.1f, "got %f\n", params.fFrequency);
+ ok(params.lWaveform == DSFXCHORUS_WAVE_SIN, "got %d\n", params.lWaveform);
+ ok(params.fDelay == 16.0f, "got %f\n", params.fDelay);
+ ok(params.lPhase == 3, "got %d\n", params.lPhase);
+ }
+
+ IDirectSoundFXChorus_Release(chorus);
+ }
+}
+
+static void test_flanger_parameters(LPDIRECTSOUNDBUFFER8 secondary8)
+{
+ HRESULT rc;
+ IDirectSoundFXFlanger *flanger;
+
+ rc=IDirectSoundBuffer8_GetObjectInPath(secondary8, &GUID_DSFX_STANDARD_FLANGER, 0, &IID_IDirectSoundFXFlanger,(void**)&flanger);
+ todo_wine ok(rc==DS_OK,"GetObjectInPath failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ DSFXFlanger params;
+
+ rc = IDirectSoundFXFlanger_GetAllParameters(flanger, ¶ms);
+ todo_wine ok(rc==DS_OK,"SetFX failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ ok(params.fWetDryMix == 50.0f, "got %f\n", params.fWetDryMix);
+ ok(params.fDepth == 100.0f, "got %f\n", params.fDepth);
+ ok(params.fFeedback == -50.0f, "got %f\n", params.fFeedback);
+ ok(params.fFrequency == 0.25f, "got %f\n", params.fFrequency);
+ ok(params.lWaveform == DSFXFLANGER_WAVE_SIN, "got %d\n", params.lWaveform);
+ ok(params.fDelay == 2.0f, "got %f\n", params.fDelay);
+ ok(params.lPhase == 2, "got %d\n", params.lPhase);
+ }
+
+ IDirectSoundFXFlanger_Release(flanger);
+ }
+}
+
+static void test_distortion_parameters(LPDIRECTSOUNDBUFFER8 secondary8)
+{
+ HRESULT rc;
+ IDirectSoundFXDistortion *distortion;
+
+ rc=IDirectSoundBuffer8_GetObjectInPath(secondary8, &GUID_DSFX_STANDARD_DISTORTION, 0, &IID_IDirectSoundFXDistortion,(void**)&distortion);
+ todo_wine ok(rc==DS_OK,"GetObjectInPath failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ DSFXDistortion params;
+
+ rc = IDirectSoundFXDistortion_GetAllParameters(distortion, ¶ms);
+ todo_wine ok(rc==DS_OK,"SetFX failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ ok(params.fGain == -18.0f, "got %f\n", params.fGain);
+ ok(params.fEdge == 15.0f, "got %f\n", params.fEdge);
+ ok(params.fPostEQCenterFrequency == 2400.0f, "got %f\n", params.fPostEQCenterFrequency);
+ ok(params.fPostEQBandwidth == 2400.0f, "got %f\n", params.fPostEQBandwidth);
+ ok(params.fPreLowpassCutoff == 3675.0f, "got %f\n", params.fPreLowpassCutoff);
+ }
+
+ IDirectSoundFXDistortion_Release(distortion);
+ }
+}
+
+static void test_compressor_parameters(LPDIRECTSOUNDBUFFER8 secondary8)
+{
+ HRESULT rc;
+ IDirectSoundFXCompressor *compressor;
+
+ rc=IDirectSoundBuffer8_GetObjectInPath(secondary8, &GUID_DSFX_STANDARD_COMPRESSOR, 0, &IID_IDirectSoundFXCompressor,(void**)&compressor);
+ todo_wine ok(rc==DS_OK,"GetObjectInPath failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ DSFXCompressor params;
+
+ rc = IDirectSoundFXCompressor_GetAllParameters(compressor, ¶ms);
+ todo_wine ok(rc==DS_OK,"SetFX failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ ok(params.fGain == 0.0f, "got %f\n", params.fGain);
+ ok(params.fAttack == 10.0f, "got %f\n", params.fAttack);
+ ok(params.fThreshold == -20.0f, "got %f\n", params.fThreshold);
+ ok(params.fRatio == 3.0f, "got %f\n", params.fRatio);
+ ok(params.fPredelay == 4.0f, "got %f\n", params.fPredelay);
+ }
+
+ IDirectSoundFXCompressor_Release(compressor);
+ }
+}
+
+static void test_parameq_parameters(LPDIRECTSOUNDBUFFER8 secondary8)
+{
+ HRESULT rc;
+ IDirectSoundFXParamEq *parameq;
+
+ rc=IDirectSoundBuffer8_GetObjectInPath(secondary8, &GUID_DSFX_STANDARD_PARAMEQ, 0, &IID_IDirectSoundFXParamEq,(void**)¶meq);
+ todo_wine ok(rc==DS_OK,"GetObjectInPath failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ DSFXParamEq params;
+
+ rc = IDirectSoundFXParamEq_GetAllParameters(parameq, ¶ms);
+ todo_wine ok(rc==DS_OK,"SetFX failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ ok(params.fCenter == 3675.0f, "got %f\n", params.fCenter);
+ ok(params.fBandwidth == 12.0f, "got %f\n", params.fBandwidth);
+ ok(params.fGain == 0.0f, "got %f\n", params.fGain);
+ }
+
+ IDirectSoundFXParamEq_Release(parameq);
+ }
+}
+
+static void test_reverb_parameters(LPDIRECTSOUNDBUFFER8 secondary8)
+{
+ HRESULT rc;
+ IDirectSoundFXI3DL2Reverb *reverb;
+
+ rc=IDirectSoundBuffer8_GetObjectInPath(secondary8, &GUID_DSFX_STANDARD_I3DL2REVERB, 0, &IID_IDirectSoundFXI3DL2Reverb,(void**)&reverb);
+ todo_wine ok(rc==DS_OK,"GetObjectInPath failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ DSFXI3DL2Reverb params;
+
+ rc = IDirectSoundFXI3DL2Reverb_GetAllParameters(reverb, ¶ms);
+ todo_wine ok(rc==DS_OK,"SetFX failed: %08x\n", rc);
+ if (rc==DS_OK)
+ {
+ ok(params.lRoom == -1000, "got %d\n", params.lRoom);
+ ok(params.flRoomRolloffFactor == 0.0f, "got %f\n", params.flRoomRolloffFactor);
+ ok(params.flDecayTime == 1.49f, "got %f\n", params.flDecayTime);
+ ok(params.flDecayHFRatio == 0.83f, "got %f\n", params.flDecayHFRatio);
+ ok(params.lReflections == -2602, "got %d\n", params.lReflections);
+ ok(params.lReverb == 200, "got %d\n", params.lReverb);
+ ok(params.flReverbDelay == 0.011f, "got %f\n", params.flReverbDelay);
+ ok(params.flDiffusion == 100.0f, "got %f\n", params.flDiffusion);
+ ok(params.flDensity == 100.0f, "got %f\n", params.flDensity);
+ ok(params.flHFReference == 5000.0f, "got %f\n", params.flHFReference);
+ }
+
+ IDirectSoundFXI3DL2Reverb_Release(reverb);
+ }
+}
+
+static void test_effects_parameters(void)
+{
+ HRESULT rc;
+ LPDIRECTSOUND8 dso;
+ LPDIRECTSOUNDBUFFER primary, secondary = NULL;
+ LPDIRECTSOUNDBUFFER8 secondary8 = NULL;
+ DSBUFFERDESC bufdesc;
+ WAVEFORMATEX wfx;
+ DSEFFECTDESC effects[8];
+ DWORD resultcodes[8];
+
+ /* Create a DirectSound8 object */
+ rc=pDirectSoundCreate8(NULL,&dso,NULL);
+ ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n",rc);
+
+ if (rc!=DS_OK)
+ return;
+
+ rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
+ ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
+ if (rc!=DS_OK)
+ {
+ IDirectSound8_Release(dso);
+ return;
+ }
+
+ primary=NULL;
+ ZeroMemory(&bufdesc, sizeof(bufdesc));
+ bufdesc.dwSize=sizeof(bufdesc);
+ bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
+ rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
+ ok((rc==DS_OK && primary!=NULL), "Failed to create a primary buffer: " "%08x\n",rc);
+ if (rc!=DS_OK)
+ goto cleanup;
+
+ init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
+ ZeroMemory(&bufdesc, sizeof(bufdesc));
+ bufdesc.dwSize=sizeof(bufdesc);
+ bufdesc.dwFlags=0;
+ bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
+ wfx.nBlockAlign);
+ bufdesc.lpwfxFormat=&wfx;
+
+ ZeroMemory(effects, sizeof(effects));
+ effects[0].dwSize=sizeof(effects[0]);
+ effects[0].guidDSFXClass=GUID_DSFX_STANDARD_ECHO;
+ effects[1].dwSize=sizeof(effects[0]);
+ effects[1].guidDSFXClass=GUID_DSFX_STANDARD_GARGLE;
+ effects[2].dwSize=sizeof(effects[0]);
+ effects[2].guidDSFXClass=GUID_DSFX_STANDARD_CHORUS;
+ effects[3].dwSize=sizeof(effects[0]);
+ effects[3].guidDSFXClass=GUID_DSFX_STANDARD_FLANGER;
+ effects[4].dwSize=sizeof(effects[0]);
+ effects[4].guidDSFXClass=GUID_DSFX_STANDARD_DISTORTION;
+ effects[5].dwSize=sizeof(effects[0]);
+ effects[5].guidDSFXClass=GUID_DSFX_STANDARD_COMPRESSOR;
+ effects[6].dwSize=sizeof(effects[0]);
+ effects[6].guidDSFXClass=GUID_DSFX_STANDARD_PARAMEQ;
+ effects[7].dwSize=sizeof(effects[0]);
+ effects[7].guidDSFXClass=GUID_DSFX_STANDARD_I3DL2REVERB;
+
+ bufdesc.dwFlags=DSBCAPS_CTRLFX;
+ rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
+ ok(rc==DS_OK && secondary!=NULL, "Failed to create a secondary buffer: %08x\n",rc);
+ if (rc!=DS_OK || !secondary)
+ goto cleanup;
+
+ rc=IDirectSoundBuffer_QueryInterface(secondary,&IID_IDirectSoundBuffer8,(LPVOID*)&secondary8);
+ ok(rc==DS_OK,"IDirectSoundBuffer_QueryInterface(IID_IDirectSoundBuffer8) failed: %08x\n", rc);
+ if (rc!=DS_OK)
+ goto cleanup;
+
+ rc=IDirectSoundBuffer8_SetFX(secondary8, ARRAY_SIZE(effects), effects, resultcodes);
+ ok(rc==DS_OK || rc==REGDB_E_CLASSNOTREG || rc==DSERR_CONTROLUNAVAIL,"SetFX failed: %08x\n", rc);
+ if (rc!=DS_OK)
+ goto cleanup;
+
+ if (resultcodes[0] == DSFXR_LOCSOFTWARE || resultcodes[0] == DSFXR_LOCHARDWARE)
+ test_echo_parameters(secondary8);
+
+ if (resultcodes[1] == DSFXR_LOCSOFTWARE || resultcodes[1] == DSFXR_LOCHARDWARE)
+ test_gargle_parameters(secondary8);
+
+ if (resultcodes[2] == DSFXR_LOCSOFTWARE || resultcodes[2] == DSFXR_LOCHARDWARE)
+ test_chorus_parameters(secondary8);
+
+ if (resultcodes[3] == DSFXR_LOCSOFTWARE || resultcodes[3] == DSFXR_LOCHARDWARE)
+ test_flanger_parameters(secondary8);
+
+ if (resultcodes[4] == DSFXR_LOCSOFTWARE || resultcodes[4] == DSFXR_LOCHARDWARE)
+ test_distortion_parameters(secondary8);
+
+ if (resultcodes[5] == DSFXR_LOCSOFTWARE || resultcodes[5] == DSFXR_LOCHARDWARE)
+ test_compressor_parameters(secondary8);
+
+ if (resultcodes[6] == DSFXR_LOCSOFTWARE || resultcodes[6] == DSFXR_LOCHARDWARE)
+ test_parameq_parameters(secondary8);
+
+ if (resultcodes[7] == DSFXR_LOCSOFTWARE || resultcodes[7] == DSFXR_LOCHARDWARE)
+ test_reverb_parameters(secondary8);
+
+cleanup:
+ if(secondary8)
+ IDirectSoundBuffer8_Release(secondary8);
+ if(primary)
+ IDirectSoundBuffer_Release(primary);
+ IDirectSound8_Release(dso);
+}
+
START_TEST(dsound8)
{
HMODULE hDsound;
@@ -1397,6 +1718,7 @@ START_TEST(dsound8)
test_hw_buffers();
test_first_device();
test_effects();
+ test_effects_parameters();
}
else
skip("DirectSoundCreate8 missing - skipping all tests\n");
--
2.17.1
Sept. 2, 2019
[PATCH v3 1/4] powrprof/tests: Test NtPowerInformation() with SystemExecutionState.
by Chip Davis
Test interaction between SetThreadExecutionState(), PowerSetRequest(),
and this parameter.
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
Notes:
v2: Test that, when a thread terminates, its execution state is cleaned up.
v3: Fix warnings.
configure.ac | 1 +
dlls/powrprof/tests/Makefile.in | 4 +
dlls/powrprof/tests/powrprof.c | 219 ++++++++++++++++++++++++++++++++
include/powrprof.h | 5 +
4 files changed, 229 insertions(+)
create mode 100644 dlls/powrprof/tests/Makefile.in
create mode 100644 dlls/powrprof/tests/powrprof.c
diff --git a/configure.ac b/configure.ac
index f45c078674c2..b277642e316f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3616,6 +3616,7 @@ WINE_CONFIG_MAKEFILE(dlls/pdh/tests)
WINE_CONFIG_MAKEFILE(dlls/photometadatahandler)
WINE_CONFIG_MAKEFILE(dlls/pidgen)
WINE_CONFIG_MAKEFILE(dlls/powrprof)
+WINE_CONFIG_MAKEFILE(dlls/powrprof/tests)
WINE_CONFIG_MAKEFILE(dlls/printui)
WINE_CONFIG_MAKEFILE(dlls/prntvpt)
WINE_CONFIG_MAKEFILE(dlls/propsys)
diff --git a/dlls/powrprof/tests/Makefile.in b/dlls/powrprof/tests/Makefile.in
new file mode 100644
index 000000000000..87aa06be5026
--- /dev/null
+++ b/dlls/powrprof/tests/Makefile.in
@@ -0,0 +1,4 @@
+TESTDLL = powrprof.dll
+IMPORTS = powrprof
+
+C_SRCS = powrprof.c
diff --git a/dlls/powrprof/tests/powrprof.c b/dlls/powrprof/tests/powrprof.c
new file mode 100644
index 000000000000..42c70f699f3d
--- /dev/null
+++ b/dlls/powrprof/tests/powrprof.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2019 Chip Davis for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winternl.h"
+#include "powrprof.h"
+
+#include "wine/test.h"
+
+HANDLE (WINAPI *pPowerCreateRequest)(REASON_CONTEXT *);
+BOOL (WINAPI *pPowerSetRequest)(HANDLE, POWER_REQUEST_TYPE);
+BOOL (WINAPI *pPowerClearRequest)(HANDLE, POWER_REQUEST_TYPE);
+
+static void test_system_execution_state(void)
+{
+ EXECUTION_STATE es, old_es;
+ NTSTATUS status;
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+
+ old_es = SetThreadExecutionState(ES_SYSTEM_REQUIRED);
+ todo_wine ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+
+ old_es = es;
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ ok(es == old_es, "unexpected execution state 0x%08x vs 0x%08x\n", es, old_es);
+
+ old_es = SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
+ todo_wine ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ todo_wine ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
+
+ old_es = SetThreadExecutionState(ES_CONTINUOUS);
+ ok(old_es == (ES_CONTINUOUS|ES_DISPLAY_REQUIRED), "unexpected execution state 0x%08x\n", old_es);
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+
+ old_es = SetThreadExecutionState(ES_DISPLAY_REQUIRED);
+ ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+
+ old_es = es;
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ ok(es == old_es, "unexpected execution state 0x%08x vs 0x%08x\n", es, old_es);
+}
+
+static HANDLE events[2];
+
+static DWORD CALLBACK execution_state_thread(LPVOID param)
+{
+ EXECUTION_STATE old_es;
+
+ SetThreadExecutionState(ES_SYSTEM_REQUIRED);
+ SignalObjectAndWait(events[0], events[1], INFINITE, FALSE);
+
+ old_es = SetThreadExecutionState(ES_DISPLAY_REQUIRED);
+ ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+ SignalObjectAndWait(events[0], events[1], INFINITE, FALSE);
+
+ old_es = SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
+ ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+ SignalObjectAndWait(events[0], events[1], INFINITE, FALSE);
+
+ old_es = SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
+ ok(old_es == (ES_CONTINUOUS|ES_SYSTEM_REQUIRED), "unexpected execution state 0x%08x\n", old_es);
+ SignalObjectAndWait(events[0], events[1], INFINITE, FALSE);
+
+ return 0;
+}
+
+static void test_system_execution_state_other_thread(void)
+{
+ HANDLE thread;
+ EXECUTION_STATE base_es, es;
+ NTSTATUS status;
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &base_es, sizeof(base_es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ trace("base execution state = 0x%08x\n", base_es);
+
+ events[0] = CreateEventW(NULL, FALSE, FALSE, NULL);
+ events[1] = CreateEventW(NULL, FALSE, FALSE, NULL);
+ thread = CreateThread(NULL, 0, execution_state_thread, NULL, 0, NULL);
+ ok(thread != NULL, "Failed to create thread, err %u\n", GetLastError());
+
+ WaitForSingleObject(events[0], INFINITE);
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ ok(es == base_es, "unexpected execution state 0x%08x\n", es);
+ es = SetThreadExecutionState(0);
+ ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
+ SignalObjectAndWait(events[1], events[0], INFINITE, FALSE);
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ ok(es == base_es, "unexpected execution state 0x%08x\n", es);
+ es = SetThreadExecutionState(0);
+ ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
+ SignalObjectAndWait(events[1], events[0], INFINITE, FALSE);
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ todo_wine ok(es & ES_SYSTEM_REQUIRED, "unexpected execution state 0x%08x\n", es);
+ es = SetThreadExecutionState(0);
+ todo_wine ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
+ SignalObjectAndWait(events[1], events[0], INFINITE, FALSE);
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ todo_wine ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
+ es = SetThreadExecutionState(0);
+ todo_wine ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
+ SignalObjectAndWait(events[1], thread, INFINITE, FALSE);
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ ok(es == base_es, "unexpected execution state 0x%08x\n", es);
+ es = SetThreadExecutionState(0);
+ todo_wine ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
+
+ CloseHandle(thread);
+ CloseHandle(events[0]);
+ CloseHandle(events[1]);
+}
+
+static void test_system_execution_state_power_request(void)
+{
+ HANDLE req;
+ REASON_CONTEXT reason;
+ BOOL ret;
+ NTSTATUS status;
+ EXECUTION_STATE base_es, es;
+ static WCHAR reasonW[] = {'W', 'i', 'n', 'e', ' ', 't', 'e', 's', 't', 0};
+
+ if (!pPowerCreateRequest)
+ {
+ win_skip("Power request objects unavailable\n");
+ return;
+ }
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &base_es, sizeof(base_es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ trace("base execution state = 0x%08x\n", base_es);
+
+ reason.Version = 0;
+ reason.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
+ reason.Reason.SimpleReasonString = reasonW;
+ req = pPowerCreateRequest(&reason);
+ todo_wine ok(req != INVALID_HANDLE_VALUE, "err %u\n", GetLastError());
+
+ ret = pPowerSetRequest(req, PowerRequestSystemRequired);
+ todo_wine ok(ret, "err %u\n", GetLastError());
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ todo_wine ok(es & ES_SYSTEM_REQUIRED, "unexpected execution state 0x%08x\n", es);
+
+ ret = pPowerClearRequest(req, PowerRequestSystemRequired);
+ todo_wine ok(ret, "err %u\n", GetLastError());
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ ok(!(es & ES_SYSTEM_REQUIRED) || (base_es & ES_SYSTEM_REQUIRED), "unexpected execution state 0x%08x\n", es);
+
+ ret = pPowerSetRequest(req, PowerRequestDisplayRequired);
+ todo_wine ok(ret, "err %u\n", GetLastError());
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ todo_wine ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
+
+ ret = CloseHandle(req);
+ todo_wine ok(ret, "err %u\n", GetLastError());
+
+ status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+ ok(status == STATUS_SUCCESS, "status %08x\n", status);
+ ok(!(es & ES_DISPLAY_REQUIRED) || (base_es & ES_DISPLAY_REQUIRED), "unexpected execution state 0x%08x\n", es);
+}
+
+START_TEST(powrprof)
+{
+ HMODULE hkernel32;
+
+ hkernel32 = GetModuleHandleA("kernel32.dll");
+ pPowerCreateRequest = (void *)GetProcAddress(hkernel32, "PowerCreateRequest");
+ pPowerSetRequest = (void *)GetProcAddress(hkernel32, "PowerSetRequest");
+ pPowerClearRequest = (void *)GetProcAddress(hkernel32, "PowerClearRequest");
+
+ test_system_execution_state();
+ test_system_execution_state_other_thread();
+ test_system_execution_state_power_request();
+}
diff --git a/include/powrprof.h b/include/powrprof.h
index 318188e465e5..421d9d4fc763 100644
--- a/include/powrprof.h
+++ b/include/powrprof.h
@@ -146,6 +146,11 @@ extern "C" {
typedef BOOLEAN (CALLBACK* PWRSCHEMESENUMPROC)(UINT, DWORD, LPWSTR, DWORD, LPWSTR, PPOWER_POLICY, LPARAM);
+#ifndef WINE_NTSTATUS_DECLARED
+#define WINE_NTSTATUS_DECLARED
+typedef LONG NTSTATUS;
+#endif
+
NTSTATUS WINAPI CallNtPowerInformation(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG);
BOOLEAN WINAPI CanUserWritePwrScheme(VOID);
BOOLEAN WINAPI DeletePwrScheme(UINT);
--
2.21.0
Sept. 2, 2019
[PATCH v2] winemac.drv: Fix build with older macOS SDKs.
by Zhiyi Zhang
macOS SDKs older than 10.11 doesn't support Metal.
macOS 10.11 and 10.12 SDK support Metal but don't
support registryID in MTLDevice protocol. Recommend
using 10.13+ SDK.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
v2: Supersede 169291. Fix build with macOS 10.11 and 10.12 SDKs as well.
configure.ac | 12 ++++++++++++
dlls/winemac.drv/cocoa_display.m | 5 ++---
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/configure.ac b/configure.ac
index d0af7ef4a1..a9e1da886d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -859,6 +859,18 @@ case $host_os in
AC_SUBST(METAL_LIBS,"-framework Metal -framework QuartzCore")
fi
+ dnl Check for MTLDevice registryID property
+ if test "$ac_cv_header_Metal_Metal_h" = "yes"
+ then
+ AC_MSG_CHECKING([whether MTLDevice protocol supports registryID property])
+ AC_LANG_PUSH([Objective C])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <Metal/Metal.h>]], [[id<MTLDevice> device; device.registryID;]])],
+ [AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_MTLDEVICE_REGISTRYID, 1, [Define if MTLDevice protocol has registryID property.])],
+ [AC_MSG_RESULT(no)])
+ AC_LANG_POP([Objective C])
+ fi
+
dnl Enable Mac driver on Mac OS X 10.6 or later
if test "$ac_cv_header_ApplicationServices_ApplicationServices_h" = "yes"
then
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m
index 3863557d96..9d95eee99a 100644
--- a/dlls/winemac.drv/cocoa_display.m
+++ b/dlls/winemac.drv/cocoa_display.m
@@ -21,7 +21,7 @@
#include "config.h"
#import <AppKit/AppKit.h>
-#ifdef HAVE_METAL_METAL_H
+#ifdef HAVE_MTLDEVICE_REGISTRYID
#import <Metal/Metal.h>
#endif
#include "macdrv_cocoa.h"
@@ -234,7 +234,7 @@ static int macdrv_get_gpu_info_from_entry(struct macdrv_gpu* gpu, io_registry_en
return ret;
}
-#ifdef HAVE_METAL_METAL_H
+#ifdef HAVE_MTLDEVICE_REGISTRYID
/***********************************************************************
* macdrv_get_gpu_info_from_registry_id
@@ -337,7 +337,6 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count)
static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count)
{
- TRACE("Metal support not compiled in\n");
return -1;
}
--
2.15.2 (Apple Git-101.1)
Sept. 2, 2019
[PATCH v3 4/4] ntdll: Semi-implement power request functions.
by Chip Davis
These create the object and alter the system execution state, but don't
actually force the computer to stay awake. It should be simple enough to
implement that on Mac OS. Linux might be a problem--in this instance,
we'll probably need to call out to some daemon over DBus.
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
Notes:
v2: Fix object leak.
v3: Remove half-implemented support for detailed reasons. Fix length passed to server. Put server changes in their own patch.
dlls/ntdll/nt.c | 56 ++++++++++++++++++++++++++++++----
dlls/powrprof/tests/powrprof.c | 14 ++++-----
2 files changed, 57 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index a6843c929895..2d64ec4aca45 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -51,6 +51,7 @@
#include <time.h>
#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "wine/debug.h"
@@ -3084,9 +3085,32 @@ NTSTATUS WINAPI NtSetThreadExecutionState( EXECUTION_STATE new_state, EXECUTION_
*/
NTSTATUS WINAPI NtCreatePowerRequest( HANDLE *handle, COUNTED_REASON_CONTEXT *context )
{
- FIXME( "(%p, %p): stub\n", handle, context );
+ UNICODE_STRING reason;
+ NTSTATUS status;
+ HMODULE mod = NULL;
+ static WCHAR emptyW = {0};
- return STATUS_NOT_IMPLEMENTED;
+ WARN( "(%p, %p): semi-stub\n", handle, context );
+
+ if (context->Flags & POWER_REQUEST_CONTEXT_SIMPLE_STRING)
+ reason = context->u.SimpleString;
+ else if (context->Flags & POWER_REQUEST_CONTEXT_DETAILED_STRING)
+ {
+ FIXME( "detailed reason strings are not supported\n" );
+ RtlInitUnicodeString( &reason, emptyW );
+ }
+
+ SERVER_START_REQ( create_power_request )
+ {
+ wine_server_add_data( req, reason.Buffer, reason.Length );
+ status = wine_server_call( req );
+ if (!status)
+ *handle = wine_server_ptr_handle( reply->handle );
+ }
+ SERVER_END_REQ;
+
+ if (mod) LdrUnloadDll( mod );
+ return status;
}
/******************************************************************************
@@ -3095,9 +3119,19 @@ NTSTATUS WINAPI NtCreatePowerRequest( HANDLE *handle, COUNTED_REASON_CONTEXT *co
*/
NTSTATUS WINAPI NtSetPowerRequest( HANDLE handle, POWER_REQUEST_TYPE type )
{
- FIXME( "(%p, %u): stub\n", handle, type );
+ NTSTATUS status;
- return STATUS_NOT_IMPLEMENTED;
+ WARN( "(%p, %u): semi-stub\n", handle, type );
+
+ SERVER_START_REQ( set_power_request )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ req->request = type;
+ status = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ return status;
}
/******************************************************************************
@@ -3106,9 +3140,19 @@ NTSTATUS WINAPI NtSetPowerRequest( HANDLE handle, POWER_REQUEST_TYPE type )
*/
NTSTATUS WINAPI NtClearPowerRequest( HANDLE handle, POWER_REQUEST_TYPE type )
{
- FIXME( "(%p, %u): stub\n", handle, type );
+ NTSTATUS status;
- return STATUS_NOT_IMPLEMENTED;
+ WARN( "(%p, %u): semi-stub\n", handle, type );
+
+ SERVER_START_REQ( clear_power_request )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ req->request = type;
+ status = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ return status;
}
#ifdef linux
diff --git a/dlls/powrprof/tests/powrprof.c b/dlls/powrprof/tests/powrprof.c
index ce9f96bfd90d..8fcb862b798f 100644
--- a/dlls/powrprof/tests/powrprof.c
+++ b/dlls/powrprof/tests/powrprof.c
@@ -173,31 +173,31 @@ static void test_system_execution_state_power_request()
reason.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
reason.Reason.SimpleReasonString = reasonW;
req = pPowerCreateRequest(&reason);
- todo_wine ok(req != INVALID_HANDLE_VALUE, "err %u\n", GetLastError());
+ ok(req != INVALID_HANDLE_VALUE, "err %u\n", GetLastError());
ret = pPowerSetRequest(req, PowerRequestSystemRequired);
- todo_wine ok(ret, "err %u\n", GetLastError());
+ ok(ret, "err %u\n", GetLastError());
status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
ok(status == STATUS_SUCCESS, "status %08x\n", status);
- todo_wine ok(es & ES_SYSTEM_REQUIRED, "unexpected execution state 0x%08x\n", es);
+ ok(es & ES_SYSTEM_REQUIRED, "unexpected execution state 0x%08x\n", es);
ret = pPowerClearRequest(req, PowerRequestSystemRequired);
- todo_wine ok(ret, "err %u\n", GetLastError());
+ ok(ret, "err %u\n", GetLastError());
status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
ok(status == STATUS_SUCCESS, "status %08x\n", status);
ok(!(es & ES_SYSTEM_REQUIRED) || (base_es & ES_SYSTEM_REQUIRED), "unexpected execution state 0x%08x\n", es);
ret = pPowerSetRequest(req, PowerRequestDisplayRequired);
- todo_wine ok(ret, "err %u\n", GetLastError());
+ ok(ret, "err %u\n", GetLastError());
status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
ok(status == STATUS_SUCCESS, "status %08x\n", status);
- todo_wine ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
+ ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
ret = CloseHandle(req);
- todo_wine ok(ret, "err %u\n", GetLastError());
+ ok(ret, "err %u\n", GetLastError());
status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
ok(status == STATUS_SUCCESS, "status %08x\n", status);
--
2.21.0
Sept. 2, 2019
[PATCH v3 3/4] ntdll: Implement SystemExecutionState handling.
by Chip Davis
Get it from the server in NtPowerInformation(), and change it when
NtSetThreadExecutionState() is called.
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
Notes:
v2: Handle thread termination.
v3: Put server changes back in their own patch.
dlls/ntdll/nt.c | 29 ++++++++++++++++++-----------
dlls/powrprof/tests/powrprof.c | 16 ++++++++--------
2 files changed, 26 insertions(+), 19 deletions(-)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index 06f8f39b169d..a6843c929895 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -3064,15 +3064,18 @@ NTSTATUS WINAPI NtInitiatePowerAction(
*/
NTSTATUS WINAPI NtSetThreadExecutionState( EXECUTION_STATE new_state, EXECUTION_STATE *old_state )
{
- static EXECUTION_STATE current =
- ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED | ES_USER_PRESENT;
- *old_state = current;
+ NTSTATUS status;
WARN( "(0x%x, %p): stub, harmless.\n", new_state, old_state );
- if (!(current & ES_CONTINUOUS) || (new_state & ES_CONTINUOUS))
- current = new_state;
- return STATUS_SUCCESS;
+ SERVER_START_REQ( set_thread_execution_state )
+ {
+ req->new_state = new_state;
+ status = wine_server_call( req );
+ *old_state = reply->old_state;
+ }
+ SERVER_END_REQ;
+ return status;
}
/******************************************************************************
@@ -3191,13 +3194,17 @@ NTSTATUS WINAPI NtPowerInformation(
return STATUS_SUCCESS;
}
case SystemExecutionState: {
- PULONG ExecutionState = lpOutputBuffer;
- WARN("semi-stub: SystemExecutionState\n"); /* Needed for .NET Framework, but using a FIXME is really noisy. */
+ EXECUTION_STATE *exec_state = lpOutputBuffer;
+ NTSTATUS status;
if (lpInputBuffer != NULL)
return STATUS_INVALID_PARAMETER;
- /* FIXME: The actual state should be the value set by SetThreadExecutionState which is not currently implemented. */
- *ExecutionState = ES_USER_PRESENT;
- return STATUS_SUCCESS;
+ SERVER_START_REQ( get_system_execution_state )
+ {
+ status = wine_server_call( req );
+ if (!status) *exec_state = reply->exec_state;
+ }
+ SERVER_END_REQ;
+ return status;
}
case ProcessorInformation: {
const int cannedMHz = 1000; /* We fake a 1GHz processor if we can't conjure up real values */
diff --git a/dlls/powrprof/tests/powrprof.c b/dlls/powrprof/tests/powrprof.c
index d744895cc484..ce9f96bfd90d 100644
--- a/dlls/powrprof/tests/powrprof.c
+++ b/dlls/powrprof/tests/powrprof.c
@@ -42,7 +42,7 @@ static void test_system_execution_state(void)
ok(status == STATUS_SUCCESS, "status %08x\n", status);
old_es = SetThreadExecutionState(ES_SYSTEM_REQUIRED);
- todo_wine ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+ ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
old_es = es;
status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
@@ -50,11 +50,11 @@ static void test_system_execution_state(void)
ok(es == old_es, "unexpected execution state 0x%08x vs 0x%08x\n", es, old_es);
old_es = SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
- todo_wine ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+ ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
ok(status == STATUS_SUCCESS, "status %08x\n", status);
- todo_wine ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
+ ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
old_es = SetThreadExecutionState(ES_CONTINUOUS);
ok(old_es == (ES_CONTINUOUS|ES_DISPLAY_REQUIRED), "unexpected execution state 0x%08x\n", old_es);
@@ -127,23 +127,23 @@ static void test_system_execution_state_other_thread(void)
status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
ok(status == STATUS_SUCCESS, "status %08x\n", status);
- todo_wine ok(es & ES_SYSTEM_REQUIRED, "unexpected execution state 0x%08x\n", es);
+ ok(es & ES_SYSTEM_REQUIRED, "unexpected execution state 0x%08x\n", es);
es = SetThreadExecutionState(0);
- todo_wine ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
+ ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
SignalObjectAndWait(events[1], events[0], INFINITE, FALSE);
status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
ok(status == STATUS_SUCCESS, "status %08x\n", status);
- todo_wine ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
+ ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
es = SetThreadExecutionState(0);
- todo_wine ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
+ ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
SignalObjectAndWait(events[1], thread, INFINITE, FALSE);
status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
ok(status == STATUS_SUCCESS, "status %08x\n", status);
ok(es == base_es, "unexpected execution state 0x%08x\n", es);
es = SetThreadExecutionState(0);
- todo_wine ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
+ ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
CloseHandle(thread);
CloseHandle(events[0]);
--
2.21.0
Sept. 2, 2019
[PATCH v3 2/4] server: Add server requests for managing the system execution state.
by Chip Davis
Signed-off-by: Chip Davis <cdavis(a)codeweavers.com>
---
Notes:
v3: Split this back out again.
include/winnt.h | 1 +
server/Makefile.in | 1 +
server/power.c | 263 ++++++++++++++++++++++++++++++++++++++++++++
server/protocol.def | 32 ++++++
server/thread.c | 2 +
server/thread.h | 2 +
6 files changed, 301 insertions(+)
create mode 100644 server/power.c
diff --git a/include/winnt.h b/include/winnt.h
index 9c4174f310d6..f3847c5f073c 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -906,6 +906,7 @@ typedef enum _HEAP_INFORMATION_CLASS {
#define ES_SYSTEM_REQUIRED 0x00000001
#define ES_DISPLAY_REQUIRED 0x00000002
#define ES_USER_PRESENT 0x00000004
+#define ES_AWAYMODE_REQUIRED 0x00000040
#define ES_CONTINUOUS 0x80000000
#include <excpt.h>
diff --git a/server/Makefile.in b/server/Makefile.in
index b39bd30305b5..e619d8223fb5 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -27,6 +27,7 @@ C_SRCS = \
procfs.c \
ptrace.c \
queue.c \
+ power.c \
region.c \
registry.c \
request.c \
diff --git a/server/power.c b/server/power.c
new file mode 100644
index 000000000000..5a8a576b2241
--- /dev/null
+++ b/server/power.c
@@ -0,0 +1,263 @@
+/*
+ * Power management support
+ *
+ * Copyright (C) 1998 Alexandre Julliard
+ * Copyright (C) 2003 Mike McCormack
+ * Copyright (C) 2005 Robert Shearman
+ * Copyright (C) 2019 Chip Davis for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+
+#include "handle.h"
+#include "request.h"
+#include "thread.h"
+#include "unicode.h"
+
+static unsigned int sys_count = 0; /* number of holds on system sleep */
+static unsigned int disp_count = 0; /* number of holds on display sleep */
+static unsigned int away_count = 0; /* number of away mode requests */
+
+struct power_request
+{
+ struct object obj; /* object header */
+ struct unicode_str reason; /* stated reason for the request */
+ unsigned sys : 1; /* hold system sleep? */
+ unsigned disp : 1; /* hold display sleep? */
+ unsigned away : 1; /* request away mode? */
+};
+
+static void power_request_dump( struct object *obj, int verbose );
+static struct object_type *power_request_get_type( struct object *obj );
+static void power_request_destroy( struct object *obj );
+
+static const struct object_ops power_request_ops =
+{
+ sizeof(struct power_request), /* size */
+ power_request_dump, /* dump */
+ power_request_get_type, /* get_type */
+ no_add_queue, /* add_queue */
+ NULL, /* remove_queue */
+ NULL, /* signaled */
+ NULL, /* satisfied */
+ no_signal, /* signal */
+ no_get_fd, /* get_fd */
+ no_map_access, /* map_access */
+ default_get_sd, /* get_sd */
+ default_set_sd, /* set_sd */
+ no_lookup_name, /* lookup_name */
+ no_link_name, /* link_name */
+ NULL, /* unlink_name */
+ no_open_file, /* open_file */
+ no_kernel_obj_list, /* get_kernel_obj_list */
+ no_close_handle, /* close_handle */
+ power_request_destroy /* destroy */
+};
+
+static void power_request_dump( struct object *obj, int verbose )
+{
+ struct power_request *power_req = (struct power_request *)obj;
+ assert( obj->ops == &power_request_ops );
+ fprintf( stderr, "PowerRequest reason=" );
+ dump_strW( power_req->reason.str, power_req->reason.len, stderr, "\"\"" );
+ fprintf( stderr, " hold system=%s hold display=%s away mode=%s\n", power_req->sys ? "TRUE" : "FALSE",
+ power_req->disp ? "TRUE" : "FALSE", power_req->away ? "TRUE" : "FALSE" );
+}
+
+static struct object_type *power_request_get_type( struct object *obj )
+{
+ static const WCHAR name[] = {'P', 'o', 'w', 'e', 'r', 'R', 'e', 'q', 'u', 'e', 's', 't'};
+ static const struct unicode_str str = { name, sizeof(name) };
+ return get_object_type( &str );
+}
+
+static void set_power_request( struct power_request *power_req, POWER_REQUEST_TYPE type )
+{
+ switch (type)
+ {
+ case PowerRequestDisplayRequired:
+ if (!power_req->disp)
+ ++disp_count;
+ power_req->disp = TRUE;
+ break;
+ case PowerRequestSystemRequired:
+ if (!power_req->sys)
+ ++sys_count;
+ power_req->sys = TRUE;
+ break;
+ case PowerRequestAwayModeRequired:
+ if (!power_req->away)
+ ++away_count;
+ power_req->away = TRUE;
+ break;
+ }
+}
+
+static void clear_power_request( struct power_request *power_req, POWER_REQUEST_TYPE type )
+{
+ switch (type)
+ {
+ case PowerRequestDisplayRequired:
+ if (power_req->disp)
+ --disp_count;
+ power_req->disp = FALSE;
+ break;
+ case PowerRequestSystemRequired:
+ if (power_req->sys)
+ --sys_count;
+ power_req->sys = FALSE;
+ break;
+ case PowerRequestAwayModeRequired:
+ if (power_req->away)
+ --away_count;
+ power_req->away = FALSE;
+ break;
+ }
+}
+
+static void power_request_destroy( struct object *obj )
+{
+ struct power_request *power_req;
+
+ assert( obj->ops == &power_request_ops );
+ power_req = (struct power_request *)obj;
+
+ clear_power_request( power_req, PowerRequestDisplayRequired );
+ clear_power_request( power_req, PowerRequestSystemRequired );
+ clear_power_request( power_req, PowerRequestAwayModeRequired );
+
+ free( (void *)power_req->reason.str );
+}
+
+/* creates a new power request */
+static struct power_request *create_power_request( struct unicode_str *reason )
+{
+ struct power_request *power_req = alloc_object( &power_request_ops );
+ if (power_req)
+ {
+ power_req->reason.str = memdup(reason->str, reason->len * sizeof(WCHAR));
+ power_req->reason.len = reason->len;
+ power_req->sys = 0;
+ power_req->disp = 0;
+ power_req->away = 0;
+ }
+ return power_req;
+}
+
+static struct power_request *get_power_request_obj( struct process *process, obj_handle_t handle )
+{
+ return (struct power_request *)get_handle_obj( process, handle, 0, &power_request_ops );
+}
+
+void release_thread_execution_state( struct thread *thread )
+{
+ if (thread->exec_state & ES_SYSTEM_REQUIRED)
+ --sys_count;
+ if (thread->exec_state & ES_DISPLAY_REQUIRED)
+ --disp_count;
+ if (thread->exec_state & ES_AWAYMODE_REQUIRED)
+ --away_count;
+}
+
+
+/* Get the current system execution state */
+DECL_HANDLER(get_system_execution_state)
+{
+ reply->exec_state = 0;
+ if (sys_count != 0)
+ reply->exec_state |= ES_SYSTEM_REQUIRED;
+ if (disp_count != 0)
+ reply->exec_state |= ES_DISPLAY_REQUIRED;
+ if (away_count != 0)
+ reply->exec_state |= ES_AWAYMODE_REQUIRED;
+}
+
+/* Set the current thread's execution state */
+DECL_HANDLER(set_thread_execution_state)
+{
+ reply->old_state = current->exec_state;
+
+ if (!(req->new_state & ES_CONTINUOUS))
+ return;
+
+ if ((current->exec_state & ES_SYSTEM_REQUIRED) && !(req->new_state & ES_SYSTEM_REQUIRED))
+ --sys_count;
+ else if (!(current->exec_state & ES_SYSTEM_REQUIRED) && (req->new_state & ES_SYSTEM_REQUIRED))
+ ++sys_count;
+
+ if ((current->exec_state & ES_DISPLAY_REQUIRED) && !(req->new_state & ES_DISPLAY_REQUIRED))
+ --disp_count;
+ else if (!(current->exec_state & ES_DISPLAY_REQUIRED) && (req->new_state & ES_DISPLAY_REQUIRED))
+ ++disp_count;
+
+ if ((current->exec_state & ES_AWAYMODE_REQUIRED) && !(req->new_state & ES_AWAYMODE_REQUIRED))
+ --away_count;
+ else if (!(current->exec_state & ES_AWAYMODE_REQUIRED) && (req->new_state & ES_AWAYMODE_REQUIRED))
+ ++away_count;
+ current->exec_state = req->new_state;
+}
+
+/* Create a power request object */
+DECL_HANDLER(create_power_request)
+{
+ struct unicode_str reason = get_req_unicode_str();
+
+ struct power_request *power_req = create_power_request( &reason );
+
+ if (power_req)
+ {
+ reply->handle = alloc_handle_no_access_check( current->process, power_req, 0, 0 );
+ release_object( power_req );
+ }
+ else
+ {
+ set_error( STATUS_NO_MEMORY );
+ }
+}
+
+/* Enable a request on a power request object */
+DECL_HANDLER(set_power_request)
+{
+ struct power_request *power_req = get_power_request_obj( current->process, req->handle );
+
+ if (power_req)
+ {
+ set_power_request( power_req, req->request );
+ release_object( power_req );
+ }
+}
+
+/* Disable a request on a power request object */
+DECL_HANDLER(clear_power_request)
+{
+ struct power_request *power_req = get_power_request_obj( current->process, req->handle );
+
+ if (power_req)
+ {
+ clear_power_request( power_req, req->request );
+ release_object( power_req );
+ }
+}
diff --git a/server/protocol.def b/server/protocol.def
index 6af0ae0cff89..191a8a810c58 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3944,3 +3944,35 @@ struct handle_info
@REQ(resume_process)
obj_handle_t handle; /* process handle */
@END
+
+/* Get the current system execution state */
+(a)REQ(get_system_execution_state)
+(a)REPLY
+ unsigned int exec_state; /* current execution state */
+(a)END
+
+/* Set the current thread's execution state */
+(a)REQ(set_thread_execution_state)
+ unsigned int new_state; /* thread's new execution state */
+(a)REPLY
+ unsigned int old_state; /* thread's old execution state */
+(a)END
+
+/* Create a power request object */
+(a)REQ(create_power_request)
+ VARARG(reason,unicode_str); /* reason for the request */
+(a)REPLY
+ obj_handle_t handle; /* power request handle */
+(a)END
+
+/* Enable a request on a power request object */
+(a)REQ(set_power_request)
+ obj_handle_t handle; /* power request handle */
+ unsigned int request; /* the request to enable */
+(a)END
+
+/* Disable a request on a power request object */
+(a)REQ(clear_power_request)
+ obj_handle_t handle; /* power request handle */
+ unsigned int request; /* the request to disable */
+(a)END
diff --git a/server/thread.c b/server/thread.c
index dc327603daa4..d34d23aec6ab 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -205,6 +205,7 @@ static inline void init_thread_structure( struct thread *thread )
thread->reply_fd = NULL;
thread->wait_fd = NULL;
thread->state = RUNNING;
+ thread->exec_state = ES_CONTINUOUS;
thread->exit_code = 0;
thread->priority = 0;
thread->suspend = 0;
@@ -1223,6 +1224,7 @@ void kill_thread( struct thread *thread, int violent_death )
wake_up( &thread->obj, 0 );
if (violent_death) send_thread_signal( thread, SIGQUIT );
cleanup_thread( thread );
+ release_thread_execution_state( thread );
remove_process_thread( thread->process, thread );
release_object( thread );
}
diff --git a/server/thread.h b/server/thread.h
index 9f7914803dec..8e29f9eda33e 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -72,6 +72,7 @@ struct thread
struct fd *reply_fd; /* fd to send a reply to a client */
struct fd *wait_fd; /* fd to use to wake a sleeping client */
enum run_state state; /* running state */
+ unsigned int exec_state; /* power execution state */
int exit_code; /* thread exit code */
int unix_pid; /* Unix pid of client */
int unix_tid; /* Unix tid of client */
@@ -130,6 +131,7 @@ extern int is_cpu_supported( enum cpu_type cpu );
extern unsigned int get_supported_cpu_mask(void);
extern int suspend_thread( struct thread *thread );
extern int resume_thread( struct thread *thread );
+extern void release_thread_execution_state( struct thread *thread );
/* ptrace functions */
--
2.21.0
Sept. 2, 2019