Windows 10 NVMe Command 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("\\\\.\\PhysicalDrive5");

#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 Windows10NVMeIdentify(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::NVMeDataTypeIdentify;
    nptwb.ProtocolSpecific.ProtocolDataOffset = sizeof(
        Windows10::TStorageProtocolSpecificData);
    nptwb.ProtocolSpecific.ProtocolDataLength = BufferSize;
    nptwb.Query.PropertyId = Windows10::StorageAdapterProtocolSpecificProperty;
    nptwb.Query.QueryType = Windows10::PropertyStandardQuery;
    DWORD dwReturned = 0;

    bRet = DeviceIoControl(hIoCtrl, IOCTL_STORAGE_QUERY_PROPERTY,
        &nptwb, sizeof(nptwb), &nptwb, sizeof(nptwb), &dwReturned, NULL);
    CloseHandle(hIoCtrl);
}

int main() {
    Windows10NVMeIdentify(TestPath);
}

4 comments on “Windows 10 NVMe Command Sample (C++)

  1. Hello Naraeon
    Could you show us a example of NVMeDataTypeFeature ?

    Here is my code, but it seems not work

    nptwb.ProtocolSpecific.ProtocolType = StorageQuery::ProtocolTypeNvme;
    nptwb.ProtocolSpecific.DataType = StorageQuery::NVMeDataTypeFeature;

    nptwb.ProtocolSpecific.ProtocolDataRequestValue = iFeatureId;
    nptwb.ProtocolSpecific.ProtocolDataRequestSubValue = iNSID;

    nptwb.ProtocolSpecific.ProtocolDataOffset = sizeof(StorageQuery::TStorageProtocolSpecificData);
    nptwb.ProtocolSpecific.ProtocolDataLength = 4096;
    nptwb.Query.PropertyId = StorageQuery::StorageAdapterProtocolSpecificProperty;
    nptwb.Query.QueryType = StorageQuery::PropertyStandardQuery;

  2. Hello Naraeon
    The result of NVMeDataTypeFeature could be got from &nptwb.ProtocolSpecific.FixedProtocolReturnData
    but it is not work for all of the feature ids 🙂

Leave a Reply

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