Последние записи
- Рандомное слайдшоу
- Событие для произвольной области внутри TImage
- Удаление папки с файлами
- Распечатка файла
- Преобразовать массив байт в вещественное число (single)
- TChromium (CEF3), сохранение изображений
- Как в Delphi XE обнулить таймер?
- Изменить цвет шрифта TextBox на форме
- Ресайз PNG без потери прозрачности
- Вывод на печать графического файла
Интенсив по Python: Работа с API и фреймворками 24-26 ИЮНЯ 2022. Знаете Python, но хотите расширить свои навыки?
Slurm подготовили для вас особенный продукт! Оставить заявку по ссылке - https://slurm.club/3MeqNEk
Online-курс Java с оплатой после трудоустройства. Каждый выпускник получает предложение о работе
И зарплату на 30% выше ожидаемой, подробнее на сайте академии, ссылка - ttps://clck.ru/fCrQw
5th
Сен
WinIO для чтения/записи портов I/O и физической памяти
Posted by obzor under Delphi
Есть подписанный ЭЦП драйвер WinIo 3.0 для доступа к портам и мапинга физической памяти для 32/64-разрадяных Windows. Драйвер с открытым исходным кодом и является весьма популярным.
На Delphi 7 я воспроизвёл код установки драйвера в системе и обращение к нему через DeviceIoControl. Драйвер успешно зарегистрировался в Service Control Manager, запустился через StartService, успешно возвратил хэндл через CreateFile и даже смог считать и писать порты ввода-вывода, как под Windows 11 x64, так и Windows 7 32-bit.
Однако если попытаться замапить память через MapPhysToLin, то драйвер возвращает совсем не то, что нужно. Код мапинга очень простой и ошибки здесь нет:
type
TtagPhysStruct = packed record
dwPhysMemSizeInBytes : Int64; //Number of bytes to map
pvPhysAddress : Int64; //Physical address to be mapped
PhysicalMemoryHandle : Int64; //Handle to a section returned by ZwOpenSection
pvPhysMemLin : Int64; //Pointer to a variable that receives the base address of the view
pvPhysSection : Int64;
end;
function MapPhysToLin(var PhysStruct: TtagPhysStruct) : Int64;
var
dwBytesReturned : DWORD;
begin
if not DeviceIoControl(hDriver,
IOCTL_WINIO_MAPPHYSTOLIN, //IOCTL 0x810
@PhysStruct,
SizeOf(TtagPhysStruct),
@PhysStruct,
SizeOf(TtagPhysStruct),
dwBytesReturned,nil)
then Result:=0
else Result:=PhysStruct.pvPhysMemLin;
Поэтому я решился попробовать замапить память через прилагаемую к драйверу библиотеку WinIo32.dll, которая экспортирует функцию GetPhysLong. Данная функция возвращает значение типа DWORD, записанное по определённому адресу в физической памяти.
var
dllGetPhysLong: function (pbPhysAddr: PByte; out pdwPhysVal: PDWORD): Boolean; stdcall;
dllInitializeWinIo: function : Boolean; stdcall;
procedure TForm1.Button2Click(Sender: TObject);
var
hLibrary: THandle;
hBuffer : PDWORD;
begin
hBuffer:=0;
hLibrary:=LoadLibrary('WinIo32.dll');
if hLibrary > HINSTANCE_ERROR then
begin
@dllInitializeWinIo:=GetProcAddress(hLibrary, 'InitializeWinIo');
@dllGetPhysLong:=GetProcAddress(hLibrary, 'GetPhysLong');
if @dllInitializeWinIo <> nil then
if dllInitializeWinIo then
if @dllGetPhysLong <> nil then
begin
if dllGetPhysLong(Ptr($C0000),hBuffer) then
ShowMessage(IntToHex(DWORD(hBuffer),8))
else ShowMessage('Error '+IntToHex(GetLastError,8));;
end;
FreeLibrary(hLibrary);
end;
end;
В коде выше я считываю 4 байта под адресу 0xC0000 (видеопамять). По этому адресу записано 0хE972AA55, которое успешно и возвращается при нажатии на кнопку. Но юзать DLL-ку мне не хочется. Хотелось бы воспроизвести все функции в своём коде самостоятельно.
Есть подозрение, что в С++ своя особенная упаковка структуры TtagPhysStruct:
#pragma pack(push)
#pragma pack(1)
struct tagPhysStruct
{
DWORD64 dwPhysMemSizeInBytes;
DWORD64 pvPhysAddress;
DWORD64 PhysicalMemoryHandle;
DWORD64 pvPhysMemLin;
DWORD64 pvPhysSection;
};
#pragma pack(pop)
#endif
В общем, если кому-то уже ранее удалось портировать WinIo на Delphi, то я был бы рад любой помощи!
Установил Delphi 11.3 Community Edition, заменил тип Int64 переменных структуры TtagPhysStruct на DWORD64, как в сишном исходнике, и скомпилировал:
type
TtagPhysStruct = packed record
dwPhysMemSizeInBytes : DWORD64; //Number of bytes to map
pvPhysAddress : DWORD64; //Physical address to be mapped
PhysicalMemoryHandle : DWORD64; //Handle to a section returned by ZwOpenSection
pvPhysMemLin : DWORD64; //Pointer to a variable that receives the base address of the view
pvPhysSection : DWORD64;
end;
function MapPhysToLin(var PhysStruct: TtagPhysStruct) : Int64;
var
dwBytesReturned : DWORD;
begin
if not DeviceIoControl(hDriver,
IOCTL_WINIO_MAPPHYSTOLIN, //IOCTL 0x810
@PhysStruct,
SizeOf(TtagPhysStruct),
@PhysStruct,
SizeOf(TtagPhysStruct),
dwBytesReturned,nil)
then Result:=0
else Result:=PhysStruct.pvPhysMemLin;
Результат, увы, тот же, как и с использованием Int64. Вместо PhysStruct в качестве выходного буфера я попробовал подставить статический массив типа Byte размерностью 40 байтов — возвращается такая же белиберда. В общем, не знаю, куда капать дальше.
Вызываю просто:
procedure TForm1.Button3Click(Sender: TObject);
var
PhysStruct : TtagPhysStruct;
ResultQw : Int64;
begin
ZeroMemory(@PhysStruct,SizeOf(PhysStruct));
PhysStruct.dwPhysMemSizeInBytes:=4; //мапинг 4-х байтов физической памяти
PhysStruct.pvPhysAddress:=$C0000; //по адресу 0xC0000 - адрес начала региона Video BIOS
ResultQw:=MapPhysToLin(PhysStruct);
end;
Функция MapPhysToLin отрабатывает нормально, т.е. функция DeviceIoControl даёт успех (True), но выходной буфер PhysStruct типа TtagPhysStruct заполняется неверно. Вот, например, так:
dwPhysMemSizeInBytes = 4
pvPhysAddress = 786432 (0xC0000)
PhysicalMemoryHandle = 508 (0x1FC)
pvPhysMemLin = 26411008 (0x1930000)
pvPhysSection = 3405802376 (0xCB006B88)
Функция GetPhysLong, экспортируемая из родной библиотеки WinIo32.dll (скомпилирована на MS VS2008 SP1), делает то же самое, что я написал в качестве кода для обработчика события кнопки Button3. В случае вызова GetPhysLong из библиотеки буфер PhysStruct заполняется корректно.
Скорее всего, что я не совсем точно перевёл код функции с С++ на Паскаль. Вот, что она собой представляет в библиотеке WinIo32.dll:
PBYTE _stdcall MapPhysToLin(tagPhysStruct &PhysStruct)
{
DWORD dwBytesReturned;
if (!DeviceIoControl(hDriver, IOCTL_WINIO_MAPPHYSTOLIN, &PhysStruct,
sizeof(tagPhysStruct), &PhysStruct, sizeof(tagPhysStruct),
&dwBytesReturned, NULL))
{
return NULL;
}
return (PBYTE)PhysStruct.pvPhysMemLin; //на этой строчке в своём коде я не преобразовываю к типу PBYTE
}
Похожие статьи
Купить рекламу на сайте за 1000 руб
пишите сюда - alarforum@yandex.ru
Да и по любым другим вопросам пишите на почту
пеллетные котлы
Пеллетный котел Emtas
Наши форумы по программированию:
- Форум Web программирование (веб)
- Delphi форумы
- Форумы C (Си)
- Форум .NET Frameworks (точка нет фреймворки)
- Форум Java (джава)
- Форум низкоуровневое программирование
- Форум VBA (вба)
- Форум OpenGL
- Форум DirectX
- Форум CAD проектирование
- Форум по операционным системам
- Форум Software (Софт)
- Форум Hardware (Компьютерное железо)