nts.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 {},
};
PK