Skip to content

Commit

Permalink
Implements read_data_root for Windows (#1173)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Dec 9, 2024
1 parent 0c932c3 commit 348523a
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 55 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion gui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@ features = ["linked", "std"]
default-features = false

[target.'cfg(windows)'.dependencies.windows-sys]
version = "0.52.0"
version = "0.59.0"
features = [
"Win32",
"Win32_Foundation",
"Win32_Security",
"Win32_System",
"Win32_System_Hypervisor",
"Win32_System_Memory",
"Win32_System_Registry",
"Win32_System_SystemInformation",
]

Expand Down
5 changes: 1 addition & 4 deletions gui/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,8 @@ int main(int argc, char *argv[])

QGuiApplication::setWindowIcon(QIcon(":/resources/obliteration-icon.png"));

// Parse arguments.
QCommandLineParser args;

// Setup main window.
MainWindow win(args);
MainWindow win;

// Run main window.
return QApplication::exec();
Expand Down
37 changes: 1 addition & 36 deletions gui/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,7 @@
#include <fcntl.h>
#endif

namespace Args {
const QCommandLineOption debug("debug", "Immediate launch the VMM in debug mode.", "addr", "127.0.0.1:1234");
const QCommandLineOption kernel("kernel", "Use this kernel instead of default one.", "path");
}

MainWindow::MainWindow(const QCommandLineParser &args) :
m_args(args),
MainWindow::MainWindow() :
m_main(nullptr)
{
// File menu.
Expand Down Expand Up @@ -83,17 +77,6 @@ void MainWindow::aboutObliteration()
"working in the future.");
}

void MainWindow::vmmError(const QString &msg)
{
QMessageBox::critical(this, "Error", msg);

if (m_args.isSet(Args::debug)) {
close();
} else {
m_main->setCurrentIndex(0);
}
}

void MainWindow::waitKernelExit(bool success)
{
if (!success) {
Expand All @@ -105,21 +88,3 @@ void MainWindow::waitKernelExit(bool success)

m_main->setCurrentIndex(0);
}

void MainWindow::stopDebug()
{
// We can't free the VMM here because the thread that trigger this method are waiting
// for us to return.
if (m_args.isSet(Args::debug)) {
QMetaObject::invokeMethod(
this,
&MainWindow::close,
Qt::QueuedConnection);
} else {
QMetaObject::invokeMethod(
this,
&MainWindow::waitKernelExit,
Qt::QueuedConnection,
true);
}
}
12 changes: 1 addition & 11 deletions gui/main_window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,17 @@
#include <QList>
#include <QMainWindow>

class QCommandLineOption;
class QCommandLineParser;
class QStackedWidget;

class MainWindow final : public QMainWindow {
public:
MainWindow(const QCommandLineParser &args);
MainWindow();
~MainWindow() override;
private slots:
void reportIssue();
void aboutObliteration();
private:
void vmmError(const QString &msg);
void waitKernelExit(bool success);
void stopDebug();

const QCommandLineParser &m_args;
QStackedWidget *m_main;
};

namespace Args {
extern const QCommandLineOption debug;
extern const QCommandLineOption kernel;
}
101 changes: 99 additions & 2 deletions gui/src/setup/windows.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,110 @@
use std::ptr::{null, null_mut};
use thiserror::Error;
use windows_sys::w;
use windows_sys::Win32::Foundation::{ERROR_FILE_NOT_FOUND, ERROR_SUCCESS};
use windows_sys::Win32::System::Registry::{
RegCloseKey, RegCreateKeyExW, RegQueryValueExW, HKEY, HKEY_CURRENT_USER, KEY_ALL_ACCESS,
REG_OPTION_NON_VOLATILE, REG_SZ,
};

pub fn read_data_root() -> Result<Option<String>, DataRootError> {
todo!()
// Open our registry key.
let mut key = null_mut();
let e = unsafe {
RegCreateKeyExW(
HKEY_CURRENT_USER,
w!("Software\\OBHQ\\Obliteration"),
0,
null(),
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
null(),
&mut key,
null_mut(),
)
};

if e != ERROR_SUCCESS {
let k = "HKEY_CURRENT_USER\\Software\\OBHQ\\Obliteration";
let e = std::io::Error::from_raw_os_error(e.try_into().unwrap());

return Err(DataRootError::CreateRegKey(k, e));
}

// Get data size.
let fqvn = "HKEY_CURRENT_USER\\Software\\OBHQ\\Obliteration\\DataRoot";
let key = Key(key);
let name = w!("DataRoot");
let mut ty = 0;
let mut len = 0;
let e = unsafe { RegQueryValueExW(key.0, name, null(), &mut ty, null_mut(), &mut len) };

if e == ERROR_FILE_NOT_FOUND {
return Ok(None);
} else if e != ERROR_SUCCESS {
let e = std::io::Error::from_raw_os_error(e.try_into().unwrap());

return Err(DataRootError::QueryRegKey(fqvn, e));
} else if ty != REG_SZ {
return Err(DataRootError::InvalidRegValue(fqvn));
}

// Read data.
let mut buf = vec![0u16; (len / 2).try_into().unwrap()];
let e = unsafe {
RegQueryValueExW(
key.0,
name,
null(),
&mut ty,
buf.as_mut_ptr().cast(),
&mut len,
)
};

if e != ERROR_SUCCESS {
let e = std::io::Error::from_raw_os_error(e.try_into().unwrap());

return Err(DataRootError::QueryRegKey(fqvn, e));
} else if ty != REG_SZ {
return Err(DataRootError::InvalidRegValue(fqvn));
}

// Remove null-terminators if any.
buf.truncate((len / 2).try_into().unwrap());

while buf.last().is_some_and(|&v| v == 0) {
buf.pop();
}

// Convert to Rust string.
String::from_utf16(&buf)
.map_err(|_| DataRootError::InvalidRegValue(fqvn))
.map(Some)
}

pub fn write_data_root(path: impl AsRef<str>) -> Result<(), DataRootError> {
todo!()
}

/// RAII struct to close `HKEY` when dropped.
struct Key(HKEY);

impl Drop for Key {
fn drop(&mut self) {
assert_eq!(unsafe { RegCloseKey(self.0) }, ERROR_SUCCESS);
}
}

/// Represents an error when read or write data root fails.
#[derive(Debug, Error)]
pub enum DataRootError {}
pub enum DataRootError {
#[error("couldn't create {0}")]
CreateRegKey(&'static str, #[source] std::io::Error),

#[error("couldn't read {0}")]
QueryRegKey(&'static str, #[source] std::io::Error),

#[error("{0} has invalid value")]
InvalidRegValue(&'static str),
}

0 comments on commit 348523a

Please sign in to comment.