1
0
SmartArrayControllerTool/src/SmartArrayControllerTool.cpp

291 lines
7.4 KiB
C++

//
// WinAPI
//
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WinSock2.h>
#include <winioctl.h>
#include <ntddscsi.h>
#include <devioctl.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#define _NTSCSI_USER_MODE_
#include <scsi.h>
#include <stdint.h>
#include "ScsiStuff.h"
#pragma comment(lib, "ws2_32")
//
// STL
//
#include <algorithm>
#include <codecvt>
#include <iomanip>
#include <iostream>
#include <locale>
#include <sstream>
#include <vector>
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
//
// Sends a sample request, sniffed from the official HP Array Configuration Utility
//
void SendScsiMiniportRequest(HANDLE handle, PUCHAR Buffer, ULONG BufferLength)
{
PSRB_IO_CONTROL pIoControl = (PSRB_IO_CONTROL)&Buffer[0];
std::wcout << L"[I] - HeaderLength: " << std::dec << pIoControl->HeaderLength << std::endl;
std::wcout << L"[I] - Signature: " << converter.from_bytes((const char*)pIoControl->Signature) << std::endl;
std::wcout << L"[I] - Timeout: " << std::dec << pIoControl->Timeout << std::endl;
std::wcout << L"[I] - ControlCode: " << std::hex << pIoControl->ControlCode << std::endl;
std::wcout << L"[I] - ReturnCode: " << std::dec << pIoControl->ReturnCode << std::endl;
std::wcout << L"[I] - Length: " << std::dec << pIoControl->Length << std::endl;
std::wcout << std::endl;
DWORD bytesReturned = 0;
BOOL ret = DeviceIoControl(
handle,
IOCTL_SCSI_MINIPORT,
Buffer,
BufferLength,
Buffer,
BufferLength,
&bytesReturned,
nullptr
);
if (ret)
{
std::wcout << L"Request succeeded" << std::endl;
std::wcout << std::endl;
std::wcout << L"[O] - HeaderLength: " << std::dec << pIoControl->HeaderLength << std::endl;
std::wcout << L"[O] - Signature: " << converter.from_bytes((const char*)pIoControl->Signature) << std::endl;
std::wcout << L"[O] - Timeout: " << std::dec << pIoControl->Timeout << std::endl;
std::wcout << L"[O] - ControlCode: " << std::hex << pIoControl->ControlCode << std::endl;
std::wcout << L"[O] - ReturnCode: " << std::dec << pIoControl->ReturnCode << std::endl;
std::wcout << L"[O] - Length: " << std::dec << pIoControl->Length << std::endl;
std::wcout << std::endl;
//
// Skips sizeof(SRB_IO_CONTROL) and only dumps the data buffer afterwards
//
const std::vector<char> buffer((PUCHAR)Buffer + pIoControl->HeaderLength, (PUCHAR)Buffer + pIoControl->HeaderLength + pIoControl->Length);
std::wostringstream ss;
ss << std::hex << std::uppercase << std::setfill(L'0');
std::for_each(buffer.cbegin(), buffer.cend(), [&](int c) { ss << std::setw(2) << (unsigned char)c << L" "; });
const std::wstring hexString = ss.str();
std::wcout << L"Result buffer: " << hexString << std::endl;
std::wcout << std::endl;
}
else
{
std::wcerr << L"Failed to send request, error: 0x" << std::hex << GetLastError() << std::endl;
}
}
int wmain(int argc, wchar_t* argv[])
{
if (argc < 2)
{
std::wcerr << L"Please specify device index" << std::endl;
return -1;
}
const std::wstring deviceName = std::wstring(L"\\\\.\\Scsi").append(argv[1]).append(L":");
const HANDLE handle = CreateFile(
deviceName.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr
);
const DWORD error = GetLastError();
if (handle == INVALID_HANDLE_VALUE)
{
std::wcerr << L"Failed to open device " << deviceName << ", error: 0x" << std::hex << error << std::endl;
return -1;
}
std::wcout << L"Successfully opened device " << deviceName << std::endl;
ULONG length = 0, returned = 0;
SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
BYTE cdb[] = { 0x12, 0x00, 0x00, 0x00, 0xFF, 0x00 }; // SCSI Inquiry CDB
ZeroMemory(&sptwb, sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.spt.PathId = 0;
sptwb.spt.TargetId = 0;
sptwb.spt.Lun = 0;
sptwb.spt.CdbLength = sizeof(cdb);
sptwb.spt.SenseInfoLength = SPT_SENSE_LENGTH;
sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.spt.DataTransferLength = SPTWB_DATA_LENGTH;
sptwb.spt.TimeOutValue = 120;
sptwb.spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf);
sptwb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf);
memcpy(sptwb.spt.Cdb, cdb, sizeof(cdb));
//sptwb.spt.Cdb[0] = 0x26; // SCSIOP_READ
//sptwb.spt.Cdb[6] = 0x11;
//
//const unsigned short reqSize = htons(sizeof(id_ctlr));
//memcpy(&sptwb.spt.Cdb[7], &reqSize, 2);
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf) + sptwb.spt.DataTransferLength;
std::wcout << std::dec
<< L"Total struct size: " << sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS)
<< L", Calculated length: " << length
<< L", Header length: " << sptwb.spt.Length
<< std::endl;
BOOL ret = DeviceIoControl(
handle,
IOCTL_SCSI_PASS_THROUGH,
&sptwb,
sizeof(SCSI_PASS_THROUGH) + sptwb.spt.SenseInfoLength,
&sptwb,
length,
&returned,
NULL
);
if (ret)
{
std::wcout << L"Request succeeded (bytes returned: " << returned << L")" << std::endl;
std::wcout << std::endl;
const std::vector<char> buffer(sptwb.ucDataBuf, sptwb.ucDataBuf + length);
std::wostringstream ss;
ss << std::hex << std::uppercase << std::setfill(L'0');
std::for_each(buffer.cbegin(), buffer.cend(), [&](int c) { ss << std::setw(2) << (unsigned char)c << L" "; });
const std::wstring hexString = ss.str();
std::wcout << L"Result buffer: " << hexString << std::endl;
std::wcout << std::endl;
}
else
{
const DWORD error = GetLastError();
std::wstring errorCode = L"Unknown";
switch (error)
{
case ERROR_IO_DEVICE:
errorCode = L"ERROR_IO_DEVICE";
break;
case ERROR_INVALID_PARAMETER:
errorCode = L"ERROR_INVALID_PARAMETER";
break;
default:
std::wcerr << L"GetLastError(): " << std::hex << GetLastError() << std::endl;
break;
}
std::wcerr << L"Failed to send request, error: " << errorCode << std::endl;
}
#ifdef ACU_REPLAY
UCHAR request01[] =
{
#include "request01.bin"
};
UCHAR request02[] =
{
#include "request02.bin"
};
UCHAR request03[] =
{
#include "request03.bin"
};
UCHAR request04[] =
{
#include "request04.bin"
};
UCHAR request05[] =
{
#include "request05.bin"
};
UCHAR request06[] =
{
#include "request06.bin"
};
UCHAR request07[] =
{
#include "request07.bin"
};
UCHAR request08[] =
{
#include "request08.bin"
};
UCHAR request09[] =
{
#include "request09.bin"
};
UCHAR request10[] =
{
#include "request10.bin"
};
UCHAR request11[] =
{
#include "request11.bin"
};
UCHAR request12[] =
{
#include "request12.bin"
};
UCHAR request13[] =
{
#include "request13.bin"
};
SendScsiMiniportRequest(handle, request01, ARRAYSIZE(request01));
SendScsiMiniportRequest(handle, request02, ARRAYSIZE(request02));
SendScsiMiniportRequest(handle, request03, ARRAYSIZE(request03));
SendScsiMiniportRequest(handle, request04, ARRAYSIZE(request04));
SendScsiMiniportRequest(handle, request05, ARRAYSIZE(request05));
SendScsiMiniportRequest(handle, request06, ARRAYSIZE(request06));
SendScsiMiniportRequest(handle, request07, ARRAYSIZE(request07));
SendScsiMiniportRequest(handle, request08, ARRAYSIZE(request08));
SendScsiMiniportRequest(handle, request09, ARRAYSIZE(request09));
SendScsiMiniportRequest(handle, request10, ARRAYSIZE(request10));
SendScsiMiniportRequest(handle, request11, ARRAYSIZE(request11));
SendScsiMiniportRequest(handle, request12, ARRAYSIZE(request12));
SendScsiMiniportRequest(handle, request13, ARRAYSIZE(request13));
#endif
CloseHandle(handle);
}