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
December 2019
- 73 participants
- 1394 messages
[PATCH 1/5] wined3d: Finish the CS before removing the context in adapter_vk_uninit_3d().
by Henri Verbeet
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/adapter_vk.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 21163a20949..4a501292824 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -466,6 +466,7 @@ static void adapter_vk_uninit_3d(struct wined3d_device *device)
device->blitter->ops->blitter_destroy(device->blitter, NULL);
+ wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
device_context_remove(device, &context_vk->c);
device->shader_backend->shader_free_private(device, NULL);
wined3d_context_vk_cleanup(context_vk);
--
2.11.0
Dec. 3, 2019
Re: [PATCH v2 4/4] winegstreamer: Use strmbase state change methods.
by Zebediah Figura
On 12/3/19 2:38 AM, Alexandre Julliard wrote:
> Zebediah Figura <z.figura12(a)gmail.com> writes:
>
>> Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
>> ---
>> dlls/winegstreamer/gstdemux.c | 255 ++++++++++++++++------------------
>> 1 file changed, 122 insertions(+), 133 deletions(-)
>
> This is still causing deadlocks:
>
> ../../../tools/runtest -q -P wine -T ../../.. -M winmm.dll -p winmm_test.exe mci && touch mci.ok
> 00e2:fixme:mci:MCI_SendCommand unhandled MCI_ALL_DEVICE_ID
> 00e2:fixme:mci:MCI_SysInfo Don't know how to get # of MCI devices of a given type
> 00e2:fixme:mci:MCI_SendCommand unhandled MCI_ALL_DEVICE_ID
> 00e2:fixme:mci:MCI_LoadMciDriver Couldn't load driver for type L"".
> 00e2:fixme:mci:MCI_LoadMciDriver Couldn't load driver for type L"".
> 00e2:fixme:mci:MCI_LoadMciDriver Couldn't load driver for type L"NOSUCHDEVICE".
> 00e2:fixme:mciwave:MCIWAVE_DriverProc Unsupported command [2134]
> 00e2:fixme:mci:mciSendStringW leaking auto-open device 1
> ALSA lib conf.c:3558:(snd_config_hooks_call) Cannot open shared library libasound_module_conf_pulse.so (/usr/lib/i386-linux-gnu/alsa-lib/libasound_module_conf_pulse.so: libasound_module_conf_pulse.so: cannot open shared object file: No such file or directory)
> ALSA lib seq.c:935:(snd_seq_open_noupdate) Unknown SEQ default
> 00e2:err:winediag:MIDIMAP_drvOpen No software synthesizer midi port found, Midi sound output probably won't work.
> 00e2:fixme:gstreamer:source_query_accept (0x6ea688) stub
> 00f9:err:ntdll:RtlpWaitForCriticalSection section 0x6ea1f0 "../strmbase/filter.c: strmbase_filter.csFilter" wait timed out in thread 00f9, blocked by 00fb, retrying (60 sec)
>
Thanks, it seems I misread the gstreamer code and mistakenly judged that
pad-removed was not sent from the streaming thread. I'll send a new
patch set that addresses this.
Dec. 3, 2019
[PATCH v3 4/4] winegstreamer: Use strmbase state change methods.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/winegstreamer/gstdemux.c | 255 ++++++++++++++++------------------
1 file changed, 122 insertions(+), 133 deletions(-)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index c9a32e35a9..da9bca6d1c 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -88,11 +88,6 @@ struct gstdemux_source
SourceSeeking seek;
};
-static inline struct gstdemux *impl_from_IBaseFilter(IBaseFilter *iface)
-{
- return CONTAINING_RECORD(iface, struct gstdemux, filter.IBaseFilter_iface);
-}
-
static inline struct gstdemux *impl_from_strmbase_filter(struct strmbase_filter *iface)
{
return CONTAINING_RECORD(iface, struct gstdemux, filter);
@@ -1247,10 +1242,123 @@ static void gstdemux_destroy(struct strmbase_filter *iface)
heap_free(filter);
}
+static HRESULT gstdemux_init_stream(struct strmbase_filter *iface)
+{
+ struct gstdemux *filter = impl_from_strmbase_filter(iface);
+ HRESULT hr = VFW_E_NOT_CONNECTED, pin_hr;
+ GstStateChangeReturn ret;
+ unsigned int i;
+
+ if (!filter->container)
+ return VFW_E_NOT_CONNECTED;
+
+ if (filter->no_more_pads_event)
+ ResetEvent(filter->no_more_pads_event);
+
+ if ((ret = gst_element_set_state(filter->container, GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE)
+ {
+ ERR("Failed to pause stream.\n");
+ return E_FAIL;
+ }
+
+ /* Make sure that all of our pads are connected before returning, lest we
+ * e.g. try to seek and fail. */
+ if (filter->no_more_pads_event)
+ WaitForSingleObject(filter->no_more_pads_event, INFINITE);
+
+ for (i = 0; i < filter->cStreams; ++i)
+ {
+ if (SUCCEEDED(pin_hr = BaseOutputPinImpl_Active(&filter->ppPins[i]->pin)))
+ hr = pin_hr;
+ }
+ return hr;
+}
+
+static HRESULT gstdemux_start_stream(struct strmbase_filter *iface, REFERENCE_TIME time)
+{
+ struct gstdemux *filter = impl_from_strmbase_filter(iface);
+ GstStateChangeReturn ret;
+
+ if (!filter->container)
+ return VFW_E_NOT_CONNECTED;
+
+ if ((ret = gst_element_set_state(filter->container, GST_STATE_PLAYING)) == GST_STATE_CHANGE_FAILURE)
+ {
+ ERR("Failed to play stream.\n");
+ return E_FAIL;
+ }
+ else if (ret == GST_STATE_CHANGE_ASYNC)
+ return S_FALSE;
+ return S_OK;
+}
+
+static HRESULT gstdemux_stop_stream(struct strmbase_filter *iface)
+{
+ struct gstdemux *filter = impl_from_strmbase_filter(iface);
+ GstStateChangeReturn ret;
+
+ if (!filter->container)
+ return VFW_E_NOT_CONNECTED;
+
+ if ((ret = gst_element_set_state(filter->container, GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE)
+ {
+ ERR("Failed to pause stream.\n");
+ return E_FAIL;
+ }
+ else if (ret == GST_STATE_CHANGE_ASYNC)
+ return S_FALSE;
+ return S_OK;
+}
+
+static HRESULT gstdemux_cleanup_stream(struct strmbase_filter *iface)
+{
+ struct gstdemux *filter = impl_from_strmbase_filter(iface);
+ GstStateChangeReturn ret;
+
+ if (!filter->container)
+ return S_OK;
+
+ filter->ignore_flush = TRUE;
+ if ((ret = gst_element_set_state(filter->container, GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE)
+ {
+ ERR("Failed to pause stream.\n");
+ return E_FAIL;
+ }
+ gst_element_get_state(filter->container, NULL, NULL, GST_CLOCK_TIME_NONE);
+ filter->ignore_flush = FALSE;
+
+ return S_OK;
+}
+
+static HRESULT gstdemux_wait_state(struct strmbase_filter *iface, DWORD timeout)
+{
+ struct gstdemux *filter = impl_from_strmbase_filter(iface);
+ GstStateChangeReturn ret;
+
+ if (!filter->container)
+ return S_OK;
+
+ ret = gst_element_get_state(filter->container, NULL, NULL,
+ timeout == INFINITE ? GST_CLOCK_TIME_NONE : timeout * 1000);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ {
+ ERR("Failed to get state.\n");
+ return E_FAIL;
+ }
+ else if (ret == GST_STATE_CHANGE_ASYNC)
+ return VFW_S_STATE_INTERMEDIATE;
+ return S_OK;
+}
+
static const struct strmbase_filter_ops filter_ops =
{
.filter_get_pin = gstdemux_get_pin,
.filter_destroy = gstdemux_destroy,
+ .filter_init_stream = gstdemux_init_stream,
+ .filter_start_stream = gstdemux_start_stream,
+ .filter_stop_stream = gstdemux_stop_stream,
+ .filter_cleanup_stream = gstdemux_cleanup_stream,
+ .filter_wait_state = gstdemux_wait_state,
};
static HRESULT sink_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE *mt)
@@ -1360,139 +1468,15 @@ IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *outer, HRESULT *phr)
return &object->filter.IUnknown_inner;
}
-static HRESULT WINAPI GST_Stop(IBaseFilter *iface)
-{
- struct gstdemux *This = impl_from_IBaseFilter(iface);
-
- TRACE("(%p)\n", This);
-
- mark_wine_thread();
-
- if (This->container) {
- This->ignore_flush = TRUE;
- gst_element_set_state(This->container, GST_STATE_READY);
- gst_element_get_state(This->container, NULL, NULL, -1);
- This->ignore_flush = FALSE;
- }
- return S_OK;
-}
-
-static HRESULT WINAPI GST_Pause(IBaseFilter *iface)
-{
- struct gstdemux *This = impl_from_IBaseFilter(iface);
- HRESULT hr = S_OK;
- GstState now;
- GstStateChangeReturn ret;
-
- TRACE("(%p)\n", This);
-
- if (!This->container)
- return VFW_E_NOT_CONNECTED;
-
- mark_wine_thread();
-
- gst_element_get_state(This->container, &now, NULL, -1);
- if (now == GST_STATE_PAUSED)
- return S_OK;
- if (now != GST_STATE_PLAYING)
- hr = IBaseFilter_Run(iface, -1);
- if (FAILED(hr))
- return hr;
- ret = gst_element_set_state(This->container, GST_STATE_PAUSED);
- if (ret == GST_STATE_CHANGE_ASYNC)
- hr = S_FALSE;
- return hr;
-}
-
-static HRESULT WINAPI GST_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
-{
- struct gstdemux *This = impl_from_IBaseFilter(iface);
- HRESULT hr = S_OK;
- ULONG i;
- GstState now;
- HRESULT hr_any = VFW_E_NOT_CONNECTED;
-
- TRACE("(%p)->(%s)\n", This, wine_dbgstr_longlong(tStart));
-
- mark_wine_thread();
-
- if (!This->container)
- return VFW_E_NOT_CONNECTED;
-
- gst_element_get_state(This->container, &now, NULL, -1);
- if (now == GST_STATE_PLAYING)
- return S_OK;
- if (now == GST_STATE_PAUSED) {
- GstStateChangeReturn ret;
- ret = gst_element_set_state(This->container, GST_STATE_PLAYING);
- if (ret == GST_STATE_CHANGE_ASYNC)
- return S_FALSE;
- return S_OK;
- }
-
- EnterCriticalSection(&This->filter.csFilter);
-
- if (This->no_more_pads_event)
- ResetEvent(This->no_more_pads_event);
-
- gst_element_set_state(This->container, GST_STATE_PLAYING);
-
- /* Make sure that all of our pads are connected before returning, lest we
- * e.g. try to seek and fail. */
- if (This->no_more_pads_event)
- WaitForSingleObject(This->no_more_pads_event, INFINITE);
-
- for (i = 0; i < This->cStreams; i++) {
- hr = BaseOutputPinImpl_Active(&This->ppPins[i]->pin);
- if (SUCCEEDED(hr)) {
- hr_any = hr;
- }
- }
- hr = hr_any;
- LeaveCriticalSection(&This->filter.csFilter);
-
- return hr;
-}
-
-static HRESULT WINAPI GST_GetState(IBaseFilter *iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
-{
- struct gstdemux *This = impl_from_IBaseFilter(iface);
- HRESULT hr = S_OK;
- GstState now, pending;
- GstStateChangeReturn ret;
-
- TRACE("(%p)->(%d, %p)\n", This, dwMilliSecsTimeout, pState);
-
- mark_wine_thread();
-
- if (!This->container) {
- *pState = State_Stopped;
- return S_OK;
- }
-
- ret = gst_element_get_state(This->container, &now, &pending, dwMilliSecsTimeout == INFINITE ? -1 : dwMilliSecsTimeout * 1000);
-
- if (ret == GST_STATE_CHANGE_ASYNC)
- hr = VFW_S_STATE_INTERMEDIATE;
- else
- pending = now;
-
- switch (pending) {
- case GST_STATE_PAUSED: *pState = State_Paused; return hr;
- case GST_STATE_PLAYING: *pState = State_Running; return hr;
- default: *pState = State_Stopped; return hr;
- }
-}
-
static const IBaseFilterVtbl GST_Vtbl = {
BaseFilterImpl_QueryInterface,
BaseFilterImpl_AddRef,
BaseFilterImpl_Release,
BaseFilterImpl_GetClassID,
- GST_Stop,
- GST_Pause,
- GST_Run,
- GST_GetState,
+ BaseFilterImpl_Stop,
+ BaseFilterImpl_Pause,
+ BaseFilterImpl_Run,
+ BaseFilterImpl_GetState,
BaseFilterImpl_SetSyncSource,
BaseFilterImpl_GetSyncSource,
BaseFilterImpl_EnumPins,
@@ -2632,6 +2616,11 @@ static const struct strmbase_filter_ops mpeg_splitter_ops =
.filter_query_interface = mpeg_splitter_query_interface,
.filter_get_pin = gstdemux_get_pin,
.filter_destroy = gstdemux_destroy,
+ .filter_init_stream = gstdemux_init_stream,
+ .filter_start_stream = gstdemux_start_stream,
+ .filter_stop_stream = gstdemux_stop_stream,
+ .filter_cleanup_stream = gstdemux_cleanup_stream,
+ .filter_wait_state = gstdemux_wait_state,
};
IUnknown * CALLBACK mpeg_splitter_create(IUnknown *outer, HRESULT *phr)
--
2.24.0
Dec. 3, 2019
[PATCH v3 3/4] winegstreamer: Also wait for the no-more-pads signal when pausing the filter.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/winegstreamer/gstdemux.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index 9eddf78ced..c9a32e35a9 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -1431,8 +1431,17 @@ static HRESULT WINAPI GST_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
}
EnterCriticalSection(&This->filter.csFilter);
+
+ if (This->no_more_pads_event)
+ ResetEvent(This->no_more_pads_event);
+
gst_element_set_state(This->container, GST_STATE_PLAYING);
+ /* Make sure that all of our pads are connected before returning, lest we
+ * e.g. try to seek and fail. */
+ if (This->no_more_pads_event)
+ WaitForSingleObject(This->no_more_pads_event, INFINITE);
+
for (i = 0; i < This->cStreams; i++) {
hr = BaseOutputPinImpl_Active(&This->ppPins[i]->pin);
if (SUCCEEDED(hr)) {
--
2.24.0
Dec. 3, 2019
[PATCH v3 2/4] winegstreamer: Don't hold the filter lock from the pad-added or pad-removed callbacks.
by Zebediah Figura
These may be called from the streaming thread, so it's not safe to do so.
Nor does it seem necessary. We expect that no streaming thread should ever
call methods on our pad or pin, and as long as we hold the filter lock and
wait for the no-more-pads signal when connecting or starting the stream, we
cannot race with application threads.
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/winegstreamer/gstdemux.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index 5fa9d66c93..9eddf78ced 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -814,13 +814,17 @@ static void removed_decoded_pad(GstElement *bin, GstPad *pad, gpointer user)
TRACE("%p %p %p\n", This, bin, pad);
- EnterCriticalSection(&This->filter.csFilter);
for (x = 0; x < This->cStreams; ++x) {
if (This->ppPins[x]->their_src == pad)
break;
}
if (x == This->cStreams)
- goto out;
+ {
+ char *name = gst_pad_get_name(pad);
+ WARN("No pin matching pad %s found.\n", debugstr_a(name));
+ g_free(name);
+ return;
+ }
pin = This->ppPins[x];
@@ -831,9 +835,6 @@ static void removed_decoded_pad(GstElement *bin, GstPad *pad, gpointer user)
gst_object_unref(pin->their_src);
pin->their_src = NULL;
-out:
- TRACE("Removed %i/%i\n", x, This->cStreams);
- LeaveCriticalSection(&This->filter.csFilter);
}
static void init_new_decoded_pad(GstElement *bin, GstPad *pad, struct gstdemux *This)
@@ -971,7 +972,6 @@ static void existing_new_pad(GstElement *bin, GstPad *pad, gpointer user)
return;
}
- EnterCriticalSection(&This->filter.csFilter);
for (x = 0; x < This->cStreams; ++x) {
struct gstdemux_source *pin = This->ppPins[x];
if (!pin->their_src) {
@@ -986,13 +986,11 @@ static void existing_new_pad(GstElement *bin, GstPad *pad, gpointer user)
pin->their_src = pad;
gst_object_ref(pin->their_src);
TRACE("Relinked\n");
- LeaveCriticalSection(&This->filter.csFilter);
return;
}
}
}
init_new_decoded_pad(bin, pad, This);
- LeaveCriticalSection(&This->filter.csFilter);
}
static gboolean query_function(GstPad *pad, GstObject *parent, GstQuery *query)
--
2.24.0
Dec. 3, 2019
[PATCH v3 1/4] strmbase: Use a separate critical section for the SourceSeeking structure.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/strmbase/seeking.c | 53 +++++++++++++++++++--------------
dlls/winegstreamer/gstdemux.c | 5 ++--
dlls/wineqtdecoder/qtsplitter.c | 3 +-
include/wine/strmbase.h | 7 +++--
4 files changed, 40 insertions(+), 28 deletions(-)
diff --git a/dlls/strmbase/seeking.c b/dlls/strmbase/seeking.c
index 8a773b51d5..d87e4f8516 100644
--- a/dlls/strmbase/seeking.c
+++ b/dlls/strmbase/seeking.c
@@ -18,7 +18,6 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-/* FIXME: critical sections */
#include "strmbase_private.h"
@@ -29,7 +28,9 @@ static inline SourceSeeking *impl_from_IMediaSeeking(IMediaSeeking *iface)
return CONTAINING_RECORD(iface, SourceSeeking, IMediaSeeking_iface);
}
-HRESULT SourceSeeking_Init(SourceSeeking *pSeeking, const IMediaSeekingVtbl *Vtbl, SourceSeeking_ChangeStop fnChangeStop, SourceSeeking_ChangeStart fnChangeStart, SourceSeeking_ChangeRate fnChangeRate, PCRITICAL_SECTION crit_sect)
+HRESULT strmbase_seeking_init(SourceSeeking *pSeeking, const IMediaSeekingVtbl *Vtbl,
+ SourceSeeking_ChangeStop fnChangeStop, SourceSeeking_ChangeStart fnChangeStart,
+ SourceSeeking_ChangeRate fnChangeRate)
{
assert(fnChangeStop && fnChangeStart && fnChangeRate);
@@ -48,10 +49,16 @@ HRESULT SourceSeeking_Init(SourceSeeking *pSeeking, const IMediaSeekingVtbl *Vtb
pSeeking->llDuration = pSeeking->llStop;
pSeeking->dRate = 1.0;
pSeeking->timeformat = TIME_FORMAT_MEDIA_TIME;
- pSeeking->crst = crit_sect;
+ InitializeCriticalSection(&pSeeking->cs);
+ pSeeking->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SourceSeeking.cs");
return S_OK;
}
+void strmbase_seeking_cleanup(SourceSeeking *seeking)
+{
+ DeleteCriticalSection(&seeking->cs);
+}
+
HRESULT WINAPI SourceSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
{
SourceSeeking *This = impl_from_IMediaSeeking(iface);
@@ -104,9 +111,9 @@ HRESULT WINAPI SourceSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFo
SourceSeeking *This = impl_from_IMediaSeeking(iface);
TRACE("(%s)\n", debugstr_guid(pFormat));
- EnterCriticalSection(This->crst);
+ EnterCriticalSection(&This->cs);
*pFormat = This->timeformat;
- LeaveCriticalSection(This->crst);
+ LeaveCriticalSection(&This->cs);
return S_OK;
}
@@ -118,10 +125,10 @@ HRESULT WINAPI SourceSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const
TRACE("(%s)\n", debugstr_guid(pFormat));
- EnterCriticalSection(This->crst);
+ EnterCriticalSection(&This->cs);
if (!IsEqualIID(pFormat, &This->timeformat))
hr = S_FALSE;
- LeaveCriticalSection(This->crst);
+ LeaveCriticalSection(&This->cs);
return hr;
}
@@ -140,9 +147,9 @@ HRESULT WINAPI SourceSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * p
TRACE("(%p)\n", pDuration);
- EnterCriticalSection(This->crst);
+ EnterCriticalSection(&This->cs);
*pDuration = This->llDuration;
- LeaveCriticalSection(This->crst);
+ LeaveCriticalSection(&This->cs);
return S_OK;
}
@@ -153,9 +160,9 @@ HRESULT WINAPI SourceSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG
TRACE("(%p)\n", pStop);
- EnterCriticalSection(This->crst);
+ EnterCriticalSection(&This->cs);
*pStop = This->llStop;
- LeaveCriticalSection(This->crst);
+ LeaveCriticalSection(&This->cs);
return S_OK;
}
@@ -167,9 +174,9 @@ HRESULT WINAPI SourceSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGL
TRACE("(%p)\n", pCurrent);
- EnterCriticalSection(This->crst);
+ EnterCriticalSection(&This->cs);
*pCurrent = This->llCurrent;
- LeaveCriticalSection(This->crst);
+ LeaveCriticalSection(&This->cs);
return S_OK;
}
@@ -214,7 +221,7 @@ HRESULT WINAPI SourceSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG *
LONGLONG llNewCurrent, llNewStop;
TRACE("(%p, %x, %p, %x)\n", pCurrent, dwCurrentFlags, pStop, dwStopFlags);
- EnterCriticalSection(This->crst);
+ EnterCriticalSection(&This->cs);
llNewCurrent = Adjust(This->llCurrent, pCurrent, dwCurrentFlags);
llNewStop = Adjust(This->llStop, pStop, dwStopFlags);
@@ -233,7 +240,7 @@ HRESULT WINAPI SourceSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG *
*pCurrent = llNewCurrent;
if (pStop && (dwStopFlags & AM_SEEKING_ReturnTime))
*pStop = llNewStop;
- LeaveCriticalSection(This->crst);
+ LeaveCriticalSection(&This->cs);
if (bChangeCurrent)
This->fnChangeStart(iface);
@@ -249,10 +256,10 @@ HRESULT WINAPI SourceSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG *
TRACE("(%p, %p)\n", pCurrent, pStop);
- EnterCriticalSection(This->crst);
+ EnterCriticalSection(&This->cs);
IMediaSeeking_GetCurrentPosition(iface, pCurrent);
IMediaSeeking_GetStopPosition(iface, pStop);
- LeaveCriticalSection(This->crst);
+ LeaveCriticalSection(&This->cs);
return S_OK;
}
@@ -263,10 +270,10 @@ HRESULT WINAPI SourceSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG *
TRACE("(%p, %p)\n", pEarliest, pLatest);
- EnterCriticalSection(This->crst);
+ EnterCriticalSection(&This->cs);
*pEarliest = 0;
*pLatest = This->llDuration;
- LeaveCriticalSection(This->crst);
+ LeaveCriticalSection(&This->cs);
return S_OK;
}
@@ -285,11 +292,11 @@ HRESULT WINAPI SourceSeekingImpl_SetRate(IMediaSeeking * iface, double dRate)
return VFW_E_UNSUPPORTED_AUDIO;
}
- EnterCriticalSection(This->crst);
+ EnterCriticalSection(&This->cs);
This->dRate = dRate;
if (bChangeRate)
hr = This->fnChangeRate(iface);
- LeaveCriticalSection(This->crst);
+ LeaveCriticalSection(&This->cs);
return hr;
}
@@ -300,10 +307,10 @@ HRESULT WINAPI SourceSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate)
TRACE("(%p)\n", dRate);
- EnterCriticalSection(This->crst);
+ EnterCriticalSection(&This->cs);
/* Forward? */
*dRate = This->dRate;
- LeaveCriticalSection(This->crst);
+ LeaveCriticalSection(&This->cs);
return S_OK;
}
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index 479077b48f..5fa9d66c93 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -1884,6 +1884,7 @@ static void free_source_pin(struct gstdemux_source *pin)
FreeMediaType(&pin->mt);
gst_segment_free(pin->segment);
+ strmbase_seeking_cleanup(&pin->seek);
strmbase_source_cleanup(&pin->pin);
heap_free(pin);
}
@@ -1936,8 +1937,8 @@ static struct gstdemux_source *create_pin(struct gstdemux *filter, const WCHAR *
pin->segment = gst_segment_new();
gst_segment_init(pin->segment, GST_FORMAT_TIME);
pin->IQualityControl_iface.lpVtbl = &GSTOutPin_QualityControl_Vtbl;
- SourceSeeking_Init(&pin->seek, &GST_Seeking_Vtbl, GST_ChangeStop,
- GST_ChangeCurrent, GST_ChangeRate, &filter->filter.csFilter);
+ strmbase_seeking_init(&pin->seek, &GST_Seeking_Vtbl, GST_ChangeStop,
+ GST_ChangeCurrent, GST_ChangeRate);
BaseFilterImpl_IncrementPinVersion(&filter->filter);
sprintf(pad_name, "qz_sink_%u", filter->cStreams);
diff --git a/dlls/wineqtdecoder/qtsplitter.c b/dlls/wineqtdecoder/qtsplitter.c
index fbec10a912..81e18d3420 100644
--- a/dlls/wineqtdecoder/qtsplitter.c
+++ b/dlls/wineqtdecoder/qtsplitter.c
@@ -340,7 +340,8 @@ IUnknown * CALLBACK QTSplitter_create(IUnknown *outer, HRESULT *phr)
This->pInputPin.pin.peer = NULL;
This->pInputPin.pin.pFuncsTable = &sink_ops;
- SourceSeeking_Init(&This->sourceSeeking, &QT_Seeking_Vtbl, QTSplitter_ChangeStop, QTSplitter_ChangeStart, QTSplitter_ChangeRate, &This->filter.csFilter);
+ strmbase_seeking_init(&This->sourceSeeking, &QT_Seeking_Vtbl,
+ QTSplitter_ChangeStop, QTSplitter_ChangeStart, QTSplitter_ChangeRate);
*phr = S_OK;
return &This->filter.IUnknown_inner;
diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h
index b08303f93d..7949e6670a 100644
--- a/include/wine/strmbase.h
+++ b/include/wine/strmbase.h
@@ -272,10 +272,13 @@ typedef struct SourceSeeking
double dRate;
LONGLONG llCurrent, llStop, llDuration;
GUID timeformat;
- PCRITICAL_SECTION crst;
+ CRITICAL_SECTION cs;
} SourceSeeking;
-HRESULT SourceSeeking_Init(SourceSeeking *pSeeking, const IMediaSeekingVtbl *Vtbl, SourceSeeking_ChangeStop fnChangeStop, SourceSeeking_ChangeStart fnChangeStart, SourceSeeking_ChangeRate fnChangeRate, PCRITICAL_SECTION crit_sect);
+HRESULT strmbase_seeking_init(SourceSeeking *seeking, const IMediaSeekingVtbl *vtbl,
+ SourceSeeking_ChangeStop fnChangeStop, SourceSeeking_ChangeStart fnChangeStart,
+ SourceSeeking_ChangeRate fnChangeRate);
+void strmbase_seeking_cleanup(SourceSeeking *seeking);
HRESULT WINAPI SourceSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities);
HRESULT WINAPI SourceSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities);
--
2.24.0
Dec. 3, 2019
[PATCH v5 resend] user32: Send a WM_ACTIVATE message after restoring a minimized window.
by Zhiyi Zhang
The WmShowRestoreMinimizedOverlappedSeq message sequence in tests
clearly show that there is a WM_ACTIVATE message at the end of
ShowWindow() calls after restoring a minimized window, and it's
not from SetFocus().
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47507
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/user32/tests/msg.c | 247 +++++++++++++++++++++++++++++++++++++++-
dlls/user32/winpos.c | 9 +-
2 files changed, 254 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index c0ba5834cf..78733f44c9 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -892,6 +892,145 @@ static const struct message WmShowVisMaxPopupSeq[] = {
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
{ 0 }
};
+/* ShowWindow(hwnd, SW_RESTORE) to a minimized window */
+static const struct message WmShowRestoreMinimizedOverlappedSeq[] =
+{
+ { HCBT_MINMAX, hook },
+ { WM_QUERYOPEN, sent },
+ { WM_GETTEXT, sent|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_GETMINMAXINFO, sent|defwinproc },
+ { WM_NCCALCSIZE, sent },
+ { HCBT_ACTIVATE, hook },
+ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+ { WM_NCACTIVATE, sent },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ACTIVATE, sent|wparam, WA_ACTIVE },
+ { HCBT_SETFOCUS, hook },
+ { WM_SETFOCUS, sent|defwinproc },
+ { WM_NCPAINT, sent },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent },
+ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_MOVE, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_NCPAINT, sent|optional },
+ { WM_ERASEBKGND, sent|optional },
+ /* Note this WM_ACTIVATE message even if the window is already active and focused */
+ { WM_ACTIVATE, sent|wparam|lparam, WA_ACTIVE, 0 },
+ { WM_SYNCPAINT, sent|optional },
+ { WM_PAINT, sent },
+ { WM_GETMINMAXINFO, sent|optional },
+ { 0 }
+};
+/* ShowWindow(hwnd, SW_SHOWNOACTIVATE) to a minimized window */
+static const struct message WmShowNoActivateMinimizedOverlappedSeq[] =
+{
+ { HCBT_MINMAX, hook },
+ { WM_QUERYOPEN, sent },
+ { WM_GETTEXT, sent|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_GETMINMAXINFO, sent|defwinproc },
+ { WM_NCCALCSIZE, sent },
+ { WM_NCPAINT, sent },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent },
+ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_MOVE, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ /* Following optional messages are on XP/2003 */
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_NCPAINT, sent|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { HCBT_SETFOCUS, hook|optional },
+ { WM_SETFOCUS, sent|optional },
+ { HCBT_ACTIVATE, hook|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+ { WM_NCACTIVATE, sent|optional },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ACTIVATE, sent|wparam|optional, WA_ACTIVE },
+ { HCBT_SETFOCUS, hook|optional },
+ { WM_SETFOCUS, sent|defwinproc|optional },
+ { WM_KILLFOCUS, sent|optional },
+ { WM_SETFOCUS, sent|optional },
+ /* Note this WM_ACTIVATE message on XP even if the window is already active and focused */
+ { WM_ACTIVATE, sent|wparam|lparam|optional, WA_ACTIVE, 0 },
+ { WM_SYNCPAINT, sent|optional },
+ { WM_PAINT, sent },
+ { WM_GETMINMAXINFO, sent|optional },
+ { 0 }
+};
+/* ShowWindow(hwnd, SW_RESTORE) to an active minimized window */
+static const struct message WmShowRestoreActiveMinimizedOverlappedSeq[] =
+{
+ { HCBT_MINMAX, hook },
+ { WM_QUERYOPEN, sent },
+ { WM_GETTEXT, sent|optional },
+ { WM_NCACTIVATE, sent },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
+ { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_MOVE, sent|optional },
+ { WM_SIZE, sent|optional },
+ { WM_GETTEXT, sent|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_GETMINMAXINFO, sent|defwinproc },
+ { WM_NCCALCSIZE, sent },
+ { WM_NCPAINT, sent },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent },
+ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_MOVE, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_NCPAINT, sent|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { HCBT_SETFOCUS, hook },
+ { WM_SETFOCUS, sent },
+ /* Note this WM_ACTIVATE message even if the window is already active */
+ { WM_ACTIVATE, sent|wparam|lparam, WA_ACTIVE, 0 },
+ { WM_SYNCPAINT, sent|optional },
+ { WM_PAINT, sent },
+ { WM_GETMINMAXINFO, sent|optional },
+ { 0 }
+};
+/* ShowWindow(hwnd, SW_SHOWNOACTIVATE) to an active minimized window */
+static const struct message WmShowNoActivateActiveMinimizedOverlappedSeq[] =
+{
+ { HCBT_MINMAX, hook },
+ { WM_QUERYOPEN, sent },
+ { WM_GETTEXT, sent|optional },
+ { WM_NCACTIVATE, sent },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
+ { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_MOVE, sent|optional },
+ { WM_SIZE, sent|optional },
+ { WM_GETTEXT, sent|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_GETMINMAXINFO, sent|defwinproc },
+ { WM_NCCALCSIZE, sent },
+ { WM_NCPAINT, sent },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent },
+ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_MOVE, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_NCPAINT, sent|optional },
+ { WM_ERASEBKGND, sent|optional },
+ /* Following optional messages are present on XP */
+ { HCBT_SETFOCUS, hook|optional },
+ { WM_SETFOCUS, sent|optional },
+ /* Note this WM_ACTIVATE message even if the window is already active and with flag SW_SHOWNOACTIVATE */
+ { WM_ACTIVATE, sent|wparam|lparam|optional, WA_ACTIVE, 0 },
+ { WM_SYNCPAINT, sent|optional },
+ { WM_PAINT, sent },
+ { WM_GETMINMAXINFO, sent|optional },
+ { 0 }
+};
/* CreateWindow (for a child popup window, not initially visible) */
static const struct message WmCreateChildPopupSeq[] = {
{ HCBT_CREATEWND, hook },
@@ -4661,7 +4800,7 @@ static void test_scroll_messages(HWND hwnd)
static void test_showwindow(void)
{
- HWND hwnd, hchild;
+ HWND hwnd, hwnd2, hchild;
RECT rc;
hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
@@ -4798,6 +4937,68 @@ static void test_showwindow(void)
ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE);
DestroyWindow(hwnd);
flush_sequence();
+
+ /* Test 5:
+ * 1. Restoring a minimized window.
+ */
+ hwnd = CreateWindowA("TestWindowClass", "window1", WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Failed to create window\n");
+
+ hwnd2 = CreateWindowA("static", "window2", WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd2 != NULL, "Failed to create window\n");
+
+ ShowWindow(hwnd, SW_MINIMIZE);
+ SetActiveWindow(hwnd2);
+ ok(GetActiveWindow() == hwnd2, "Unexpected active window\n");
+ flush_events();
+ flush_sequence();
+ ShowWindow(hwnd, SW_RESTORE);
+ flush_events();
+ ok_sequence(WmShowRestoreMinimizedOverlappedSeq,
+ "ShowWindow(hwnd, SW_RESTORE): minimized overlapped", TRUE);
+
+ ShowWindow(hwnd, SW_MINIMIZE);
+ SetActiveWindow(hwnd2);
+ ok(GetActiveWindow() == hwnd2, "Unexpected active window\n");
+ flush_events();
+ flush_sequence();
+ ShowWindow(hwnd, SW_SHOWNOACTIVATE);
+ flush_events();
+ ok_sequence(WmShowNoActivateMinimizedOverlappedSeq,
+ "ShowWindow(hwnd, SW_SHOWNOACTIVATE): minimized overlapped", TRUE);
+
+ DestroyWindow(hwnd2);
+ DestroyWindow(hwnd);
+ flush_sequence();
+
+ /* Test 6:
+ * 1. Restoring a minimized but active window.
+ */
+ hwnd = CreateWindowA("TestWindowClass", "parent", WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Failed to create window\n");
+
+ ShowWindow(hwnd, SW_MINIMIZE);
+ SetActiveWindow(hwnd);
+ ok(GetActiveWindow() == hwnd, "Unexpected active window\n");
+ flush_events();
+ flush_sequence();
+ ShowWindow(hwnd, SW_RESTORE);
+ flush_events();
+ ok_sequence(WmShowRestoreActiveMinimizedOverlappedSeq,
+ "ShowWindow(hwnd, SW_RESTORE): active minimized overlapped", TRUE);
+
+ ShowWindow(hwnd, SW_MINIMIZE);
+ SetActiveWindow(hwnd);
+ ok(GetActiveWindow() == hwnd, "Unexpected active window\n");
+ flush_events();
+ flush_sequence();
+ ShowWindow(hwnd, SW_SHOWNOACTIVATE);
+ flush_events();
+ ok_sequence(WmShowNoActivateActiveMinimizedOverlappedSeq,
+ "ShowWindow(hwnd, SW_SHOWNOACTIVATE): active minimized overlapped", TRUE);
+
+ DestroyWindow(hwnd);
+ flush_sequence();
}
static void test_sys_menu(void)
@@ -15521,6 +15722,42 @@ static const struct message WmRestoreMinimizedOverlappedSeq[] =
{ 0 }
};
+/* DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) to an active minimized window */
+static const struct message WmRestoreActiveMinimizedOverlappedSeq[] =
+{
+ { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_RESTORE, 0 },
+ { HCBT_MINMAX, hook },
+ { WM_QUERYOPEN, sent },
+ { WM_GETTEXT, sent|optional },
+ { WM_NCACTIVATE, sent },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
+ { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_MOVE, sent|optional },
+ { WM_SIZE, sent|optional },
+ { WM_GETTEXT, sent|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_GETMINMAXINFO, sent|defwinproc },
+ { WM_NCCALCSIZE, sent },
+ { WM_NCPAINT, sent },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent },
+ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_MOVE, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_NCPAINT, sent|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { HCBT_SETFOCUS, hook },
+ { WM_SETFOCUS, sent },
+ /* Note this WM_ACTIVATE messages even if the window is already active */
+ { WM_ACTIVATE, sent|wparam|lparam, WA_ACTIVE, 0 },
+ { WM_SYNCPAINT, sent|optional },
+ { WM_PAINT, sent },
+ { WM_GETMINMAXINFO, sent|optional },
+ { 0 }
+};
+
struct rbuttonup_thread_data
{
HWND hwnd;
@@ -15582,7 +15819,15 @@ static void test_defwinproc(void)
DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
flush_events();
ok_sequence(WmRestoreMinimizedOverlappedSeq, "DefWindowProcA(SC_RESTORE):overlapped", TRUE);
+
+ ShowWindow(hwnd, SW_MINIMIZE);
+ SetActiveWindow(hwnd);
+ ok(GetActiveWindow() == hwnd, "Unexpected active window\n");
+ flush_events();
flush_sequence();
+ DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
+ flush_events();
+ ok_sequence(WmRestoreActiveMinimizedOverlappedSeq, "DefWindowProcA(SC_RESTORE):active minimized overlapped", TRUE);
GetCursorPos(&pos);
GetWindowRect(hwnd, &rect);
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index aad5274973..7aca94e8fe 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -1182,7 +1182,14 @@ static BOOL show_window( HWND hwnd, INT cmd )
else WIN_ReleasePtr( wndPtr );
/* if previous state was minimized Windows sets focus to the window */
- if (style & WS_MINIMIZE) SetFocus( hwnd );
+ if (style & WS_MINIMIZE)
+ {
+ SetFocus( hwnd );
+ /* Send a WM_ACTIVATE message for a top level window, even if the window is already active */
+ style = GetWindowLongW( hwnd, GWL_STYLE );
+ if (!(style & WS_CHILD) && !(swp & SWP_NOACTIVATE))
+ SendMessageW( hwnd, WM_ACTIVATE, WA_ACTIVE, 0 );
+ }
done:
SetThreadDpiAwarenessContext( context );
--
2.24.0
Dec. 3, 2019
[PATCH 3/3] user32/tests: Use a higher resolution in test_ChangeDisplaySettingsEx().
by Zhiyi Zhang
640x480 is not supported on some Windows 10 versions.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
Fix https://test.winehq.org/data/5536df1ee1042c6cf20a7d96c43520003a547092/win10…
dlls/user32/tests/monitor.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c
index 4268dba9c5..567870e3d1 100644
--- a/dlls/user32/tests/monitor.c
+++ b/dlls/user32/tests/monitor.c
@@ -234,20 +234,20 @@ struct vid_mode
};
static const struct vid_mode vid_modes_test[] = {
- {640, 480, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY, 0},
- {640, 480, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY, 1},
- {640, 480, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL , 0},
- {640, 480, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT , 1},
- {640, 480, 0, 0, DM_BITSPERPEL , 0},
- {640, 480, 0, 0, DM_DISPLAYFREQUENCY, 0},
+ {1024, 768, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY, 0},
+ {1024, 768, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY, 1},
+ {1024, 768, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL , 0},
+ {1024, 768, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT , 1},
+ {1024, 768, 0, 0, DM_BITSPERPEL , 0},
+ {1024, 768, 0, 0, DM_DISPLAYFREQUENCY, 0},
{0, 0, 0, 0, DM_PELSWIDTH, 0},
{0, 0, 0, 0, DM_PELSHEIGHT, 0},
- {640, 480, 0, 0, DM_PELSWIDTH, 0},
- {640, 480, 0, 0, DM_PELSHEIGHT, 0},
- { 0, 480, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT, 0},
- {640, 0, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT, 0},
+ {1024, 768, 0, 0, DM_PELSWIDTH, 0},
+ {1024, 768, 0, 0, DM_PELSHEIGHT, 0},
+ { 0, 768, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT, 0},
+ {1024, 0, 0, 0, DM_PELSWIDTH | DM_PELSHEIGHT, 0},
/* the following test succeeds under XP SP3
{0, 0, 0, 0, DM_DISPLAYFREQUENCY, 0}
--
2.24.0
Dec. 3, 2019
[PATCH 2/3] user32/tests: Test cursor clip rectangles in per-monitor aware context.
by Zhiyi Zhang
So the tests don't fail in HiDPI environment.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/user32/tests/monitor.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c
index ca87a89deb..4268dba9c5 100644
--- a/dlls/user32/tests/monitor.c
+++ b/dlls/user32/tests/monitor.c
@@ -28,6 +28,7 @@
static HMODULE hdll;
static LONG (WINAPI *pGetDisplayConfigBufferSizes)(UINT32,UINT32*,UINT32*);
+static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
static void init_function_pointers(void)
{
@@ -39,6 +40,7 @@ static void init_function_pointers(void)
trace("GetProcAddress(%s) failed\n", #func);
GET_PROC(GetDisplayConfigBufferSizes)
+ GET_PROC(SetThreadDpiAwarenessContext)
#undef GET_PROC
}
@@ -254,6 +256,7 @@ static const struct vid_mode vid_modes_test[] = {
static void test_ChangeDisplaySettingsEx(void)
{
+ DPI_AWARENESS_CONTEXT context = NULL;
DEVMODEA dm;
DEVMODEW dmW;
DWORD width;
@@ -328,6 +331,11 @@ static void test_ChangeDisplaySettingsEx(void)
res == DISP_CHANGE_BADMODE /* XP SP3 */,
"ChangeDisplaySettingsExW returned %d\n", res);
+ /* Test clip rectangle after resolution changes */
+ /* GetClipCursor always returns result in physical pixels but GetSystemMetrics(SM_CX/CYVIRTUALSCREEN) are not.
+ * Set per-monitor aware context so that virtual screen rectangles are in physical pixels */
+ if (pSetThreadDpiAwarenessContext)
+ context = pSetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
memset(&dm, 0, sizeof(dm));
dm.dmSize = sizeof(dm);
@@ -384,6 +392,8 @@ static void test_ChangeDisplaySettingsEx(void)
ClipCursor(&virt);
}
}
+ if (pSetThreadDpiAwarenessContext && context)
+ pSetThreadDpiAwarenessContext(context);
res = ChangeDisplaySettingsExA(NULL, NULL, NULL, CDS_RESET, NULL);
ok(res == DISP_CHANGE_SUCCESSFUL, "Failed to reset default resolution: %d\n", res);
}
--
2.24.0
Dec. 3, 2019
[PATCH 1/3] user32/tests: Import functions if possible.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/user32/tests/monitor.c | 126 +++++++++++-------------------------
1 file changed, 36 insertions(+), 90 deletions(-)
diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c
index 04e63dc38d..ca87a89deb 100644
--- a/dlls/user32/tests/monitor.c
+++ b/dlls/user32/tests/monitor.c
@@ -27,15 +27,6 @@
#include <stdio.h>
static HMODULE hdll;
-static LONG (WINAPI *pChangeDisplaySettingsExA)(LPCSTR, LPDEVMODEA, HWND, DWORD, LPVOID);
-static LONG (WINAPI *pChangeDisplaySettingsExW)(LPCWSTR, LPDEVMODEW, HWND, DWORD, LPVOID);
-static BOOL (WINAPI *pEnumDisplayDevicesA)(LPCSTR,DWORD,LPDISPLAY_DEVICEA,DWORD);
-static BOOL (WINAPI *pEnumDisplayMonitors)(HDC,LPRECT,MONITORENUMPROC,LPARAM);
-static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
-static BOOL (WINAPI *pGetMonitorInfoW)(HMONITOR,LPMONITORINFO);
-static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);
-static HMONITOR (WINAPI *pMonitorFromRect)(LPCRECT,DWORD);
-static HMONITOR (WINAPI *pMonitorFromWindow)(HWND,DWORD);
static LONG (WINAPI *pGetDisplayConfigBufferSizes)(UINT32,UINT32*,UINT32*);
static void init_function_pointers(void)
@@ -47,16 +38,7 @@ static void init_function_pointers(void)
if(!p ## func) \
trace("GetProcAddress(%s) failed\n", #func);
- GET_PROC(ChangeDisplaySettingsExA)
- GET_PROC(ChangeDisplaySettingsExW)
- GET_PROC(EnumDisplayDevicesA)
- GET_PROC(EnumDisplayMonitors)
GET_PROC(GetDisplayConfigBufferSizes)
- GET_PROC(GetMonitorInfoA)
- GET_PROC(GetMonitorInfoW)
- GET_PROC(MonitorFromPoint)
- GET_PROC(MonitorFromRect)
- GET_PROC(MonitorFromWindow)
#undef GET_PROC
}
@@ -69,7 +51,7 @@ static BOOL CALLBACK monitor_enum_proc(HMONITOR hmon, HDC hdc, LPRECT lprc,
mi.cbSize = sizeof(mi);
- ok(pGetMonitorInfoA(hmon, (MONITORINFO*)&mi), "GetMonitorInfo failed\n");
+ ok(GetMonitorInfoA(hmon, (MONITORINFO*)&mi), "GetMonitorInfo failed\n");
if (mi.dwFlags & MONITORINFOF_PRIMARY)
strcpy(primary, mi.szDevice);
@@ -203,20 +185,14 @@ static void test_enumdisplaydevices(void)
int monitor_index;
BOOL ret;
- if (!pEnumDisplayDevicesA)
- {
- win_skip("EnumDisplayDevicesA is not available\n");
- return;
- }
-
/* Doesn't accept \\.\DISPLAY */
dd.cb = sizeof(dd);
- ret = pEnumDisplayDevicesA("\\\\.\\DISPLAY", 0, &dd, 0);
+ ret = EnumDisplayDevicesA("\\\\.\\DISPLAY", 0, &dd, 0);
ok(!ret, "Expect failure\n");
/* Enumeration */
for (flag_index = 0; flag_index < ARRAY_SIZE(flags); flag_index++)
- for (adapter_index = 0; pEnumDisplayDevicesA(NULL, adapter_index, &dd, flags[flag_index]); adapter_index++)
+ for (adapter_index = 0; EnumDisplayDevicesA(NULL, adapter_index, &dd, flags[flag_index]); adapter_index++)
{
lstrcpyA(adapter_name, dd.DeviceName);
@@ -228,7 +204,7 @@ static void test_enumdisplaydevices(void)
test_enumdisplaydevices_adapter(adapter_index, &dd, flags[flag_index]);
- for (monitor_index = 0; pEnumDisplayDevicesA(adapter_name, monitor_index, &dd, flags[flag_index]);
+ for (monitor_index = 0; EnumDisplayDevicesA(adapter_name, monitor_index, &dd, flags[flag_index]);
monitor_index++)
test_enumdisplaydevices_monitor(adapter_index, monitor_index, adapter_name, &dd, flags[flag_index]);
}
@@ -237,18 +213,12 @@ static void test_enumdisplaydevices(void)
/* XP on Testbot doesn't report a monitor, whereas XP on real machine does */
ok(broken(monitor_count == 0) || monitor_count > 0, "Expect at least one monitor found\n");
- if (!pEnumDisplayMonitors || !pGetMonitorInfoA)
- {
- win_skip("EnumDisplayMonitors or GetMonitorInfoA are not available\n");
- return;
- }
-
- ret = pEnumDisplayDevicesA(NULL, 0, &dd, 0);
+ ret = EnumDisplayDevicesA(NULL, 0, &dd, 0);
ok(ret, "Expect success\n");
lstrcpyA(primary_device_name, dd.DeviceName);
primary_monitor_device_name[0] = 0;
- ret = pEnumDisplayMonitors(NULL, NULL, monitor_enum_proc, (LPARAM)primary_monitor_device_name);
+ ret = EnumDisplayMonitors(NULL, NULL, monitor_enum_proc, (LPARAM)primary_monitor_device_name);
ok(ret, "EnumDisplayMonitors failed\n");
ok(!strcmp(primary_monitor_device_name, primary_device_name),
"monitor device name %s, device name %s\n", primary_monitor_device_name,
@@ -290,12 +260,6 @@ static void test_ChangeDisplaySettingsEx(void)
LONG res;
int i;
- if (!pChangeDisplaySettingsExA)
- {
- win_skip("ChangeDisplaySettingsExA is not available\n");
- return;
- }
-
SetLastError(0xdeadbeef);
res = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dm);
ok(res, "EnumDisplaySettings error %u\n", GetLastError());
@@ -311,7 +275,7 @@ static void test_ChangeDisplaySettingsEx(void)
/* crashes under XP SP3 for large dmDriverExtra values */
dm.dmDriverExtra = 1;
- res = pChangeDisplaySettingsExA(NULL, &dm, NULL, CDS_TEST, NULL);
+ res = ChangeDisplaySettingsExA(NULL, &dm, NULL, CDS_TEST, NULL);
ok(res == DISP_CHANGE_SUCCESSFUL,
"ChangeDisplaySettingsExW returned %d, expected DISP_CHANGE_SUCCESSFUL\n", res);
ok(dm.dmDriverExtra == 1, "ChangeDisplaySettingsExA shouldn't reset dmDriverExtra to 0\n");
@@ -333,7 +297,7 @@ static void test_ChangeDisplaySettingsEx(void)
/* Apparently XP treats dmDriverExtra being != 0 as an error */
dmW.dmDriverExtra = 1;
- res = pChangeDisplaySettingsExW(NULL, &dmW, NULL, CDS_TEST, NULL);
+ res = ChangeDisplaySettingsExW(NULL, &dmW, NULL, CDS_TEST, NULL);
if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
{
ok(res == DISP_CHANGE_SUCCESSFUL,
@@ -347,7 +311,7 @@ static void test_ChangeDisplaySettingsEx(void)
memset(&dm, 0, sizeof(dm));
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
dm.dmPelsWidth = width;
- res = pChangeDisplaySettingsExA(NULL, &dm, NULL, CDS_TEST, NULL);
+ res = ChangeDisplaySettingsExA(NULL, &dm, NULL, CDS_TEST, NULL);
ok(res == DISP_CHANGE_SUCCESSFUL ||
res == DISP_CHANGE_BADMODE || /* Win98, WinMe */
res == DISP_CHANGE_FAILED, /* NT4 */
@@ -357,7 +321,7 @@ static void test_ChangeDisplaySettingsEx(void)
dmW.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
dmW.dmPelsWidth = width;
SetLastError(0xdeadbeef);
- res = pChangeDisplaySettingsExW(NULL, &dmW, NULL, CDS_TEST, NULL);
+ res = ChangeDisplaySettingsExW(NULL, &dmW, NULL, CDS_TEST, NULL);
if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
ok(res == DISP_CHANGE_FAILED ||
res == DISP_CHANGE_BADPARAM || /* NT4 */
@@ -374,7 +338,7 @@ static void test_ChangeDisplaySettingsEx(void)
dm.dmBitsPerPel = vid_modes_test[i].bpp;
dm.dmDisplayFrequency = vid_modes_test[i].freq;
dm.dmFields = vid_modes_test[i].fields;
- res = pChangeDisplaySettingsExA(NULL, &dm, NULL, CDS_TEST, NULL);
+ res = ChangeDisplaySettingsExA(NULL, &dm, NULL, CDS_TEST, NULL);
ok(vid_modes_test[i].must_succeed ?
(res == DISP_CHANGE_SUCCESSFUL || res == DISP_CHANGE_RESTART) :
(res == DISP_CHANGE_SUCCESSFUL || res == DISP_CHANGE_RESTART ||
@@ -420,7 +384,7 @@ static void test_ChangeDisplaySettingsEx(void)
ClipCursor(&virt);
}
}
- res = pChangeDisplaySettingsExA(NULL, NULL, NULL, CDS_RESET, NULL);
+ res = ChangeDisplaySettingsExA(NULL, NULL, NULL, CDS_RESET, NULL);
ok(res == DISP_CHANGE_SUCCESSFUL, "Failed to reset default resolution: %d\n", res);
}
@@ -464,76 +428,64 @@ static void test_monitors(void)
{0xdeadbeef, FALSE},
};
- if (!pMonitorFromPoint || !pMonitorFromWindow || !pMonitorFromRect)
- {
- win_skip("MonitorFromPoint, MonitorFromWindow, or MonitorFromRect is not available\n");
- return;
- }
-
pt.x = pt.y = 0;
- primary = pMonitorFromPoint( pt, MONITOR_DEFAULTTOPRIMARY );
+ primary = MonitorFromPoint( pt, MONITOR_DEFAULTTOPRIMARY );
ok( primary != 0, "couldn't get primary monitor\n" );
- monitor = pMonitorFromWindow( 0, MONITOR_DEFAULTTONULL );
+ monitor = MonitorFromWindow( 0, MONITOR_DEFAULTTONULL );
ok( !monitor, "got %p, should not get a monitor for an invalid window\n", monitor );
- monitor = pMonitorFromWindow( 0, MONITOR_DEFAULTTOPRIMARY );
+ monitor = MonitorFromWindow( 0, MONITOR_DEFAULTTOPRIMARY );
ok( monitor == primary, "got %p, should get primary %p for MONITOR_DEFAULTTOPRIMARY\n", monitor, primary );
- monitor = pMonitorFromWindow( 0, MONITOR_DEFAULTTONEAREST );
+ monitor = MonitorFromWindow( 0, MONITOR_DEFAULTTONEAREST );
ok( monitor == primary, "got %p, should get primary %p for MONITOR_DEFAULTTONEAREST\n", monitor, primary );
SetRect( &rc, 0, 0, 1, 1 );
- monitor = pMonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
+ monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
- monitor = pMonitorFromRect( &rc, MONITOR_DEFAULTTOPRIMARY );
+ monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTOPRIMARY );
ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
- monitor = pMonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST );
+ monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST );
ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
/* Empty rect at 0,0 is considered inside the primary monitor */
SetRect( &rc, 0, 0, -1, -1 );
- monitor = pMonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
+ monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
/* Even if there is a monitor left of the primary, the primary will have the most overlapping area */
SetRect( &rc, -1, 0, 2, 1 );
- monitor = pMonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
+ monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
/* But the width of the rect doesn't matter if it's empty. */
SetRect( &rc, -1, 0, 2, -1 );
- monitor = pMonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
+ monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
ok( monitor != primary, "got primary %p\n", monitor );
- if (!pGetMonitorInfoA)
- {
- win_skip("GetMonitorInfoA is not available\n");
- return;
- }
-
/* Search for a monitor that has no others equally near to (left, top-1) */
SetRect( &rc, -1, -2, 2, 0 );
- monitor = pMonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
+ monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
nearest = primary;
while (monitor != NULL)
{
ok( monitor != primary, "got primary %p\n", monitor );
nearest = monitor;
mi.cbSize = sizeof(mi);
- ret = pGetMonitorInfoA( monitor, &mi );
+ ret = GetMonitorInfoA( monitor, &mi );
ok( ret, "GetMonitorInfo failed\n" );
SetRect( &rc, mi.rcMonitor.left-1, mi.rcMonitor.top-2, mi.rcMonitor.left+2, mi.rcMonitor.top );
- monitor = pMonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
+ monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
}
/* tests for cbSize in MONITORINFO */
- monitor = pMonitorFromWindow( 0, MONITOR_DEFAULTTOPRIMARY );
+ monitor = MonitorFromWindow( 0, MONITOR_DEFAULTTOPRIMARY );
for (i = 0; i < ARRAY_SIZE(testdatami); i++)
{
memset( &mi, 0, sizeof(mi) );
mi.cbSize = testdatami[i].cbSize;
- ret = pGetMonitorInfoA( monitor, &mi );
+ ret = GetMonitorInfoA( monitor, &mi );
ok( ret == testdatami[i].ret, "GetMonitorInfo returned wrong value\n" );
if (ret)
ok( (mi.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag isn't set\n" );
@@ -542,7 +494,7 @@ static void test_monitors(void)
memset( &miexw, 0, sizeof(miexw) );
miexw.cbSize = testdatamiexw[i].cbSize;
- ret = pGetMonitorInfoW( monitor, (LPMONITORINFO)&miexw );
+ ret = GetMonitorInfoW( monitor, (LPMONITORINFO)&miexw );
ok( ret == testdatamiexw[i].ret, "GetMonitorInfo returned wrong value\n" );
if (ret)
ok( (miexw.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag isn't set\n" );
@@ -555,7 +507,7 @@ static void test_monitors(void)
{
memset( &miexa, 0, sizeof(miexa) );
miexa.cbSize = testdatamiexa[i].cbSize;
- ret = pGetMonitorInfoA( monitor, (LPMONITORINFO)&miexa );
+ ret = GetMonitorInfoA( monitor, (LPMONITORINFO)&miexa );
ok( ret == testdatamiexa[i].ret, "GetMonitorInfo returned wrong value\n" );
if (ret)
ok( (miexa.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag isn't set\n" );
@@ -568,7 +520,7 @@ static void test_monitors(void)
{
memset( &miexw, 0, sizeof(miexw) );
miexw.cbSize = testdatamiexw[i].cbSize;
- ret = pGetMonitorInfoW( monitor, (LPMONITORINFO)&miexw );
+ ret = GetMonitorInfoW( monitor, (LPMONITORINFO)&miexw );
ok( ret == testdatamiexw[i].ret, "GetMonitorInfo returned wrong value\n" );
if (ret)
ok( (miexw.dwFlags & MONITORINFOF_PRIMARY), "MONITORINFOF_PRIMARY flag isn't set\n" );
@@ -578,13 +530,13 @@ static void test_monitors(void)
SetRect( &rc, rc.left+1, rc.top+1, rc.left+2, rc.top+2 );
- monitor = pMonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
+ monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONULL );
ok( monitor == NULL, "got %p\n", monitor );
- monitor = pMonitorFromRect( &rc, MONITOR_DEFAULTTOPRIMARY );
+ monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTOPRIMARY );
ok( monitor == primary, "got %p, should get primary %p\n", monitor, primary );
- monitor = pMonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST );
+ monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST );
ok( monitor == nearest, "got %p, should get nearest %p\n", monitor, nearest );
}
@@ -594,7 +546,7 @@ static BOOL CALLBACK find_primary_mon(HMONITOR hmon, HDC hdc, LPRECT rc, LPARAM
BOOL ret;
mi.cbSize = sizeof(mi);
- ret = pGetMonitorInfoA(hmon, &mi);
+ ret = GetMonitorInfoA(hmon, &mi);
ok(ret, "GetMonitorInfo failed\n");
if (mi.dwFlags & MONITORINFOF_PRIMARY)
{
@@ -613,19 +565,13 @@ static void test_work_area(void)
WINDOWPLACEMENT wp;
BOOL ret;
- if (!pEnumDisplayMonitors || !pGetMonitorInfoA)
- {
- win_skip("EnumDisplayMonitors or GetMonitorInfoA are not available\n");
- return;
- }
-
hmon = 0;
- ret = pEnumDisplayMonitors(NULL, NULL, find_primary_mon, (LPARAM)&hmon);
+ ret = EnumDisplayMonitors(NULL, NULL, find_primary_mon, (LPARAM)&hmon);
ok(!ret && hmon != 0, "Failed to find primary monitor\n");
mi.cbSize = sizeof(mi);
SetLastError(0xdeadbeef);
- ret = pGetMonitorInfoA(hmon, &mi);
+ ret = GetMonitorInfoA(hmon, &mi);
ok(ret, "GetMonitorInfo error %u\n", GetLastError());
ok(mi.dwFlags & MONITORINFOF_PRIMARY, "not a primary monitor\n");
trace("primary monitor %s\n", wine_dbgstr_rect(&mi.rcMonitor));
--
2.24.0
Dec. 3, 2019
Re: [PATCH 4/5] msvcrt: Create global lc_time_curr and use when possible.
by Piotr Caban
Hi Jeff,
Could you please rename the MSVCRT_time_curr to something like
time_data_c so the name shows it's for C locale?
It also needs to be freed on dll unload. On the other hand it may better
to initialize it statically.
Thanks,
Piotr
Dec. 3, 2019
Re: [PATCH 2/5] msvcrt: Refactor failure code for create_locinfo.
by Piotr Caban
Hi Jeff,
On 12/2/19 6:52 PM, Jeff Smith wrote:
> - if(!locinfo->lconv) {
> - free_locinfo(locinfo);
> - return NULL;
> - }
> + if(!locinfo->lconv)
> + goto failed;
I'm not sure if it's an improvement. I think I would prefer the code to
stay as it is.
Thanks,
Piotr
Dec. 3, 2019
Re: [PATCH 1/5] ucrtbase: Improve strftime special test cases for %c %r formats.
by Piotr Caban
Hi Jeff,
On 12/2/19 6:52 PM, Jeff Smith wrote:
> + locale = p_setlocale(LC_ALL, NULL);
> + p_setlocale(LC_ALL, "fr-FR");
setlocale may fail if the system is not supporting given locale. Please
skip the test in this case.
> + ret = p_strftime(buf, sizeof(buf), "%c", &epoch);
> + ok(ret == strlen(expected), "ret = %d\n", ret);
> + ok(!strcmp(buf, expected), "buf = \"%s\", expected \"%s\"\n", buf, expected);
> + ret = p_strftime(buf, sizeof(buf), "%x %r", &epoch);
> + todo_wine ok(ret == strlen(expected), "ret = %d\n", ret);
> + todo_wine ok(!strcmp(buf, expected), "buf = \"%s\", expected \"%s\"\n", buf, expected);
Please change it to:
ok(ret == strlen(buf), "ret = %d\n", ret);
todo_wine ok(!strcmp(buf, "01/01/1970 00:00:00"), ...);
It makes the expected variable not needed. I think the test is easier to
read this way.
> + p_setlocale(LC_ALL, locale);
Please restore C locale after the test (there's no need to store
previous locale).
Thanks,
Piotr
Dec. 3, 2019
Re: [PATCH v2 6/6] wined3d: Store the blend factor in the stateblock as a render state.
by Henri Verbeet
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
Dec. 3, 2019
[PATCH] mshtml/tests: Fix a typo in ok() message.
by Andrey Gusev
Signed-off-by: Andrey Gusev <andrey.goosev(a)gmail.com>
---
dlls/mshtml/tests/htmldoc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mshtml/tests/htmldoc.c b/dlls/mshtml/tests/htmldoc.c
index 4b55fdd0c8..141d2378db 100644
--- a/dlls/mshtml/tests/htmldoc.c
+++ b/dlls/mshtml/tests/htmldoc.c
@@ -2879,7 +2879,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID
readystate_set_interactive = (load_state != LD_INTERACTIVE);
break;
default:
- ok(0, "unexpevted V_I4(pvaIn)=%d\n", V_I4(pvaIn));
+ ok(0, "unexpected V_I4(pvaIn)=%d\n", V_I4(pvaIn));
}
return S_OK;
--
2.23.0
Dec. 3, 2019
[PATCH] ieframe/tests: Fix a typo in ok() message.
by Andrey Gusev
Signed-off-by: Andrey Gusev <andrey.goosev(a)gmail.com>
---
dlls/ieframe/tests/webbrowser.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ieframe/tests/webbrowser.c b/dlls/ieframe/tests/webbrowser.c
index a99c68ac5e..f89b2c5b57 100644
--- a/dlls/ieframe/tests/webbrowser.c
+++ b/dlls/ieframe/tests/webbrowser.c
@@ -420,7 +420,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID
CHECK_EXPECT2(Exec_SETDOWNLOADSTATE_1);
break;
default:
- ok(0, "unexpevted V_I4(pvaIn)=%d\n", V_I4(pvaIn));
+ ok(0, "unexpected V_I4(pvaIn)=%d\n", V_I4(pvaIn));
}
return S_OK;
case OLECMDID_UPDATECOMMANDS:
--
2.23.0
Dec. 3, 2019
[PATCH 2/2] mfplat: Set origin name attribute for stream based bytestreams too.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mfplat/main.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index fc656678ca..910b923542 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -3245,6 +3245,7 @@ HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **byt
{
struct bytestream *object;
LARGE_INTEGER position;
+ STATSTG stat;
HRESULT hr;
TRACE("%p, %p.\n", stream, bytestream);
@@ -3271,6 +3272,16 @@ HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **byt
position.QuadPart = 0;
IStream_Seek(object->stream, position, STREAM_SEEK_SET, NULL);
+ if (SUCCEEDED(IStream_Stat(object->stream, &stat, 0)))
+ {
+ if (stat.pwcsName)
+ {
+ IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME,
+ stat.pwcsName);
+ CoTaskMemFree(stat.pwcsName);
+ }
+ }
+
*bytestream = &object->IMFByteStream_iface;
return S_OK;
--
2.24.0
Dec. 3, 2019
[PATCH 1/2] mfplat: Use underlying stream access mode for bytestream capabilities.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mfplat/main.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index e4ade7f202..fc656678ca 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -2700,6 +2700,24 @@ static ULONG WINAPI bytestream_Release(IMFByteStream *iface)
return refcount;
}
+static HRESULT WINAPI bytestream_stream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
+{
+ struct bytestream *stream = impl_from_IMFByteStream(iface);
+ STATSTG stat;
+ HRESULT hr;
+
+ TRACE("%p, %p.\n", iface, capabilities);
+
+ if (FAILED(hr = IStream_Stat(stream->stream, &stat, STATFLAG_NONAME)))
+ return hr;
+
+ *capabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_SEEKABLE;
+ if (stat.grfMode & (STGM_WRITE | STGM_READWRITE))
+ *capabilities |= MFBYTESTREAM_IS_WRITABLE;
+
+ return S_OK;
+}
+
static HRESULT WINAPI bytestream_GetCapabilities(IMFByteStream *iface, DWORD *capabilities)
{
struct bytestream *stream = impl_from_IMFByteStream(iface);
@@ -3060,7 +3078,7 @@ static const IMFByteStreamVtbl bytestream_stream_vtbl =
bytestream_QueryInterface,
bytestream_AddRef,
bytestream_Release,
- bytestream_GetCapabilities,
+ bytestream_stream_GetCapabilities,
bytestream_stream_GetLength,
bytestream_stream_SetLength,
bytestream_stream_GetCurrentPosition,
@@ -3252,7 +3270,6 @@ HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **byt
IStream_AddRef(object->stream);
position.QuadPart = 0;
IStream_Seek(object->stream, position, STREAM_SEEK_SET, NULL);
- object->capabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_SEEKABLE;
*bytestream = &object->IMFByteStream_iface;
--
2.24.0
Dec. 3, 2019
[PATCH 2/2] ntdll: Add support for querying thread suspend count.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
x64dbg debugger uses this info class, checking suspend status periodically.
When unavailable, it repeatedly suspends/resumes threads as a fallback to
get NtSuspendThread() returned counter, which is not ideal.
dlls/ntdll/tests/exception.c | 63 +++++++++++++++++++++++++++++++++-
dlls/ntdll/thread.c | 21 ++++++++++++
include/wine/server_protocol.h | 4 ++-
include/winternl.h | 1 +
server/protocol.def | 1 +
server/request.h | 5 +--
server/thread.c | 1 +
server/trace.c | 1 +
8 files changed, 93 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index fb58c0ee7a..44df47466b 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -50,6 +50,7 @@ static ULONG (WINAPI *pRtlRemoveVectoredContinueHandler)(PVOID handler);
static NTSTATUS (WINAPI *pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE handle, LONG exit_code);
static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
+static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG);
static NTSTATUS (WINAPI *pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
static NTSTATUS (WINAPI *pNtClose)(HANDLE);
@@ -3163,11 +3164,34 @@ static DWORD WINAPI suspend_thread_test( void *arg )
return 0;
}
+static void test_suspend_count(HANDLE hthread, ULONG expected_count, int line)
+{
+ static BOOL supported = TRUE;
+ NTSTATUS status;
+ ULONG count;
+
+ if (!supported)
+ return;
+
+ count = ~0u;
+ status = pNtQueryInformationThread(hthread, ThreadSuspendCount, &count, sizeof(count), NULL);
+ if (status)
+ {
+ win_skip("ThreadSuspendCount is not supported.\n");
+ supported = FALSE;
+ return;
+ }
+
+ ok_(__FILE__, line)(!status, "Failed to get suspend count, status %#x.\n", status);
+ ok_(__FILE__, line)(count == expected_count, "Unexpected suspend count %u.\n", count);
+}
+
static void test_suspend_thread(void)
{
+#define TEST_SUSPEND_COUNT(thread, count) test_suspend_count((thread), (count), __LINE__)
HANDLE thread, event;
+ ULONG count, len;
NTSTATUS status;
- ULONG count;
DWORD ret;
status = NtSuspendThread(0, NULL);
@@ -3184,6 +3208,31 @@ static void test_suspend_thread(void)
ret = WaitForSingleObject(thread, 0);
ok(ret == WAIT_TIMEOUT, "Unexpected status %d.\n", ret);
+ status = pNtQueryInformationThread(thread, ThreadSuspendCount, &count, sizeof(count), NULL);
+ if (!status)
+ {
+ status = pNtQueryInformationThread(thread, ThreadSuspendCount, NULL, sizeof(count), NULL);
+ ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#x.\n", status);
+
+ status = pNtQueryInformationThread(thread, ThreadSuspendCount, &count, sizeof(count) / 2, NULL);
+ ok(status == STATUS_INFO_LENGTH_MISMATCH, "Unexpected status %#x.\n", status);
+
+ len = 123;
+ status = pNtQueryInformationThread(thread, ThreadSuspendCount, &count, sizeof(count) / 2, &len);
+ ok(status == STATUS_INFO_LENGTH_MISMATCH, "Unexpected status %#x.\n", status);
+ ok(len == 123, "Unexpected info length %u.\n", len);
+
+ len = 123;
+ status = pNtQueryInformationThread(thread, ThreadSuspendCount, NULL, 0, &len);
+ ok(status == STATUS_INFO_LENGTH_MISMATCH, "Unexpected status %#x.\n", status);
+ ok(len == 123, "Unexpected info length %u.\n", len);
+
+ count = 10;
+ status = pNtQueryInformationThread(0, ThreadSuspendCount, &count, sizeof(count), NULL);
+ ok(status, "Unexpected status %#x.\n", status);
+ ok(count == 10, "Unexpected suspend count %u.\n", count);
+ }
+
status = NtResumeThread(thread, NULL);
ok(!status, "Unexpected status %#x.\n", status);
@@ -3191,24 +3240,35 @@ static void test_suspend_thread(void)
ok(!status, "Unexpected status %#x.\n", status);
ok(count == 0, "Unexpected suspended count %u.\n", count);
+ TEST_SUSPEND_COUNT(thread, 0);
+
status = NtSuspendThread(thread, NULL);
ok(!status, "Failed to suspend a thread, status %#x.\n", status);
+ TEST_SUSPEND_COUNT(thread, 1);
+
status = NtSuspendThread(thread, &count);
ok(!status, "Failed to suspend a thread, status %#x.\n", status);
ok(count == 1, "Unexpected suspended count %u.\n", count);
+ TEST_SUSPEND_COUNT(thread, 2);
+
status = NtResumeThread(thread, &count);
ok(!status, "Failed to resume a thread, status %#x.\n", status);
ok(count == 2, "Unexpected suspended count %u.\n", count);
+ TEST_SUSPEND_COUNT(thread, 1);
+
status = NtResumeThread(thread, NULL);
ok(!status, "Failed to resume a thread, status %#x.\n", status);
+ TEST_SUSPEND_COUNT(thread, 0);
+
SetEvent(event);
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
+#undef TEST_SUSPEND_COUNT
}
static const char *suspend_process_event_name = "suspend_process_event";
@@ -3418,6 +3478,7 @@ START_TEST(exception)
X(RtlAddVectoredContinueHandler);
X(RtlRemoveVectoredContinueHandler);
X(NtQueryInformationProcess);
+ X(NtQueryInformationThread);
X(NtSetInformationProcess);
X(NtSuspendProcess);
X(NtResumeProcess);
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index fd8d388403..f993dd314c 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -1115,6 +1115,27 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
*(BOOL*)data = FALSE;
if (ret_len) *ret_len = sizeof(BOOL);
return STATUS_SUCCESS;
+ case ThreadSuspendCount:
+ {
+ ULONG count = 0;
+
+ if (length != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
+ if (!data) return STATUS_ACCESS_VIOLATION;
+
+ SERVER_START_REQ( get_thread_info )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ req->tid_in = 0;
+ if (!(status = wine_server_call( req )))
+ count = reply->suspend_count;
+ }
+ SERVER_END_REQ;
+
+ if (!status)
+ *(ULONG *)data = count;
+
+ return status;
+ }
case ThreadDescription:
{
THREAD_DESCRIPTION_INFORMATION *info = data;
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 108701b2bc..aaa5fd2e33 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1006,8 +1006,10 @@ struct get_thread_info_reply
int exit_code;
int priority;
int last;
+ int suspend_count;
data_size_t desc_len;
/* VARARG(desc,unicode_str); */
+ char __pad_60[4];
};
@@ -6700,6 +6702,6 @@ union generic_reply
struct resume_process_reply resume_process_reply;
};
-#define SERVER_PROTOCOL_VERSION 592
+#define SERVER_PROTOCOL_VERSION 593
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/include/winternl.h b/include/winternl.h
index 311fba3ae9..83449b80c7 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -1008,6 +1008,7 @@ typedef enum _THREADINFOCLASS {
ThreadUmsInformation,
ThreadCounterProfiling,
ThreadIdealProcessorEx,
+ ThreadSuspendCount = 35,
ThreadDescription = 38,
MaxThreadInfoClass
} THREADINFOCLASS;
diff --git a/server/protocol.def b/server/protocol.def
index 566bc83bb2..1cb1fea602 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -944,6 +944,7 @@ struct rawinput_device
int exit_code; /* thread exit code */
int priority; /* thread priority level */
int last; /* last thread in process */
+ int suspend_count; /* thread suspend count */
data_size_t desc_len; /* description length in bytes */
VARARG(desc,unicode_str); /* description string */
@END
diff --git a/server/request.h b/server/request.h
index de7720ae68..2930b31d72 100644
--- a/server/request.h
+++ b/server/request.h
@@ -849,8 +849,9 @@ C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, affinity) == 32 );
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, exit_code) == 40 );
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, priority) == 44 );
C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, last) == 48 );
-C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, desc_len) == 52 );
-C_ASSERT( sizeof(struct get_thread_info_reply) == 56 );
+C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, suspend_count) == 52 );
+C_ASSERT( FIELD_OFFSET(struct get_thread_info_reply, desc_len) == 56 );
+C_ASSERT( sizeof(struct get_thread_info_reply) == 64 );
C_ASSERT( FIELD_OFFSET(struct get_thread_times_request, handle) == 12 );
C_ASSERT( sizeof(struct get_thread_times_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_thread_times_reply, creation_time) == 8 );
diff --git a/server/thread.c b/server/thread.c
index 4fc6abf0ef..80db41b48d 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -1463,6 +1463,7 @@ DECL_HANDLER(get_thread_info)
reply->priority = thread->priority;
reply->affinity = thread->affinity;
reply->last = thread->process->running_threads == 1;
+ reply->suspend_count = thread->suspend;
reply->desc_len = thread->desc_len;
if (thread->desc && get_reply_max_size())
diff --git a/server/trace.c b/server/trace.c
index d44f67a021..411369a4f6 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1423,6 +1423,7 @@ static void dump_get_thread_info_reply( const struct get_thread_info_reply *req
fprintf( stderr, ", exit_code=%d", req->exit_code );
fprintf( stderr, ", priority=%d", req->priority );
fprintf( stderr, ", last=%d", req->last );
+ fprintf( stderr, ", suspend_count=%d", req->suspend_count );
fprintf( stderr, ", desc_len=%u", req->desc_len );
dump_varargs_unicode_str( ", desc=", cur_size );
}
--
2.24.0
Dec. 3, 2019
[PATCH 1/2] ntdll: Use better type for thread description info structure.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
I didn't realize UNICODE_STRING lengths are 2-byte.
dlls/kernel32/tests/thread.c | 28 ++++++++++++++--------------
dlls/kernelbase/thread.c | 14 ++++++--------
dlls/ntdll/thread.c | 12 +++++-------
include/winternl.h | 3 +--
4 files changed, 26 insertions(+), 31 deletions(-)
diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
index 8ff34ba5f3..9a8ad9151c 100644
--- a/dlls/kernel32/tests/thread.c
+++ b/dlls/kernel32/tests/thread.c
@@ -2145,14 +2145,15 @@ static void test_thread_description(void)
ok(len == sizeof(*thread_desc), "Unexpected structure length %u.\n", len);
len2 = 0;
- thread_desc->Length = 1;
- thread_desc->Description = (WCHAR *)thread_desc;
+ thread_desc->Description.Length = 1;
+ thread_desc->Description.MaximumLength = 0;
+ thread_desc->Description.Buffer = (WCHAR *)thread_desc;
status = pNtQueryInformationThread(GetCurrentThread(), ThreadDescription, thread_desc, len, &len2);
ok(!status, "Failed to get thread info, status %#x.\n", status);
ok(len2 == sizeof(*thread_desc), "Unexpected structure length %u.\n", len);
- ok(!thread_desc->Length, "Unexpected description length %#x.\n", thread_desc->Length);
- ok(thread_desc->Description == (WCHAR *)(thread_desc + 1), "Unexpected description string pointer %p, %p.\n",
- thread_desc->Description, thread_desc);
+ ok(!thread_desc->Description.Length, "Unexpected description length %#x.\n", thread_desc->Description.Length);
+ ok(thread_desc->Description.Buffer == (WCHAR *)(thread_desc + 1),
+ "Unexpected description string pointer %p, %p.\n", thread_desc->Description.Buffer, thread_desc);
hr = pSetThreadDescription(GetCurrentThread(), NULL);
ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#x.\n", hr);
@@ -2176,11 +2177,11 @@ static void test_thread_description(void)
ok(!status, "Failed to get thread info.\n");
ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %u.\n", len);
- ok(thread_desc->Length == (desc_len << 16 | desc_len), "Unexpected description length %#x.\n",
- thread_desc->Length);
- ok(thread_desc->Description == (WCHAR *)(thread_desc + 1), "Unexpected description string pointer %p, %p.\n",
- thread_desc->Description, thread_desc);
- ok(!memcmp(thread_desc->Description, desc, desc_len), "Unexpected description string.\n");
+ ok(thread_desc->Description.Length == desc_len && thread_desc->Description.MaximumLength == desc_len,
+ "Unexpected description length %u.\n", thread_desc->Description.Length);
+ ok(thread_desc->Description.Buffer == (WCHAR *)(thread_desc + 1),
+ "Unexpected description string pointer %p, %p.\n", thread_desc->Description.Buffer, thread_desc);
+ ok(!memcmp(thread_desc->Description.Buffer, desc, desc_len), "Unexpected description string.\n");
/* Partial results. */
len = 0;
@@ -2193,7 +2194,7 @@ static void test_thread_description(void)
ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %u.\n", len);
/* Change description. */
- thread_desc->Length = 8 << 16 | 8;
+ thread_desc->Description.Length = thread_desc->Description.MaximumLength = 8;
lstrcpyW((WCHAR *)(thread_desc + 1), L"desc");
status = pNtSetInformationThread(GetCurrentThread(), ThreadDescription, thread_desc, sizeof(*thread_desc));
@@ -2211,7 +2212,7 @@ static void test_thread_description(void)
status = NtSetInformationThread(GetCurrentThread(), ThreadDescription, NULL, sizeof(*thread_desc));
ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#x.\n", status);
- thread_desc->Description = NULL;
+ thread_desc->Description.Buffer = NULL;
status = pNtSetInformationThread(GetCurrentThread(), ThreadDescription, thread_desc, sizeof(*thread_desc));
ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#x.\n", status);
@@ -2228,8 +2229,7 @@ static void test_thread_description(void)
hr = pSetThreadDescription(GetCurrentThread(), L"123");
ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#x.\n", hr);
- thread_desc->Length = 0;
- thread_desc->Description = NULL;
+ memset(thread_desc, 0, sizeof(*thread_desc));
status = pNtSetInformationThread(GetCurrentThread(), ThreadDescription, thread_desc, sizeof(*thread_desc));
ok(!status, "Failed to set thread description, status %#x.\n", status);
diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c
index 521d3be079..2f0bcb7dde 100644
--- a/dlls/kernelbase/thread.c
+++ b/dlls/kernelbase/thread.c
@@ -404,8 +404,8 @@ HRESULT WINAPI DECLSPEC_HOTPATCH SetThreadDescription( HANDLE thread, PCWSTR des
if (length > USHRT_MAX)
return HRESULT_FROM_NT(STATUS_INVALID_PARAMETER);
- info.Length = length << 16 | length;
- info.Description = (WCHAR *)description;
+ info.Description.Length = info.Description.MaximumLength = length;
+ info.Description.Buffer = (WCHAR *)description;
return HRESULT_FROM_NT(NtSetInformationThread( thread, ThreadDescription, &info, sizeof(info) ));
}
@@ -434,15 +434,13 @@ HRESULT WINAPI DECLSPEC_HOTPATCH GetThreadDescription( HANDLE thread, WCHAR **de
status = NtQueryInformationThread( thread, ThreadDescription, info, length, &length );
if (!status)
{
- length = info->Length & 0xffff;
-
- if (!(*description = LocalAlloc( 0, length + sizeof(WCHAR))))
+ if (!(*description = LocalAlloc( 0, info->Description.Length + sizeof(WCHAR))))
status = STATUS_NO_MEMORY;
else
{
- if (length)
- memcpy(*description, info->Description, length);
- (*description)[length / sizeof(WCHAR)] = 0;
+ if (info->Description.Length)
+ memcpy(*description, info->Description.Buffer, info->Description.Length);
+ (*description)[info->Description.Length / sizeof(WCHAR)] = 0;
}
}
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 6079a6c195..fd8d388403 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -1137,8 +1137,8 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
status = STATUS_BUFFER_TOO_SMALL;
else if (status == STATUS_SUCCESS)
{
- info->Length = desc_len << 16 | desc_len;
- info->Description = ptr;
+ info->Description.Length = info->Description.MaximumLength = desc_len;
+ info->Description.Buffer = ptr;
}
if (ret_len && (status == STATUS_SUCCESS || status == STATUS_BUFFER_TOO_SMALL))
@@ -1303,20 +1303,18 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
case ThreadDescription:
{
const THREAD_DESCRIPTION_INFORMATION *info = data;
- data_size_t desc_len;
if (length != sizeof(*info)) return STATUS_INFO_LENGTH_MISMATCH;
if (!info) return STATUS_ACCESS_VIOLATION;
- desc_len = info->Length & 0xffff;
- if (info->Length >> 16 != desc_len) return STATUS_INVALID_PARAMETER;
- if (info->Length && !info->Description) return STATUS_ACCESS_VIOLATION;
+ if (info->Description.Length != info->Description.MaximumLength) return STATUS_INVALID_PARAMETER;
+ if (info->Description.Length && !info->Description.Buffer) return STATUS_ACCESS_VIOLATION;
SERVER_START_REQ( set_thread_info )
{
req->handle = wine_server_obj_handle( handle );
req->mask = SET_THREAD_INFO_DESCRIPTION;
- wine_server_add_data( req, info->Description, desc_len );
+ wine_server_add_data( req, info->Description.Buffer, info->Description.Length );
status = wine_server_call( req );
}
SERVER_END_REQ;
diff --git a/include/winternl.h b/include/winternl.h
index 1477932d10..311fba3ae9 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -1030,8 +1030,7 @@ typedef struct _THREAD_DESCRIPTOR_INFORMATION
typedef struct _THREAD_DESCRIPTION_INFORMATION
{
- DWORD Length;
- WCHAR *Description;
+ UNICODE_STRING Description;
} THREAD_DESCRIPTION_INFORMATION, *PTHREAD_DESCRIPTION_INFORMATION;
typedef struct _KERNEL_USER_TIMES {
--
2.24.0
Dec. 3, 2019
[PATCH] d3dcompiler/tests: Fix parameter desc test on d3d10.
by Matteo Bruni
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
---
D3D11_SIGNATURE_PARAMETER_DESC has an additional "Stream" field
compared to D3D10_SIGNATURE_PARAMETER_DESC but they share the same
size on 64-bit because of padding (while they do not on 32-bit). Don't
check the contents of the padding area.
Inspired by a patch from Sven Baars.
dlls/d3dcompiler_43/tests/reflection.c | 38 +++++++++++++++++++-------
1 file changed, 28 insertions(+), 10 deletions(-)
diff --git a/dlls/d3dcompiler_43/tests/reflection.c b/dlls/d3dcompiler_43/tests/reflection.c
index f8c97230d61..44e66044ec1 100644
--- a/dlls/d3dcompiler_43/tests/reflection.c
+++ b/dlls/d3dcompiler_43/tests/reflection.c
@@ -433,8 +433,14 @@ static void test_reflection_desc_vs(void)
i, desc.Mask, pdesc->Mask);
ok(desc.ReadWriteMask == pdesc->ReadWriteMask, "GetInputParameterDesc(%u) ReadWriteMask failed, got %x, expected %x\n",
i, desc.ReadWriteMask, pdesc->ReadWriteMask);
- ok(desc.Stream == pdesc->Stream, "GetInputParameterDesc(%u) Stream failed, got %u, expected %u\n",
- i, desc.Stream, pdesc->Stream);
+ /* The Stream field of D3D11_SIGNATURE_PARAMETER_DESC is in the
+ * trailing padding of the D3D10_SIGNATURE_PARAMETER_DESC struct on
+ * 64-bits and thus undefined. Don't test it. */
+ if (D3D_COMPILER_VERSION)
+ ok(desc.Stream == pdesc->Stream, "(%u): got unexpected Stream %u, expected %u.\n",
+ i, desc.Stream, pdesc->Stream);
+ else if (sizeof(void *) == 4)
+ ok(!desc.Stream, "(%u): got unexpected Stream %u.\n", i, desc.Stream);
}
for (i = 0; i < ARRAY_SIZE(test_reflection_desc_vs_resultout); ++i)
@@ -458,8 +464,11 @@ static void test_reflection_desc_vs(void)
i, desc.Mask, pdesc->Mask);
ok(desc.ReadWriteMask == pdesc->ReadWriteMask, "GetOutputParameterDesc(%u) ReadWriteMask failed, got %x, expected %x\n",
i, desc.ReadWriteMask, pdesc->ReadWriteMask);
- ok(desc.Stream == pdesc->Stream, "GetOutputParameterDesc(%u) Stream failed, got %u, expected %u\n",
- i, desc.Stream, pdesc->Stream);
+ if (D3D_COMPILER_VERSION)
+ ok(desc.Stream == pdesc->Stream, "(%u): got unexpected Stream %u, expected %u.\n",
+ i, desc.Stream, pdesc->Stream);
+ else if (sizeof(void *) == 4)
+ ok(!desc.Stream, "(%u): got unexpected Stream %u.\n", i, desc.Stream);
}
count = ref11->lpVtbl->Release(ref11);
@@ -740,8 +749,11 @@ static void test_reflection_desc_ps(void)
i, desc.Mask, pdesc->Mask);
ok(desc.ReadWriteMask == pdesc->ReadWriteMask, "GetInputParameterDesc(%u) ReadWriteMask failed, got %x, expected %x\n",
i, desc.ReadWriteMask, pdesc->ReadWriteMask);
- ok(desc.Stream == pdesc->Stream, "GetInputParameterDesc(%u) Stream failed, got %u, expected %u\n",
- i, desc.Stream, pdesc->Stream);
+ if (D3D_COMPILER_VERSION)
+ ok(desc.Stream == pdesc->Stream, "(%u): got unexpected Stream %u, expected %u.\n",
+ i, desc.Stream, pdesc->Stream);
+ else if (sizeof(void *) == 4)
+ ok(!desc.Stream, "(%u): got unexpected Stream %u.\n", i, desc.Stream);
}
for (i = 0; i < ARRAY_SIZE(test_reflection_desc_ps_resultout); ++i)
@@ -771,8 +783,11 @@ static void test_reflection_desc_ps(void)
i, desc.Mask, pdesc->Mask);
ok(desc.ReadWriteMask == pdesc->ReadWriteMask, "GetOutputParameterDesc(%u) ReadWriteMask failed, got %x, expected %x\n",
i, desc.ReadWriteMask, pdesc->ReadWriteMask);
- ok(desc.Stream == pdesc->Stream, "GetOutputParameterDesc(%u) Stream failed, got %u, expected %u\n",
- i, desc.Stream, pdesc->Stream);
+ if (D3D_COMPILER_VERSION)
+ ok(desc.Stream == pdesc->Stream, "(%u): got unexpected Stream %u, expected %u.\n",
+ i, desc.Stream, pdesc->Stream);
+ else if (sizeof(void *) == 4)
+ ok(!desc.Stream, "(%u): got unexpected Stream %u.\n", i, desc.Stream);
}
count = ref11->lpVtbl->Release(ref11);
@@ -1008,8 +1023,11 @@ static void test_reflection_desc_ps_output(void)
i, desc.Mask, pdesc->Mask);
ok(desc.ReadWriteMask == pdesc->ReadWriteMask, "(%u): GetOutputParameterDesc ReadWriteMask failed, got %x, expected %x\n",
i, desc.ReadWriteMask, pdesc->ReadWriteMask);
- ok(desc.Stream == pdesc->Stream, "(%u): GetOutputParameterDesc Stream failed, got %u, expected %u\n",
- i, desc.Stream, pdesc->Stream);
+ if (D3D_COMPILER_VERSION)
+ ok(desc.Stream == pdesc->Stream, "(%u): got unexpected Stream %u, expected %u.\n",
+ i, desc.Stream, pdesc->Stream);
+ else if (sizeof(void *) == 4)
+ ok(!desc.Stream, "(%u): got unexpected Stream %u.\n", i, desc.Stream);
count = ref11->lpVtbl->Release(ref11);
ok(count == 0, "(%u): Release failed %u\n", i, count);
--
2.23.0
Dec. 3, 2019
Re: [PATCH] msiexec: Improve RegQueryValueExW() calls a bit.
by Alexandre Julliard
Serge Gautherie <winehq-git_serge_180711(a)gautherie.fr> writes:
> Signed-off-by: Serge Gautherie <winehq-git_serge_180711(a)gautherie.fr>
> ---
> programs/msiexec/msiexec.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/programs/msiexec/msiexec.c b/programs/msiexec/msiexec.c
> index 17d4bf8..dd83dac 100644
> --- a/programs/msiexec/msiexec.c
> +++ b/programs/msiexec/msiexec.c
> @@ -573,14 +573,14 @@ static BOOL process_args_from_reg( const WCHAR *ident, int *pargc, WCHAR ***parg
> {
> LONG r;
> HKEY hkey;
> - DWORD sz = 0, type = 0;
> + DWORD sz, type;
> WCHAR *buf;
> BOOL ret = FALSE;
>
> r = RegOpenKeyW(HKEY_LOCAL_MACHINE, InstallRunOnce, &hkey);
> if(r != ERROR_SUCCESS)
> return FALSE;
> - r = RegQueryValueExW(hkey, ident, 0, &type, 0, &sz);
> + r = RegQueryValueExW(hkey, ident, NULL, &type, NULL, &sz);
The indentation is messed up. Also please try to write better commit
messages, "improve a bit" doesn't tell us anything.
--
Alexandre Julliard
julliard(a)winehq.org
Dec. 3, 2019
Re: [PATCH] riched20/tests: Fix function names in two ok() messages.
by Huw Davies
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
Dec. 3, 2019
Re: [PATCH v2 4/4] winegstreamer: Use strmbase state change methods.
by Alexandre Julliard
Zebediah Figura <z.figura12(a)gmail.com> writes:
> Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
> ---
> dlls/winegstreamer/gstdemux.c | 255 ++++++++++++++++------------------
> 1 file changed, 122 insertions(+), 133 deletions(-)
This is still causing deadlocks:
../../../tools/runtest -q -P wine -T ../../.. -M winmm.dll -p winmm_test.exe mci && touch mci.ok
00e2:fixme:mci:MCI_SendCommand unhandled MCI_ALL_DEVICE_ID
00e2:fixme:mci:MCI_SysInfo Don't know how to get # of MCI devices of a given type
00e2:fixme:mci:MCI_SendCommand unhandled MCI_ALL_DEVICE_ID
00e2:fixme:mci:MCI_LoadMciDriver Couldn't load driver for type L"".
00e2:fixme:mci:MCI_LoadMciDriver Couldn't load driver for type L"".
00e2:fixme:mci:MCI_LoadMciDriver Couldn't load driver for type L"NOSUCHDEVICE".
00e2:fixme:mciwave:MCIWAVE_DriverProc Unsupported command [2134]
00e2:fixme:mci:mciSendStringW leaking auto-open device 1
ALSA lib conf.c:3558:(snd_config_hooks_call) Cannot open shared library libasound_module_conf_pulse.so (/usr/lib/i386-linux-gnu/alsa-lib/libasound_module_conf_pulse.so: libasound_module_conf_pulse.so: cannot open shared object file: No such file or directory)
ALSA lib seq.c:935:(snd_seq_open_noupdate) Unknown SEQ default
00e2:err:winediag:MIDIMAP_drvOpen No software synthesizer midi port found, Midi sound output probably won't work.
00e2:fixme:gstreamer:source_query_accept (0x6ea688) stub
00f9:err:ntdll:RtlpWaitForCriticalSection section 0x6ea1f0 "../strmbase/filter.c: strmbase_filter.csFilter" wait timed out in thread 00f9, blocked by 00fb, retrying (60 sec)
--
Alexandre Julliard
julliard(a)winehq.org
Dec. 3, 2019
Re: [PATCH 1/4] wusa: Add support for extracting MSU files.
by Hans Leidekker
> diff --git a/programs/wusa/wusa.h b/programs/wusa/wusa.h
> new file mode 100644
> index 0000000000..c6bf7eda11
> +
> +static void *heap_alloc(size_t len) __WINE_ALLOC_SIZE(1);
> +static inline void *heap_alloc(size_t len)
> +{
> + return HeapAlloc(GetProcessHeap(), 0, len);
> +}
> +
> +static inline BOOL heap_free(void *mem)
>
> Is there a reason why your not using the wine/heap.h ones?
I left it because we may as well switch to the C allocation functions,
now that we're building with msvcrt.
Dec. 3, 2019