1 // Copyright © 2017 winapi-rs developers 2 // Licensed under the Apache License, Version 2.0 3 // <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 4 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option. 5 // All files in the project carrying such notice may not be copied, modified, or distributed 6 // except according to those terms. 7 8 #![allow(bad_style)] 9 #![allow(unused)] 10 11 use crate::winapi::Interface; 12 use crate::winapi::BSTR; 13 use crate::winapi::LPCOLESTR; 14 use crate::winapi::LPSAFEARRAY; 15 use crate::winapi::S_FALSE; 16 use crate::winapi::{CoCreateInstance, CLSCTX_ALL}; 17 use crate::winapi::{IUnknown, IUnknownVtbl}; 18 use crate::winapi::{HRESULT, LCID, LPCWSTR, PULONGLONG}; 19 use crate::winapi::{LPFILETIME, ULONG}; 20 use std::ffi::OsString; 21 use std::ptr::null_mut; 22 23 use crate::com::{BStr, ComPtr}; 24 25 // Bindings to the Setup.Configuration stuff 26 pub type InstanceState = u32; 27 28 pub const eNone: InstanceState = 0; 29 pub const eLocal: InstanceState = 1; 30 pub const eRegistered: InstanceState = 2; 31 pub const eNoRebootRequired: InstanceState = 4; 32 pub const eComplete: InstanceState = -1i32 as u32; 33 34 RIDL! {#[uuid(0xb41463c3, 0x8866, 0x43b5, 0xbc, 0x33, 0x2b, 0x06, 0x76, 0xf7, 0xf4, 0x2e)] 35 interface ISetupInstance(ISetupInstanceVtbl): IUnknown(IUnknownVtbl) { 36 fn GetInstanceId( 37 pbstrInstanceId: *mut BSTR, 38 ) -> HRESULT, 39 fn GetInstallDate( 40 pInstallDate: LPFILETIME, 41 ) -> HRESULT, 42 fn GetInstallationName( 43 pbstrInstallationName: *mut BSTR, 44 ) -> HRESULT, 45 fn GetInstallationPath( 46 pbstrInstallationPath: *mut BSTR, 47 ) -> HRESULT, 48 fn GetInstallationVersion( 49 pbstrInstallationVersion: *mut BSTR, 50 ) -> HRESULT, 51 fn GetDisplayName( 52 lcid: LCID, 53 pbstrDisplayName: *mut BSTR, 54 ) -> HRESULT, 55 fn GetDescription( 56 lcid: LCID, 57 pbstrDescription: *mut BSTR, 58 ) -> HRESULT, 59 fn ResolvePath( 60 pwszRelativePath: LPCOLESTR, 61 pbstrAbsolutePath: *mut BSTR, 62 ) -> HRESULT, 63 }} 64 65 RIDL! {#[uuid(0x89143c9a, 0x05af, 0x49b0, 0xb7, 0x17, 0x72, 0xe2, 0x18, 0xa2, 0x18, 0x5c)] 66 interface ISetupInstance2(ISetupInstance2Vtbl): ISetupInstance(ISetupInstanceVtbl) { 67 fn GetState( 68 pState: *mut InstanceState, 69 ) -> HRESULT, 70 fn GetPackages( 71 ppsaPackages: *mut LPSAFEARRAY, 72 ) -> HRESULT, 73 fn GetProduct( 74 ppPackage: *mut *mut ISetupPackageReference, 75 ) -> HRESULT, 76 fn GetProductPath( 77 pbstrProductPath: *mut BSTR, 78 ) -> HRESULT, 79 }} 80 81 RIDL! {#[uuid(0x6380bcff, 0x41d3, 0x4b2e, 0x8b, 0x2e, 0xbf, 0x8a, 0x68, 0x10, 0xc8, 0x48)] 82 interface IEnumSetupInstances(IEnumSetupInstancesVtbl): IUnknown(IUnknownVtbl) { 83 fn Next( 84 celt: ULONG, 85 rgelt: *mut *mut ISetupInstance, 86 pceltFetched: *mut ULONG, 87 ) -> HRESULT, 88 fn Skip( 89 celt: ULONG, 90 ) -> HRESULT, 91 fn Reset() -> HRESULT, 92 fn Clone( 93 ppenum: *mut *mut IEnumSetupInstances, 94 ) -> HRESULT, 95 }} 96 97 RIDL! {#[uuid(0x42843719, 0xdb4c, 0x46c2, 0x8e, 0x7c, 0x64, 0xf1, 0x81, 0x6e, 0xfd, 0x5b)] 98 interface ISetupConfiguration(ISetupConfigurationVtbl): IUnknown(IUnknownVtbl) { 99 fn EnumInstances( 100 ppEnumInstances: *mut *mut IEnumSetupInstances, 101 ) -> HRESULT, 102 fn GetInstanceForCurrentProcess( 103 ppInstance: *mut *mut ISetupInstance, 104 ) -> HRESULT, 105 fn GetInstanceForPath( 106 wzPath: LPCWSTR, 107 ppInstance: *mut *mut ISetupInstance, 108 ) -> HRESULT, 109 }} 110 111 RIDL! {#[uuid(0x26aab78c, 0x4a60, 0x49d6, 0xaf, 0x3b, 0x3c, 0x35, 0xbc, 0x93, 0x36, 0x5d)] 112 interface ISetupConfiguration2(ISetupConfiguration2Vtbl): 113 ISetupConfiguration(ISetupConfigurationVtbl) { 114 fn EnumAllInstances( 115 ppEnumInstances: *mut *mut IEnumSetupInstances, 116 ) -> HRESULT, 117 }} 118 119 RIDL! {#[uuid(0xda8d8a16, 0xb2b6, 0x4487, 0xa2, 0xf1, 0x59, 0x4c, 0xcc, 0xcd, 0x6b, 0xf5)] 120 interface ISetupPackageReference(ISetupPackageReferenceVtbl): IUnknown(IUnknownVtbl) { 121 fn GetId( 122 pbstrId: *mut BSTR, 123 ) -> HRESULT, 124 fn GetVersion( 125 pbstrVersion: *mut BSTR, 126 ) -> HRESULT, 127 fn GetChip( 128 pbstrChip: *mut BSTR, 129 ) -> HRESULT, 130 fn GetLanguage( 131 pbstrLanguage: *mut BSTR, 132 ) -> HRESULT, 133 fn GetBranch( 134 pbstrBranch: *mut BSTR, 135 ) -> HRESULT, 136 fn GetType( 137 pbstrType: *mut BSTR, 138 ) -> HRESULT, 139 fn GetUniqueId( 140 pbstrUniqueId: *mut BSTR, 141 ) -> HRESULT, 142 }} 143 144 RIDL! {#[uuid(0x42b21b78, 0x6192, 0x463e, 0x87, 0xbf, 0xd5, 0x77, 0x83, 0x8f, 0x1d, 0x5c)] 145 interface ISetupHelper(ISetupHelperVtbl): IUnknown(IUnknownVtbl) { 146 fn ParseVersion( 147 pwszVersion: LPCOLESTR, 148 pullVersion: PULONGLONG, 149 ) -> HRESULT, 150 fn ParseVersionRange( 151 pwszVersionRange: LPCOLESTR, 152 pullMinVersion: PULONGLONG, 153 pullMaxVersion: PULONGLONG, 154 ) -> HRESULT, 155 }} 156 157 DEFINE_GUID! {CLSID_SetupConfiguration, 158 0x177f0c4a, 0x1cd3, 0x4de7, 0xa3, 0x2c, 0x71, 0xdb, 0xbb, 0x9f, 0xa3, 0x6d} 159 160 // Safe wrapper around the COM interfaces 161 pub struct SetupConfiguration(ComPtr<ISetupConfiguration>); 162 163 impl SetupConfiguration { 164 pub fn new() -> Result<SetupConfiguration, i32> { 165 let mut obj = null_mut(); 166 let err = unsafe { 167 CoCreateInstance( 168 &CLSID_SetupConfiguration, 169 null_mut(), 170 CLSCTX_ALL, 171 &ISetupConfiguration::uuidof(), 172 &mut obj, 173 ) 174 }; 175 if err < 0 { 176 return Err(err); 177 } 178 let obj = unsafe { ComPtr::from_raw(obj as *mut ISetupConfiguration) }; 179 Ok(SetupConfiguration(obj)) 180 } 181 pub fn get_instance_for_current_process(&self) -> Result<SetupInstance, i32> { 182 let mut obj = null_mut(); 183 let err = unsafe { self.0.GetInstanceForCurrentProcess(&mut obj) }; 184 if err < 0 { 185 return Err(err); 186 } 187 Ok(unsafe { SetupInstance::from_raw(obj) }) 188 } 189 pub fn enum_instances(&self) -> Result<EnumSetupInstances, i32> { 190 let mut obj = null_mut(); 191 let err = unsafe { self.0.EnumInstances(&mut obj) }; 192 if err < 0 { 193 return Err(err); 194 } 195 Ok(unsafe { EnumSetupInstances::from_raw(obj) }) 196 } 197 pub fn enum_all_instances(&self) -> Result<EnumSetupInstances, i32> { 198 let mut obj = null_mut(); 199 let this = self.0.cast::<ISetupConfiguration2>()?; 200 let err = unsafe { this.EnumAllInstances(&mut obj) }; 201 if err < 0 { 202 return Err(err); 203 } 204 Ok(unsafe { EnumSetupInstances::from_raw(obj) }) 205 } 206 } 207 208 pub struct SetupInstance(ComPtr<ISetupInstance>); 209 210 impl SetupInstance { 211 pub unsafe fn from_raw(obj: *mut ISetupInstance) -> SetupInstance { 212 SetupInstance(ComPtr::from_raw(obj)) 213 } 214 pub fn instance_id(&self) -> Result<OsString, i32> { 215 let mut s = null_mut(); 216 let err = unsafe { self.0.GetInstanceId(&mut s) }; 217 let bstr = unsafe { BStr::from_raw(s) }; 218 if err < 0 { 219 return Err(err); 220 } 221 Ok(bstr.to_osstring()) 222 } 223 pub fn installation_name(&self) -> Result<OsString, i32> { 224 let mut s = null_mut(); 225 let err = unsafe { self.0.GetInstallationName(&mut s) }; 226 let bstr = unsafe { BStr::from_raw(s) }; 227 if err < 0 { 228 return Err(err); 229 } 230 Ok(bstr.to_osstring()) 231 } 232 pub fn installation_path(&self) -> Result<OsString, i32> { 233 let mut s = null_mut(); 234 let err = unsafe { self.0.GetInstallationPath(&mut s) }; 235 let bstr = unsafe { BStr::from_raw(s) }; 236 if err < 0 { 237 return Err(err); 238 } 239 Ok(bstr.to_osstring()) 240 } 241 pub fn installation_version(&self) -> Result<OsString, i32> { 242 let mut s = null_mut(); 243 let err = unsafe { self.0.GetInstallationVersion(&mut s) }; 244 let bstr = unsafe { BStr::from_raw(s) }; 245 if err < 0 { 246 return Err(err); 247 } 248 Ok(bstr.to_osstring()) 249 } 250 pub fn product_path(&self) -> Result<OsString, i32> { 251 let mut s = null_mut(); 252 let this = self.0.cast::<ISetupInstance2>()?; 253 let err = unsafe { this.GetProductPath(&mut s) }; 254 let bstr = unsafe { BStr::from_raw(s) }; 255 if err < 0 { 256 return Err(err); 257 } 258 Ok(bstr.to_osstring()) 259 } 260 } 261 262 pub struct EnumSetupInstances(ComPtr<IEnumSetupInstances>); 263 264 impl EnumSetupInstances { 265 pub unsafe fn from_raw(obj: *mut IEnumSetupInstances) -> EnumSetupInstances { 266 EnumSetupInstances(ComPtr::from_raw(obj)) 267 } 268 } 269 270 impl Iterator for EnumSetupInstances { 271 type Item = Result<SetupInstance, i32>; 272 fn next(&mut self) -> Option<Result<SetupInstance, i32>> { 273 let mut obj = null_mut(); 274 let err = unsafe { self.0.Next(1, &mut obj, null_mut()) }; 275 if err < 0 { 276 return Some(Err(err)); 277 } 278 if err == S_FALSE { 279 return None; 280 } 281 Some(Ok(unsafe { SetupInstance::from_raw(obj) })) 282 } 283 } 284