0

Is there a way in VC++ to get whether the installed drive in a computer is HDD or SSD? Also, to get where a certain resides in HDD or SSD.

I would appreciate any help.. Thanks!

patlimosnero
  • 963
  • 4
  • 13
  • 22
  • 1
    What exactly are your needs? In many cases even the OS doesn't know that a drive is an SSD. – Gabe Apr 20 '11 at 02:17
  • 1
    Given the cost of SSD, why not just ask the owner? She'll know. – Hans Passant Apr 20 '11 at 02:35
  • Consider this not possible. An important feature of an SSD is that it behaves exactly the same way as a standard hard disk. Anything that would be specific to an SSD would be handled by the operating system and low-level drivers, not your application. – Cody Gray - on strike Apr 20 '11 at 04:46
  • @Gabe: "In most cases" is the problem. – user541686 May 13 '12 at 21:02
  • @CodyGray: It's quiet possible, with good accuracy; see my answer. There might even be a 100% accurate way to do it, though I don't know one personally. (I just came across [this](http://stackoverflow.com/questions/9273373/tell-if-a-path-refers-to-a-solid-state-drive-with-winapi), which might also work, though I haven't tried it.) – user541686 May 13 '12 at 21:02
  • @Mehrdad Yeah, the point was "consider it not possible" because the point of an SSD is that it works exactly the same way as a normal spinning platter disk. Of course sniffing the product name will work (except when it doesn't), the point was that the difference should not ever be relevant, and if you think it is, you're doing something wrong from the outset. – Cody Gray - on strike May 14 '12 at 17:33

1 Answers1

0

This isn't 100% foolproof, but it's the method Linux uses.
It checks if the word "SSD" is in the Product ID of the drive:

#include <tchar.h>
#include <windows.h>
#include <winioctl.h>

void Check(LPCTSTR file, LPCTSTR volPathWithLeadingPrefix)
{
    HANDLE hFile = CreateFile(
        volPathWithLeadingPrefix,
        FILE_READ_ATTRIBUTES,  // Just querying; don't mount
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
    STORAGE_PROPERTY_QUERY spq =
    { StorageDeviceProperty, PropertyStandardQuery };
    union
    {
        STORAGE_DEVICE_DESCRIPTOR StorageDeviceDescriptor;
        BYTE Data[1024];
    } output = {0};
    DWORD br;
    if (DeviceIoControl(
        hFile, IOCTL_STORAGE_QUERY_PROPERTY,
        &spq, sizeof(spq), &output, sizeof(output),
        &br, NULL))
    {
        STORAGE_DEVICE_DESCRIPTOR &sdd =
            output.StorageDeviceDescriptor;
        if (sdd.ProductIdOffset > 0)
        {
            LPCSTR productID = (LPCSTR)&((LPBYTE)&sdd)[sdd.ProductIdOffset];
            BOOL isSSD = strstr(productID, "SSD") != NULL;
            _tprintf(_T("\"%s\": %s\n"), file, isSSD ? _T("SSD") : _T("HDD"));
        }
        else { _ftprintf(stderr, _T("No product ID.")); }
    }
    else
    { _ftprintf(stderr, _T("Error %u querying storage.\n"), GetLastError()); }
}

int _tmain(int argc, TCHAR *argv[])
{
    for (int i = 1; i < argc; i++)
    {
        LPCTSTR file = argv[i];
        TCHAR volPath[MAX_PATH];
        if (GetVolumePathName(file, volPath, ARRAYSIZE(volPath)))
        {
            for (size_t cchVolPath = _tcslen(volPath);
                cchVolPath > 0 && volPath[cchVolPath - 1] == TEXT('\\');
                cchVolPath--)
            { volPath[cchVolPath - 1] = TEXT('\0'); }

            TCHAR volPathWithLeadingPrefix[ARRAYSIZE(volPath)];
            if (_sntprintf(
                volPathWithLeadingPrefix,
                ARRAYSIZE(volPathWithLeadingPrefix),
                volPath[0] == _T('\\') ? _T("%s") : _T("\\\\.\\%s"),
                volPath) < ARRAYSIZE(volPathWithLeadingPrefix))
            {
                Check(file, volPathWithLeadingPrefix);
            }
            else
            {
                SetLastError(ERROR_FILENAME_EXCED_RANGE);
                _ftprintf(stderr, _T("Path \"%s\" is too long.\n"), volPath);
            }
        }
        else
        {
            _ftprintf(
                stderr,
                _T("Error %u getting volume path.\n"),
                GetLastError());
        }
    }
}
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
user541686
  • 205,094
  • 128
  • 528
  • 886
  • 1
    My SSD says "SAMSUNG MMCRE28G8MXP-0VB". – Gabe May 13 '12 at 21:14
  • @Gabe: Like I said, it isn't foolproof. But it [*is*](http://linux.derkeiler.com/Mailing-Lists/Kernel/2009-04/msg03625.html) the method used by some programs, and it *does* sometimes work, so it's better than nothing. Maybe [this](http://stackoverflow.com/a/9273540/541686) would work better though, I don't know. – user541686 May 13 '12 at 21:18