From ae7c91554dd00afe7424896c909d8fd1910aafd6 Mon Sep 17 00:00:00 2001 From: Guillaume Bougard Date: Fri, 13 Jan 2017 16:22:25 +0100 Subject: [PATCH 1/5] Handle case no regkey/regval path is provided --- lib/FusionInventory/Agent/Tools/Win32.pm | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/FusionInventory/Agent/Tools/Win32.pm b/lib/FusionInventory/Agent/Tools/Win32.pm index 6576b1770e..405065b4dd 100644 --- a/lib/FusionInventory/Agent/Tools/Win32.pm +++ b/lib/FusionInventory/Agent/Tools/Win32.pm @@ -182,6 +182,13 @@ sub _getWMIObjects { sub getRegistryValue { my (%params) = @_; + if (!$params{path}) { + $params{logger}->error( + "No registry value path provided" + ) if $params{logger}; + return; + } + my ($root, $keyName, $valueName); if ($params{path} =~ m{^(HKEY_\S+)/(.+)/([^/]+)} ) { $root = $1; @@ -217,6 +224,13 @@ sub getRegistryValue { sub getRegistryKey { my (%params) = @_; + if (!$params{path}) { + $params{logger}->error( + "No registry key path provided" + ) if $params{logger}; + return; + } + my ($root, $keyName); if ($params{path} =~ m{^(HKEY_\S+)/(.+)} ) { $root = $1; From 2ad8cc6ace835a13f8672420c057685ab56d897e Mon Sep 17 00:00:00 2001 From: Guillaume Bougard Date: Fri, 13 Jan 2017 16:23:25 +0100 Subject: [PATCH 2/5] Support Win32::TieRegistry::GetValue() faked API in tests --- t/lib/fake/windows/Win32/TieRegistry.pm | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/t/lib/fake/windows/Win32/TieRegistry.pm b/t/lib/fake/windows/Win32/TieRegistry.pm index eabc53fae5..899fd5f0f5 100644 --- a/t/lib/fake/windows/Win32/TieRegistry.pm +++ b/t/lib/fake/windows/Win32/TieRegistry.pm @@ -3,6 +3,9 @@ package Win32::TieRegistry; use strict; use warnings; +use constant REG_DWORD => 0x4; +use constant REG_SZ => 0x7; + our $Registry; sub import { @@ -13,4 +16,18 @@ sub import { *{"$callpkg\::KEY_READ"} = sub {}; } +sub GetValue { + my ($self, $value ) = @_ ; + # Subkey case + if ($value && exists($self->{$value})) { + return wantarray ? () : undef ; + } + # Value case + $value = '/'.$value; + return unless ($value && exists($self->{$value})); + return wantarray ? + ( $self->{$value}, $self->{$value} =~ /^0x/ ? REG_DWORD : REG_SZ ) + : $self->{$value} ; +} + 1; From a79506cec85308c8e63159196ddc74ff98bffc67 Mon Sep 17 00:00:00 2001 From: Guillaume Bougard Date: Fri, 13 Jan 2017 16:37:46 +0100 Subject: [PATCH 3/5] Add getRegistryKey/getRegistryValue APIs win32 unittests --- t/agent/tools/win32.t | 132 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/t/agent/tools/win32.t b/t/agent/tools/win32.t index 33a625c894..90df526c8b 100755 --- a/t/agent/tools/win32.t +++ b/t/agent/tools/win32.t @@ -5,6 +5,9 @@ use warnings; use utf8; use lib 't/lib'; +use constant REG_DWORD => 0x4; +use constant REG_SZ => 0x7; + use English qw(-no_match_vars); use Test::Deep qw(cmp_deeply); use Test::MockModule; @@ -146,10 +149,98 @@ my %tests = ( ] ); +# Emulated registry +my %register = ( + 'HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node' => { + 'TeamViewer' => { + # Values key begins with a slash + '/ClientID' => '0x12345678', + '/Version' => '12.0.72365', + # Subkey ends with a slash + 'subkey/' => { + '/value' => '' + } + } + } +); + +my %regkey_tests = ( + 'nopath' => { + _expected => undef + }, + 'undef-path' => { + path => undef, + _expected => undef + }, + 'emptypath' => { + path => '', + _expected => undef + }, + 'badroot' => { + path => 'HKEY_NOT_A_ROOT/Not_existing_Key_path', + _expected => undef + }, + 'teamviewer' => { + path => 'HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/TeamViewer', + _expected => bless({ + '/ClientID' => '0x12345678', + '/Version' => '12.0.72365', + 'subkey/' => bless({ + '/value' => '' + }, 'Win32::TieRegistry') + }, 'Win32::TieRegistry') + } +); + +my %regval_tests = ( + 'nopath' => { + _expected => undef + }, + 'undef-path' => { + path => undef, + _expected => undef + }, + 'emptypath' => { + path => '', + _expected => undef + }, + 'badroot' => { + path => 'HKEY_NOT_A_ROOT/Not_existing_Key_path', + _expected => undef + }, + 'teamviewerid' => { + path => 'HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/TeamViewer/ClientID', + _expected => '0x12345678' + }, + 'teamviewer-all' => { + path => 'HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/TeamViewer/*', + _expected => { + 'ClientID' => '0x12345678', + 'Version' => '12.0.72365', + 'subkey/' => undef + } + }, + 'teamviewerid-withtype' => { + path => 'HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/TeamViewer/ClientID', + withtype => 1, + _expected => [ '0x12345678', REG_DWORD ] + }, + 'teamviewer-all-withtype' => { + path => 'HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/TeamViewer/*', + withtype => 1, + _expected => { + 'ClientID' => [ '0x12345678', REG_DWORD ], + 'Version' => [ '12.0.72365', REG_SZ ], + 'subkey/' => [] + } + } +); + my $win32_only_test_count = 7; plan tests => - (scalar keys %tests) + $win32_only_test_count; + (scalar keys %tests) + $win32_only_test_count + + (scalar keys %regkey_tests) + (scalar keys %regval_tests); FusionInventory::Agent::Tools::Win32->require(); FusionInventory::Agent::Tools::Win32->use('getInterfaces'); @@ -214,3 +305,42 @@ SKIP: { exit(0); } } + +$module->mock( + '_getRegistryKey', + sub { + my (%params) = @_; + return unless ($params{root} && $params{keyName}); + return unless exists($register{$params{root}}); + my $root = $register{$params{root}}; + return unless exists($root->{$params{keyName}}); + my $key = { %{$root->{$params{keyName}}} }; + # Bless leaf as expected + map { bless $key->{$_}, 'Win32::TieRegistry' } + grep { ref($key->{$_}) eq 'HASH' } keys %{$key}; + bless $key, 'Win32::TieRegistry'; + return $key; + } +); + +FusionInventory::Agent::Tools::Win32->use('getRegistryKey'); +foreach my $test (keys %regkey_tests) { + + my $regkey = getRegistryKey( %{$regkey_tests{$test}} ); + cmp_deeply( + $regkey, + $regkey_tests{$test}->{_expected}, + "$test regkey" + ); +} + +FusionInventory::Agent::Tools::Win32->use('getRegistryValue'); +foreach my $test (keys %regval_tests) { + + my $regval = getRegistryValue( %{$regval_tests{$test}} ); + cmp_deeply( + $regval, + $regval_tests{$test}->{_expected}, + "$test regval" + ); +} From d78dec68f7317af5f5350b4a6ed4593f42c82726 Mon Sep 17 00:00:00 2001 From: Guillaume Bougard Date: Fri, 13 Jan 2017 16:46:25 +0100 Subject: [PATCH 4/5] Update with win32 failing unittests reproducing #143 --- t/agent/tools/win32.t | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/t/agent/tools/win32.t b/t/agent/tools/win32.t index 90df526c8b..27d2cd5a63 100755 --- a/t/agent/tools/win32.t +++ b/t/agent/tools/win32.t @@ -161,6 +161,12 @@ my %register = ( '/value' => '' } } + }, + 'HKEY_LOCAL_MACHINE/CurrentControlSet/Control/Session Manager' => { + 'Environment' => { + '/TEMP' => '%SystemRoot%\\TEMP', + '/OS' => 'Windows_NT', + } } ); @@ -189,6 +195,13 @@ my %regkey_tests = ( '/value' => '' }, 'Win32::TieRegistry') }, 'Win32::TieRegistry') + }, + 'environment' => { + path => 'HKEY_LOCAL_MACHINE/CurrentControlSet/Control/Session Manager/Environment', + _expected => bless({ + '/TEMP' => '%SystemRoot%\\TEMP', + '/OS' => 'Windows_NT' + }, 'Win32::TieRegistry') } ); @@ -233,6 +246,10 @@ my %regval_tests = ( 'Version' => [ '12.0.72365', REG_SZ ], 'subkey/' => [] } + }, + 'temp-env' => { + path => 'HKEY_LOCAL_MACHINE/CurrentControlSet/Control/Session Manager/Environment/TEMP', + _expected => '%SystemRoot%\\TEMP' } ); From 74bef5415b59305adfda0dd9e569d8014577182d Mon Sep 17 00:00:00 2001 From: Guillaume Bougard Date: Fri, 13 Jan 2017 16:47:31 +0100 Subject: [PATCH 5/5] Fix win32 regkey path parsing Fixes #143 --- lib/FusionInventory/Agent/Tools/Win32.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/FusionInventory/Agent/Tools/Win32.pm b/lib/FusionInventory/Agent/Tools/Win32.pm index 405065b4dd..80701a037d 100644 --- a/lib/FusionInventory/Agent/Tools/Win32.pm +++ b/lib/FusionInventory/Agent/Tools/Win32.pm @@ -190,7 +190,7 @@ sub getRegistryValue { } my ($root, $keyName, $valueName); - if ($params{path} =~ m{^(HKEY_\S+)/(.+)/([^/]+)} ) { + if ($params{path} =~ m{^(HKEY_\w+.*)/([^/]+)/([^/]+)} ) { $root = $1; $keyName = $2; $valueName = $3; @@ -232,7 +232,7 @@ sub getRegistryKey { } my ($root, $keyName); - if ($params{path} =~ m{^(HKEY_\S+)/(.+)} ) { + if ($params{path} =~ m{^(HKEY_\w+.*)/([^/]+)} ) { $root = $1; $keyName = $2; } else {