none
ERROR_INVALID_FUNCTION issuing NVME Protocol specific property request with IOCTL_STORAGE_QUERY_PROPERTY RRS feed

  • Question

  • Hello,

    This code was compiled against the Windows 10 WDK and run on a NVME device using the Windows 10 Inbox driver.

    I am wondering if somebody can tell me if I am performing these requests incorrectly. I can successfully request data of type "NVMeDataTypeFeature" through  IOCTL_STORAGE_QUERY_PROPERTY. It seems that this works because it does not need a separate data device transfer (according to ntddstor.h in WDK 10). However when I request for "NVMeDataTypeIdentify" or "NVMeDataTypeLogPage", I get returned "Error #1 : ERROR_INVALID_FUNCTION". Sample code:

    #include <iostream>
    #include <tchar.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <Windows.h>
    #include <devioctl.h>
    #include <ntddstor.h>
    
    
    void queryNVMEProperty(bool requestFromDevice, int value, int subvalue, int feature, HANDLE * handle, UCHAR * outArray, DWORD outArraySize) {
    	memset(outArray, 0, outArraySize);
    	const DWORD IN_ARRAY_SIZE = sizeof(STORAGE_PROPERTY_QUERY) + sizeof(STORAGE_PROTOCOL_SPECIFIC_DATA);
    	UCHAR propQuery[IN_ARRAY_SIZE];
    	memset(propQuery, 0, IN_ARRAY_SIZE);
    	PSTORAGE_PROPERTY_QUERY pQueryDataDesc = reinterpret_cast<PSTORAGE_PROPERTY_QUERY>(propQuery);
    	PSTORAGE_PROTOCOL_SPECIFIC_DATA pNvmeExtraData = reinterpret_cast<PSTORAGE_PROTOCOL_SPECIFIC_DATA>(pQueryDataDesc->AdditionalParameters);
    	
    	pNvmeExtraData->ProtocolType = ProtocolTypeNvme;
    	pNvmeExtraData->DataType = feature;
    	pNvmeExtraData->ProtocolDataRequestValue = value;
    	pNvmeExtraData->ProtocolDataRequestSubValue = subvalue;
    	std::cout << " CONFIGURATION:" << std::endl;
    	if (requestFromDevice) {
    		std::cout << "  StorageDeviceProtocolSpecificProperty " << feature << " " << value << " " << subvalue << std::endl;
    		pQueryDataDesc->PropertyId = StorageDeviceProtocolSpecificProperty;
    	}
    	else {
    		std::cout << "  StorageAdapterProtocolSpecificProperty " << value << " " << subvalue << std::endl;
    		pQueryDataDesc->PropertyId = StorageAdapterProtocolSpecificProperty;
    	}
    	pQueryDataDesc->QueryType = PropertyStandardQuery;
    	DWORD bytesRet = 0;
    
    	if (DeviceIoControl(*handle,
    		IOCTL_STORAGE_QUERY_PROPERTY,
    		propQuery,
    		sizeof(propQuery),
    		outArray,
    		outArraySize,
    		&bytesRet,
    		NULL)) {
    		std::cout << "  IOCTL_STORAGE_QUERY_PROPERTY returned OK" << std::endl;
    	}
    	else {
    		std::cout << "   IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: " << GetLastError() << std::endl;
    	}
    }
    
    int __cdecl main(int argc, char *argv[]) {
    	printf("Test NVME property query...\n");
    	//const char * locator =  "\\\\?\\scsi#disk&ven_nvme&prod_intel_ssdpedme40#5&20ba80d3&1&000000#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}";
    	//const char * locator2 = "\\\\?\\scsi#disk&ven_nvme&prod_thnsn51t02du7_to#5&1145c5b5&0&000000#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}";
    
    	if (argc < 2) {
    		fprintf(stderr, "Usage : %s <device locator>\n", argv[0]);
    		fprintf(stderr, "Sample locator \"%s\"\n", "\\\\?\\scsi#disk&ven_nvme&prod_intel_ssdpedme40#5&20ba80d3&1&000000#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}");
    		return 3;
    	}
    
    	HANDLE handle = CreateFile(_T(argv[1]),
    		GENERIC_READ|GENERIC_WRITE,
    		FILE_SHARE_READ|FILE_SHARE_WRITE,
    		NULL,
    		OPEN_EXISTING,
    		NULL,
    		NULL
    		);
    	
    	if (handle == INVALID_HANDLE_VALUE) {
    			std::cout << "INVALID HANDLE, exiting" << std::endl;
    			return 1;
    	}	
    	else {
    		std::cout << "Successfully opened handle to : \"" << argv[1] << "\"" << std::endl;
    	}
    
    	UCHAR identifyData[sizeof(STORAGE_PROTOCOL_DATA_DESCRIPTOR) + 4096]; //enough room for Identify result
    	queryNVMEProperty(true, 0, 0, 1, &handle, identifyData, sizeof(identifyData)); //NVMeDataTypeIdentify
    	queryNVMEProperty(true, 0, 1, 1, &handle, identifyData, sizeof(identifyData)); //NVMeDataTypeIdentify
    	queryNVMEProperty(true, 0, 1, 1, &handle, identifyData, sizeof(identifyData)); //NVMeDataTypeIdentify
    	queryNVMEProperty(true, 1, 1, 1, &handle, identifyData, sizeof(identifyData)); //NVMeDataTypeIdentify
    	queryNVMEProperty(false, 0, 0, 1, &handle, identifyData, sizeof(identifyData)); //NVMeDataTypeIdentify
    	queryNVMEProperty(false, 1, 0, 1, &handle, identifyData, sizeof(identifyData)); //NVMeDataTypeIdentify
    	queryNVMEProperty(false, 0, 1, 1, &handle, identifyData, sizeof(identifyData)); //NVMeDataTypeIdentify
    	queryNVMEProperty(false, 1, 1, 1, &handle, identifyData, sizeof(identifyData)); //NVMeDataTypeIdentify
    
    	UCHAR featureData[sizeof(STORAGE_PROTOCOL_DATA_DESCRIPTOR)];
    	//I assume ProtocolDataRequestValue is the FEATURE to request, this is not documented here
    	//https://msdn.microsoft.com/en-us/library/windows/hardware/dn931816(v=vs.85).aspx
    	queryNVMEProperty(true, 1, 0, 3, &handle, featureData, sizeof(featureData)); //NVMeDataTypeFeature
    	queryNVMEProperty(true, 2, 0, 3, &handle, featureData, sizeof(featureData)); //NVMeDataTypeFeature
    	queryNVMEProperty(true, 3, 0, 3, &handle, featureData, sizeof(featureData)); //NVMeDataTypeFeature
    	queryNVMEProperty(true, 4, 0, 3, &handle, featureData, sizeof(featureData)); //NVMeDataTypeFeature
    	queryNVMEProperty(true, 5, 0, 3, &handle, featureData, sizeof(featureData)); //NVMeDataTypeFeature
    	queryNVMEProperty(true, 6, 0, 3, &handle, featureData, sizeof(featureData)); //NVMeDataTypeFeature
    
    	UCHAR logData[sizeof(STORAGE_PROTOCOL_DATA_DESCRIPTOR) + 4096];
    	//I assume ProtocolDataRequestValue is the LOG PAGE to request, this is not documented here
    	//https://msdn.microsoft.com/en-us/library/windows/hardware/dn931816(v=vs.85).aspx
    	queryNVMEProperty(true, 1, 0, 2, &handle, logData, sizeof(logData)); //NVMeDataTypeLogPage
    	queryNVMEProperty(true, 2, 0, 2, &handle, logData, sizeof(logData)); //NVMeDataTypeLogPage
    	queryNVMEProperty(true, 3, 0, 2, &handle, logData, sizeof(logData)); //NVMeDataTypeLogPage
    	queryNVMEProperty(true, 4, 0, 2, &handle, logData, sizeof(logData)); //NVMeDataTypeLogPage
    	queryNVMEProperty(true, 5, 0, 2, &handle, logData, sizeof(logData)); //NVMeDataTypeLogPage
    	queryNVMEProperty(true, 6, 0, 2, &handle, logData, sizeof(logData)); //NVMeDataTypeLogPage
    	
    	CloseHandle(handle);
    
    	return 0;
    }

    This returns for me:

    ApplicationForDrivers7.exe "\\?\scsi#disk&ven_nvme&prod_intel_ssdpedme40#5&20ba80d3&1&000000#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}"
    Test NVME property query...
    Successfully opened handle to : "\\?\scsi#disk&ven_nvme&prod_intel_ssdpedme40#5&20ba80d3&1&000000#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}"
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 1 0 0
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 1 0 1
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 1 0 1
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 1 1 1
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageAdapterProtocolSpecificProperty 0 0
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageAdapterProtocolSpecificProperty 1 0
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageAdapterProtocolSpecificProperty 0 1
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageAdapterProtocolSpecificProperty 1 1
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 3 1 0
      IOCTL_STORAGE_QUERY_PROPERTY returned OK
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 3 2 0
      IOCTL_STORAGE_QUERY_PROPERTY returned OK
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 3 3 0
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 3 4 0
      IOCTL_STORAGE_QUERY_PROPERTY returned OK
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 3 5 0
      IOCTL_STORAGE_QUERY_PROPERTY returned OK
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 3 6 0
      IOCTL_STORAGE_QUERY_PROPERTY returned OK
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 2 1 0
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 2 2 0
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 2 3 0
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 2 4 0
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 2 5 0
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1
     CONFIGURATION:
      StorageDeviceProtocolSpecificProperty 2 6 0
       IOCTL_STORAGE_QUERY_PROPERTY FAILED with error: 1117

    =====================================

    The errors for:

    "StorageDeviceProtocolSpecificProperty 3 3 0: error 1" and "StorageDeviceProtocolSpecificProperty 2 6 0: error 1117", are expected, presumably because the feature and log are not supported by the device respectively. The other errors are not expected. Can somebody tell me if I am formulating these requests incorrectly?

    Thank you



    • Edited by paul_s04 Wednesday, October 14, 2015 4:17 PM
    Wednesday, October 14, 2015 4:07 PM

Answers

  • This turned out to be my misunderstanding of how to formulate the arguments to DeviceIoControl. I have since resolved this, it was an issue with the input and output buffer I was using as arguments. Using the same buffer as an argument and setting the ProtocolDataOffset and ProtocolDataLength in STORAGE_PROTOCOL_SPECIFIC_DATA accordingly resolves the problem.

    Thanks, Paul


    • Marked as answer by paul_s04 Wednesday, October 14, 2015 8:13 PM
    • Edited by paul_s04 Wednesday, October 14, 2015 8:14 PM
    Wednesday, October 14, 2015 8:13 PM