1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! Types for interacting with COM related system APIs
use std::ffi::c_void;

/// A Windows result code
pub type HRESULT = i32;

/// Equivalent of the [FAILED macro](https://docs.microsoft.com/en-us/windows/win32/api/winerror/nf-winerror-failed)
#[allow(non_snake_case)]
pub fn FAILED(result: HRESULT) -> bool {
    result < 0
}

/// BOOL type
pub type BOOL = i32;
/// LSTATUS type
pub type LSTATUS = i32;
/// HKEY type
pub type HKEY = *mut c_void;

/// No error
pub const S_OK: HRESULT = 0;
/// No error
pub const NOERROR: HRESULT = 0;
/// False
pub const S_FALSE: HRESULT = 1;

/// Argument was invalid
pub const E_INVALIDARG: HRESULT = -0x7FF8_FFA9;
/// No interface found
pub const E_NOINTERFACE: HRESULT = -0x7FFF_BFFE;
/// Invalid pointer
pub const E_POINTER: HRESULT = -0x7FFF_BFFD;

/// No aggregation for CoClass
pub const CLASS_E_NOAGGREGATION: HRESULT = -0x7FFB_FEF0;
/// Class is not available
pub const CLASS_E_CLASSNOTAVAILABLE: HRESULT = -0x7FFB_FEEF;

/// No error
pub const ERROR_SUCCESS: u32 = 0;
/// Registration error
pub const SELFREG_E_CLASS: HRESULT = -0x7FFB_FDFF;
/// A in process server
pub const CLSCTX_INPROC_SERVER: u32 = 0x1;

/// An single threaded apartment (STA)
pub const COINIT_APARTMENTTHREADED: u32 = 0x2;
/// An multi threaded apartment (STA)
pub const COINIT_MULTITHREADED: u32 = 0x0;

/// A globally unique identifier
#[repr(C)]
#[derive(Copy, Clone, PartialEq)]
pub struct GUID {
    #[allow(missing_docs)]
    pub data1: u32,
    #[allow(missing_docs)]
    pub data2: u16,
    #[allow(missing_docs)]
    pub data3: u16,
    #[allow(missing_docs)]
    pub data4: [u8; 8],
}

/// An interface ID
pub type IID = GUID;
/// A class ID
pub type CLSID = GUID;

impl std::fmt::Debug for GUID {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{:08X?}-{:04X?}-{:04X?}-{:02X?}{:02X?}-{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}",
            self.data1,
            self.data2,
            self.data3,
            self.data4[0],
            self.data4[1],
            self.data4[2],
            self.data4[3],
            self.data4[4],
            self.data4[5],
            self.data4[6],
            self.data4[7]
        )
    }
}

#[link(name = "ole32")]
extern "system" {
    pub fn CoIncrementMTAUsage(cookie: *mut c_void) -> HRESULT;
    pub fn RegCreateKeyExA(
        hKey: HKEY,
        lpSubKey: *const i8,
        Reserved: u32,
        lpClass: *mut u8,
        dwOptions: u32,
        samDesired: u32,
        lpSecurityAttributes: *mut c_void,
        phkResult: *mut HKEY,
        lpdwDisposition: *mut u32,
    ) -> LSTATUS;
    pub fn GetModuleFileNameA(hModule: *mut c_void, lpFilename: *mut i8, nSize: u32) -> u32;
    pub fn RegCloseKey(hKey: HKEY) -> LSTATUS;
    pub fn RegSetValueExA(
        hKey: HKEY,
        lpValueName: *const i8,
        Reserved: u32,
        dwType: u32,
        lpData: *const u8,
        cbData: u32,
    ) -> LSTATUS;
    pub fn RegDeleteKeyA(hKey: HKEY, lpSubKey: *const i8) -> LSTATUS;
    pub fn GetModuleHandleA(lpModuleName: *const i8) -> *mut c_void;
    pub fn CoInitializeEx(pvReserved: *mut c_void, dwCoInit: u32) -> HRESULT;
    pub fn CoGetClassObject(
        rclsid: *const IID,
        dwClsContext: u32,
        pvReserved: *mut c_void,
        riid: *const IID,
        ppv: *mut *mut c_void,
    ) -> HRESULT;
    pub fn CoCreateInstance(
        rclsid: *const IID,
        pUnkOuter: *mut c_void,
        dwClsContext: u32,
        riid: *const IID,
        ppv: *mut *mut c_void,
    ) -> HRESULT;
    pub fn CoUninitialize();
}