diff options
Diffstat (limited to 'toolkit/components/utils/WindowsVersionInfo.sys.mjs')
-rw-r--r-- | toolkit/components/utils/WindowsVersionInfo.sys.mjs | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/toolkit/components/utils/WindowsVersionInfo.sys.mjs b/toolkit/components/utils/WindowsVersionInfo.sys.mjs new file mode 100644 index 0000000000..70fa3ef9c6 --- /dev/null +++ b/toolkit/components/utils/WindowsVersionInfo.sys.mjs @@ -0,0 +1,112 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; +import { ctypes } from "resource://gre/modules/ctypes.sys.mjs"; + +const BYTE = ctypes.uint8_t; +const WORD = ctypes.uint16_t; +const DWORD = ctypes.uint32_t; +const WCHAR = ctypes.char16_t; +const BOOL = ctypes.int; + +export var WindowsVersionInfo = { + UNKNOWN_VERSION_INFO: { + servicePackMajor: null, + servicePackMinor: null, + buildNumber: null, + }, + + /** + * Gets the service pack and build number on Windows platforms. + * + * @param opts {Object} keyword arguments + * @param opts.throwOnError {boolean} Optional, defaults to true. If set to + * false will return an object with keys set to null instead of throwing an + * error. If set to true, errors will be thrown instead. + * @throws If `throwOnError` is true and version information cannot be + * determined. + * @return {object} An object containing keys `servicePackMajor`, + * `servicePackMinor`, and `buildNumber`. If `throwOnError` is false, these + * values may be null. + */ + get({ throwOnError = true } = {}) { + function throwOrUnknown(err) { + if (throwOnError) { + throw err; + } + console.error(err); + return WindowsVersionInfo.UNKNOWN_VERSION_INFO; + } + + if (AppConstants.platform !== "win") { + return throwOrUnknown( + WindowsVersionInfo.NotWindowsError( + `Cannot get Windows version info on platform ${AppConstants.platform}` + ) + ); + } + + // This structure is described at: + // http://msdn.microsoft.com/en-us/library/ms724833%28v=vs.85%29.aspx + const SZCSDVERSIONLENGTH = 128; + const OSVERSIONINFOEXW = new ctypes.StructType("OSVERSIONINFOEXW", [ + { dwOSVersionInfoSize: DWORD }, + { dwMajorVersion: DWORD }, + { dwMinorVersion: DWORD }, + { dwBuildNumber: DWORD }, + { dwPlatformId: DWORD }, + { szCSDVersion: ctypes.ArrayType(WCHAR, SZCSDVERSIONLENGTH) }, + { wServicePackMajor: WORD }, + { wServicePackMinor: WORD }, + { wSuiteMask: WORD }, + { wProductType: BYTE }, + { wReserved: BYTE }, + ]); + + let kernel32; + try { + kernel32 = ctypes.open("kernel32"); + } catch (err) { + return throwOrUnknown( + new WindowsVersionInfo.CannotOpenKernelError( + `Unable to open kernel32! ${err}` + ) + ); + } + + try { + let GetVersionEx = kernel32.declare( + "GetVersionExW", + ctypes.winapi_abi, + BOOL, + OSVERSIONINFOEXW.ptr + ); + let winVer = OSVERSIONINFOEXW(); + winVer.dwOSVersionInfoSize = OSVERSIONINFOEXW.size; + + if (GetVersionEx(winVer.address()) === 0) { + throw new WindowsVersionInfo.GetVersionExError( + "Failure in GetVersionEx (returned 0)" + ); + } + + return { + servicePackMajor: winVer.wServicePackMajor, + servicePackMinor: winVer.wServicePackMinor, + buildNumber: winVer.dwBuildNumber, + }; + } catch (err) { + return throwOrUnknown(err); + } finally { + if (kernel32) { + kernel32.close(); + } + } + }, + + CannotOpenKernelError: class extends Error {}, + GetVersionExError: class extends Error {}, + NotWindowsError: class extends Error {}, +}; |