1. Особенности использования winapi не совсем по тематике форума. Надо гуглить самому.
Первая попавшаяся ссылка в гугуле
https://stackoverflow.com/questions/48250004/how-to-get-a-serial-number-of-a-windows-disk2. Биндинги к winapi в блэкбоке устаревшие и/или не полные. Всякую экзотику надо самому расковыривать из заголовков для сишки.
Иногда константы в заголовках очень запутано объявляются. Можно на
godbolt побыстрому посмотреть что там на выходе.
Для надёжности лучше использовать компилятор
x86 msvc (32 бит).
Код:
#include <windows.h>
void y(void) {
int x = IOCTL_STORAGE_QUERY_PROPERTY;
}
Код:
push ebp
mov ebp, esp
push ecx
mov DWORD PTR _x$[ebp], 2954240 ; 002d1400H
mov esp, ebp
pop ebp
ret 0
2954240 - интересующее нас число.
3. Пример программы.
Не уверен, правда, серийный номер чего оно выдаёт. Но какой-то выдаёт.
Обращаю внимание что используются структуры переменной размерности, возможно именно поэтому их нету в биндингах.
Код:
MODULE TestDisk;
IMPORT SYSTEM, WinApi, StdLog;
PROCEDURE Do*;
CONST
IOCTL_STORAGE_QUERY_PROPERTY = 2954240;
StorageDeviceProperty = 0;
PropertyStandardQuery = 0;
TYPE
STORAGE_PROPERTY_QUERY = RECORD [untagged]
PropertyID, QueryType: INTEGER;
AdditionalParameters: ARRAY 4 OF BYTE; (*variadic*)
END;
STORAGE_DEVICE_DESCRIPTOR = RECORD [untagged]
Version, Size: INTEGER;
DeviceType, DeviceTypeModifier: BYTE;
RemovableMedia, CommandQueueing: BYTE;
VendorIDOffset, ProductIDOffset, ProductRevisionOffset, SerialNumberOffset: INTEGER;
BusType: INTEGER;
RawPropertiesLength: INTEGER;
RawDeviceProperties: ARRAY 4096 OF BYTE; (*variadic*)
END;
VAR
handle: WinApi.HANDLE;
spq: STORAGE_PROPERTY_QUERY;
buf: STORAGE_DEVICE_DESCRIPTOR;
str: WinApi.PtrSTR;
ok: WinApi.BOOL;
i, n: INTEGER;
BEGIN
handle := WinApi.CreateFileW ("\\.\C:", {}, WinApi.FILE_SHARE_WRITE, NIL, WinApi.OPEN_EXISTING, {}, 0);
IF handle # WinApi.INVALID_HANDLE_VALUE THEN
spq.PropertyID := StorageDeviceProperty;
spq.QueryType := PropertyStandardQuery;
FOR i := 0 TO LEN(spq.AdditionalParameters) - 1 DO (*clear just in case*)
spq.AdditionalParameters[i] := 0;
END;
IF WinApi.DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, SYSTEM.ADR(spq), SIZE(STORAGE_PROPERTY_QUERY), SYSTEM.ADR(buf), SIZE(STORAGE_DEVICE_DESCRIPTOR), n, NIL) = WinApi.TRUE THEN
IF buf.Version >= 40 THEN
IF buf.Size <= SIZE(STORAGE_DEVICE_DESCRIPTOR) THEN
IF buf.SerialNumberOffset > 0 THEN
str := SYSTEM.VAL(WinApi.PtrSTR, SYSTEM.ADR(buf) + buf.SerialNumberOffset)
ELSE str := "<NOT AVAILABLE>"
END;
StdLog.String("Serial: "); StdLog.String(str$); StdLog.Ln
ELSE StdLog.String("buffer too small"); StdLog.Ln
END
ELSE StdLog.String("unsupported version"); StdLog.Ln
END
ELSE StdLog.String("fail to get device properties"); StdLog.Ln
END;
ok := WinApi.CloseHandle(handle)
ELSE StdLog.String("fail to open device"); StdLog.Ln
END
END Do;
END TestDisk.
^Q DevCompiler.CompileAndUnload
^Q TestDisk.Do
PS: Динамические строки и структуры, которые не сохраняются где-то внутри winapi, вполне можно передавать через обычный POINTER. А кучу (heap) процесса лучше не использовать - она используется самим блэкбоксом и однажды может стать плохо и не понятно отчего, по возможности лучше использовать статические объекты на стеке.