ExylonFiber
Well-Known Member
- Joined
- Apr 25, 2020
- Messages
- 26
- Thread Author
-
- #1
I am getting an access violation when iterating through SCSI HDD's. I'm sure I'm doing something that needs a minor tweak to get it to work properly. Anyone have any ideas on why I'm getting an access violation every time?
Code:
HANDLE handle = CreateFile("\\\\.\\PhysicalDrive1", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
PUCHAR inBuffer[sizeof(SRB_IO_CONTROL) + sizeof(FIRMWARE_REQUEST_BLOCK)];
PUCHAR outBuffer[sizeof(SRB_IO_CONTROL) + sizeof(FIRMWARE_REQUEST_BLOCK) + sizeof(STORAGE_FIRMWARE_SLOT_INFO)];
DWORD outBufferLength = sizeof(outBuffer);
DWORD inBufferLength = sizeof(inBuffer);
BOOL result;
ULONG returnedLength;
ULONG firmwareInfoOffset;
memset(&inBuffer, 0, sizeof(SRB_IO_CONTROL) + sizeof(FIRMWARE_REQUEST_BLOCK));
PSRB_IO_CONTROL srbControl;
std::cout << "srbControl size: " << sizeof(SRB_IO_CONTROL) << "\n";
PFIRMWARE_REQUEST_BLOCK firmwareRequest;
PSTORAGE_FIRMWARE_INFO firmwareInfo; //Define Structure for Firmware Info
srbControl = (PSRB_IO_CONTROL)inBuffer;
firmwareRequest = (PFIRMWARE_REQUEST_BLOCK)(srbControl + 1);
//The STORAGE_FIRMWARE_INFO is located after SRB_IO_CONTROL and FIRMWARE_REQUEST_BLOCK
firmwareInfoOffset = ((sizeof(SRB_IO_CONTROL) + sizeof(FIRMWARE_REQUEST_BLOCK) - 1) / sizeof(PVOID) + 1) * sizeof(PVOID);
//
// Setup the SRB control with the firmware ioctl control info
//
srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
srbControl->ControlCode = IOCTL_SCSI_MINIPORT_FIRMWARE;
RtlMoveMemory(srbControl->Signature, IOCTL_MINIPORT_SIGNATURE_FIRMWARE, 8);
srbControl->Timeout = 30;
srbControl->Length = inBufferLength - sizeof(SRB_IO_CONTROL);
//
// Set firmware request fields for FIRMWARE_FUNCTION_GET_INFO. This request is to the controller so
// FIRMWARE_REQUEST_FLAG_CONTROLLER is set in the flags
//
firmwareRequest->Version = FIRMWARE_REQUEST_BLOCK_STRUCTURE_VERSION;
firmwareRequest->Size = sizeof(FIRMWARE_REQUEST_BLOCK);
firmwareRequest->Function = FIRMWARE_FUNCTION_GET_INFO;
firmwareRequest->Flags = FIRMWARE_REQUEST_FLAG_CONTROLLER;
firmwareRequest->DataBufferOffset = firmwareInfoOffset;
firmwareRequest->DataBufferLength = inBufferLength - firmwareInfoOffset;
//
// Send the request to get the device firmware info
//
result = DeviceIoControl(handle,
IOCTL_SCSI_MINIPORT,
inBuffer,
inBufferLength,
outBuffer,
outBufferLength,
&returnedLength,
NULL
);
std::cout << "Returned Length: " << returnedLength << "\n";
std::cout << "result: " << result << "\n";
//
// Format and display the firmware info
//
if (result != 0) {
if (!result) {
_tprintf(_T("\t Get Firmware Information Failed: 0x%X\n"), GetLastError());
}
else {
UCHAR i;
TCHAR revision[16] = { 0 };
firmwareInfo = (PSTORAGE_FIRMWARE_INFO)((PUCHAR)srbControl + firmwareRequest->DataBufferOffset);
_tprintf(_T("\t ----Firmware Information----\n"));
_tprintf(_T("\t Support upgrade command: %s\n"), firmwareInfo->UpgradeSupport ? _T("Yes") : _T("No"));
_tprintf(_T("\t Slot Count: %d\n"), firmwareInfo->SlotCount);
_tprintf(_T("\t FWVersion: ")); std::cout << firmwareInfo->Version << "\n";
_tprintf(_T("\t Current Active Slot: %d\n"), firmwareInfo->ActiveSlot);
if (firmwareInfo->PendingActivateSlot == STORAGE_FIRMWARE_INFO_INVALID_SLOT) {
_tprintf(_T("\t Pending Active Slot: %s\n\n"), _T("No"));
}
else {
_tprintf(_T("\t Pending Active Slot: %d\n\n"), firmwareInfo->PendingActivateSlot);
}
for (i = 0; i < firmwareInfo->SlotCount; i++) {
RtlCopyMemory(revision, &firmwareInfo->Slot[i].Revision.AsUlonglong, 8);
_tprintf(_T("\t\t Slot Number: %d\n"), firmwareInfo->Slot[i].SlotNumber);
_tprintf(_T("\t\t Slot Read Only: %s\n"), firmwareInfo->Slot[i].ReadOnly ? _T("Yes") : _T("No"));
_tprintf(_T("\t\t Revision: %s\n"), revision);
_tprintf(_T("\n"));
}
}
_tprintf(_T("\n"));
}
CloseHandle(handle);
Solution
I figured it out! By setting ONE BUFFER big enough for BOTH IN and OUT operations of the IOCTL_SCSI_MINIPORT as listed below:
And setting the DeviceIoControl Function to use the same buffer for both in and out:
It effectively found only the active slot I specified (0 for the first SSD, 1 for the second SSD)
Code:
PUCHAR Buffer[sizeof(FIRMWARE_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL) + sizeof(STORAGE_FIRMWARE_INFO)];
And setting the DeviceIoControl Function to use the same buffer for both in and out:
Code:
result = DeviceIoControl(hDevice,
IOCTL_SCSI_MINIPORT,
Buffer,
BufferLength,
Buffer,
BufferLength,
&returnedLength,
NULL
);
It effectively found only the active slot I specified (0 for the first SSD, 1 for the second SSD)
ExylonFiber
Well-Known Member
- Joined
- Apr 25, 2020
- Messages
- 26
- Thread Author
-
- #2
Here is the output:
And the error:
And the error:
Last edited by a moderator:
ExylonFiber
Well-Known Member
- Joined
- Apr 25, 2020
- Messages
- 26
- Thread Author
-
- #3
It would seem that the for-loop is not counting slots incrementally and just doing it in a random order. Particularly strange.
ExylonFiber
Well-Known Member
- Joined
- Apr 25, 2020
- Messages
- 26
- Thread Author
-
- #4
I figured it out! By setting ONE BUFFER big enough for BOTH IN and OUT operations of the IOCTL_SCSI_MINIPORT as listed below:
And setting the DeviceIoControl Function to use the same buffer for both in and out:
It effectively found only the active slot I specified (0 for the first SSD, 1 for the second SSD)
Code:
PUCHAR Buffer[sizeof(FIRMWARE_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL) + sizeof(STORAGE_FIRMWARE_INFO)];
And setting the DeviceIoControl Function to use the same buffer for both in and out:
Code:
result = DeviceIoControl(hDevice,
IOCTL_SCSI_MINIPORT,
Buffer,
BufferLength,
Buffer,
BufferLength,
&returnedLength,
NULL
);
It effectively found only the active slot I specified (0 for the first SSD, 1 for the second SSD)