Skip to content
Permalink
Browse files

CrystalDiskInfo 8.1.0 Beta1

- Official support for Realtek RTL9210 support
- Improved ASMedia ASM2362 support
  • Loading branch information...
hiyohiyo committed Apr 12, 2019
1 parent 0f944fa commit b343c85d4731d7a5a90e49c8c0cdeb82c91c351a
Showing with 258 additions and 53 deletions.
  1. +198 −26 AtaSmart.cpp
  2. +6 −0 AtaSmart.h
  3. +6 −5 DiskInfo.rc
  4. +16 −17 DiskInfo.vcxproj
  5. +1 −0 DiskInfoDlg.h
  6. +2 −0 DiskInfoDlgInit.cpp
  7. +23 −0 DiskInfoDlgMenu.cpp
  8. +2 −1 Resource.h
  9. +4 −4 stdafx.h
@@ -38,6 +38,7 @@ static const TCHAR *commandTypeString[] =
_T("sq"), // NVMe Storage Query
_T("nj"), // NVMe JMicron
_T("na"), // NVMe ASMedia
_T("nr"), // NVMe Realtek
};

static const TCHAR *ssdVendorString[] =
@@ -3110,6 +3111,7 @@ BOOL CAtaSmart::AddDiskNVMe(INT physicalDriveId, INT scsiPort, INT scsiTargetId,
|| (commandType == CMD_TYPE_NVME_SAMSUNG && GetSmartAttributeNVMeSamsung951(physicalDriveId, scsiPort, scsiTargetId, &asi))
|| (commandType == CMD_TYPE_NVME_JMICRON && GetSmartAttributeNVMeJMicron(physicalDriveId, scsiPort, scsiTargetId, &asi))
|| (commandType == CMD_TYPE_NVME_ASMEDIA && GetSmartAttributeNVMeASMedia(physicalDriveId, scsiPort, scsiTargetId, &asi))
|| (commandType == CMD_TYPE_NVME_REALTEK && GetSmartAttributeNVMeRealtek(physicalDriveId, scsiPort, scsiTargetId, &asi))
)
{
asi.IsSmartSupported = TRUE;
@@ -4621,6 +4623,18 @@ BOOL CAtaSmart::GetDiskInfo(INT physicalDriveId, INT scsiPort, INT scsiTargetId,
return FALSE;
}
}

if (interfaceType == INTERFACE_TYPE_USB && usbVendorId == USB_VENDOR_REALTEK)
{
if (FlagUsbNVMeRealtek && DoIdentifyDeviceNVMeRealtek(physicalDriveId, scsiPort, scsiTargetId, &identify))
{
debug.Format(_T("DoIdentifyDeviceNVMeRealtek"));
DebugPrint(debug);
debug.Format(_T("AddDiskNVMe - CMD_TYPE_NVME_REALTEK"));
DebugPrint(debug);
return AddDiskNVMe(physicalDriveId, scsiPort, scsiTargetId, scsiBus, scsiTargetId, CMD_TYPE_NVME_REALTEK, &identify);
}
}

// 2009/7/30, 2009/8/21
// IO-DATA HDPS-U https://crystalmark.info/bbs/c-board.cgi?cmd=one;no=2918;id=report#2918
@@ -4737,6 +4751,14 @@ BOOL CAtaSmart::GetDiskInfo(INT physicalDriveId, INT scsiPort, INT scsiTargetId,
DebugPrint(debug);
return AddDiskNVMe(physicalDriveId, scsiPort, scsiTargetId, scsiBus, scsiTargetId, CMD_TYPE_NVME_ASMEDIA, &identify);
}
else if (DoIdentifyDeviceNVMeRealtek(physicalDriveId, scsiPort, scsiTargetId, &identify))
{
debug.Format(_T("DoIdentifyDeviceNVMeRealtek"));
DebugPrint(debug);
debug.Format(_T("AddDiskNVMe - CMD_TYPE_NVME_REALTEK"));
DebugPrint(debug);
return AddDiskNVMe(physicalDriveId, scsiPort, scsiTargetId, scsiBus, scsiTargetId, CMD_TYPE_NVME_REALTEK, &identify);
}
}
else
{
@@ -4766,78 +4788,88 @@ BOOL CAtaSmart::GetDiskInfo(INT physicalDriveId, INT scsiPort, INT scsiTargetId,

return flag;
}
else if(FlagUsbJmicron && DoIdentifyDeviceSat(physicalDriveId, 0xA0, &identify, CMD_TYPE_JMICRON))

if(FlagUsbJmicron && DoIdentifyDeviceSat(physicalDriveId, 0xA0, &identify, CMD_TYPE_JMICRON))
{
DebugPrint(_T("AddDisk - USB11"));
return AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xA0, CMD_TYPE_JMICRON, &identify, siliconImageType, NULL, pnpDeviceId);
if (AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xA0, CMD_TYPE_JMICRON, &identify, siliconImageType, NULL, pnpDeviceId)){return TRUE;}
}
else if(FlagUsbSunplus && DoIdentifyDeviceSat(physicalDriveId, 0xA0, &identify, CMD_TYPE_SUNPLUS))
if(FlagUsbSunplus && DoIdentifyDeviceSat(physicalDriveId, 0xA0, &identify, CMD_TYPE_SUNPLUS))
{
DebugPrint(_T("AddDisk - USB12"));
return AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xA0, CMD_TYPE_SUNPLUS, &identify, siliconImageType, NULL, pnpDeviceId);
if (AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xA0, CMD_TYPE_SUNPLUS, &identify, siliconImageType, NULL, pnpDeviceId)) { return TRUE; }
}
else if(FlagUsbCypress && DoIdentifyDeviceSat(physicalDriveId, 0xA0, &identify, CMD_TYPE_CYPRESS))
if(FlagUsbCypress && DoIdentifyDeviceSat(physicalDriveId, 0xA0, &identify, CMD_TYPE_CYPRESS))
{
DebugPrint(_T("AddDisk - USB13"));
return AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xA0, CMD_TYPE_CYPRESS, &identify, siliconImageType, NULL, pnpDeviceId);
if (AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xA0, CMD_TYPE_CYPRESS, &identify, siliconImageType, NULL, pnpDeviceId)) { return TRUE; }
}
else if(FlagUsbLogitec1 && DoIdentifyDeviceSat(physicalDriveId, 0xA0, &identify, CMD_TYPE_LOGITEC1))
if(FlagUsbLogitec1 && DoIdentifyDeviceSat(physicalDriveId, 0xA0, &identify, CMD_TYPE_LOGITEC1))
{
DebugPrint(_T("AddDisk - USB14"));
return AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xA0, CMD_TYPE_LOGITEC1, &identify, siliconImageType, NULL, pnpDeviceId);
if (AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xA0, CMD_TYPE_LOGITEC1, &identify, siliconImageType, NULL, pnpDeviceId)) { return TRUE; }
}
else if (FlagUsbLogitec2 && DoIdentifyDeviceSat(physicalDriveId, 0xA0, &identify, CMD_TYPE_LOGITEC2))
if (FlagUsbLogitec2 && DoIdentifyDeviceSat(physicalDriveId, 0xA0, &identify, CMD_TYPE_LOGITEC2))
{
DebugPrint(_T("AddDisk - USB14"));
return AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xA0, CMD_TYPE_LOGITEC2, &identify, siliconImageType, NULL, pnpDeviceId);
if (AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xA0, CMD_TYPE_LOGITEC2, &identify, siliconImageType, NULL, pnpDeviceId)) { return TRUE; }
}
else if(FlagUsbSat && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_SAT))
if(FlagUsbSat && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_SAT))
{
DebugPrint(_T("AddDisk - USB15"));
return AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_SAT, &identify, siliconImageType, NULL, pnpDeviceId);
if (AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_SAT, &identify, siliconImageType, NULL, pnpDeviceId)) { return TRUE; }
}
else if(FlagUsbJmicron && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_JMICRON))
if(FlagUsbJmicron && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_JMICRON))
{
DebugPrint(_T("AddDisk - USB16"));
return AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_JMICRON, &identify, siliconImageType, NULL, pnpDeviceId);
if (AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_JMICRON, &identify, siliconImageType, NULL, pnpDeviceId)) { return TRUE; }
}
else if(FlagUsbSunplus && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_SUNPLUS))
if(FlagUsbSunplus && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_SUNPLUS))
{
DebugPrint(_T("AddDisk - USB17"));
return AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_SUNPLUS, &identify, siliconImageType, NULL, pnpDeviceId);
if (AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_SUNPLUS, &identify, siliconImageType, NULL, pnpDeviceId)) { return TRUE; }
}
else if(FlagUsbCypress && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_CYPRESS))
if(FlagUsbCypress && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_CYPRESS))
{
DebugPrint(_T("AddDisk - USB18"));
return AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_CYPRESS, &identify, siliconImageType, NULL, pnpDeviceId);
if (AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_CYPRESS, &identify, siliconImageType, NULL, pnpDeviceId)) { return TRUE; }
}
else if(FlagUsbLogitec1 && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_LOGITEC1))
if(FlagUsbLogitec1 && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_LOGITEC1))
{
DebugPrint(_T("AddDisk - USB19"));
return AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_LOGITEC1, &identify, siliconImageType, NULL, pnpDeviceId);
if (AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_LOGITEC1, &identify, siliconImageType, NULL, pnpDeviceId)) { return TRUE; }
}
else if (FlagUsbLogitec2 && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_LOGITEC2))
if (FlagUsbLogitec2 && DoIdentifyDeviceSat(physicalDriveId, 0xB0, &identify, CMD_TYPE_LOGITEC2))
{
DebugPrint(_T("AddDisk - USB20"));
return AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_LOGITEC2, &identify, siliconImageType, NULL, pnpDeviceId);
if (AddDisk(physicalDriveId, scsiPort, scsiTargetId, scsiBus, 0xB0, CMD_TYPE_LOGITEC2, &identify, siliconImageType, NULL, pnpDeviceId)) { return TRUE; }
}
// USB-NVMe
else if (FlagUsbNVMeJMicron && DoIdentifyDeviceNVMeJMicron(physicalDriveId, scsiPort, scsiTargetId, &identify))
if (FlagUsbNVMeJMicron && DoIdentifyDeviceNVMeJMicron(physicalDriveId, scsiPort, scsiTargetId, &identify))
{
debug.Format(_T("DoIdentifyDeviceNVMeJMicron"));
DebugPrint(debug);
debug.Format(_T("AddDiskNVMe - CMD_TYPE_NVME_JMICRON"));
DebugPrint(debug);
return AddDiskNVMe(physicalDriveId, scsiPort, scsiTargetId, scsiBus, scsiTargetId, CMD_TYPE_NVME_JMICRON, &identify);
if (AddDiskNVMe(physicalDriveId, scsiPort, scsiTargetId, scsiBus, scsiTargetId, CMD_TYPE_NVME_JMICRON, &identify)) { return TRUE; }
}
// USB-NVMe
else if (FlagUsbNVMeASMedia && DoIdentifyDeviceNVMeASMedia(physicalDriveId, scsiPort, scsiTargetId, &identify))
if (FlagUsbNVMeASMedia && DoIdentifyDeviceNVMeASMedia(physicalDriveId, scsiPort, scsiTargetId, &identify))
{
debug.Format(_T("DoIdentifyDeviceNVMeASMedia"));
DebugPrint(debug);
debug.Format(_T("AddDiskNVMe - CMD_TYPE_NVME_ASMEDIA"));
DebugPrint(debug);
return AddDiskNVMe(physicalDriveId, scsiPort, scsiTargetId, scsiBus, scsiTargetId, CMD_TYPE_NVME_ASMEDIA, &identify);
if (AddDiskNVMe(physicalDriveId, scsiPort, scsiTargetId, scsiBus, scsiTargetId, CMD_TYPE_NVME_ASMEDIA, &identify)) { return TRUE; }
}
// USB-NVMe
if (FlagUsbNVMeRealtek && DoIdentifyDeviceNVMeRealtek(physicalDriveId, scsiPort, scsiTargetId, &identify))
{
debug.Format(_T("DoIdentifyDeviceNVMeRealtek"));
DebugPrint(debug);
debug.Format(_T("AddDiskNVMe - CMD_TYPE_NVME_REALTEK"));
DebugPrint(debug);
if (AddDiskNVMe(physicalDriveId, scsiPort, scsiTargetId, scsiBus, scsiTargetId, CMD_TYPE_NVME_REALTEK, &identify)) { return TRUE; }
}
}
}
@@ -5552,6 +5584,146 @@ BOOL CAtaSmart::GetSmartAttributeNVMeASMedia(INT physicalDriveId, INT scsiPort,
return TRUE;
}

/*---------------------------------------------------------------------------*/
// NVMe Realtek
/*---------------------------------------------------------------------------*/
BOOL CAtaSmart::DoIdentifyDeviceNVMeRealtek(INT physicalDriveId, INT scsiPort, INT scsiTargetId, IDENTIFY_DEVICE* data)
{
BOOL bRet;
HANDLE hIoCtrl;
DWORD dwReturned;
DWORD length;

SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;

if (data == NULL)
{
return FALSE;
}

::ZeroMemory(data, sizeof(IDENTIFY_DEVICE));

hIoCtrl = GetIoCtrlHandle(physicalDriveId);

if (hIoCtrl == INVALID_HANDLE_VALUE)
{
return FALSE;
}

::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 = 16;
sptwb.Spt.SenseInfoLength = 32;
sptwb.Spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.Spt.DataTransferLength = 4096;
sptwb.Spt.TimeOutValue = 2;
sptwb.Spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf);
sptwb.Spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseBuf);

sptwb.Spt.Cdb[0] = 0xE4; // NVME READ
sptwb.Spt.Cdb[1] = BYTE(4096);
sptwb.Spt.Cdb[2] = BYTE(4096 >> 8);
sptwb.Spt.Cdb[3] = 0x06; // IDENTIFY
sptwb.Spt.Cdb[4] = 0x01;

length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf) + sptwb.Spt.DataTransferLength;

bRet = ::DeviceIoControl(hIoCtrl, IOCTL_SCSI_PASS_THROUGH,
&sptwb, length,
&sptwb, length, &dwReturned, NULL);

if (bRet == FALSE)
{
::CloseHandle(hIoCtrl);
return FALSE;
}

DWORD count = 0;
for (int i = 0; i < 512; i++)
{
count += sptwb.DataBuf[i];
}
if (count == 0)
{
::CloseHandle(hIoCtrl);
return FALSE;
}

memcpy_s(data, sizeof(IDENTIFY_DEVICE), sptwb.DataBuf, sizeof(IDENTIFY_DEVICE));

::CloseHandle(hIoCtrl);

return TRUE;
}

BOOL CAtaSmart::GetSmartAttributeNVMeRealtek(INT physicalDriveId, INT scsiPort, INT scsiTargetId, ATA_SMART_INFO* asi)
{
BOOL bRet;
HANDLE hIoCtrl;
DWORD dwReturned;
DWORD length;

SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;

DebugPrint(_T("GetSmartAttributeNVMeRealtek"));

hIoCtrl = GetIoCtrlHandle(physicalDriveId);

if (hIoCtrl == INVALID_HANDLE_VALUE)
{
return FALSE;
}

::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 = 16;
sptwb.Spt.SenseInfoLength = 32;
sptwb.Spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.Spt.DataTransferLength = 512;
sptwb.Spt.TimeOutValue = 2;
sptwb.Spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf);
sptwb.Spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseBuf);

sptwb.Spt.Cdb[0] = 0xE4; // NVME READ
sptwb.Spt.Cdb[1] = BYTE(512);
sptwb.Spt.Cdb[2] = BYTE(512>>8);
sptwb.Spt.Cdb[3] = 0x02; //GetLogPage

length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf) + sptwb.Spt.DataTransferLength;

bRet = ::DeviceIoControl(hIoCtrl, IOCTL_SCSI_PASS_THROUGH,
&sptwb, length,
&sptwb, length, &dwReturned, NULL);

if (bRet == FALSE)
{
::CloseHandle(hIoCtrl);
return FALSE;
}

DWORD count = 0;
for (int i = 0; i < 512; i++)
{
count += sptwb.DataBuf[i];
}
if (count == 0)
{
::CloseHandle(hIoCtrl);
return FALSE;
}

memcpy_s(&(asi->SmartReadData), 512, sptwb.DataBuf, 512);

::CloseHandle(hIoCtrl);

return TRUE;
}

/*---------------------------------------------------------------------------*/
// NVMe SAMSUNG
@@ -108,6 +108,7 @@ class CAtaSmart
CMD_TYPE_NVME_STORAGE_QUERY,
CMD_TYPE_NVME_JMICRON,
CMD_TYPE_NVME_ASMEDIA,
CMD_TYPE_NVME_REALTEK,
CMD_TYPE_DEBUG
};

@@ -160,6 +161,7 @@ class CAtaSmart
USB_VENDOR_CYPRESS = 0x04B4,
USB_VENDOR_OXFORD = 0x0928,
USB_VENDOR_PROLIFIC = 0x067B,
USB_VENDOR_REALTEK = 0x0BDA,
USB_VENDOR_ALL = 0xFFFF,
};

@@ -1505,6 +1507,7 @@ typedef struct _CSMI_SAS_RAID_CONFIG_BUFFER {
BOOL FlagUsbMemory;
BOOL FlagUsbNVMeJMicron;
BOOL FlagUsbNVMeASMedia;
BOOL FlagUsbNVMeRealtek;

DWORD CsmiType;

@@ -1547,6 +1550,9 @@ typedef struct _CSMI_SAS_RAID_CONFIG_BUFFER {

BOOL DoIdentifyDeviceNVMeASMedia(INT physicalDriveId, INT scsiPort, INT scsiTargetId, IDENTIFY_DEVICE* identify);
BOOL GetSmartAttributeNVMeASMedia(INT physicalDriveId, INT scsiPort, INT scsiTargetId, ATA_SMART_INFO* asi);

BOOL DoIdentifyDeviceNVMeRealtek(INT physicalDriveId, INT scsiPort, INT scsiTargetId, IDENTIFY_DEVICE* data);
BOOL GetSmartAttributeNVMeRealtek(INT physicalDriveId, INT scsiPort, INT scsiTargetId, ATA_SMART_INFO* asi);

BOOL DoIdentifyDeviceNVMeSamsung(INT physicalDriveId, INT scsiPort, INT scsiTargetId, IDENTIFY_DEVICE* identify);
BOOL GetSmartAttributeNVMeSamsung(INT physicalDriveId, INT scsiPort, INT scsiTargetId, ATA_SMART_INFO* asi);
@@ -461,8 +461,8 @@ END
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 8.0.0,2018
PRODUCTVERSION 8.0.0,2018
FILEVERSION 8.1.0,2019
PRODUCTVERSION 8.1.0,2019
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -479,9 +479,9 @@ BEGIN
BEGIN
VALUE "Comments", "https://crystalmark.info/, The MIT License."
VALUE "CompanyName", "Crystal Dew World"
VALUE "FileVersion", "8.0.0.2018"
VALUE "LegalCopyright", "(C) 2008-2018 hiyohiyo"
VALUE "ProductVersion", "8.0.0.2018"
VALUE "FileVersion", "8.1.0.2019"
VALUE "LegalCopyright", "(C) 2008-2019 hiyohiyo"
VALUE "ProductVersion", "8.1.0.2019"
VALUE "ProductName", "CrystalDiskInfo"
VALUE "FileDescription", "CrystalDiskInfo"
VALUE "OriginalFilename", "DiskInfo.exe"
@@ -699,6 +699,7 @@ BEGIN
MENUITEM "USB Memory (SAT)", ID_USB_MEMORY
MENUITEM "SCSI_NVME_TRANSLATION (JMicron)", ID_USB_NVME_JMICRON
MENUITEM "SCSI_NVME_TRANSLATION (ASMedia)", ID_USB_NVME_ASMEDIA
MENUITEM "SCSI_NVME_TRANSLATION (Realtek)", ID_USB_NVME_REALTEK
MENUITEM SEPARATOR
MENUITEM "Enable All", ID_USB_ENABLE_ALL
MENUITEM "Disable All", ID_USB_DISABLE_ALL

0 comments on commit b343c85

Please sign in to comment.
You can’t perform that action at this time.