Ran cargofmt and added single command run for example

This commit is contained in:
adrianwithah 2019-08-07 16:46:15 +01:00
Родитель c1ae8f8b38
Коммит 58f62d39d2
8 изменённых файлов: 113 добавлений и 63 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -1,6 +1,7 @@
# Generated by Cargo
# will have compiled files and executables
/target/
**/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html

Просмотреть файл

@ -2,11 +2,4 @@
name = "com"
version = "0.0.1"
authors = ["Microsoft Corp"]
edition = "2018"
[workspace]
members = [
"examples/basic/client",
"examples/basic/server",
"examples/basic/interface",
]
edition = "2018"

12
examples/basic/Cargo.toml Normal file
Просмотреть файл

@ -0,0 +1,12 @@
[package]
name = "basic"
version = "0.0.1"
authors = ["Microsoft Corp"]
edition = "2018"
[workspace]
members = [
"client",
"interface",
"server",
]

Просмотреть файл

@ -2,24 +2,31 @@
A COM example in Rust
# Install
# Run
First build the server by running the following in the server folder:
To install the server and run the client, simply run the following from the basic folder:
```bash
cargo run
```
Alternatively, you can choose to build/install/run the server and client seperately.
# Build & Install Server
You can build the server by running the following in the server folder:
```bash
cargo build
```
To "install" the server dll, you need to add the following keys to your Windows registry:
To "install" the server, you need to add the CLSIDs to your Windows registry. You can do that by running:
```
[Computer\HKEY_CLASSES_ROOT\CLSID\{C5F45CBC-4439-418C-A9F9-05AC67525E43}]
@="Cat Component"
[Computer\HKEY_CLASSES_ROOT\CLSID\{C5F45CBC-4439-418C-A9F9-05AC67525E43}\InprocServer32]
@="C:\path\to\the\server\dll\file\in\your\target\folder"
```bash
regsvr32 path/to/your/server/dll/file
```
# Run
# Run Client
To run the client which talks to the server, simply run the following from the client folder:

Просмотреть файл

@ -7,7 +7,6 @@ edition = "2018"
[dependencies]
com = { path = "../../.." }
interface = { path = "../interface" }
server = { path = "../server" }
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["winuser", "winreg"] }

Просмотреть файл

@ -1,34 +1,26 @@
extern crate winapi;
mod implementation;
mod interface;
use com::{RawIUnknown, CLASS_E_CLASSNOTAVAILABLE, HRESULT, IID, LPVOID, REFCLSID, REFIID, S_OK};
use winapi::{
um::{
libloaderapi::{ GetModuleHandleA, GetModuleFileNameA },
winreg::{ HKEY_CLASSES_ROOT, RegCreateKeyExA, RegSetValueExA, RegDeleteKeyA, LSTATUS, RegCloseKey },
winnt::{ KEY_QUERY_VALUE, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, CHAR, REG_SZ },
minwinbase:: {SECURITY_ATTRIBUTES},
olectl::{SELFREG_E_CLASS}
},
shared::{
minwindef::{HKEY, DWORD},
winerror::{ERROR_SUCCESS, S_FALSE}
}
};
use std::ffi::{CString, CStr};
use std::os::raw::c_void;
use std::convert::TryInto;
pub use interface::{IAnimal, ICat, IDomesticAnimal, IExample, IFileManager, ILocalFileManager};
pub const CLSID_CAT_CLASS: IID = IID {
data1: 0xC5F45CBC,
data2: 0x4439,
data3: 0x418C,
data4: [0xA9, 0xF9, 0x05, 0xAC, 0x67, 0x52, 0x5E, 0x43],
use std::ffi::{CStr, CString};
use std::os::raw::c_void;
use winapi::{
shared::{
minwindef::{DWORD, HKEY},
winerror::{ERROR_SUCCESS, S_FALSE},
},
um::{
libloaderapi::{GetModuleFileNameA, GetModuleHandleA},
minwinbase::SECURITY_ATTRIBUTES,
olectl::SELFREG_E_CLASS,
winnt::{CHAR, KEY_ALL_ACCESS, KEY_QUERY_VALUE, REG_OPTION_NON_VOLATILE, REG_SZ},
winreg::{
RegCloseKey, RegCreateKeyExA, RegDeleteKeyA, RegSetValueExA, HKEY_CLASSES_ROOT, LSTATUS,
},
},
};
pub use interface::{IAnimal, ICat, IDomesticAnimal, IExample, IFileManager, ILocalFileManager, CLSID_CAT_CLASS, CLSID_LOCAL_FILE_MANAGER_CLASS, CLSID_WINDOWS_FILE_MANAGER_CLASS};
mod british_short_hair_cat;
mod british_short_hair_cat_class;
mod local_file_manager;
@ -86,7 +78,6 @@ extern "stdcall" fn DllGetClassObject(rclsid: REFCLSID, riid: REFIID, ppv: *mut
#[no_mangle]
extern "stdcall" fn DllRegisterServer() -> HRESULT {
unsafe {
let registry_keys_to_add = get_relevant_registry_keys();
for key_info in registry_keys_to_add.iter() {
@ -137,7 +128,7 @@ unsafe fn add_class_key(key_info: &registry_key_info) -> LSTATUS {
KEY_ALL_ACCESS,
lpSecurityAttributes,
&hkResult as *const _ as *mut HKEY,
lpdwDisposition
lpdwDisposition,
);
if result as u32 != ERROR_SUCCESS {
println!("Error creating key. error code: {}", result);
@ -150,7 +141,12 @@ unsafe fn add_class_key(key_info: &registry_key_info) -> LSTATUS {
0,
REG_SZ,
key_info.key_value_data.as_ptr() as *const u8,
key_info.key_value_data.to_bytes_with_nul().len().try_into().unwrap()
key_info
.key_value_data
.to_bytes_with_nul()
.len()
.try_into()
.unwrap(),
);
if result as u32 != ERROR_SUCCESS {
println!("Error creating key. error code: {}", result);
@ -161,17 +157,15 @@ unsafe fn add_class_key(key_info: &registry_key_info) -> LSTATUS {
}
unsafe fn remove_class_key(key_info: &registry_key_info) -> LSTATUS {
RegDeleteKeyA(
HKEY_CLASSES_ROOT,
key_info.key_path.as_ptr()
)
RegDeleteKeyA(HKEY_CLASSES_ROOT, key_info.key_path.as_ptr())
}
unsafe fn get_relevant_registry_keys() -> Vec<registry_key_info> {
let MAX_FILE_PATH_LENGTH = 260;
let hModule = GetModuleHandleA(CString::new("server.dll").unwrap().as_ptr());
let raw_ptr = CString::new(Vec::with_capacity(MAX_FILE_PATH_LENGTH)).expect("Failed to create empty string!").into_raw();
let raw_ptr = CString::new(Vec::with_capacity(MAX_FILE_PATH_LENGTH))
.expect("Failed to create empty string!")
.into_raw();
GetModuleFileNameA(hModule, raw_ptr, MAX_FILE_PATH_LENGTH.try_into().unwrap());
@ -185,29 +179,49 @@ unsafe fn get_relevant_registry_keys() -> Vec<registry_key_info> {
key_value_data: CString::new("Cat Component").unwrap(),
},
registry_key_info {
key_path: CString::new(format!("CLSID\\{}\\InprocServer32", CLSID_CAT_CLASS.to_string())).unwrap(),
key_path: CString::new(format!(
"CLSID\\{}\\InprocServer32",
CLSID_CAT_CLASS.to_string()
))
.unwrap(),
key_value_name: CString::new("").unwrap(),
key_value_data: file_path.clone(),
},
registry_key_info {
key_path: CString::new(format!("CLSID\\{}", CLSID_LOCAL_FILE_MANAGER_CLASS.to_string())).unwrap(),
key_path: CString::new(format!(
"CLSID\\{}",
CLSID_LOCAL_FILE_MANAGER_CLASS.to_string()
))
.unwrap(),
key_value_name: CString::new("").unwrap(),
key_value_data: CString::new("Local File Manager Component").unwrap(),
},
registry_key_info {
key_path: CString::new(format!("CLSID\\{}\\InprocServer32", CLSID_LOCAL_FILE_MANAGER_CLASS.to_string())).unwrap(),
key_path: CString::new(format!(
"CLSID\\{}\\InprocServer32",
CLSID_LOCAL_FILE_MANAGER_CLASS.to_string()
))
.unwrap(),
key_value_name: CString::new("").unwrap(),
key_value_data: file_path.clone(),
},
registry_key_info {
key_path: CString::new(format!("CLSID\\{}", CLSID_WINDOWS_FILE_MANAGER_CLASS.to_string())).unwrap(),
key_path: CString::new(format!(
"CLSID\\{}",
CLSID_WINDOWS_FILE_MANAGER_CLASS.to_string()
))
.unwrap(),
key_value_name: CString::new("").unwrap(),
key_value_data: CString::new("Windows File Manager Component").unwrap(),
},
},
registry_key_info {
key_path: CString::new(format!("CLSID\\{}\\InprocServer32", CLSID_WINDOWS_FILE_MANAGER_CLASS.to_string())).unwrap(),
key_path: CString::new(format!(
"CLSID\\{}\\InprocServer32",
CLSID_WINDOWS_FILE_MANAGER_CLASS.to_string()
))
.unwrap(),
key_value_name: CString::new("").unwrap(),
key_value_data: file_path.clone(),
},
},
]
}
}

Просмотреть файл

@ -0,0 +1,22 @@
use std::process::{Command, Stdio};
use std::io::{self, Write};
fn main() {
let mut child_proc = Command::new("cmd")
.args(&["/C", "cls && cargo build --all --release"])
.spawn()
.expect("Something went wrong!");
child_proc.wait().unwrap();
let mut child_proc = Command::new("cmd")
.args(&["/C", "regsvr32 /s target/release/server.dll"])
.spawn()
.expect("Something went wrong!");
child_proc.wait().unwrap();
let mut child_proc = Command::new("cmd")
.args(&["/C", "cargo run --release --package client"])
.spawn()
.expect("Something went wrong!");
child_proc.wait().unwrap();
}

Просмотреть файл

@ -6,7 +6,7 @@ mod iunknown;
pub use iclassfactory::{
IClassFactory, IClassFactoryMethods, IClassFactoryVTable, RawIClassFactory, IID_ICLASS_FACTORY,
};
pub use iunknown::{IID_IUnknown, IUnknown, IUnknownMethods, IUnknownVTable, RawIUnknown};
pub use iunknown::{IUnknown, IUnknownMethods, IUnknownVTable, RawIUnknown, IID_IUNKNOWN};
use std::fmt;
pub use comptr::ComPtr;
@ -22,7 +22,9 @@ pub struct IID {
impl fmt::Display for IID {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{{{:04X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}}}",
write!(
f,
"{{{:04X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}}}",
self.data1,
self.data2,
self.data3,