unit MBM5Shared;

interface

uses
  Windows, Classes, SysUtils, Variants, Registry;

type
  TNewBusType     = (btISA, btSMBus,btVIA686ABus, btDirectIO);
  TNewSMBType     = (smtSMBIntel, smtSMBAMD, smtSMBALi, smtSMBNForce, smtSMBSIS);
  TNewSensorType  = (stUnknown, stTemperature, stVoltage, stFan, stMhz, stPercentage);

  TNewSharedIndex = record
    iType : TNewSensorType;                          // type of sensor
    Count : integer;                              // number of sensor for that type
  end;

  TNewSharedSensor = record
    ssType    : TNewSensorType;                      // type of sensor
    ssName    : array [0..11] of AnsiChar;        // name of sensor
    sspadding1: array [0..2] of Char;             // padding of 3 byte
    ssCurrent : Double;                           // current value
    ssLow     : Double;                           // lowest readout
    ssHigh    : Double;                           // highest readout
    ssCount   : LongInt;                          // total number of readout
    sspadding2: array [0..3] of Char;             // padding of 4 byte
    ssTotal   : Extended;                         // total amout of all readouts
    sspadding3: array [0..5] of Char;             // padding of 6 byte
    ssAlarm1  : Double;                           // temp & fan: high alarm; voltage: % off;
    ssAlarm2  : Double;                           // temp: low alarm
  end;

  TNewSharedInfo = record
    siSMB_Base       : Word;                      // SMBus base address
    siSMB_Type       : TNewBusType;                  // SMBus/Isa bus used to access chip
    siSMB_Code       : TNewSMBType;                  // SMBus sub type, Intel, AMD or ALi
    siSMB_Addr       : Byte;                      // Address of sensor chip on SMBus
    siSMB_Name       : array [0..40] of AnsiChar; // Nice name for SMBus
    siISA_Base       : Word;                      // ISA base address of sensor chip on ISA
    siChipType       : Integer;                   // Chip nr, connects with Chipinfo.ini
    siVoltageSubType : Byte;                      // Subvoltage option selected
  end;

  TNewSharedData =  record
    sdVersion : Double;                           // version number (example: 51090)
    sdIndex   : array [0..9]   of TNewSharedIndex;   // Sensor index
    sdSensor  : array [0..99]  of TNewSharedSensor;  // sensor info
    sdInfo    : TNewSharedInfo;                      // misc. info
    sdStart   : array [0..40]  of AnsiChar;       // start time
    sdCurrent : array [0..40]  of AnsiChar;       // current time
    sdPath    : array [0..255] of AnsiChar;       // MBM path
  end;

  PNewSharedData   = ^TNewSharedData;

  TStartDLL = function : Integer; stdcall;
  TStopDLL  = function : Integer; stdcall;

  Var
   DLLHandle: hwnd;

  Const
   MBMRegPath = '\Software\Alexander van Kaam\MBM 5';
   MBMRegKey = HKEY_CURRENT_USER;
   MBMStarterOK = 1;


function ReadSharedSensor(SensorType: TNewSensorType; SensorIndex: Integer): TNewSharedSensor; overload;
Function ReadSharedSensor(Index: Integer): TNewSharedSensor; overload;
Function NumberOfSensors: Integer;
Function PathToOk(APath: String): String;
Function LoadStarter: Boolean;
Function UnloadStarter: Boolean;


implementation

Function NumberOfSensors: Integer;
  var     myHandle: Integer;
  NewSharedData: PNewSharedData;
begin
  myHandle :=  OpenFileMapping(FILE_MAP_READ, False, '$M$B$M$5$S$D$');
  if myHandle > 0 then begin
    NewSharedData := MapViewOfFile(myHandle, FILE_MAP_READ, 0, 0, 0);
    with NewSharedData^ do begin
      Result := sdIndex[0].Count +
                    sdIndex[1].Count +
                    sdIndex[2].Count +
                    sdIndex[3].Count +
                    sdIndex[4].Count;
    end;
    UnMapViewOfFile(NewSharedData);
    CloseHandle(myHandle);
  end else result := -1;
End;

Function ReadSharedSensor(Index: Integer): TNewSharedSensor;
Var
  NewSharedData   : PNewSharedData;
  myHandle: Integer;
Begin
  myHandle :=  OpenFileMapping(FILE_MAP_READ, False, '$M$B$M$5$S$D$');
  if myHandle > 0 then begin
   NewSharedData := MapViewOfFile(myHandle, FILE_MAP_READ, 0, 0, 0);
   with NewSharedData^ do begin
    Result := sdSensor[Index];
   End;
   UnMapViewOfFile(NewSharedData);
  End;
  CloseHandle(myHandle);
End;

function ReadSharedSensor(SensorType: TNewSensorType; SensorIndex: Integer): TNewSharedSensor;
var
  NewSharedData   : PNewSharedData;
  TempCount, FanCount, VolCount, MhzCount: Integer;
  ReadAt, myHandle: Integer;
begin
  Result.ssType := stUnknown;
  Result.ssCount := -1;
  myHandle :=  OpenFileMapping(FILE_MAP_READ, False, '$M$B$M$5$S$D$');
  if myHandle > 0 then begin
   NewSharedData := MapViewOfFile(myHandle, FILE_MAP_READ, 0, 0, 0);
   TempCount := NewSharedData.sdIndex[0].Count;
   VolCount := NewSharedData.sdIndex[1].Count;
   FanCount := NewSharedData.sdIndex[2].Count;
   MhzCount := NewSharedData.sdIndex[3].Count;

   ReadAt := 0;
   Case SensorType of
    stTemperature: ReadAt := 0;
    stVoltage    : ReadAt := TempCount;
    stFan        : ReadAt := TempCount + VolCount;
    stMhz        : ReadAt := TempCount + VolCount + FanCount;
    stPercentage : ReadAt := TempCount + VolCount + FanCount + MhzCount;
   End;
   ReadAt := ReadAt + SensorIndex;

   with NewSharedData^ do begin
    Result := sdSensor[ReadAt];
   End;

   UnMapViewOfFile(NewSharedData);
  End;
  CloseHandle(myHandle);
end;

Function PathToOk(APath: String): String;
Begin
 If APath = '' Then begin
  Result := APath;
  Exit;
 End;
 If APath[length(APath)] <> '\' Then APath := APath + '\';
 Result := APath;
End;

Function LoadStarter: Boolean;
Var
 CStartDLL: TStartDLL;
 hSInfo       : Integer;
 P: Pointer;
 B: Byte;
 Registry: TRegistry;
 MBMPAth: String;
 ECode: Integer;
Begin
 Result := false;
 // Load MBM location from the registry
 Registry := TRegistry.Create;
 Registry.RootKey := MBMRegKey;
 If Registry.OpenKey(MBMRegPath, False) then
  MBMPath := Registry.ReadString('Location')
 else
 begin
  // MBM not installed - Render this plugin invalid
  Result := False;
  Exit;
 end;
 MBMPath := PathToOk(PathToOk(MBMPath) + 'Misc\');
 Registry.Free;
 // Does the starter
 If not fileexists(MBMPath + 'MBMStarter.dll') Then begin
  // MBM Starter could not be found - Render plugin invalid
  Result := False;
  Exit;
 End;

 DLLHandle:=LoadLibrary(Pchar(MBMPath + 'MBMStarter.dll'));
 if DLLHandle <> 0 then
 begin
  @CStartDLL:=GetProcAddress(DLLHandle, 'Start');
  ECode := CStartDLL;
  If ECode <> MBMStarterOK Then Begin
   // Incorrect startup of DLL Starter - Render plugin Invalid
   Result := False;
   Exit;
  End;
  hSInfo:=OpenFileMapping(FILE_MAP_READ, False, '$M$B$M$5$S$D$');
  if hSInfo = 0 then Exit;
  Result := true;
  P:=MapViewOfFile(hSInfo, FILE_MAP_READ, 0, 0, 0);
  move(p^, b, sizeof(b));
  UnMapViewOfFile(P);
  CloseHandle(hSInfo);
 end;
end;

Function UnloadStarter: Boolean;
Var
 CStopDLL: TStopDLL;
Begin
 if DLLHandle<>0 then begin
  @CStopDLL:=GetProcAddress(DLLHandle, 'Stop');
  CStopDLL;
  FreeLibrary(DLLHandle);
  DLLHandle:=0;
  Result := true;
 End
  else Result := true;
end;

end.
