Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enable registry config get use, add build script #11

Merged
merged 4 commits into from
Feb 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
Cargo.lock
target
bin/
83 changes: 83 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
param(
[switch]$Release,
[ValidateSet('none','aarch64-pc-windows-msvc',' x86_64-pc-windows-msvc')]
$architecture = 'none',
[switch]$Clippy
)

## Create the output folder
$configuration = $Release ? 'release' : 'debug'
$target = Join-Path $PSScriptRoot 'bin' $configuration
if (Test-Path $target) {
Remove-Item $target -Recurse -ErrorAction Stop
}
New-Item -ItemType Directory $target > $null

$flags = @($Release ? '-r' : $null)
if ($architecture -ne 'none') {
$flags += '--target'
$flags += $architecture
$path = ".\target\$architecture\$configuration"
}
else {
$path = ".\target\$configuration"
}

$windows_projects = @("registry")
$projects = @("config")
if ($IsWindows) {
$projects += $windows_projects
}

foreach ($project in $projects) {
## Build format_json
Write-Host -ForegroundColor Cyan "Building $project ..."
try {
Push-Location "$PSScriptRoot/$project"
if ($Clippy) {
cargo clippy @flags
}
else {
cargo build @flags
}

if ($IsWindows) {
Copy-Item "$path/$project.exe" $target
}
else {
Copy-Item "$path/$project" $target
}

Copy-Item *.command.json $target
} finally {
Pop-Location
}
}

$relative = Resolve-Path $target -Relative
Write-Host -ForegroundColor Green "`nEXE's are copied to $target ($relative)"

$paths = $env:PATH.Split([System.IO.Path]::PathSeparator)
$found = $false
foreach ($path in $paths) {
if ($path -eq $target) {
$found = $true
break
}
}

# remove the other target in case switching between them
if ($Release) {
$oldTarget = $target.Replace('\release', '\debug')
}
else {
$oldTarget = $target.Replace('\debug', '\release')
}
$env:PATH = $env:PATH.Replace(';' + $oldTarget, '')

if (!$found) {
Write-Host -ForegroundCOlor Yellow "Adding $target to `$env:PATH"
$env:PATH += [System.IO.Path]::PathSeparator + $target
}

$env:RUST_BACKTRACE=1
8 changes: 4 additions & 4 deletions ntreg/src/registry_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,12 +338,12 @@ impl RegistryKey {
data = binary_data.as_mut_ptr() as *mut c_void;
len = binary_data.len();
}
RegistryValueData::Dword(ref value) => {
RegistryValueData::DWord(ref value) => {
let mut value = *value;
data = &mut value as *mut u32 as *mut c_void;
len = size_of::<u32>();
}
RegistryValueData::Qword(ref value) => {
RegistryValueData::QWord(ref value) => {
let mut value = *value;
data = &mut value as *mut u64 as *mut c_void;
len = size_of::<u64>();
Expand All @@ -355,13 +355,13 @@ impl RegistryKey {
RegistryValueData::String(_) => 1,
RegistryValueData::ExpandString(_) => 2,
RegistryValueData::Binary(_) => 3,
RegistryValueData::Dword(_) => 4,
RegistryValueData::DWord(_) => 4,
RegistryValueData::Link(_) => 6,
RegistryValueData::MultiString(_) => 7,
RegistryValueData::ResourceList(_) => 8,
RegistryValueData::FullResourceDescriptor(_) => 9,
RegistryValueData::ResourceRequirementsList(_) => 10,
RegistryValueData::Qword(_) => 11,
RegistryValueData::QWord(_) => 11,
};

let status = unsafe {
Expand Down
12 changes: 6 additions & 6 deletions ntreg/src/registry_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ pub enum RegistryValueData {
String(String),
ExpandString(String),
Binary(Vec<u8>),
Dword(u32), // excluding REG_DWORD_BIG_ENDIAN as it's intended for UNIX systems and not used on Windows
DWord(u32), // excluding REG_DWORD_BIG_ENDIAN as it's intended for UNIX systems and not used on Windows
Link(String),
MultiString(Vec<String>),
ResourceList(Vec<u8>),
FullResourceDescriptor(Vec<u8>),
ResourceRequirementsList(Vec<u8>),
Qword(u64),
QWord(u64),
}

/// Represents a registry value.
Expand Down Expand Up @@ -131,13 +131,13 @@ impl fmt::Display for RegistryValueData {
RegistryValueData::String(ref data) => format!("String: {}", data),
RegistryValueData::ExpandString(ref data) => format!("ExpandString: {}", data),
RegistryValueData::Binary(ref data) => format!("Binary: {}", convert_vec_to_string(&data.to_vec())),
RegistryValueData::Dword(ref data) => format!("Dword: {}", data),
RegistryValueData::DWord(ref data) => format!("Dword: {}", data),
RegistryValueData::Link(ref data) => format!("Link: {}", data),
RegistryValueData::MultiString(ref data) => format!("MultiString: {:?}", data),
RegistryValueData::ResourceList(ref data) => format!("ResourceList: {:?}", convert_vec_to_string(&data.to_vec())),
RegistryValueData::FullResourceDescriptor(ref data) => format!("FullResourceDescriptor: {:?}", convert_vec_to_string(&data.to_vec())),
RegistryValueData::ResourceRequirementsList(ref data) => format!("ResourceRequirementsList: {:?}", convert_vec_to_string(&data.to_vec())),
RegistryValueData::Qword(ref data) => format!("Qword: {}", data),
RegistryValueData::QWord(ref data) => format!("Qword: {}", data),
};

write!(f, "{}", data)
Expand Down Expand Up @@ -168,7 +168,7 @@ fn get_data_value(value_information: PKEY_VALUE_FULL_INFORMATION) -> RegistryVal
std::slice::from_raw_parts(data_ptr as *const u16, (data_length / size_of::<u16>()) - 1)
})),
3 => RegistryValueData::Binary(data.to_vec()),
4 => RegistryValueData::Dword(unsafe {
4 => RegistryValueData::DWord(unsafe {
*(data_ptr as *const u32)
}),
6 => RegistryValueData::Link(String::from_utf16_lossy(unsafe {
Expand Down Expand Up @@ -202,7 +202,7 @@ fn get_data_value(value_information: PKEY_VALUE_FULL_INFORMATION) -> RegistryVal
8 => RegistryValueData::ResourceList(data.to_vec()),
9 => RegistryValueData::FullResourceDescriptor(data.to_vec()),
10 => RegistryValueData::ResourceRequirementsList(data.to_vec()),
11 => RegistryValueData::Qword(unsafe {
11 => RegistryValueData::QWord(unsafe {
*(data_ptr as *const u64)
}),
_ => RegistryValueData::None,
Expand Down
8 changes: 4 additions & 4 deletions ntreg/tests/registry_value_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ fn test_set_value_dword() {
let new_key = key.unwrap().create_or_get_key("TestKey_dword");
assert!(new_key.is_ok());
let new_key = new_key.unwrap();
let reg_value = RegistryValueData::Dword(1234);
let reg_value = RegistryValueData::DWord(1234);
let result = new_key.set_value("TestDword", &reg_value);
assert!(result.is_ok());
let result = result.unwrap();
assert_eq!(result.name, "TestDword".to_string());
assert_eq!(result.data, RegistryValueData::Dword(1234));
assert_eq!(result.data, RegistryValueData::DWord(1234));
assert!(new_key.delete(false).is_ok());
}

Expand All @@ -98,12 +98,12 @@ fn test_set_value_qword() {
let new_key = key.unwrap().create_or_get_key("TestKey_qword");
assert!(new_key.is_ok());
let new_key = new_key.unwrap();
let reg_value = RegistryValueData::Qword(12_345_678_901);
let reg_value = RegistryValueData::QWord(12_345_678_901);
let result = new_key.set_value("TestQword", &reg_value);
assert!(result.is_ok());
let result = result.unwrap();
assert_eq!(result.name, "TestQword".to_string());
assert_eq!(result.data, RegistryValueData::Qword(12_345_678_901));
assert_eq!(result.data, RegistryValueData::QWord(12_345_678_901));
assert!(new_key.delete(false).is_ok());
}

Expand Down
9 changes: 8 additions & 1 deletion ntstatuserror/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use thiserror::Error;
use ntapi::winapi::shared::ntdef::{NTSTATUS};
use ntapi::winapi::shared::ntstatus::{STATUS_OBJECT_NAME_NOT_FOUND, STATUS_OBJECT_PATH_NOT_FOUND, STATUS_OBJECT_PATH_SYNTAX_BAD, STATUS_ACCESS_DENIED, STATUS_KEY_DELETED, STATUS_CANNOT_DELETE};
use std::fmt;
use thiserror::Error;

/// Struct for returning NTSTATUS errors
#[derive(Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -74,3 +75,9 @@ impl From<NTSTATUS> for NtStatusErrorKind {
}
}
}

impl fmt::Display for NtStatusError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.status, self.message)
}
}
1 change: 1 addition & 0 deletions registry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ lto = true
atty = { version = "0.2" }
clap = { version = "3.2", features = ["derive"] }
ntreg = { path = "../ntreg" }
ntstatuserror = { path = "../ntstatuserror" }
pal = { path = "../pal" }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["preserve_order"] }
Expand Down
47 changes: 47 additions & 0 deletions registry/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Registry command and resource

## Example JSON

```json
{
"keyPath": "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion",
"valueName": "ProductName"
}
```

## Examples for config

### Get the ProductName of current version of Windows

```powershell
@'
{
"keyPath": "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion",
"valueName": "ProductName"
}
'@ | registry config get
```

### Test that the key exists

```powershell
@'
{
"keyPath": "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion",
"_ensure": "Present"
}
'@ | registry config test
$LASTEXITCODE -eq 0
```

### Test that the key does not exist

```powershell
@'
{
"keyPath": "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion",
"_ensure": "Absent"
}
'@ | registry config test
$LASTEXITCODE -ne 0
```
15 changes: 15 additions & 0 deletions registry/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ pub struct Arguments {
pub subcommand: SubCommand,
}

#[derive(Debug, PartialEq, Eq, Subcommand)]
pub enum ConfigSubCommand {
#[clap(name = "get", about = "Retrieve registry configuration.")]
Get,
#[clap(name = "set", about = "Apply registry configuration.")]
Set,
#[clap(name = "test", about = "Validate registry configuration.")]
Test,
}

#[derive(Debug, PartialEq, Eq, Subcommand)]
pub enum SubCommand {
#[clap(name = "query", about = "Query a registry key or value.", arg_required_else_help = true)]
Expand Down Expand Up @@ -50,4 +60,9 @@ pub enum SubCommand {
#[clap(short, long, help = "Only find values.")]
values_only: Option<bool>,
},
#[clap(name = "config", about = "Manage registry configuration.", arg_required_else_help = true)]
Config {
#[clap(subcommand)]
subcommand: ConfigSubCommand,
},
}
File renamed without changes.
36 changes: 36 additions & 0 deletions registry/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum EnsureKind {
Present,
Absent,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum RegistryValueData {
String(String),
ExpandString(String),
Binary(Vec<u8>),
DWord(u32),
MultiString(Vec<String>),
QWord(u64),
}

#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename = "Registry")]
pub struct RegistryConfig {
#[serde(rename = "keyPath")]
pub key_path: String,
#[serde(rename = "valueName")]
#[serde(skip_serializing_if = "Option::is_none")]
pub value_name: Option<String>,
#[serde(rename = "valueData")]
#[serde(skip_serializing_if = "Option::is_none")]
pub value_data: Option<RegistryValueData>,
#[serde(rename = "_ensure")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ensure: Option<EnsureKind>,
#[serde(rename = "_clobber")]
#[serde(skip_serializing_if = "Option::is_none")]
pub clobber: Option<bool>,
}
Loading