Windows 10 NVMe Get Features sample (C++)

This article only has code sample. If you need explanation, see this article.
This is the code for below WDK 10. If you have newer WDK than 8.1, erase namespace Windows 10.

#include <string>
#include <iostream>
#include <windows.h>
#include <Ntddscsi.h>
#include <tchar.h>

const TCHAR* TestPath = _T("\\\\.\\PhysicalDrive2");

#define BufferSize 4096

namespace Windows10 {
    typedef enum {
        StorageDeviceProperty = 0,
        StorageAdapterProperty,
        StorageDeviceIdProperty,
        StorageDeviceUniqueIdProperty,
        StorageDeviceWriteCacheProperty,
        StorageMiniportProperty,
        StorageAccessAlignmentProperty,
        StorageDeviceSeekPenaltyProperty,
        StorageDeviceTrimProperty,
        StorageDeviceWriteAggregationProperty,
        StorageDeviceDeviceTelemetryProperty,
        StorageDeviceLBProvisioningProperty,
        StorageDevicePowerProperty,
        StorageDeviceCopyOffloadProperty,
        StorageDeviceResiliencyProperty,
        StorageDeviceMediumProductType,
        StorageDeviceRpmbProperty,
        StorageDeviceIoCapabilityProperty = 48,
        StorageAdapterProtocolSpecificProperty,
        StorageDeviceProtocolSpecificProperty,
        StorageAdapterTemperatureProperty,
        StorageDeviceTemperatureProperty,
        StorageAdapterPhysicalTopologyProperty,
        StorageDevicePhysicalTopologyProperty,
        StorageDeviceAttributesProperty,
    } TStoragePropertyId;

    typedef enum {
        PropertyStandardQuery = 0,
        PropertyExistsQuery,
        PropertyMaskQuery,
        PropertyQueryMaxDefined
    } TStorageQueryType;

    typedef struct {
        TStoragePropertyId PropertyId;
        TStorageQueryType QueryType;
    } TStoragePropertyQuery;

    typedef enum {
        ProtocolTypeUnknown = 0x00,
        ProtocolTypeScsi,
        ProtocolTypeAta,
        ProtocolTypeNvme,
        ProtocolTypeSd,
        ProtocolTypeProprietary = 0x7E,
        ProtocolTypeMaxReserved = 0x7F
    } TStroageProtocolType;

    typedef struct {
        TStroageProtocolType ProtocolType;
        DWORD   DataType;
        DWORD   ProtocolDataRequestValue;
        DWORD   ProtocolDataRequestSubValue;
        DWORD   ProtocolDataOffset;
        DWORD   ProtocolDataLength;
        DWORD   FixedProtocolReturnData;
        DWORD   Reserved[3];
    } TStorageProtocolSpecificData;

    typedef enum {
        NVMeDataTypeUnknown = 0,
        NVMeDataTypeIdentify,
        NVMeDataTypeLogPage,
        NVMeDataTypeFeature,
    } TStorageProtocolNVMeDataType;

    typedef struct {
        TStoragePropertyQuery Query;
        TStorageProtocolSpecificData ProtocolSpecific;
        BYTE Buffer[BufferSize];
    } TStorageQueryWithBuffer;
}

void Windows10NVMeGetFeatures(const TCHAR* Path) {
    HANDLE hIoCtrl = CreateFile(TestPath, GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

    Windows10::TStorageQueryWithBuffer nptwb;
    BOOL bRet = 0;
    ZeroMemory(&nptwb, sizeof(nptwb));

    nptwb.ProtocolSpecific.ProtocolType = Windows10::ProtocolTypeNvme;
    nptwb.ProtocolSpecific.DataType = Windows10::NVMeDataTypeFeature;
    nptwb.ProtocolSpecific.ProtocolDataOffset = sizeof(
        Windows10::TStorageProtocolSpecificData);
    nptwb.ProtocolSpecific.ProtocolDataLength = BufferSize;
    nptwb.Query.PropertyId = Windows10::StorageAdapterProtocolSpecificProperty;
    nptwb.Query.QueryType = Windows10::PropertyStandardQuery;
    nptwb.ProtocolSpecific.ProtocolDataRequestValue = 0x04; // Feature Identifier 04h, Temperature Threshold

    DWORD dwReturned = 0;

    bRet = DeviceIoControl(hIoCtrl, IOCTL_STORAGE_QUERY_PROPERTY,
        &nptwb, sizeof(nptwb), &nptwb, sizeof(nptwb), &dwReturned, NULL);
    printf("Result: %d\n", nptwb.ProtocolSpecific.FixedProtocolReturnData);
    CloseHandle(hIoCtrl);
}

int main() {
    Windows10NVMeGetFeatures(TestPath);
    system("pause");
}

Leave a Reply

Your email address will not be published. Required fields are marked *