OberonCore https://forum.oberoncore.ru/ |
|
Как узнать серийный номер диска? https://forum.oberoncore.ru/viewtopic.php?f=23&t=6988 |
Страница 1 из 1 |
Автор: | Александр К [ Суббота, 07 Сентябрь, 2024 06:39 ] |
Заголовок сообщения: | Как узнать серийный номер диска? |
Доброго времени суток. Подскажите, как при помощи WinApi.DeviceIoControl узнать серийный номер диска? Получаю дескриптор устройства Код: VAR hDevice, procHeap3: WinApi.HANDLE; lpFileName: WinApi.PtrWSTR; p3: WinApi.PtrVoid; myType1, myType2: MyType; BEGIN procHeap3 := WinApi.GetProcessHeap(); p3 := WinApi.HeapAlloc (procHeap3, {}, 19* SIZE(CHAR)); SYSTEM.PUT (SYSTEM.ADR (lpFileName), p3); lpFileName[0] := "\"; lpFileName[1] := "\"; lpFileName[2] := "."; lpFileName[3] := "\"; lpFileName[4] := "P"; lpFileName[5] := "h"; lpFileName[6] := "y"; lpFileName[7] := "s"; lpFileName[8] := "i"; lpFileName[9] := "c"; lpFileName[10] := "a"; lpFileName[11] := "l"; lpFileName[12] := "D"; lpFileName[13] := "r"; lpFileName[14] := "i"; lpFileName[15] := "v"; lpFileName[16] := "e"; lpFileName[17] := "0"; lpFileName[18] := 0X; hDevice := WinApi.CreateFileW (lpFileName, {}, WinApi.FILE_SHARE_WRITE, NIL, WinApi.OPEN_EXISTING, {}, 0); IF hDevice # WinApi.INVALID_HANDLE_VALUE THEN ??? ELSE StdLog.String ("Ошибка при получении дескриптора файла") END Вроде не ругается, а как дальше применить WinApi.DeviceIoControl - не знаю, а именно: что указать в коде управления операции (dwIoControlCode) и как работать с lpInBuffer, lpOutBuffer: PtrVoid? |
Автор: | SovietPony [ Суббота, 07 Сентябрь, 2024 15:36 ] |
Заголовок сообщения: | Re: Как узнать серийный номер диска? |
1. Особенности использования winapi не совсем по тематике форума. Надо гуглить самому. Первая попавшаяся ссылка в гугуле https://stackoverflow.com/questions/48250004/how-to-get-a-serial-number-of-a-windows-disk 2. Биндинги к winapi в блэкбоке устаревшие и/или не полные. Всякую экзотику надо самому расковыривать из заголовков для сишки. Иногда константы в заголовках очень запутано объявляются. Можно на godbolt побыстрому посмотреть что там на выходе. Для надёжности лучше использовать компилятор x86 msvc (32 бит). Код: #include <windows.h> void y(void) { int x = IOCTL_STORAGE_QUERY_PROPERTY; } Код: push ebp 2954240 - интересующее нас число.mov ebp, esp push ecx mov DWORD PTR _x$[ebp], 2954240 ; 002d1400H mov esp, ebp pop ebp ret 0 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) процесса лучше не использовать - она используется самим блэкбоксом и однажды может стать плохо и не понятно отчего, по возможности лучше использовать статические объекты на стеке. |
Автор: | Александр К [ Воскресенье, 08 Сентябрь, 2024 05:21 ] |
Заголовок сообщения: | Re: Как узнать серийный номер диска? |
Очень благодарен за ответ. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |