Skip to content

Commit

Permalink
Implemented support for registrykey attribute for property elements. #…
Browse files Browse the repository at this point in the history
  • Loading branch information
end2endzone committed Dec 17, 2023
1 parent 106241c commit 84174cf
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 1 deletion.
80 changes: 80 additions & 0 deletions src/core/ActionProperty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "ObjectFactory.h"
#include "LoggerHelper.h"
#include "SaUtils.h"
#include "Win32Registry.h"

#include "rapidassist/strings.h"
#include "rapidassist/filesystem_utf8.h"
Expand All @@ -40,6 +41,16 @@ namespace shellanything
const std::string ActionProperty::XML_ELEMENT_NAME = "property";
const size_t ActionProperty::DEFAULT_MAX_FILE_SIZE = 10240;

void append_optional_null(std::string& value)
{
if (value.empty())
return;
const char* data = value.data();
char last = data[value.size()];
if (last != '\0')
value.append(1, '\0');
}

class ActionPropertyFactory : public virtual IActionFactory
{
public:
Expand Down Expand Up @@ -112,6 +123,13 @@ namespace shellanything
action->SetFileSize(tmp_str);
}

//parse registrykey
tmp_str = "";
if (ObjectFactory::ParseAttribute(element, "registrykey", true, true, tmp_str, error))
{
action->SetRegistryKey(tmp_str);
}

//done parsing
return action;
}
Expand Down Expand Up @@ -139,6 +157,7 @@ namespace shellanything
std::string exprtk = pmgr.Expand(mExprtk);
std::string file = pmgr.Expand(mFile);
std::string filesize = pmgr.Expand(mFileSize);
std::string regisrykey = pmgr.Expand(mRegistryKey);

// If exprtk is specified, it has priority over value. This is required to allow setting a property to an empty value (a.k.a. value="").
if (!exprtk.empty())
Expand All @@ -160,6 +179,57 @@ namespace shellanything
value = ra::strings::ToString(result);
}

// If regisrykey is specified, it has priority over value. This is required to allow setting a property to an empty value (a.k.a. value="").
if (!regisrykey.empty())
{
Win32Registry::REGISTRY_TYPE key_type;
Win32Registry::MemoryBuffer key_value;
bool key_found = false;

if (!key_found)
{
// Search for a registry key and value that matches regisrykey.
// Split as a key path and key name.
std::string key_path = ra::filesystem::GetParentPath(regisrykey.c_str());
std::string key_name = ra::filesystem::GetFilename(regisrykey.c_str());
key_found = Win32Registry::GetValue(key_path.c_str(), key_name.c_str(), key_type, key_value);
}

if (!key_found)
{
// Search for a registry key default that matches regisrykey.
key_found = Win32Registry::GetDefaultKeyValue(regisrykey.c_str(), key_type, key_value);
}

// Store the result in 'value' as if user set this specific value (to use the same process as a property that sets a value).
if (key_found)
{
switch (key_type)
{
case Win32Registry::REGISTRY_TYPE_STRING:
value = key_value;
break;
case Win32Registry::REGISTRY_TYPE_BINARY:
// Properties must end with '\0' to be printable
append_optional_null(key_value);
value = key_value;
break;
case Win32Registry::REGISTRY_TYPE_UINT32:
{
uint32_t* tmp32 = (uint32_t*)key_value.data();
value = ra::strings::ToString(*tmp32);
}
break;
case Win32Registry::REGISTRY_TYPE_UINT64:
{
uint64_t* tmp64 = (uint64_t*)key_value.data();
value = ra::strings::ToString(*tmp64);
}
break;
}
}
}

// If file is specified, it has priority over value. This is required to allow setting a property to an empty value (a.k.a. value="").
if (!file.empty())
{
Expand Down Expand Up @@ -284,4 +354,14 @@ namespace shellanything
mFileSize = value;
}

const std::string& ActionProperty::GetRegistryKey() const
{
return mRegistryKey;
}

void ActionProperty::SetRegistryKey(const std::string& value)
{
mRegistryKey = value;
}

} //namespace shellanything
11 changes: 11 additions & 0 deletions src/core/ActionProperty.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,23 @@ namespace shellanything
/// </summary>
void SetFileSize(const std::string& value);

/// <summary>
/// Getter for the 'registrykey' parameter.
/// </summary>
const std::string& GetRegistryKey() const;

/// <summary>
/// Setter for the 'registrykey' parameter.
/// </summary>
void SetRegistryKey(const std::string& value);

private:
std::string mName;
std::string mValue;
std::string mExprtk;
std::string mFile;
std::string mFileSize;
std::string mRegistryKey;
};


Expand Down
1 change: 1 addition & 0 deletions src/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(CONFIGURATION_TEST_FILES ""
${CMAKE_CURRENT_SOURCE_DIR}/test_files/samples.xml
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestActionProperty.testCaptureOutput.xml
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestActionProperty.testCopyFile.xml
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestActionProperty.testRegistryKey.xml
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestConfigManager.testAssignCommandId.1.xml
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestConfigManager.testAssignCommandId.2.xml
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestConfigManager.testAssignCommandIdsInvalid.xml
Expand Down
67 changes: 67 additions & 0 deletions src/tests/TestActionProperty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,73 @@ namespace shellanything
//Cleanup
ASSERT_TRUE(workspace.Cleanup()) << "Failed deleting workspace directory '" << workspace.GetBaseDirectory() << "'.";
}
//--------------------------------------------------------------------------------------------------
TEST_F(TestActionProperty, testRegistryKey)
{
ConfigManager& cmgr = ConfigManager::GetInstance();
PropertyManager& pmgr = PropertyManager::GetInstance();

//Creating a temporary workspace for the test execution.
Workspace workspace;
ASSERT_FALSE(workspace.GetBaseDirectory().empty());

//Load the test Configuration File that matches this test name.
QuickLoader loader;
loader.SetWorkspace(&workspace);
ASSERT_TRUE(loader.DeleteConfigurationFilesInWorkspace());
ASSERT_TRUE(loader.LoadCurrentTestConfigurationFile());

//Get all menus.
Configuration::ConfigurationPtrList configs = cmgr.GetConfigurations();
ASSERT_EQ(1, configs.size());

//ASSERT a single menu is available
Menu::MenuPtrList menus = cmgr.GetConfigurations()[0]->GetMenus();
ASSERT_GT(menus.size(), 1);

//Clear properties
static const char* properties[] = {
"test1",
"test2",
"test3",
"test4",
"test5",
};
static const size_t properties_count = sizeof(properties) / sizeof(properties[0]);
for (size_t i = 0; i < properties_count; i++)
{
pmgr.ClearProperty(properties[i]);
}

//Create a valid context
SelectionContext c;
StringList elements;
elements.push_back("C:\\Windows");
c.SetElements(elements);
c.RegisterProperties();

// Execute
for (size_t i = 0; i < menus.size(); i++)
{
Menu* menu = menus[i];
bool executed = ActionManager::Execute(menu, c);
ASSERT_TRUE(executed) << "Failed to execute actions of menu '" << menu->GetName() << "'.";
}

//ASSERT the properties were set
for (size_t i = 0; i < properties_count; i++)
{
const char* property_name = properties[i];
ASSERT_TRUE(pmgr.HasProperty(property_name)) << "Property not found: '" << property_name << "'.";
}

//ASSERT a single value
std::string test1 = pmgr.GetProperty("test1");
ASSERT_EQ("C:\\Program Files\\7-Zip\\", test1);

//Cleanup
ASSERT_TRUE(workspace.Cleanup()) << "Failed deleting workspace directory '" << workspace.GetBaseDirectory() << "'.";
}

} //namespace test
} //namespace shellanything
8 changes: 7 additions & 1 deletion src/tests/TestObjectFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,20 +678,22 @@ namespace shellanything

//ASSERT a multiple menus are available
Menu::MenuPtrList menus = cmgr.GetConfigurations()[0]->GetMenus();
ASSERT_EQ(5, menus.size());
ASSERT_EQ(6, menus.size());

//Assert all menus have a property element as the first action
ActionProperty* property00 = GetFirstActionProperty(menus[00]);
ActionProperty* property01 = GetFirstActionProperty(menus[01]);
ActionProperty* property02 = GetFirstActionProperty(menus[02]);
ActionProperty* property03 = GetFirstActionProperty(menus[03]);
ActionProperty* property04 = GetFirstActionProperty(menus[04]);
ActionProperty* property05 = GetFirstActionProperty(menus[05]);

ASSERT_TRUE(property00 != NULL);
ASSERT_TRUE(property01 != NULL);
ASSERT_TRUE(property02 != NULL);
ASSERT_TRUE(property03 != NULL);
ASSERT_TRUE(property04 != NULL);
ASSERT_TRUE(property05 != NULL);

//Assert menu #0 have a name and a value parsed
static const std::string EMPTY_STRING;
Expand All @@ -718,6 +720,10 @@ namespace shellanything
std::string property04_filesize = property04->GetFileSize();
ASSERT_EQ(std::string("13"), property04_filesize);

//Assert menu #5 have a registrykey attribute parsed
std::string property05_registrykey = property05->GetRegistryKey();
ASSERT_EQ(std::string("HKEY_LOCAL_MACHINE\\SOFTWARE\\7-Zip\\Path"), property05_registrykey);

//Cleanup
ASSERT_TRUE(workspace.Cleanup()) << "Failed deleting workspace directory '" << workspace.GetBaseDirectory() << "'.";
}
Expand Down
41 changes: 41 additions & 0 deletions src/tests/test_files/TestActionProperty.testRegistryKey.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<shell>

<menu name="menu1">
<actions>
<!-- Read string `C:\Program Files\7-Zip\` -->
<property name="test1" registrykey="HKEY_LOCAL_MACHINE\SOFTWARE\7-Zip\Path" />
</actions>
</menu>

<menu name="menu2">
<actions>
<!-- Read string `1` -->
<property name="test2" registrykey="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\DateTime\Servers" />
</actions>
</menu>

<menu name="menu3">
<actions>
<!-- Read string `Microsoft Windows Property System` -->
<property name="test3" registrykey="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\PropertySystem" />
</actions>
</menu>

<menu name="menu4">
<actions>
<!-- Read 32bit value `0x66` -->
<property name="test4" registrykey="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\LastTaskOperationHandle" />
</actions>
</menu>

<menu name="menu5">
<actions>
<!-- Read BINARY `0x06 0x02 0x50 0x01 0x1e 0x1c ...` -->
<property name="test5" registrykey="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\SusClientIdValidation" />
</actions>
</menu>

</shell>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
<property name="foo" file="c:\foo\bar.txt" filesize="13" />
</actions>
</menu>

<menu name="menu05">
<actions>
<!--basic registrykey usage-->
<property name="foo" registrykey="HKEY_LOCAL_MACHINE\SOFTWARE\7-Zip\Path" />
</actions>
</menu>

</shell>
</root>

0 comments on commit 84174cf

Please sign in to comment.