////////////////////////////////////////////////////////////////////////////////
// CM2GenPlugTypes.pas
// -------------------
// This unit contains general plugin system routines for CoolMon 2.
//
// Last Edit: June 19th, 2006
// Certified: NA
//
// This unit is coded in : Delphi 7
//
// Unit is copyright (c) 2003 - 2006, The CoolMon Project
////////////////////////////////////////////////////////////////////////////////
{$D+}
unit CM2GenPlugTypes;

interface

Uses
 CM2PlugInTypes,                                                                // Declares everything general used by both plugin types
 CM2GenInterface,
 comobj,
 Windows,
 SysUtils,
 Registry,
 classes,
 Dialogs,
 Verbose,
 CM2EditorSupportInterface;

Type
 TSensorQuery = Record
  SensorID: cardinal;
  Parameter: PChar;
 End;
 TSensorQueryList = Array of TSensorQuery;
 TSensor = Record                                                               // Part of the sensor list in the CoolMon II core
  ID: Cardinal;                                                                 // ID for the actually sensor
  Name: String;                                                                 // Sensor Name
  SensorStyle: Byte;
 End;
 TSensorList = Class(TObject)                                                   // should be self explaining :)
  private
   fSensorList: Array of TSensor;                                               // The actual list
   function GetCount: Integer;                                                  // Returns the length of the list
   procedure SetSensor(Index: Integer; const Value: TSensor);
   function GetSensor(Index: Integer): TSensor;
  public
   Procedure Add(Sensor: TSensor);                                              // Add a sensor
   Procedure Delete(Index: Integer);                                            // Delete a sensor
   Property Sensor[Index: Integer]: TSensor read GetSensor write SetSensor; Default; // Access a specific sensor in the list
   Property Count: Integer read GetCount;                                       // Return the length of the list
 end;
 TData = Class(TObject)                                                         // Enables us to hold an unlimited number of sensors and various dll/sensor data
 private
 public
  Info: TInfoList;                                                              // should be self explaining :)
  Res: TResultList;                                                                // should be self explaining :)
  Constructor Create;
  Destructor Destroy; override;
 End;
 TGenPlugIn = Class(TObject)
 private
  fName: String;
  fRCV: word;
  fVersion: Word;
  fGuid: TGUID;
  fResult: TResult;
  Procedure InitSensorList;
  Procedure InitInfoList;
 public
  PlugIn: ICM2GenPlug; // Lies here to allow hardcoding for Required and Optional parameter routines
  InfoList: TInfoList;
  SensorList: TSensorList;
  Property Name: String read fName;
  Property Version: Word read fVersion;
  Property RequiredCoreVersion: word read fRCV;
  Property GUID: TGUID read fGuid;
  Property Result: TResult read fResult;
  Constructor Create(GUID: TGUID; ParentHandle: THandle);
  Destructor Destroy; override;
  Procedure Setup;
  Function Poll(Index: Integer; Parameters: String): Boolean;
  Function GetSensorIndex(SensorName: String): Integer;
  Function GetLastErrorMessage: String;
 end;
 PGenPlugIn = ^TGenPlugIn;

 TGenPlugInList = Class(TObject)                                                // A list of TGenPlugIn
 Private
  fGenPlugInList: Array of TGenPlugIn;
  fPWHandle: THandle;                                          // The actual list
  function GetCount: Integer;                                                   // Return the length of the list
  function GetGenPlugIn(Index: Integer): TGenPlugIn;
  procedure SetGenPlugIn(Index: Integer; const Value: TGenPlugIn);              // Update the property index in all GenPlugIn's in the list
 public
  Progress: TPlugInListProgress;
  Constructor Create(ParentWindowHandle: THandle);
  Destructor Destroy; override;
  Function Add(GUID: TGUID): TGenPlugIn; overload;                                           // Add a GenPlugIn to the list
//  Function Add(Filename: String; Var PlugName: String): Boolean; overload;
  Procedure Delete(Index: Integer);                                             // Delete a GenPlugIn from the list
  Property GenPlugIn[Index: Integer]: TGenPlugIn read GetGenPlugIn write SetGenPlugIn; default;
  Function GetPlugInAddr(Index: Integer): PGenPlugIn; overload;
  Function GetPlugInAddr(GUID: TGUID): PGenPlugIn; overload;
  Property Count: Integer read GetCount;                                        // Returns the length the list
  Property ParentWindowHandle: THandle read fPWHandle;
  Function IndexOf(PlugName: String): Integer;
  Procedure UnloadAll;
  Procedure LoadAll;
  Function LoadPlugIn(Name: String): Boolean;
 End;
 PGenPlugInList = ^TGenPlugInList;

 TESGen = Record
  ParameterName: String;
  ValueType: Byte;
  ValueRange: String;
 end;
 TEditorSupportGen = Class(Tobject)
 private
  fList: Array of TESGen;
    fSupportsEditor: Boolean;
    fShowAt: Byte;
    function GET_ESGEN(Index: Integer): TESGen;
    function GET_COUNT: Integer;
 public
  Procedure LoadFrom(PlugIn: TGenPlugIn; SensorIndex: Integer);
  Property SupportsEditor: Boolean read fSupportsEditor;
  Property ShowAt: Byte read fShowAt;
  Property ESGen[Index: Integer]: TESGen read GET_ESGEN; default;
  Function GetByName(Name: String): TESGen;
  Property Count: Integer read GET_COUNT;
 end;

 TGenExList = Class(TObject)
 private
  fList: Array of TExInfoList;
  PlugIn: ICM2GenPlug;
  function GetCount: Integer;
  function GetExInfoList(Index: Integer): TExInfoList;
 public
  Constructor Create(CreateFrom: ICM2GenPlug);
  Destructor Destroy; override;
  Property ExList[Index: Integer]: TExInfoList read GetExInfoList; default;
  Property Count: Integer read GetCount;
 End;

implementation

{ TSensorList }

procedure TSensorList.Add(Sensor: TSensor);
Var
 Index: Integer;
begin
 SetLength(Self.fSensorList, Length(Self.fSensorList) + 1);
 Index := Length(Self.fSensorList) - 1;
 Self.fSensorList[Index] := Sensor;
end;

procedure TSensorList.Delete(Index: Integer);
Var
 I: Integer;
begin
 If (Index < 0) or (Index > Length(fSensorList) - 1) Then
  Raise EOutOfBounds.Create('TSensor List Error - Index out of bounds');
 For I := Index to Length(fSensorList) - 2 do begin
  fSensorList[I] := fSensorList[I + 1];
 End;
 SetLength(fSensorList, Length(fSensorList) - 1);
end;

function TSensorList.GetCount: Integer;
begin
 Result := Length(fSensorList);
end;

function TSensorList.GetSensor(Index: Integer): TSensor;
begin
 Result := fSensorList[Index];
end;

procedure TSensorList.SetSensor(Index: Integer; const Value: TSensor);
begin
 fSensorList[Index] := Value;
end;

{ TData }

constructor TData.Create;
begin
 Self.Info := TInfoList.Create;
 Self.Res := TResultList.Create;
end;

destructor TData.Destroy;
begin
  Self.Info.Free;
  Self.Res.Free;
  inherited;
end;

{ TGenPlugIn }

constructor TGenPlugIn.Create(GUID: TGUID; ParentHandle: THandle);
Var
 Name: PChar;
 V, RCV: Word;
begin
 // Set Plugin active status to false
 If Debug then Form4.Add('TGenPlugIn.Create GUID:' + GUIDToString(GUID), dlplugins);
 fGUID := GUID;
 If Debug then Form4.Add('Create InfoList ... ', dlplugins);
 Self.InfoList := TInfoList.Create;
 If Debug then Form4.Append('done', dlplugins);
 If Debug then Form4.Add('Create SensorList ... ', dlplugins);
 SElf.SensorList := TSensorList.Create;
 If Debug then Form4.Append('done', dlplugins);
 If Debug then Form4.Add('Create ComObject [' + GUIDToString(GUID) + '] (as ICM2GenPlug) ... ', dlplugins);
 PlugIn := CreateComObject (GUID) as ICM2GenPlug;
 If Plugin = nil then
  raise Exception.Create('Plugin is not created');
 If Debug then Form4.Append('done', dlplugins);
 If Debug then Form4.Add('Load Plugin Name ... ', dlplugins);
 If PlugIn.Name(Name) = E_FAIL Then Raise EDLLError.Create('Failed to return plugin name [' + Self.GetLastErrorMessage + ']');
 If Debug then Form4.append(name, dlplugins);
 If Debug then Form4.Add('Load Plugin Version ... ', dlplugins);
 If PlugIn.Version(V) = E_FAIL Then raise EDLLError.Create('Failed to return Version number [' + Self.GetLastErrorMessage + ']');
 If Debug then Form4.append(Inttostr(V), dlplugins);
 If Debug then Form4.Add('Load RequiredCoreVersion ... ', dlplugins);
 If PlugIn.RequiredCoreVersion(RCV) = E_FAIL Then raise EDLLError.Create('Failed to return RequiredCoreVersion Number [' + Self.GetLastErrorMessage + ']');
 If Debug then Form4.append(inttostr(RCV), dlplugins);
 If Debug then Form4.Add('Set parent Handle', dlplugins);
 If PlugIn.SetParentHandle(ParentHandle) = E_FAIL Then raise EDLLError.Create('Failed to set Parent Handle [' + Self.GetLastErrorMessage + ']');
 If Debug then Form4.Add('Run plugins Init block', dlplugins);
 If PlugIn.Init = E_FAIL then raise EDLLError.Create('Failed to run init procedure properly [' + Self.GetLastErrorMessage + ']');
 fNAme := Name;
 fVersion := V;
 fRCV := RCV;
 // Plugin creation went well, now activate it
 InitSensorList;
 InitInfoList;
end;

destructor TGenPlugIn.Destroy;
begin
 If Debug then Form4.Add('Run Plugins Terminate Block', dlplugins);
 If PlugIn.Terminating = E_FAIL then begin
  raise EDLLError.Create('Failed to run terminate procedure properly [' + Self.GetLastErrorMessage + ']');
 End;
 If Debug then Form4.Add('Free InfoList ... ', dlplugins);
 InfoList.Free;
 If Debug then Form4.Append('done', dlplugins);
 If Debug then Form4.Add('Free SensorList ... ', dlplugins);
 SensorList.Free;
 If Debug then Form4.Append('done', dlplugins);
 inherited;
end;

function TGenPlugIn.GetLastErrorMessage: String;
Var
 Msg: PChar;
begin
 If Debug then Form4.Add('GetLastErrorMessage ... ', dlerror);
 If PlugIn.GetLastErrorMsg(Msg) = S_OK Then begin
  Result := Msg;
  Form4.Append(Msg, dlerror);
  exit;
 End;
 Result := 'Could not retrieve last error message';
 If Debug then Form4.Append('Failed', dlerror, mterror);
end;

function TGenPlugIn.GetSensorIndex(SensorName: String): Integer;
Var
 I: Integer;
begin
 REsult := -1;
 For I := 0 to SElf.SensorList.Count - 1 do begin
  If Self.SensorList[I].Name = SensorName Then begin
   Result := I;
   Exit;
  End;
 End;
end;

procedure TGenPlugIn.InitInfoList;
Var
 I, Cnt: Integer;
 S1, S2: PChar;
begin
 If Debug then Form4.Add('Initialize Info List', dlplugins);
 If Debug then Form4.Add('Get PlugIn Info Count', dlplugins);
 If PlugIn.GetInfoCount(Cnt) = E_FAIL Then begin
  Raise EDLLError.Create('Failed to return Info count [' + Self.GetLastErrorMessage + ']');
 end;
 For I := 0 to cnt - 1 do begin
  If Debug then Form4.Add('Get PlugIn Info [#' + IntToStr(I) + ']', dlplugins);
  IF PlugIn.GetInfo(I, S1, S2) = E_FAIL Then begin
   Raise EDLLError.Create('Failed to return Info data [' + Self.GetLastErrorMessage + ']');
  End;
  SElf.InfoList.Add(S1, S2);
 End;
end;

procedure TGenPlugIn.InitSensorList;
Var
 I, Cnt: Integer;
 S1: Pchar;
 Sensor: TSensor;
 SensorStyle: Byte;
 B: Byte;
begin
 If Debug then Form4.Add('Initialize Sensor List', dlplugins);
 If Debug then Form4.Add('Get PlugIn Sensor Count', dlplugins);
 If PlugIn.GetSensorCount(Cnt) = E_FAIL Then Begin
  Raise EDLLError.Create('Failed to return Info count [' + Self.GetLastErrorMessage + ']');
 End;
 For I := 0 to cnt - 1 do begin
  If Debug then Form4.Add('Get PlugIn Sensor [#' + IntToStr(I) + ']', dlplugins);
  IF PlugIn.GetSensorNameOnly(I, S1, B) = E_FAIL Then begin
   Raise EDLLError.Create('Failed to return Info data [' + Self.GetLastErrorMessage + ']');
  End;
  Sensor.ID := I;
  Sensor.Name := S1;
  SensorStyle := ssUnknown;
  Case B of
   0: SensorStyle := ssNumeric;
   1: SensorStyle := ssNonNumeric;
   2: SensorStyle := ssUnknown;
  End;
  Sensor.SensorStyle := SensorStyle;
  Self.SensorList.Add(Sensor);
 End;
end;

Function TGenPlugIn.Poll(Index: Integer; Parameters: String): Boolean;
Var
 N, S: Pchar;
 V: Double;
 B: Byte;
begin
 N := ''; S := ''; V := 0; B := 0;
 If Debug then Form4.Add('GenPlug: ' + Self.fName + '.Poll [Sensor #' + IntToStr(Index) + ' - Parameter: ' +  Parameters + ']', dlplugins);
 If Debug then Form4.Add('Get Sensor ... ', dlplugins);
 If PlugIn.GetSensor(Index, PChar(Parameters), N, B, S, V) = E_FAIL Then begin
  raise EDLLError.Create('Failed to execute poll function');
 End;
 If Debug then Form4.Append('done', dlplugins);
 Result := true;
 Case B of
  0: fResult.SensorStyle := ssNumeric;
  1: fResult.SensorStyle := ssNonNumeric;
  2: fResult.SensorStyle := ssUnknown;
 End;
 { If B = 0 then fResult.IsNumeric := True
  else fResult.IsNumeric := false;}
 fResult.Name := N;
 If fResult.SensorStyle > ssNumeric Then fResult.Str := S;
 fResult.Value := V;
end;

procedure TGenPlugIn.Setup;
Var
 Res: HResult;
begin
 If Debug then Form4.Add('GenPlug: ' + Self.fName + '.Setup ... ', dlplugins);
 Res := PlugIn.Setup;
 Case Res of
  E_FAIL: begin
           raise EDLLError.Create('Failed to run Setup correctly [' + Self.GetLastErrorMessage + ']');
          end;
  E_NOTIMPL: begin
              MessageDlg('Nothing to setup', mtInformation, [mbOK], 0);
             end;
 end;
 If Debug then Form4.Append('done', dlplugins);
end;

{ TGenPlugInList }

function TGenPlugInList.Add(GUID: TGUID): TGenPlugIn;
Var
 Index: Integer;
begin
 If Debug then Form4.Add('GenPlugInList.Add [' + GUIDToString(GUID) + ']', dlcore);
 Setlength(Self.fGenPlugInList, Length(Self.fGenPlugInList) + 1);               // Resize the List by adding one slot
 Index := Length(Self.fGenPlugInList) - 1;                                      // Set Index to be the newly added slots position
 fGenPlugInList[Index] := TGenPlugIn.Create(GUID, ParentWindowHandle);                                    // Add the VISPlugIn to the list
 Result := fGenPlugInList[Index];                                               // Return the Index of the newly added plugin
end;

(*function TGenPlugInList.Add(Filename: String; Var PlugName: String): Boolean;
Var
 GPI: TGenPlugIn;
begin
 Result := False;
 If Not fileexists(Filename) then exit;
 GPI := Self.Add;
 GPI.Filename := Filename;
 Result := True;
 Try
  GPI.ExamineDLL;
 Except
  on EDLLError do begin
   Self.Delete(GPI.Index);
   Result := False;
  End;
  on EVersionError do begin
   Self.Delete(GPI.Index);
   Result := False;
   // Use event manager to set the message event here
  End;
 end;
 PlugName := GPI.Name;
end;
   *)
constructor TGenPlugInList.Create(ParentWindowHandle: THandle);
begin
 Self.fPWHandle := ParentWindowHandle;
end;

procedure TGenPlugInList.Delete(Index: Integer);
begin
 If Debug then Form4.Add('GenPlugInList.Delete [' + IntToStr(Index) + '] ... ', dlcore);
 If (Index < 0) or (Index > Length(Self.fGenPlugInList)-1) then Begin           // verify that index isn't out of bounds
  Self.fGenPlugInList[Index].Free;                                              // Delete the request GenPlugInList
  If (Index < Length(Self.fGenPlugInList) - 1) Then begin                       // If the selected wasn't the last one ...
   Self.fGenPlugInList[Index] := Self.fGenPlugInList[Length(Self.fGenPlugInList)-1]; // Move the last one of the list to the newly open slot
   Self.fGenPlugInList[Length(Self.fGenPlugInList)-1].Free;                     // Delete the last GenPlugIn from the list
  End;
  SetLength(Self.fGenPlugInList, Length(Self.fGenPlugInList) - 1);              // Resize the list
 End;
 If Debug then Form4.append('done', dlcore);
end;

destructor TGenPlugInList.Destroy;
Var
 I: Integer;
begin
  If Length(Self.fGenPlugInList) > 0 Then begin                                 // If there is GenPlugIn in the list ...
   For I := 0 to Length(Self.fGenPlugInList)-1 do begin                         // Free them all
    Self.fGenPlugInList[I].Free;
   End;
   SetLength(Self.fGenPlugInList, 0);                                           // Set new array length to nothing
  End;
  inherited;
end;

function TGenPlugInList.GetCount: Integer;
begin
 Result := Length(Self.fGenPlugInList);
end;

function TGenPlugInList.GetGenPlugIn(Index: Integer): TGenPlugIn;
begin
 Result := fGenPlugInList[Index];
end;

function TGenPlugInList.GetPlugInAddr(Index: Integer): PGenPlugIn;
begin
 Result := nil;
 If (Index < 0) or (Index > SElf.Count - 1) then exit;
 Result := Addr(fGenPlugInList[Index]);
end;

function TGenPlugInList.GetPlugInAddr(GUID: TGUID): PGenPlugIn;
Var
 I: Integer;
 Sel: Integer;
begin
 Sel := -1;
 Result := nil;
 For I := 0 to count - 1 do begin
  If GUIDToString(GenPlugIn[I].GUID) = GUIDToString(GUID) then begin
   Sel := I;
   break;
  end;
 end;
 If Sel > -1 then begin
  Result := GetPlugInAddr(Sel);
 end;
end;

function TGenPlugInList.IndexOf(PlugName: String): Integer;
Var
 I: Integer;
begin
 Result := -1;
 For I := 0 to GetCount - 1 do begin
  if Uppercase(Self.fGenPlugInList[I].Name) = uppercase(PlugName) Then begin
   Result := I;
   exit;                                                                        // Exit loop to speed up execution
  end;
 End;
 If LoadPlugIn(PlugName) then begin
  For I := 0 to GetCount - 1 do begin
   if Uppercase(Self.fGenPlugInList[I].Name) = uppercase(PlugName) Then begin
    Result := I;
    exit;                                                                        // Exit loop to speed up execution
   end;
  End;
 end;
end;

procedure TGenPlugInList.LoadAll;
Var
 Reg: TRegistry;
 I: Integer;
 Strings: TStrings;
 S: String;
 RCV: Word;
 N: String;
 GoForLaunch: Boolean;
begin
 If Debug then Form4.Add('GenPlugInList.LoadAll', dlcore);
 If Self.Count > 0 Then Unloadall;
 If Debug then Form4.Add('Create TRegistry ... ', dlcore);
 Reg := Tregistry.Create;
 If Debug then Form4.Append('done', dlcore);
 If Debug then Form4.Add('Create TStringList ... ', dlcore);
 Strings := TStringlist.Create;
 If Debug then Form4.append('done', dlcore);
 If Debug then Form4.Add('Load Plugin List ... ', dlcore);
 If Reg.OpenKey(CertifiedGENPluginsLocation, False) Then Begin
  Reg.GetKeyNames(Strings);
  For I := 0 to Strings.Count - 1 do begin
    S := Strings[I];
    RCV := 0;
    if Reg.OpenKey(CertifiedGENPluginsLocation + '\' + S, false) then begin
     RCV := Reg.ReadInteger('RequiredCoreVersion');
     N := Reg.ReadString('');
    end;
    If Debug then Form4.Add('Adding ' + N + ' ... ', dlcore);
    If Assigned(Progress) then Progress(N, I - 1, Strings.Count);
    GoForLaunch := True;
    If RCV > CoreVersion Then begin
     GoForLaunch := False;
     messagedlg('Core outdated' + #13#10 + 'General PlugIn: ' + N + #13#10 + 'requires: ' + Inttostr(RCV) + #13#10 + 'current: ' + IntToStr(CoreVersion), mtWarning, [mbOk], 0);
     If Debug then Form4.append('Core outdated', dlplugins);
    end;
    If RCV <= OutDatedCoreVersion Then begin
     GoForLaunch := False;
     messagedlg('PlugIn outdated' + #13#10 + 'General PlugIn: ' + N + #13#10 + 'requires: ' + Inttostr(RCV) + #13#10 + 'current: ' + IntToStr(CoreVersion), mtWarning, [mbOk], 0);
     If Debug then Form4.append('PlugIn outdated', dlplugins);
    end;
    If GoForLaunch then Self.Add(StringToGUID(S));
    If Assigned(Progress) then Progress(N, I, Strings.Count);
  End;
 End
  else
 Begin
  If Debug then Form4.Add('Failure No plugins', dlerror, mtError);
 End;
 If Debug then Form4.Add('Free StringsList ... ', dlcore);
 Strings.Free;
 If Debug then Form4.Append('done', dlcore);
 If Debug then Form4.Add('Free Reg ... ', dlcore);
 REg.Free;
 If Debug then Form4.append('done', dlcore);
end;

Function TGenPlugInList.LoadPlugIn(Name: String): Boolean;
Var
 I: Integer;
 Reg: TRegistry;
 SL: TStrings;
 RCV: Integer;
 GoForLaunch: Boolean;
 N: String;
begin
 Result := False;
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 SL := TStringList.Create;
 If Reg.OpenKey(CertifiedGENPluginsLocation, false) then begin
  Reg.GetKeyNames(SL);
  For I := 0 to SL.Count - 1 do begin
   Reg.OpenKey(CertifiedGENPluginsLocation+ '\' + SL[I], false);
   N := Reg.ReadString('');
   If uppercase(N) = uppercase(Name) then begin
    RCV := Reg.ReadInteger('RequiredCoreVersion');
    GoForLaunch := True;
    If RCV > CoreVersion Then begin
     GoForLaunch := False;
     messagedlg('Core outdated' + #13#10 + 'General PlugIn: ' + N + #13#10 + 'requires: ' + Inttostr(RCV) + #13#10 + 'current: ' + IntToStr(CoreVersion), mtWarning, [mbOk], 0);
    end;
    If RCV <= OutDatedCoreVersion Then begin
     GoForLaunch := False;
     messagedlg('PlugIn outdated' + #13#10 + 'General PlugIn: ' + N + #13#10 + 'requires: ' + Inttostr(RCV) + #13#10 + 'current: ' + IntToStr(CoreVersion), mtWarning, [mbOk], 0);
    end;
    If GoForLaunch then begin
     Self.Add(StringToGUID(SL[I]));
     Result := true;
    end;
   end;
  end;
 end;
 FreeAndNil(SL);
 freeAndNil(Reg);
end;

procedure TGenPlugInList.SetGenPlugIn(Index: Integer;
  const Value: TGenPlugIn);
begin
 fGenPlugInList[Index] := Value;
end;

procedure TGenPlugInList.UnloadAll;
Var
 I: Integer;
begin
 If Debug then Form4.Add('Unload all plugins ... ', dlcore);
 For I := 0 to SElf.Count- 1 do begin
  // fGenPlugInList[I].Free;
  FreeAndNil(fGenPlugInList[I]);
 End;
 SetLength(fGenPlugInList, 0);
 If Debug then form4.append('done', dlcore);
end;

{ TGenExList }

constructor TGenExList.Create(CreateFrom: ICM2GenPlug);
Var
 Cnt, Cnt2, I, I2: Integer;
 N, V, D: PChar;
begin
 If Debug then Form4.Add('TGenExList.Create -->', dlplugins);
 If CreateFrom.GetSensorCount(Cnt) <> S_OK then begin
  If Debug then Form4.Add('Unable to load SensorCount', dlplugins);
  exit;
 end;
 For I := 0 to Cnt-1 do begin
  SetLength(fList, length(fList) + 1);
  fList[Length(fList) - 1] := TExInfoList.Create;
  If CreateFrom.GetDefaultCount(I, Cnt2) <> S_OK Then begin
   If Debug then Form4.Add('Unable to load Default Count', dlplugins);
   exit;
  End;
  For I2 := 0 to Cnt2-1 do begin
   CreateFrom.GetDefault(I, I2, N, V, D);
   fList[Length(fList) -1].Add(N, V, D, eitRequired);
  End;
  If CreateFrom.GetOptionalCount(I, Cnt2) <> S_OK Then begin
   If Debug then Form4.Add('Unable to load Optional Count', dlplugins);
   exit;
  End;
  For I2 := 0 to Cnt2-1 do begin
   CreateFrom.GetOptional(I, I2, N, V, D);
   fList[Length(fList) -1].Add(N, V, D, eitOptional);
  End;
 End;
 Self.PlugIn := CreateFrom;
 If Debug then form4.Add('Done - TGenListEx.Create', dlplugins);
end;

destructor TGenExList.Destroy;
Var
 I: Integer;
begin
 For I := count - 1 downto 0 do begin
  fList[I].Free;
 End;
 inherited;
end;

function TGenExList.GetCount: Integer;
begin
 Result := Length(fList);
end;

function TGenExList.GetExInfoList(Index: Integer): TExInfoList;
begin
 Result := fList[Index];
// showmessage('bogus value');
end;

{ TEditorSupportGen }

function TEditorSupportGen.GetByName(Name: String): TESGen;
Var
 I: Integer;
begin
 Result.ValueType := vtUnknown;
 Result.ValueRange := '';
 For I := 0 to count - 1 do begin
  If uppercase(name) = uppercase(fList[I].ParameterName) then begin
   Result := fList[I];
   exit;
  end;
 End;
end;

function TEditorSupportGen.GET_COUNT: Integer;
begin
 Result := Length(fList);
end;

function TEditorSupportGen.GET_ESGEN(Index: Integer): TESGen;
begin
 Result := fList[Index];
end;

procedure TEditorSupportGen.LoadFrom(PlugIn: TGenPlugIn;
  SensorIndex: Integer);
Var
 EditSupport: ICM2EditorSupport10;
 EditSupport20: ICM2EditorSupport20;
 GenExList: TGenExlist;
 I: Integer;
 ValueRange: Pchar;
 Valuetype, ShowAt: Byte;
 Res: HResult;
 InterfaceVersion: Byte;
begin
 SetLength(fList, 0);
 Self.fSupportsEditor := True;
 InterfaceVersion := 0;
 Try
  EditSupport20 := CreateCOMObject (PlugIn.GUID) as ICM2EditorSupport20;
  InterfaceVersion := 2;
 Except
  Try
   EditSupport := CreateComObject (PlugIn.GUID) as ICM2EditorSupport10;
   InterfaceVersion := 1;
  except
   fSupportsEditor := False;
  end;
 end;
 If Not SupportsEditor then exit;
 Res := E_FAIL;
 Case InterfaceVersion of
  1: Begin
      Res := EditSupport.ShowSensor(SensorIndex, ShowAt);
     end;
  2: Begin
      Res := EditSupport20.ShowSensor(SensorIndex, ShowAt);
     end;
 end;
 If Res <> S_OK Then begin
  ShowAt := saDesignTime;
 end;
 GenExList := TGenExList.Create(PlugIn.PlugIn);
 For I := 0 to GenExList.ExList[SensorIndex].Count - 1 do begin
  SetLength(fList, Length(fList) + 1);
  fList[length(fList)-1].ParameterName := GenExList.ExList[SensorIndex].ExInfo[I].Name;
  fList[Length(fList)-1].ValueType := vtUnknown;
  fList[Length(fList)-1].ValueRange := '';
  ValueRange := ''; ValueType := vtUnknown;
  Res := E_FAIL;
  Case InterfaceVersion of
   1: Begin
       Res := EditSupport.ObjIns(SensorIndex, PChar(fList[Length(fList)-1].ParameterName), ValueType, ValueRange);
      end;
   2: begin
       Res := EditSupport20.ObjIns(SensorIndex, PChar(fList[Length(fList)-1].ParameterName), Valuetype, ValueRange);
      end;
  end;
  If Res = S_OK then begin
   fList[Length(fList)-1].ValueType := ValueType;
   fList[Length(fList)-1].ValueRange := ValueRange;
  end;
 end;
 FreeAndNil(GenExList);
end;

end.
