Skip to content

Commit ab926d1

Browse files
committed
Implement sys.getwindowsversion
1 parent 1527184 commit ab926d1

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

vm/src/sysmodule.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::builtins;
55
use crate::frame::FrameRef;
66
use crate::function::{Args, OptionalArg, PyFuncArgs};
77
use crate::obj::objstr::PyStringRef;
8+
use crate::obj::objtuple::PyTupleRef;
89
use crate::pyhash::PyHashInfo;
910
use crate::pyobject::{
1011
IntoPyObject, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyResult, TypeProtocol,
@@ -231,6 +232,63 @@ fn sys_displayhook(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
231232
Ok(())
232233
}
233234

235+
#[pystruct_sequence(name = "sys.getwindowsversion")]
236+
#[derive(Default, Debug)]
237+
#[cfg(windows)]
238+
struct WindowsVersion {
239+
major: u32,
240+
minor: u32,
241+
build: u32,
242+
platform: u32,
243+
service_pack: String,
244+
service_pack_major: u16,
245+
service_pack_minor: u16,
246+
suite_mask: u16,
247+
product_type: u8,
248+
platform_version: (u32, u32, u32),
249+
}
250+
251+
#[cfg(windows)]
252+
fn sys_getwindowsversion(vm: &VirtualMachine) -> PyResult<PyTupleRef> {
253+
use winapi::um::{sysinfoapi::GetVersionExW, winnt::{OSVERSIONINFOEXW, LPOSVERSIONINFOW, LPOSVERSIONINFOEXW}};
254+
use std::ffi::OsString;
255+
use std::os::windows::ffi::OsStringExt;
256+
257+
let mut version: OSVERSIONINFOEXW = Default::default();
258+
version.dwOSVersionInfoSize = std::mem::size_of::<OSVERSIONINFOEXW>() as u32;
259+
let result = unsafe {
260+
let osvi = &mut version as LPOSVERSIONINFOEXW as LPOSVERSIONINFOW;
261+
// SAFE: GetVersionExW accepts a pointer of OSVERSIONINFOW, but winapi crate's type currently doesn't allow to do so.
262+
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversionexw#parameters
263+
GetVersionExW(osvi)
264+
};
265+
266+
if result == 0 {
267+
Err(vm.new_os_error("failed to get windows version".to_owned()))
268+
} else {
269+
let service_pack = {
270+
let sp = OsString::from_wide(&version.szCSDVersion);
271+
if let Ok(string) = sp.into_string() {
272+
string
273+
} else {
274+
Err(vm.new_os_error("service pack is not ASCII".to_owned()))?
275+
}
276+
};
277+
WindowsVersion {
278+
major: version.dwMajorVersion,
279+
minor: version.dwMinorVersion,
280+
build: version.dwBuildNumber,
281+
platform: version.dwPlatformId,
282+
service_pack,
283+
service_pack_major: version.wServicePackMajor,
284+
service_pack_minor: version.wServicePackMinor,
285+
suite_mask: version.wSuiteMask,
286+
product_type: version.wProductType,
287+
platform_version: (version.dwMajorVersion, version.dwMinorVersion, version.dwBuildNumber) // TODO Provide accurate version, like CPython impl
288+
}.into_struct_sequence(vm, vm.try_class("sys", "windows_version")?)
289+
}
290+
}
291+
234292
const PLATFORM: &str = {
235293
cfg_if::cfg_if! {
236294
if #[cfg(any(target_os = "linux", target_os = "android"))] {

0 commit comments

Comments
 (0)