@@ -5,6 +5,7 @@ use crate::builtins;
5
5
use crate :: frame:: FrameRef ;
6
6
use crate :: function:: { Args , OptionalArg , PyFuncArgs } ;
7
7
use crate :: obj:: objstr:: PyStringRef ;
8
+ use crate :: obj:: objtuple:: PyTupleRef ;
8
9
use crate :: pyhash:: PyHashInfo ;
9
10
use crate :: pyobject:: {
10
11
IntoPyObject , ItemProtocol , PyClassImpl , PyContext , PyObjectRef , PyResult , TypeProtocol ,
@@ -231,6 +232,63 @@ fn sys_displayhook(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
231
232
Ok ( ( ) )
232
233
}
233
234
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
+
234
292
const PLATFORM : & str = {
235
293
cfg_if:: cfg_if! {
236
294
if #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ] {
0 commit comments