/*
* os_win32.cpp
*
- * Home page of code is: http://smartmontools.sourceforge.net
+ * Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2004-15 Christian Franke
*
#define strnicmp strncasecmp
#endif
-const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 4098 2015-05-30 16:37:37Z chrfranke $";
+const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 4156 2015-10-18 12:20:40Z samm2 $";
/////////////////////////////////////////////////////////////////////////////
// Windows I/O-controls, some declarations are missing in the include files
const int vlen = sizeof(vstr)-sizeof(SMARTMONTOOLS_BUILD_HOST);
assert(vptr == vstr+strlen(vstr) && vptr+vlen+1 == vstr+sizeof(vstr));
- OSVERSIONINFOEXA vi; memset(&vi, 0, sizeof(vi));
+ // Starting with Windows 8.1, GetVersionEx() does no longer report the
+ // actual OS version, see:
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
+
+ // RtlGetVersion() is not affected
+ LONG /*NTSTATUS*/ (WINAPI /*NTAPI*/ * RtlGetVersion_p)(LPOSVERSIONINFOEXW) =
+ (LONG (WINAPI *)(LPOSVERSIONINFOEXW))
+ GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion");
+
+ OSVERSIONINFOEXW vi; memset(&vi, 0, sizeof(vi));
vi.dwOSVersionInfoSize = sizeof(vi);
- if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
- memset(&vi, 0, sizeof(vi));
- vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
- if (!GetVersionExA((OSVERSIONINFOA *)&vi))
+ if (!RtlGetVersion_p || RtlGetVersion_p(&vi)) {
+ if (!GetVersionExW((OSVERSIONINFOW *)&vi))
return vstr;
}
const char * w = 0;
- if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-
- if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) {
- // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the
- // actual OS version, see:
- // http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
-
- ULONGLONG major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
- for (unsigned major = vi.dwMajorVersion; major <= 9; major++) {
- OSVERSIONINFOEXA vi2; memset(&vi2, 0, sizeof(vi2));
- vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major;
- if (!VerifyVersionInfo(&vi2, VER_MAJORVERSION, major_equal))
- continue;
- if (vi.dwMajorVersion < major) {
- vi.dwMajorVersion = major; vi.dwMinorVersion = 0;
- }
-
- ULONGLONG minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
- for (unsigned minor = vi.dwMinorVersion; minor <= 9; minor++) {
- memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2);
- vi2.dwMinorVersion = minor;
- if (!VerifyVersionInfo(&vi2, VER_MINORVERSION, minor_equal))
- continue;
- vi.dwMinorVersion = minor;
- break;
- }
-
- break;
- }
- }
-
- if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) {
- bool ws = (vi.wProductType <= VER_NT_WORKSTATION);
- switch (vi.dwMajorVersion << 4 | vi.dwMinorVersion) {
- case 0x50: w = "2000"; break;
- case 0x51: w = "xp"; break;
- case 0x52: w = (!GetSystemMetrics(89/*SM_SERVERR2*/)
- ? "2003" : "2003r2"); break;
- case 0x60: w = (ws ? "vista" : "2008" ); break;
- case 0x61: w = (ws ? "win7" : "2008r2"); break;
- case 0x62: w = (ws ? "win8" : "2012" ); break;
- case 0x63: w = (ws ? "win8.1": "2012r2"); break;
- case 0x64: w = (ws ? "win10" : "w10srv"); break;
- }
+ if ( vi.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) {
+ bool ws = (vi.wProductType <= VER_NT_WORKSTATION);
+ switch (vi.dwMajorVersion << 4 | vi.dwMinorVersion) {
+ case 0x50: w = "2000"; break;
+ case 0x51: w = "xp"; break;
+ case 0x52: w = (!GetSystemMetrics(89/*SM_SERVERR2*/)
+ ? "2003" : "2003r2"); break;
+ case 0x60: w = (ws ? "vista" : "2008" ); break;
+ case 0x61: w = (ws ? "win7" : "2008r2"); break;
+ case 0x62: w = (ws ? "win8" : "2012" ); break;
+ case 0x63: w = (ws ? "win8.1": "2012r2"); break;
+ case 0x64: w = (ws ? "w10tp" : "w10tps"); break; // 6.4 = Win 10 Technical Preview
+ case 0xa0: w = (ws ? "win10" : "w10srv"); break; // 10.0 = Win 10 Final
}
}
static win_dev_type get_phy_drive_type(int drive);
static win_dev_type get_phy_drive_type(int drive, GETVERSIONINPARAMS_EX * ata_version_ex);
static win_dev_type get_log_drive_type(int drive);
-static bool get_usb_id(int drive, unsigned short & vendor_id,
+static bool get_usb_id(int phydrive, int logdrive,
+ unsigned short & vendor_id,
unsigned short & product_id);
static const char * ata_get_def_options(void);
return phydrive;
}
-static win_dev_type get_dev_type(const char * name, int & phydrive)
+static win_dev_type get_dev_type(const char * name, int & phydrive, int & logdrive)
{
- phydrive = -1;
+ phydrive = logdrive = -1;
+
name = skipdev(name);
if (!strncmp(name, "st", 2))
return DEV_SCSI;
if (!strncmp(name, "tape", 4))
return DEV_SCSI;
- int logdrive = drive_letter(name);
+ logdrive = drive_letter(name);
if (logdrive >= 0) {
win_dev_type type = get_log_drive_type(logdrive);
return (type != DEV_UNKNOWN ? type : DEV_SCSI);
return get_phy_drive_type(phydrive);
}
- phydrive = -1;
if (sscanf(name, "pd%d", &phydrive) == 1 && phydrive >= 0)
return get_phy_drive_type(phydrive);
+
return DEV_UNKNOWN;
}
if (str_starts_with(testname, "csmi"))
return new win_csmi_device(this, name, "");
- int phydrive = -1;
- win_dev_type type = get_dev_type(name, phydrive);
+ int phydrive = -1, logdrive = -1;
+ win_dev_type type = get_dev_type(name, phydrive, logdrive);
if (type == DEV_ATA)
return new win_ata_device(this, name, "");
if (type == DEV_USB) {
// Get USB bridge ID
unsigned short vendor_id = 0, product_id = 0;
- if (!(phydrive >= 0 && get_usb_id(phydrive, vendor_id, product_id))) {
+ if (!get_usb_id(phydrive, logdrive, vendor_id, product_id)) {
set_err(EINVAL, "Unable to read USB device ID");
return 0;
}
raid_seen[vers_ex.wControllerId] = true;
// Add physical drives
int len = strlen(name);
- for (int pi = 0; pi < 32; pi++) {
+ for (unsigned int pi = 0; pi < 32; pi++) {
if (vers_ex.dwDeviceMapEx & (1L << pi)) {
snprintf(name+len, sizeof(name)-1-len, ",%u", pi);
devlist.push_back( new win_ata_device(this, name, "ata") );
// TODO: Use common function for this and autodetect_smart_device()
// Get USB bridge ID
unsigned short vendor_id = 0, product_id = 0;
- if (!get_usb_id(i, vendor_id, product_id))
+ if (!get_usb_id(i, -1, vendor_id, product_id))
continue;
// Get type name for this ID
const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id);
/////////////////////////////////////////////////////////////////////////////
// USB ID detection using WMI
-// Get USB ID for a physical drive number
-static bool get_usb_id(int drive, unsigned short & vendor_id, unsigned short & product_id)
+// Get USB ID for a physical or logical drive number
+static bool get_usb_id(int phydrive, int logdrive,
+ unsigned short & vendor_id,
+ unsigned short & product_id)
{
bool debug = (scsi_debugmode > 1);
}
// Get device name
+ std::string name;
+
wbem_object wo;
- if (!ws.query1(wo, "SELECT Model FROM Win32_DiskDrive WHERE DeviceID=\"\\\\\\\\.\\\\PHYSICALDRIVE%d\"", drive))
+ if (0 <= logdrive && logdrive <= 'Z'-'A') {
+ // Drive letter -> Partition info
+ if (!ws.query1(wo, "ASSOCIATORS OF {Win32_LogicalDisk.DeviceID=\"%c:\"} WHERE ResultClass = Win32_DiskPartition",
+ 'A'+logdrive))
+ return false;
+
+ std::string partid = wo.get_str("DeviceID");
+ if (debug)
+ pout("%c: --> \"%s\" -->\n", 'A'+logdrive, partid.c_str());
+
+ // Partition ID -> Physical drive info
+ if (!ws.query1(wo, "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=\"%s\"} WHERE ResultClass = Win32_DiskDrive",
+ partid.c_str()))
+ return false;
+
+ name = wo.get_str("Model");
+ if (debug)
+ pout("%s --> \"%s\":\n", wo.get_str("DeviceID").c_str(), name.c_str());
+ }
+
+ else if (phydrive >= 0) {
+ // Physical drive number -> Physical drive info
+ if (!ws.query1(wo, "SELECT Model FROM Win32_DiskDrive WHERE DeviceID=\"\\\\\\\\.\\\\PHYSICALDRIVE%d\"", phydrive))
+ return false;
+
+ name = wo.get_str("Model");
+ if (debug)
+ pout("\\.\\\\PHYSICALDRIVE%d --> \"%s\":\n", phydrive, name.c_str());
+ }
+ else
return false;
- std::string name = wo.get_str("Model");
- if (debug)
- pout("PhysicalDrive%d, \"%s\":\n", drive, name.c_str());
// Get USB_CONTROLLER -> DEVICE associations
wbem_enumerator we;
prev_usb_ant = ant;
if (debug)
pout(" +-> \"%s\" [0x%04x:0x%04x]\n", devid.c_str(), prev_usb_venid, prev_usb_proid);
- continue;
}
- else if (str_starts_with(devid, "USBSTOR\\\\")) {
- // USBSTOR device found
+ else if (str_starts_with(devid, "USBSTOR\\\\") || str_starts_with(devid, "SCSI\\\\")) {
+ // USBSTORage or SCSI device found
if (debug)
pout(" +--> \"%s\"\n", devid.c_str());
close();
return set_err(ENOSYS);
}
- devmap = 0x0f;
}
m_smartver_state = 1;
break;
case 'f':
if (in.in_regs.command == ATA_IDENTIFY_DEVICE) {
- rc = get_identify_from_device_property(get_fh(), (ata_identify_device *)data);
+ ata_identify_device * id = reinterpret_cast<ata_identify_device *>(data);
+ rc = get_identify_from_device_property(get_fh(), id);
if (rc == 0 && m_phydrive >= 0)
- get_serial_from_wmi(m_phydrive, (ata_identify_device *)data);
+ get_serial_from_wmi(m_phydrive, id);
id_is_cached = true;
}
else if (in.in_regs.command == ATA_SMART_CMD) switch (in.in_regs.features) {
smart_device * win_areca_ata_device::autodetect_open()
{
- int is_ata = 1;
-
// autodetect device type
- is_ata = arcmsr_get_dev_type();
+ int is_ata = arcmsr_get_dev_type();
if(is_ata < 0)
{
set_err(EIO);