1"""
2Get Version information from Windows
3"""
4# http://stackoverflow.com/questions/32300004/python-ctypes-getting-0-with-getversionex-function
5
6import ctypes
7
8HAS_WIN32 = True
9try:
10    from ctypes.wintypes import BYTE, WORD, DWORD, WCHAR
11    import win32net
12    import win32netcon
13except (ImportError, ValueError):
14    HAS_WIN32 = False
15
16if HAS_WIN32:
17    kernel32 = ctypes.WinDLL(
18        "kernel32",
19        use_last_error=True,
20    )
21
22
23# Although utils are often directly imported, it is also possible to use the
24# loader.
25def __virtual__():
26    """
27    Only load if Win32 Libraries are installed
28    """
29    if not HAS_WIN32:
30        return False, "This utility requires pywin32"
31
32    return "win_osinfo"
33
34
35def os_version_info_ex():
36    """
37    Helper function to return the results of the GetVersionExW Windows API call.
38    It is a ctypes Structure that contains Windows OS Version information.
39
40    Returns:
41        class: An instance of a class containing version info
42    """
43    if not HAS_WIN32:
44        return
45
46    class OSVersionInfo(ctypes.Structure):
47        _fields_ = (
48            ("dwOSVersionInfoSize", DWORD),
49            ("dwMajorVersion", DWORD),
50            ("dwMinorVersion", DWORD),
51            ("dwBuildNumber", DWORD),
52            ("dwPlatformId", DWORD),
53            ("szCSDVersion", WCHAR * 128),
54        )
55
56        def __init__(self, *args, **kwds):
57            super().__init__(*args, **kwds)
58            self.dwOSVersionInfoSize = ctypes.sizeof(self)
59            kernel32.GetVersionExW(ctypes.byref(self))
60
61    class OSVersionInfoEx(OSVersionInfo):
62        _fields_ = (
63            ("wServicePackMajor", WORD),
64            ("wServicePackMinor", WORD),
65            ("wSuiteMask", WORD),
66            ("wProductType", BYTE),
67            ("wReserved", BYTE),
68        )
69
70    return OSVersionInfoEx()
71
72
73def get_os_version_info():
74    info = os_version_info_ex()
75    ret = {
76        "MajorVersion": info.dwMajorVersion,
77        "MinorVersion": info.dwMinorVersion,
78        "BuildNumber": info.dwBuildNumber,
79        "PlatformID": info.dwPlatformId,
80        "ServicePackMajor": info.wServicePackMajor,
81        "ServicePackMinor": info.wServicePackMinor,
82        "SuiteMask": info.wSuiteMask,
83        "ProductType": info.wProductType,
84    }
85
86    return ret
87
88
89def get_join_info():
90    """
91    Gets information about the domain/workgroup. This will tell you if the
92    system is joined to a domain or a workgroup
93
94    .. versionadded:: 2018.3.4
95
96    Returns:
97        dict: A dictionary containing the domain/workgroup and its status
98    """
99    info = win32net.NetGetJoinInformation()
100    status = {
101        win32netcon.NetSetupUnknown: "Unknown",
102        win32netcon.NetSetupUnjoined: "Unjoined",
103        win32netcon.NetSetupWorkgroupName: "Workgroup",
104        win32netcon.NetSetupDomainName: "Domain",
105    }
106    return {"Domain": info[0], "DomainType": status[info[1]]}
107