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
June 2018
- 68 participants
- 1149 messages
[PATCH 2/7] testbot/web: Let LogUtils build the list of task reports and logs.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/WineTestBot/LogUtils.pm | 55 ++++++++++++++++++++++++++++-
testbot/web/JobDetails.pl | 20 ++++-------
2 files changed, 60 insertions(+), 15 deletions(-)
diff --git a/testbot/lib/WineTestBot/LogUtils.pm b/testbot/lib/WineTestBot/LogUtils.pm
index daa9c0bd8..3dfd7c5e7 100644
--- a/testbot/lib/WineTestBot/LogUtils.pm
+++ b/testbot/lib/WineTestBot/LogUtils.pm
@@ -27,7 +27,7 @@ WineTestBot::LogUtils - Provides functions to parse task logs
use Exporter 'import';
-our @EXPORT = qw(GetLogLineCategory ParseTaskLog);
+our @EXPORT = qw(GetLogFileNames GetLogLabel GetLogLineCategory ParseTaskLog);
#
@@ -133,4 +133,57 @@ sub GetLogLineCategory($)
return "none";
}
+=pod
+=over 12
+
+=item C<GetLogFileNames()>
+
+Scans the directory for test reports and task logs and returns their filenames.
+The filenames are returned in the order in which the logs are meant to be
+presented.
+
+=back
+=cut
+
+sub GetLogFileNames($;$)
+{
+ my ($Dir, $IncludeOld) = @_;
+
+ my @Candidates = ("exe32.report", "exe64.report",
+ "log", "err");
+ push @Candidates, "log.old", "err.old" if ($IncludeOld);
+
+ my @Logs;
+ foreach my $FileName (@Candidates)
+ {
+ push @Logs, $FileName if (-f "$Dir/$FileName" and !-z "$Dir/$FileName");
+ }
+ return \@Logs;
+}
+
+my %_LogFileLabels = (
+ "exe32.report" => "32 bit Windows report",
+ "exe64.report" => "64 bit Windows report",
+ "err" => "task errors",
+ "log" => "task log",
+ "err.old" => "old task errors",
+ "log.old" => "old logs",
+);
+
+=pod
+=over 12
+
+=item C<GetLogLabel()>
+
+Returns a user-friendly description of the content of the specified log file.
+
+=back
+=cut
+
+sub GetLogLabel($)
+{
+ my ($LogFileName) = @_;
+ return $_LogFileLabels{$LogFileName};
+}
+
1;
diff --git a/testbot/web/JobDetails.pl b/testbot/web/JobDetails.pl
index 07924f4e6..e5f792929 100644
--- a/testbot/web/JobDetails.pl
+++ b/testbot/web/JobDetails.pl
@@ -261,14 +261,6 @@ sub GetHtmlLine($$$)
return $Html;
}
-my @MILogFiles = qw(exe32.report exe64.report log log.old);
-my %MILogLabels = (
- "exe32.report" => "32 bit Windows report",
- "exe64.report" => "64 bit Windows report",
- "log" => "task log",
- "log.old" => "old logs",
-);
-
sub InitMoreInfo($)
{
my ($self) = @_;
@@ -282,15 +274,15 @@ sub InitMoreInfo($)
my $Value = $self->GetParam("f$Key");
my $TaskDir = $StepTask->GetTaskDir();
- foreach my $Log (@MILogFiles)
+ foreach my $Log (@{GetLogFileNames($TaskDir, 1)})
{
- if (!-f "$TaskDir/$Log" or -z "$TaskDir/$Log")
+ if ($Log =~ s/^err/log/)
{
- my $Err = $Log;
- next if ($Err !~ s/^log/err/ or !-f "$TaskDir/$Err" or -z "$TaskDir/$Err");
+ # We don't want separate entries for log* and err* but we also want a
+ # log* entry even if only err* exists.
+ next if (($More->{$Key}->{Logs}->[-1] || "") eq $Log);
}
push @{$More->{$Key}->{Logs}}, $Log;
-
$More->{$Key}->{Full} = $Log if (uri_escape($Log) eq $Value);
}
$More->{$Key}->{Full} ||= "";
@@ -385,7 +377,7 @@ sub GenerateBody($)
foreach my $Log (@{$MoreInfo->{Logs}})
{
- $self->GenerateMoreInfoLink($Key, $MILogLabels{$Log}, "Full", $Log);
+ $self->GenerateMoreInfoLink($Key, GetLogLabel($Log), "Full", $Log);
}
print "</div>\n";
--
2.18.0
June 26, 2018
[PATCH 1/7] testbot: Move log line categorization to LogUtils and simplify line highlighting.
by Francois Gouget
GetLogLineCategory() identifies log lines of interest which makes it
possible to decide how to display them.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
This makes it reusable in WineSendLog.pl.
testbot/lib/WineTestBot/LogUtils.pm | 61 +++++++++++++++++++++-
testbot/web/JobDetails.pl | 78 +++++++++++------------------
2 files changed, 88 insertions(+), 51 deletions(-)
diff --git a/testbot/lib/WineTestBot/LogUtils.pm b/testbot/lib/WineTestBot/LogUtils.pm
index 3e40fbc35..daa9c0bd8 100644
--- a/testbot/lib/WineTestBot/LogUtils.pm
+++ b/testbot/lib/WineTestBot/LogUtils.pm
@@ -27,7 +27,7 @@ WineTestBot::LogUtils - Provides functions to parse task logs
use Exporter 'import';
-our @EXPORT = qw(ParseTaskLog);
+our @EXPORT = qw(GetLogLineCategory ParseTaskLog);
#
@@ -74,4 +74,63 @@ sub ParseTaskLog($$)
return "nolog:Unable to open the task log for reading: $!";
}
+
+#
+# Log querying and formatting
+#
+
+=pod
+=over 12
+
+=item C<GetLogLineCategory()>
+
+Identifies the category of the given log line: an error message, a todo, just
+an informational message or none of these. The category can then be used to
+decide whether to hide the line or, on the contrary, highlight it.
+
+=back
+=cut
+
+sub GetLogLineCategory($)
+{
+ my ($Line) = @_;
+
+ if ($Line =~ /: Test marked todo: /)
+ {
+ return "todo";
+ }
+ if ($Line =~ /: Tests skipped: / or
+ $Line =~ /^\w+:\w+ skipped /)
+ {
+ return "skip";
+ }
+ if ($Line =~ /: Test (?:failed|succeeded inside todo block): / or
+ $Line =~ /Fatal: test .* does not exist/ or
+ $Line =~ / done \(258\)/ or
+ $Line =~ /: unhandled exception [0-9a-fA-F]{8} at / or
+ $Line =~ /^Unhandled exception: / or
+ # Git errors
+ $Line =~ /^CONFLICT / or
+ $Line =~ /^error: patch failed:/ or
+ $Line =~ /^error: corrupt patch / or
+ # Build errors
+ $Line =~ /: error: / or
+ $Line =~ /^Makefile:[0-9]+: recipe for target .* failed$/ or
+ $Line =~ /^(?:Build|Reconfig|Task): (?!ok)/ or
+ # Typical perl errors
+ $Line =~ /^Use of uninitialized value/)
+ {
+ return "error";
+ }
+ if ($Line =~ /^\+ \S/ or
+ $Line =~ /^\w+:\w+ start / or
+ # Build messages
+ $Line =~ /^(?:Build|Reconfig|Task): ok/)
+ {
+ return "info";
+ }
+
+ return "none";
+}
+
1;
diff --git a/testbot/web/JobDetails.pl b/testbot/web/JobDetails.pl
index f05c0f62e..07924f4e6 100644
--- a/testbot/web/JobDetails.pl
+++ b/testbot/web/JobDetails.pl
@@ -28,6 +28,7 @@ use URI::Escape;
use WineTestBot::Config;
use WineTestBot::Jobs;
+use WineTestBot::LogUtils;
use WineTestBot::StepsTasks;
use WineTestBot::Engine::Notify;
@@ -228,59 +229,36 @@ sub GeneratePage($)
$self->SUPER::GeneratePage();
}
+=pod
+=over 12
+
+=item C<GetHtmlLine()>
+
+Determines if the log line should be shown, how, and escapes it so it is valid
+HTML.
+
+When not showing the full log, returns undef except for error messages which
+are the only lines tha should be shown.
+When showing the full log error messages and other lines of interest are
+highlighted to make the log more readable.
+
+=back
+=cut
+
sub GetHtmlLine($$$)
{
my ($self, $FullLog, $Line) = @_;
- $Line = $self->escapeHTML($Line);
- if ($Line =~ /: Test marked todo: /)
- {
- return (undef, $Line) if (!$FullLog);
- my $Html = $Line;
- $Html =~ s~^(.*\S)\s*\r?$~<span class='log-todo'>$1</span>~;
- return ($Html, $Line);
- }
- if ($Line =~ /: Tests skipped: / or
- $Line =~ /^\w+:\w+ skipped /)
- {
- return (undef, $Line) if (!$FullLog);
- my $Html = $Line;
- $Html =~ s~^(.*\S)\s*\r?$~<span class='log-skip'>$1</span>~;
- return ($Html, $Line);
- }
- if ($Line =~ /: Test (?:failed|succeeded inside todo block): / or
- $Line =~ /Fatal: test .* does not exist/ or
- $Line =~ / done \(258\)/ or
- $Line =~ /: unhandled exception [0-9a-fA-F]{8} at / or
- $Line =~ /^Unhandled exception: / or
- # Git errors
- $Line =~ /^CONFLICT / or
- $Line =~ /^error: patch failed:/ or
- $Line =~ /^error: corrupt patch / or
- # Build errors
- $Line =~ /: error: / or
- $Line =~ /^Makefile:[0-9]+: recipe for target .* failed$/ or
- $Line =~ /^(?:Build|Reconfig|Task): (?!ok)/ or
- # Typical perl errors
- $Line =~ /^Use of uninitialized value/)
- {
- return ($Line, $Line) if (!$FullLog);
- my $Html = $Line;
- $Html =~ s~^(.*\S)\s*\r?$~<span class='log-error'>$1</span>~;
- return ($Html, $Line);
- }
- if ($FullLog &&
- ($Line =~ /^\+ \S/ or
- $Line =~ /^\w+:\w+ start / or
- # Build messages
- $Line =~ /^(?:Build|Reconfig|Task): ok/))
+ my $Category = GetLogLineCategory($Line);
+ return undef if ($Category ne "error" and !$FullLog);
+
+ my $Html = $self->escapeHTML($Line);
+ if ($FullLog and $Category ne "none")
{
- my $Html = $Line;
- $Html =~ s~^(.*\S)\s*\r?$~<span class='log-info'>$1</span>~;
- return ($Html, $Line);
+ # Highlight all line categories in the full log
+ $Html =~ s~^(.*\S)\s*\r?$~<span class='log-$Category'>$1</span>~;
}
-
- return (undef, $Line);
+ return $Html;
}
my @MILogFiles = qw(exe32.report exe64.report log log.old);
@@ -429,8 +407,8 @@ sub GenerateBody($)
{
$CurrentDll = $1;
}
- my ($Highlight, $Plain) = $self->GetHtmlLine($MoreInfo->{Full}, $Line);
- next if (!$MoreInfo->{Full} and !defined $Highlight);
+ my $Html = $self->GetHtmlLine($MoreInfo->{Full}, $Line);
+ next if (!defined $Html);
if ($PrintedDll ne $CurrentDll && !$MoreInfo->{Full})
{
@@ -451,7 +429,7 @@ sub GenerateBody($)
}
else
{
- print(($Highlight || $Plain), "\n");
+ print "$Html\n";
}
}
close($LogFile);
--
2.18.0
June 26, 2018
Re: [PATCH 2/2] msvcp120: Add test for Concurrent_vector_grow_to_at_least_with_result.
by Piotr Caban
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
June 26, 2018
Re: [PATCH 1/2] msvcp120: Add test for Concurrent_vector_grow_by.
by Piotr Caban
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
June 26, 2018
[PATCH 2/2] msvcp120: Add test for Concurrent_vector_grow_to_at_least_with_result.
by Hua Meng
Signed-off-by: Hua meng <161220092(a)smail.nju.edu.cn>
---
dlls/msvcp120/tests/msvcp120.c | 46 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/dlls/msvcp120/tests/msvcp120.c b/dlls/msvcp120/tests/msvcp120.c
index b5e470cba3..2974482ec1 100644
--- a/dlls/msvcp120/tests/msvcp120.c
+++ b/dlls/msvcp120/tests/msvcp120.c
@@ -420,6 +420,8 @@ static void* (__thiscall *p_vector_base_v4__Internal_compact)(
void (__cdecl*)(void*, const void*, size_t));
static size_t (__thiscall *p_vector_base_v4__Internal_grow_by)(
vector_base_v4*, size_t, size_t, void (__cdecl*)(void*, const void*, size_t), const void *);
+static size_t (__thiscall *p_vector_base_v4__Internal_grow_to_at_least_with_result)(
+ vector_base_v4*, size_t, size_t, void (__cdecl*)(void*, const void*, size_t), const void *);
static HMODULE msvcp;
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
@@ -572,6 +574,8 @@ static BOOL init(void)
"?_Internal_compact(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IEAAPEAX_KPEAXP6AX10(a)ZP6AX1PEBX0@Z(a)Z");
SET(p_vector_base_v4__Internal_grow_by,
"?_Internal_grow_by(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IEAA_K_K0P6AXPEAXPEBX0(a)Z2@Z");
+ SET(p_vector_base_v4__Internal_grow_to_at_least_with_result,
+ "?_Internal_grow_to_at_least_with_result(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IEAA_K_K0P6AXPEAXPEBX0(a)Z2@Z");
} else {
SET(p_tr2_sys__File_size,
"?_File_size(a)sys@tr2(a)std@@YA_KPBD(a)Z");
@@ -693,6 +697,8 @@ static BOOL init(void)
"?_Internal_compact(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAEPAXIPAXP6AX0I(a)ZP6AX0PBXI@Z(a)Z");
SET(p_vector_base_v4__Internal_grow_by,
"?_Internal_grow_by(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAEIIIP6AXPAXPBXI(a)Z1@Z");
+ SET(p_vector_base_v4__Internal_grow_to_at_least_with_result,
+ "?_Internal_grow_to_at_least_with_result(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAEIIIP6AXPAXPBXI(a)Z1@Z");
#else
SET(p__Thrd_current,
"_Thrd_current");
@@ -742,6 +748,8 @@ static BOOL init(void)
"?_Internal_compact(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAAPAXIPAXP6AX0I(a)ZP6AX0PBXI@Z(a)Z");
SET(p_vector_base_v4__Internal_grow_by,
"?_Internal_grow_by(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAAIIIP6AXPAXPBXI(a)Z1@Z");
+ SET(p_vector_base_v4__Internal_grow_to_at_least_with_result,
+ "?_Internal_grow_to_at_least_with_result(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAAIIIP6AXPAXPBXI(a)Z1@Z");
#endif
}
SET(p__Thrd_equal,
@@ -3036,6 +3044,44 @@ static void test_vector_base_v4(void)
CHECK_CALLED(concurrent_vector_int_destroy);
concurrent_vector_int_dtor(&v2);
+ /* test for Internal_grow_to_at_least_with_result */
+ concurrent_vector_int_ctor(&v2);
+ SET_EXPECT(concurrent_vector_int_alloc);
+ data = call_func3(p_vector_base_v4__Internal_push_back, &v2, sizeof(int), &idx);
+ CHECK_CALLED(concurrent_vector_int_alloc);
+ ok(data != NULL, "_Internal_push_back returned NULL\n");
+ data = call_func3(p_vector_base_v4__Internal_push_back, &v2, sizeof(int), &idx);
+ ok(data != NULL, "_Internal_push_back returned NULL\n");
+ vector_elem_count += 2;
+ ok(v2.first_block == 1, "v2.first_block got %ld expected 1\n", (long)v2.first_block);
+ ok(v2.early_size == 2, "v2.early_size got %ld expected 2\n", (long)v2.early_size);
+ i = 0;
+ SET_EXPECT(concurrent_vector_int_alloc);
+ SET_EXPECT(concurrent_vector_int_copy);
+ idx = (size_t)call_func5(p_vector_base_v4__Internal_grow_to_at_least_with_result,
+ &v2, 3, sizeof(int), concurrent_vector_int_copy, &i);
+ CHECK_CALLED(concurrent_vector_int_alloc);
+ CHECK_CALLED(concurrent_vector_int_copy);
+ ok(idx == 2, "_Internal_grow_to_at_least_with_result returned %ld expected 2\n", (long)idx);
+ ok(v2.first_block == 1, "v2.first_block got %ld expected 1\n", (long)v2.first_block);
+ ok(v2.early_size == 3, "v2.early_size got %ld expected 3\n", (long)v2.early_size);
+ i = 0;
+ SET_EXPECT(concurrent_vector_int_alloc);
+ SET_EXPECT(concurrent_vector_int_copy);
+ idx = (size_t)call_func5(p_vector_base_v4__Internal_grow_to_at_least_with_result,
+ &v2, 5, sizeof(int), concurrent_vector_int_copy, &i);
+ CHECK_CALLED(concurrent_vector_int_alloc);
+ CHECK_CALLED(concurrent_vector_int_copy);
+ ok(idx == 3, "_Internal_grow_to_at_least_with_result returned %ld expected 3\n", (long)idx);
+ ok(v2.first_block == 1, "v2.first_block got %ld expected 1\n", (long)v2.first_block);
+ ok(v2.early_size == 5, "v2.early_size got %ld expected 5\n", (long)v2.early_size);
+ SET_EXPECT(concurrent_vector_int_destroy);
+ size = (size_t)call_func2(p_vector_base_v4__Internal_clear,
+ &v2, concurrent_vector_int_destroy);
+ ok(size == 3, "_Internal_clear returned %ld expected 3\n", (long)size);
+ CHECK_CALLED(concurrent_vector_int_destroy);
+ concurrent_vector_int_dtor(&v2);
+
SET_EXPECT(concurrent_vector_int_destroy);
size = (size_t)call_func2(p_vector_base_v4__Internal_clear,
&vector, concurrent_vector_int_destroy);
--
2.11.0
June 26, 2018
[PATCH 1/2] msvcp120: Add test for Concurrent_vector_grow_by.
by Hua Meng
Signed-off-by: Hua meng <161220092(a)smail.nju.edu.cn>
---
dlls/msvcp120/tests/msvcp120.c | 46 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/dlls/msvcp120/tests/msvcp120.c b/dlls/msvcp120/tests/msvcp120.c
index 0ec9fbd3b1..b5e470cba3 100644
--- a/dlls/msvcp120/tests/msvcp120.c
+++ b/dlls/msvcp120/tests/msvcp120.c
@@ -418,6 +418,8 @@ static void (__thiscall *p_vector_base_v4__Internal_swap)(
static void* (__thiscall *p_vector_base_v4__Internal_compact)(
vector_base_v4*, size_t, void*, void (__cdecl*)(void*, size_t),
void (__cdecl*)(void*, const void*, size_t));
+static size_t (__thiscall *p_vector_base_v4__Internal_grow_by)(
+ vector_base_v4*, size_t, size_t, void (__cdecl*)(void*, const void*, size_t), const void *);
static HMODULE msvcp;
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
@@ -568,6 +570,8 @@ static BOOL init(void)
"?_Internal_swap(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IEAAXAEAV123@@Z");
SET(p_vector_base_v4__Internal_compact,
"?_Internal_compact(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IEAAPEAX_KPEAXP6AX10(a)ZP6AX1PEBX0@Z(a)Z");
+ SET(p_vector_base_v4__Internal_grow_by,
+ "?_Internal_grow_by(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IEAA_K_K0P6AXPEAXPEBX0(a)Z2@Z");
} else {
SET(p_tr2_sys__File_size,
"?_File_size(a)sys@tr2(a)std@@YA_KPBD(a)Z");
@@ -687,6 +691,8 @@ static BOOL init(void)
"?_Internal_swap(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAEXAAV123@@Z");
SET(p_vector_base_v4__Internal_compact,
"?_Internal_compact(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAEPAXIPAXP6AX0I(a)ZP6AX0PBXI@Z(a)Z");
+ SET(p_vector_base_v4__Internal_grow_by,
+ "?_Internal_grow_by(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAEIIIP6AXPAXPBXI(a)Z1@Z");
#else
SET(p__Thrd_current,
"_Thrd_current");
@@ -734,7 +740,8 @@ static BOOL init(void)
"?_Internal_swap(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAAXAAV123@@Z");
SET(p_vector_base_v4__Internal_compact,
"?_Internal_compact(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAAPAXIPAXP6AX0I(a)ZP6AX0PBXI@Z(a)Z");
-
+ SET(p_vector_base_v4__Internal_grow_by,
+ "?_Internal_grow_by(a)_Concurrent_vector_base_v4@details(a)Concurrency@@IAAIIIP6AXPAXPBXI(a)Z1@Z");
#endif
}
SET(p__Thrd_equal,
@@ -2992,6 +2999,43 @@ static void test_vector_base_v4(void)
CHECK_CALLED(concurrent_vector_int_destroy);
concurrent_vector_int_dtor(&v2);
+ /* test for Internal_grow_by */
+ concurrent_vector_int_ctor(&v2);
+ SET_EXPECT(concurrent_vector_int_alloc);
+ data = call_func3(p_vector_base_v4__Internal_push_back, &v2, sizeof(int), &idx);
+ CHECK_CALLED(concurrent_vector_int_alloc);
+ ok(data != NULL, "_Internal_push_back returned NULL\n");
+ data = call_func3(p_vector_base_v4__Internal_push_back, &v2, sizeof(int), &idx);
+ ok(data != NULL, "_Internal_push_back returned NULL\n");
+ vector_elem_count += 2;
+ ok(v2.first_block == 1, "v2.first_block got %ld expected 1\n", (long)v2.first_block);
+ ok(v2.early_size == 2, "v2.early_size got %ld expected 2\n", (long)v2.early_size);
+ i = 0;
+ SET_EXPECT(concurrent_vector_int_alloc);
+ SET_EXPECT(concurrent_vector_int_copy);
+ idx = (size_t)call_func5(p_vector_base_v4__Internal_grow_by,
+ &v2, 1, sizeof(int), concurrent_vector_int_copy, &i);
+ CHECK_CALLED(concurrent_vector_int_alloc);
+ CHECK_CALLED(concurrent_vector_int_copy);
+ ok(idx == 2, "_Internal_grow_by returned %ld expected 2\n", (long)idx);
+ ok(v2.first_block == 1, "v2.first_block got %ld expected 1\n", (long)v2.first_block);
+ ok(v2.early_size == 3, "v2.early_size got %ld expected 3\n", (long)v2.early_size);
+ SET_EXPECT(concurrent_vector_int_alloc);
+ SET_EXPECT(concurrent_vector_int_copy);
+ idx = (size_t)call_func5(p_vector_base_v4__Internal_grow_by,
+ &v2, 2, sizeof(int), concurrent_vector_int_copy, &i);
+ CHECK_CALLED(concurrent_vector_int_alloc);
+ CHECK_CALLED(concurrent_vector_int_copy);
+ ok(idx == 3, "_Internal_grow_by returned %ld expected 3\n", (long)idx);
+ ok(v2.first_block == 1, "v2.first_block got %ld expected 1\n", (long)v2.first_block);
+ ok(v2.early_size == 5, "v2.early_size got %ld expected 5\n", (long)v2.early_size);
+ SET_EXPECT(concurrent_vector_int_destroy);
+ size = (size_t)call_func2(p_vector_base_v4__Internal_clear,
+ &v2, concurrent_vector_int_destroy);
+ ok(size == 3, "_Internal_clear returned %ld expected 3\n", (long)size);
+ CHECK_CALLED(concurrent_vector_int_destroy);
+ concurrent_vector_int_dtor(&v2);
+
SET_EXPECT(concurrent_vector_int_destroy);
size = (size_t)call_func2(p_vector_base_v4__Internal_clear,
&vector, concurrent_vector_int_destroy);
--
2.11.0
June 26, 2018
Re: [PATCH] gdi32/tests: Use the available ARRAY_SIZE() macro
by Huw Davies
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
June 26, 2018
[PATCH 2/2] testbot/Janitor: Clean up the latest directory too.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/Janitor.pl | 46 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/testbot/bin/Janitor.pl b/testbot/bin/Janitor.pl
index 9252efa65..a9cdd52cd 100755
--- a/testbot/bin/Janitor.pl
+++ b/testbot/bin/Janitor.pl
@@ -299,6 +299,52 @@ else
Error "Unable to open '$DataDir/staging': $!";
}
+# Check the content of the latest directory
+if (opendir(my $dh, "$DataDir/latest"))
+{
+ # We will be deleting files so read the directory in one go
+ my @Entries = readdir($dh);
+ close($dh);
+
+ my $AllVMs = $VMs->Clone();
+ foreach my $Entry (@Entries)
+ {
+ next if ($Entry eq "." or $Entry eq "..");
+ $Entry =~ m%^([^/]+)$%;
+ my $FileName = "$DataDir/latest/$1";
+ my $Age = int((-M $FileName) + 0.5);
+
+ if ($Entry =~ /^(.*)_[a-z0-9]+\.(?:err|log)$/)
+ {
+ # Keep the reference WineTest reports for all VMs even if they are
+ # retired or scheduled for deletion.
+ my $VMName = $1;
+ next if ($AllVMs->GetItem($VMName));
+ }
+ elsif ($Entry =~ /^(?:TestLauncher[0-9]*\.exe|winefiles.txt|winetest[0-9]*-latest\.exe)$/)
+ {
+ next;
+ }
+
+ Trace "Found a suspicious latest file: $Entry\n";
+ if ($JobPurgeDays != 0)
+ {
+ if ($Age >= $JobPurgeDays + 7)
+ {
+ DeletePath($FileName);
+ }
+ elsif ($Age > $JobPurgeDays)
+ {
+ Trace "'$FileName' will be deleted in ", $JobPurgeDays + 7 - $Age, " day(s).\n";
+ }
+ }
+ }
+}
+else
+{
+ Error "Unable to open '$DataDir/latest': $!";
+}
+
# Delete obsolete record groups
if ($JobPurgeDays != 0)
{
--
2.18.0
June 26, 2018
[PATCH 1/2] testbot/Janitor: Add DeletePath() to simplify deleting file/directories.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/Janitor.pl | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/testbot/bin/Janitor.pl b/testbot/bin/Janitor.pl
index 9fb38efde..9252efa65 100755
--- a/testbot/bin/Janitor.pl
+++ b/testbot/bin/Janitor.pl
@@ -116,6 +116,17 @@ if (defined $Usage)
# Main
#
+sub DeletePath($)
+{
+ my ($Path) = @_;
+
+ Trace "Deleting '$Path'\n";
+ if (!$DryRun and !rmtree($Path))
+ {
+ Error "Could not delete '$Path': $!\n";
+ }
+}
+
# Delete obsolete Jobs
if ($JobPurgeDays != 0)
{
@@ -268,11 +279,7 @@ if (opendir(my $dh, "$DataDir/staging"))
{
if ($Age >= $JobPurgeDays + 7)
{
- Trace "Deleting '$FileName'\n";
- if (!$DryRun and !rmtree($FileName))
- {
- Error "Could not delete '$FileName': $!\n";
- }
+ DeletePath($FileName);
}
elsif ($Age > $JobPurgeDays)
{
@@ -282,12 +289,8 @@ if (opendir(my $dh, "$DataDir/staging"))
}
elsif ($Age >= 1)
{
- Trace "Deleting '$FileName'\n";
- if (!$DryRun and !unlink $FileName)
- {
- # The user abandoned the submit procedure half-way through
- Error "Could not delete '$FileName': $!\n";
- }
+ # The user abandoned the submit procedure half-way through
+ DeletePath($FileName);
}
}
}
--
2.18.0
June 26, 2018
[PATCH 2/2] crypt32: Fix string arguments tracing.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/crypt32/base64.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/crypt32/base64.c b/dlls/crypt32/base64.c
index 4a904d41cc..2ba8055961 100644
--- a/dlls/crypt32/base64.c
+++ b/dlls/crypt32/base64.c
@@ -622,7 +622,7 @@ static LONG Base64WithHeaderAndTrailerToBinaryA(LPCSTR pszString,
if (!(headerBegins = strstr(pszString, header)))
{
- TRACE("Can't find %s in %s.\n", header, pszString);
+ TRACE("Can't find %s in %s.\n", header, debugstr_an(pszString, cchString));
return ERROR_INVALID_DATA;
}
@@ -746,7 +746,7 @@ BOOL WINAPI CryptStringToBinaryA(LPCSTR pszString,
StringToBinaryAFunc decoder;
LONG ret;
- TRACE("(%s, %d, %08x, %p, %p, %p, %p)\n", debugstr_a(pszString),
+ TRACE("(%s, %d, %08x, %p, %p, %p, %p)\n", debugstr_an(pszString, cchString ? cchString : -1),
cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags);
if (!pszString)
@@ -833,7 +833,7 @@ static LONG Base64WithHeaderAndTrailerToBinaryW(LPCWSTR pszString,
if (!(headerBegins = strstrW(pszString, header)))
{
- TRACE("Can't find %s in %s.\n", debugstr_w(header), debugstr_w(pszString));
+ TRACE("Can't find %s in %s.\n", debugstr_w(header), debugstr_wn(pszString, cchString));
return ERROR_INVALID_DATA;
}
@@ -957,7 +957,7 @@ BOOL WINAPI CryptStringToBinaryW(LPCWSTR pszString,
StringToBinaryWFunc decoder;
LONG ret;
- TRACE("(%s, %d, %08x, %p, %p, %p, %p)\n", debugstr_w(pszString),
+ TRACE("(%s, %d, %08x, %p, %p, %p, %p)\n", debugstr_wn(pszString, cchString ? cchString : -1),
cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags);
if (!pszString)
--
2.18.0
June 26, 2018
[PATCH 1/2] crypt32: Implement verification of ECDSA signatures.
by Nikolay Sivov
From: Michael Müller <michael(a)fds-team.de>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
Modifications from original patch:
- few renames to make it closer to existing code;
- removed unrelated formatting changes in existing code;
- new BCrypt path is rearranged to match existing order : import -> hash -> verify.
dlls/crypt32/Makefile.in | 2 +-
dlls/crypt32/cert.c | 260 +++++++++++++++++++++++++++++++++++++--
2 files changed, 250 insertions(+), 12 deletions(-)
diff --git a/dlls/crypt32/Makefile.in b/dlls/crypt32/Makefile.in
index d3a409fcae..0934222119 100644
--- a/dlls/crypt32/Makefile.in
+++ b/dlls/crypt32/Makefile.in
@@ -1,7 +1,7 @@
EXTRADEFS = -D_CRYPT32_
MODULE = crypt32.dll
IMPORTLIB = crypt32
-IMPORTS = user32 advapi32
+IMPORTS = user32 advapi32 bcrypt
DELAYIMPORTS = cryptnet
EXTRALIBS = $(SECURITY_LIBS)
diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c
index 83aac5d8f4..1667b42b0b 100644
--- a/dlls/crypt32/cert.c
+++ b/dlls/crypt32/cert.c
@@ -21,9 +21,14 @@
#include <stdarg.h>
#define NONAMELESSUNION
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "winternl.h"
+#define CRYPT_OID_INFO_HAS_EXTRA_FIELDS
#include "wincrypt.h"
+#include "bcrypt.h"
#include "winnls.h"
#include "rpc.h"
#include "wine/debug.h"
@@ -2408,22 +2413,13 @@ BOOL WINAPI CryptVerifyCertificateSignature(HCRYPTPROV_LEGACY hCryptProv,
CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pPublicKey, 0, NULL);
}
-static BOOL CRYPT_VerifyCertSignatureFromPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv,
- DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pubKeyInfo,
- const CERT_SIGNED_CONTENT_INFO *signedCert)
+static BOOL CRYPT_VerifySignature(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEncodingType,
+ CERT_PUBLIC_KEY_INFO *pubKeyInfo, const CERT_SIGNED_CONTENT_INFO *signedCert, const CRYPT_OID_INFO *info)
{
BOOL ret;
HCRYPTKEY key;
- PCCRYPT_OID_INFO info;
ALG_ID pubKeyID, hashID;
- info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
- signedCert->SignatureAlgorithm.pszObjId, 0);
- if (!info || info->dwGroupId != CRYPT_SIGN_ALG_OID_GROUP_ID)
- {
- SetLastError(NTE_BAD_ALGID);
- return FALSE;
- }
hashID = info->u.Algid;
if (info->ExtraInfo.cbData >= sizeof(ALG_ID))
pubKeyID = *(ALG_ID *)info->ExtraInfo.pbData;
@@ -2453,6 +2449,248 @@ static BOOL CRYPT_VerifyCertSignatureFromPublicKeyInfo(HCRYPTPROV_LEGACY hCryptP
return ret;
}
+static BOOL CNG_CalcHash(const WCHAR *algorithm, const CERT_SIGNED_CONTENT_INFO *signedCert,
+ BYTE **hash_value, DWORD *hash_len)
+{
+ BCRYPT_HASH_HANDLE hash = NULL;
+ BCRYPT_ALG_HANDLE alg = NULL;
+ NTSTATUS status;
+ DWORD size;
+
+ if ((status = BCryptOpenAlgorithmProvider(&alg, algorithm, NULL, 0)))
+ goto done;
+
+ if ((status = BCryptCreateHash(alg, &hash, NULL, 0, NULL, 0, 0)))
+ goto done;
+
+ if ((status = BCryptHashData(hash, signedCert->ToBeSigned.pbData, signedCert->ToBeSigned.cbData, 0)))
+ goto done;
+
+ if ((status = BCryptGetProperty(hash, BCRYPT_HASH_LENGTH, (BYTE *)hash_len, sizeof(*hash_len), &size, 0)))
+ goto done;
+
+ if (!(*hash_value = CryptMemAlloc(*hash_len)))
+ {
+ status = STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ if ((status = BCryptFinishHash(hash, *hash_value, *hash_len, 0)))
+ {
+ CryptMemFree(*hash_value);
+ goto done;
+ }
+
+done:
+ if (hash) BCryptDestroyHash(hash);
+ if (alg) BCryptCloseAlgorithmProvider(alg, 0);
+ if (status) SetLastError(RtlNtStatusToDosError(status));
+ return status == 0;
+}
+
+static BOOL CNG_ImportECCPubKey(CERT_PUBLIC_KEY_INFO *pubKeyInfo, BCRYPT_KEY_HANDLE *key)
+{
+ DWORD blob_magic, ecckey_len, size;
+ BCRYPT_ALG_HANDLE alg = NULL;
+ BCRYPT_ECCKEY_BLOB *ecckey;
+ const WCHAR *sign_algo;
+ char **ecc_curve;
+ NTSTATUS status;
+
+ if (!pubKeyInfo->PublicKey.cbData)
+ {
+ SetLastError(NTE_BAD_ALGID);
+ return FALSE;
+ }
+
+ if (pubKeyInfo->PublicKey.pbData[0] != 0x4)
+ {
+ FIXME("Compressed ECC curves (%02x) not yet supported\n", pubKeyInfo->PublicKey.pbData[0]);
+ SetLastError(NTE_BAD_ALGID);
+ return FALSE;
+ }
+
+ if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_OBJECT_IDENTIFIER, pubKeyInfo->Algorithm.Parameters.pbData,
+ pubKeyInfo->Algorithm.Parameters.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &ecc_curve, &size))
+ return FALSE;
+
+ if (!strcmp(*ecc_curve, szOID_ECC_CURVE_P256))
+ {
+ sign_algo = BCRYPT_ECDSA_P256_ALGORITHM;
+ blob_magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
+ }
+ else if (!strcmp(*ecc_curve, szOID_ECC_CURVE_P384))
+ {
+ sign_algo = BCRYPT_ECDSA_P384_ALGORITHM;
+ blob_magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC;
+ }
+ else
+ {
+ FIXME("Unsupported ecc curve type: %s\n", *ecc_curve);
+ sign_algo = NULL;
+ blob_magic = 0;
+ }
+ LocalFree(ecc_curve);
+
+ if (!sign_algo)
+ {
+ SetLastError(NTE_BAD_ALGID);
+ return FALSE;
+ }
+
+ if ((status = BCryptOpenAlgorithmProvider(&alg, sign_algo, NULL, 0)))
+ goto done;
+
+ ecckey_len = sizeof(BCRYPT_ECCKEY_BLOB) + pubKeyInfo->PublicKey.cbData - 1;
+ if (!(ecckey = CryptMemAlloc(ecckey_len)))
+ {
+ status = STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ ecckey->dwMagic = blob_magic;
+ ecckey->cbKey = (pubKeyInfo->PublicKey.cbData - 1) / 2;
+ memcpy(ecckey + 1, pubKeyInfo->PublicKey.pbData + 1, pubKeyInfo->PublicKey.cbData - 1);
+
+ status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPUBLIC_BLOB, key, (BYTE*)ecckey, ecckey_len, 0);
+
+done:
+ if (alg) BCryptCloseAlgorithmProvider(alg, 0);
+ if (status) SetLastError(RtlNtStatusToDosError(status));
+ return !status;
+}
+
+static BOOL CNG_ImportPubKey(CERT_PUBLIC_KEY_INFO *pubKeyInfo, BCRYPT_KEY_HANDLE *key)
+{
+ if (!strcmp(pubKeyInfo->Algorithm.pszObjId, szOID_ECC_PUBLIC_KEY))
+ return CNG_ImportECCPubKey(pubKeyInfo, key);
+
+ FIXME("Unsupported public key type: %s\n", debugstr_a(pubKeyInfo->Algorithm.pszObjId));
+ SetLastError(NTE_BAD_ALGID);
+ return FALSE;
+}
+
+static BOOL CNG_PrepareSignatureECC(BYTE *encoded_sig, DWORD encoded_size, BYTE **sig_value, DWORD *sig_len)
+{
+ CERT_ECC_SIGNATURE *ecc_sig;
+ DWORD size;
+ int i;
+
+ if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_ECC_SIGNATURE, encoded_sig, encoded_size,
+ CRYPT_DECODE_ALLOC_FLAG, NULL, &ecc_sig, &size))
+ return FALSE;
+
+ if (!ecc_sig->r.cbData || !ecc_sig->s.cbData)
+ {
+ LocalFree(ecc_sig);
+ SetLastError(ERROR_INVALID_DATA);
+ return FALSE;
+ }
+
+ *sig_len = ecc_sig->r.cbData + ecc_sig->s.cbData;
+ if (!(*sig_value = CryptMemAlloc(*sig_len)))
+ {
+ LocalFree(ecc_sig);
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ for (i = 0; i < ecc_sig->r.cbData; i++)
+ (*sig_value)[i] = ecc_sig->r.pbData[ecc_sig->r.cbData - i - 1];
+ for (i = 0; i < ecc_sig->s.cbData; i++)
+ (*sig_value)[ecc_sig->r.cbData + i] = ecc_sig->s.pbData[ecc_sig->s.cbData - i - 1];
+
+ LocalFree(ecc_sig);
+ return TRUE;
+}
+
+static BOOL CNG_PrepareSignature(CERT_PUBLIC_KEY_INFO *pubKeyInfo, const CERT_SIGNED_CONTENT_INFO *signedCert,
+ BYTE **sig_value, DWORD *sig_len)
+{
+ BYTE *encoded_sig;
+ BOOL ret = FALSE;
+ int i;
+
+ if (!signedCert->Signature.cbData)
+ {
+ SetLastError(ERROR_INVALID_DATA);
+ return FALSE;
+ }
+
+ if (!(encoded_sig = CryptMemAlloc(signedCert->Signature.cbData)))
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ for (i = 0; i < signedCert->Signature.cbData; i++)
+ encoded_sig[i] = signedCert->Signature.pbData[signedCert->Signature.cbData - i - 1];
+
+ if (!strcmp(pubKeyInfo->Algorithm.pszObjId, szOID_ECC_PUBLIC_KEY))
+ ret = CNG_PrepareSignatureECC(encoded_sig, signedCert->Signature.cbData, sig_value, sig_len);
+ else
+ {
+ FIXME("Unsupported public key type: %s\n", debugstr_a(pubKeyInfo->Algorithm.pszObjId));
+ SetLastError(NTE_BAD_ALGID);
+ }
+
+ CryptMemFree(encoded_sig);
+ return ret;
+}
+
+static BOOL CNG_VerifySignature(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEncodingType,
+ CERT_PUBLIC_KEY_INFO *pubKeyInfo, const CERT_SIGNED_CONTENT_INFO *signedCert, const CRYPT_OID_INFO *info)
+{
+ BCRYPT_KEY_HANDLE key = NULL;
+ BYTE *hash_value = NULL, *sig_value;
+ DWORD hash_len, sig_len;
+ NTSTATUS status;
+ BOOL ret;
+
+ ret = CNG_ImportPubKey(pubKeyInfo, &key);
+ if (ret)
+ {
+ ret = CNG_CalcHash(info->pwszCNGAlgid, signedCert, &hash_value, &hash_len);
+ if (ret)
+ {
+ ret = CNG_PrepareSignature(pubKeyInfo, signedCert, &sig_value, &sig_len);
+ if (ret)
+ {
+ status = BCryptVerifySignature(key, NULL, hash_value, hash_len, sig_value, sig_len, 0);
+ if (status)
+ {
+ FIXME("Failed to verify signature: %08x\n", status);
+ SetLastError(RtlNtStatusToDosError(status));
+ ret = FALSE;
+ }
+ CryptMemFree(sig_value);
+ }
+ CryptMemFree(hash_value);
+ }
+ BCryptDestroyKey(key);
+ }
+
+ return ret;
+}
+
+static BOOL CRYPT_VerifyCertSignatureFromPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEncodingType,
+ CERT_PUBLIC_KEY_INFO *pubKeyInfo, const CERT_SIGNED_CONTENT_INFO *signedCert)
+{
+ CCRYPT_OID_INFO *info;
+
+ info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, signedCert->SignatureAlgorithm.pszObjId, 0);
+ if (!info || info->dwGroupId != CRYPT_SIGN_ALG_OID_GROUP_ID)
+ {
+ SetLastError(NTE_BAD_ALGID);
+ return FALSE;
+ }
+
+ if (info->u.Algid == CALG_OID_INFO_CNG_ONLY)
+ return CNG_VerifySignature(hCryptProv, dwCertEncodingType, pubKeyInfo, signedCert, info);
+ else
+ return CRYPT_VerifySignature(hCryptProv, dwCertEncodingType, pubKeyInfo, signedCert, info);
+}
+
BOOL WINAPI CryptVerifyCertificateSignatureEx(HCRYPTPROV_LEGACY hCryptProv,
DWORD dwCertEncodingType, DWORD dwSubjectType, void *pvSubject,
DWORD dwIssuerType, void *pvIssuer, DWORD dwFlags, void *pvReserved)
--
2.18.0
June 26, 2018
[PATCH] msi: Remove checks for negative value.
by Hans Leidekker
From: Andrey Gusev <andrey.goosev(a)gmail.com>
Signed-off-by: Andrey Gusev <andrey.goosev(a)gmail.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/msi/format.c | 2 +-
dlls/msi/string.c | 5 ++---
dlls/msi/table.c | 4 +---
3 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/dlls/msi/format.c b/dlls/msi/format.c
index 9356c9e30d..d32afb2a60 100644
--- a/dlls/msi/format.c
+++ b/dlls/msi/format.c
@@ -242,7 +242,7 @@ static WCHAR *deformat_file( FORMAT *format, FORMSTR *str, BOOL shortname, int *
if ((ret = strdupW( file->TargetPath ))) len = strlenW( ret );
goto done;
}
- if ((len = GetShortPathNameW(file->TargetPath, NULL, 0)) <= 0)
+ if (!(len = GetShortPathNameW(file->TargetPath, NULL, 0)))
{
if ((ret = strdupW( file->TargetPath ))) len = strlenW( ret );
goto done;
diff --git a/dlls/msi/string.c b/dlls/msi/string.c
index f094a53c9e..7383fddbed 100644
--- a/dlls/msi/string.c
+++ b/dlls/msi/string.c
@@ -233,7 +233,7 @@ static void set_st_entry( string_table *st, UINT n, WCHAR *str, int len, USHORT
static UINT string2id( const string_table *st, const char *buffer, UINT *id )
{
- DWORD sz;
+ int sz;
UINT r = ERROR_INVALID_PARAMETER;
LPWSTR str;
@@ -245,8 +245,7 @@ static UINT string2id( const string_table *st, const char *buffer, UINT *id )
return ERROR_SUCCESS;
}
- sz = MultiByteToWideChar( st->codepage, 0, buffer, -1, NULL, 0 );
- if( sz <= 0 )
+ if (!(sz = MultiByteToWideChar( st->codepage, 0, buffer, -1, NULL, 0 )))
return r;
str = msi_alloc( sz*sizeof(WCHAR) );
if( !str )
diff --git a/dlls/msi/table.c b/dlls/msi/table.c
index 45a181445a..e046c5c9e2 100644
--- a/dlls/msi/table.c
+++ b/dlls/msi/table.c
@@ -1279,9 +1279,7 @@ static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT
UINT r;
int ival;
- if ( (iField <= 0) ||
- (iField > tv->num_cols) ||
- MSI_RecordIsNull( rec, iField ) )
+ if (!iField || iField > tv->num_cols || MSI_RecordIsNull( rec, iField ))
return ERROR_FUNCTION_FAILED;
columninfo = tv->columns[ iField - 1 ];
--
2.11.0
June 26, 2018
[PATCH] shell32: use characters as arguments to GetTempPathW and GetLongPathNameW
by Marcus Meissner
Signed-off-by: Marcus Meissner <marcus(a)jet.franken.de>
---
dlls/shell32/tests/shlfolder.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index 6460fd9381..bb303f66e4 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -244,8 +244,8 @@ todo_wine_if(parse_tests[i].todo)
CoTaskMemFree(pidl);
/* Relative paths are interpreted relative to the desktop. */
- GetTempPathW(sizeof(buffer), buffer);
- GetLongPathNameW(buffer, buffer, sizeof(buffer));
+ GetTempPathW(ARRAY_SIZE(buffer), buffer);
+ GetLongPathNameW(buffer, buffer, ARRAY_SIZE(buffer));
SetCurrentDirectoryW(buffer);
CreateDirectoryW(testdirW, NULL);
--
2.17.1
June 26, 2018
Re: [PATCH 5/5] include: Make fil_data.idl a common header.
by Marvin
Hi,
While running your changed tests on Windows, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at
https://testbot.winehq.org/JobDetails.pl?Key=39362
Your paranoid android.
=== w2008s64 (64 bit referenceclock) ===
TestBot process got stuck or died unexpectedly
The previous 1 run(s) terminated abnormally
June 26, 2018
[PATCH 5/5] include: Make fil_data.idl a common header.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/devenum/Makefile.in | 3 +-
dlls/devenum/createdevenum.c | 2 +-
dlls/devenum/fil_data.idl | 47 --------------------------
dlls/dxdiagn/Makefile.in | 3 +-
dlls/dxdiagn/provider.c | 2 +-
dlls/quartz/Makefile.in | 1 -
dlls/quartz/fil_data.idl | 52 -----------------------------
dlls/quartz/filtermapper.c | 2 +-
dlls/quartz/tests/Makefile.in | 1 -
dlls/quartz/tests/fil_data.idl | 52 -----------------------------
dlls/quartz/tests/filtermapper.c | 2 +-
include/Makefile.in | 1 +
{dlls/dxdiagn => include/wine}/fil_data.idl | 21 ++----------
13 files changed, 10 insertions(+), 179 deletions(-)
delete mode 100644 dlls/devenum/fil_data.idl
delete mode 100644 dlls/quartz/fil_data.idl
delete mode 100644 dlls/quartz/tests/fil_data.idl
rename {dlls/dxdiagn => include/wine}/fil_data.idl (67%)
diff --git a/dlls/devenum/Makefile.in b/dlls/devenum/Makefile.in
index d1407a9..2760eed 100644
--- a/dlls/devenum/Makefile.in
+++ b/dlls/devenum/Makefile.in
@@ -9,7 +9,6 @@ C_SRCS = \
parsedisplayname.c
IDL_SRCS = \
- devenum_classes.idl \
- fil_data.idl
+ devenum_classes.idl
RC_SRCS = devenum.rc
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c
index 8275c99..c138cb7 100644
--- a/dlls/devenum/createdevenum.c
+++ b/dlls/devenum/createdevenum.c
@@ -37,7 +37,7 @@
#include "mmddk.h"
#include "initguid.h"
-#include "fil_data.h"
+#include "wine/fil_data.h"
WINE_DEFAULT_DEBUG_CHANNEL(devenum);
diff --git a/dlls/devenum/fil_data.idl b/dlls/devenum/fil_data.idl
deleted file mode 100644
index 7e37a75..0000000
--- a/dlls/devenum/fil_data.idl
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2009 Vitaliy Margolen
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#pragma makedep header
-
-import "objidl.idl";
-import "strmif.idl";
-import "unknwn.idl";
-
-
-/*****************************************************************************
- * IAMFilterData interface
- */
-[
- object,
- uuid(97f7c4d4-547b-4a5f-8332-536430ad2e4d),
- pointer_default(unique)
-]
-interface IAMFilterData : IUnknown
-{
- typedef [unique] IAMFilterData *LPIAMFILTERDATA;
-
- HRESULT ParseFilterData(
- [in] BYTE * rgbFilterData,
- [in] ULONG cb,
- [out] BYTE ** prgbRegFilter2);
-
- HRESULT CreateFilterData(
- [in] REGFILTER2 * prf2,
- [out] BYTE ** prgbFilterData,
- [out] ULONG * pcb);
-}
diff --git a/dlls/dxdiagn/Makefile.in b/dlls/dxdiagn/Makefile.in
index 3a1017e..c16396e 100644
--- a/dlls/dxdiagn/Makefile.in
+++ b/dlls/dxdiagn/Makefile.in
@@ -9,5 +9,4 @@ C_SRCS = \
RC_SRCS = dxdiagn.rc
IDL_SRCS = \
- dxdiagn.idl \
- fil_data.idl
+ dxdiagn.idl
diff --git a/dlls/dxdiagn/provider.c b/dlls/dxdiagn/provider.c
index 4f964ad..1fdab5e 100644
--- a/dlls/dxdiagn/provider.c
+++ b/dlls/dxdiagn/provider.c
@@ -35,7 +35,7 @@
#include "d3d9.h"
#include "strmif.h"
#include "initguid.h"
-#include "fil_data.h"
+#include "wine/fil_data.h"
#include "psapi.h"
#include "wbemcli.h"
diff --git a/dlls/quartz/Makefile.in b/dlls/quartz/Makefile.in
index e938865..5eb8d44 100644
--- a/dlls/quartz/Makefile.in
+++ b/dlls/quartz/Makefile.in
@@ -30,7 +30,6 @@ RC_SRCS = version.rc
IDL_SRCS = \
control_tlb.idl \
- fil_data.idl \
quartz_strmif.idl
dlldata_EXTRADEFS = -DENTRY_PREFIX=QUARTZ_ -DPROXY_DELEGATION -DWINE_REGISTER_DLL
diff --git a/dlls/quartz/fil_data.idl b/dlls/quartz/fil_data.idl
deleted file mode 100644
index ab93499..0000000
--- a/dlls/quartz/fil_data.idl
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2009 Vitaliy Margolen
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#pragma makedep header
-
-import "objidl.idl";
-import "strmif.idl";
-import "unknwn.idl";
-
-
-/*****************************************************************************
- * IAMFilterData interface
- *
- * Notes:
- * - This interface is deprecated and IFilterMapper2 should be used instead.
- * - There is no full replacement for IAMFilterData::ParseFilterData short of manually
- * parsing out the REGFILTER2 struct from the binary blob.
- */
-[
- object,
- uuid(97f7c4d4-547b-4a5f-8332-536430ad2e4d),
- pointer_default(unique)
-]
-interface IAMFilterData : IUnknown
-{
- typedef [unique] IAMFilterData *LPIAMFILTERDATA;
-
- HRESULT ParseFilterData(
- [in] BYTE * rgbFilterData,
- [in] ULONG cb,
- [out] BYTE ** prgbRegFilter2);
-
- HRESULT CreateFilterData(
- [in] REGFILTER2 * prf2,
- [out] BYTE ** prgbFilterData,
- [out] ULONG * pcb);
-}
diff --git a/dlls/quartz/filtermapper.c b/dlls/quartz/filtermapper.c
index 20c7e3a..d78f643 100644
--- a/dlls/quartz/filtermapper.c
+++ b/dlls/quartz/filtermapper.c
@@ -37,7 +37,7 @@
#include "wine/unicode.h"
#include "uuids.h"
#include "initguid.h"
-#include "fil_data.h"
+#include "wine/fil_data.h"
#include "wine/debug.h"
diff --git a/dlls/quartz/tests/Makefile.in b/dlls/quartz/tests/Makefile.in
index 4f54666..6b880c3 100644
--- a/dlls/quartz/tests/Makefile.in
+++ b/dlls/quartz/tests/Makefile.in
@@ -12,7 +12,6 @@ C_SRCS = \
referenceclock.c \
videorenderer.c
-IDL_SRCS = fil_data.idl
RC_SRCS = \
rsrc.rc
diff --git a/dlls/quartz/tests/fil_data.idl b/dlls/quartz/tests/fil_data.idl
deleted file mode 100644
index ab93499..0000000
--- a/dlls/quartz/tests/fil_data.idl
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2009 Vitaliy Margolen
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#pragma makedep header
-
-import "objidl.idl";
-import "strmif.idl";
-import "unknwn.idl";
-
-
-/*****************************************************************************
- * IAMFilterData interface
- *
- * Notes:
- * - This interface is deprecated and IFilterMapper2 should be used instead.
- * - There is no full replacement for IAMFilterData::ParseFilterData short of manually
- * parsing out the REGFILTER2 struct from the binary blob.
- */
-[
- object,
- uuid(97f7c4d4-547b-4a5f-8332-536430ad2e4d),
- pointer_default(unique)
-]
-interface IAMFilterData : IUnknown
-{
- typedef [unique] IAMFilterData *LPIAMFILTERDATA;
-
- HRESULT ParseFilterData(
- [in] BYTE * rgbFilterData,
- [in] ULONG cb,
- [out] BYTE ** prgbRegFilter2);
-
- HRESULT CreateFilterData(
- [in] REGFILTER2 * prf2,
- [out] BYTE ** prgbFilterData,
- [out] ULONG * pcb);
-}
diff --git a/dlls/quartz/tests/filtermapper.c b/dlls/quartz/tests/filtermapper.c
index 5a43785..7b6a018 100644
--- a/dlls/quartz/tests/filtermapper.c
+++ b/dlls/quartz/tests/filtermapper.c
@@ -26,7 +26,7 @@
#include "dshow.h"
#include "winternl.h"
-#include "fil_data.h"
+#include "wine/fil_data.h"
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
diff --git a/include/Makefile.in b/include/Makefile.in
index 39f2691..995544a 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -664,6 +664,7 @@ SOURCES = \
windowsx.h \
wine/debug.h \
wine/exception.h \
+ wine/fil_data.idl \
wine/itss.idl \
wine/library.h \
wine/svcctl.idl \
diff --git a/dlls/dxdiagn/fil_data.idl b/include/wine/fil_data.idl
similarity index 67%
rename from dlls/dxdiagn/fil_data.idl
rename to include/wine/fil_data.idl
index 7e37a75..19dfa8a 100644
--- a/dlls/dxdiagn/fil_data.idl
+++ b/include/wine/fil_data.idl
@@ -16,16 +16,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#pragma makedep header
-
-import "objidl.idl";
-import "strmif.idl";
import "unknwn.idl";
+import "strmif.idl";
-
-/*****************************************************************************
- * IAMFilterData interface
- */
[
object,
uuid(97f7c4d4-547b-4a5f-8332-536430ad2e4d),
@@ -33,15 +26,7 @@ import "unknwn.idl";
]
interface IAMFilterData : IUnknown
{
- typedef [unique] IAMFilterData *LPIAMFILTERDATA;
+ HRESULT ParseFilterData( [in] BYTE *data, [in] ULONG size, [out] BYTE **regfilter );
- HRESULT ParseFilterData(
- [in] BYTE * rgbFilterData,
- [in] ULONG cb,
- [out] BYTE ** prgbRegFilter2);
-
- HRESULT CreateFilterData(
- [in] REGFILTER2 * prf2,
- [out] BYTE ** prgbFilterData,
- [out] ULONG * pcb);
+ HRESULT CreateFilterData( [in] REGFILTER2 *regfilter, [out] BYTE **data, [out] ULONG *size );
}
--
2.7.4
June 26, 2018
[PATCH 4/5] devenum: Remove an unused typedef.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/devenum/devenum_main.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/dlls/devenum/devenum_main.c b/dlls/devenum/devenum_main.c
index 98ad1ad..b17bc93 100644
--- a/dlls/devenum/devenum_main.c
+++ b/dlls/devenum/devenum_main.c
@@ -28,13 +28,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(devenum);
DECLSPEC_HIDDEN LONG dll_refs;
static HINSTANCE devenum_instance;
-typedef struct
-{
- REFCLSID clsid;
- LPCWSTR friendly_name;
- BOOL instance;
-} register_info;
-
/***********************************************************************
* DllEntryPoint
*/
--
2.7.4
June 26, 2018
[PATCH 3/5] devenum: Make some variables static.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/devenum/createdevenum.c | 14 ++++++--------
dlls/devenum/devenum_main.c | 13 ++++---------
dlls/devenum/devenum_private.h | 4 +---
dlls/devenum/mediacatenum.c | 4 +++-
4 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c
index 06c264c..8275c99 100644
--- a/dlls/devenum/createdevenum.c
+++ b/dlls/devenum/createdevenum.c
@@ -41,8 +41,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(devenum);
-extern HINSTANCE DEVENUM_hInstance;
-
static const WCHAR wszFilterKeyName[] = {'F','i','l','t','e','r',0};
static const WCHAR wszMeritName[] = {'M','e','r','i','t',0};
static const WCHAR wszPins[] = {'P','i','n','s',0};
@@ -460,7 +458,7 @@ static void register_legacy_filters(void)
V_VT(&var) = VT_BSTR;
if (!(V_BSTR(&var) = SysAllocString(wszFilterSubkeyName)))
goto cleanup;
- hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ hr = IPropertyBag_Write(prop_bag, clsidW, &var);
if (FAILED(hr)) goto cleanup;
VariantClear(&var);
@@ -537,7 +535,7 @@ static BOOL CALLBACK register_dsound_devices(GUID *guid, const WCHAR *desc, cons
StringFromGUID2(&CLSID_DSoundRender, clsid, CHARS_IN_GUID);
if (!(V_BSTR(&var) = SysAllocString(clsid)))
goto cleanup;
- hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ hr = IPropertyBag_Write(prop_bag, clsidW, &var);
if (FAILED(hr)) goto cleanup;
VariantClear(&var);
@@ -620,7 +618,7 @@ static void register_waveout_devices(void)
StringFromGUID2(&CLSID_AudioRender, clsid, CHARS_IN_GUID);
if (!(V_BSTR(&var) = SysAllocString(clsid)))
goto cleanup;
- hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ hr = IPropertyBag_Write(prop_bag, clsidW, &var);
if (FAILED(hr)) goto cleanup;
VariantClear(&var);
@@ -693,7 +691,7 @@ static void register_wavein_devices(void)
StringFromGUID2(&CLSID_AudioRecord, clsid, CHARS_IN_GUID);
if (!(V_BSTR(&var) = SysAllocString(clsid)))
goto cleanup;
- hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ hr = IPropertyBag_Write(prop_bag, clsidW, &var);
if (FAILED(hr)) goto cleanup;
VariantClear(&var);
@@ -765,7 +763,7 @@ static void register_midiout_devices(void)
StringFromGUID2(&CLSID_AVIMIDIRender, clsid, CHARS_IN_GUID);
if (!(V_BSTR(&var) = SysAllocString(clsid)))
goto cleanup;
- hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ hr = IPropertyBag_Write(prop_bag, clsidW, &var);
if (FAILED(hr)) goto cleanup;
VariantClear(&var);
@@ -854,7 +852,7 @@ static void register_vfw_codecs(void)
StringFromGUID2(&CLSID_AVICo, clsid, CHARS_IN_GUID);
if (!(V_BSTR(&var) = SysAllocString(clsid)))
goto cleanup;
- hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
+ hr = IPropertyBag_Write(prop_bag, clsidW, &var);
if (FAILED(hr)) goto cleanup;
VariantClear(&var);
diff --git a/dlls/devenum/devenum_main.c b/dlls/devenum/devenum_main.c
index 3499f99..98ad1ad 100644
--- a/dlls/devenum/devenum_main.c
+++ b/dlls/devenum/devenum_main.c
@@ -26,7 +26,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(devenum);
DECLSPEC_HIDDEN LONG dll_refs;
-DECLSPEC_HIDDEN HINSTANCE DEVENUM_hInstance;
+static HINSTANCE devenum_instance;
typedef struct
{
@@ -36,11 +36,6 @@ typedef struct
} register_info;
/***********************************************************************
- * Global string constant definitions
- */
-const WCHAR clsid_keyname[6] = { 'C', 'L', 'S', 'I', 'D', 0 };
-
-/***********************************************************************
* DllEntryPoint
*/
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
@@ -49,7 +44,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
- DEVENUM_hInstance = hinstDLL;
+ devenum_instance = hinstDLL;
DisableThreadLibraryCalls(hinstDLL);
break;
}
@@ -166,7 +161,7 @@ HRESULT WINAPI DllRegisterServer(void)
TRACE("\n");
- res = __wine_register_resources( DEVENUM_hInstance );
+ res = __wine_register_resources( devenum_instance );
if (FAILED(res))
return res;
@@ -214,5 +209,5 @@ HRESULT WINAPI DllRegisterServer(void)
HRESULT WINAPI DllUnregisterServer(void)
{
FIXME("stub!\n");
- return __wine_unregister_resources( DEVENUM_hInstance );
+ return __wine_unregister_resources( devenum_instance );
}
diff --git a/dlls/devenum/devenum_private.h b/dlls/devenum/devenum_private.h
index ea4e017..e18c57d 100644
--- a/dlls/devenum/devenum_private.h
+++ b/dlls/devenum/devenum_private.h
@@ -83,7 +83,7 @@ extern IParseDisplayName DEVENUM_ParseDisplayName DECLSPEC_HIDDEN;
*/
static const WCHAR backslashW[] = {'\\',0};
-static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
+static const WCHAR clsidW[] = {'C','L','S','I','D',0};
static const WCHAR instanceW[] = {'\\','I','n','s','t','a','n','c','e',0};
static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
@@ -93,5 +93,3 @@ static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0};
static const WCHAR dmoW[] = {'d','m','o',':',0};
static const WCHAR swW[] = {'s','w',':',0};
static const WCHAR cmW[] = {'c','m',':',0};
-
-extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
diff --git a/dlls/devenum/mediacatenum.c b/dlls/devenum/mediacatenum.c
index c4338a2..660e81c 100644
--- a/dlls/devenum/mediacatenum.c
+++ b/dlls/devenum/mediacatenum.c
@@ -347,6 +347,7 @@ static HRESULT create_PropertyBag(MediaCatMoniker *mon, IPropertyBag **ppBag)
else if (rpb->type == DEVICE_FILTER)
{
strcpyW(rpb->path, clsidW);
+ strcatW(rpb->path, backslashW);
if (mon->has_class)
{
StringFromGUID2(&mon->class, rpb->path + strlenW(rpb->path), CHARS_IN_GUID);
@@ -496,7 +497,7 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject(IMoniker *iface, IBi
if (SUCCEEDED(res))
{
V_VT(&var) = VT_LPWSTR;
- res = IPropertyBag_Read(pProp, clsid_keyname, &var, NULL);
+ res = IPropertyBag_Read(pProp, clsidW, &var, NULL);
}
if (SUCCEEDED(res))
{
@@ -1027,6 +1028,7 @@ HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **ppEnumMoniker)
pEnumMoniker->class = *class;
strcpyW(buffer, clsidW);
+ strcatW(buffer, backslashW);
StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID);
strcatW(buffer, instanceW);
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &pEnumMoniker->sw_key))
--
2.7.4
June 26, 2018
[PATCH 2/5] devenum: Use separate factories for CLSID_SystemDeviceEnum and CLSID_CDeviceMoniker.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/devenum/devenum_main.c | 46 +++++++++++++++++++++++----------------------
1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/dlls/devenum/devenum_main.c b/dlls/devenum/devenum_main.c
index 7bfc593..3499f99 100644
--- a/dlls/devenum/devenum_main.c
+++ b/dlls/devenum/devenum_main.c
@@ -56,6 +56,17 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
return TRUE;
}
+struct class_factory
+{
+ IClassFactory IClassFactory_iface;
+ IUnknown *obj;
+};
+
+static inline struct class_factory *impl_from_IClassFactory( IClassFactory *iface )
+{
+ return CONTAINING_RECORD( iface, struct class_factory, IClassFactory_iface );
+}
+
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID iid, void **obj)
{
TRACE("(%p, %s, %p)\n", iface, debugstr_guid(iid), obj);
@@ -87,24 +98,15 @@ static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface,
IUnknown *outer, REFIID iid, void **obj)
{
+ struct class_factory *This = impl_from_IClassFactory( iface );
+
TRACE("(%p, %s, %p)\n", outer, debugstr_guid(iid), obj);
if (!obj) return E_POINTER;
if (outer) return CLASS_E_NOAGGREGATION;
- if (IsEqualGUID(&IID_ICreateDevEnum, iid))
- {
- *obj = &DEVENUM_CreateDevEnum;
- return S_OK;
- }
- if (IsEqualGUID(&IID_IParseDisplayName, iid))
- {
- *obj = &DEVENUM_ParseDisplayName;
- return S_OK;
- }
-
- return CLASS_E_CLASSNOTAVAILABLE;
+ return IUnknown_QueryInterface(This->obj, iid, obj);
}
static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL lock)
@@ -124,24 +126,24 @@ static const IClassFactoryVtbl ClassFactory_vtbl = {
ClassFactory_LockServer
};
-static IClassFactory devenum_cf = { &ClassFactory_vtbl };
+static struct class_factory create_devenum_cf = { { &ClassFactory_vtbl }, (IUnknown *)&DEVENUM_CreateDevEnum };
+static struct class_factory device_moniker_cf = { { &ClassFactory_vtbl }, (IUnknown *)&DEVENUM_ParseDisplayName };
/***********************************************************************
* DllGetClassObject (DEVENUM.@)
*/
-HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
+HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **obj)
{
- TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
+ TRACE("(%s, %s, %p)\n", debugstr_guid(clsid), debugstr_guid(iid), obj);
- *ppv = NULL;
+ *obj = NULL;
- /* FIXME: we should really have two class factories.
- * Oh well - works just fine as it is */
- if (IsEqualGUID(rclsid, &CLSID_SystemDeviceEnum) ||
- IsEqualGUID(rclsid, &CLSID_CDeviceMoniker))
- return IClassFactory_QueryInterface(&devenum_cf, iid, ppv);
+ if (IsEqualGUID(clsid, &CLSID_SystemDeviceEnum))
+ return IClassFactory_QueryInterface(&create_devenum_cf.IClassFactory_iface, iid, obj);
+ else if (IsEqualGUID(clsid, &CLSID_CDeviceMoniker))
+ return IClassFactory_QueryInterface(&device_moniker_cf.IClassFactory_iface, iid, obj);
- FIXME("CLSID: %s, IID: %s\n", debugstr_guid(rclsid), debugstr_guid(iid));
+ FIXME("class %s not available\n", debugstr_guid(clsid));
return CLASS_E_CLASSNOTAVAILABLE;
}
--
2.7.4
June 26, 2018
[PATCH 1/5] devenum: Merge factory.c into devenum_main.c.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/devenum/Makefile.in | 1 -
dlls/devenum/devenum_main.c | 74 ++++++++++++++++++++++-
dlls/devenum/devenum_private.h | 10 ---
dlls/devenum/factory.c | 134 -----------------------------------------
4 files changed, 72 insertions(+), 147 deletions(-)
delete mode 100644 dlls/devenum/factory.c
diff --git a/dlls/devenum/Makefile.in b/dlls/devenum/Makefile.in
index ae138b6..d1407a9 100644
--- a/dlls/devenum/Makefile.in
+++ b/dlls/devenum/Makefile.in
@@ -5,7 +5,6 @@ DELAYIMPORTS = msvfw32
C_SRCS = \
createdevenum.c \
devenum_main.c \
- factory.c \
mediacatenum.c \
parsedisplayname.c
diff --git a/dlls/devenum/devenum_main.c b/dlls/devenum/devenum_main.c
index cb4b454..7bfc593 100644
--- a/dlls/devenum/devenum_main.c
+++ b/dlls/devenum/devenum_main.c
@@ -1,5 +1,5 @@
/*
- * exported dll functions for devenum.dll
+ * Device Enumeration
*
* Copyright (C) 2002 John K. Hohm
* Copyright (C) 2002 Robert Shearman
@@ -56,6 +56,76 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
return TRUE;
}
+static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID iid, void **obj)
+{
+ TRACE("(%p, %s, %p)\n", iface, debugstr_guid(iid), obj);
+
+ if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory))
+ {
+ IClassFactory_AddRef(iface);
+ *obj = iface;
+ return S_OK;
+ }
+
+ *obj = NULL;
+ WARN("no interface for %s\n", debugstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
+{
+ DEVENUM_LockModule();
+ return 2;
+}
+
+static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
+{
+ DEVENUM_UnlockModule();
+ return 1;
+}
+
+static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface,
+ IUnknown *outer, REFIID iid, void **obj)
+{
+ TRACE("(%p, %s, %p)\n", outer, debugstr_guid(iid), obj);
+
+ if (!obj) return E_POINTER;
+
+ if (outer) return CLASS_E_NOAGGREGATION;
+
+ if (IsEqualGUID(&IID_ICreateDevEnum, iid))
+ {
+ *obj = &DEVENUM_CreateDevEnum;
+ return S_OK;
+ }
+ if (IsEqualGUID(&IID_IParseDisplayName, iid))
+ {
+ *obj = &DEVENUM_ParseDisplayName;
+ return S_OK;
+ }
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL lock)
+{
+ if (lock)
+ DEVENUM_LockModule();
+ else
+ DEVENUM_UnlockModule();
+ return S_OK;
+}
+
+static const IClassFactoryVtbl ClassFactory_vtbl = {
+ ClassFactory_QueryInterface,
+ ClassFactory_AddRef,
+ ClassFactory_Release,
+ ClassFactory_CreateInstance,
+ ClassFactory_LockServer
+};
+
+static IClassFactory devenum_cf = { &ClassFactory_vtbl };
+
/***********************************************************************
* DllGetClassObject (DEVENUM.@)
*/
@@ -69,7 +139,7 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
* Oh well - works just fine as it is */
if (IsEqualGUID(rclsid, &CLSID_SystemDeviceEnum) ||
IsEqualGUID(rclsid, &CLSID_CDeviceMoniker))
- return IClassFactory_QueryInterface(&DEVENUM_ClassFactory.IClassFactory_iface, iid, ppv);
+ return IClassFactory_QueryInterface(&devenum_cf, iid, ppv);
FIXME("CLSID: %s, IID: %s\n", debugstr_guid(rclsid), debugstr_guid(iid));
return CLASS_E_CLASSNOTAVAILABLE;
diff --git a/dlls/devenum/devenum_private.h b/dlls/devenum/devenum_private.h
index df0080d..ea4e017 100644
--- a/dlls/devenum/devenum_private.h
+++ b/dlls/devenum/devenum_private.h
@@ -51,15 +51,6 @@ extern LONG dll_refs DECLSPEC_HIDDEN;
static inline void DEVENUM_LockModule(void) { InterlockedIncrement(&dll_refs); }
static inline void DEVENUM_UnlockModule(void) { InterlockedDecrement(&dll_refs); }
-
-/**********************************************************************
- * ClassFactory declaration for devenum.dll
- */
-typedef struct
-{
- IClassFactory IClassFactory_iface;
-} ClassFactoryImpl;
-
enum device_type
{
DEVICE_FILTER,
@@ -84,7 +75,6 @@ typedef struct
MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) DECLSPEC_HIDDEN;
HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **enum_mon) DECLSPEC_HIDDEN;
-extern ClassFactoryImpl DEVENUM_ClassFactory DECLSPEC_HIDDEN;
extern ICreateDevEnum DEVENUM_CreateDevEnum DECLSPEC_HIDDEN;
extern IParseDisplayName DEVENUM_ParseDisplayName DECLSPEC_HIDDEN;
diff --git a/dlls/devenum/factory.c b/dlls/devenum/factory.c
deleted file mode 100644
index c808fa5..0000000
--- a/dlls/devenum/factory.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * ClassFactory implementation for DEVENUM.dll
- *
- * Copyright (C) 2002 John K. Hohm
- * Copyright (C) 2002 Robert Shearman
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "devenum_private.h"
-
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(devenum);
-
-/**********************************************************************
- * DEVENUM_IClassFactory_QueryInterface (also IUnknown)
- */
-static HRESULT WINAPI DEVENUM_IClassFactory_QueryInterface(IClassFactory *iface, REFIID riid,
- void **ppvObj)
-{
- TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppvObj);
-
- if (ppvObj == NULL) return E_POINTER;
-
- if (IsEqualGUID(riid, &IID_IUnknown) ||
- IsEqualGUID(riid, &IID_IClassFactory))
- {
- *ppvObj = iface;
- IClassFactory_AddRef(iface);
- return S_OK;
- }
- else if (IsEqualGUID(riid, &IID_IParseDisplayName))
- {
- return IClassFactory_CreateInstance(iface, NULL, riid, ppvObj);
- }
-
- FIXME("- no interface IID: %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
-}
-
-/**********************************************************************
- * DEVENUM_IClassFactory_AddRef (also IUnknown)
- */
-static ULONG WINAPI DEVENUM_IClassFactory_AddRef(IClassFactory *iface)
-{
- TRACE("\n");
-
- DEVENUM_LockModule();
-
- return 2; /* non-heap based object */
-}
-
-/**********************************************************************
- * DEVENUM_IClassFactory_Release (also IUnknown)
- */
-static ULONG WINAPI DEVENUM_IClassFactory_Release(IClassFactory *iface)
-{
- TRACE("\n");
-
- DEVENUM_UnlockModule();
-
- return 1; /* non-heap based object */
-}
-
-/**********************************************************************
- * DEVENUM_IClassFactory_CreateInstance
- */
-static HRESULT WINAPI DEVENUM_IClassFactory_CreateInstance(IClassFactory *iface,
- IUnknown *pUnkOuter, REFIID riid, void **ppvObj)
-{
- TRACE("(%p)->(%p, %s, %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppvObj);
-
- if (ppvObj == NULL) return E_POINTER;
-
- /* Don't support aggregation (Windows doesn't) */
- if (pUnkOuter != NULL) return CLASS_E_NOAGGREGATION;
-
- if (IsEqualGUID(&IID_ICreateDevEnum, riid))
- {
- *ppvObj = &DEVENUM_CreateDevEnum;
- return S_OK;
- }
- if (IsEqualGUID(&IID_IParseDisplayName, riid))
- {
- *ppvObj = &DEVENUM_ParseDisplayName;
- return S_OK;
- }
-
- return CLASS_E_CLASSNOTAVAILABLE;
-}
-
-/**********************************************************************
- * DEVENUM_IClassFactory_LockServer
- */
-static HRESULT WINAPI DEVENUM_IClassFactory_LockServer(IClassFactory *iface, BOOL fLock)
-{
- TRACE("\n");
-
- if (fLock)
- DEVENUM_LockModule();
- else
- DEVENUM_UnlockModule();
- return S_OK;
-}
-
-/**********************************************************************
- * IClassFactory_Vtbl
- */
-static const IClassFactoryVtbl IClassFactory_Vtbl =
-{
- DEVENUM_IClassFactory_QueryInterface,
- DEVENUM_IClassFactory_AddRef,
- DEVENUM_IClassFactory_Release,
- DEVENUM_IClassFactory_CreateInstance,
- DEVENUM_IClassFactory_LockServer
-};
-
-/**********************************************************************
- * static ClassFactory instance
- */
-ClassFactoryImpl DEVENUM_ClassFactory = { { &IClassFactory_Vtbl } };
--
2.7.4
June 26, 2018
[PATCH v2 3/3] comctl32/taskdialog: Add support for command links.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/taskdialog.c | 62 +++++++++++++++++++++++++++++---
dlls/comctl32/tests/taskdialog.c | 61 +++++++++++++++++--------------
2 files changed, 93 insertions(+), 30 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 207f77b012..42d50a93cb 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -60,6 +60,8 @@ struct taskdialog_info
HWND progress_bar;
HWND *radio_buttons;
INT radio_button_count;
+ HWND *command_links;
+ INT command_link_count;
HWND *buttons;
INT button_count;
HWND default_button;
@@ -184,7 +186,8 @@ static HWND taskdialog_find_button(HWND *buttons, INT count, INT id)
static void taskdialog_enable_button(const struct taskdialog_info *dialog_info, INT id, BOOL enable)
{
- HWND hwnd = taskdialog_find_button(dialog_info->buttons, dialog_info->button_count, id);
+ HWND hwnd = taskdialog_find_button(dialog_info->command_links, dialog_info->command_link_count, id);
+ if (!hwnd) hwnd = taskdialog_find_button(dialog_info->buttons, dialog_info->button_count, id);
if (hwnd) EnableWindow(hwnd, enable);
}
@@ -253,6 +256,11 @@ static BOOL taskdialog_hyperlink_enabled(struct taskdialog_info *dialog_info)
return dialog_info->taskconfig->dwFlags & TDF_ENABLE_HYPERLINKS;
}
+static BOOL taskdialog_use_command_link(struct taskdialog_info *dialog_info)
+{
+ return dialog_info->taskconfig->dwFlags & (TDF_USE_COMMAND_LINKS | TDF_USE_COMMAND_LINKS_NO_ICON);
+}
+
static void taskdialog_get_label_size(struct taskdialog_info *dialog_info, HWND hwnd, LONG max_width, SIZE *size,
BOOL syslink)
{
@@ -486,6 +494,34 @@ static void taskdialog_add_radio_buttons(struct taskdialog_info *dialog_info)
}
}
+static void taskdialog_add_command_links(struct taskdialog_info *dialog_info)
+{
+ const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+ DWORD default_style = BS_MULTILINE | BS_LEFT | BS_TOP | WS_CHILD | WS_VISIBLE | WS_TABSTOP, style;
+ BOOL is_default;
+ WCHAR *textW;
+ INT i;
+
+ if (!taskconfig->cButtons || !taskconfig->pButtons || !taskdialog_use_command_link(dialog_info)) return;
+
+ dialog_info->command_links = Alloc(taskconfig->cButtons * sizeof(*dialog_info->command_links));
+ if (!dialog_info->command_links) return;
+
+ dialog_info->command_link_count = taskconfig->cButtons;
+ for (i = 0; i < dialog_info->command_link_count; i++)
+ {
+ is_default = taskconfig->pButtons[i].nButtonID == taskconfig->nDefaultButton;
+ style = is_default ? default_style | BS_DEFCOMMANDLINK : default_style | BS_COMMANDLINK;
+ textW = taskdialog_gettext(dialog_info, TRUE, taskconfig->pButtons[i].pszButtonText);
+ dialog_info->command_links[i] = CreateWindowW(WC_BUTTONW, textW, style, 0, 0, 0, 0, dialog_info->hwnd,
+ (HMENU)taskconfig->pButtons[i].nButtonID, 0, NULL);
+ SendMessageW(dialog_info->command_links[i], WM_SETFONT, (WPARAM)dialog_info->font, 0);
+ Free(textW);
+
+ if (is_default && !dialog_info->default_button) dialog_info->default_button = dialog_info->command_links[i];
+ }
+}
+
static void taskdialog_add_button(struct taskdialog_info *dialog_info, HWND *button, INT_PTR id, const WCHAR *text,
BOOL custom_button)
{
@@ -504,17 +540,18 @@ static void taskdialog_add_button(struct taskdialog_info *dialog_info, HWND *but
static void taskdialog_add_buttons(struct taskdialog_info *dialog_info)
{
const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+ BOOL use_command_links = taskdialog_use_command_link(dialog_info);
DWORD flags = taskconfig->dwCommonButtons;
INT count, max_count;
/* Allocate enough memory for the custom and the default buttons. Maximum 6 default buttons possible. */
max_count = 6;
- if (taskconfig->cButtons && taskconfig->pButtons) max_count += taskconfig->cButtons;
+ if (!use_command_links && taskconfig->cButtons && taskconfig->pButtons) max_count += taskconfig->cButtons;
dialog_info->buttons = Alloc(max_count * sizeof(*dialog_info->buttons));
if (!dialog_info->buttons) return;
- for (count = 0; count < taskconfig->cButtons; count++)
+ for (count = 0; !use_command_links && count < taskconfig->cButtons; count++)
taskdialog_add_button(dialog_info, &dialog_info->buttons[count], taskconfig->pButtons[count].nButtonID,
taskconfig->pButtons[count].pszButtonText, TRUE);
@@ -532,7 +569,7 @@ static void taskdialog_add_buttons(struct taskdialog_info *dialog_info)
if (flags & TDCBF_CANCEL_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(CANCEL);
if (flags & TDCBF_CLOSE_BUTTON) TASKDIALOG_INIT_COMMON_BUTTON(CLOSE);
- if (!count) TASKDIALOG_INIT_COMMON_BUTTON(OK);
+ if (!count && !dialog_info->command_link_count) TASKDIALOG_INIT_COMMON_BUTTON(OK);
#undef TASKDIALOG_INIT_COMMON_BUTTON
dialog_info->button_count = count;
@@ -621,6 +658,19 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
dialog_height = y + size.cy;
}
+ /* Command links */
+ for (i = 0; i < dialog_info->command_link_count; i++)
+ {
+ x = main_icon_right + h_spacing;
+ y = dialog_height + v_spacing;
+ taskdialog_get_label_size(dialog_info, dialog_info->command_links[i], dialog_width - x - h_spacing, &size, FALSE);
+ size.cx = dialog_width - x - h_spacing;
+ /* Add spacing */
+ size.cy += 4;
+ SetWindowPos(dialog_info->command_links[i], 0, x, y, size.cx, size.cy, SWP_NOZORDER);
+ dialog_height = y + size.cy;
+ }
+
dialog_height = max(dialog_height, main_icon_bottom);
/* Common and custom buttons */
@@ -756,9 +806,12 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
taskdialog_add_content(dialog_info);
taskdialog_add_progress_bar(dialog_info);
taskdialog_add_radio_buttons(dialog_info);
+ taskdialog_add_command_links(dialog_info);
taskdialog_add_buttons(dialog_info);
/* Set default button */
+ if (!dialog_info->default_button && dialog_info->command_links)
+ dialog_info->default_button = dialog_info->command_links[0];
if (!dialog_info->default_button) dialog_info->default_button = dialog_info->buttons[0];
SendMessageW(dialog_info->hwnd, WM_NEXTDLGCTL, (WPARAM)dialog_info->default_button, TRUE);
id = GetWindowLongW(dialog_info->default_button, GWLP_ID);
@@ -774,6 +827,7 @@ static void taskdialog_destroy(struct taskdialog_info *dialog_info)
if (dialog_info->main_instruction_font) DeleteObject(dialog_info->main_instruction_font);
if (dialog_info->buttons) Free(dialog_info->buttons);
if (dialog_info->radio_buttons) Free(dialog_info->radio_buttons);
+ if (dialog_info->command_links) Free(dialog_info->command_links);
}
static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
diff --git a/dlls/comctl32/tests/taskdialog.c b/dlls/comctl32/tests/taskdialog.c
index 2cda04081f..33d3757308 100644
--- a/dlls/comctl32/tests/taskdialog.c
+++ b/dlls/comctl32/tests/taskdialog.c
@@ -323,7 +323,7 @@ static void test_callback(void)
static void test_buttons(void)
{
TASKDIALOGCONFIG info = {0};
-
+ static const DWORD command_link_flags[] = {0, TDF_USE_COMMAND_LINKS, TDF_USE_COMMAND_LINKS_NO_ICON};
TASKDIALOG_BUTTON custom_buttons[TEST_NUM_BUTTONS], radio_buttons[TEST_NUM_RADIO_BUTTONS];
const WCHAR button_format[] = {'%','0','2','d',0};
/* Each button has two digits as title, plus null-terminator */
@@ -373,31 +373,40 @@ static void test_buttons(void)
info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_CLOSE_BUTTON;
run_test(&info, IDCANCEL, 0, msg_return_press_cancel, "default button: unset default");
- /* Test with all common and custom buttons and invalid default ID */
- info.nDefaultButton = 0xff; /* Random ID, should also default to first created button */
- info.cButtons = TEST_NUM_BUTTONS;
- info.pButtons = custom_buttons;
- run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, with common buttons - 1");
-
- info.nDefaultButton = -1; /* Should work despite button ID -1 */
- run_test(&info, -1, 0, msg_return_press_custom10, "default button: invalid default, with common buttons - 2");
-
- info.nDefaultButton = -2; /* Should also default to first created button */
- run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, with common buttons - 3");
-
- /* Test with only custom buttons and invalid default ID */
- info.dwCommonButtons = 0;
- run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, no common buttons");
-
- /* Test with common and custom buttons and valid default ID */
- info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
- | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
- info.nDefaultButton = IDRETRY;
- run_test(&info, IDRETRY, 0, msg_return_press_retry, "default button: valid default - 1");
-
- /* Test with common and custom buttons and valid default ID */
- info.nDefaultButton = ID_START_BUTTON + 3;
- run_test(&info, ID_START_BUTTON + 3, 0, msg_return_press_custom4, "default button: valid default - 2");
+ /* Custom buttons could be command links */
+ for (i = 0; i < ARRAY_SIZE(command_link_flags); i++)
+ {
+ info.dwFlags = command_link_flags[i];
+
+ /* Test with all common and custom buttons and invalid default ID */
+ info.nDefaultButton = 0xff; /* Random ID, should also default to first created button */
+ info.cButtons = TEST_NUM_BUTTONS;
+ info.pButtons = custom_buttons;
+ run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1,
+ "default button: invalid default, with common buttons - 1");
+
+ info.nDefaultButton = -1; /* Should work despite button ID -1 */
+ run_test(&info, -1, 0, msg_return_press_custom10, "default button: invalid default, with common buttons - 2");
+
+ info.nDefaultButton = -2; /* Should also default to first created button */
+ run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1,
+ "default button: invalid default, with common buttons - 3");
+
+ /* Test with only custom buttons and invalid default ID */
+ info.dwCommonButtons = 0;
+ run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1,
+ "default button: invalid default, no common buttons");
+
+ /* Test with common and custom buttons and valid default ID */
+ info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON
+ | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
+ info.nDefaultButton = IDRETRY;
+ run_test(&info, IDRETRY, 0, msg_return_press_retry, "default button: valid default - 1");
+
+ /* Test with common and custom buttons and valid default ID */
+ info.nDefaultButton = ID_START_BUTTON + 3;
+ run_test(&info, ID_START_BUTTON + 3, 0, msg_return_press_custom4, "default button: valid default - 2");
+ }
/* Test radio buttons */
info.nDefaultButton = 0;
--
2.17.1
June 26, 2018
[PATCH v2 2/3] comctl32/taskdialog: Add support for radio buttons.
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/taskdialog.c | 139 ++++++++++++++++++++++++-
dlls/comctl32/tests/taskdialog.c | 172 +++++++++++++++++++++++++++----
2 files changed, 290 insertions(+), 21 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 5625f2bc24..207f77b012 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -58,6 +58,8 @@ struct taskdialog_info
HWND main_instruction;
HWND content;
HWND progress_bar;
+ HWND *radio_buttons;
+ INT radio_button_count;
HWND *buttons;
INT button_count;
HWND default_button;
@@ -69,6 +71,7 @@ struct taskdialog_info
LONG h_spacing;
LONG v_spacing;
} m;
+ INT selected_radio_id;
};
struct button_layout_info
@@ -185,6 +188,18 @@ static void taskdialog_enable_button(const struct taskdialog_info *dialog_info,
if (hwnd) EnableWindow(hwnd, enable);
}
+static void taskdialog_enable_radio_button(const struct taskdialog_info *dialog_info, INT id, BOOL enable)
+{
+ HWND hwnd = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count, id);
+ if (hwnd) EnableWindow(hwnd, enable);
+}
+
+static void taskdialog_click_radio_button(const struct taskdialog_info *dialog_info, INT id)
+{
+ HWND hwnd = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count, id);
+ if (hwnd) SendMessageW(hwnd, BM_CLICK, 0, 0);
+}
+
static HRESULT taskdialog_notify(struct taskdialog_info *dialog_info, UINT notification, WPARAM wparam, LPARAM lparam)
{
const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
@@ -193,8 +208,18 @@ static HRESULT taskdialog_notify(struct taskdialog_info *dialog_info, UINT notif
: S_OK;
}
-static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, WORD command_id)
+static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, INT command_id)
{
+ HWND radio_button;
+
+ radio_button = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count, command_id);
+ if (radio_button)
+ {
+ dialog_info->selected_radio_id = command_id;
+ taskdialog_notify(dialog_info, TDN_RADIO_BUTTON_CLICKED, command_id, 0);
+ return;
+ }
+
if (taskdialog_notify(dialog_info, TDN_BUTTON_CLICKED, command_id, 0) == S_OK)
EndDialog(dialog_info->hwnd, command_id);
}
@@ -269,6 +294,49 @@ static void taskdialog_get_label_size(struct taskdialog_info *dialog_info, HWND
Free(text);
}
+static void taskdialog_get_radio_button_size(struct taskdialog_info *dialog_info, HWND hwnd, LONG max_width, SIZE *size)
+{
+ DWORD style = DT_EXPANDTABS | DT_CALCRECT | DT_WORDBREAK;
+ HFONT hfont, old_hfont;
+ HDC hdc;
+ RECT rect = {0};
+ INT text_length;
+ WCHAR *text;
+ INT text_offset, radio_box_width, radio_box_height;
+
+ hdc = GetDC(hwnd);
+ hfont = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0);
+ old_hfont = SelectObject(hdc, hfont);
+
+ radio_box_width = 12 * GetDeviceCaps(hdc, LOGPIXELSX) / 96 + 1;
+ radio_box_height = 12 * GetDeviceCaps(hdc, LOGPIXELSY) / 96 + 1;
+ GetCharWidthW(hdc, '0', '0', &text_offset);
+ text_offset /= 2;
+
+ if (dialog_info->taskconfig->dwFlags & TDF_RTL_LAYOUT)
+ style |= DT_RIGHT | DT_RTLREADING;
+ else
+ style |= DT_LEFT;
+
+ rect.right = max_width - radio_box_width - text_offset;
+ text_length = GetWindowTextLengthW(hwnd);
+ text = Alloc((text_length + 1) * sizeof(WCHAR));
+ if (!text)
+ {
+ size->cx = 0;
+ size->cy = 0;
+ return;
+ }
+ GetWindowTextW(hwnd, text, text_length + 1);
+ size->cy = DrawTextW(hdc, text, text_length, &rect, style);
+ size->cx = min(max_width - radio_box_width - text_offset, rect.right - rect.left);
+ size->cx += radio_box_width + text_offset;
+ size->cy = max(size->cy, radio_box_height);
+ if (old_hfont) SelectObject(hdc, old_hfont);
+ Free(text);
+ ReleaseDC(hwnd, hdc);
+}
+
static ULONG_PTR taskdialog_get_standard_icon(LPCWSTR icon)
{
if (icon == TD_WARNING_ICON)
@@ -309,6 +377,28 @@ static void taskdialog_set_icon(struct taskdialog_info *dialog_info, INT element
}
}
+static void taskdialog_check_default_radio_buttons(struct taskdialog_info *dialog_info)
+{
+ const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+ HWND default_button;
+ INT id;
+
+ if (!dialog_info->radio_button_count) return;
+
+ default_button = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count,
+ taskconfig->nDefaultRadioButton);
+
+ if (!default_button && !(taskconfig->dwFlags & TDF_NO_DEFAULT_RADIO_BUTTON))
+ default_button = dialog_info->radio_buttons[0];
+
+ if (default_button)
+ {
+ SendMessageW(default_button, BM_SETCHECK, BST_CHECKED, 0);
+ id = GetWindowLongW(default_button, GWLP_ID);
+ taskdialog_on_button_click(dialog_info, id);
+ }
+}
+
static void taskdialog_add_main_icon(struct taskdialog_info *dialog_info)
{
if (!dialog_info->taskconfig->u.hMainIcon) return;
@@ -372,6 +462,30 @@ static void taskdialog_add_progress_bar(struct taskdialog_info *dialog_info)
CreateWindowW(PROGRESS_CLASSW, NULL, style, 0, 0, 0, 0, dialog_info->hwnd, NULL, 0, NULL);
}
+static void taskdialog_add_radio_buttons(struct taskdialog_info *dialog_info)
+{
+ const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
+ static const DWORD style = BS_AUTORADIOBUTTON | BS_MULTILINE | BS_TOP | WS_CHILD | WS_VISIBLE | WS_TABSTOP;
+ WCHAR *textW;
+ INT i;
+
+ if (!taskconfig->cRadioButtons || !taskconfig->pRadioButtons) return;
+
+ dialog_info->radio_buttons = Alloc(taskconfig->cRadioButtons * sizeof(*dialog_info->radio_buttons));
+ if (!dialog_info->radio_buttons) return;
+
+ dialog_info->radio_button_count = taskconfig->cRadioButtons;
+ for (i = 0; i < dialog_info->radio_button_count; i++)
+ {
+ textW = taskdialog_gettext(dialog_info, TRUE, taskconfig->pRadioButtons[i].pszButtonText);
+ dialog_info->radio_buttons[i] =
+ CreateWindowW(WC_BUTTONW, textW, i == 0 ? style | WS_GROUP : style, 0, 0, 0, 0, dialog_info->hwnd,
+ (HMENU)taskconfig->pRadioButtons[i].nButtonID, 0, NULL);
+ SendMessageW(dialog_info->radio_buttons[i], WM_SETFONT, (WPARAM)dialog_info->font, 0);
+ Free(textW);
+ }
+}
+
static void taskdialog_add_button(struct taskdialog_info *dialog_info, HWND *button, INT_PTR id, const WCHAR *text,
BOOL custom_button)
{
@@ -496,6 +610,17 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
dialog_height = y + size.cy;
}
+ /* Radio buttons */
+ for (i = 0; i < dialog_info->radio_button_count; i++)
+ {
+ x = main_icon_right + h_spacing;
+ y = dialog_height;
+ taskdialog_get_radio_button_size(dialog_info, dialog_info->radio_buttons[i], dialog_width - x - h_spacing, &size);
+ size.cx = dialog_width - x - h_spacing;
+ SetWindowPos(dialog_info->radio_buttons[i], 0, x, y, size.cx, size.cy, SWP_NOZORDER);
+ dialog_height = y + size.cy;
+ }
+
dialog_height = max(dialog_height, main_icon_bottom);
/* Common and custom buttons */
@@ -630,6 +755,7 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
taskdialog_add_main_instruction(dialog_info);
taskdialog_add_content(dialog_info);
taskdialog_add_progress_bar(dialog_info);
+ taskdialog_add_radio_buttons(dialog_info);
taskdialog_add_buttons(dialog_info);
/* Set default button */
@@ -647,6 +773,7 @@ static void taskdialog_destroy(struct taskdialog_info *dialog_info)
if (dialog_info->font) DeleteObject(dialog_info->font);
if (dialog_info->main_instruction_font) DeleteObject(dialog_info->main_instruction_font);
if (dialog_info->buttons) Free(dialog_info->buttons);
+ if (dialog_info->radio_buttons) Free(dialog_info->radio_buttons);
}
static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -698,6 +825,12 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
case TDM_SET_PROGRESS_BAR_MARQUEE:
SendMessageW(dialog_info->progress_bar, PBM_SETMARQUEE, wParam, lParam);
break;
+ case TDM_CLICK_RADIO_BUTTON:
+ taskdialog_click_radio_button(dialog_info, wParam);
+ break;
+ case TDM_ENABLE_RADIO_BUTTON:
+ taskdialog_enable_radio_button(dialog_info, wParam, lParam);
+ break;
case WM_INITDIALOG:
dialog_info = (struct taskdialog_info *)lParam;
@@ -706,6 +839,8 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
SetPropW(hwnd, taskdialog_info_propnameW, dialog_info);
taskdialog_notify(dialog_info, TDN_DIALOG_CONSTRUCTED, 0, 0);
taskdialog_notify(dialog_info, TDN_CREATED, 0, 0);
+ /* Default radio button click notification sent after TDN_CREATED */
+ taskdialog_check_default_radio_buttons(dialog_info);
return FALSE;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
@@ -771,7 +906,7 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *taskconfig, int *butto
Free(template);
if (button) *button = ret;
- if (radio_button) *radio_button = taskconfig->nDefaultButton;
+ if (radio_button) *radio_button = dialog_info.selected_radio_id;
if (verification_flag_checked) *verification_flag_checked = TRUE;
return S_OK;
diff --git a/dlls/comctl32/tests/taskdialog.c b/dlls/comctl32/tests/taskdialog.c
index e91a878876..2cda04081f 100644
--- a/dlls/comctl32/tests/taskdialog.c
+++ b/dlls/comctl32/tests/taskdialog.c
@@ -35,9 +35,11 @@
#define TASKDIALOG_SEQ_INDEX 0
#define TEST_NUM_BUTTONS 10 /* Number of custom buttons to test with */
+#define TEST_NUM_RADIO_BUTTONS 3
#define ID_START 20 /* Lower IDs might be used by the system */
#define ID_START_BUTTON (ID_START + 0)
+#define ID_START_RADIO_BUTTON (ID_START + 20)
static HRESULT (WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *, int *, int *, BOOL *);
static HRESULT (WINAPI *pTaskDialog)(HWND, HINSTANCE, const WCHAR *, const WCHAR *, const WCHAR *,
@@ -141,6 +143,78 @@ static const struct message_info msg_got_tdn_help[] =
{ 0 }
};
+/* Three radio buttons */
+static const struct message_info msg_return_default_radio_button_1[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_default_radio_button_2[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_default_radio_button_3[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, -2, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_select_first_radio_button[] =
+{
+ { TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
+ { 0 }
+};
+
+static const struct message_info msg_return_first_radio_button[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_select_first_radio_button },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_select_first_disabled_radio_button_and_press_ok[] =
+{
+ { TDM_ENABLE_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
+ { TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
+ { TDM_CLICK_BUTTON, IDOK, 0 },
+ { 0 }
+};
+
+static const struct message_info msg_return_default_radio_button_clicking_disabled[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_select_first_disabled_radio_button_and_press_ok },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_no_default_radio_button_flag[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_no_default_radio_button_id_and_flag[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct message *msg)
{
msg->message = WM_TD_CALLBACK;
@@ -151,11 +225,13 @@ static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct
msg->stage = 0;
}
-#define run_test(info, expect_button, seq, context) \
- run_test_(info, expect_button, seq, context, ARRAY_SIZE(seq) - 1, __FILE__, __LINE__)
+#define run_test(info, expect_button, expect_radio_button, seq, context) \
+ run_test_(info, expect_button, expect_radio_button, seq, context, \
+ ARRAY_SIZE(seq) - 1, __FILE__, __LINE__)
-static void run_test_(TASKDIALOGCONFIG *info, int expect_button, const struct message_info *test_messages,
- const char *context, int test_messages_len, const char *file, int line)
+static void run_test_(TASKDIALOGCONFIG *info, int expect_button, int expect_radio_button,
+ const struct message_info *test_messages, const char *context, int test_messages_len,
+ const char *file, int line)
{
struct message *msg, *msg_start;
int ret_button = 0;
@@ -182,6 +258,8 @@ static void run_test_(TASKDIALOGCONFIG *info, int expect_button, const struct me
ok_sequence_(sequences, TASKDIALOG_SEQ_INDEX, msg_start, context, FALSE, file, line);
ok_(file, line)(ret_button == expect_button,
"Wrong button. Expected %d, got %d\n", expect_button, ret_button);
+ ok_(file, line)(ret_radio == expect_radio_button,
+ "Wrong radio button. Expected %d, got %d\n", expect_radio_button, ret_radio);
heap_free(msg_start);
}
@@ -239,16 +317,17 @@ static void test_callback(void)
info.pfCallback = taskdialog_callback_proc;
info.lpCallbackData = test_ref_data;
- run_test(&info, IDOK, msg_return_press_ok, "Press VK_RETURN.");
+ run_test(&info, IDOK, 0, msg_return_press_ok, "Press VK_RETURN.");
}
static void test_buttons(void)
{
TASKDIALOGCONFIG info = {0};
- TASKDIALOG_BUTTON custom_buttons[TEST_NUM_BUTTONS];
+ TASKDIALOG_BUTTON custom_buttons[TEST_NUM_BUTTONS], radio_buttons[TEST_NUM_RADIO_BUTTONS];
const WCHAR button_format[] = {'%','0','2','d',0};
- WCHAR button_titles[TEST_NUM_BUTTONS * 3]; /* Each button has two digits as title, plus null-terminator */
+ /* Each button has two digits as title, plus null-terminator */
+ WCHAR button_titles[TEST_NUM_BUTTONS * 3], radio_button_titles[TEST_NUM_BUTTONS * 3];
int i;
info.cbSize = sizeof(TASKDIALOGCONFIG);
@@ -266,48 +345,103 @@ static void test_buttons(void)
}
custom_buttons[TEST_NUM_BUTTONS - 1].nButtonID = -1;
+ /* Init radio buttons */
+ for (i = 0; i < TEST_NUM_RADIO_BUTTONS; i++)
+ {
+ WCHAR *text = &radio_button_titles[i * 3];
+ wsprintfW(text, button_format, i);
+
+ radio_buttons[i].pszButtonText = text;
+ radio_buttons[i].nButtonID = ID_START_RADIO_BUTTON + i;
+ }
+ radio_buttons[TEST_NUM_RADIO_BUTTONS - 1].nButtonID = -2;
+
/* Test nDefaultButton */
/* Test common buttons with invalid default ID */
info.nDefaultButton = 0; /* Should default to first created button */
info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
| TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
- run_test(&info, IDOK, msg_return_press_ok, "default button: unset default");
+ run_test(&info, IDOK, 0, msg_return_press_ok, "default button: unset default");
info.dwCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
| TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
- run_test(&info, IDYES, msg_return_press_yes, "default button: unset default");
+ run_test(&info, IDYES, 0, msg_return_press_yes, "default button: unset default");
info.dwCommonButtons = TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
- run_test(&info, IDNO, msg_return_press_no, "default button: unset default");
+ run_test(&info, IDNO, 0, msg_return_press_no, "default button: unset default");
info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
- run_test(&info, IDRETRY, msg_return_press_retry, "default button: unset default");
+ run_test(&info, IDRETRY, 0, msg_return_press_retry, "default button: unset default");
info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_CLOSE_BUTTON;
- run_test(&info, IDCANCEL, msg_return_press_cancel, "default button: unset default");
+ run_test(&info, IDCANCEL, 0, msg_return_press_cancel, "default button: unset default");
/* Test with all common and custom buttons and invalid default ID */
info.nDefaultButton = 0xff; /* Random ID, should also default to first created button */
info.cButtons = TEST_NUM_BUTTONS;
info.pButtons = custom_buttons;
- run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button: invalid default, with common buttons - 1");
+ run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, with common buttons - 1");
info.nDefaultButton = -1; /* Should work despite button ID -1 */
- run_test(&info, -1, msg_return_press_custom10, "default button: invalid default, with common buttons - 2");
+ run_test(&info, -1, 0, msg_return_press_custom10, "default button: invalid default, with common buttons - 2");
info.nDefaultButton = -2; /* Should also default to first created button */
- run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button: invalid default, with common buttons - 3");
+ run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, with common buttons - 3");
/* Test with only custom buttons and invalid default ID */
info.dwCommonButtons = 0;
- run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button: invalid default, no common buttons");
+ run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, no common buttons");
/* Test with common and custom buttons and valid default ID */
info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
| TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
info.nDefaultButton = IDRETRY;
- run_test(&info, IDRETRY, msg_return_press_retry, "default button: valid default - 1");
+ run_test(&info, IDRETRY, 0, msg_return_press_retry, "default button: valid default - 1");
/* Test with common and custom buttons and valid default ID */
info.nDefaultButton = ID_START_BUTTON + 3;
- run_test(&info, ID_START_BUTTON + 3, msg_return_press_custom4, "default button: valid default - 2");
+ run_test(&info, ID_START_BUTTON + 3, 0, msg_return_press_custom4, "default button: valid default - 2");
+
+ /* Test radio buttons */
+ info.nDefaultButton = 0;
+ info.cButtons = 0;
+ info.pButtons = 0;
+ info.dwCommonButtons = TDCBF_OK_BUTTON;
+ info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
+ info.pRadioButtons = radio_buttons;
+
+ /* Test default first radio button */
+ run_test(&info, IDOK, ID_START_RADIO_BUTTON, msg_return_default_radio_button_1, "default radio button: default first radio button");
+
+ /* Test default radio button */
+ info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
+ run_test(&info, IDOK, info.nDefaultRadioButton, msg_return_default_radio_button_2, "default radio button: default radio button");
+
+ /* Test default radio button with -2 */
+ info.nDefaultRadioButton = -2;
+ run_test(&info, IDOK, info.nDefaultRadioButton, msg_return_default_radio_button_3, "default radio button: default radio button with id -2");
+
+ /* Test default radio button after clicking the first, messages still work even radio button is disabled */
+ info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
+ run_test(&info, IDOK, ID_START_RADIO_BUTTON, msg_return_first_radio_button, "default radio button: radio button after clicking");
+
+ /* Test radio button after disabling and clicking the first */
+ info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
+ run_test(&info, IDOK, ID_START_RADIO_BUTTON, msg_return_default_radio_button_clicking_disabled, "default radio button: disable radio button before clicking");
+
+ /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set, TDN_RADIO_BUTTON_CLICKED will still be received, just radio button not selected */
+ info.nDefaultRadioButton = ID_START_RADIO_BUTTON;
+ info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
+ run_test(&info, IDOK, info.nDefaultRadioButton, msg_return_no_default_radio_button_flag, "default radio button: no default radio flag");
+
+ /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and nDefaultRadioButton is 0.
+ * TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
+ info.nDefaultRadioButton = 0;
+ info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
+ run_test(&info, IDOK, 0, msg_return_no_default_radio_button_id_and_flag, "default radio button: no default radio id and flag");
+
+ /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and nDefaultRadioButton is invalid.
+ * TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
+ info.nDefaultRadioButton = 0xff;
+ info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
+ run_test(&info, IDOK, 0, msg_return_no_default_radio_button_id_and_flag, "default radio button: no default flag, invalid id");
}
static void test_help(void)
@@ -319,7 +453,7 @@ static void test_help(void)
info.lpCallbackData = test_ref_data;
info.dwCommonButtons = TDCBF_OK_BUTTON;
- run_test(&info, IDOK, msg_got_tdn_help, "send f1");
+ run_test(&info, IDOK, 0, msg_got_tdn_help, "send f1");
}
struct timer_notification_data
--
2.17.1
June 26, 2018
[PATCH v2 1/3] comctl32/taskdialog: Use dynamic buffer for taskdialog_get_label_size().
by Zhiyi Zhang
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/comctl32/taskdialog.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
index 33fb578910..5625f2bc24 100644
--- a/dlls/comctl32/taskdialog.c
+++ b/dlls/comctl32/taskdialog.c
@@ -235,7 +235,7 @@ static void taskdialog_get_label_size(struct taskdialog_info *dialog_info, HWND
HFONT hfont, old_hfont;
HDC hdc;
RECT rect = {0};
- WCHAR text[1024];
+ WCHAR *text;
INT text_length;
if (syslink)
@@ -250,7 +250,15 @@ static void taskdialog_get_label_size(struct taskdialog_info *dialog_info, HWND
style |= DT_LEFT;
hfont = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0);
- text_length = GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ text_length = GetWindowTextLengthW(hwnd);
+ text = Alloc((text_length + 1) * sizeof(WCHAR));
+ if (!text)
+ {
+ size->cx = 0;
+ size->cy = 0;
+ return;
+ }
+ GetWindowTextW(hwnd, text, text_length + 1);
hdc = GetDC(hwnd);
old_hfont = SelectObject(hdc, hfont);
rect.right = max_width;
@@ -258,6 +266,7 @@ static void taskdialog_get_label_size(struct taskdialog_info *dialog_info, HWND
size->cx = min(max_width, rect.right - rect.left);
if (old_hfont) SelectObject(hdc, old_hfont);
ReleaseDC(hwnd, hdc);
+ Free(text);
}
static ULONG_PTR taskdialog_get_standard_icon(LPCWSTR icon)
--
2.17.1
June 26, 2018
Re: [PATCH v2 4/4] winemac.drv: Implement waking up the display when activity occurs.
by Ken Thomases
This prevents display sleep and/or wakes a sleeping display, but doesn't prevent the screensaver from kicking in. We don't know why and don't see any other suitable API, so:
Signed-off-by: Ken Thomases <ken(a)codeweavers.com>
June 25, 2018
[PATCH 3/3] wsdapi: Send Probe Matches message via UDP unicast.
by Owen Rudge
Signed-off-by: Owen Rudge <orudge(a)codeweavers.com>
---
dlls/wsdapi/network.c | 32 ++++++++++++++++++++++++++++++++
dlls/wsdapi/soap.c | 4 ++--
dlls/wsdapi/tests/discovery.c | 22 +++++++++++-----------
dlls/wsdapi/wsdapi_internal.h | 1 +
4 files changed, 46 insertions(+), 13 deletions(-)
June 25, 2018
[PATCH 2/3] wsdapi: Implement generation of ProbeMatches message.
by Owen Rudge
Signed-off-by: Owen Rudge <orudge(a)codeweavers.com>
---
dlls/wsdapi/soap.c | 169
+++++++++++++++++++++++++++++++++++++++++-
dlls/wsdapi/tests/discovery.c | 2 +-
2 files changed, 169 insertions(+), 2 deletions(-)
June 25, 2018
[PATCH 1/3] wsdapi: Implement matching of names in MatchProbeEx.
by Owen Rudge
Signed-off-by: Owen Rudge <orudge(a)codeweavers.com>
---
dlls/wsdapi/discovery.c | 58
++++++++++++++++++++++++++++++++++++++++---
dlls/wsdapi/soap.c | 9 +++++++
dlls/wsdapi/wsdapi_internal.h | 6 +++++
3 files changed, 69 insertions(+), 4 deletions(-)
June 25, 2018
wine-3.0.2-rc3 Available
by Michael Stefaniuc
Hello guys,
I have pushed wine-3.0.2-rc3 (with tag) to
https://github.com/mstefani/wine-stable/tree/stable
http://static-winehq.193b.starter-ca-central-1.openshiftapps.com/stable/
Changes since rc2:
- Added "ddraw: Fix D3DEXECUTEDATA.dwSize handling." as that is a
dependency for "ddraw: Don't read past the end of the executebuffer."
bye
michael
June 25, 2018
Re: [PATCH v2] hnetcfg: Store the full path in INetFwAuthorizedApplication_put_ProcessImageFileName().
by Zebediah Figura
On 25/06/18 15:09, Alexandre Julliard wrote:
> Zebediah Figura <z.figura12(a)gmail.com> writes:
>
>> Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
>> ---
>> dlls/hnetcfg/apps.c | 17 ++++++++++++-----
>> dlls/hnetcfg/tests/policy.c | 5 ++++-
>> 2 files changed, 16 insertions(+), 6 deletions(-)
>
> It doesn't work here:
>
> ../../../tools/runtest -q -P wine -T ../../.. -M hnetcfg.dll -p hnetcfg_test.exe.so policy && touch policy.ok
> 0009:err:seh:raise_exception Unhandled exception code c0000005 flags 0 addr 0x7bc4ed69
> Makefile:183: recipe for target 'policy.ok' failed
>
Sorry I'm so sloppy today. Updated version sent.
June 25, 2018
[PATCH v3] hnetcfg: Store the full path in INetFwAuthorizedApplication_put_ProcessImageFileName().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/hnetcfg/apps.c | 17 ++++++++++++-----
dlls/hnetcfg/tests/policy.c | 5 ++++-
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/dlls/hnetcfg/apps.c b/dlls/hnetcfg/apps.c
index 34ef108..69eabd6 100644
--- a/dlls/hnetcfg/apps.c
+++ b/dlls/hnetcfg/apps.c
@@ -268,7 +268,7 @@ static HRESULT WINAPI fw_app_put_ProcessImageFileName(
{
fw_app *This = impl_from_INetFwAuthorizedApplication( iface );
UNIVERSAL_NAME_INFOW *info;
- WCHAR *netpath;
+ WCHAR *path;
DWORD res;
DWORD sz;
@@ -281,22 +281,29 @@ static HRESULT WINAPI fw_app_put_ProcessImageFileName(
res = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL, NULL, &sz);
if (res == WN_MORE_DATA)
{
- if (!(netpath = heap_alloc(sz)))
+ if (!(path = heap_alloc(sz)))
return E_OUTOFMEMORY;
- info = (UNIVERSAL_NAME_INFOW *)&netpath;
+ info = (UNIVERSAL_NAME_INFOW *)&path;
res = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL, &info, &sz);
if (res == NO_ERROR)
{
SysFreeString(This->filename);
This->filename = SysAllocString(info->lpUniversalName);
}
- heap_free(netpath);
+ heap_free(path);
return HRESULT_FROM_WIN32(res);
}
+ sz = GetFullPathNameW(image, 0, NULL, NULL);
+ if (!(path = heap_alloc(++sz * sizeof(WCHAR))))
+ return E_OUTOFMEMORY;
+
+ GetFullPathNameW(image, sz, path, NULL);
+
SysFreeString( This->filename );
- This->filename = SysAllocString(image);
+ This->filename = SysAllocString(path);
+ heap_free(path);
return This->filename ? S_OK : E_OUTOFMEMORY;
}
diff --git a/dlls/hnetcfg/tests/policy.c b/dlls/hnetcfg/tests/policy.c
index f2d1372..954af5c 100644
--- a/dlls/hnetcfg/tests/policy.c
+++ b/dlls/hnetcfg/tests/policy.c
@@ -107,6 +107,7 @@ static void test_NetFwAuthorizedApplication(void)
INetFwAuthorizedApplication *app;
static WCHAR empty[] = {0};
UNIVERSAL_NAME_INFOW *info;
+ WCHAR fullpath[MAX_PATH];
WCHAR netpath[MAX_PATH];
WCHAR image[MAX_PATH];
HRESULT hr;
@@ -138,13 +139,15 @@ static void test_NetFwAuthorizedApplication(void)
ok(hr == S_OK, "got: %08x\n", hr);
SysFreeString(bstr);
+ GetFullPathNameW(image, ARRAY_SIZE(fullpath), fullpath, NULL);
+
info = (UNIVERSAL_NAME_INFOW *)&netpath;
sz = sizeof(netpath);
hr = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL, &info, &sz);
if (hr != NO_ERROR)
{
info->lpUniversalName = netpath + sizeof(*info)/sizeof(WCHAR);
- lstrcpyW(info->lpUniversalName, image);
+ lstrcpyW(info->lpUniversalName, fullpath);
}
hr = INetFwAuthorizedApplication_get_ProcessImageFileName(app, &bstr);
--
2.7.4
June 25, 2018
Re: [PATCH v2] hnetcfg: Store the full path in INetFwAuthorizedApplication_put_ProcessImageFileName().
by Alexandre Julliard
Zebediah Figura <z.figura12(a)gmail.com> writes:
> Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
> ---
> dlls/hnetcfg/apps.c | 17 ++++++++++++-----
> dlls/hnetcfg/tests/policy.c | 5 ++++-
> 2 files changed, 16 insertions(+), 6 deletions(-)
It doesn't work here:
../../../tools/runtest -q -P wine -T ../../.. -M hnetcfg.dll -p hnetcfg_test.exe.so policy && touch policy.ok
0009:err:seh:raise_exception Unhandled exception code c0000005 flags 0 addr 0x7bc4ed69
Makefile:183: recipe for target 'policy.ok' failed
--
Alexandre Julliard
julliard(a)winehq.org
June 25, 2018
[PATCH v2 4/4] winemac.drv: Implement waking up the display when activity occurs.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winemac.drv/macdrv_main.c | 12 ++++++++++++
dlls/winemac.drv/winemac.drv.spec | 3 +++
2 files changed, 15 insertions(+)
diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c
index 491ab06..ea0beec 100644
--- a/dlls/winemac.drv/macdrv_main.c
+++ b/dlls/winemac.drv/macdrv_main.c
@@ -451,3 +451,15 @@ BOOL CDECL macdrv_SystemParametersInfo( UINT action, UINT int_param, void *ptr_p
}
return FALSE;
}
+
+/***********************************************************************
+ * wine_notify_activity (MACDRV.@)
+ *
+ * Notify the display server that activity has occurred, e.g. to wake up
+ * the display and reset any power management related timeouts.
+ */
+void CDECL macdrv_notify_activity(void)
+{
+ static IOPMAssertionID assertion;
+ IOPMAssertionDeclareUserActivity(CFSTR("Wine user input"), kIOPMUserActiveLocal, &assertion);
+}
diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec
index 6fa723a..9658fad 100644
--- a/dlls/winemac.drv/winemac.drv.spec
+++ b/dlls/winemac.drv/winemac.drv.spec
@@ -45,6 +45,9 @@
@ cdecl WindowPosChanged(long long long ptr ptr ptr ptr ptr) macdrv_WindowPosChanged
@ cdecl WindowPosChanging(long long long ptr ptr ptr ptr) macdrv_WindowPosChanging
+# Desktop
+@ cdecl wine_notify_activity() macdrv_notify_activity
+
# System tray
@ cdecl wine_notify_icon(long ptr)
--
2.7.4
June 25, 2018
[PATCH v2 3/4] winex11.drv: Implement waking up the display when activity occurs.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/winex11.drv/winex11.drv.spec | 1 +
dlls/winex11.drv/x11drv_main.c | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec
index 614f0b9..c833edb 100644
--- a/dlls/winex11.drv/winex11.drv.spec
+++ b/dlls/winex11.drv/winex11.drv.spec
@@ -57,6 +57,7 @@
# Desktop
@ cdecl wine_create_desktop(long long) X11DRV_create_desktop
+@ cdecl wine_notify_activity() X11DRV_notify_activity
# System tray
@ cdecl wine_notify_icon(long ptr)
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index 4654556..0dbd4f6 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -739,3 +739,15 @@ BOOL CDECL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_p
}
return FALSE; /* let user32 handle it */
}
+
+/***********************************************************************
+ * wine_notify_activity (X11DRV.@)
+ *
+ * Notify the display server that activity has occurred, e.g. to wake up
+ * the display and reset any power management related timeouts.
+ */
+void CDECL X11DRV_notify_activity(void)
+{
+ XResetScreenSaver( gdi_display );
+ XFlush( gdi_display );
+}
--
2.7.4
June 25, 2018
[PATCH v2 2/4] dinput: Notify the desktop window when device input is received.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/dinput/device.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 7b83a39..daa6406 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -39,6 +39,8 @@
#include "device_private.h"
#include "dinput_private.h"
+#define WM_WINE_NOTIFY_ACTIVITY WM_USER
+
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
static inline IDirectInputDeviceImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
@@ -935,6 +937,8 @@ void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD tim
/* Event is being set regardless of the queue state */
if (This->hEvent) SetEvent(This->hEvent);
+ SendMessageW(GetDesktopWindow(), WM_WINE_NOTIFY_ACTIVITY, 0, 0);
+
if (!This->queue_len || This->overflow || ofs < 0) return;
next_pos = (This->queue_head + 1) % This->queue_len;
--
2.7.4
June 25, 2018
[PATCH v2 1/4] explorer: Add a private message to notify the graphics driver when activity occurs.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
programs/explorer/desktop.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c
index a2d9e1a..f5a01c2 100644
--- a/programs/explorer/desktop.c
+++ b/programs/explorer/desktop.c
@@ -46,6 +46,10 @@ static const WCHAR default_driver[] = {'m','a','c',',','x','1','1',0};
static const WCHAR default_driver[] = {'x','1','1',0};
#endif
+static void (CDECL *wine_notify_activity)(void);
+
+#define WM_WINE_NOTIFY_ACTIVITY WM_USER
+
static BOOL using_root;
struct launcher
@@ -661,6 +665,11 @@ static LRESULT WINAPI desktop_wnd_proc( HWND hwnd, UINT message, WPARAM wp, LPAR
}
return 0;
+ case WM_WINE_NOTIFY_ACTIVITY:
+ if (wine_notify_activity)
+ wine_notify_activity();
+ return 0;
+
default:
return DefWindowProcW( hwnd, message, wp, lp );
}
@@ -1005,6 +1014,8 @@ void manage_desktop( WCHAR *arg )
{
pShellDDEInit( TRUE );
}
+
+ wine_notify_activity = (void *)GetProcAddress( graphics_driver, "wine_notify_activity" );
}
}
--
2.7.4
June 25, 2018
[PATCH] gdi32/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/gdi32/tests/bitmap.c | 10 ++++-----
dlls/gdi32/tests/brush.c | 2 +-
dlls/gdi32/tests/dc.c | 6 +++---
dlls/gdi32/tests/dib.c | 38 ++++++++++++++++-----------------
dlls/gdi32/tests/font.c | 52 ++++++++++++++++++++++-----------------------
dlls/gdi32/tests/gdiobj.c | 2 +-
dlls/gdi32/tests/icm.c | 2 +-
dlls/gdi32/tests/metafile.c | 7 +++---
dlls/gdi32/tests/path.c | 14 ++++++------
dlls/gdi32/tests/pen.c | 2 +-
10 files changed, 67 insertions(+), 68 deletions(-)
diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c
index a4002c83b5..4748691791 100644
--- a/dlls/gdi32/tests/bitmap.c
+++ b/dlls/gdi32/tests/bitmap.c
@@ -84,7 +84,7 @@ static void test_bitmap_info(HBITMAP hbm, INT expected_depth, const BITMAPINFOHE
SetLastError(0xdeadbeef);
test_size[0] = bm.bmWidthBytes * bm.bmHeight;
/* NULL output buffer with different count values */
- for (i = 0; i < sizeof(test_size) / sizeof(test_size[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(test_size); i++)
{
ret = GetBitmapBits(hbm, test_size[i], NULL);
ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
@@ -94,7 +94,7 @@ static void test_bitmap_info(HBITMAP hbm, INT expected_depth, const BITMAPINFOHE
memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight);
/* Correct output buffer with different count values */
- for (i = 0; i < sizeof(test_size) / sizeof(test_size[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(test_size); i++)
{
int expect = i == 1 ? 0 : bm.bmWidthBytes * bm.bmHeight;
memset(buf, 0xAA, sizeof(buf));
@@ -1745,7 +1745,7 @@ static void test_mono_bitmap(void)
SelectObject( hdc, hbmp );
- for (col = 0; col < sizeof(colors) / sizeof(colors[0]); col++)
+ for (col = 0; col < ARRAY_SIZE(colors); col++)
{
SetTextColor( hdc, colors[col][0] );
SetBkColor( hdc, colors[col][1] );
@@ -2690,7 +2690,7 @@ static void test_select_object(void)
DeleteObject(hbm);
- for(i = 0; i < sizeof(depths)/sizeof(depths[0]); i++) {
+ for(i = 0; i < ARRAY_SIZE(depths); i++) {
/* test a color bitmap to dc bpp matching */
planes = GetDeviceCaps(hdc, PLANES);
bpp = GetDeviceCaps(hdc, BITSPIXEL);
@@ -5710,7 +5710,7 @@ static void test_D3DKMTCreateDCFromMemory( void )
status = pD3DKMTCreateDCFromMemory( NULL );
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status);
- for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
+ for (i = 0; i < ARRAY_SIZE(test_data); ++i)
{
memset( data, 0xaa, sizeof(data) );
diff --git a/dlls/gdi32/tests/brush.c b/dlls/gdi32/tests/brush.c
index 1a10429c05..a3ebb91e1e 100644
--- a/dlls/gdi32/tests/brush.c
+++ b/dlls/gdi32/tests/brush.c
@@ -48,7 +48,7 @@ static void test_solidbrush(void)
size_t i;
INT ret;
- for(i=0; i<sizeof(stock)/sizeof(stock[0]); i++) {
+ for(i = 0; i < ARRAY_SIZE(stock); i++) {
solidBrush = CreateSolidBrush(stock[i].color);
if(stock[i].stockobj != -1) {
diff --git a/dlls/gdi32/tests/dc.c b/dlls/gdi32/tests/dc.c
index 3c1fa603a6..5ad3b31483 100644
--- a/dlls/gdi32/tests/dc.c
+++ b/dlls/gdi32/tests/dc.c
@@ -361,7 +361,7 @@ static void test_device_caps( HDC hdc, HDC ref_dc, const char *descr, int scale
if (GetObjectType( hdc ) == OBJ_METADC)
{
- for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(caps); i++)
ok( GetDeviceCaps( hdc, caps[i] ) == (caps[i] == TECHNOLOGY ? DT_METAFILE : 0),
"wrong caps on %s for %u: %u\n", descr, caps[i],
GetDeviceCaps( hdc, caps[i] ) );
@@ -384,7 +384,7 @@ static void test_device_caps( HDC hdc, HDC ref_dc, const char *descr, int scale
}
else
{
- for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(caps); i++)
{
INT precision = 0;
INT hdc_caps = GetDeviceCaps( hdc, caps[i] );
@@ -506,7 +506,7 @@ static void test_device_caps( HDC hdc, HDC ref_dc, const char *descr, int scale
dib = CreateDIBSection( ref_dc, info, DIB_RGB_COLORS, NULL, NULL, 0 );
old = SelectObject( hdc, dib );
- for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(caps); i++)
ok( GetDeviceCaps( hdc, caps[i] ) == GetDeviceCaps( ref_dc, caps[i] ),
"mismatched caps on %s and DIB for %u: %u/%u\n", descr, caps[i],
GetDeviceCaps( hdc, caps[i] ), GetDeviceCaps( ref_dc, caps[i] ) );
diff --git a/dlls/gdi32/tests/dib.c b/dlls/gdi32/tests/dib.c
index e3f188749d..d16cb0df5c 100644
--- a/dlls/gdi32/tests/dib.c
+++ b/dlls/gdi32/tests/dib.c
@@ -1559,7 +1559,7 @@ static const POINT polypoly_lines[] =
static const DWORD polypoly_counts[] =
{
- sizeof(polypoly_lines)/sizeof(polypoly_lines[0])
+ ARRAY_SIZE(polypoly_lines)
};
static const RECT patblt_clips[] =
@@ -1816,7 +1816,7 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
}
compare_hash(hdc, bmi, bits, "diagonal solid lines");
- for(i = 0; i < sizeof(bias_check) / sizeof(bias_check[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(bias_check); i++)
{
MoveToEx(hdc, bias_check[i].left, bias_check[i].top, NULL);
LineTo(hdc, bias_check[i].right, bias_check[i].bottom);
@@ -1851,21 +1851,21 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
ExtSelectClipRgn(hdc, hrgn, RGN_COPY);
DeleteObject(hrgn2);
- for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(hline_clips); i++)
{
MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL);
LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom);
}
compare_hash(hdc, bmi, bits, "clipped solid hlines");
- for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(vline_clips); i++)
{
MoveToEx(hdc, vline_clips[i].left, vline_clips[i].top, NULL);
LineTo(hdc, vline_clips[i].right, vline_clips[i].bottom);
}
compare_hash(hdc, bmi, bits, "clipped solid vlines");
- for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(line_clips); i++)
{
MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL);
LineTo(hdc, line_clips[i].right, line_clips[i].bottom);
@@ -1873,7 +1873,7 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
compare_hash(hdc, bmi, bits, "clipped solid diagonal lines");
/* clipped PatBlt */
- for(i = 0; i < sizeof(patblt_clips) / sizeof(patblt_clips[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(patblt_clips); i++)
{
PatBlt(hdc, patblt_clips[i].left, patblt_clips[i].top,
patblt_clips[i].right - patblt_clips[i].left,
@@ -1887,35 +1887,35 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
SetBkMode(hdc, TRANSPARENT);
SetBkColor(hdc, RGB(0, 0xff, 0));
- for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(hline_clips); i++)
{
MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL);
LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom);
}
compare_hash(hdc, bmi, bits, "clipped dashed hlines");
- for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(hline_clips); i++)
{
MoveToEx(hdc, hline_clips[i].right - 1, hline_clips[i].bottom, NULL);
LineTo(hdc, hline_clips[i].left - 1, hline_clips[i].top);
}
compare_hash(hdc, bmi, bits, "clipped dashed hlines r -> l");
- for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(vline_clips); i++)
{
MoveToEx(hdc, vline_clips[i].left, vline_clips[i].top, NULL);
LineTo(hdc, vline_clips[i].right, vline_clips[i].bottom);
}
compare_hash(hdc, bmi, bits, "clipped dashed vlines");
- for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(vline_clips); i++)
{
MoveToEx(hdc, vline_clips[i].right, vline_clips[i].bottom - 1, NULL);
LineTo(hdc, vline_clips[i].left, vline_clips[i].top - 1);
}
compare_hash(hdc, bmi, bits, "clipped dashed vlines b -> t");
- for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(line_clips); i++)
{
MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL);
LineTo(hdc, line_clips[i].right, line_clips[i].bottom);
@@ -1924,7 +1924,7 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
SetBkMode(hdc, OPAQUE);
- for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(line_clips); i++)
{
MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL);
LineTo(hdc, line_clips[i].right, line_clips[i].bottom);
@@ -2163,13 +2163,13 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
SelectObject(hdc, solid_pen);
SelectObject(hdc, solid_brush);
- for(i = 0; i < sizeof(rectangles)/sizeof(rectangles[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(rectangles); i++)
{
Rectangle(hdc, rectangles[i].left, rectangles[i].top, rectangles[i].right, rectangles[i].bottom);
}
SelectObject(hdc, dashed_pen);
- for(i = 0; i < sizeof(rectangles)/sizeof(rectangles[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(rectangles); i++)
{
Rectangle(hdc, rectangles[i].left, rectangles[i].top + 150, rectangles[i].right, rectangles[i].bottom + 150);
}
@@ -2775,7 +2775,7 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
wide_pen = CreatePen( PS_SOLID, 7, RGB( 0xff, 0, 0 ) );
SelectObject( hdc, wide_pen );
- for (i = 0; i < sizeof( wide_lines ) / sizeof( wide_lines[0] ); i++)
+ for (i = 0; i < ARRAY_SIZE(wide_lines); i++)
{
MoveToEx( hdc, wide_lines[i].left, wide_lines[i].top, NULL );
LineTo( hdc, wide_lines[i].right, wide_lines[i].bottom );
@@ -2794,7 +2794,7 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
9, &log_brush, 0, NULL );
SelectObject( hdc, wide_pen );
SetBrushOrgEx( hdc, 3, 3, NULL );
- Polyline( hdc, poly_lines, sizeof(poly_lines) / sizeof(poly_lines[0]) );
+ Polyline( hdc, poly_lines, ARRAY_SIZE( poly_lines ));
compare_hash_broken_todo( hdc, bmi, bits, "wide pen - flat caps, mitred", is_ddb, is_ddb );
SetBrushOrgEx( hdc, 0, 0, NULL );
@@ -2805,7 +2805,7 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
16, &log_brush, 0, NULL );
SelectObject( hdc, wide_pen );
- Polyline( hdc, poly_lines, sizeof(poly_lines) / sizeof(poly_lines[0]) );
+ Polyline( hdc, poly_lines, ARRAY_SIZE( poly_lines ));
compare_hash_broken_todo( hdc, bmi, bits, "wide pen - square caps, bevelled", is_ddb, is_ddb );
SelectObject( hdc, orig_pen );
@@ -2815,7 +2815,7 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
9, &log_brush, 0, NULL );
SelectObject( hdc, wide_pen );
- PolyPolyline( hdc, polypoly_lines, polypoly_counts, sizeof(polypoly_counts)/sizeof(polypoly_counts[0]) );
+ PolyPolyline( hdc, polypoly_lines, polypoly_counts, ARRAY_SIZE( polypoly_counts ));
compare_hash_broken_todo( hdc, bmi, bits, "wide pen - empty segments", is_ddb, is_ddb );
SelectObject( hdc, orig_pen );
@@ -2833,7 +2833,7 @@ static void draw_graphics(HDC hdc, const BITMAPINFO *bmi, BYTE *bits)
12, &log_brush, 0, NULL );
ok( wide_pen != 0, "failed to create pen\n" );
SelectObject( hdc, wide_pen );
- Polyline( hdc, poly_lines, sizeof(poly_lines) / sizeof(poly_lines[0]) );
+ Polyline( hdc, poly_lines, ARRAY_SIZE( poly_lines ));
for (i = 1; i < 20; i++)
{
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index 6243a6d339..8f5454b918 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -937,7 +937,7 @@ static void test_bitmap_font_metrics(void)
screen_log_pixels = GetDeviceCaps(hdc, LOGPIXELSY);
diff = 32768;
font_res = 0;
- for (i = 0; i < sizeof(font_log_pixels)/sizeof(font_log_pixels[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(font_log_pixels); i++)
{
int new_diff = abs(font_log_pixels[i] - screen_log_pixels);
if (new_diff < diff)
@@ -948,7 +948,7 @@ static void test_bitmap_font_metrics(void)
}
trace("best font resolution is %d\n", font_res);
- for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(fd); i++)
{
int bit, height;
@@ -1190,7 +1190,7 @@ static void test_GetCharABCWidths(void)
UINT cs;
UINT a;
UINT w;
- BOOL r[sizeof range / sizeof range[0]];
+ BOOL r[ARRAY_SIZE(range)];
} c[] =
{
{ANSI_CHARSET, 0x30, 0x30,
@@ -1253,7 +1253,7 @@ static void test_GetCharABCWidths(void)
hfont = SelectObject(hdc, hfont);
DeleteObject(hfont);
- for (i = 0; i < sizeof c / sizeof c[0]; ++i)
+ for (i = 0; i < ARRAY_SIZE(c); ++i)
{
ABC a[2], w[2];
ABC full[256];
@@ -1285,7 +1285,7 @@ static void test_GetCharABCWidths(void)
ok(memcmp(&a[0], &full[code], sizeof(ABC)) == 0,
"GetCharABCWidthsA info should match. codepage = %u\n", c[i].cs);
- for (j = 0; j < sizeof range / sizeof range[0]; ++j)
+ for (j = 0; j < ARRAY_SIZE(range); ++j)
{
memset(full, 0xdd, sizeof full);
ret = pGetCharABCWidthsA(hdc, range[j].first, range[j].last, full);
@@ -1774,7 +1774,7 @@ static void test_GetKerningPairs(void)
return;
}
- for (i = 0; i < sizeof(kd)/sizeof(kd[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(kd); i++)
{
OUTLINETEXTMETRICW otm;
UINT uiRet;
@@ -2095,7 +2095,7 @@ static void test_height_selection_vdmx( HDC hdc )
return;
}
- for (i = 0; i < sizeof(data) / sizeof(data[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(data); i++)
{
res = get_res_data( "wine_vdmx.ttf", &size );
@@ -2356,7 +2356,7 @@ static void testJustification(HDC hdc, PCSTR str, RECT *clientArea)
{
SetTextJustification(hdc, areaWidth - size.cx, breakCount);
GetTextExtentPoint32A(hdc, pFirstChar, pLastChar - pFirstChar, &size);
- if (size.cx != areaWidth && nErrors < sizeof(error)/sizeof(error[0]) - 1)
+ if (size.cx != areaWidth && nErrors < ARRAY_SIZE(error) - 1)
{
error[nErrors].start = pFirstChar;
error[nErrors].len = pLastChar - pFirstChar;
@@ -2613,7 +2613,7 @@ static void test_font_charset(void)
return;
}
- for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(cd); i++)
{
if (cd[i].charset == SYMBOL_CHARSET)
{
@@ -2687,7 +2687,7 @@ static void test_GdiGetCodePage(void)
acp = GetACP();
- for (i = 0; i < sizeof(matching_data) / sizeof(struct _matching_data); i++)
+ for (i = 0; i < ARRAY_SIZE(matching_data); i++)
{
/* only test data matched current locale codepage */
if (matching_data[i].current_codepage != acp)
@@ -3700,7 +3700,7 @@ static int match_name_table_language( const sfnt_name *name, LANGID lang )
break;
case TT_PLATFORM_MACINTOSH:
if (!IsValidCodePage( get_mac_code_page( name ))) return 0;
- if (GET_BE_WORD(name->language_id) >= sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) return 0;
+ if (GET_BE_WORD(name->language_id) >= ARRAY_SIZE(mac_langid_table)) return 0;
name_lang = mac_langid_table[GET_BE_WORD(name->language_id)];
break;
case TT_PLATFORM_APPLE_UNICODE:
@@ -3710,7 +3710,7 @@ static int match_name_table_language( const sfnt_name *name, LANGID lang )
case TT_APPLE_ID_DEFAULT:
case TT_APPLE_ID_ISO_10646:
case TT_APPLE_ID_UNICODE_2_0:
- if (GET_BE_WORD(name->language_id) >= sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) return 0;
+ if (GET_BE_WORD(name->language_id) >= ARRAY_SIZE(mac_langid_table)) return 0;
name_lang = mac_langid_table[GET_BE_WORD(name->language_id)];
break;
default:
@@ -4105,7 +4105,7 @@ static void test_nonexistent_font(void)
hdc = CreateCompatibleDC(0);
- for (i = 0; i < sizeof(shell_subst)/sizeof(shell_subst[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(shell_subst); i++)
{
ret = is_font_installed(shell_subst[i].name);
ok(ret || broken(!ret) /* win2000 */, "%s should be enumerated\n", shell_subst[i].name);
@@ -4201,7 +4201,7 @@ todo_wine /* Wine uses Arial for all substitutions */
ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
DeleteObject(SelectObject(hdc, hfont));
- for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(font_subst); i++)
{
ret = is_font_installed(font_subst[i].name);
todo_wine
@@ -4487,8 +4487,8 @@ static void test_GetTextFace(void)
dc = GetDC(NULL);
g = SelectObject(dc, f);
- n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
- ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
+ n = GetTextFaceW(dc, ARRAY_SIZE(bufW), bufW);
+ ok(n == ARRAY_SIZE(faceW), "GetTextFaceW returned %d\n", n);
ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
/* Play with the count arg. */
@@ -4508,7 +4508,7 @@ static void test_GetTextFace(void)
ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n");
n = GetTextFaceW(dc, 0, NULL);
- ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
+ ok(n == ARRAY_SIZE(faceW), "GetTextFaceW returned %d\n", n);
DeleteObject(SelectObject(dc, g));
ReleaseDC(NULL, dc);
@@ -4719,7 +4719,7 @@ static void test_GetGlyphOutline(void)
if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
ok(ret == GDI_ERROR, "GetGlyphOutlineW should return an error when the buffer size is too small.\n");
- for (i = 0; i < sizeof(fmt) / sizeof(fmt[0]); ++i)
+ for (i = 0; i < ARRAY_SIZE(fmt); ++i)
{
DWORD dummy;
@@ -4785,7 +4785,7 @@ static void test_GetGlyphOutline(void)
SelectObject(hdc, old_hfont);
DeleteObject(hfont);
- for (i = 0; i < sizeof c / sizeof c[0]; ++i)
+ for (i = 0; i < ARRAY_SIZE(c); ++i)
{
static const MAT2 rotate_mat = {{0, 0}, {0, -1}, {0, 1}, {0, 0}};
TEXTMETRICA tm;
@@ -4955,7 +4955,7 @@ static void test_CreateFontIndirect(void)
lf.lfItalic = FALSE;
lf.lfWeight = FW_DONTCARE;
- for (i = 0; i < sizeof(TestName)/sizeof(TestName[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(TestName); i++)
{
lstrcpyA(lf.lfFaceName, TestName[i]);
hfont = CreateFontIndirectA(&lf);
@@ -5409,7 +5409,7 @@ static void test_fullname(void)
lf.lfItalic = FALSE;
lf.lfWeight = FW_DONTCARE;
- for (i = 0; i < sizeof(TestName) / sizeof(TestName[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(TestName); i++)
{
if (!is_font_installed_fullname("Lucida Sans", TestName[i]))
{
@@ -6058,7 +6058,7 @@ static void test_vertical_font(void)
ok(hgi != vgi, "same glyph h:%u v:%u\n", hgi, vgi);
- for (i = 0; i < sizeof(face_list)/sizeof(face_list[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(face_list); i++) {
const char* face = face_list[i];
if (!is_truetype_font_installed(face)) {
skip("%s is not installed\n", face);
@@ -6092,7 +6092,7 @@ static void test_east_asian_font_selection(void)
hdc = GetDC(NULL);
- for (i = 0; i < sizeof(charset)/sizeof(charset[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(charset); i++)
{
LOGFONTA lf;
HFONT hfont;
@@ -6214,7 +6214,7 @@ static void test_stock_fonts(void)
};
int i, j;
- for (i = 0; i < sizeof(font)/sizeof(font[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(font); i++)
{
HFONT hfont;
LOGFONTA lf;
@@ -6314,7 +6314,7 @@ static void test_max_height(void)
DeleteObject(SelectObject(hdc, hfont_old));
/* test an invalid value */
- for (i = 0; i < sizeof(invalid_height)/sizeof(invalid_height[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(invalid_height); i++) {
lf.lfHeight = invalid_height[i];
hfont = CreateFontIndirectA(&lf);
hfont_old = SelectObject(hdc, hfont);
@@ -6638,7 +6638,7 @@ static void test_bitmap_font_glyph_index(void)
bmi.bmiHeader.biHeight = 32;
bmi.bmiHeader.biCompression = BI_RGB;
- for (i = 0; i < sizeof(bitmap_font_list)/sizeof(bitmap_font_list[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(bitmap_font_list); i++) {
memset(&lf, 0, sizeof(lf));
lf.lfCharSet = bitmap_font_list[i].charset;
strcpy(lf.lfFaceName, bitmap_font_list[i].face);
diff --git a/dlls/gdi32/tests/gdiobj.c b/dlls/gdi32/tests/gdiobj.c
index 65374ea85d..8f3d01c27d 100644
--- a/dlls/gdi32/tests/gdiobj.c
+++ b/dlls/gdi32/tests/gdiobj.c
@@ -345,7 +345,7 @@ static void test_handles_on_win64(void)
if (sizeof(void*) != 8)
return;
- for (i = 0; i < sizeof(cases)/sizeof(cases[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(cases); i++)
{
hrgn = CreateRectRgn(10, 10, 20, 20);
hrgn_test = (HRGN)(ULONG_PTR)((ULONG_PTR)hrgn | ((ULONGLONG)cases[i].high << 32) | cases[i].low);
diff --git a/dlls/gdi32/tests/icm.c b/dlls/gdi32/tests/icm.c
index 620809018a..340ebeef55 100644
--- a/dlls/gdi32/tests/icm.c
+++ b/dlls/gdi32/tests/icm.c
@@ -278,7 +278,7 @@ static void test_SetICMProfileW( HDC dc )
return;
}
- len = sizeof(profile)/sizeof(profile[0]);
+ len = ARRAY_SIZE(profile);
ret = GetICMProfileW( dc, &len, profile );
ok(ret, "GetICMProfileW failed %u\n", GetLastError());
diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c
index 780b65f1b6..230d1e6d84 100644
--- a/dlls/gdi32/tests/metafile.c
+++ b/dlls/gdi32/tests/metafile.c
@@ -183,7 +183,7 @@ static void test_ExtTextOut(void)
static const RECT rc = { 0, 0, 100, 100 };
BOOL ret;
- assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
+ assert(ARRAY_SIZE(dx) >= lstrlenA(text));
/* Win9x doesn't play EMFs on invisible windows */
hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
@@ -3895,8 +3895,7 @@ static void test_emf_GradientFill(void)
* written to the EMF, but is not considered in the bounds
* calculation.
*/
- ret = GdiGradientFill( mf, v, sizeof(v) / sizeof(v[0]), tri, sizeof(tri) / sizeof(tri[0]),
- GRADIENT_FILL_TRIANGLE );
+ ret = GdiGradientFill( mf, v, ARRAY_SIZE(v), tri, ARRAY_SIZE(tri), GRADIENT_FILL_TRIANGLE );
ok( ret, "GradientFill\n" );
hemf = CloseEnhMetaFile( mf );
@@ -4117,7 +4116,7 @@ static void test_emf_WorldTransform(void)
{ "manual modify", TRUE, FALSE }
};
- for(i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
+ for(i = 0; i < ARRAY_SIZE(test_data); ++i)
{
hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
diff --git a/dlls/gdi32/tests/path.c b/dlls/gdi32/tests/path.c
index 48ef4f016a..80145fc6b2 100644
--- a/dlls/gdi32/tests/path.c
+++ b/dlls/gdi32/tests/path.c
@@ -495,7 +495,7 @@ static void test_arcto(void)
CloseFigure(hdc);
EndPath(hdc);
- ok_path(hdc, "arcto_path", arcto_path, sizeof(arcto_path)/sizeof(path_test_t));
+ ok_path(hdc, "arcto_path", arcto_path, ARRAY_SIZE(arcto_path));
done:
ReleaseDC(0, hdc);
}
@@ -540,7 +540,7 @@ static void test_anglearc(void)
CloseFigure(hdc);
EndPath(hdc);
- ok_path(hdc, "anglearc_path", anglearc_path, sizeof(anglearc_path)/sizeof(path_test_t));
+ ok_path(hdc, "anglearc_path", anglearc_path, ARRAY_SIZE(anglearc_path));
done:
ReleaseDC(0, hdc);
}
@@ -681,7 +681,7 @@ static void test_polydraw(void)
ok( pos.x == 80 && pos.y == 80, "wrong pos %d,%d\n", pos.x, pos.y );
EndPath(hdc);
- ok_path(hdc, "polydraw_path", polydraw_path, sizeof(polydraw_path)/sizeof(path_test_t));
+ ok_path(hdc, "polydraw_path", polydraw_path, ARRAY_SIZE(polydraw_path));
GetCurrentPositionEx( hdc, &pos );
ok( pos.x == 80 && pos.y == 80, "wrong pos %d,%d\n", pos.x, pos.y );
done:
@@ -966,7 +966,7 @@ static void test_rectangle(void)
SetArcDirection( hdc, AD_COUNTERCLOCKWISE );
EndPath( hdc );
SetMapMode( hdc, MM_TEXT );
- ok_path( hdc, "rectangle_path", rectangle_path, sizeof(rectangle_path)/sizeof(path_test_t) );
+ ok_path( hdc, "rectangle_path", rectangle_path, ARRAY_SIZE(rectangle_path) );
ReleaseDC( 0, hdc );
}
@@ -1327,7 +1327,7 @@ static void test_roundrect(void)
SetArcDirection( hdc, AD_COUNTERCLOCKWISE );
EndPath( hdc );
SetMapMode( hdc, MM_TEXT );
- ok_path( hdc, "roundrect_path", roundrect_path, sizeof(roundrect_path)/sizeof(path_test_t) );
+ ok_path( hdc, "roundrect_path", roundrect_path, ARRAY_SIZE(roundrect_path) );
ReleaseDC( 0, hdc );
}
@@ -1707,7 +1707,7 @@ static void test_ellipse(void)
SetArcDirection( hdc, AD_COUNTERCLOCKWISE );
EndPath( hdc );
SetMapMode( hdc, MM_TEXT );
- ok_path( hdc, "ellipse_path", ellipse_path, sizeof(ellipse_path)/sizeof(path_test_t) );
+ ok_path( hdc, "ellipse_path", ellipse_path, ARRAY_SIZE(ellipse_path) );
}
static const path_test_t all_funcs_path[] =
@@ -1890,7 +1890,7 @@ static void test_all_functions(void)
LineTo( hdc, 150, 150 );
/* FIXME: ExtTextOut */
EndPath( hdc );
- ok_path( hdc, "all_funcs_path", all_funcs_path, sizeof(all_funcs_path)/sizeof(path_test_t) );
+ ok_path( hdc, "all_funcs_path", all_funcs_path, ARRAY_SIZE(all_funcs_path) );
ReleaseDC( 0, hdc );
}
diff --git a/dlls/gdi32/tests/pen.c b/dlls/gdi32/tests/pen.c
index 43f00d8f50..badc585f57 100644
--- a/dlls/gdi32/tests/pen.c
+++ b/dlls/gdi32/tests/pen.c
@@ -72,7 +72,7 @@ static void test_logpen(void)
EXTLOGPEN *ext_pen = (EXTLOGPEN *)elp_buffer;
DWORD *ext_style = ext_pen->elpStyleEntry;
- for (i = 0; i < sizeof(pen)/sizeof(pen[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(pen); i++)
{
trace("%d: testing style %u\n", i, pen[i].style);
--
2.14.4
June 25, 2018
Re: [PATCH] hnetcfg: Store the full path in INetFwAuthorizedApplication_put_ProcessImageFileName().
by Zebediah Figura
On 25/06/18 08:20, Nikolay Sivov wrote:
> On 06/25/2018 06:46 AM, Zebediah Figura wrote:
>
>> Should hopefully fix test failures on Windows.
>>
>> Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
>> ---
>> dlls/hnetcfg/apps.c | 17 ++++++++++++-----
>> dlls/hnetcfg/tests/policy.c | 5 ++++-
>> 2 files changed, 16 insertions(+), 6 deletions(-)
>>
>> diff --git a/dlls/hnetcfg/apps.c b/dlls/hnetcfg/apps.c
>> index 34ef108..fe47721 100644
>> --- a/dlls/hnetcfg/apps.c
>> +++ b/dlls/hnetcfg/apps.c
>> @@ -268,7 +268,7 @@ static HRESULT WINAPI
>> fw_app_put_ProcessImageFileName(
>> {
>> fw_app *This = impl_from_INetFwAuthorizedApplication( iface );
>> UNIVERSAL_NAME_INFOW *info;
>> - WCHAR *netpath;
>> + WCHAR *path;
>> DWORD res;
>> DWORD sz;
>> @@ -281,22 +281,29 @@ static HRESULT WINAPI
>> fw_app_put_ProcessImageFileName(
>> res = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL,
>> NULL, &sz);
>> if (res == WN_MORE_DATA)
>> {
>> - if (!(netpath = heap_alloc(sz)))
>> + if (!(path = heap_alloc(sz)))
>> return E_OUTOFMEMORY;
>> - info = (UNIVERSAL_NAME_INFOW *)&netpath;
>> + info = (UNIVERSAL_NAME_INFOW *)&path;
>> res = WNetGetUniversalNameW(image,
>> UNIVERSAL_NAME_INFO_LEVEL, &info, &sz);
>> if (res == NO_ERROR)
>> {
>> SysFreeString(This->filename);
>> This->filename = SysAllocString(info->lpUniversalName);
>> }
>> - heap_free(netpath);
>> + heap_free(path);
>> return HRESULT_FROM_WIN32(res);
>> }
>> + sz = GetFullPathNameW(image, 0, NULL, NULL);
>> + if (!(path = heap_alloc(++sz)))
>> + return E_OUTOFMEMORY;
>> +
>> + GetFullPathNameW(image, sz, path, NULL);
>
> ...
>
>>
>> + GetFullPathNameW(image, sizeof(fullpath), fullpath, NULL);
> ...
>
> This one takes character length I think, not byte length.
>
>
Thanks for the catch; resent.
June 25, 2018
[PATCH v2] hnetcfg: Store the full path in INetFwAuthorizedApplication_put_ProcessImageFileName().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/hnetcfg/apps.c | 17 ++++++++++++-----
dlls/hnetcfg/tests/policy.c | 5 ++++-
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/dlls/hnetcfg/apps.c b/dlls/hnetcfg/apps.c
index 34ef108..fe47721 100644
--- a/dlls/hnetcfg/apps.c
+++ b/dlls/hnetcfg/apps.c
@@ -268,7 +268,7 @@ static HRESULT WINAPI fw_app_put_ProcessImageFileName(
{
fw_app *This = impl_from_INetFwAuthorizedApplication( iface );
UNIVERSAL_NAME_INFOW *info;
- WCHAR *netpath;
+ WCHAR *path;
DWORD res;
DWORD sz;
@@ -281,22 +281,29 @@ static HRESULT WINAPI fw_app_put_ProcessImageFileName(
res = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL, NULL, &sz);
if (res == WN_MORE_DATA)
{
- if (!(netpath = heap_alloc(sz)))
+ if (!(path = heap_alloc(sz)))
return E_OUTOFMEMORY;
- info = (UNIVERSAL_NAME_INFOW *)&netpath;
+ info = (UNIVERSAL_NAME_INFOW *)&path;
res = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL, &info, &sz);
if (res == NO_ERROR)
{
SysFreeString(This->filename);
This->filename = SysAllocString(info->lpUniversalName);
}
- heap_free(netpath);
+ heap_free(path);
return HRESULT_FROM_WIN32(res);
}
+ sz = GetFullPathNameW(image, 0, NULL, NULL);
+ if (!(path = heap_alloc(++sz)))
+ return E_OUTOFMEMORY;
+
+ GetFullPathNameW(image, sz, path, NULL);
+
SysFreeString( This->filename );
- This->filename = SysAllocString(image);
+ This->filename = SysAllocString(path);
+ heap_free(path);
return This->filename ? S_OK : E_OUTOFMEMORY;
}
diff --git a/dlls/hnetcfg/tests/policy.c b/dlls/hnetcfg/tests/policy.c
index f2d1372..954af5c 100644
--- a/dlls/hnetcfg/tests/policy.c
+++ b/dlls/hnetcfg/tests/policy.c
@@ -107,6 +107,7 @@ static void test_NetFwAuthorizedApplication(void)
INetFwAuthorizedApplication *app;
static WCHAR empty[] = {0};
UNIVERSAL_NAME_INFOW *info;
+ WCHAR fullpath[MAX_PATH];
WCHAR netpath[MAX_PATH];
WCHAR image[MAX_PATH];
HRESULT hr;
@@ -138,13 +139,15 @@ static void test_NetFwAuthorizedApplication(void)
ok(hr == S_OK, "got: %08x\n", hr);
SysFreeString(bstr);
+ GetFullPathNameW(image, ARRAY_SIZE(fullpath), fullpath, NULL);
+
info = (UNIVERSAL_NAME_INFOW *)&netpath;
sz = sizeof(netpath);
hr = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL, &info, &sz);
if (hr != NO_ERROR)
{
info->lpUniversalName = netpath + sizeof(*info)/sizeof(WCHAR);
- lstrcpyW(info->lpUniversalName, image);
+ lstrcpyW(info->lpUniversalName, fullpath);
}
hr = INetFwAuthorizedApplication_get_ProcessImageFileName(app, &bstr);
--
2.7.4
June 25, 2018
[PATCH] hnetcfg: GetModuleFileNameW gets characters, not bytes (Coverity)
by Marcus Meissner
CID 1437516
Signed-off-by: Marcus Meissner <meissner(a)suse.de>
---
dlls/hnetcfg/tests/policy.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/hnetcfg/tests/policy.c b/dlls/hnetcfg/tests/policy.c
index f2d1372ba6..b28535d448 100644
--- a/dlls/hnetcfg/tests/policy.c
+++ b/dlls/hnetcfg/tests/policy.c
@@ -117,7 +117,7 @@ static void test_NetFwAuthorizedApplication(void)
&IID_INetFwAuthorizedApplication, (void**)&app);
ok(hr == S_OK, "got: %08x\n", hr);
- hr = GetModuleFileNameW(NULL, image, sizeof(image));
+ hr = GetModuleFileNameW(NULL, image, ARRAY_SIZE(image));
ok(hr, "GetModuleFileName failed: %u\n", GetLastError());
hr = INetFwAuthorizedApplication_get_ProcessImageFileName(app, NULL);
--
2.17.1
June 25, 2018
[PATCH v3] comctl32/imagelist: fix ImageList_Read
by Denis Malikov
Fix for versions x600 and x620 and pointer calculation for mixing image and mask bits.
Tested on *.reg files extracted from:
- XP/2003 key HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\TrayNotify;
- Vista/7 key HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify
Signed-off-by: Denis Malikov <mdn40000(a)mail.ru>
---
dlls/comctl32/imagelist.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c
index a08d60752e..be901462a0 100644
--- a/dlls/comctl32/imagelist.c
+++ b/dlls/comctl32/imagelist.c
@@ -2267,7 +2267,9 @@ HIMAGELIST WINAPI ImageList_Read(IStream *pstm)
return NULL;
if (ilHead.usMagic != (('L' << 8) | 'I'))
return NULL;
- if (ilHead.usVersion != 0x101) /* probably version? */
+ if (ilHead.usVersion != 0x101 &&
+ ilHead.usVersion != 0x600 && /* XP/2003 version */
+ ilHead.usVersion != 0x620) /* Vista/7 version */
return NULL;
TRACE("cx %u, cy %u, flags 0x%04x, cCurImage %u, cMaxImage %u\n",
@@ -2296,23 +2298,25 @@ HIMAGELIST WINAPI ImageList_Read(IStream *pstm)
{
DWORD *ptr = image_bits;
BYTE *mask_ptr = mask_bits;
- int stride = himl->cy * image_info->bmiHeader.biWidth;
+ int stride = himl->cy * (ilHead.usVersion != 0x101 ? himl->cx : image_info->bmiHeader.biWidth);
+ int image_step = ilHead.usVersion != 0x101 ? 1 : TILE_COUNT;
+ int mask_step = ilHead.usVersion != 0x101 ? 4 : 8;
if (image_info->bmiHeader.biHeight > 0) /* bottom-up */
{
ptr += image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride;
- mask_ptr += (image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride) / 8;
+ mask_ptr += (image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride) / mask_step;
stride = -stride;
image_info->bmiHeader.biHeight = himl->cy;
}
else image_info->bmiHeader.biHeight = -himl->cy;
- for (i = 0; i < ilHead.cCurImage; i += TILE_COUNT)
+ for (i = 0; i < ilHead.cCurImage; i += image_step)
{
- add_dib_bits( himl, i, min( ilHead.cCurImage - i, TILE_COUNT ),
+ add_dib_bits( himl, i, min( ilHead.cCurImage - i, image_step ),
himl->cx, himl->cy, image_info, mask_info, ptr, mask_ptr );
ptr += stride;
- mask_ptr += stride / 8;
+ mask_ptr += stride / mask_step;
}
}
else
--
2.16.2.windows.1
June 25, 2018
Re: [PATCH] hnetcfg: Store the full path in INetFwAuthorizedApplication_put_ProcessImageFileName().
by Nikolay Sivov
On 06/25/2018 06:46 AM, Zebediah Figura wrote:
> Should hopefully fix test failures on Windows.
>
> Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
> ---
> dlls/hnetcfg/apps.c | 17 ++++++++++++-----
> dlls/hnetcfg/tests/policy.c | 5 ++++-
> 2 files changed, 16 insertions(+), 6 deletions(-)
>
> diff --git a/dlls/hnetcfg/apps.c b/dlls/hnetcfg/apps.c
> index 34ef108..fe47721 100644
> --- a/dlls/hnetcfg/apps.c
> +++ b/dlls/hnetcfg/apps.c
> @@ -268,7 +268,7 @@ static HRESULT WINAPI fw_app_put_ProcessImageFileName(
> {
> fw_app *This = impl_from_INetFwAuthorizedApplication( iface );
> UNIVERSAL_NAME_INFOW *info;
> - WCHAR *netpath;
> + WCHAR *path;
> DWORD res;
> DWORD sz;
>
> @@ -281,22 +281,29 @@ static HRESULT WINAPI fw_app_put_ProcessImageFileName(
> res = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL, NULL, &sz);
> if (res == WN_MORE_DATA)
> {
> - if (!(netpath = heap_alloc(sz)))
> + if (!(path = heap_alloc(sz)))
> return E_OUTOFMEMORY;
>
> - info = (UNIVERSAL_NAME_INFOW *)&netpath;
> + info = (UNIVERSAL_NAME_INFOW *)&path;
> res = WNetGetUniversalNameW(image, UNIVERSAL_NAME_INFO_LEVEL, &info, &sz);
> if (res == NO_ERROR)
> {
> SysFreeString(This->filename);
> This->filename = SysAllocString(info->lpUniversalName);
> }
> - heap_free(netpath);
> + heap_free(path);
> return HRESULT_FROM_WIN32(res);
> }
>
> + sz = GetFullPathNameW(image, 0, NULL, NULL);
> + if (!(path = heap_alloc(++sz)))
> + return E_OUTOFMEMORY;
> +
> + GetFullPathNameW(image, sz, path, NULL);
...
>
>
> + GetFullPathNameW(image, sizeof(fullpath), fullpath, NULL);
...
This one takes character length I think, not byte length.
June 25, 2018
[PATCH] fonts: Add clock images to Wingdings font. (v2)
by Dmitry Timoshkov
v2: I've created the glyphs on my own.
wingding.ttf should be rebuilt in maintainer mode after applying this patch.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
fonts/wingding.sfd | 760 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 758 insertions(+), 2 deletions(-)
diff --git a/fonts/wingding.sfd b/fonts/wingding.sfd
index c46152b077..d5b7ec871b 100644
--- a/fonts/wingding.sfd
+++ b/fonts/wingding.sfd
@@ -50,9 +50,9 @@ NameList: Adobe Glyph List
DisplaySize: -48
AntiAlias: 1
FitToEm: 1
-WinInfo: 0 29 12
+WinInfo: 0 38 13
TeXData: 1 0 0 708670 354335 236222 1342177 -2147484 236222 783286 444596 497025 792723 393216 433062 380633 303038 157286 324010 404750 52429 2506097 1059062 262144
-BeginChars: 256 38
+BeginChars: 256 50
StartChar: f020
Encoding: 0 61472 0
@@ -788,5 +788,761 @@ LayerCount: 2
Fore
Refer: 34 63724 N 0 1 -1 0 1653 -173 2
EndChar
+
+StartChar: oneoclock
+Encoding: 183 8721 38
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+1045.63 1112.56 m 1,0,-1
+ 1117 1081.1 l 1,1,-1
+ 888.373 614.638 l 1,2,-1
+ 817 646.1 l 1,3,-1
+ 1045.63 1112.56 l 1,0,-1
+1045.63 1112.56 m 1,4,-1
+ 1117 1081.1 l 1,5,-1
+ 888.373 614.638 l 1,6,-1
+ 817 646.1 l 1,7,-1
+ 1045.63 1112.56 l 1,4,-1
+871 1297.1 m 1,8,-1
+ 949 1297.1 l 1,9,-1
+ 949 595.1 l 1,10,-1
+ 871 595.1 l 1,11,-1
+ 871 1297.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+868 238.1 m 1,16,-1
+ 943 238.1 l 1,17,-1
+ 943 151.1 l 1,18,-1
+ 868 151.1 l 1,19,-1
+ 868 238.1 l 1,16,-1
+1408 784.1 m 1,20,-1
+ 1483 784.1 l 1,21,-1
+ 1483 697.1 l 1,22,-1
+ 1408 697.1 l 1,23,-1
+ 1408 784.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
+
+StartChar: twooclock
+Encoding: 184 8719 39
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+1259.61 981.841 m 1,0,-1
+ 1308.09 920.734 l 1,1,-1
+ 888.373 614.638 l 1,2,-1
+ 839.896 675.744 l 1,3,-1
+ 1259.61 981.841 l 1,0,-1
+1259.61 981.841 m 1,4,-1
+ 1308.09 920.734 l 1,5,-1
+ 888.373 614.638 l 1,6,-1
+ 839.896 675.744 l 1,7,-1
+ 1259.61 981.841 l 1,4,-1
+871 1297.1 m 1,8,-1
+ 949 1297.1 l 1,9,-1
+ 949 595.1 l 1,10,-1
+ 871 595.1 l 1,11,-1
+ 871 1297.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+868 238.1 m 1,16,-1
+ 943 238.1 l 1,17,-1
+ 943 151.1 l 1,18,-1
+ 868 151.1 l 1,19,-1
+ 868 238.1 l 1,16,-1
+1408 784.1 m 1,20,-1
+ 1483 784.1 l 1,21,-1
+ 1483 697.1 l 1,22,-1
+ 1408 697.1 l 1,23,-1
+ 1408 784.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
+
+StartChar: threeoclock
+Encoding: 185 960 40
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+1417 769.1 m 1,0,-1
+ 1492 769.1 l 1,1,-1
+ 1492 682.1 l 1,2,-1
+ 1417 682.1 l 1,3,-1
+ 1417 769.1 l 1,0,-1
+1354 760.1 m 1,4,-1
+ 1357.3 682.17 l 1,5,-1
+ 837.828 681.208 l 1,6,-1
+ 834.522 759.138 l 1,7,-1
+ 1354 760.1 l 1,4,-1
+1354 760.1 m 1,8,-1
+ 1357.3 682.17 l 1,9,-1
+ 837.828 681.208 l 1,10,-1
+ 834.522 759.138 l 1,11,-1
+ 1354 760.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+871 1297.1 m 1,16,-1
+ 949 1297.1 l 1,17,-1
+ 949 595.1 l 1,18,-1
+ 871 595.1 l 1,19,-1
+ 871 1297.1 l 1,16,-1
+868 238.1 m 1,20,-1
+ 943 238.1 l 1,21,-1
+ 943 151.1 l 1,22,-1
+ 868 151.1 l 1,23,-1
+ 868 238.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
+
+StartChar: fouroclock
+Encoding: 186 8747 41
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+1400.73 513.884 m 1,0,-1
+ 1377.42 439.448 l 1,1,-1
+ 888.373 614.638 l 1,2,-1
+ 911.681 689.074 l 1,3,-1
+ 1400.73 513.884 l 1,0,-1
+1400.73 513.884 m 1,4,-1
+ 1377.42 439.448 l 1,5,-1
+ 888.373 614.638 l 1,6,-1
+ 911.681 689.074 l 1,7,-1
+ 1400.73 513.884 l 1,4,-1
+871 1297.1 m 1,8,-1
+ 949 1297.1 l 1,9,-1
+ 949 595.1 l 1,10,-1
+ 871 595.1 l 1,11,-1
+ 871 1297.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+868 238.1 m 1,16,-1
+ 943 238.1 l 1,17,-1
+ 943 151.1 l 1,18,-1
+ 868 151.1 l 1,19,-1
+ 868 238.1 l 1,16,-1
+1408 784.1 m 1,20,-1
+ 1483 784.1 l 1,21,-1
+ 1483 697.1 l 1,22,-1
+ 1408 697.1 l 1,23,-1
+ 1408 784.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
+
+StartChar: fiveoclock
+Encoding: 187 170 42
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+1169.2 333.396 m 1,0,-1
+ 1105 289.1 l 1,1,-1
+ 827.557 728.283 l 1,2,-1
+ 891.758 772.579 l 1,3,-1
+ 1169.2 333.396 l 1,0,-1
+1169.2 333.396 m 1,4,-1
+ 1105 289.1 l 1,5,-1
+ 827.557 728.283 l 1,6,-1
+ 891.758 772.579 l 1,7,-1
+ 1169.2 333.396 l 1,4,-1
+871 1297.1 m 1,8,-1
+ 949 1297.1 l 1,9,-1
+ 949 595.1 l 1,10,-1
+ 871 595.1 l 1,11,-1
+ 871 1297.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+868 238.1 m 1,16,-1
+ 943 238.1 l 1,17,-1
+ 943 151.1 l 1,18,-1
+ 868 151.1 l 1,19,-1
+ 868 238.1 l 1,16,-1
+1408 784.1 m 1,20,-1
+ 1483 784.1 l 1,21,-1
+ 1483 697.1 l 1,22,-1
+ 1408 697.1 l 1,23,-1
+ 1408 784.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
+
+StartChar: sixoclock
+Encoding: 188 186 43
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+872.619 844.557 m 1,0,-1
+ 950.58 847.024 l 1,1,-1
+ 945.961 327.567 l 1,2,-1
+ 868 325.1 l 1,3,-1
+ 872.619 844.557 l 1,0,-1
+872.619 844.557 m 1,4,-1
+ 950.58 847.024 l 1,5,-1
+ 945.961 327.567 l 1,6,-1
+ 868 325.1 l 1,7,-1
+ 872.619 844.557 l 1,4,-1
+871 1297.1 m 1,8,-1
+ 949 1297.1 l 1,9,-1
+ 949 595.1 l 1,10,-1
+ 871 595.1 l 1,11,-1
+ 871 1297.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+868 238.1 m 1,16,-1
+ 943 238.1 l 1,17,-1
+ 943 151.1 l 1,18,-1
+ 868 151.1 l 1,19,-1
+ 868 238.1 l 1,16,-1
+1408 784.1 m 1,20,-1
+ 1483 784.1 l 1,21,-1
+ 1483 697.1 l 1,22,-1
+ 1408 697.1 l 1,23,-1
+ 1408 784.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
+
+StartChar: sevenoclock
+Encoding: 189 937 44
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+682 289.1 m 1,0,-1
+ 616.783 331.886 l 1,1,-1
+ 919.107 754.327 l 1,2,-1
+ 984.324 711.541 l 1,3,-1
+ 682 289.1 l 1,0,-1
+682 289.1 m 1,4,-1
+ 616.783 331.886 l 1,5,-1
+ 919.107 754.327 l 1,6,-1
+ 984.324 711.541 l 1,7,-1
+ 682 289.1 l 1,4,-1
+871 1297.1 m 1,8,-1
+ 949 1297.1 l 1,9,-1
+ 949 595.1 l 1,10,-1
+ 871 595.1 l 1,11,-1
+ 871 1297.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+868 238.1 m 1,16,-1
+ 943 238.1 l 1,17,-1
+ 943 151.1 l 1,18,-1
+ 868 151.1 l 1,19,-1
+ 868 238.1 l 1,16,-1
+1408 784.1 m 1,20,-1
+ 1483 784.1 l 1,21,-1
+ 1483 697.1 l 1,22,-1
+ 1408 697.1 l 1,23,-1
+ 1408 784.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
+
+StartChar: eightoclock
+Encoding: 190 230 45
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+544.217 438.639 m 1,0,-1
+ 501.419 503.848 l 1,1,-1
+ 946.903 771.055 l 1,2,-1
+ 989.703 705.847 l 1,3,-1
+ 544.217 438.639 l 1,0,-1
+544.217 438.639 m 1,4,-1
+ 501.419 503.848 l 1,5,-1
+ 946.903 771.055 l 1,6,-1
+ 989.703 705.847 l 1,7,-1
+ 544.217 438.639 l 1,4,-1
+871 1297.1 m 1,8,-1
+ 949 1297.1 l 1,9,-1
+ 949 595.1 l 1,10,-1
+ 871 595.1 l 1,11,-1
+ 871 1297.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+868 238.1 m 1,16,-1
+ 943 238.1 l 1,17,-1
+ 943 151.1 l 1,18,-1
+ 868 151.1 l 1,19,-1
+ 868 238.1 l 1,16,-1
+1408 784.1 m 1,20,-1
+ 1483 784.1 l 1,21,-1
+ 1483 697.1 l 1,22,-1
+ 1408 697.1 l 1,23,-1
+ 1408 784.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
+
+StartChar: nineoclock
+Encoding: 191 248 46
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+517 679.1 m 1,0,-1
+ 513.82 757.034 l 1,1,-1
+ 1033.3 757.157 l 1,2,-1
+ 1036.48 679.223 l 1,3,-1
+ 517 679.1 l 1,0,-1
+517 679.1 m 1,4,-1
+ 513.82 757.034 l 1,5,-1
+ 1033.3 757.157 l 1,6,-1
+ 1036.48 679.223 l 1,7,-1
+ 517 679.1 l 1,4,-1
+871 1297.1 m 1,8,-1
+ 949 1297.1 l 1,9,-1
+ 949 595.1 l 1,10,-1
+ 871 595.1 l 1,11,-1
+ 871 1297.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+868 238.1 m 1,16,-1
+ 943 238.1 l 1,17,-1
+ 943 151.1 l 1,18,-1
+ 868 151.1 l 1,19,-1
+ 868 238.1 l 1,16,-1
+1408 784.1 m 1,20,-1
+ 1483 784.1 l 1,21,-1
+ 1483 697.1 l 1,22,-1
+ 1408 697.1 l 1,23,-1
+ 1408 784.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
+
+StartChar: tenoclock
+Encoding: 192 191 47
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+555.232 898.87 m 1,0,-1
+ 598 964.1 l 1,1,-1
+ 1020.53 661.897 l 1,2,-1
+ 977.762 596.668 l 1,3,-1
+ 555.232 898.87 l 1,0,-1
+555.232 898.87 m 1,4,-1
+ 598 964.1 l 1,5,-1
+ 1020.53 661.897 l 1,6,-1
+ 977.762 596.668 l 1,7,-1
+ 555.232 898.87 l 1,4,-1
+871 1297.1 m 1,8,-1
+ 949 1297.1 l 1,9,-1
+ 949 595.1 l 1,10,-1
+ 871 595.1 l 1,11,-1
+ 871 1297.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+868 238.1 m 1,16,-1
+ 943 238.1 l 1,17,-1
+ 943 151.1 l 1,18,-1
+ 868 151.1 l 1,19,-1
+ 868 238.1 l 1,16,-1
+1408 784.1 m 1,20,-1
+ 1483 784.1 l 1,21,-1
+ 1483 697.1 l 1,22,-1
+ 1408 697.1 l 1,23,-1
+ 1408 784.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
+
+StartChar: elevenoclock
+Encoding: 193 161 48
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+693.722 1059.02 m 1,0,-1
+ 758.041 1103.14 l 1,1,-1
+ 1034.32 663.226 l 1,2,-1
+ 970 619.1 l 1,3,-1
+ 693.722 1059.02 l 1,0,-1
+693.722 1059.02 m 1,4,-1
+ 758.041 1103.14 l 1,5,-1
+ 1034.32 663.226 l 1,6,-1
+ 970 619.1 l 1,7,-1
+ 693.722 1059.02 l 1,4,-1
+871 1297.1 m 1,8,-1
+ 949 1297.1 l 1,9,-1
+ 949 595.1 l 1,10,-1
+ 871 595.1 l 1,11,-1
+ 871 1297.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+868 238.1 m 1,16,-1
+ 943 238.1 l 1,17,-1
+ 943 151.1 l 1,18,-1
+ 868 151.1 l 1,19,-1
+ 868 238.1 l 1,16,-1
+1408 784.1 m 1,20,-1
+ 1483 784.1 l 1,21,-1
+ 1483 697.1 l 1,22,-1
+ 1408 697.1 l 1,23,-1
+ 1408 784.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
+
+StartChar: twelveoclock
+Encoding: 194 172 49
+Width: 1825
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+872.906 1111.69 m 1,0,-1
+ 950.853 1114.57 l 1,1,-1
+ 949 595.1 l 1,2,-1
+ 871.054 592.217 l 1,3,-1
+ 872.906 1111.69 l 1,0,-1
+872.906 1111.69 m 1,4,-1
+ 950.853 1114.57 l 1,5,-1
+ 949 595.1 l 1,6,-1
+ 871.054 592.217 l 1,7,-1
+ 872.906 1111.69 l 1,4,-1
+871 1297.1 m 1,8,-1
+ 949 1297.1 l 1,9,-1
+ 949 595.1 l 1,10,-1
+ 871 595.1 l 1,11,-1
+ 871 1297.1 l 1,8,-1
+871 1297.1 m 1,12,-1
+ 949 1297.1 l 1,13,-1
+ 949 595.1 l 1,14,-1
+ 871 595.1 l 1,15,-1
+ 871 1297.1 l 1,12,-1
+868 238.1 m 1,16,-1
+ 943 238.1 l 1,17,-1
+ 943 151.1 l 1,18,-1
+ 868 151.1 l 1,19,-1
+ 868 238.1 l 1,16,-1
+1408 784.1 m 1,20,-1
+ 1483 784.1 l 1,21,-1
+ 1483 697.1 l 1,22,-1
+ 1408 697.1 l 1,23,-1
+ 1408 784.1 l 1,20,-1
+340 763.1 m 1,24,-1
+ 415 763.1 l 1,25,-1
+ 415 676.1 l 1,26,-1
+ 340 676.1 l 1,27,-1
+ 340 763.1 l 1,24,-1
+438.5 254.1 m 0,28,29
+ 680.837 45.2673 680.837 45.2673 917.027 58.1245 c 0,30,31
+ 1187.65 72.8563 1187.65 72.8563 1382.5 266.1 c 0,32,33
+ 1576.5 458.508 1576.5 458.508 1574.5 734.1 c 0,34,35
+ 1571.93 1022.95 1571.93 1022.95 1414 1180.1 c 0,36,37
+ 1202.96 1390.1 1202.96 1390.1 906.5 1390.1 c 0,38,39
+ 620.354 1390.1 620.354 1390.1 442.5 1198.1 c 0,40,41
+ 236.614 975.839 236.614 975.839 246.5 722.1 c 0,42,43
+ 258.697 409.044 258.697 409.044 438.5 254.1 c 0,28,29
+1430.5 1245.5 m 128,-1,45
+ 1644 1032 1644 1032 1644 730 c 256,46,47
+ 1644 428 1644 428 1430.5 214 c 128,-1,48
+ 1217 0 1217 0 914 0 c 0,49,50
+ 612 0 612 0 398.5 214 c 128,-1,51
+ 185 428 185 428 185 730 c 256,52,53
+ 185 1032 185 1032 398.5 1245.5 c 128,-1,54
+ 612 1459 612 1459 914 1459 c 0,55,44
+ 1217 1459 1217 1459 1430.5 1245.5 c 128,-1,45
+EndSplineSet
+EndChar
EndChars
EndSplineFont
--
2.16.3
June 25, 2018
[PATCH] crypt32: Correctly return how the issuer of a self signed certificate was matched.
by Nikolay Sivov
Original patch by Michael Müller.
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/crypt32/chain.c | 53 +++++++++++++++-------------------
dlls/crypt32/crypt32_private.h | 2 +-
2 files changed, 24 insertions(+), 31 deletions(-)
diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c
index 6e8076c66c..d7015d797d 100644
--- a/dlls/crypt32/chain.c
+++ b/dlls/crypt32/chain.c
@@ -265,10 +265,10 @@ typedef struct _CertificateChain
LONG ref;
} CertificateChain;
-BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert)
+DWORD CRYPT_IsCertificateSelfSigned(const CERT_CONTEXT *cert)
{
+ DWORD size, status = 0;
PCERT_EXTENSION ext;
- DWORD size;
BOOL ret;
if ((ext = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2,
@@ -296,10 +296,9 @@ BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert)
&info->AuthorityCertIssuer.rgAltEntry[i];
if (directoryName)
{
- ret = CertCompareCertificateName(cert->dwCertEncodingType,
- &directoryName->u.DirectoryName, &cert->pCertInfo->Issuer)
- && CertCompareIntegerBlob(&info->AuthorityCertSerialNumber,
- &cert->pCertInfo->SerialNumber);
+ if (CertCompareCertificateName(cert->dwCertEncodingType, &directoryName->u.DirectoryName, &cert->pCertInfo->Issuer)
+ && CertCompareIntegerBlob(&info->AuthorityCertSerialNumber, &cert->pCertInfo->SerialNumber))
+ status = CERT_TRUST_HAS_NAME_MATCH_ISSUER;
}
else
{
@@ -317,16 +316,12 @@ BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert)
if (buf)
{
- CertGetCertificateContextProperty(cert,
- CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
- ret = !memcmp(buf, info->KeyId.pbData, size);
+ CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
+ if (!memcmp(buf, info->KeyId.pbData, size))
+ status = CERT_TRUST_HAS_KEY_MATCH_ISSUER;
CryptMemFree(buf);
}
- else
- ret = FALSE;
}
- else
- ret = FALSE;
}
LocalFree(info);
}
@@ -344,10 +339,9 @@ BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert)
{
if (info->CertIssuer.cbData && info->CertSerialNumber.cbData)
{
- ret = CertCompareCertificateName(cert->dwCertEncodingType,
- &info->CertIssuer, &cert->pCertInfo->Issuer) &&
- CertCompareIntegerBlob(&info->CertSerialNumber,
- &cert->pCertInfo->SerialNumber);
+ if (CertCompareCertificateName(cert->dwCertEncodingType, &info->CertIssuer, &cert->pCertInfo->Issuer)
+ && CertCompareIntegerBlob(&info->CertSerialNumber, &cert->pCertInfo->SerialNumber))
+ status = CERT_TRUST_HAS_NAME_MATCH_ISSUER;
}
else if (info->KeyId.cbData)
{
@@ -361,24 +355,23 @@ BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert)
{
CertGetCertificateContextProperty(cert,
CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
- ret = !memcmp(buf, info->KeyId.pbData, size);
+ if (!memcmp(buf, info->KeyId.pbData, size))
+ status = CERT_TRUST_HAS_KEY_MATCH_ISSUER;
CryptMemFree(buf);
}
- else
- ret = FALSE;
}
- else
- ret = FALSE;
}
- else
- ret = FALSE;
LocalFree(info);
}
}
else
- ret = CertCompareCertificateName(cert->dwCertEncodingType,
- &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
- return ret;
+ if (CertCompareCertificateName(cert->dwCertEncodingType, &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer))
+ status = CERT_TRUST_HAS_NAME_MATCH_ISSUER;
+
+ if (status)
+ status |= CERT_TRUST_IS_SELF_SIGNED;
+
+ return status;
}
static void CRYPT_FreeChainElement(PCERT_CHAIN_ELEMENT element)
@@ -1890,6 +1883,7 @@ static void CRYPT_CheckSimpleChain(CertificateChainEngine *engine,
int i;
BOOL pathLengthConstraintViolated = FALSE;
CERT_BASIC_CONSTRAINTS2_INFO constraints = { FALSE, FALSE, 0 };
+ DWORD status;
TRACE_(chain)("checking chain with %d elements for time %s\n",
chain->cElement, filetime_to_str(time));
@@ -1977,10 +1971,9 @@ static void CRYPT_CheckSimpleChain(CertificateChainEngine *engine,
}
CRYPT_CheckChainNameConstraints(chain);
CRYPT_CheckChainPolicies(chain);
- if (CRYPT_IsCertificateSelfSigned(rootElement->pCertContext))
+ if ((status = CRYPT_IsCertificateSelfSigned(rootElement->pCertContext)))
{
- rootElement->TrustStatus.dwInfoStatus |=
- CERT_TRUST_IS_SELF_SIGNED | CERT_TRUST_HAS_NAME_MATCH_ISSUER;
+ rootElement->TrustStatus.dwInfoStatus |= status;
CRYPT_CheckRootCert(engine->hRoot, rootElement);
}
CRYPT_CombineTrustStatus(&chain->TrustStatus, &rootElement->TrustStatus);
diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h
index dbf6dca411..95ee67c6cb 100644
--- a/dlls/crypt32/crypt32_private.h
+++ b/dlls/crypt32/crypt32_private.h
@@ -343,7 +343,7 @@ void CRYPT_ImportSystemRootCertsToReg(void) DECLSPEC_HIDDEN;
BOOL CRYPT_SerializeContextsToReg(HKEY key, DWORD flags, const WINE_CONTEXT_INTERFACE *contextInterface,
HCERTSTORE memStore) DECLSPEC_HIDDEN;
-BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert) DECLSPEC_HIDDEN;
+DWORD CRYPT_IsCertificateSelfSigned(const CERT_CONTEXT *cert) DECLSPEC_HIDDEN;
/* Allocates and initializes a certificate chain engine, but without creating
* the root store. Instead, it uses root, and assumes the caller has done any
--
2.18.0
June 25, 2018
Wine staging 3.11 release
by Alistair Leslie-Hughes
Binary packages for various distributions will be available from:
https://www.winehq.org/download
Summary of the past few weeks
* Rebased to current wine 3.11 (900 patches are applied to wine vanilla)
* Reviewed and upstreamed patches.
Added
* [34989] msi: Implement deferral for standard and custom actions
Where can you help
* Run Steam/Battle.net/UPlay.
* Try you favorite game: Upward lonely robot
* Test your favorite applications.
* Steal staging patches and get them accepted upstream.
As always, if you find a bug, please report it via
https://bugs.winehq.org
Best Regards
Alistair.
June 25, 2018
[PATCH] wininet: Remove checks for negative value.
by Andrey Gusev
Signed-off-by: Andrey Gusev <andrey.goosev(a)gmail.com>
---
dlls/wininet/ftp.c | 2 +-
dlls/wininet/http.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/wininet/ftp.c b/dlls/wininet/ftp.c
index e12e494160..9e4da08fdf 100644
--- a/dlls/wininet/ftp.c
+++ b/dlls/wininet/ftp.c
@@ -3290,7 +3290,7 @@ static BOOL FTP_SendData(ftp_session_t *lpwfs, INT nDataSocket, HANDLE hFile)
{
nBytesToSend = nBytesRead - nBytesSent;
- if (nBytesToSend <= 0)
+ if (nBytesToSend == 0)
{
/* Read data from file. */
nBytesSent = 0;
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index b91dbdf175..3e14049b4e 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -6264,7 +6264,7 @@ static DWORD HTTP_InsertCustomHeader(http_request_t *request, LPHTTPHEADERW lpHd
*/
static BOOL HTTP_DeleteCustomHeader(http_request_t *request, DWORD index)
{
- if( request->nCustHeaders <= 0 )
+ if( request->nCustHeaders == 0 )
return FALSE;
if( index >= request->nCustHeaders )
return FALSE;
--
2.17.1
June 25, 2018
[PATCH] msi: Remove checks for negative value.
by Andrey Gusev
Signed-off-by: Andrey Gusev <andrey.goosev(a)gmail.com>
---
dlls/msi/format.c | 2 +-
dlls/msi/string.c | 2 +-
dlls/msi/table.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/msi/format.c b/dlls/msi/format.c
index 9356c9e30d..2534b8f6a3 100644
--- a/dlls/msi/format.c
+++ b/dlls/msi/format.c
@@ -242,7 +242,7 @@ static WCHAR *deformat_file( FORMAT *format, FORMSTR *str, BOOL shortname, int *
if ((ret = strdupW( file->TargetPath ))) len = strlenW( ret );
goto done;
}
- if ((len = GetShortPathNameW(file->TargetPath, NULL, 0)) <= 0)
+ if ((len = GetShortPathNameW(file->TargetPath, NULL, 0)) == 0)
{
if ((ret = strdupW( file->TargetPath ))) len = strlenW( ret );
goto done;
diff --git a/dlls/msi/string.c b/dlls/msi/string.c
index f094a53c9e..b0e61e5d76 100644
--- a/dlls/msi/string.c
+++ b/dlls/msi/string.c
@@ -246,7 +246,7 @@ static UINT string2id( const string_table *st, const char *buffer, UINT *id )
}
sz = MultiByteToWideChar( st->codepage, 0, buffer, -1, NULL, 0 );
- if( sz <= 0 )
+ if( sz == 0 )
return r;
str = msi_alloc( sz*sizeof(WCHAR) );
if( !str )
diff --git a/dlls/msi/table.c b/dlls/msi/table.c
index 45a181445a..41e313736f 100644
--- a/dlls/msi/table.c
+++ b/dlls/msi/table.c
@@ -1279,7 +1279,7 @@ static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT
UINT r;
int ival;
- if ( (iField <= 0) ||
+ if ( (iField == 0) ||
(iField > tv->num_cols) ||
MSI_RecordIsNull( rec, iField ) )
return ERROR_FUNCTION_FAILED;
--
2.17.1
June 25, 2018
[PATCH] comctl32: Remove checks for negative value.
by Andrey Gusev
Signed-off-by: Andrey Gusev <andrey.goosev(a)gmail.com>
---
dlls/comctl32/rebar.c | 2 +-
dlls/comctl32/tab.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/comctl32/rebar.c b/dlls/comctl32/rebar.c
index 20ce49b3f9..2d00dfd7ca 100644
--- a/dlls/comctl32/rebar.c
+++ b/dlls/comctl32/rebar.c
@@ -2090,7 +2090,7 @@ REBAR_HandleUDDrag (REBAR_INFO *infoPtr, const POINT *ptsmove)
INT iHitBand, iRowBegin, iNextRowBegin;
REBAR_BAND *hitBand, *rowBeginBand;
- if(infoPtr->uNumBands <= 0)
+ if(infoPtr->uNumBands == 0)
ERR("There are no bands in this rebar\n");
/* Up/down dragging can only occur when there is more than one
diff --git a/dlls/comctl32/tab.c b/dlls/comctl32/tab.c
index f8a54935ca..2e17e142f6 100644
--- a/dlls/comctl32/tab.c
+++ b/dlls/comctl32/tab.c
@@ -365,7 +365,7 @@ static BOOL TAB_InternalGetItemRect(
RECT tmpItemRect,clientRect;
/* Perform a sanity check and a trivial visibility check. */
- if ( (infoPtr->uNumItem <= 0) ||
+ if ( (infoPtr->uNumItem == 0) ||
(itemIndex >= infoPtr->uNumItem) ||
(!(((infoPtr->dwStyle & TCS_MULTILINE) || (infoPtr->dwStyle & TCS_VERTICAL))) &&
(itemIndex < infoPtr->leftmostVisible)))
--
2.17.1
June 25, 2018
[PATCH] advapi32: Remove checks for negative value.
by Andrey Gusev
Signed-off-by: Andrey Gusev <andrey.goosev(a)gmail.com>
---
dlls/advapi32/crypt.c | 2 +-
dlls/advapi32/crypt_lmhash.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/advapi32/crypt.c b/dlls/advapi32/crypt.c
index 01d5880423..6ac63e7f08 100644
--- a/dlls/advapi32/crypt.c
+++ b/dlls/advapi32/crypt.c
@@ -661,7 +661,7 @@ BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, ULONG_PTR dwFlags)
}
pProv->refcount--;
- if (pProv->refcount <= 0)
+ if (pProv->refcount == 0)
{
ret = pProv->pFuncs->pCPReleaseContext(pProv->hPrivate, dwFlags);
pProv->dwMagic = 0;
diff --git a/dlls/advapi32/crypt_lmhash.c b/dlls/advapi32/crypt_lmhash.c
index 345c89ddb7..de4fce2511 100644
--- a/dlls/advapi32/crypt_lmhash.c
+++ b/dlls/advapi32/crypt_lmhash.c
@@ -196,7 +196,7 @@ NTSTATUS WINAPI SystemFunction004(const struct ustring *in,
unsigned char deskey[7];
unsigned int crypt_len, ofs;
- if (key->Length<=0)
+ if (key->Length==0)
return STATUS_INVALID_PARAMETER_2;
crypt_len = ((in->Length+7)&~7);
@@ -255,7 +255,7 @@ NTSTATUS WINAPI SystemFunction005(const struct ustring *in,
unsigned char deskey[7];
unsigned int ofs, crypt_len;
- if (key->Length<=0)
+ if (key->Length==0)
return STATUS_INVALID_PARAMETER_2;
if (key->Length<sizeof deskey)
--
2.17.1
June 25, 2018
Re: [PATCH 2/3] comctl32/taskdialog: Add support for radio buttons.
by Zhiyi Zhang
On Mon 6 25 13:22, Nikolay Sivov wrote:
>
>
> On 06/17/2018 11:17 AM, Zhiyi Zhang wrote:
>> Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
>> ---
>> dlls/comctl32/taskdialog.c | 130 ++++++++++++++++++++++-
>> dlls/comctl32/tests/taskdialog.c | 172 +++++++++++++++++++++++++++----
>> 2 files changed, 281 insertions(+), 21 deletions(-)
>>
>> diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
>> index 33fb578910..c3c5fa0420 100644
>> --- a/dlls/comctl32/taskdialog.c
>> +++ b/dlls/comctl32/taskdialog.c
>> @@ -58,6 +58,8 @@ struct taskdialog_info
>> HWND main_instruction;
>> HWND content;
>> HWND progress_bar;
>> + HWND *radio_buttons;
>> + INT radio_button_count;
>> HWND *buttons;
>> INT button_count;
>> HWND default_button;
>> @@ -69,6 +71,7 @@ struct taskdialog_info
>> LONG h_spacing;
>> LONG v_spacing;
>> } m;
>> + INT selected_radio_id;
>> };
>> struct button_layout_info
>> @@ -185,6 +188,18 @@ static void taskdialog_enable_button(const struct taskdialog_info *dialog_info,
>> if (hwnd) EnableWindow(hwnd, enable);
>> }
>> +static void taskdialog_enable_radio_button(const struct taskdialog_info *dialog_info, INT id, BOOL enable)
>> +{
>> + HWND hwnd = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count, id);
>> + if (hwnd) EnableWindow(hwnd, enable);
>> +}
>> +
>> +static void taskdialog_click_radio_button(const struct taskdialog_info *dialog_info, INT id)
>> +{
>> + HWND hwnd = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count, id);
>> + if (hwnd) SendMessageW(hwnd, BM_CLICK, 0, 0);
>> +}
>> +
>> static HRESULT taskdialog_notify(struct taskdialog_info *dialog_info, UINT notification, WPARAM wparam, LPARAM lparam)
>> {
>> const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
>> @@ -193,8 +208,18 @@ static HRESULT taskdialog_notify(struct taskdialog_info *dialog_info, UINT notif
>> : S_OK;
>> }
>> -static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, WORD command_id)
>> +static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, unsigned long command_id)
>
> Why the type change?
>
In taskdialog_check_default_radio_buttons(), id via GetWindowLongW(default_button, GWLP_ID) is passed to
taskdialog_on_button_click(). And id is originally int in pRadioButtons. So WORD is not enough. Tested on
Windows, 0x1FFFF is allowed as a valid id. And on second thought, an INT should be enough.
>> {
>> + HWND radio_button;
>> +
>> + radio_button = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count, command_id);
>> + if (radio_button)
>> + {
>> + dialog_info->selected_radio_id = command_id;
>> + taskdialog_notify(dialog_info, TDN_RADIO_BUTTON_CLICKED, command_id, 0);
>> + return;
>> + }
>> +
>> if (taskdialog_notify(dialog_info, TDN_BUTTON_CLICKED, command_id, 0) == S_OK)
>> EndDialog(dialog_info->hwnd, command_id);
>> }
>> @@ -260,6 +285,40 @@ static void taskdialog_get_label_size(struct taskdialog_info *dialog_info, HWND
>> ReleaseDC(hwnd, hdc);
>> }
>> +static void taskdialog_get_checkbox_height(struct taskdialog_info *dialog_info, HWND hwnd, LONG max_width, SIZE *size)
>
> Do we call that "checkbox" anywhere in wine? It doesn't feel right.
>
>> +{
>> + DWORD style = DT_EXPANDTABS | DT_CALCRECT | DT_WORDBREAK;
>> + HFONT hfont, old_hfont;
>> + HDC hdc;
>> + RECT rect = {0};
>> + WCHAR text[1024];
>
> I think it's better to make this dynamic.
>
>> + INT text_length;
>> + LONG text_offset, checkbox_width, checkbox_height;
>> +
>> + hdc = GetDC(hwnd);
>> + hfont = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0);
>> + old_hfont = SelectObject(hdc, hfont);
>> +
>> + checkbox_width = 12 * GetDeviceCaps(hdc, LOGPIXELSX) / 96 + 1;
>> + checkbox_height = 12 * GetDeviceCaps(hdc, LOGPIXELSY) / 96 + 1;
>> + GetCharWidthW(hdc, '0', '0', &text_offset);
>> + text_offset /= 2;
>> +
>> + if (dialog_info->taskconfig->dwFlags & TDF_RTL_LAYOUT)
>> + style |= DT_RIGHT | DT_RTLREADING;
>> + else
>> + style |= DT_LEFT;
>> +
>> + rect.right = max_width - checkbox_width - text_offset;
>> + text_length = GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
>> + size->cy = DrawTextW(hdc, text, text_length, &rect, style);
>> + size->cx = min(max_width - checkbox_width - text_offset, rect.right - rect.left);
>> + size->cx += checkbox_width + text_offset;
>> + size->cy = max(size->cy, checkbox_height);
>> + if (old_hfont) SelectObject(hdc, old_hfont);
>> + ReleaseDC(hwnd, hdc);
>> +}
>> +
>> static ULONG_PTR taskdialog_get_standard_icon(LPCWSTR icon)
>> {
>> if (icon == TD_WARNING_ICON)
>> @@ -300,6 +359,28 @@ static void taskdialog_set_icon(struct taskdialog_info *dialog_info, INT element
>> }
>> }
>> +static void taskdialog_check_default_radio_buttons(struct taskdialog_info *dialog_info)
>> +{
>> + const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
>> + HWND default_button;
>> + INT id;
>> +
>> + if (!dialog_info->radio_button_count) return;
>> +
>> + default_button = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count,
>> + taskconfig->nDefaultRadioButton);
>> +
>> + if (!default_button && !(taskconfig->dwFlags & TDF_NO_DEFAULT_RADIO_BUTTON))
>> + default_button = dialog_info->radio_buttons[0];
>> +
>> + if (default_button)
>> + {
>> + SendMessageW(default_button, BM_SETCHECK, BST_CHECKED, 0);
>> + id = GetWindowLongW(default_button, GWLP_ID);
>> + taskdialog_on_button_click(dialog_info, id);
>> + }
>> +}
>> +
>> static void taskdialog_add_main_icon(struct taskdialog_info *dialog_info)
>> {
>> if (!dialog_info->taskconfig->u.hMainIcon) return;
>> @@ -363,6 +444,30 @@ static void taskdialog_add_progress_bar(struct taskdialog_info *dialog_info)
>> CreateWindowW(PROGRESS_CLASSW, NULL, style, 0, 0, 0, 0, dialog_info->hwnd, NULL, 0, NULL);
>> }
>> +static void taskdialog_add_radio_buttons(struct taskdialog_info *dialog_info)
>> +{
>> + const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
>> + static const DWORD style = BS_AUTORADIOBUTTON | BS_MULTILINE | BS_TOP | WS_CHILD | WS_VISIBLE | WS_TABSTOP;
>> + WCHAR *textW;
>> + INT i;
>> +
>> + if (!taskconfig->cRadioButtons || !taskconfig->pRadioButtons) return;
>> +
>> + dialog_info->radio_buttons = Alloc(taskconfig->cRadioButtons * sizeof(*dialog_info->radio_buttons));
>> + if (!dialog_info->radio_buttons) return;
>> +
>> + dialog_info->radio_button_count = taskconfig->cRadioButtons;
>> + for (i = 0; i < dialog_info->radio_button_count; i++)
>> + {
>> + textW = taskdialog_gettext(dialog_info, TRUE, taskconfig->pRadioButtons[i].pszButtonText);
>> + dialog_info->radio_buttons[i] =
>> + CreateWindowW(WC_BUTTONW, textW, i == 0 ? style | WS_GROUP : style, 0, 0, 0, 0, dialog_info->hwnd,
>> + (HMENU)taskconfig->pRadioButtons[i].nButtonID, 0, NULL);
>> + SendMessageW(dialog_info->radio_buttons[i], WM_SETFONT, (WPARAM)dialog_info->font, 0);
>> + Free(textW);
>> + }
>> +}
>> +
>> static void taskdialog_add_button(struct taskdialog_info *dialog_info, HWND *button, INT_PTR id, const WCHAR *text,
>> BOOL custom_button)
>> {
>> @@ -487,6 +592,17 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
>> dialog_height = y + size.cy;
>> }
>> + /* Radio buttons */
>> + for (i = 0; i < dialog_info->radio_button_count; i++)
>> + {
>> + x = main_icon_right + h_spacing;
>> + y = dialog_height;
>> + taskdialog_get_checkbox_height(dialog_info, dialog_info->radio_buttons[i], dialog_width - x - h_spacing, &size);
>> + size.cx = dialog_width - x - h_spacing;
>> + SetWindowPos(dialog_info->radio_buttons[i], 0, x, y, size.cx, size.cy, SWP_NOZORDER);
>> + dialog_height = y + size.cy;
>> + }
>> +
>> dialog_height = max(dialog_height, main_icon_bottom);
>> /* Common and custom buttons */
>> @@ -621,6 +737,7 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
>> taskdialog_add_main_instruction(dialog_info);
>> taskdialog_add_content(dialog_info);
>> taskdialog_add_progress_bar(dialog_info);
>> + taskdialog_add_radio_buttons(dialog_info);
>> taskdialog_add_buttons(dialog_info);
>> /* Set default button */
>> @@ -638,6 +755,7 @@ static void taskdialog_destroy(struct taskdialog_info *dialog_info)
>> if (dialog_info->font) DeleteObject(dialog_info->font);
>> if (dialog_info->main_instruction_font) DeleteObject(dialog_info->main_instruction_font);
>> if (dialog_info->buttons) Free(dialog_info->buttons);
>> + if (dialog_info->radio_buttons) Free(dialog_info->radio_buttons);
>> }
>> static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
>> @@ -689,6 +807,12 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
>> case TDM_SET_PROGRESS_BAR_MARQUEE:
>> SendMessageW(dialog_info->progress_bar, PBM_SETMARQUEE, wParam, lParam);
>> break;
>> + case TDM_CLICK_RADIO_BUTTON:
>> + taskdialog_click_radio_button(dialog_info, wParam);
>> + break;
>> + case TDM_ENABLE_RADIO_BUTTON:
>> + taskdialog_enable_radio_button(dialog_info, wParam, lParam);
>> + break;
>> case WM_INITDIALOG:
>> dialog_info = (struct taskdialog_info *)lParam;
>> @@ -697,6 +821,8 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
>> SetPropW(hwnd, taskdialog_info_propnameW, dialog_info);
>> taskdialog_notify(dialog_info, TDN_DIALOG_CONSTRUCTED, 0, 0);
>> taskdialog_notify(dialog_info, TDN_CREATED, 0, 0);
>> + /* Default radio button click notification sent after TDN_CREATED */
>> + taskdialog_check_default_radio_buttons(dialog_info);
>> return FALSE;
>> case WM_COMMAND:
>> if (HIWORD(wParam) == BN_CLICKED)
>> @@ -762,7 +888,7 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *taskconfig, int *butto
>> Free(template);
>> if (button) *button = ret;
>> - if (radio_button) *radio_button = taskconfig->nDefaultButton;
>> + if (radio_button) *radio_button = dialog_info.selected_radio_id;
>> if (verification_flag_checked) *verification_flag_checked = TRUE;
>> return S_OK;
>> diff --git a/dlls/comctl32/tests/taskdialog.c b/dlls/comctl32/tests/taskdialog.c
>> index e91a878876..2cda04081f 100644
>> --- a/dlls/comctl32/tests/taskdialog.c
>> +++ b/dlls/comctl32/tests/taskdialog.c
>> @@ -35,9 +35,11 @@
>> #define TASKDIALOG_SEQ_INDEX 0
>> #define TEST_NUM_BUTTONS 10 /* Number of custom buttons to test with */
>> +#define TEST_NUM_RADIO_BUTTONS 3
>> #define ID_START 20 /* Lower IDs might be used by the system */
>> #define ID_START_BUTTON (ID_START + 0)
>> +#define ID_START_RADIO_BUTTON (ID_START + 20)
>> static HRESULT (WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *, int *, int *, BOOL *);
>> static HRESULT (WINAPI *pTaskDialog)(HWND, HINSTANCE, const WCHAR *, const WCHAR *, const WCHAR *,
>> @@ -141,6 +143,78 @@ static const struct message_info msg_got_tdn_help[] =
>> { 0 }
>> };
>> +/* Three radio buttons */
>> +static const struct message_info msg_return_default_radio_button_1[] =
>> +{
>> + { TDN_CREATED, 0, 0, S_OK, NULL },
>> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_click_ok },
>> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
>> + { 0 }
>> +};
>> +
>> +static const struct message_info msg_return_default_radio_button_2[] =
>> +{
>> + { TDN_CREATED, 0, 0, S_OK, NULL },
>> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_send_click_ok },
>> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
>> + { 0 }
>> +};
>> +
>> +static const struct message_info msg_return_default_radio_button_3[] =
>> +{
>> + { TDN_CREATED, 0, 0, S_OK, NULL },
>> + { TDN_RADIO_BUTTON_CLICKED, -2, 0, S_OK, msg_send_click_ok },
>> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
>> + { 0 }
>> +};
>> +
>> +static const struct message_info msg_select_first_radio_button[] =
>> +{
>> + { TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
>> + { 0 }
>> +};
>> +
>> +static const struct message_info msg_return_first_radio_button[] =
>> +{
>> + { TDN_CREATED, 0, 0, S_OK, NULL },
>> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_select_first_radio_button },
>> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_click_ok },
>> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
>> + { 0 }
>> +};
>> +
>> +static const struct message_info msg_select_first_disabled_radio_button_and_press_ok[] =
>> +{
>> + { TDM_ENABLE_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
>> + { TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
>> + { TDM_CLICK_BUTTON, IDOK, 0 },
>> + { 0 }
>> +};
>> +
>> +static const struct message_info msg_return_default_radio_button_clicking_disabled[] =
>> +{
>> + { TDN_CREATED, 0, 0, S_OK, NULL },
>> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_select_first_disabled_radio_button_and_press_ok },
>> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
>> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
>> + { 0 }
>> +};
>> +
>> +static const struct message_info msg_return_no_default_radio_button_flag[] =
>> +{
>> + { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
>> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
>> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
>> + { 0 }
>> +};
>> +
>> +static const struct message_info msg_return_no_default_radio_button_id_and_flag[] =
>> +{
>> + { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
>> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
>> + { 0 }
>> +};
>> +
>> static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct message *msg)
>> {
>> msg->message = WM_TD_CALLBACK;
>> @@ -151,11 +225,13 @@ static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct
>> msg->stage = 0;
>> }
>> -#define run_test(info, expect_button, seq, context) \
>> - run_test_(info, expect_button, seq, context, ARRAY_SIZE(seq) - 1, __FILE__, __LINE__)
>> +#define run_test(info, expect_button, expect_radio_button, seq, context) \
>> + run_test_(info, expect_button, expect_radio_button, seq, context, \
>> + ARRAY_SIZE(seq) - 1, __FILE__, __LINE__)
>> -static void run_test_(TASKDIALOGCONFIG *info, int expect_button, const struct message_info *test_messages,
>> - const char *context, int test_messages_len, const char *file, int line)
>> +static void run_test_(TASKDIALOGCONFIG *info, int expect_button, int expect_radio_button,
>> + const struct message_info *test_messages, const char *context, int test_messages_len,
>> + const char *file, int line)
>> {
>> struct message *msg, *msg_start;
>> int ret_button = 0;
>> @@ -182,6 +258,8 @@ static void run_test_(TASKDIALOGCONFIG *info, int expect_button, const struct me
>> ok_sequence_(sequences, TASKDIALOG_SEQ_INDEX, msg_start, context, FALSE, file, line);
>> ok_(file, line)(ret_button == expect_button,
>> "Wrong button. Expected %d, got %d\n", expect_button, ret_button);
>> + ok_(file, line)(ret_radio == expect_radio_button,
>> + "Wrong radio button. Expected %d, got %d\n", expect_radio_button, ret_radio);
>> heap_free(msg_start);
>> }
>> @@ -239,16 +317,17 @@ static void test_callback(void)
>> info.pfCallback = taskdialog_callback_proc;
>> info.lpCallbackData = test_ref_data;
>> - run_test(&info, IDOK, msg_return_press_ok, "Press VK_RETURN.");
>> + run_test(&info, IDOK, 0, msg_return_press_ok, "Press VK_RETURN.");
>> }
>> static void test_buttons(void)
>> {
>> TASKDIALOGCONFIG info = {0};
>> - TASKDIALOG_BUTTON custom_buttons[TEST_NUM_BUTTONS];
>> + TASKDIALOG_BUTTON custom_buttons[TEST_NUM_BUTTONS], radio_buttons[TEST_NUM_RADIO_BUTTONS];
>> const WCHAR button_format[] = {'%','0','2','d',0};
>> - WCHAR button_titles[TEST_NUM_BUTTONS * 3]; /* Each button has two digits as title, plus null-terminator */
>> + /* Each button has two digits as title, plus null-terminator */
>> + WCHAR button_titles[TEST_NUM_BUTTONS * 3], radio_button_titles[TEST_NUM_BUTTONS * 3];
>> int i;
>> info.cbSize = sizeof(TASKDIALOGCONFIG);
>> @@ -266,48 +345,103 @@ static void test_buttons(void)
>> }
>> custom_buttons[TEST_NUM_BUTTONS - 1].nButtonID = -1;
>> + /* Init radio buttons */
>> + for (i = 0; i < TEST_NUM_RADIO_BUTTONS; i++)
>> + {
>> + WCHAR *text = &radio_button_titles[i * 3];
>> + wsprintfW(text, button_format, i);
>> +
>> + radio_buttons[i].pszButtonText = text;
>> + radio_buttons[i].nButtonID = ID_START_RADIO_BUTTON + i;
>> + }
>> + radio_buttons[TEST_NUM_RADIO_BUTTONS - 1].nButtonID = -2;
>> +
>> /* Test nDefaultButton */
>> /* Test common buttons with invalid default ID */
>> info.nDefaultButton = 0; /* Should default to first created button */
>> info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
>> | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
>> - run_test(&info, IDOK, msg_return_press_ok, "default button: unset default");
>> + run_test(&info, IDOK, 0, msg_return_press_ok, "default button: unset default");
>> info.dwCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
>> | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
>> - run_test(&info, IDYES, msg_return_press_yes, "default button: unset default");
>> + run_test(&info, IDYES, 0, msg_return_press_yes, "default button: unset default");
>> info.dwCommonButtons = TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
>> - run_test(&info, IDNO, msg_return_press_no, "default button: unset default");
>> + run_test(&info, IDNO, 0, msg_return_press_no, "default button: unset default");
>> info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
>> - run_test(&info, IDRETRY, msg_return_press_retry, "default button: unset default");
>> + run_test(&info, IDRETRY, 0, msg_return_press_retry, "default button: unset default");
>> info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_CLOSE_BUTTON;
>> - run_test(&info, IDCANCEL, msg_return_press_cancel, "default button: unset default");
>> + run_test(&info, IDCANCEL, 0, msg_return_press_cancel, "default button: unset default");
>> /* Test with all common and custom buttons and invalid default ID */
>> info.nDefaultButton = 0xff; /* Random ID, should also default to first created button */
>> info.cButtons = TEST_NUM_BUTTONS;
>> info.pButtons = custom_buttons;
>> - run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button: invalid default, with common buttons - 1");
>> + run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, with common buttons - 1");
>> info.nDefaultButton = -1; /* Should work despite button ID -1 */
>> - run_test(&info, -1, msg_return_press_custom10, "default button: invalid default, with common buttons - 2");
>> + run_test(&info, -1, 0, msg_return_press_custom10, "default button: invalid default, with common buttons - 2");
>> info.nDefaultButton = -2; /* Should also default to first created button */
>> - run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button: invalid default, with common buttons - 3");
>> + run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, with common buttons - 3");
>> /* Test with only custom buttons and invalid default ID */
>> info.dwCommonButtons = 0;
>> - run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button: invalid default, no common buttons");
>> + run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, no common buttons");
>> /* Test with common and custom buttons and valid default ID */
>> info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
>> | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
>> info.nDefaultButton = IDRETRY;
>> - run_test(&info, IDRETRY, msg_return_press_retry, "default button: valid default - 1");
>> + run_test(&info, IDRETRY, 0, msg_return_press_retry, "default button: valid default - 1");
>> /* Test with common and custom buttons and valid default ID */
>> info.nDefaultButton = ID_START_BUTTON + 3;
>> - run_test(&info, ID_START_BUTTON + 3, msg_return_press_custom4, "default button: valid default - 2");
>> + run_test(&info, ID_START_BUTTON + 3, 0, msg_return_press_custom4, "default button: valid default - 2");
>> +
>> + /* Test radio buttons */
>> + info.nDefaultButton = 0;
>> + info.cButtons = 0;
>> + info.pButtons = 0;
>> + info.dwCommonButtons = TDCBF_OK_BUTTON;
>> + info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
>> + info.pRadioButtons = radio_buttons;
>> +
>> + /* Test default first radio button */
>> + run_test(&info, IDOK, ID_START_RADIO_BUTTON, msg_return_default_radio_button_1, "default radio button: default first radio button");
>> +
>> + /* Test default radio button */
>> + info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
>> + run_test(&info, IDOK, info.nDefaultRadioButton, msg_return_default_radio_button_2, "default radio button: default radio button");
>> +
>> + /* Test default radio button with -2 */
>> + info.nDefaultRadioButton = -2;
>> + run_test(&info, IDOK, info.nDefaultRadioButton, msg_return_default_radio_button_3, "default radio button: default radio button with id -2");
>> +
>> + /* Test default radio button after clicking the first, messages still work even radio button is disabled */
>> + info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
>> + run_test(&info, IDOK, ID_START_RADIO_BUTTON, msg_return_first_radio_button, "default radio button: radio button after clicking");
>> +
>> + /* Test radio button after disabling and clicking the first */
>> + info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
>> + run_test(&info, IDOK, ID_START_RADIO_BUTTON, msg_return_default_radio_button_clicking_disabled, "default radio button: disable radio button before clicking");
>> +
>> + /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set, TDN_RADIO_BUTTON_CLICKED will still be received, just radio button not selected */
>> + info.nDefaultRadioButton = ID_START_RADIO_BUTTON;
>> + info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
>> + run_test(&info, IDOK, info.nDefaultRadioButton, msg_return_no_default_radio_button_flag, "default radio button: no default radio flag");
>> +
>> + /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and nDefaultRadioButton is 0.
>> + * TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
>> + info.nDefaultRadioButton = 0;
>> + info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
>> + run_test(&info, IDOK, 0, msg_return_no_default_radio_button_id_and_flag, "default radio button: no default radio id and flag");
>> +
>> + /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and nDefaultRadioButton is invalid.
>> + * TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
>> + info.nDefaultRadioButton = 0xff;
>> + info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
>> + run_test(&info, IDOK, 0, msg_return_no_default_radio_button_id_and_flag, "default radio button: no default flag, invalid id");
>> }
>> static void test_help(void)
>> @@ -319,7 +453,7 @@ static void test_help(void)
>> info.lpCallbackData = test_ref_data;
>> info.dwCommonButtons = TDCBF_OK_BUTTON;
>> - run_test(&info, IDOK, msg_got_tdn_help, "send f1");
>> + run_test(&info, IDOK, 0, msg_got_tdn_help, "send f1");
>> }
>> struct timer_notification_data
>
>
>
June 25, 2018
Re: [PATCH 2/3] comctl32/taskdialog: Add support for radio buttons.
by Nikolay Sivov
On 06/17/2018 11:17 AM, Zhiyi Zhang wrote:
> Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
> ---
> dlls/comctl32/taskdialog.c | 130 ++++++++++++++++++++++-
> dlls/comctl32/tests/taskdialog.c | 172 +++++++++++++++++++++++++++----
> 2 files changed, 281 insertions(+), 21 deletions(-)
>
> diff --git a/dlls/comctl32/taskdialog.c b/dlls/comctl32/taskdialog.c
> index 33fb578910..c3c5fa0420 100644
> --- a/dlls/comctl32/taskdialog.c
> +++ b/dlls/comctl32/taskdialog.c
> @@ -58,6 +58,8 @@ struct taskdialog_info
> HWND main_instruction;
> HWND content;
> HWND progress_bar;
> + HWND *radio_buttons;
> + INT radio_button_count;
> HWND *buttons;
> INT button_count;
> HWND default_button;
> @@ -69,6 +71,7 @@ struct taskdialog_info
> LONG h_spacing;
> LONG v_spacing;
> } m;
> + INT selected_radio_id;
> };
>
> struct button_layout_info
> @@ -185,6 +188,18 @@ static void taskdialog_enable_button(const struct taskdialog_info *dialog_info,
> if (hwnd) EnableWindow(hwnd, enable);
> }
>
> +static void taskdialog_enable_radio_button(const struct taskdialog_info *dialog_info, INT id, BOOL enable)
> +{
> + HWND hwnd = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count, id);
> + if (hwnd) EnableWindow(hwnd, enable);
> +}
> +
> +static void taskdialog_click_radio_button(const struct taskdialog_info *dialog_info, INT id)
> +{
> + HWND hwnd = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count, id);
> + if (hwnd) SendMessageW(hwnd, BM_CLICK, 0, 0);
> +}
> +
> static HRESULT taskdialog_notify(struct taskdialog_info *dialog_info, UINT notification, WPARAM wparam, LPARAM lparam)
> {
> const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
> @@ -193,8 +208,18 @@ static HRESULT taskdialog_notify(struct taskdialog_info *dialog_info, UINT notif
> : S_OK;
> }
>
> -static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, WORD command_id)
> +static void taskdialog_on_button_click(struct taskdialog_info *dialog_info, unsigned long command_id)
Why the type change?
> {
> + HWND radio_button;
> +
> + radio_button = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count, command_id);
> + if (radio_button)
> + {
> + dialog_info->selected_radio_id = command_id;
> + taskdialog_notify(dialog_info, TDN_RADIO_BUTTON_CLICKED, command_id, 0);
> + return;
> + }
> +
> if (taskdialog_notify(dialog_info, TDN_BUTTON_CLICKED, command_id, 0) == S_OK)
> EndDialog(dialog_info->hwnd, command_id);
> }
> @@ -260,6 +285,40 @@ static void taskdialog_get_label_size(struct taskdialog_info *dialog_info, HWND
> ReleaseDC(hwnd, hdc);
> }
>
> +static void taskdialog_get_checkbox_height(struct taskdialog_info *dialog_info, HWND hwnd, LONG max_width, SIZE *size)
Do we call that "checkbox" anywhere in wine? It doesn't feel right.
> +{
> + DWORD style = DT_EXPANDTABS | DT_CALCRECT | DT_WORDBREAK;
> + HFONT hfont, old_hfont;
> + HDC hdc;
> + RECT rect = {0};
> + WCHAR text[1024];
I think it's better to make this dynamic.
> + INT text_length;
> + LONG text_offset, checkbox_width, checkbox_height;
> +
> + hdc = GetDC(hwnd);
> + hfont = (HFONT)SendMessageW(hwnd, WM_GETFONT, 0, 0);
> + old_hfont = SelectObject(hdc, hfont);
> +
> + checkbox_width = 12 * GetDeviceCaps(hdc, LOGPIXELSX) / 96 + 1;
> + checkbox_height = 12 * GetDeviceCaps(hdc, LOGPIXELSY) / 96 + 1;
> + GetCharWidthW(hdc, '0', '0', &text_offset);
> + text_offset /= 2;
> +
> + if (dialog_info->taskconfig->dwFlags & TDF_RTL_LAYOUT)
> + style |= DT_RIGHT | DT_RTLREADING;
> + else
> + style |= DT_LEFT;
> +
> + rect.right = max_width - checkbox_width - text_offset;
> + text_length = GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
> + size->cy = DrawTextW(hdc, text, text_length, &rect, style);
> + size->cx = min(max_width - checkbox_width - text_offset, rect.right - rect.left);
> + size->cx += checkbox_width + text_offset;
> + size->cy = max(size->cy, checkbox_height);
> + if (old_hfont) SelectObject(hdc, old_hfont);
> + ReleaseDC(hwnd, hdc);
> +}
> +
> static ULONG_PTR taskdialog_get_standard_icon(LPCWSTR icon)
> {
> if (icon == TD_WARNING_ICON)
> @@ -300,6 +359,28 @@ static void taskdialog_set_icon(struct taskdialog_info *dialog_info, INT element
> }
> }
>
> +static void taskdialog_check_default_radio_buttons(struct taskdialog_info *dialog_info)
> +{
> + const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
> + HWND default_button;
> + INT id;
> +
> + if (!dialog_info->radio_button_count) return;
> +
> + default_button = taskdialog_find_button(dialog_info->radio_buttons, dialog_info->radio_button_count,
> + taskconfig->nDefaultRadioButton);
> +
> + if (!default_button && !(taskconfig->dwFlags & TDF_NO_DEFAULT_RADIO_BUTTON))
> + default_button = dialog_info->radio_buttons[0];
> +
> + if (default_button)
> + {
> + SendMessageW(default_button, BM_SETCHECK, BST_CHECKED, 0);
> + id = GetWindowLongW(default_button, GWLP_ID);
> + taskdialog_on_button_click(dialog_info, id);
> + }
> +}
> +
> static void taskdialog_add_main_icon(struct taskdialog_info *dialog_info)
> {
> if (!dialog_info->taskconfig->u.hMainIcon) return;
> @@ -363,6 +444,30 @@ static void taskdialog_add_progress_bar(struct taskdialog_info *dialog_info)
> CreateWindowW(PROGRESS_CLASSW, NULL, style, 0, 0, 0, 0, dialog_info->hwnd, NULL, 0, NULL);
> }
>
> +static void taskdialog_add_radio_buttons(struct taskdialog_info *dialog_info)
> +{
> + const TASKDIALOGCONFIG *taskconfig = dialog_info->taskconfig;
> + static const DWORD style = BS_AUTORADIOBUTTON | BS_MULTILINE | BS_TOP | WS_CHILD | WS_VISIBLE | WS_TABSTOP;
> + WCHAR *textW;
> + INT i;
> +
> + if (!taskconfig->cRadioButtons || !taskconfig->pRadioButtons) return;
> +
> + dialog_info->radio_buttons = Alloc(taskconfig->cRadioButtons * sizeof(*dialog_info->radio_buttons));
> + if (!dialog_info->radio_buttons) return;
> +
> + dialog_info->radio_button_count = taskconfig->cRadioButtons;
> + for (i = 0; i < dialog_info->radio_button_count; i++)
> + {
> + textW = taskdialog_gettext(dialog_info, TRUE, taskconfig->pRadioButtons[i].pszButtonText);
> + dialog_info->radio_buttons[i] =
> + CreateWindowW(WC_BUTTONW, textW, i == 0 ? style | WS_GROUP : style, 0, 0, 0, 0, dialog_info->hwnd,
> + (HMENU)taskconfig->pRadioButtons[i].nButtonID, 0, NULL);
> + SendMessageW(dialog_info->radio_buttons[i], WM_SETFONT, (WPARAM)dialog_info->font, 0);
> + Free(textW);
> + }
> +}
> +
> static void taskdialog_add_button(struct taskdialog_info *dialog_info, HWND *button, INT_PTR id, const WCHAR *text,
> BOOL custom_button)
> {
> @@ -487,6 +592,17 @@ static void taskdialog_layout(struct taskdialog_info *dialog_info)
> dialog_height = y + size.cy;
> }
>
> + /* Radio buttons */
> + for (i = 0; i < dialog_info->radio_button_count; i++)
> + {
> + x = main_icon_right + h_spacing;
> + y = dialog_height;
> + taskdialog_get_checkbox_height(dialog_info, dialog_info->radio_buttons[i], dialog_width - x - h_spacing, &size);
> + size.cx = dialog_width - x - h_spacing;
> + SetWindowPos(dialog_info->radio_buttons[i], 0, x, y, size.cx, size.cy, SWP_NOZORDER);
> + dialog_height = y + size.cy;
> + }
> +
> dialog_height = max(dialog_height, main_icon_bottom);
>
> /* Common and custom buttons */
> @@ -621,6 +737,7 @@ static void taskdialog_init(struct taskdialog_info *dialog_info, HWND hwnd)
> taskdialog_add_main_instruction(dialog_info);
> taskdialog_add_content(dialog_info);
> taskdialog_add_progress_bar(dialog_info);
> + taskdialog_add_radio_buttons(dialog_info);
> taskdialog_add_buttons(dialog_info);
>
> /* Set default button */
> @@ -638,6 +755,7 @@ static void taskdialog_destroy(struct taskdialog_info *dialog_info)
> if (dialog_info->font) DeleteObject(dialog_info->font);
> if (dialog_info->main_instruction_font) DeleteObject(dialog_info->main_instruction_font);
> if (dialog_info->buttons) Free(dialog_info->buttons);
> + if (dialog_info->radio_buttons) Free(dialog_info->radio_buttons);
> }
>
> static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
> @@ -689,6 +807,12 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
> case TDM_SET_PROGRESS_BAR_MARQUEE:
> SendMessageW(dialog_info->progress_bar, PBM_SETMARQUEE, wParam, lParam);
> break;
> + case TDM_CLICK_RADIO_BUTTON:
> + taskdialog_click_radio_button(dialog_info, wParam);
> + break;
> + case TDM_ENABLE_RADIO_BUTTON:
> + taskdialog_enable_radio_button(dialog_info, wParam, lParam);
> + break;
> case WM_INITDIALOG:
> dialog_info = (struct taskdialog_info *)lParam;
>
> @@ -697,6 +821,8 @@ static INT_PTR CALLBACK taskdialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
> SetPropW(hwnd, taskdialog_info_propnameW, dialog_info);
> taskdialog_notify(dialog_info, TDN_DIALOG_CONSTRUCTED, 0, 0);
> taskdialog_notify(dialog_info, TDN_CREATED, 0, 0);
> + /* Default radio button click notification sent after TDN_CREATED */
> + taskdialog_check_default_radio_buttons(dialog_info);
> return FALSE;
> case WM_COMMAND:
> if (HIWORD(wParam) == BN_CLICKED)
> @@ -762,7 +888,7 @@ HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *taskconfig, int *butto
> Free(template);
>
> if (button) *button = ret;
> - if (radio_button) *radio_button = taskconfig->nDefaultButton;
> + if (radio_button) *radio_button = dialog_info.selected_radio_id;
> if (verification_flag_checked) *verification_flag_checked = TRUE;
>
> return S_OK;
> diff --git a/dlls/comctl32/tests/taskdialog.c b/dlls/comctl32/tests/taskdialog.c
> index e91a878876..2cda04081f 100644
> --- a/dlls/comctl32/tests/taskdialog.c
> +++ b/dlls/comctl32/tests/taskdialog.c
> @@ -35,9 +35,11 @@
> #define TASKDIALOG_SEQ_INDEX 0
>
> #define TEST_NUM_BUTTONS 10 /* Number of custom buttons to test with */
> +#define TEST_NUM_RADIO_BUTTONS 3
>
> #define ID_START 20 /* Lower IDs might be used by the system */
> #define ID_START_BUTTON (ID_START + 0)
> +#define ID_START_RADIO_BUTTON (ID_START + 20)
>
> static HRESULT (WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *, int *, int *, BOOL *);
> static HRESULT (WINAPI *pTaskDialog)(HWND, HINSTANCE, const WCHAR *, const WCHAR *, const WCHAR *,
> @@ -141,6 +143,78 @@ static const struct message_info msg_got_tdn_help[] =
> { 0 }
> };
>
> +/* Three radio buttons */
> +static const struct message_info msg_return_default_radio_button_1[] =
> +{
> + { TDN_CREATED, 0, 0, S_OK, NULL },
> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_click_ok },
> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
> + { 0 }
> +};
> +
> +static const struct message_info msg_return_default_radio_button_2[] =
> +{
> + { TDN_CREATED, 0, 0, S_OK, NULL },
> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_send_click_ok },
> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
> + { 0 }
> +};
> +
> +static const struct message_info msg_return_default_radio_button_3[] =
> +{
> + { TDN_CREATED, 0, 0, S_OK, NULL },
> + { TDN_RADIO_BUTTON_CLICKED, -2, 0, S_OK, msg_send_click_ok },
> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
> + { 0 }
> +};
> +
> +static const struct message_info msg_select_first_radio_button[] =
> +{
> + { TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
> + { 0 }
> +};
> +
> +static const struct message_info msg_return_first_radio_button[] =
> +{
> + { TDN_CREATED, 0, 0, S_OK, NULL },
> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_select_first_radio_button },
> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_click_ok },
> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
> + { 0 }
> +};
> +
> +static const struct message_info msg_select_first_disabled_radio_button_and_press_ok[] =
> +{
> + { TDM_ENABLE_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
> + { TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
> + { TDM_CLICK_BUTTON, IDOK, 0 },
> + { 0 }
> +};
> +
> +static const struct message_info msg_return_default_radio_button_clicking_disabled[] =
> +{
> + { TDN_CREATED, 0, 0, S_OK, NULL },
> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_select_first_disabled_radio_button_and_press_ok },
> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
> + { 0 }
> +};
> +
> +static const struct message_info msg_return_no_default_radio_button_flag[] =
> +{
> + { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
> + { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
> + { 0 }
> +};
> +
> +static const struct message_info msg_return_no_default_radio_button_id_and_flag[] =
> +{
> + { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
> + { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
> + { 0 }
> +};
> +
> static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct message *msg)
> {
> msg->message = WM_TD_CALLBACK;
> @@ -151,11 +225,13 @@ static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct
> msg->stage = 0;
> }
>
> -#define run_test(info, expect_button, seq, context) \
> - run_test_(info, expect_button, seq, context, ARRAY_SIZE(seq) - 1, __FILE__, __LINE__)
> +#define run_test(info, expect_button, expect_radio_button, seq, context) \
> + run_test_(info, expect_button, expect_radio_button, seq, context, \
> + ARRAY_SIZE(seq) - 1, __FILE__, __LINE__)
>
> -static void run_test_(TASKDIALOGCONFIG *info, int expect_button, const struct message_info *test_messages,
> - const char *context, int test_messages_len, const char *file, int line)
> +static void run_test_(TASKDIALOGCONFIG *info, int expect_button, int expect_radio_button,
> + const struct message_info *test_messages, const char *context, int test_messages_len,
> + const char *file, int line)
> {
> struct message *msg, *msg_start;
> int ret_button = 0;
> @@ -182,6 +258,8 @@ static void run_test_(TASKDIALOGCONFIG *info, int expect_button, const struct me
> ok_sequence_(sequences, TASKDIALOG_SEQ_INDEX, msg_start, context, FALSE, file, line);
> ok_(file, line)(ret_button == expect_button,
> "Wrong button. Expected %d, got %d\n", expect_button, ret_button);
> + ok_(file, line)(ret_radio == expect_radio_button,
> + "Wrong radio button. Expected %d, got %d\n", expect_radio_button, ret_radio);
>
> heap_free(msg_start);
> }
> @@ -239,16 +317,17 @@ static void test_callback(void)
> info.pfCallback = taskdialog_callback_proc;
> info.lpCallbackData = test_ref_data;
>
> - run_test(&info, IDOK, msg_return_press_ok, "Press VK_RETURN.");
> + run_test(&info, IDOK, 0, msg_return_press_ok, "Press VK_RETURN.");
> }
>
> static void test_buttons(void)
> {
> TASKDIALOGCONFIG info = {0};
>
> - TASKDIALOG_BUTTON custom_buttons[TEST_NUM_BUTTONS];
> + TASKDIALOG_BUTTON custom_buttons[TEST_NUM_BUTTONS], radio_buttons[TEST_NUM_RADIO_BUTTONS];
> const WCHAR button_format[] = {'%','0','2','d',0};
> - WCHAR button_titles[TEST_NUM_BUTTONS * 3]; /* Each button has two digits as title, plus null-terminator */
> + /* Each button has two digits as title, plus null-terminator */
> + WCHAR button_titles[TEST_NUM_BUTTONS * 3], radio_button_titles[TEST_NUM_BUTTONS * 3];
> int i;
>
> info.cbSize = sizeof(TASKDIALOGCONFIG);
> @@ -266,48 +345,103 @@ static void test_buttons(void)
> }
> custom_buttons[TEST_NUM_BUTTONS - 1].nButtonID = -1;
>
> + /* Init radio buttons */
> + for (i = 0; i < TEST_NUM_RADIO_BUTTONS; i++)
> + {
> + WCHAR *text = &radio_button_titles[i * 3];
> + wsprintfW(text, button_format, i);
> +
> + radio_buttons[i].pszButtonText = text;
> + radio_buttons[i].nButtonID = ID_START_RADIO_BUTTON + i;
> + }
> + radio_buttons[TEST_NUM_RADIO_BUTTONS - 1].nButtonID = -2;
> +
> /* Test nDefaultButton */
>
> /* Test common buttons with invalid default ID */
> info.nDefaultButton = 0; /* Should default to first created button */
> info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
> | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
> - run_test(&info, IDOK, msg_return_press_ok, "default button: unset default");
> + run_test(&info, IDOK, 0, msg_return_press_ok, "default button: unset default");
> info.dwCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
> | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
> - run_test(&info, IDYES, msg_return_press_yes, "default button: unset default");
> + run_test(&info, IDYES, 0, msg_return_press_yes, "default button: unset default");
> info.dwCommonButtons = TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
> - run_test(&info, IDNO, msg_return_press_no, "default button: unset default");
> + run_test(&info, IDNO, 0, msg_return_press_no, "default button: unset default");
> info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
> - run_test(&info, IDRETRY, msg_return_press_retry, "default button: unset default");
> + run_test(&info, IDRETRY, 0, msg_return_press_retry, "default button: unset default");
> info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_CLOSE_BUTTON;
> - run_test(&info, IDCANCEL, msg_return_press_cancel, "default button: unset default");
> + run_test(&info, IDCANCEL, 0, msg_return_press_cancel, "default button: unset default");
>
> /* Test with all common and custom buttons and invalid default ID */
> info.nDefaultButton = 0xff; /* Random ID, should also default to first created button */
> info.cButtons = TEST_NUM_BUTTONS;
> info.pButtons = custom_buttons;
> - run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button: invalid default, with common buttons - 1");
> + run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, with common buttons - 1");
>
> info.nDefaultButton = -1; /* Should work despite button ID -1 */
> - run_test(&info, -1, msg_return_press_custom10, "default button: invalid default, with common buttons - 2");
> + run_test(&info, -1, 0, msg_return_press_custom10, "default button: invalid default, with common buttons - 2");
>
> info.nDefaultButton = -2; /* Should also default to first created button */
> - run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button: invalid default, with common buttons - 3");
> + run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, with common buttons - 3");
>
> /* Test with only custom buttons and invalid default ID */
> info.dwCommonButtons = 0;
> - run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button: invalid default, no common buttons");
> + run_test(&info, ID_START_BUTTON, 0, msg_return_press_custom1, "default button: invalid default, no common buttons");
>
> /* Test with common and custom buttons and valid default ID */
> info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
> | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
> info.nDefaultButton = IDRETRY;
> - run_test(&info, IDRETRY, msg_return_press_retry, "default button: valid default - 1");
> + run_test(&info, IDRETRY, 0, msg_return_press_retry, "default button: valid default - 1");
>
> /* Test with common and custom buttons and valid default ID */
> info.nDefaultButton = ID_START_BUTTON + 3;
> - run_test(&info, ID_START_BUTTON + 3, msg_return_press_custom4, "default button: valid default - 2");
> + run_test(&info, ID_START_BUTTON + 3, 0, msg_return_press_custom4, "default button: valid default - 2");
> +
> + /* Test radio buttons */
> + info.nDefaultButton = 0;
> + info.cButtons = 0;
> + info.pButtons = 0;
> + info.dwCommonButtons = TDCBF_OK_BUTTON;
> + info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
> + info.pRadioButtons = radio_buttons;
> +
> + /* Test default first radio button */
> + run_test(&info, IDOK, ID_START_RADIO_BUTTON, msg_return_default_radio_button_1, "default radio button: default first radio button");
> +
> + /* Test default radio button */
> + info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
> + run_test(&info, IDOK, info.nDefaultRadioButton, msg_return_default_radio_button_2, "default radio button: default radio button");
> +
> + /* Test default radio button with -2 */
> + info.nDefaultRadioButton = -2;
> + run_test(&info, IDOK, info.nDefaultRadioButton, msg_return_default_radio_button_3, "default radio button: default radio button with id -2");
> +
> + /* Test default radio button after clicking the first, messages still work even radio button is disabled */
> + info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
> + run_test(&info, IDOK, ID_START_RADIO_BUTTON, msg_return_first_radio_button, "default radio button: radio button after clicking");
> +
> + /* Test radio button after disabling and clicking the first */
> + info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
> + run_test(&info, IDOK, ID_START_RADIO_BUTTON, msg_return_default_radio_button_clicking_disabled, "default radio button: disable radio button before clicking");
> +
> + /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set, TDN_RADIO_BUTTON_CLICKED will still be received, just radio button not selected */
> + info.nDefaultRadioButton = ID_START_RADIO_BUTTON;
> + info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
> + run_test(&info, IDOK, info.nDefaultRadioButton, msg_return_no_default_radio_button_flag, "default radio button: no default radio flag");
> +
> + /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and nDefaultRadioButton is 0.
> + * TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
> + info.nDefaultRadioButton = 0;
> + info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
> + run_test(&info, IDOK, 0, msg_return_no_default_radio_button_id_and_flag, "default radio button: no default radio id and flag");
> +
> + /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and nDefaultRadioButton is invalid.
> + * TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
> + info.nDefaultRadioButton = 0xff;
> + info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
> + run_test(&info, IDOK, 0, msg_return_no_default_radio_button_id_and_flag, "default radio button: no default flag, invalid id");
> }
>
> static void test_help(void)
> @@ -319,7 +453,7 @@ static void test_help(void)
> info.lpCallbackData = test_ref_data;
> info.dwCommonButtons = TDCBF_OK_BUTTON;
>
> - run_test(&info, IDOK, msg_got_tdn_help, "send f1");
> + run_test(&info, IDOK, 0, msg_got_tdn_help, "send f1");
> }
>
> struct timer_notification_data
June 25, 2018