⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vmqueryimpl.pas

📁 《参透Delphi Kylix》通过131个事例
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit VMQueryImpl;

interface

uses
  Windows, SysUtils, Classes, Dialogs;

const
  Delimiter = '|'; { Separate every part of the information string }

type
  // Callback function of VirtualMemoryWalk function which outputs Buffer in specific window or component.
  // Buffer format:
  // <BaseAddress(Hex)>|<(Region/Block)Pages(4KB)>|<BlocksCount>|<(Region/Block)State(Commit/Free/Reserve)>|<(Region/Block)Type(Private/Image/Mapped)>|<PageAttributes(Read/Write/Execute/etc.)>|<Description>#0#0
  TVirtualMemoryWalkerCallback = procedure (Buffer: PChar; BufferSize: DWORD); stdcall;

  // Virtual memory information record, which extends the TMemoryBasicInformation record defined in Windows unit.
  PVirtualMemoryInformation = ^TVirtualMemoryInformation;
  TVirtualMemoryInformation = packed record
    // Region Information
    { Pointer to the base address of the region of pages. }
    RegionBaseAddress: Pointer;
    { Pointer to the base address of a range of pages allocated by the VirtualAlloc function. }
    { The page pointed to by the BaseAddress member is contained within this allocation range. }
    RegionAllocationBase: Pointer;
    { Specifies the access protection given when the region was initially allocated. }
    { This member can be one of the following values, along with PAGE_GUARD and PAGE_NOCACHE. }
    { PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY, PAGE_EXECUTE, PAGE_EXECUTE_READ, }
    { PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY, PAGE_GUARD, PAGE_NOACCESS, or PAGE_NOCACHE }
    RegionAllocationProtect: DWORD;
    { Specifies the size, in bytes, of the region beginning at the base address }
    { in which all pages have identical attributes. }
    RegionSize: DWORD;
    { Specifies the state of the pages in the region. One of the following states is indicated. }
    { MEM_COMMIT, MEM_FREE, or MEM_RESERVE }
    RegionState: DWORD;
    { Specifies the access protection of the pages in the region. }
    { One of the values listed for the AllocationProtect member is specified. }
    RegionProtect: DWORD;
    { Specifies the type of pages in the region. The following types are defined. }
    { MEM_IMAGE, MEM_MAPPED, or MEM_PRIVATE }
    RegionType: DWORD;
    // Block Information
    { Pointer to the base address of the block of the region of pages. }
    BlockBaseAddress: Pointer;
    { Specifies the number of blocks in the region of pages. }
    BlocksCount: DWORD;
    { Specifies the number of blocks with PAGE_GUARD protect flag in the region of pages. }
    BlocksCountWithPageGuard: DWORD;
    { Specifies the size, in bytes, of the block beginning at the base address }
    { in which all pages have identical attributes. }
    BlockSize: DWORD;
    { Specifies the access protection of the pages in the block. }
    { One of the values listed for the AllocationProtect member is specified. }
    BlockProtect: DWORD;
    { Specifies the state of the pages in the block. One of the following states is indicated. }
    { MEM_COMMIT, MEM_FREE, or MEM_RESERVE }
    BlockState: DWORD;
    { Specifies the type of pages in the block. The following types are defined. }
    { MEM_IMAGE, MEM_MAPPED, or MEM_PRIVATE }
    BlockType: DWORD;
  end;

//var
//  PageSize: DWORD = 0;
//  AllocationGranularity: DWORD = 0;

// Get the page size of memory under specific CPU architecture
function GetPageSize(): DWORD; stdcall;
// Get the allocation granularity of memory under specific CPU architecture
function GetAllocationGranularity(): DWORD; stdcall;

// Convert a TVirtualMemoryInformation record to a null-terminated string
procedure GetMemoryInformation(
  VMI: TVirtualMemoryInformation; { Information buffer }
  var Buffer: PChar; var BufferSize: DWORD; { Converted string information buffer and its size }
  Expanded: Boolean { If True, show expanded block information, otherwise just show region information }
); stdcall;

// Virtual memory query function
// If succeed, the return value is True, otherwise False.
function VirtualMemoryQuery(
  Address: Pointer; { Base address of the block }
  PVMI: PVirtualMemoryInformation; { Information buffer }
  Length: DWORD { Size of the information buffer }
): BOOL; stdcall;

// Virtual memory walk function
// Iterate in the process space to get information of every region and its every block.
// If succeed, the return value is True, otherwise False.
function VirtualMemoryWalk(
  VirtualMemoryWalker: TVirtualMemoryWalkerCallback; { Callback function of VirtualMemoryQuery }
  Detailed: Boolean = True { If True, show detailed every block info of every region; otherwise show only region info }
): BOOL; stdcall;

function VMWalk(Detailed: Boolean = True): BOOL; stdcall;

implementation

uses
  JuSectionObjs;

const
  SReturnedInfoMemMapping = 'JuMemMapping.ReturnedInfo';

type
  PReturnedInfo = ^TReturnedInfo;
  TReturnedInfo = record
    Size: Cardinal;
    Data: array [0..64 * 1024 - 5] of Char;
  end;

function GetAllocationGranularity(): DWORD; stdcall;
var
  SI: TSystemInfo;
begin
  GetSystemInfo(SI);
  Result := SI.dwAllocationGranularity;
end;

function GetPageSize(): DWORD; stdcall;
var
  SI: TSystemInfo;
begin
  GetSystemInfo(SI);
  Result := SI.dwPageSize;
end;

procedure GetMemoryInformation(VMI: TVirtualMemoryInformation; var Buffer: PChar; var BufferSize: DWORD; Expanded: Boolean); stdcall;
var
  LInfoStr: string;
  LBuffer: PChar;
  LBufferSize: DWORD;

  function GetRegionInformation(): string;
  var
    L1, L2, L3, L4: string;
    L5: PChar;
  begin
    L1 := Format('%p', [VMI.RegionBaseAddress]);
    L1 := L1 + Delimiter + Format('%d', [VMI.RegionSize div GetPageSize()]);
    L1 := L1 + Delimiter + Format('%d', [VMI.BlocksCount]);
    case VMI.RegionState of
      MEM_COMMIT: L2 := 'Commit';
      MEM_FREE: L2 := 'Free';
      MEM_RESERVE: L2 := 'Reserve';
    end;
    L1 := L1 + Delimiter + L2;
    case VMI.RegionType of
      MEM_IMAGE: L3 := 'Image';
      MEM_MAPPED: L3 := 'Mapped';
      MEM_PRIVATE: L3 := 'Private';
    end;
    L1 := L1 + Delimiter + L3;
    case VMI.RegionProtect and (not (PAGE_GUARD or PAGE_NOCACHE)) of
      PAGE_READONLY: L4 := 'Read';
      PAGE_READWRITE: L4 := 'Read/Write';
      PAGE_WRITECOPY: L4 := 'Read/Write/Copy-on-write';
      PAGE_EXECUTE: L4 := 'Execute';
      PAGE_EXECUTE_READ: L4 := 'Read/Execute';
      PAGE_EXECUTE_READWRITE: L4 := 'Read/Write/Execute';
      PAGE_EXECUTE_WRITECOPY: L4 := 'Read/Write/Execute/Copy-on-write';
      PAGE_NOACCESS: L4 := '';
    end;
    if (VMI.RegionProtect and PAGE_GUARD) = PAGE_GUARD then
      L4 := L4 + '/Guard';
    if (VMI.RegionProtect and PAGE_NOCACHE) = PAGE_NOCACHE then
      L4 := L4 + '/No-cache';
    L1 := L1 + Delimiter + L4;
    if VMI.RegionAllocationBase <> nil then
    begin
      GetMem(L5, MAX_PATH);
      try
        if GetModuleFileName(HMODULE(VMI.RegionAllocationBase), L5, MAX_PATH) <> 0 then
          L1 := L1 + Delimiter + L5
        else
          L1 := L1 + Delimiter;
      finally
        FreeMem(L5);
      end;
    end
    else
      L1 := L1 + Delimiter;
    Result := L1;
  end;

  function GetBlockInformation(): string;
  var
    L1, L2, L3, L4: string;
  begin
    L1 := Format('      %p', [VMI.BlockBaseAddress]);
    L1 := L1 + Delimiter + Format('%d', [VMI.BlockSize div GetPageSize()]);
    L1 := L1 + Delimiter;
    case VMI.BlockState of
      MEM_COMMIT: L2 := 'Commit';
      MEM_FREE: L2 := 'Free';
      MEM_RESERVE: L2 := 'Reserve';
    end;
    L1 := L1 + Delimiter + L2;
    case VMI.BlockType of
      MEM_IMAGE: L3 := 'Image';
      MEM_MAPPED: L3 := 'Mapped';
      MEM_PRIVATE: L3 := 'Private';
    end;
    L1 := L1 + Delimiter + L3;
    case VMI.BlockProtect and (not (PAGE_GUARD or PAGE_NOCACHE)) of
      PAGE_READONLY: L4 := 'Read';
      PAGE_READWRITE: L4 := 'Read/Write';
      PAGE_WRITECOPY: L4 := 'Read/Write/Copy-on-write';
      PAGE_EXECUTE: L4 := 'Execute';
      PAGE_EXECUTE_READ: L4 := 'Read/Execute';
      PAGE_EXECUTE_READWRITE: L4 := 'Read/Write/Execute';
      PAGE_EXECUTE_WRITECOPY: L4 := 'Read/Write/Execute/Copy-on-write';
      PAGE_NOACCESS: L4 := '';
    end;
    if (VMI.BlockProtect and PAGE_GUARD) = PAGE_GUARD then
      L4 := L4 + '/Guard';
    if (VMI.BlockProtect and PAGE_NOCACHE) = PAGE_NOCACHE then
      L4 := L4 + '/No-cache';
    L1 := L1 + Delimiter + L4 + Delimiter;
    Result := L1;
  end;

begin
  if Expanded then
    LInfoStr := GetBlockInformation()
  else
    LInfoStr := GetRegionInformation();
  LBufferSize := Length(LInfoStr) + SizeOf(Char);// + 1;
  GetMem(LBuffer, LBufferSize);
  FillChar(LBuffer^, LBufferSize, 0);
  StrCopy(LBuffer, PChar(LInfoStr));
  Buffer := LBuffer;
  BufferSize := LBufferSize;
end;

function VirtualMemoryQuery(Address: Pointer; PVMI: PVirtualMemoryInformation; Length: DWORD): BOOL; stdcall;

  procedure DoCommittedMemoryQuery(PVMI: PVirtualMemoryInformation; MBI: TMemoryBasicInformation);
  var
    LRegionAllocationBase: Pointer;
    LBlockAddress: Pointer;
    LSentinal: Boolean;
  begin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -