Skip to content

Commit 49fbf4b

Browse files
committed
COM scope fix.
As stated on the MSDN, A thread must call CoUninitialize once for each successful call it has made to the CoInitialize or CoInitializeEx function, including any call that returns S_FALSE. We were not calling it previously, so the fix is to make a scope guard, which handles this.
1 parent 525f3f8 commit 49fbf4b

4 files changed

Lines changed: 30 additions & 7 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "thound"
3-
version = "0.1.0"
3+
version = "0.1.1"
44
authors = ["Denys Mentiei <endden@gmail.com>"]
55
description = "Finds the folders with VC toolchain and Windows SDK"
66
license = "MIT"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Add `thound` to your `Cargo.toml`:
2323

2424
``` toml
2525
[dependencies]
26-
thound = "0.1.0"
26+
thound = "0.1"
2727
```
2828

2929
## Usage

src/lib.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,7 @@ pub fn find_vc_and_windows_sdk() -> Option<Info> {
123123
}
124124

125125
fn find_vc_toolchain() -> Option<ToolchainInfo> {
126-
let hr = unsafe { CoInitializeEx(null_mut(), COINIT_MULTITHREADED) };
127-
// S_FALSE means COM has been already initialized.
128-
if hr != S_OK && hr != S_FALSE {
129-
return None;
130-
}
126+
let _com = ComScope::start()?;
131127

132128
let mut config = null_mut();
133129
let status = unsafe {

src/winapi.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ extern "stdcall" {
107107
#[link(name = "Ole32")]
108108
extern "stdcall" {
109109
pub fn CoInitializeEx(pvReserved: LPVOID, dwCoInit: DWORD) -> HRESULT;
110+
pub fn CoUninitialize();
110111
pub fn CoCreateInstance(
111112
rclsid: REFCLSID,
112113
pUnkOuter: LPUNKNOWN,
@@ -400,3 +401,29 @@ pub(crate) fn reg_query_string_value(key: &RegKey, sub_key: &str) -> Option<Path
400401
let root = OsString::from_wide(&value[..]);
401402
Some(root.into())
402403
}
404+
405+
// COM initialization seems to be a ref-count of some kind under the
406+
// hood, so we need to make sure we play by the rules and uninit it.
407+
pub(crate) struct ComScope;
408+
409+
impl ComScope {
410+
#[must_use]
411+
pub fn start() -> Option<Self> {
412+
let hr = unsafe { CoInitializeEx(null_mut(), COINIT_MULTITHREADED) };
413+
// S_FALSE means COM has been already initialized.
414+
if hr != S_OK && hr != S_FALSE {
415+
return None;
416+
}
417+
418+
Some(ComScope)
419+
}
420+
}
421+
422+
impl Drop for ComScope {
423+
fn drop(&mut self) {
424+
// A thread must call CoUninitialize once for each successful
425+
// call it has made to the CoInitialize or CoInitializeEx
426+
// function, including any call that returns S_FALSE.
427+
unsafe { CoUninitialize() };
428+
}
429+
}

0 commit comments

Comments
 (0)