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
November 2021
- 83 participants
- 2620 messages
[PATCH 4/6] light.msstyles: Add TMT_TRANSITIONDURATIONS property.
by Zhiyi Zhang
Set all transition duration to 100ms for different states and 0ms for the same state.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/light.msstyles/light.rc | 193 +++++++++++++++++++++++++++++++++++
dlls/uxtheme/tests/system.c | 1 -
2 files changed, 193 insertions(+), 1 deletion(-)
diff --git a/dlls/light.msstyles/light.rc b/dlls/light.msstyles/light.rc
index cf9271cb612..aad8aa51d09 100644
--- a/dlls/light.msstyles/light.rc
+++ b/dlls/light.msstyles/light.rc
@@ -194,6 +194,13 @@ BLUE_INI TEXTFILE
"ImageLayout = Vertical\r\n"
"TextColor = 0 0 0\r\n"
"MinSize = 10, 5\r\n"
+"TransitionDurations = 6, "
+"0, 100, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, 100, "
+"100, 100, 0, 100, 100, 100, "
+"100, 100, 100, 0, 100, 100, "
+"100, 100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 100, 0\r\n"
"[Button.Pushbutton(Pressed)]\r\n"
"TextColor = 255 255 255\r\n"
@@ -227,6 +234,27 @@ BLUE_INI TEXTFILE
"MinDpi5 = 192\r\n"
"MinDpi6 = 216\r\n"
"MinDpi7 = 240\r\n"
+"TransitionDurations = 20, "
+"0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 100, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0, 100, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0, 100, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0, 100, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0, 100, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0, 100, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0, 100, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0, 100, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0\r\n"
"[Button.Checkbox(Checkeddisabled)]\r\n"
"TextColor = 189 189 189\r\n"
@@ -262,6 +290,15 @@ BLUE_INI TEXTFILE
"MinDpi5 = 192\r\n"
"MinDpi6 = 216\r\n"
"MinDpi7 = 240\r\n"
+"TransitionDurations = 8, "
+"0, 100, 100, 100, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, 100, 100, 100, "
+"100, 100, 0, 100, 100, 100, 100, 100, "
+"100, 100, 100, 0, 100, 100, 100, 100, "
+"100, 100, 100, 100, 0, 100, 100, 100, "
+"100, 100, 100, 100, 100, 0, 100, 100, "
+"100, 100, 100, 100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 100, 100, 100, 0\r\n"
"[Button.Radiobutton(Checkeddisabled)]\r\n"
"TextColor = 189 189 189\r\n"
@@ -292,6 +329,13 @@ BLUE_INI TEXTFILE
"Transparent = True\r\n"
"TextColor = 0 0 0\r\n"
"MinSize = 10, 5\r\n"
+"TransitionDurations = 6, "
+"0, 100, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, 100, "
+"100, 100, 0, 100, 100, 100, "
+"100, 100, 100, 0, 100, 100, "
+"100, 100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 100, 0\r\n"
"[Button.Commandlink(Hot)]\r\n"
"TextColor = 48 150 250\r\n"
@@ -333,6 +377,11 @@ BLUE_INI TEXTFILE
"BorderSize = 1\r\n"
"FillColor = 255 255 255\r\n"
"BorderColor = 174 174 174\r\n"
+"TransitionDurations = 4, "
+"0, 100, 100, 100, "
+"100, 0, 100, 100, "
+"100, 100, 0, 100, "
+"100, 100, 100, 0\r\n"
"[ComboBox(Disabled)]\r\n"
"BorderColor = 228 228 228\r\n"
@@ -350,6 +399,11 @@ BLUE_INI TEXTFILE
"GlyphImageFile = blue_combobutton_glyph.bmp\r\n"
"GlyphTransparent = True\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 4, "
+"0, 100, 100, 100, "
+"100, 0, 100, 100, "
+"100, 100, 0, 100, "
+"100, 100, 100, 0\r\n"
"\r\n; Edit\r\n"
"[Edit]\r\n"
@@ -492,6 +546,14 @@ BLUE_INI TEXTFILE
"VAlign = Top\r\n"
"\r\n; Scroll Bar\r\n"
+"[ScrollBar]\r\n"
+"TransitionDurations = 5, "
+"0, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, "
+"100, 100, 0, 100, 100, "
+"100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 0\r\n"
+
"[ScrollBar.ArrowBtn]\r\n"
"BgType = ImageFile\r\n"
"SizingMargins = 5, 5, 5, 5\r\n"
@@ -601,6 +663,11 @@ BLUE_INI TEXTFILE
"GlyphType = ImageGlyph\r\n"
"GlyphImageFile = blue_spin_glyph_up.bmp\r\n"
"GlyphTransparent = True\r\n"
+"TransitionDurations = 4, "
+"0, 100, 100, 100, "
+"100, 0, 100, 100, "
+"100, 100, 0, 100, "
+"100, 100, 100, 0\r\n"
"[Spin.Down]\r\n"
"BgType = ImageFile\r\n"
@@ -613,6 +680,11 @@ BLUE_INI TEXTFILE
"GlyphType = ImageGlyph\r\n"
"GlyphImageFile = blue_spin_glyph_down.bmp\r\n"
"GlyphTransparent = True\r\n"
+"TransitionDurations = 4, "
+"0, 100, 100, 100, "
+"100, 0, 100, 100, "
+"100, 100, 0, 100, "
+"100, 100, 100, 0\r\n"
"[Spin.Uphorz]\r\n"
"BgType = ImageFile\r\n"
@@ -625,6 +697,11 @@ BLUE_INI TEXTFILE
"GlyphType = ImageGlyph\r\n"
"GlyphImageFile = blue_spin_glyph_right.bmp\r\n"
"GlyphTransparent = True\r\n"
+"TransitionDurations = 4, "
+"0, 100, 100, 100, "
+"100, 0, 100, 100, "
+"100, 100, 0, 100, "
+"100, 100, 100, 0\r\n"
"[Spin.Downhorz]\r\n"
"BgType = ImageFile\r\n"
@@ -637,6 +714,11 @@ BLUE_INI TEXTFILE
"GlyphType = ImageGlyph\r\n"
"GlyphImageFile = blue_spin_glyph_left.bmp\r\n"
"GlyphTransparent = True\r\n"
+"TransitionDurations = 4, "
+"0, 100, 100, 100, "
+"100, 0, 100, 100, "
+"100, 100, 0, 100, "
+"100, 100, 100, 0\r\n"
"\r\n; Status\r\n"
"[Status]\r\n"
@@ -703,6 +785,12 @@ BLUE_INI TEXTFILE
"ImageFile = blue_tab_item.bmp\r\n"
"ImageCount = 5\r\n"
"ImageLayout = Vertical\r\n"
+"TransitionDurations = 5, "
+"0, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, "
+"100, 100, 0, 100, 100, "
+"100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 0\r\n"
"[Tab.TabItemLeftEdge]\r\n"
"SizingMargins = 2, 2, 6, 6\r\n"
@@ -712,6 +800,12 @@ BLUE_INI TEXTFILE
"ImageCount = 5\r\n"
"ImageLayout = Vertical\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 5, "
+"0, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, "
+"100, 100, 0, 100, 100, "
+"100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 0\r\n"
"[Tab.TabItemRightEdge]\r\n"
"SizingMargins = 2, 2, 6, 6\r\n"
@@ -721,6 +815,12 @@ BLUE_INI TEXTFILE
"ImageCount = 5\r\n"
"ImageLayout = Vertical\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 5, "
+"0, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, "
+"100, 100, 0, 100, 100, "
+"100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 0\r\n"
"[Tab.TabItemBothEdge]\r\n"
"SizingMargins = 2, 2, 6, 6\r\n"
@@ -729,6 +829,12 @@ BLUE_INI TEXTFILE
"ImageFile = blue_tab_item.bmp\r\n"
"ImageCount = 5\r\n"
"ImageLayout = Vertical\r\n"
+"TransitionDurations = 5, "
+"0, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, "
+"100, 100, 0, 100, 100, "
+"100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 0\r\n"
"[Tab.TopTabItem]\r\n"
"SizingMargins = 2, 2, 6, 6\r\n"
@@ -738,6 +844,12 @@ BLUE_INI TEXTFILE
"ImageCount = 5\r\n"
"ImageLayout = Vertical\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 5, "
+"0, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, "
+"100, 100, 0, 100, 100, "
+"100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 0\r\n"
"[Tab.TopTabItemLeftEdge]\r\n"
"SizingMargins = 2, 2, 6, 6\r\n"
@@ -747,6 +859,12 @@ BLUE_INI TEXTFILE
"ImageCount = 5\r\n"
"ImageLayout = Vertical\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 5, "
+"0, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, "
+"100, 100, 0, 100, 100, "
+"100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 0\r\n"
"[Tab.TopTabItemRightEdge]\r\n"
"SizingMargins = 2, 2, 6, 6\r\n"
@@ -756,6 +874,12 @@ BLUE_INI TEXTFILE
"ImageCount = 5\r\n"
"ImageLayout = Vertical\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 5, "
+"0, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, "
+"100, 100, 0, 100, 100, "
+"100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 0\r\n"
"[Tab.TopTabItemBothEdge]\r\n"
"SizingMargins = 2, 2, 6, 6\r\n"
@@ -765,6 +889,12 @@ BLUE_INI TEXTFILE
"ImageCount = 5\r\n"
"ImageLayout = Vertical\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 5, "
+"0, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, "
+"100, 100, 0, 100, 100, "
+"100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 0\r\n"
"[Tab.Body]\r\n"
"BgType = ImageFile\r\n"
@@ -776,6 +906,15 @@ BLUE_INI TEXTFILE
"BorderSize = 0\r\n"
"FillColor = 244 244 244\r\n"
"TextColor = 0 0 0\r\n"
+"TransitionDurations = 8, "
+"0, 100, 100, 100, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, 100, 100, 100, "
+"100, 100, 0, 100, 100, 100, 100, 100, "
+"100, 100, 100, 0, 100, 100, 100, 100, "
+"100, 100, 100, 100, 0, 100, 100, 100, "
+"100, 100, 100, 100, 100, 0, 100, 100, "
+"100, 100, 100, 100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 100, 100, 100, 0\r\n"
"[Toolbar(Pressed)]\r\n"
"TextColor = 0 0 0\r\n"
@@ -789,6 +928,15 @@ BLUE_INI TEXTFILE
"ImageCount = 6\r\n"
"SizingType = Stretch\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 8, "
+"0, 100, 100, 100, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, 100, 100, 100, "
+"100, 100, 0, 100, 100, 100, 100, 100, "
+"100, 100, 100, 0, 100, 100, 100, 100, "
+"100, 100, 100, 100, 0, 100, 100, 100, "
+"100, 100, 100, 100, 100, 0, 100, 100, "
+"100, 100, 100, 100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 100, 100, 100, 0\r\n"
"[Toolbar.Separator]\r\n"
"SizingMargins = 5, 2, 2, 1\r\n"
@@ -797,6 +945,15 @@ BLUE_INI TEXTFILE
"ImageCount = 1\r\n"
"SizingType = Tile\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 8, "
+"0, 100, 100, 100, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, 100, 100, 100, "
+"100, 100, 0, 100, 100, 100, 100, 100, "
+"100, 100, 100, 0, 100, 100, 100, 100, "
+"100, 100, 100, 100, 0, 100, 100, 100, "
+"100, 100, 100, 100, 100, 0, 100, 100, "
+"100, 100, 100, 100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 100, 100, 100, 0\r\n"
"[Toolbar.SeparatorVert]\r\n"
"SizingMargins = 2, 1, 5, 1\r\n"
@@ -805,6 +962,15 @@ BLUE_INI TEXTFILE
"ImageCount = 1\r\n"
"SizingType = Tile\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 8, "
+"0, 100, 100, 100, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, 100, 100, 100, "
+"100, 100, 0, 100, 100, 100, 100, 100, "
+"100, 100, 100, 0, 100, 100, 100, 100, "
+"100, 100, 100, 100, 0, 100, 100, 100, "
+"100, 100, 100, 100, 100, 0, 100, 100, "
+"100, 100, 100, 100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 100, 100, 100, 0\r\n"
"[Toolbar.DropdownButton]\r\n"
"SizingMargins = 4, 4, 4, 4\r\n"
@@ -815,6 +981,15 @@ BLUE_INI TEXTFILE
"ImageCount = 6\r\n"
"SizingType = Stretch\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 8, "
+"0, 100, 100, 100, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, 100, 100, 100, "
+"100, 100, 0, 100, 100, 100, 100, 100, "
+"100, 100, 100, 0, 100, 100, 100, 100, "
+"100, 100, 100, 100, 0, 100, 100, 100, "
+"100, 100, 100, 100, 100, 0, 100, 100, "
+"100, 100, 100, 100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 100, 100, 100, 0\r\n"
"[Toolbar.SplitButton]\r\n"
"SizingMargins = 3, 2, 3, 3\r\n"
@@ -824,6 +999,15 @@ BLUE_INI TEXTFILE
"ImageCount = 6\r\n"
"SizingType = Stretch\r\n"
"Transparent = True\r\n"
+"TransitionDurations = 8, "
+"0, 100, 100, 100, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, 100, 100, 100, "
+"100, 100, 0, 100, 100, 100, 100, 100, "
+"100, 100, 100, 0, 100, 100, 100, 100, "
+"100, 100, 100, 100, 0, 100, 100, 100, "
+"100, 100, 100, 100, 100, 0, 100, 100, "
+"100, 100, 100, 100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 100, 100, 100, 0\r\n"
"[Toolbar.SplitButtonDropdown]\r\n"
"SizingMargins = 1, 3, 3, 3\r\n"
@@ -836,6 +1020,15 @@ BLUE_INI TEXTFILE
"GlyphType = ImageGlyph\r\n"
"GlyphImageFile = blue_toolbar_buttons_split_dropdown_glyph.bmp\r\n"
"GlyphTransparent = True\r\n"
+"TransitionDurations = 8, "
+"0, 100, 100, 100, 100, 100, 100, 100, "
+"100, 0, 100, 100, 100, 100, 100, 100, "
+"100, 100, 0, 100, 100, 100, 100, 100, "
+"100, 100, 100, 0, 100, 100, 100, 100, "
+"100, 100, 100, 100, 0, 100, 100, 100, "
+"100, 100, 100, 100, 100, 0, 100, 100, "
+"100, 100, 100, 100, 100, 100, 0, 100, "
+"100, 100, 100, 100, 100, 100, 100, 0\r\n"
"\r\n; TrackBar\r\n"
"[TrackBar]\r\n"
diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c
index 7992911bc19..541d46deeaa 100644
--- a/dlls/uxtheme/tests/system.c
+++ b/dlls/uxtheme/tests/system.c
@@ -1293,7 +1293,6 @@ static void test_GetThemeIntList(void)
if (LOBYTE(LOWORD(GetVersion())) < 6)
ok(hr == E_PROP_ID_UNSUPPORTED, "Expected %#x, got %#x.\n", E_PROP_ID_UNSUPPORTED, hr);
else
- todo_wine
ok(hr == S_OK, "GetThemeIntList failed, hr %#x.\n", hr);
CloseThemeData(theme);
--
2.32.0
Nov. 2, 2021
[PATCH 3/6] uxtheme: Support TMT_TRANSITIONDURATIONS property.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/uxtheme/stylemap.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/uxtheme/stylemap.c b/dlls/uxtheme/stylemap.c
index a7928348304..c9a23429511 100644
--- a/dlls/uxtheme/stylemap.c
+++ b/dlls/uxtheme/stylemap.c
@@ -257,6 +257,7 @@ static const MSSTYLES_PROPERTY_MAP mapProperty[] = {
{TMT_BOOL, TMT_USERPICTURE, L"USERPICTURE"},
{TMT_RECT, TMT_DEFAULTPANESIZE, L"DEFAULTPANESIZE"},
{TMT_COLOR, TMT_BLENDCOLOR, L"BLENDCOLOR"},
+ {TMT_INTLIST, TMT_TRANSITIONDURATIONS, L"TRANSITIONDURATIONS"},
{0, 0, L""}
};
--
2.32.0
Nov. 2, 2021
[PATCH 2/6] uxtheme: Use vssym32.h instead of tmschema.h.
by Zhiyi Zhang
tmschema.h is obsolete and missing some definitions. The deleted global and menu classes are not
used anywhere and not in Windows headers.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/uxtheme/draw.c | 2 +-
dlls/uxtheme/metric.c | 2 +-
dlls/uxtheme/msstyles.c | 2 +-
dlls/uxtheme/property.c | 2 +-
dlls/uxtheme/stylemap.c | 62 ++++++-----------------------------------
dlls/uxtheme/system.c | 2 +-
include/tmschema.h | 28 -------------------
include/vsstyle.h | 7 +++++
8 files changed, 20 insertions(+), 87 deletions(-)
diff --git a/dlls/uxtheme/draw.c b/dlls/uxtheme/draw.c
index a03217b65cf..bf294ed3cc8 100644
--- a/dlls/uxtheme/draw.c
+++ b/dlls/uxtheme/draw.c
@@ -32,7 +32,7 @@
#include "commoncontrols.h"
#include "vfwmsgs.h"
#include "uxtheme.h"
-#include "tmschema.h"
+#include "vssym32.h"
#include "msstyles.h"
#include "uxthemedll.h"
diff --git a/dlls/uxtheme/metric.c b/dlls/uxtheme/metric.c
index 2d5a09d0256..b7c173740d7 100644
--- a/dlls/uxtheme/metric.c
+++ b/dlls/uxtheme/metric.c
@@ -26,7 +26,7 @@
#include "winuser.h"
#include "vfwmsgs.h"
#include "uxtheme.h"
-#include "tmschema.h"
+#include "vssym32.h"
#include "msstyles.h"
diff --git a/dlls/uxtheme/msstyles.c b/dlls/uxtheme/msstyles.c
index f129d998d65..c0f626d54aa 100644
--- a/dlls/uxtheme/msstyles.c
+++ b/dlls/uxtheme/msstyles.c
@@ -28,7 +28,7 @@
#include "winnls.h"
#include "vfwmsgs.h"
#include "uxtheme.h"
-#include "tmschema.h"
+#include "vssym32.h"
#include "msstyles.h"
diff --git a/dlls/uxtheme/property.c b/dlls/uxtheme/property.c
index 93a72ab9189..188f13836e2 100644
--- a/dlls/uxtheme/property.c
+++ b/dlls/uxtheme/property.c
@@ -26,7 +26,7 @@
#include "wingdi.h"
#include "vfwmsgs.h"
#include "uxtheme.h"
-#include "tmschema.h"
+#include "vssym32.h"
#include "msstyles.h"
diff --git a/dlls/uxtheme/stylemap.c b/dlls/uxtheme/stylemap.c
index 4fe254c1e7a..a7928348304 100644
--- a/dlls/uxtheme/stylemap.c
+++ b/dlls/uxtheme/stylemap.c
@@ -23,9 +23,10 @@
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
-#include "tmschema.h"
+#include "vssym32.h"
#define TMT_ENUM 200
+#define TMT_STOCKIMAGEFILE 3007
typedef struct _MSSTYLES_PROPERTY_MAP {
WORD dwPrimitiveType;
@@ -332,24 +333,6 @@ static const MSSTYLES_ENUM_MAP mapEnum[] = {
* Defined as PartID,StateID,TextName
* If StateID == 0 then its a part being defined
*/
-
-/* These are globals to all classes, but its treated as a separate class */
-static const MSSTYLES_CLASS_MAP classGlobals[] = {
- {GP_BORDER, 0, L"BORDER"},
- {GP_BORDER, BSS_FLAT, L"FLAT"},
- {GP_BORDER, BSS_RAISED, L"RAISED"},
- {GP_BORDER, BSS_SUNKEN, L"SUNKEN"},
- {GP_LINEHORZ, 0, L"LINEHORZ"},
- {GP_LINEHORZ, LHS_FLAT, L"FLAT"},
- {GP_LINEHORZ, LHS_RAISED, L"RAISED"},
- {GP_LINEHORZ, LHS_SUNKEN, L"SUNKEN"},
- {GP_LINEVERT, 0, L"LINEVERT"},
- {GP_LINEVERT, LVS_FLAT, L"FLAT"},
- {GP_LINEVERT, LVS_RAISED, L"RAISED"},
- {GP_LINEVERT, LVS_SUNKEN, L"SUNKEN"},
- {0, 0, L""}
-};
-
static const MSSTYLES_CLASS_MAP classButton[] = {
{BP_PUSHBUTTON, 0, L"PUSHBUTTON"},
{BP_PUSHBUTTON, PBS_NORMAL, L"NORMAL"},
@@ -488,11 +471,12 @@ static const MSSTYLES_CLASS_MAP classHeader[] = {
static const MSSTYLES_CLASS_MAP classListview[] = {
{LVP_LISTITEM, 0, L"LISTITEM"},
- {LVP_LISTITEM, LIS_NORMAL, L"NORMAL"},
- {LVP_LISTITEM, LIS_HOT, L"HOT"},
- {LVP_LISTITEM, LIS_SELECTED, L"SELECTED"},
- {LVP_LISTITEM, LIS_DISABLED, L"DISABLED"},
- {LVP_LISTITEM, LIS_SELECTEDNOTFOCUS, L"SELECTEDNOTFOCUS"},
+ {LVP_LISTITEM, LISS_NORMAL, L"NORMAL"},
+ {LVP_LISTITEM, LISS_HOT, L"HOT"},
+ {LVP_LISTITEM, LISS_SELECTED, L"SELECTED"},
+ {LVP_LISTITEM, LISS_DISABLED, L"DISABLED"},
+ {LVP_LISTITEM, LISS_SELECTEDNOTFOCUS, L"SELECTEDNOTFOCUS"},
+ {LVP_LISTITEM, LISS_HOTSELECTED, L"HOTSELECTED"},
{LVP_LISTGROUP, 0, L"LISTGROUP"},
{LVP_LISTDETAIL, 0, L"LISTDETAIL"},
{LVP_LISTSORTEDDETAIL, 0, L"LISTSORTEDDETAIL"},
@@ -500,34 +484,6 @@ static const MSSTYLES_CLASS_MAP classListview[] = {
{0, 0, L""}
};
-static const MSSTYLES_CLASS_MAP classMenu[] = {
- {MP_MENUITEM, 0, L"MENUITEM"},
- {MP_MENUITEM, MS_NORMAL, L"NORMAL"},
- {MP_MENUITEM, MS_SELECTED, L"SELECTED"},
- {MP_MENUITEM, MS_DEMOTED, L"DEMOTED"},
- {MP_MENUDROPDOWN, 0, L"MENUDROPDOWN"},
- {MP_MENUDROPDOWN, MS_NORMAL, L"NORMAL"},
- {MP_MENUDROPDOWN, MS_SELECTED, L"SELECTED"},
- {MP_MENUDROPDOWN, MS_DEMOTED, L"DEMOTED"},
- {MP_MENUBARITEM, 0, L"MENUBARITEM"},
- {MP_MENUBARITEM, MS_NORMAL, L"NORMAL"},
- {MP_MENUBARITEM, MS_SELECTED, L"SELECTED"},
- {MP_MENUBARITEM, MS_DEMOTED, L"DEMOTED"},
- {MP_MENUBARDROPDOWN, 0, L"MENUBARDROPDOWN"},
- {MP_MENUBARDROPDOWN, MS_NORMAL, L"NORMAL"},
- {MP_MENUBARDROPDOWN, MS_SELECTED, L"SELECTED"},
- {MP_MENUBARDROPDOWN, MS_DEMOTED, L"DEMOTED"},
- {MP_CHEVRON, 0, L"CHEVRON"},
- {MP_CHEVRON, MS_NORMAL, L"NORMAL"},
- {MP_CHEVRON, MS_SELECTED, L"SELECTED"},
- {MP_CHEVRON, MS_DEMOTED, L"DEMOTED"},
- {MP_SEPARATOR, 0, L"SEPARATOR"},
- {MP_SEPARATOR, MS_NORMAL, L"NORMAL"},
- {MP_SEPARATOR, MS_SELECTED, L"SELECTED"},
- {MP_SEPARATOR, MS_DEMOTED, L"DEMOTED"},
- {0, 0, L""}
-};
-
static const MSSTYLES_CLASS_MAP classMenuband[] = {
{MDP_NEWAPPBUTTON, 0, L"NEWAPPBUTTON"},
{MDP_NEWAPPBUTTON, MDS_NORMAL, L"NORMAL"},
@@ -1036,7 +992,6 @@ static const MSSTYLES_CLASS_MAP classWindow[] = {
/* Map class names to part/state maps */
static const MSSTYLES_CLASS_NAME mapClass[] = {
- {classGlobals, L"GLOBALS"},
{classButton, L"BUTTON"},
{classClock, L"CLOCK"},
{classCombobox, L"COMBOBOX"},
@@ -1044,7 +999,6 @@ static const MSSTYLES_CLASS_NAME mapClass[] = {
{classExplorerbar, L"EXPLORERBAR"},
{classHeader, L"HEADER"},
{classListview, L"LISTVIEW"},
- {classMenu, L"MENU"},
{classMenuband, L"MENUBAND"},
{classPage, L"PAGE"},
{classProgress, L"PROGRESS"},
diff --git a/dlls/uxtheme/system.c b/dlls/uxtheme/system.c
index 0298fe61d4a..ba579a02edc 100644
--- a/dlls/uxtheme/system.c
+++ b/dlls/uxtheme/system.c
@@ -28,7 +28,7 @@
#include "winreg.h"
#include "vfwmsgs.h"
#include "uxtheme.h"
-#include "tmschema.h"
+#include "vssym32.h"
#include "uxthemedll.h"
#include "msstyles.h"
diff --git a/include/tmschema.h b/include/tmschema.h
index 47eb146ebdc..81bd606d11b 100644
--- a/include/tmschema.h
+++ b/include/tmschema.h
@@ -594,34 +594,6 @@ BEGIN_TM_PART_STATES(SPECIALGROUPEXPAND)
TM_STATE(3, EBSGE, PRESSED)
END_TM_PART_STATES()
-/* GLOBALS parts */
-BEGIN_TM_CLASS_PARTS(GLOBALS)
- TM_PART(1, GP, BORDER)
- TM_PART(2, GP, LINEHORZ)
- TM_PART(3, GP, LINEVERT)
-END_TM_CLASS_PARTS()
-
-/* GLOBALS - BORDER states */
-BEGIN_TM_PART_STATES(BORDER)
- TM_STATE(1, BSS, FLAT)
- TM_STATE(2, BSS, RAISED)
- TM_STATE(3, BSS, SUNKEN)
-END_TM_PART_STATES()
-
-/* GLOBALS - LINEHORZ states */
-BEGIN_TM_PART_STATES(LINEHORZ)
- TM_STATE(1, LHS, FLAT)
- TM_STATE(2, LHS, RAISED)
- TM_STATE(3, LHS, SUNKEN)
-END_TM_PART_STATES()
-
-/* GLOBAL - LINEVERT states */
-BEGIN_TM_PART_STATES(LINEVERT)
- TM_STATE(1, LVS, FLAT)
- TM_STATE(2, LVS, RAISED)
- TM_STATE(3, LVS, SUNKEN)
-END_TM_PART_STATES()
-
/* HEADER parts */
BEGIN_TM_CLASS_PARTS(HEADER)
TM_PART(1, HP, HEADERITEM)
diff --git a/include/vsstyle.h b/include/vsstyle.h
index c5850111fb3..d6ea9071f64 100644
--- a/include/vsstyle.h
+++ b/include/vsstyle.h
@@ -1632,6 +1632,13 @@ enum MINBUTTONSTATES {
MINBS_DISABLED = 4,
};
+enum MAXBUTTONSTATES {
+ MAXBS_NORMAL = 1,
+ MAXBS_HOT = 2,
+ MAXBS_PUSHED = 3,
+ MAXBS_DISABLED = 4,
+};
+
enum RESTOREBUTTONSTATES {
RBS_NORMAL = 1,
RBS_HOT = 2,
--
2.32.0
Nov. 2, 2021
[PATCH 1/6] uxtheme/tests: Add GetThemeIntList() tests.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/uxtheme/tests/system.c | 40 ++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c
index f56c3d2c273..7992911bc19 100644
--- a/dlls/uxtheme/tests/system.c
+++ b/dlls/uxtheme/tests/system.c
@@ -28,7 +28,7 @@
#include "ddk/d3dkmthk.h"
#include "vfwmsgs.h"
#include "uxtheme.h"
-#include "vsstyle.h"
+#include "vssym32.h"
#include "msg.h"
#include "wine/test.h"
@@ -42,6 +42,7 @@ static HRESULT (WINAPI *pGetBufferedPaintBits)(HPAINTBUFFER, RGBQUAD **, int *);
static HDC (WINAPI *pGetBufferedPaintDC)(HPAINTBUFFER);
static HDC (WINAPI *pGetBufferedPaintTargetDC)(HPAINTBUFFER);
static HRESULT (WINAPI *pGetBufferedPaintTargetRect)(HPAINTBUFFER, RECT *);
+static HRESULT (WINAPI *pGetThemeIntList)(HTHEME, int, int, int, INTLIST *);
static LONG (WINAPI *pDisplayConfigGetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER *);
static LONG (WINAPI *pDisplayConfigSetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER *);
@@ -79,6 +80,7 @@ static void init_funcs(void)
GET_PROC(uxtheme, GetBufferedPaintDC)
GET_PROC(uxtheme, GetBufferedPaintTargetDC)
GET_PROC(uxtheme, GetBufferedPaintTargetRect)
+ GET_PROC(uxtheme, GetThemeIntList)
GET_PROC(uxtheme, OpenThemeDataEx)
GET_PROC(uxtheme, OpenThemeDataForDpi)
@@ -1263,6 +1265,41 @@ static void test_EnableTheming(void)
}
}
+static void test_GetThemeIntList(void)
+{
+ INTLIST intlist;
+ HTHEME theme;
+ HRESULT hr;
+ HWND hwnd;
+
+ if (!pGetThemeIntList)
+ {
+ win_skip("GetThemeIntList is unavailable.\n");
+ return;
+ }
+
+ hwnd = CreateWindowA("static", "", WS_POPUP, 0, 0, 100, 100, 0, 0, 0, NULL);
+ theme = OpenThemeData(hwnd, L"Button");
+ if (!theme)
+ {
+ skip("Theming is not active.\n");
+ DestroyWindow(hwnd);
+ return;
+ }
+
+ /* Check properties */
+ /* TMT_TRANSITIONDURATIONS is a vista+ property */
+ hr = pGetThemeIntList(theme, BP_PUSHBUTTON, PBS_NORMAL, TMT_TRANSITIONDURATIONS, &intlist);
+ if (LOBYTE(LOWORD(GetVersion())) < 6)
+ ok(hr == E_PROP_ID_UNSUPPORTED, "Expected %#x, got %#x.\n", E_PROP_ID_UNSUPPORTED, hr);
+ else
+ todo_wine
+ ok(hr == S_OK, "GetThemeIntList failed, hr %#x.\n", hr);
+
+ CloseThemeData(theme);
+ DestroyWindow(hwnd);
+}
+
START_TEST(system)
{
init_funcs();
@@ -1282,6 +1319,7 @@ START_TEST(system)
test_GetThemePartSize();
test_CloseThemeData();
test_buffered_paint();
+ test_GetThemeIntList();
/* Test EnableTheming() in the end because it may disable theming */
test_EnableTheming();
--
2.32.0
Nov. 2, 2021
Re: [PATCH v8 2/3] robocopy: Add argument parser and basic copy logic
by Zebediah Figura (she/her)
On 10/31/21 15:34, Florian Eder wrote:
> Parses path arguments as source, destination and files to include,
> reads all files in the source folder that match any of the files to include
> and copies them to the destination, creating necessary folders in the process
>
> Signed-off-by: Florian Eder <others.meder(a)gmail.com>
> ---
> v8: Made some arguments constant, added helper function to replace / remove duplicates of very long flags for PathAllocCombine and
> simplified logic in append_matching_directory_content
>
> This patch still converts both source and destination path to absolute paths, as doing otherwise would break the already existing
> support for paths > MAX_PATH. It would also not really save many LoCs / much logic, as it would still be required to make sure the
> paths both end with a backslash, to simplify the copy logic (as we then can just append the relative paths).
Right, thanks, that makes sense.
Just a few more nitpicks below...
> +struct robocopy_options options;
Missing "static".
> +static void combine_path(const WCHAR *path1, const WCHAR *path2, WCHAR **out)
> +{
> + PathAllocCombine(path1, path2,
> + PATHCCH_ALLOW_LONG_PATHS | PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS,
> + out);
> +}
You might consider making the combined path the return value. Food for
thought.
> +
> +static void append_matching_directory_content(struct list *paths, const WCHAR *search_path, const WCHAR *root, struct path_array *file_names)
"file_names" could be const. This line is also kind of long—we don't
really have a hard limit, but 120 characters is pushing it.
> +{
> + WIN32_FIND_DATAW entry_data;
> + HANDLE handle;
> + WCHAR *current_absolute_path;
> + struct path *new_path;
> +
> + handle = FindFirstFileExW(search_path, FindExInfoStandard, &entry_data, FindExSearchNameMatch, NULL, 0);
> + if (handle == INVALID_HANDLE_VALUE) return;
> + do
> + {
> + if (!wcscmp(L".", entry_data.cFileName) || !wcscmp(L"..", entry_data.cFileName)) continue;
> +
> + combine_path(root, entry_data.cFileName, ¤t_absolute_path);
> +
> + if (PathIsDirectoryW(current_absolute_path) || path_in_array(entry_data.cFileName, file_names))
> + {
> + new_path = calloc(1, sizeof(struct path));
> + new_path->name = wcsdup(entry_data.cFileName);
> + list_add_tail(paths, &new_path->entry);
> + }
> + }
> + while (FindNextFileW(handle, &entry_data));
> +}
> +
> +static void get_file_paths_in_folder(const WCHAR *root, struct list *paths)
> +{
> + struct path *new_path;
> + WCHAR *current_search_path;
> +
> + list_init(paths);
This list is initialized both here and in the caller. Not sure which
makes more sense given following patches, but once is enough ;-)
> + new_path = calloc(1, sizeof(struct path));
> + new_path->name = calloc(2, sizeof(WCHAR));
> + list_add_tail(paths, &new_path->entry);
> +
> + combine_path(root, L"*", ¤t_search_path);
> + append_matching_directory_content(paths, current_search_path, root, options.files);
> +}
Nov. 2, 2021
Re: [PATCH v8 1/3] robocopy/tests: Add basic conformance tests
by Zebediah Figura (she/her)
On 10/31/21 15:34, Florian Eder wrote:
> Basic conformance tests create test source directories with
> files and sub folders, execute robocopy on it, checking whether the resulting
> destination directory, the remaining source directory and the exit code
> is as expected
>
> Signed-off-by: Florian Eder <others.meder(a)gmail.com>
> ---
> v8: Added helper functions to check the source folder to reduce amount of
> duplicated code, use only the relative path for DeleteFileW / RemoveDirectoryW
> and used string arrays to reduce the amount of code necessary for the tests.
>
> The remaining tests that are not using an array / loop structure either break not completly identical
> with the other tests or will not be fixed with the same patch (which would in turn break the tests when
> implementing the feature, as the test would succeed for most cmd strings, but not for all).
>
> For the cmd return value, this could be fixed with a todo_wine_if and hard coding the array entries that fail,
> but then the check_*_test functions would still fail as there are also differences in the resulting files.
>
> Another solution to this problem would be to also give the id of the specific array entry that is checked
> as an argument to the check_*_test functions, so that todo_wine_if could be used, but this would
>
> a) require hardcoding array entry ids, which could easily change if tests are added from the top
> instead of the end of the array,
> b) make the tests more complex, as an additional function is linked to the content of the cmd string array,
> c) deviate even further from other tests that are (AFAIK) seen as the "gold standard".
>
> However, if you prefer this solution, feel free to tell me. :-)
>
> Also, basic_copy_tests and absolute_copy_tests could be theoretically merged, as it should not hurt to
> use the strings in basic_copy_tests as format strings for swprintf (they don't contain any format specifiers,
> causing swprintf to do nothing).
> I think it's reasonable to seperate those tests anyway, as it's not directly visible what strings are added to the
> strings otherwise (it's IMO much more clear when talking about a test for absolute paths, which requires information only
> available at runtime), but if you think otherwise, I'll change it immediately. :-)
In general I personally don't think it's worth going to extremes to
accommodate incremental removal of todo_wine. My rule of thumb is "order
the tests before the patch unless it's hard to do so".
What you have right now already looks a lot easier to parse, I think, so
it's fine as-is. What you might do to improve it even further is to do
what most other tests do and separate each test into helper functions,
e.g. test_basic_copy(), test_absolute_path(), test_wildcards().
Just a few other nitpicks below (sorry I keep missing things... the
bigger a patch is, the harder it gets to find everything the first time...)
> +static void create_test_file(const WCHAR *relative_path, size_t size)
> +{
> + HANDLE handle;
> + WCHAR path[MAX_PATH];
> + swprintf(path, ARRAY_SIZE(path), L"%s%s", temp_path, relative_path);
> + handle = CreateFileW(path, FILE_GENERIC_WRITE | FILE_GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
> + ok(handle != INVALID_HANDLE_VALUE, "creation of %s failed (0x%08x)\n", debugstr_w(path), GetLastError());
> + if (size != 0)
> + {
> + BYTE *data;
> + DWORD bytes_written;
> + data = calloc(size, sizeof(BYTE));
> + ok(WriteFile(handle, data, size, &bytes_written, NULL), "writing to %s failed (%d)\n", debugstr_w(path), GetLastError());
> + }
> + CloseHandle(handle);
> +}
> +
> +static void create_test_folder(const WCHAR *relative_path)
> +{
> + WCHAR path[MAX_PATH];
> + swprintf(path, ARRAY_SIZE(path), L"%s%s", temp_path, relative_path);
> +
> + CreateDirectoryW(path, NULL);
> +}
> +
I know I only said DeleteFile() and RemoveDirectory(), but, well, these
ones too. Most Win32 functions are capable of taking relative paths;
there's no reasons not to make use of that in places like this.
> +static void check_file(const WCHAR *relative_path, BOOL should_exist)
"relative_path" is somewhat redundant when you're not dealing with any
other kind of path anymore.
> +{
> + ok (DeleteFileW(relative_path) == should_exist, "file %s expected exist to be %d, but is %d\n", debugstr_w(relative_path), should_exist, !should_exist);
This ok message strikes me as a little more verbose than it needs to be.
I'd suggest just "DeleteFile returned %d"; you could append "expected
%d" to the end but it's pretty much implicit.
> + if (!should_exist)
> + ok(GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND,
> + "file %s DeleteFileW returned error %d, should not exist\n",
> + debugstr_w(relative_path),
> + GetLastError());
> +}
The way these lines wrap is very inconsistent. The first line in this
function is very long; the last line wraps even where not particularly
necessary.
The two ok() calls have inconsistent spacing before the parenthesis as well.
Same for check_folder() below of course.
> +
> +static void check_folder(const WCHAR *relative_path, BOOL should_exist)
> +{
> + ok (RemoveDirectoryW(relative_path) == should_exist, "folder %s expected exist to be %d, but is %d\n", debugstr_w(relative_path), should_exist, !should_exist);
> + if (!should_exist)
> + ok(GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND,
> + "folder %s RemoveDirectoryW returned error %d, should not exist\n",
> + debugstr_w(relative_path),
> + GetLastError());
> +}
> +
...
> +START_TEST(robocopy)
> +{
> + DWORD exit_code;
> + WCHAR temp_cmd[512];
> + int i;
> + static const WCHAR *invalid_syntax_tests[] =
"static const WCHAR *const invalid_syntax_tests[]" etc.
Nov. 2, 2021
[PATCH 7/7] winegstreamer: Implement IWMSyncReader::Open().
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winegstreamer/gst_private.h | 2 +
dlls/winegstreamer/wm_reader.c | 132 +++++++++++++++++++++++------
dlls/winegstreamer/wm_syncreader.c | 8 +-
dlls/wmvcore/tests/wmvcore.c | 40 +++++++++
4 files changed, 151 insertions(+), 31 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index f11543d7fb2..9674ee35052 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -139,6 +139,7 @@ struct wm_reader
QWORD start_time;
IStream *source_stream;
+ HANDLE file;
HANDLE read_thread;
bool read_thread_shutdown;
struct wg_parser *wg_parser;
@@ -167,6 +168,7 @@ struct wm_stream *wm_reader_get_stream_by_stream_number(struct wm_reader *reader
HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
INSSBuffer **sample, QWORD *pts, QWORD *duration, DWORD *flags);
void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops);
+HRESULT wm_reader_open_file(struct wm_reader *reader, const WCHAR *filename);
HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream);
void wm_reader_seek(struct wm_reader *reader, QWORD start, LONGLONG duration);
HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output,
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index bd7fcd06bd3..2f5659608a9 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -438,22 +438,34 @@ static DWORD CALLBACK read_thread(void *arg)
{
struct wm_reader *reader = arg;
IStream *stream = reader->source_stream;
+ HANDLE file = reader->file;
size_t buffer_size = 4096;
uint64_t file_size;
- STATSTG stat;
void *data;
if (!(data = malloc(buffer_size)))
return 0;
- IStream_Stat(stream, &stat, STATFLAG_NONAME);
- file_size = stat.cbSize.QuadPart;
+ if (file)
+ {
+ LARGE_INTEGER size;
+
+ GetFileSizeEx(file, &size);
+ file_size = size.QuadPart;
+ }
+ else
+ {
+ STATSTG stat;
+
+ IStream_Stat(stream, &stat, STATFLAG_NONAME);
+ file_size = stat.cbSize.QuadPart;
+ }
TRACE("Starting read thread for reader %p.\n", reader);
while (!reader->read_thread_shutdown)
{
- LARGE_INTEGER stream_offset;
+ LARGE_INTEGER large_offset;
uint64_t offset;
ULONG ret_size;
uint32_t size;
@@ -481,14 +493,32 @@ static DWORD CALLBACK read_thread(void *arg)
ret_size = 0;
- stream_offset.QuadPart = offset;
- if (SUCCEEDED(hr = IStream_Seek(stream, stream_offset, STREAM_SEEK_SET, NULL)))
- hr = IStream_Read(stream, data, size, &ret_size);
- if (FAILED(hr))
- ERR("Failed to read %u bytes at offset %I64u, hr %#x.\n", size, offset, hr);
- else if (ret_size != size)
+ large_offset.QuadPart = offset;
+ if (file)
+ {
+ if (!SetFilePointerEx(file, large_offset, NULL, FILE_BEGIN)
+ || !ReadFile(file, data, size, &ret_size, NULL))
+ {
+ ERR("Failed to read %u bytes at offset %I64u, error %u.\n", size, offset, GetLastError());
+ wg_parser_push_data(reader->wg_parser, NULL, 0);
+ continue;
+ }
+ }
+ else
+ {
+ if (SUCCEEDED(hr = IStream_Seek(stream, large_offset, STREAM_SEEK_SET, NULL)))
+ hr = IStream_Read(stream, data, size, &ret_size);
+ if (FAILED(hr))
+ {
+ ERR("Failed to read %u bytes at offset %I64u, hr %#x.\n", size, offset, hr);
+ wg_parser_push_data(reader->wg_parser, NULL, 0);
+ continue;
+ }
+ }
+
+ if (ret_size != size)
ERR("Unexpected short read: requested %u bytes, got %u.\n", size, ret_size);
- wg_parser_push_data(reader->wg_parser, SUCCEEDED(hr) ? data : NULL, ret_size);
+ wg_parser_push_data(reader->wg_parser, data, ret_size);
}
free(data);
@@ -1326,26 +1356,16 @@ static const IWMReaderTimecodeVtbl timecode_vtbl =
timecode_GetTimecodeRangeBounds,
};
-HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream)
+static HRESULT init_stream(struct wm_reader *reader, QWORD file_size)
{
struct wg_parser *wg_parser;
- STATSTG stat;
HRESULT hr;
WORD i;
- if (FAILED(hr = IStream_Stat(stream, &stat, STATFLAG_NONAME)))
- {
- ERR("Failed to stat stream, hr %#x.\n", hr);
- return hr;
- }
-
if (!(wg_parser = wg_parser_create(WG_PARSER_DECODEBIN, false)))
return E_OUTOFMEMORY;
- EnterCriticalSection(&reader->cs);
-
reader->wg_parser = wg_parser;
- IStream_AddRef(reader->source_stream = stream);
reader->read_thread_shutdown = false;
if (!(reader->read_thread = CreateThread(NULL, 0, read_thread, reader, 0, NULL)))
{
@@ -1353,7 +1373,7 @@ HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream)
goto out_destroy_parser;
}
- if (FAILED(hr = wg_parser_connect(reader->wg_parser, stat.cbSize.QuadPart)))
+ if (FAILED(hr = wg_parser_connect(reader->wg_parser, file_size)))
{
ERR("Failed to connect parser, hr %#x.\n", hr);
goto out_shutdown_thread;
@@ -1402,7 +1422,6 @@ HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream)
wg_parser_stream_seek(reader->streams[0].wg_stream, 1.0, 0, 0,
AM_SEEKING_AbsolutePositioning, AM_SEEKING_NoPositioning);
- LeaveCriticalSection(&reader->cs);
return S_OK;
out_disconnect_parser:
@@ -1417,8 +1436,60 @@ out_shutdown_thread:
out_destroy_parser:
wg_parser_destroy(reader->wg_parser);
reader->wg_parser = NULL;
- IStream_Release(reader->source_stream);
- reader->source_stream = NULL;
+
+ return hr;
+}
+
+HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream)
+{
+ STATSTG stat;
+ HRESULT hr;
+
+ if (FAILED(hr = IStream_Stat(stream, &stat, STATFLAG_NONAME)))
+ {
+ ERR("Failed to stat stream, hr %#x.\n", hr);
+ return hr;
+ }
+
+ EnterCriticalSection(&reader->cs);
+
+ IStream_AddRef(reader->source_stream = stream);
+ if (FAILED(hr = init_stream(reader, stat.cbSize.QuadPart)))
+ {
+ IStream_Release(stream);
+ reader->source_stream = NULL;
+ }
+
+ LeaveCriticalSection(&reader->cs);
+ return hr;
+}
+
+HRESULT wm_reader_open_file(struct wm_reader *reader, const WCHAR *filename)
+{
+ LARGE_INTEGER size;
+ HANDLE file;
+ HRESULT hr;
+
+ if ((file = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
+ {
+ ERR("Failed to open %s, error %u.\n", debugstr_w(filename), GetLastError());
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ if (!GetFileSizeEx(file, &size))
+ {
+ ERR("Failed to get the size of %s, error %u.\n", debugstr_w(filename), GetLastError());
+ CloseHandle(file);
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ EnterCriticalSection(&reader->cs);
+
+ reader->file = file;
+
+ if (FAILED(hr = init_stream(reader, size.QuadPart)))
+ reader->file = NULL;
LeaveCriticalSection(&reader->cs);
return hr;
@@ -1428,7 +1499,7 @@ HRESULT wm_reader_close(struct wm_reader *reader)
{
EnterCriticalSection(&reader->cs);
- if (!reader->source_stream)
+ if (!reader->wg_parser)
{
LeaveCriticalSection(&reader->cs);
return NS_E_INVALID_REQUEST;
@@ -1443,8 +1514,13 @@ HRESULT wm_reader_close(struct wm_reader *reader)
wg_parser_destroy(reader->wg_parser);
reader->wg_parser = NULL;
- IStream_Release(reader->source_stream);
+
+ if (reader->source_stream)
+ IStream_Release(reader->source_stream);
reader->source_stream = NULL;
+ if (reader->file)
+ CloseHandle(reader->file);
+ reader->file = NULL;
LeaveCriticalSection(&reader->cs);
return S_OK;
diff --git a/dlls/winegstreamer/wm_syncreader.c b/dlls/winegstreamer/wm_syncreader.c
index 2c65f652cdb..fff048df06e 100644
--- a/dlls/winegstreamer/wm_syncreader.c
+++ b/dlls/winegstreamer/wm_syncreader.c
@@ -226,9 +226,11 @@ static HRESULT WINAPI WMSyncReader_GetStreamSelected(IWMSyncReader2 *iface, WORD
static HRESULT WINAPI WMSyncReader_Open(IWMSyncReader2 *iface, const WCHAR *filename)
{
- struct sync_reader *This = impl_from_IWMSyncReader2(iface);
- FIXME("(%p)->(%s): stub!\n", This, debugstr_w(filename));
- return E_NOTIMPL;
+ struct sync_reader *reader = impl_from_IWMSyncReader2(iface);
+
+ TRACE("reader %p, filename %s.\n", reader, debugstr_w(filename));
+
+ return wm_reader_open_file(&reader->reader, filename);
}
static HRESULT WINAPI WMSyncReader_OpenStream(IWMSyncReader2 *iface, IStream *stream)
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index 92208c0b8a3..eae320c4d2e 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -1012,6 +1012,45 @@ static void test_sync_reader_types(void)
ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(filename), GetLastError());
}
+static void test_sync_reader_file(void)
+{
+ const WCHAR *filename = load_resource(L"test.wmv");
+ IWMSyncReader *reader;
+ IWMProfile *profile;
+ DWORD count;
+ HRESULT hr;
+ ULONG ref;
+ BOOL ret;
+
+ hr = WMCreateSyncReader(NULL, 0, &reader);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ IWMSyncReader_QueryInterface(reader, &IID_IWMProfile, (void **)&profile);
+
+ hr = IWMSyncReader_Open(reader, filename);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ count = 0xdeadbeef;
+ hr = IWMSyncReader_GetOutputCount(reader, &count);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(count == 2, "Got count %u.\n", count);
+
+ hr = IWMSyncReader_Close(reader);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IWMSyncReader_Close(reader);
+ ok(hr == NS_E_INVALID_REQUEST, "Got hr %#x.\n", hr);
+
+ hr = IWMSyncReader_Open(reader, filename);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IWMProfile_Release(profile);
+ ref = IWMSyncReader_Release(reader);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ ret = DeleteFileW(filename);
+ ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(filename), GetLastError());
+}
+
START_TEST(wmvcore)
{
HRESULT hr;
@@ -1030,6 +1069,7 @@ START_TEST(wmvcore)
test_iscontentprotected();
test_sync_reader_streaming();
test_sync_reader_types();
+ test_sync_reader_file();
CoUninitialize();
}
--
2.33.0
Nov. 2, 2021
[PATCH 6/7] winegstreamer: Implement IWMHeaderInfo::GetAttributeByName(L"Seekable").
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winegstreamer/wm_reader.c | 21 +++++++++++++++++++++
dlls/wmvcore/tests/wmvcore.c | 22 ++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index 80393d4e7a1..bd7fcd06bd3 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -910,6 +910,27 @@ static HRESULT WINAPI header_info_GetAttributeByName(IWMHeaderInfo3 *iface, WORD
memcpy(value, &duration, sizeof(QWORD));
return S_OK;
}
+ else if (!wcscmp(name, L"Seekable"))
+ {
+ if (*stream_number)
+ {
+ WARN("Requesting duration for stream %u, returning ASF_E_NOTFOUND.\n", *stream_number);
+ return ASF_E_NOTFOUND;
+ }
+
+ *size = sizeof(BOOL);
+ if (!value)
+ {
+ *type = WMT_TYPE_BOOL;
+ return S_OK;
+ }
+ if (req_size < *size)
+ return ASF_E_BUFFERTOOSMALL;
+
+ *type = WMT_TYPE_BOOL;
+ *(BOOL *)value = TRUE;
+ return S_OK;
+ }
else
{
FIXME("Unknown attribute %s.\n", debugstr_w(name));
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index 6d510553fef..92208c0b8a3 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -468,6 +468,17 @@ static void test_reader_attributes(IWMProfile *profile)
ok(ret_stream_number == stream_number, "Expected stream number %u, got %u.\n",
stream_number, ret_stream_number);
+ size = sizeof(DWORD);
+ type = 0xdeadbeef;
+ dword = 0xdeadbeef;
+ hr = IWMHeaderInfo_GetAttributeByName(header_info, &ret_stream_number,
+ L"Seekable", &type, (BYTE *)&dword, &size);
+ ok(hr == ASF_E_NOTFOUND, "Got hr %#x.\n", hr);
+ ok(type == 0xdeadbeef, "Got type %#x.\n", type);
+ ok(size == sizeof(DWORD), "Got size %u.\n", size);
+ ok(ret_stream_number == stream_number, "Expected stream number %u, got %u.\n",
+ stream_number, ret_stream_number);
+
IWMStreamConfig_Release(config);
}
@@ -546,6 +557,17 @@ static void test_reader_attributes(IWMProfile *profile)
ok(size == sizeof(QWORD), "Got size %u.\n", size);
ok(stream_number == 0, "Got stream number %u.\n", stream_number);
+ size = sizeof(DWORD);
+ type = 0xdeadbeef;
+ dword = 0xdeadbeef;
+ hr = IWMHeaderInfo_GetAttributeByName(header_info, &stream_number,
+ L"Seekable", &type, (BYTE *)&dword, &size);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(type == WMT_TYPE_BOOL, "Got type %#x.\n", type);
+ ok(size == sizeof(DWORD), "Got size %u.\n", size);
+ ok(dword == TRUE, "Got duration %I64u.\n", duration);
+ ok(stream_number == 0, "Got stream number %u.\n", stream_number);
+
IWMHeaderInfo_Release(header_info);
}
--
2.33.0
Nov. 2, 2021
[PATCH 5/7] winegstreamer: Implement IWMHeaderInfo::GetAttributeByName(L"Duration").
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winegstreamer/wm_reader.c | 44 ++++++++++-
dlls/wmvcore/tests/wmvcore.c | 131 +++++++++++++++++++++++++++++++++
2 files changed, 172 insertions(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index 1d46db3fb0d..80393d4e7a1 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -874,9 +874,47 @@ static HRESULT WINAPI header_info_GetAttributeByIndex(IWMHeaderInfo3 *iface, WOR
static HRESULT WINAPI header_info_GetAttributeByName(IWMHeaderInfo3 *iface, WORD *stream_number,
const WCHAR *name, WMT_ATTR_DATATYPE *type, BYTE *value, WORD *size)
{
- FIXME("iface %p, stream_number %p, name %s, type %p, value %p, size %p, stub!\n",
- iface, stream_number, debugstr_w(name), type, value, size);
- return E_NOTIMPL;
+ struct wm_reader *reader = impl_from_IWMHeaderInfo3(iface);
+ const WORD req_size = *size;
+
+ TRACE("reader %p, stream_number %p, name %s, type %p, value %p, size %u.\n",
+ reader, stream_number, debugstr_w(name), type, value, *size);
+
+ if (!stream_number)
+ return E_INVALIDARG;
+
+ if (!wcscmp(name, L"Duration"))
+ {
+ QWORD duration;
+
+ if (*stream_number)
+ {
+ WARN("Requesting duration for stream %u, returning ASF_E_NOTFOUND.\n", *stream_number);
+ return ASF_E_NOTFOUND;
+ }
+
+ *size = sizeof(QWORD);
+ if (!value)
+ {
+ *type = WMT_TYPE_QWORD;
+ return S_OK;
+ }
+ if (req_size < *size)
+ return ASF_E_BUFFERTOOSMALL;
+
+ *type = WMT_TYPE_QWORD;
+ EnterCriticalSection(&reader->cs);
+ duration = wg_parser_stream_get_duration(wg_parser_get_stream(reader->wg_parser, 0));
+ LeaveCriticalSection(&reader->cs);
+ TRACE("Returning duration %s.\n", debugstr_time(duration));
+ memcpy(value, &duration, sizeof(QWORD));
+ return S_OK;
+ }
+ else
+ {
+ FIXME("Unknown attribute %s.\n", debugstr_w(name));
+ return ASF_E_NOTFOUND;
+ }
}
static HRESULT WINAPI header_info_SetAttribute(IWMHeaderInfo3 *iface, WORD stream_number,
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index bc7d044b39b..6d510553fef 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -420,6 +420,135 @@ static const IStreamVtbl stream_vtbl =
stream_Clone,
};
+static void test_reader_attributes(IWMProfile *profile)
+{
+ WORD size, stream_number, ret_stream_number;
+ IWMHeaderInfo *header_info;
+ IWMStreamConfig *config;
+ WMT_ATTR_DATATYPE type;
+ ULONG count, i;
+ QWORD duration;
+ DWORD dword;
+ HRESULT hr;
+
+ IWMProfile_QueryInterface(profile, &IID_IWMHeaderInfo, (void **)&header_info);
+
+ hr = IWMProfile_GetStreamCount(profile, &count);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(count == 2, "Got count %u.\n", count);
+
+ for (i = 0; i < count; ++i)
+ {
+ hr = IWMProfile_GetStream(profile, i, &config);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IWMStreamConfig_GetStreamNumber(config, &stream_number);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret_stream_number = stream_number;
+
+ size = sizeof(DWORD);
+ type = 0xdeadbeef;
+ dword = 0xdeadbeef;
+ hr = IWMHeaderInfo_GetAttributeByName(header_info, &ret_stream_number,
+ L"WM/VideoFrameRate", &type, (BYTE *)&dword, &size);
+ ok(hr == ASF_E_NOTFOUND, "Got hr %#x.\n", hr);
+ ok(type == 0xdeadbeef, "Got type %#x.\n", type);
+ ok(size == sizeof(DWORD), "Got size %u.\n", size);
+ ok(dword == 0xdeadbeef, "Got frame rate %u.\n", dword);
+ ok(ret_stream_number == stream_number, "Expected stream number %u, got %u.\n",
+ stream_number, ret_stream_number);
+
+ size = sizeof(QWORD);
+ type = 0xdeadbeef;
+ duration = 0xdeadbeef;
+ hr = IWMHeaderInfo_GetAttributeByName(header_info, &ret_stream_number,
+ L"Duration", &type, (BYTE *)&duration, &size);
+ ok(hr == ASF_E_NOTFOUND, "Got hr %#x.\n", hr);
+ ok(type == 0xdeadbeef, "Got type %#x.\n", type);
+ ok(size == sizeof(QWORD), "Got size %u.\n", size);
+ ok(ret_stream_number == stream_number, "Expected stream number %u, got %u.\n",
+ stream_number, ret_stream_number);
+
+ IWMStreamConfig_Release(config);
+ }
+
+ /* WM/VideoFrameRate with a NULL stream number. */
+
+ size = sizeof(DWORD);
+ type = 0xdeadbeef;
+ dword = 0xdeadbeef;
+ hr = IWMHeaderInfo_GetAttributeByName(header_info, NULL,
+ L"WM/VideoFrameRate", &type, (BYTE *)&dword, &size);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ ok(type == 0xdeadbeef, "Got type %#x.\n", type);
+ ok(size == sizeof(DWORD), "Got size %u.\n", size);
+ ok(dword == 0xdeadbeef, "Got frame rate %u.\n", dword);
+
+ /* And with a zero stream number. */
+
+ stream_number = 0;
+ size = sizeof(DWORD);
+ type = 0xdeadbeef;
+ dword = 0xdeadbeef;
+ hr = IWMHeaderInfo_GetAttributeByName(header_info, &stream_number,
+ L"WM/VideoFrameRate", &type, (BYTE *)&dword, &size);
+ ok(hr == ASF_E_NOTFOUND, "Got hr %#x.\n", hr);
+ ok(type == 0xdeadbeef, "Got type %#x.\n", type);
+ ok(size == sizeof(DWORD), "Got size %u.\n", size);
+ ok(dword == 0xdeadbeef, "Got frame rate %u.\n", dword);
+ ok(stream_number == 0, "Got stream number %u.\n", stream_number);
+
+ /* Duration with a NULL stream number. */
+
+ size = sizeof(QWORD);
+ type = 0xdeadbeef;
+ duration = 0xdeadbeef;
+ hr = IWMHeaderInfo_GetAttributeByName(header_info, NULL,
+ L"Duration", &type, (BYTE *)&duration, &size);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ ok(type == 0xdeadbeef, "Got type %#x.\n", type);
+ ok(size == sizeof(QWORD), "Got size %u.\n", size);
+ ok(duration == 0xdeadbeef, "Got duration %I64u.\n", duration);
+
+ /* And with a zero stream number. */
+
+ size = sizeof(QWORD);
+ type = 0xdeadbeef;
+ duration = 0xdeadbeef;
+ hr = IWMHeaderInfo_GetAttributeByName(header_info, &stream_number,
+ L"Duration", &type, (BYTE *)&duration, &size);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(type == WMT_TYPE_QWORD, "Got type %#x.\n", type);
+ ok(size == sizeof(QWORD), "Got size %u.\n", size);
+ ok(duration == 20460000, "Got duration %I64u.\n", duration);
+ ok(stream_number == 0, "Got stream number %u.\n", stream_number);
+
+ /* Pass a too-small size. */
+
+ size = sizeof(QWORD) - 1;
+ type = 0xdeadbeef;
+ duration = 0xdeadbeef;
+ hr = IWMHeaderInfo_GetAttributeByName(header_info, &stream_number,
+ L"Duration", &type, (BYTE *)&duration, &size);
+ ok(hr == ASF_E_BUFFERTOOSMALL, "Got hr %#x.\n", hr);
+ ok(type == 0xdeadbeef, "Got type %#x.\n", type);
+ ok(size == sizeof(QWORD), "Got size %u.\n", size);
+ ok(duration == 0xdeadbeef, "Got duration %I64u.\n", duration);
+ ok(stream_number == 0, "Got stream number %u.\n", stream_number);
+
+ /* Pass a NULL buffer. */
+
+ size = 0xdead;
+ type = 0xdeadbeef;
+ hr = IWMHeaderInfo_GetAttributeByName(header_info, &stream_number,
+ L"Duration", &type, NULL, &size);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(type == WMT_TYPE_QWORD, "Got type %#x.\n", type);
+ ok(size == sizeof(QWORD), "Got size %u.\n", size);
+ ok(stream_number == 0, "Got stream number %u.\n", stream_number);
+
+ IWMHeaderInfo_Release(header_info);
+}
+
static void test_sync_reader_streaming(void)
{
DWORD size, flags, output_number, expect_output_number;
@@ -596,6 +725,8 @@ static void test_sync_reader_streaming(void)
&pts, &duration, &flags, NULL, NULL);
ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
+ test_reader_attributes(profile);
+
hr = IWMSyncReader_Close(reader);
ok(hr == S_OK, "Got hr %#x.\n", hr);
--
2.33.0
Nov. 2, 2021
[PATCH 4/7] winegstreamer: Return S_OK from IWMSyncReader::SetOutputSetting(L"VideoSampleDurations").
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winegstreamer/wm_syncreader.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/dlls/winegstreamer/wm_syncreader.c b/dlls/winegstreamer/wm_syncreader.c
index 1f5827cf244..2c65f652cdb 100644
--- a/dlls/winegstreamer/wm_syncreader.c
+++ b/dlls/winegstreamer/wm_syncreader.c
@@ -249,12 +249,24 @@ static HRESULT WINAPI WMSyncReader_SetOutputProps(IWMSyncReader2 *iface, DWORD o
return wm_reader_set_output_props(&reader->reader, output, props);
}
-static HRESULT WINAPI WMSyncReader_SetOutputSetting(IWMSyncReader2 *iface, DWORD output_num, const WCHAR *name,
- WMT_ATTR_DATATYPE type, const BYTE *value, WORD length)
+static HRESULT WINAPI WMSyncReader_SetOutputSetting(IWMSyncReader2 *iface, DWORD output,
+ const WCHAR *name, WMT_ATTR_DATATYPE type, const BYTE *value, WORD size)
{
- struct sync_reader *This = impl_from_IWMSyncReader2(iface);
- FIXME("(%p)->(%d %s %d %p %d): stub!\n", This, output_num, debugstr_w(name), type, value, length);
- return E_NOTIMPL;
+ struct sync_reader *reader = impl_from_IWMSyncReader2(iface);
+
+ TRACE("reader %p, output %u, name %s, type %#x, value %p, size %u.\n",
+ reader, output, debugstr_w(name), type, value, size);
+
+ if (!wcscmp(name, L"VideoSampleDurations"))
+ {
+ FIXME("Ignoring VideoSampleDurations setting.\n");
+ return S_OK;
+ }
+ else
+ {
+ FIXME("Unknown setting %s; returning E_NOTIMPL.\n", debugstr_w(name));
+ return E_NOTIMPL;
+ }
}
static HRESULT WINAPI WMSyncReader_SetRange(IWMSyncReader2 *iface, QWORD start, LONGLONG duration)
--
2.33.0
Nov. 2, 2021