Код, конечно, не радует. Сочетание ошибок, дурных манер и плохого английского.
- Код: Выделить всё
If IsSSDDrive(sDrive, False) = False Then
MsgBox "Drive " & Chr(34) & sDrive & Chr(34) & " is HDD Disk."
Else
MsgBox "Drive " & Chr(34) & sDrive & Chr(34) & " is SSD Disk."
End If
Можно было бы ужать до
MsgBox "Drive """ & sDrive & """ is " & IIf(IsSSDDrive(sDrive), "SSD", "HDD") & " Disk."_________________________
- Код: Выделить всё
'Is handle is not created exit function
If lHandle = 0 Then
MsgBox "Error with creating disk handle (WinAPI: CreateFile function ): #" & Err.LastDllError
Exit Function
End If
Вот это очень плохой блок. Во-первых, если
CreateFile сбойнет, она вернёт
INVALID_HANDLE_VALUE, а эта константа численно равна
-1&, а не нулю. Так что же в этом месте код пойдёт исполняться дальше, вместо того, чтобы указать на место возникновения проблемы.
Во-вторых, комментарий очень мутный. Тут видимо должно было быть
If вместо
Is, но даже так это звучит неважно. Лучше поменять
is not created на
wasn't created или
has not been created. А ещё лучше — поменять смысл. Привязываться не к факту создания(!) хендла, а к факту сбоя функции.
___________
- Код: Выделить всё
'Create ATA_PASS_THROUGH_EX structure
DiskData.Length = Len(DiskData)
DiskData.AtaFlags = 2 ' ATA_FLAGS_DATA_IN
DiskData.DataTransferLength = 512 'The command returns a 512 byte package of info.
DiskData.TimeOutValue = 3 '10 second timeout.
DiskData.CurrentTaskFile(6) = 236 'the command "IDENTIFY DEVICE"
DiskData.DataBufferOffset = Len(DiskData)
Почему здесь везде стоят просто числа вместо соответствующих констант? Особенно на фоне того, что константа
ATA_FLAGS_DATA_IN объявлена выше, почему тут стоит двойка, а в комментарии даётся имя константы, вместо того, чтобы просто использовать константу?
Не делай так!
_____________________
«Error with» звучит диковато — обычно «Error while» или «Error when».
______________________
Вообще, идея вгонять в эту функцию «c:» или «k:» кажется противоречиво и неправильной с идеологической точки зрения.
Ведь «c:» и «k:» это тома, а деление на SSD/HDD относится к устройствам.
А том не тождественнен устройству.И, вообще, тут всё сложнее, чем кажется.
- Существующая философия, заложенная в код, построена исходя из позиции, что любой том — это либо HDD, либо SSD. А между тем, том может оказаться флешкой, компакт-диском или вообще флоппи-диском.
- Более того, среди «томов» в стиле «X:» могут оказаться объекты, представляющие собой симлинки на объекты, вообще никак не относящиеся к физическим накопителям. Например, так называемые сетевые диски являются симлинками на \Device\LanmanRedirector с постфиксами. А, к примеру, в VirtualBox диски для шар с родительской системы — симлинки на \DeviceVBoxMniRdr (с постфиксом).
- За большинством томов (A:, B:, C: и так далее) стоят какое-то устройство. Но всегда это диск (для которого уместно деление на HDD или SDD), и не всегда это физическое устройство — вполне может быть и виртуальное устройство.
- Кроме того, вызовом встроенной в Windows команды subst можно заставить отдельный каталог с какого-то одного тома стать новым отдельным томом.
- Сама архитектура Windows такова, что в ней существует дерево устройств, состоящее из узлов-устройств, и с каждым таким узлом ассоциирован определённый драйвер. И если пройтись по ветви в таком дереве от вершины к корню и посмотреть на драйверы, то цепочка из драйверов образовывает так называемый стек драйверов (driver stack) для устройства.
Диски (как и всё остальное) подчиняется этой же схемой, поэтому сам накопитель представлен в дереве устройств отдельный объектом-устройством (олицетворяющем накопитель), а тома (существующие на накопителе) — это уже дочерние объекты-устройства в дереве.
В объектом, олицетворяющих физические накопители — свой драйвер.
А у объектов, олицетворяющих тома — совершенно другой.
Когда ты вызываешь DeviceIoControl, то ты по сути шлёшь IRP соответствующему объекту-устройству в дереве, а обрабатывать этот IRP (с кодом типа IRP_MJ_DEVICE_CONTROL) будет Dispatch-процедура драйвера.
И в том случае, когда ты шлёшь этот IRP объекту-тому, обрабатывать этот IRP придётся драйверу тома (файловой системы), а не драйверу диску. С какой вообще стати драйвер тома отвечает на IRP, суть которого в выполнении ATA-команды, ведь на уровне работы с томами и ФС никому нет дела до физического оборудования? По идее, корректно реагировать на этот IRP должен только объект-диск, а не объект-том, так почему же текущий код работает?
Работает он по той причине, что драйвер устройства-тома перенаправляет этот IRP по стеку вниз, и IRP переадресовывается нижележащему (в дереве) объекту — устройству-диску, а уже его драйвер знает, как обработать этот запрос.
Но в принципе существует вероятность, что драйвер тома не будет пересылать запрос (IRP) нижележащему драйверу, а обработает его сам как неизвестный непредполагаемый.
Вывод: чем слать IRP к устройству-тому (например в адрес объекта \\.\c:, который является симлинком на \Device\HarddiskVolume1), лучше слать его устройству-диску.
В твоём случае это означает, что вместо \\.\c:, \\.\d:, \\.\e: надо передавать \\.\PhysicalDrive0, \\.\PhysicalDrive1 и т.п. в CreateFile.
То есть, с учётом вышесказанного, если тебя интересуют тома D:, N: и Z:, сперва выяснить, что это тома приемлемого типа, что они «дисковые», дальше выяснить имена устройств-дисков, которые скрываются за этими томами, а потом опросить эти диски.
- Всё оказывается ещё сложнее, если вспомнить про NTFS Junction Points и NTFS Hardlinks.
Если взять твои слова
Gasparini писал(а):Необходимо, чтобы оно по разному себя вело на SSD и HDD диске, с целью снижения износа SSD диска от частых перезаписей.
то получается, что допустим твой софт пишет лог или какую-то иную запись в папку, скажем, c:\mysoft\logs\2017\.
Ты урезаешь этот путь до тома «c:». Допустим, ты определишь, что этот том относится к физическому диску \\?\PhysicalDrive6, который является HDD. Однако может оказать, что папка c:\mysoft\log лежит не на этом HDD, а на другом, который, возможно, SSD. Этот другой диск может иметь сколько-то томов, а сами эти тома могут вообще не иметь никакой собственной буквы. И не только отдельная директория, но и отдельный файл, который с виду хранится на одном томе, может в реальности храниться на другом.
Взгляд на ту же ситуацию с другой стороны: в компьютере может быть установлена куча HDD и SDD, и при этом будет только том «c:», а все остальные диски и их тома будут смонтированы в иерархию ФС тома «C:», то есть примерно так же, как это обстоит в unix-подобных ОС, где букв дисков нет вообще. Без всяких там RAID-ов, чисто средствами NT.
Выводы, если кратко:
- Лучше работать с дисками, а не томами.
- Не за всякой буквенным томом скрывается хард.
- Иногда буквенный том — это всего-лишь отдельный каталог локального (результат subst) или удалённого (сетевой диск) хранилища.
- В иерархии одного тома могут попасться файлы и папки, живущие на другом томе того же самого или вообще совершенно другого диска.
- Могут быть отдельные тома (и значит целые диски, где все тома такие), которые не имеют собственной буквы.
- За разными буквами, олицетворяющими разные тома, может стоять один диск.
- За разными буквами может стоять один и тот же том.
Финальный вывод: работать с дисками, а не томами, идентифицируемыми буквой + помнить, что имея путь к файлу или папке, нельзя судить о томе и диске, на которых размещён этот объект, по первой букве пути.