TOP

{--------------------------------------------------------------------

Author: J.M.Wehlou

Description:
    The memory mapped file used as communication between app
    and perfmon dll.

--------------------------------------------------------------------}

unit MemMappedFile;

interface

uses
  SysUtils,
  Windows;

type
  TMemMappedFile = class
  fsName     : string;
  fhMMF      : THANDLE;
  fPtr       : pointer;
  fuSize     : cardinal;
public
  constructor Create(const sName: string; uSize: cardinal);
  destructor  Destroy; override;
  procedure   WriteDWORD(uOffset: DWORD; uValue: DWORD);
  function    ReadDWORD(uOffset: DWORD): DWORD;
  function    GetPtr(): pointer;
end;


// ------------------------------------------------------------------

implementation


// ==================================================================
{ TMemMappedFile }

constructor TMemMappedFile.Create(const sName: string; uSize: cardinal);
var
  bExisted : boolean;
begin
  fuSize := uSize;
  fhMMF := 0;
  fPtr := nil;

  fhMMF := CreateFileMapping(
    THANDLE($FFFFFFFF), // signals it should be backed by pagefile
    nil,                // security
    PAGE_READWRITE,     // protection
    0,                  // high 32 bits of size
    uSize,              // low 32 bits of size
    PChar(sName)
  );
  if fhMMF = 0 then
    raise Exception.Create('Failed opening memory mapped area: ' +
        SysErrorMessage(GetLastError()));

  // yep, this happens when a real handle is returned; ie it's not an error
  bExisted := (GetLastError() = ERROR_ALREADY_EXISTS);

  fPtr := MapViewOfFile(
    fhMMF,
    FILE_MAP_ALL_ACCESS,
    0,
    0,
    0
  );

  if fPtr = nil then
    raise Exception.Create('Failed to map a view on memory file: ' +
        SysErrorMessage(GetLastError()));

end;

// ------------------------------------------------------------------

destructor TMemMappedFile.Destroy;
begin
  UnmapViewOfFile(fPtr);
  CloseHandle(fhMMF);
  inherited;
end;

// ------------------------------------------------------------------

function TMemMappedFile.GetPtr: pointer;
begin
  Result := fPtr;
end;

// ------------------------------------------------------------------

function TMemMappedFile.ReadDWORD(uOffset: DWORD): DWORD;
var
  ptr : pointer;
begin
  if uOffset <= fuSize - sizeof(DWORD) then begin
    ptr := pointer(integer(fPtr) + uOffset);
    CopyMemory(@Result, ptr, sizeof(DWORD));
  end;
end;

// ------------------------------------------------------------------

procedure TMemMappedFile.WriteDWORD(uOffset, uValue: DWORD);
var
  ptr : pointer;
begin
  if uOffset <= fuSize - sizeof(DWORD) then begin
    ptr := pointer(integer(fPtr) + uOffset);
    CopyMemory(ptr, @uValue, sizeof(DWORD));
  end;
end;

// ------------------------------------------------------------------

end.