unit Unit1;

interface

uses
  Windows, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, shellapi, ImgList, JclCompression, strutils,
  listdriver, parseinf, inifiles, MySetupApi, Menus, Buttons, CommCtrl, Clipbrd,
  RzTabs, RzPanel, cDataStructs,
  RzButton, math, ComCtrls, VirtualTrees, RzRadGrp,
  RzCommon, RzGrafx,
  unFileMapping, Indexobj, Messages, JvCombobox, gauges, JvExStdCtrls,
  JvExControls, JvAnimatedImage, JvGIFCtrl,
  registry,
  RzSpnEdt, RzBmpBtn, jpeg, RzBorder, RzStatus, Generics.Collections,
  newparser, Vcl.ButtonGroup, Vcl.CategoryButtons, JvgPage, JvPageList,
  JvComponentBase, JvComCtrls, JvExComCtrls, JvTabBar, JvTabBarXPPainter,
  Vcl.OleCtrls, SHDocVw;

type
  TStringArray = array of ansiString;
  Tbase = TDIctionary<ansiString, TmappedFile>;
  PTbase = ^Tbase;
  TBaseList = TDIctionary<ansiString, Tbase>;

  TmyFunction = function(): word;

  Proc2 = procedure(Sender: TObject);

  { TVirtualStringTree = class(VirtualTrees.TVirtualStringTree)
    protected
    function GetHintWindowClass: THintWindowClass; override;
    end;
  }
  PWindows = ^TWindows;

  TWindows = record
    WindowHandle: HWND;
    WindowText: string;
  end;

  PTreeDP = ^TTreeDP;

  TTreeDP = record
    image: word;
    name: string;
    Filename: string;
    size: integer;
    indexed: boolean;
    progress: integer;
    isextracting: boolean;
  end;

  Pdevice = ^TDevice;

  TDevice = record
    Driver_NAME: ansiString;
    Driver_HWID: ansiString;
    Driver_date: ansiString;
    Driver_ver: ansiString;
    Driver_Dir: ansiString;
    Driver_INF: ansiString;
    Driver_Pack: ansiString;
    Driver_image: word;
    Driver_MFG: ansiString;
    Driver_status: word;
    Driver_Progress: integer;

    Device_index: word; // index of device, in case if gona delete them
    Device_HWID: ansiString;
    Device_HWID_compatible: ansiString;
    Device_date: ansiString;
    Device_Ver: ansiString;

  end;

  TDirection = (diHorizon, diVertical);

  TMYCURSOR = record
    Pointer: Pansichar;
    Hasleft: integer;
  end;

  TIndexThread = class(TThread)
  private
  protected
    // CurrentDP:integer;
    MyValue, MyMaxValue: Int64;
    MyValue2, MyMaxValue2: integer;
    // typeSync:integer;
    Myselected: Tstringlist;
    CurrentStatus: string;
    CurrentDP: integer;

    CurrentNode: PVirtualNode;
    CurrentData: PTreeDP;
    IndexTime: ttime;

    procedure Execute(); override;
    function ExtractInf(Extractdir: string; ArchiveFilename: string)
      : Tstringlist;
    procedure ArchiveProgress(Sender: TObject; const Value, MaxValue: Int64);
    procedure Setprogress();
    procedure SetFocus();

    procedure SetTHEend();

    procedure GetNodeData;

  end;

  TUpdateThread = class(TThread)
  private
  protected
    RefreshProcedure: Proc2;
    CurrentDriver: integer;
    CurrentOperation: string;
    LogStatus: string;
    MyValue, MyMaxValue: Int64;
    // MyValue2, MyMaxValue2:integer;

    // Inputlist:Tlistview;
    // Mainlist:tlistview;

    F5button: TRZBitBtn;
    // SetupButton:TRZBitBtn;
    VTV: TVirtualStringTree;
    Mydevice: Pdevice;
    Mynode: PVirtualNode;

    procedure Execute(); override;
    // function ExtractInf(Extractdir:string;ArchiveFilename:string):tstringlist;
    // procedure ArchiveProgress(Sender: TObject; const Value, MaxValue: Int64);
    // procedure Setprogress();
    procedure SetLogStatus();
    procedure ArchiveProgress(Sender: TObject; const Value, MaxValue: Int64);
    // procedure Setprogress();
    function ExtractDPdir(Extractdir: string; ArchiveFilename: string;
      DPdir: string): Tstringlist;

  end;

  TForm1 = class(TForm)

    PageControl1: TRZPageControl;
    TabSheet2: TRZTabSheet;
    Panel1: TRZPanel;
    Splitter1: TSplitter;
    TabSheet5: TRZTabSheet;
    Panel3: TPanel;
    Panel4: TRZPanel;
    Label6: TLabel;
    Panel6: TPanel;
    TabSheet1: TRZTabSheet;
    Panel2: TRZPanel;
    MainMenu1: TMainMenu;
    N1: TMenuItem;
    N2: TMenuItem;
    N3: TMenuItem;
    N4: TMenuItem;
    TabSheet6: TRZTabSheet;
    Panel8: TRZPanel;
    SmallDevices: TImageList;
    Button7: TRZBitBtn;
    BitBtn1: TRZBitBtn;
    Button4: TRZBitBtn;
    Button9: TRZBitBtn;
    tvDevices: TTreeView;
    ilDevices: TImageList;
    lvAdvancedInfo: TListView;
    BitBtn3: TRZBitBtn;
    ImageTabs: TImageList;
    N5: TMenuItem;
    DirectX1: TMenuItem;
    N6: TMenuItem;
    N7: TMenuItem;
    N8: TMenuItem;
    PopupMenu1: TPopupMenu;
    N9: TMenuItem;
    N10: TMenuItem;
    N11: TMenuItem;
    PopupDP: TPopupMenu;
    N12: TMenuItem;
    RzBitBtn1: TRZBitBtn;
    RzBitBtn2: TRZBitBtn;
    RzPanel6: TRZPanel;
    PopupSet_N_Upd: TPopupMenu;
    N16: TMenuItem;
    N17: TMenuItem;
    Button10: TRZBitBtn;
    N19: TMenuItem;
    N20: TMenuItem;
    N18: TMenuItem;
    N21: TMenuItem;
    ShowDP: TMenuItem;
    RzCheckGroup1: TRzCheckGroup;
    RzCheckGroup2: TRzCheckGroup;
    N22: TMenuItem;
    N23: TMenuItem;
    N24: TMenuItem;
    N26: TMenuItem;
    DEVID1: TMenuItem;
    MS1: TMenuItem;
    RzBitBtn4: TRZBitBtn;
    N27: TMenuItem;
    N28: TMenuItem;
    N29: TMenuItem;
    ImageMenu: TImageList;
    TimerUnsigned: TTimer;
    VST_DP: TVirtualStringTree;
    StaticText1: TStaticText;
    VTV_update: TVirtualStringTree;
    ImageButtons: TImageList;
    VTV_setup: TVirtualStringTree;
    Progress_INDEX: TGauge;
    OS_label: TMenuItem;
    TabSheet3: TRZTabSheet;
    Memo1: TMemo;
    RichEdit1: TRichEdit;
    RzPanel2: TRZPanel;
    RzBitBtn3: TRZBitBtn;
    RzBitBtn9: TRZBitBtn;
    RzBitBtn11: TRZBitBtn;
    RzBitBtn12: TRZBitBtn;
    RzBitBtn10: TRZBitBtn;
    RzBitBtn5: TRZBitBtn;
    RzBitBtn6: TRZBitBtn;
    Panel5: TPanel;
    RzBitBtn7: TRZBitBtn;
    RzBitBtn8: TRZBitBtn;
    Debug1: TMenuItem;
    SaveDevices1: TMenuItem;
    LoadDevices1: TMenuItem;
    RzPanel1: TRZPanel;
    Logbutton: TRzToolButton;
    ListBox1: TListBox;
    OpenDriverInarchive1: TMenuItem;
    ProgressBar1: TProgressBar;

    procedure FormCreate(Sender: TObject);
    procedure Label2Click(Sender: TObject);

    procedure InitializeGB();
    function FillDRPLIST3(): integer;
    procedure CheckBases();
    procedure FormShow(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure N4Click(Sender: TObject);
    procedure N2Click(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure tvDevicesChange(Sender: TObject; Node: TTreeNode);
    procedure Button10Click(Sender: TObject);
    procedure N5Click(Sender: TObject);
    procedure DirectX1Click(Sender: TObject);
    procedure N7Click(Sender: TObject);
    procedure N8Click(Sender: TObject);
    procedure Label6MouseEnter(Sender: TObject);
    procedure Label6MouseLeave(Sender: TObject);
    procedure N9Click(Sender: TObject);
    procedure BitBtn3Click(Sender: TObject);
    procedure N10Click(Sender: TObject);
    procedure N12Click(Sender: TObject);

    // procedure DrawProgressBar(ACanvas: TCanvas; lpRect: TRect; ProgressCount: Integer);
    procedure DrawProgressBar(ACanvas: TCanvas; CellRect: TRect;
      ProgressCount: integer);
    procedure Button9Click(Sender: TObject);
    procedure RzBitBtn1Click(Sender: TObject);
    procedure TabSheet6Show(Sender: TObject);
    procedure TabSheet1Show(Sender: TObject);
    procedure TabSheet2Show(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure N16Click(Sender: TObject);
    procedure N17Click(Sender: TObject);
    procedure N19Click(Sender: TObject);
    procedure N20Click(Sender: TObject);
    procedure ShowDPClick(Sender: TObject);
    procedure RzCheckGroup1Change(Sender: TObject; Index: integer;
      NewState: TCheckBoxState);
    procedure N22Click(Sender: TObject);
    procedure N24Click(Sender: TObject);
    procedure RzBitBtn4Click(Sender: TObject);
    procedure DEVID1Click(Sender: TObject);
    procedure MS1Click(Sender: TObject);
    procedure N29Click(Sender: TObject);
    procedure RzCheckGroup2Change(Sender: TObject; Index: integer;
      NewState: TCheckBoxState);
    procedure RzBitBtn11Click(Sender: TObject);
    procedure TimerUnsignedTimer(Sender: TObject);

    procedure VST_DPGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: boolean;
      var ImageIndex: integer);
    procedure VST_DPBeforeCellPaint(Sender: TBaseVirtualTree;
      TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
      CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect);
    procedure RzBitBtn12Click(Sender: TObject);
    procedure TabSheet5Show(Sender: TObject);
    procedure RzBitBtn10Click(Sender: TObject);
    procedure RzBitBtn3Click(Sender: TObject);
    procedure RzBitBtn9Click(Sender: TObject);
    procedure VTV_updateGetImageIndex(Sender: TBaseVirtualTree;
      Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
      var Ghosted: boolean; var ImageIndex: integer);
    procedure VTV_updateBeforeCellPaint(Sender: TBaseVirtualTree;
      TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
      CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect);
    procedure VTV_updateGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle;
      var HintText: String);
    procedure VTV_updatePaintText(Sender: TBaseVirtualTree;
      const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
      TextType: TVSTTextType);
    procedure VTV_updateDrawText(Sender: TBaseVirtualTree;
      TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
      const Text: String; const CellRect: TRect; var DefaultDraw: boolean);
    procedure RzBitBtn2Click(Sender: TObject);
    procedure VTV_updateDblClick(Sender: TObject);
    procedure VTV_updateCompareNodes(Sender: TBaseVirtualTree;
      Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: integer);
    procedure VTV_updateHeaderClick(Sender: TVTHeader; Column: TColumnIndex;
      Button: TMouseButton; Shift: TShiftState; X, Y: integer);
    procedure RzBitBtn5Click(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
    procedure VTV_updateMeasureItem(Sender: TBaseVirtualTree;
      TargetCanvas: TCanvas; Node: PVirtualNode; var NodeHeight: integer);
    procedure VTV_updateChecking(Sender: TBaseVirtualTree; Node: PVirtualNode;
      var NewState: TCheckState; var Allowed: boolean);
    // procedure VTV_updateChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
    // procedure VTV_updateInitNode(Sender: TBaseVirtualTree;
    // ParentNode, Node: PVirtualNode;
    // var InitialStates: TVirtualNodeInitStates);
    procedure RzBitBtn8Click(Sender: TObject);
    procedure RzBitBtn7Click(Sender: TObject);
    procedure SaveDevices1Click(Sender: TObject);
    procedure LoadDevices1Click(Sender: TObject);
    procedure VTV_updateGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
    procedure VST_DPGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
    procedure CategoryButtons1DrawButton(Sender: TObject;
      const Button: TButtonItem; Canvas: TCanvas; Rect: TRect;
      State: TButtonDrawState);
    procedure LogbuttonClick(Sender: TObject);
    procedure ListBox1DrawItem(Control: TWinControl; Index: integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure ListBox1Exit(Sender: TObject);
    procedure OpenDriverInarchive1Click(Sender: TObject);
    procedure VST_DPPaintText(Sender: TBaseVirtualTree;
      const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
      TextType: TVSTTextType);
    procedure OS_labelClick(Sender: TObject);

    { Private declarations }
  public
    { Public declarations }
  end;

function Check_Write(): boolean;
procedure ClickUpdate(Sender: TObject);
procedure ClickSetup(Sender: TObject);

function SetThreadUILanguage(LangId: word): word; stdcall;
  external 'kernel32.dll';

var

  GetThreadUILanguage: TmyFunction;

  h, h2, h3: THintWindow;
  AWindows: PWindows;

  // Ïåðåìåííûå ñ ïðåôèêñìî GB_ ãëîáàëüíûå è äîëæíû èíèçèàëèçèðîâàòñÿ ïðè çàïóñêå ïðîãðàììû
  // GB_DRPfolder,
  GB_TMPfolder, GB_DevDB, GB_Appdir: ansiString;
  GB_64bit: boolean; // Битность Системы
  GB_Minor: integer;
  GB_Major: integer;
  GB_DriverList: TDriverList;
  //
  GB_toEmulate: boolean;
  GB_Oses: Tstringlist;
  // GB_DEV_BASES: Tstringlist;
  // GB_DEV_BASES содержит название паков и пути к ним Используется Глобально
  GB_Driverpack: Pansichar;

  GB_hashdict: TObjectDictionary;
  // GB_hashdict2:TPointerDictionary;

  // GB_MapFiles: array of TmappedFile;

  GB_baseLoaded: boolean;

  GB_INI_PATH: string;
  GB_DRP_DIR: string;
  GB_devcon: string;
  GB_Oem_install: boolean;

  GB_Write_allowed: boolean;

  GB_IGNORE: Tstringlist;

  GB_OStype: TStringArray;

  GB_Baselist: TBaseList;

  Devices_global: HDEVINFO;
  Form1: TForm1;
  time11, time22: ttime;
  // IndexList:TDriverIndexList;
  NewThread: TIndexThread;

  UpdateThread1: TUpdateThread;
  UpdateThread2: TUpdateThread;
  UpdateThread1_running: boolean;
  UpdateThread2_running: boolean;

  // Íàñòðîéêè
  GB_1HWID: boolean;
  GB_restorepoint: boolean;

  Bmp: TBitmap;
  bmp2: TBitmap;
  // FX: TJvPaintFX;

const

  { DpTemplates:array[0..3] of string= (
    '_DRP.txt','_XP.txt','_Vista-7-x86.txt','_Vista-7-x64.txt'); }

  INI_ext: string = '.INI';
  ZIP7_ext: string = '.7Z';
  UNKNOWN: string = 'UNKNOWN';
  KEY_WOW64_64KEY = $0100;
  KEY_WOW64_32KEY = $0200;

const
  NT_ALL: array [0 .. 5] of ansiString = ('ALL_32BIT', 'ALL_64BIT', 'NT5_32BIT',
    'NT5_64BIT', 'NT6_32BIT', 'NT6_64BIT');

  DpStringTypes: array [1 .. 26] of string = ('GAMING', 'MISC', 'CHIPSET',
    'CPU', 'MASSSTORAGE', 'MASSTORAGE', 'BLUETOOTH', 'BROADBAND', 'MODEM',
    'WEBCAM', 'AUDIO', 'SOUND', '_LAN', 'USB', 'HID', 'INPUT', 'GRAPHICS',
    'VIDEO', 'WLAN', 'CARDREADERS', '_TV', 'MONITOR', 'PRINTER', 'SCANNER',
    'TOUCHPAD', 'PHONE');

  DpStringResult: array [1 .. 26] of integer = (1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7,
    7, 8, 9, 10, 10, 11, 11, 12, 13, 14, 14, 15, 16, 17, 18);

implementation

uses Types, Settings, Contnrs, Unit3, splash, about, emulate;

{$R *.dfm}

procedure TOLOG(msg: string);
begin
  Form1.ListBox1.items.Add(msg);
  Form1.ListBox1.ItemIndex := Form1.ListBox1.Count - 1;
  Form1.ListBox1.TopIndex := Form1.ListBox1.Count - 1;
end;

function Get_File_Size2(sFileToExamine: string): integer;
var
  SearchRec: TSearchRec;
  inRetval: integer;
begin
  try
    inRetval := FindFirst(ExpandFileName(sFileToExamine), faAnyFile, SearchRec);
    if inRetval = 0 then
      Result := SearchRec.size
    else
      Result := -1;
  finally
    SysUtils.FindClose(SearchRec);
  end;
end;

function Get_OStype(): TStringArray;
var
  Bit_n_Ext: ansiString;
begin
  SetLength(Result, 0);
  SetLength(Result, length(Result) + 1);
  if GB_64bit then
  begin
    Bit_n_Ext := '_64.INI';
    Result[length(Result) - 1] := 'ALL' + Bit_n_Ext;
  end
  else
  begin
    Bit_n_Ext := '_32.INI';
    Result[length(Result) - 1] := 'ALL' + Bit_n_Ext;
  end;

  SetLength(Result, length(Result) + 1);
  Result[length(Result) - 1] := 'NT' + IntToStr(GB_Major) + Bit_n_Ext;

  SetLength(Result, length(Result) + 1);
  Result[length(Result) - 1] := 'NT' + IntToStr(GB_Major) + IntToStr(GB_Minor) +
    Bit_n_Ext;
end;

procedure GetThreadUILanguageON();
var
  hDll: THandle;
begin
  hDll := LoadLibrary('Kernel32.dll');
  if hDll >= 32 then { success }
  begin
    GetThreadUILanguage := GetProcAddress(hDll, 'GetThreadUILanguage');
  end
  else
    MessageDlg('Error: could not find exampleDLL.DLL', mtError, [mbOk], 0)
end;

function CopyOEMfile(): boolean;
var
  OEM_INI: string;
  OEM_BMP: ansiString;
  sys32: string;
begin
  sys32 := GetSystemDirectory;
  OEM_BMP := GB_Appdir + '\tools\oemlogo.bmp';

  if GB_Major = 5 then
  begin
    OEM_INI := GB_Appdir + '\tools\oeminfo.ini';
    CopyFile(Pchar(OEM_INI), Pchar(sys32 + '\oeminfo.ini'), true);
    CopyFile(Pchar(OEM_BMP), Pchar(sys32 + '\oemlogo.bmp'), true);
  end
  else
  begin
    OEM_INI := GB_Appdir + '\tools\oeminfo7.reg';
    ShellExecute(Form1.Handle, 'open', 'reg.exe',
      Pchar('import "' + OEM_INI + '"'), nil, SW_HIDE);
    CopyFile(Pchar(OEM_BMP), Pchar(sys32 + '\OEM\oemlogo.bmp'), true);

  end;

  Result := true;
end;

{ function TVirtualStringTree.GetHintWindowClass: THintWindowClass;
  begin
  Result :=TJvBalloonWindow;// HTHintWindow;// TVirtualTreeHintWindow ;//TVirtualTreeHintWindowEx;
  end; }

function FindNode(AVST: TCustomVirtualStringTree; ANode: PVirtualNode;
  const APattern: WideString): PVirtualNode;
var
  NextNode: PVirtualNode;
  PhoneNode: Pdevice;
begin
  Result := nil;
  NextNode := ANode.FirstChild;
  if Assigned(NextNode) then
    repeat
      PhoneNode := AVST.GetNodeData(NextNode);
      if Assigned(PhoneNode) then
        if PhoneNode^.Driver_NAME = APattern then
        begin
          Result := NextNode;
          exit;
        end
        else
      else if PhoneNode^.Driver_NAME = APattern then
      begin
        Result := NextNode;
        exit;
      end;
      // Èùåì â äî÷åðíèõ âåòêàõ
      Result := FindNode(AVST, NextNode, APattern);
      // Ïåðåõîäèì íà ñîñåäíþþ âåòêó...
      NextNode := NextNode.NextSibling;
    until
    // ...ïîêà íå âìàæåìñÿ ëáîì â ñòåíó :)
      NextNode = nil;
end;

function AddVSTDevice(AVST: TCustomVirtualStringTree; ANode: PVirtualNode;
  ARecord: Tdriver; var data: Pdevice; HaveDubles: boolean): PVirtualNode;
// var
// Data: Pdevice;
begin
  Result := AVST.AddChild(ANode);
  if HaveDubles then
    Result.CheckType := ctRadioButton
  else
    Result.CheckType := ctTriStateCheckBox;
  data := AVST.GetNodeData(Result);
  AVST.ValidateNode(Result, False);
  if ARecord = nil then
    exit;
  data^.Driver_NAME := ARecord.name;
  data^.Driver_HWID := ARecord.Hwid;
  data^.Driver_date := ARecord.Date;
  data^.Driver_ver := ARecord.Ver;
  data^.Driver_Dir := ARecord.Dir;
  data^.Driver_INF := ARecord.Inffile;
  data^.Driver_MFG := ARecord.Manufactor;

  AVST.ReinitNode(Result, False);
end;

function AddVSTStructure(AVST: TCustomVirtualStringTree; ANode: PVirtualNode;
  ARecord: TTreeDP): PVirtualNode;
var
  data: PTreeDP;
begin
  Result := AVST.AddChild(ANode);
  Result.CheckType := ctTriStateCheckBox;
  data := AVST.GetNodeData(Result);
  AVST.ValidateNode(Result, False);
  data^.name := ARecord.name;
  data^.Filename := ARecord.Filename;
  data^.size := ARecord.size;
  data^.indexed := ARecord.indexed;
  data^.image := ARecord.image;
  data^.progress := ARecord.progress;
  // data^.Number:=ARecord.Number;
  Form1.VST_DP.ReinitNode(Result, False);
end;

procedure GradVertical(Canvas: TCanvas; Rect: TRect;
  FromColor, ToColor: TColor);
var
  Y: integer;
  dr, dg, db: Extended;
  C1, C2: TColor;
  r1, r2, g1, g2, b1, b2: Byte;
  R, G, B: Byte;
  cnt: integer;
  oldpen: Tpen;
begin
  oldpen := Canvas.Pen;
  C1 := FromColor;
  r1 := GetRValue(C1);
  g1 := GetGValue(C1);
  b1 := GetBValue(C1);

  C2 := ToColor;
  r2 := GetRValue(C2);
  g2 := GetGValue(C2);
  b2 := GetBValue(C2);

  dr := (r2 - r1) / Rect.Bottom - Rect.Top;
  dg := (g2 - g1) / Rect.Bottom - Rect.Top;
  db := (b2 - b1) / Rect.Bottom - Rect.Top;

  cnt := 0;
  for Y := Rect.Top to Rect.Bottom - 1 do
  begin
    R := r1 + Ceil(dr * cnt);
    G := g1 + Ceil(dg * cnt);
    B := b1 + Ceil(db * cnt);

    Canvas.Pen.Color := RGB(R, G, B);
    Canvas.MoveTo(Rect.Left, Y);
    Canvas.LineTo(Rect.Right, Y);
    Inc(cnt);
  end;

  Canvas.Pen := oldpen;
end;

procedure checkDRPfolders();
// var i:integer;
begin
  if not(DirectoryExists(GB_Appdir + '\' + GB_DRP_DIR + '\')) then
    CreateDir(GB_Appdir + '\' + GB_DRP_DIR + '\');
  { for i:=1 to 3 do
    if not( DirectoryExists(GB_Appdir+'\'+GB_DRP_DIRS[0]+'\'+GB_DRP_DIRS[i]+'\') ) then
    CreateDir(GB_Appdir+'\'+GB_DRP_DIRS[0]+'\'+GB_DRP_DIRS[i]+'\'); }

end;

procedure ParseFieldDriver(InpString: Pansichar; var Index: Tdriver);
var
  // curpos: Integer;
  // secpos:integer;
  Pstr: Pansichar;

begin
  Pstr := InpString; // @inpstring[1];

  index.Hwid := InpString;
  // ShowMessage(index.HWID);
  // ShowMessage(pstr);
  // curpos:=posEx(#9,Pstr,0);
  // inc(pstr,curpos);// Ïðîïóñêàåì HWID
  { pol:=InpString;
    inc(pol,25); }
  // ShowMessage(InpString);

  // try
  // curpos:=posEx(#0,Pstr,0);
  // inc(pstr,curpos);
  // k:=0;
  // inc(pstr,length(Pstr)+1);
  while not(Pstr[0] = #0) do
    Inc(Pstr); // Ïðîïóñêàåì HWID
  Inc(Pstr);
  index.Dir := Pstr;

  // inc(pstr,length(Pstr)+1);
  // ShowMessage(pstr);

  /// curpos:=posEx(#0,Pstr,0);

  // index.dir[curpos-1]:=#0;

  while not(Pstr[0] = #0) do
    Inc(Pstr); // Ïðîïóñêàåì Dir
  Inc(Pstr);
  index.Inffile := Pstr;
  // curpos:=posEx(#0,Pstr,0);

  // ShowMessage(pstr);
  // index.Inffile[curpos-1]:=#0;

  while not(Pstr[0] = #0) do
    Inc(Pstr); // Ïðîïóñêàåì Infile
  Inc(Pstr);
  index.Manufactor := Pstr;
  // curpos:=posEx(#0,Pstr,0);


  // index.Manufactor[curpos-1]:=#0;

  while not(Pstr[0] = #0) do
    Inc(Pstr); // Ïðîïóñêàåì Manufactor
  Inc(Pstr);
  index.Date := Pstr;
  // curpos:=posEx(#0,Pstr,0);

  // ShowMessage(pstr);
  // index.DataVer[curpos-1]:=#0;

  while not(Pstr[0] = #0) do
    Inc(Pstr); // Ïðîïóñêàåì Date
  Inc(Pstr);
  index.Ver := Pstr;

  while not(Pstr[0] = #0) do
    Inc(Pstr); // Ïðîïóñêàåì Ver
  Inc(Pstr);
  index.name := Pstr;

  // curpos:=pos(#9,Pstr);

  // except ShowMessage(InpString+' BUG');    end;
  // index.name:=copy(Pstr,0,length(pstr));

end;

function GetFirstField(var InpString: Pchar): String;
var
  curpos: integer;
  // k:pchar;
begin
  // k:=@inpstring[1];
  curpos := posEx(#9, InpString, 0);
  // k[curpos-1]:=#0;
  Result := copy(InpString, 0, curpos - 1);
  Inc(InpString, curpos);
end;

function GetFirstField2(var InpString: Pchar): Pchar;
var
  curpos: integer;
  // k:pchar;
begin
  curpos := posEx(#9, InpString, 0);

  Result := InpString;
  Result[curpos - 1] := #0;
  Inc(InpString, curpos);
end;

function DB_GetLine(var Mcursor: TMYCURSOR): Pansichar;
var
  k: integer;
  CUR_PI: Pansichar;
begin
  k := 0;
  CUR_PI := Mcursor.Pointer;

  while not(CUR_PI[k] = #13) do
  begin
    Inc(k);
    // (Mcursor.Pointer);
    if k >= Mcursor.Hasleft then
    begin
      Result := nil;
      exit;
    end;

  end;

  // k:=pos(#13,Mpoint);
  if k > 0 then
  begin
    // ShowMessage(IntToStr(k))
    // Result:=copy(Mpoint,0,k-1);
    Result := Mcursor.Pointer;
    // Result[k]:=#0;
    // Mpoint[k-1]:=#0;
    Inc(Mcursor.Pointer, k + 2);
    dec(Mcursor.Hasleft, k + 2);
    exit;
  end;
  Result := nil;

end;

function GET_OS_sections(): ansiString;
begin
  if GB_64bit then
    Result := Result + '[' + NT_ALL[1] + ']'
  else
    Result := Result + '[' + NT_ALL[0] + ']';

  if GB_64bit then
    case GB_Major of
      5:
        Result := Result + '-[' + NT_ALL[3] + ']';
      6:
        Result := Result + '-[' + NT_ALL[5] + ']';
    end;

  if not(GB_64bit) then
    case GB_Major of
      5:
        Result := Result + '-[' + NT_ALL[2] + ']';
      6:
        Result := Result + '-[' + NT_ALL[4] + ']';
    end;

end;

procedure UnLoadHashMAPS_OBJ();
var
  i: integer;
  CurrentDP: ansiString;
  currentBase: ansiString;
begin
  GB_hashdict.Clear;
  GB_baseLoaded := False;
  // GB_DEV_BASES.Clear;

  for CurrentDP in GB_Baselist.Keys do
    for currentBase in GB_Baselist.items[CurrentDP].Keys do
    begin
      GB_Baselist.items[CurrentDP].items[currentBase].Free;

    end;

end;

function FindDP(input: string; Strings: Tstringlist): string;
var
  i: integer;
begin

  for i := 0 to Strings.Count - 1 do
    if pos(UpperCase(input), UpperCase(Strings.Strings[i])) > 0 then
    begin
      Result := Strings.Strings[i];
      break;
    end;
end;

procedure LoadHashMAPS_OBJ();
label NEWSEC;
var
  searchResult: TSearchRec;
  i: integer;
  // L:integer;
  // DB_strings:tstringlist;
  // tick:dword;
  // tick2:dword;
  // alltick:dword;
  // Indexlist :TDriverIndexList;
  // HWID:string;
  // HWID2:pchar;
  // Index :TDriverIndex;
  // os:integer;
  /// ////////////////////////////////
  // sdata, srow: TStrings;

  // Cur_Str:pchar;
  // ini1:tinifile;
  // k:integer;

  // MapFile1:array of  TMappedFile;

  NewString: Pansichar;
  // NewString:string;
  // PointerS:pchar;
  Mycursor: TMYCURSOR;
  // OS_Sections: ansiString;
  MyDrivers: TDrivers;
  Driver0: Tdriver;
  dp_files: Tstringlist;
  // indexDP:integer;

  SplashForm0: TSplashForm;
  // cavb : 0..255;
  CurrentBaseObject: Tbase;
  CurrentDP, currentBase, CurrentBaseDir: ansiString;
  currentMapFile: TmappedFile;
begin

  // Получаем список типов ОС (NT6_32.ini или NT6_64.ini)
  GB_OStype := Get_OStype();

  // tick2:=0;
  GB_baseLoaded := False;
  // OS_Sections := GET_OS_sections;
  // MessageBoxA(0,pansichar(os_sections),'kkk',mb_ok);

  // ShowMessage(OS_Sections);

  // GB_DEV_BASES := Tstringlist.Create;
  dp_files := Tstringlist.Create;

  // ShowMessage(GB_Appdir+'\'+GB_DRP_DIRS[0]+'\');

  // Получаем имена драйверпаков
  ScanDir(GB_Appdir + '\' + GB_DRP_DIR + '\', ZIP7_ext, true, dp_files);

  for i := 0 to dp_files.Count - 1 do
    dp_files.Strings[i] := dp_files.names[i];

  GB_Baselist := TBaseList.Create;

  // Получаем список Драйверпаков
  for i := 0 to dp_files.Count - 1 do
    GB_Baselist.Add(dp_files.Strings[i], nil);

  // Помечаем значения для которых нет Базы индекса,точнее папки индексов
  dp_files.Clear;
  for CurrentDP in GB_Baselist.Keys do
  begin
    CurrentBaseDir := GB_DevDB + ExtractFileName(CurrentDP) + '\';
    if not(DirectoryExists(string(CurrentBaseDir))) then
      dp_files.Add(CurrentDP);
  end;

  // Удаляем значения для которых нет Базы индекса,точнее папки индексов
  for i := 0 to dp_files.Count - 1 do
    GB_Baselist.Remove(dp_files.Strings[i]);

  // GB_Baselist.TrimExcess;

  // ShowMessage('Bases count ' + IntToStr(GB_Baselist.Count));
  // for CurrentDP in GB_Baselist.Keys do
  // begin
  // for CurrentBase in GB_Baselist.Items[CurrentDP]. Keys do
  // ShowMessage(CurrentDp);

  // end;

  dp_files.Clear;
  // Создаем элементы базы и заполняем индексами по типу нашей ОС
  for CurrentDP in GB_Baselist.Keys do
  begin

    CurrentBaseObject := Tbase.Create;
    CurrentBaseDir := GB_DevDB + ExtractFileName(CurrentDP);

    for i := Low(GB_OStype) to High(GB_OStype) do
      if Get_File_Size2(CurrentBaseDir + '\' + GB_OStype[i]) > 0 then
        CurrentBaseObject.Add(CurrentBaseDir + '\' + GB_OStype[i], nil);

    if CurrentBaseObject.Count <= 0 then
    begin
      CurrentBaseObject.Free;
      dp_files.Add(CurrentDP);
      // ShowMessage(CurrentDP+' removed');
    end
    else
      GB_Baselist.items[CurrentDP] := CurrentBaseObject;
  end;

  for i := 0 to dp_files.Count - 1 do
    GB_Baselist.Remove(dp_files.Strings[i]);

  // GB_Baselist.TrimExcess;
  // ShowMessage('POST Bases count ' + IntToStr(GB_Baselist.Count));



  // for i := Low(GB_OStype) to High(GB_OStype) do
  // ShowMessage(GB_OStype[i] + '_____' + IntToStr(i));

  // Ïûòàåìñÿ íàéòè ïðàâèëüíûå ôàéëû, ñîîòâåòñòâóþùèå *_XP.txt â êàòàëîãå
  // if FindFirst(GB_DevDB + '*' + INI_ext, faAnyFile, searchResult) = 0 then
  // begin
  // repeat
  // // ShowMessage(searchResult.Name);
  // // indexDP:=dp_files.IndexOf(UpperCase( ChangeFileExt(searchResult.Name,'')));
  // // dp_files.Find()
  // // if indexDP>=0 then
  // GB_DEV_BASES.Add(searchResult.name + '=' +
  // FindDP(ChangeFileExt(searchResult.name, ZIP7_ext), dp_files));
  // // else
  // // GB_DEV_BASES.Add(searchResult.Name+'='+GetRealDP(searchResult.Name));
  //
  // until FindNext(searchResult) <> 0;
  //
  // // Äîëæåí îñâîáîäèòü ðåñóðñû, èñïîëüçóåìûå ýòèìè óñïåøíûìè, ïîèñêàìè
  // FindClose(searchResult);
  // end;

  // ShowMessage('Ïðèâåò ');
  if Assigned(GB_hashdict) then
    GB_hashdict.Free;

  GB_hashdict := TObjectDictionary.CreateEx(nil, nil, true, False, False,
    ddIgnore);
  GB_hashdict.IsItemOwner := true;

  // SetLength(GB_MapFiles, GB_DEV_BASES.Count);

  // ShowMessage('    SetLength(GB_MapFiles,GB_DEV_BASES.Count);');

  SplashForm0 := TSplashForm.Create(nil);
  SplashForm0.Show;
  SplashForm0.Refresh;

  SplashForm0.RzProgressBar1.TotalParts := GB_Baselist.Keys.Count;

  // SplashForm0.AlphaBlendValue:=0;

  i := 0;

  for CurrentDP in GB_Baselist.Keys do
  begin
    if i = 5 then
      GB_Driverpack := @CurrentDP[1];

    // ShowMessage(GB_Driverpack);
    // if i=5 then

    // MessageBoxA(0,GB_Driverpack,nil,MB_OK);

    // GB_DEV_BASES.Add(CurrentDP + '=' + ExtractFileName(CurrentDP));
    // cavb:=AlphaBlendValue;       //
    SplashForm0.AlphaBlendValue := 128 +
      Round(i / (GB_Baselist.Keys.Count / 128));
    SplashForm0.AlphaBlend := true;

    SplashForm0.Label1.Caption := 'Loading' + #13 + ExtractFileName(CurrentDP);
    SplashForm0.RzProgressBar1.PartsComplete := i;
    Application.ProcessMessages;

    for currentBase in GB_Baselist.items[CurrentDP].Keys do
    begin

      GB_Baselist.items[CurrentDP].items[currentBase] :=
        TmappedFile.Create(currentBase);
      // ShowMessage(CurrentBase);
      // currentMapFile := GB_Baselist.Items[CurrentDP].Items[CurrentBase];

      Mycursor.Pointer := nil;
      Mycursor.Hasleft := 0;
      Mycursor.Pointer := GB_Baselist.items[CurrentDP].items
        [currentBase].Content;
      Mycursor.Hasleft := GB_Baselist.items[CurrentDP].items[currentBase].size;

      NewString := DB_GetLine(Mycursor);

      while NewString <> nil do
      begin
        if GB_hashdict.HasKey(NewString) then
        begin
          Driver0 := Tdriver.Create;
          // Driver0.DP := i;
          Driver0.DPack := @CurrentDP[1];

          (GB_hashdict.Item[NewString] as TDrivers).Add(Driver0);
          ParseFieldDriver(NewString, Driver0);
        end
        else
        begin
          MyDrivers := TDrivers.Create(true);
          Driver0 := Tdriver.Create;
          // Driver0.DP := i;
          Driver0.DPack := @CurrentDP[1];

          MyDrivers.Add(Driver0);
          ParseFieldDriver(NewString, Driver0);
          GB_hashdict.Add(NewString, MyDrivers);
        end;

        NewString := DB_GetLine(Mycursor);
      end;

    end; // for CurrentDp in GB_Baselist.items[CurrentDP].Keys do

    Inc(i);
  end; // for CurrentBase in GB_Baselist.Keys do

  // if GB_DEV_BASES.Count > 0 then
  GB_baseLoaded := true;

  SplashForm0.Hide;
  // showmessage(GB_DEV_BASES.Text)
end;

function GetDosOutput(const CommandLine: string): string;
var
  SA: TSecurityAttributes;
  SI: TStartupInfo;
  PI: TProcessInformation;
  StdOutPipeRead, StdOutPipeWrite: THandle;
  WasOK: boolean;
  Buffer: array [0 .. 255] of ansichar;
  BytesRead: Cardinal;
  WorkDir, Line: ansiString;
  k: Pansichar;
begin
  Application.ProcessMessages;
  with SA do
  begin
    nLength := sizeof(SA);
    bInheritHandle := true;
    lpSecurityDescriptor := nil;
  end;
  CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
  try
    with SI do
    begin
      FillChar(SI, sizeof(SI), 0);
      cb := sizeof(SI);
      dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
      wShowWindow := SW_HIDE;
      hStdInput := GetStdHandle(STD_INPUT_HANDLE);
      hStdOutput := StdOutPipeWrite;
      hStdError := StdOutPipeWrite;
    end;

    WorkDir := ExtractFilePath(CommandLine);
    WasOK := CreateProcess(nil, Pchar(CommandLine), nil, nil, true,
      CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, SI, PI);

    CloseHandle(StdOutPipeWrite);

    if not WasOK then
      raise Exception.Create('Could not execute command line!' +
        SysErrorMessage(GetLastError()))
    else
      try

        Line := '';
        repeat

          WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);

          if BytesRead > 0 then
          begin

            Buffer[BytesRead] := #0;

            Line := Line + Buffer;

          end;
        until not WasOK or (BytesRead = 0);

        WaitForSingleObject(PI.hProcess, INFINITE);
      finally

        CloseHandle(PI.hThread);
        CloseHandle(PI.hProcess);
      end;
  finally
    k := @Line[1];
    if pos(#10, k) > 0 then
      Inc(k, pos(#10, k));
    Result := AnsiReplaceStr(k, #13#10, '');
    // result:=k;
    // result:=Line;
    CloseHandle(StdOutPipeRead);
  end;
end;

function TUpdateThread.ExtractDPdir(Extractdir: string; ArchiveFilename: string;
  DPdir: string): Tstringlist;
var
  // AFormat: TJcl7zDecompressArchive;// DecompressArchiveClass;
  i: integer;
  posInf: integer;
  FArchive: TJcl7zDecompressArchive; // CompressionArchive;
begin
  Result := Tstringlist.Create;

  // AFormat := GetArchiveFormats.FindDecompressFormat(ArchiveFileName);

  // if AFormat <> nil then
  begin

    FArchive := TJcl7zDecompressArchive.Create(ArchiveFilename, 0, False);
    FArchive.OnProgress := ArchiveProgress;

    if FArchive is TJclDecompressArchive then
      TJclDecompressArchive(FArchive).ListFiles;
    // else
    // if FArchive is TJclUpdateArchive then
    // TJclUpdateArchive(FArchive). ListFiles;

    for i := 0 to FArchive.ItemCount - 1 do
    begin

      posInf := pos(AnsiUpperCase(DPdir),
        AnsiUpperCase(FArchive.items[i].PackedName));

      if posInf > 0 then
      begin
        Result.Add(FArchive.items[i].PackedName);
        // ShowMessage(FArchive.Items[i].PackedName);
        FArchive.items[i].Selected := true;
      end;
    end;

    if FArchive is TJcl7zDecompressArchive then
    begin
      try
        TJcl7zDecompressArchive(FArchive).ExtractSelected(Extractdir, true);
      except
      end;
    end
    // else
    // if FArchive is TJcl7zUpdateArchive then
    // begin
    // TJcl7zUpdateArchive(FArchive).ExtractSelected(Extractdir, True);
    // end
  end;
  // else
  // ShowMessage('Ôîðìàò Àðõèâà íå ïîääåðæèâàåòñÿ');
  // end;

  FreeAndNil(FArchive); // çàêðûòèå ÀÐÕÈÂÀ
end;

procedure TUpdateThread.SetLogStatus();
// var logitem:tlistitem;
begin
  try
    // logitem:=Loglist. Items.Add;
    // form1.Listlog.add . Items.Add;
    if LogStatus <> '' then
    begin
      TOLOG(TimeToStr(time) + #9 + LogStatus);
      // Loglist. Items.Add(TimeToStr(time)+#9+LogStatus);
      /// Test1.Add(TimeToStr(time) + #9 + LogStatus);
      // Test1..ItemIndex:=form1.JvComboBox1.items.count-1;
      // logitem.SubItems.Add(LogStatus);
      LogStatus := '';
      VTV.RepaintNode(Mynode);
    end
  except
  end;
  // Loglist. Items.Add('');

  // Loglist.ItemIndex:=Loglist.Count-1;

end;

{ procedure TUpdateThread.Setprogress();
  var k:integer;
  begin
  k:=round(myvalue /(myMaxValue/100)) ;

  Mydevice^.Driver_Progress:=k;

  if Mynode=nil then exit;
  if VTV=nil then exit;
  VTV.RepaintNode(Mynode);

  //mainlist.Items.Item[CurrentDriver].StateIndex:=k;

  end; }

procedure TUpdateThread.ArchiveProgress(Sender: TObject;
  const Value, MaxValue: Int64);
// var
var
  k: integer;
begin
  MyValue := Value;
  MyMaxValue := MaxValue;
  while MyMaxValue > High(word) do
  begin
    MyMaxValue := MyMaxValue shr 8;
    MyValue := MyValue shr 8;
  end;

  k := Round(MyValue / (MyMaxValue / 100));

  Mydevice^.Driver_Progress := k;

  if Mynode = nil then
    exit;
  if VTV = nil then
    exit;
  VTV.RepaintNode(Mynode);

  // Synchronize(Setprogress);

end;

procedure TUpdateThread.Execute();
label EX1;
var // i:integer;
  // newitem:tlistitem;
  // Dpack:string;
  Infpack: string;
  Dirs: Tstringlist;
  // logitem:tlistitem;
  Devcon_result: string;

begin
  Form1.ProgressBar1.Show;
  // Form1.Animation.Animate := true;
  // Form1.Animation.Show;

  Form1.TimerUnsigned.Enabled := true;
  // âêëþ÷åíèå òàéìåðà çàêðûòèÿ îêíà íåïîäïèñàííûõ äðîâ

  Mynode := VTV.GetFirstVisible(nil);

  if VTV.HasChildren[Mynode] then
    Mynode := VTV.GetNextVisible(Mynode);

  if Mynode = nil then
    exit;

  /// //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  /// //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  { if GB_Oem_install then
    CopyOEMfile; }

  if Mynode <> nil then
    repeat
      Mydevice := VTV.GetNodeData(Mynode);
      VTV.ScrollIntoView(Mynode, true, true);
      // for i:=0 to mainlist.Items.Count-1 do
      // Dpack:=mainlist.Items.Item[i].SubItems[2];

      // ShowMessage(IntToStr( Mydevice^.d dp);

      Mydevice^.Driver_status := 1;
      LogStatus := 'Extracting Driver.';
      // mydevice.Driver_NAME:='sdsdsdsd';
      Synchronize(SetLogStatus);

      // CurrentDriver:=i;
      // CurrentOperation:='Ðàñïàêîâêà äðàéâåðà =>';
      // Synchronize(SetFocus1);

      // ShowMessage(mydevice^.Driver_Pack);

      Dirs := ExtractDPdir(GB_TMPfolder, Mydevice^.Driver_Pack,
        Mydevice^.Driver_Dir);

      LogStatus := 'Extracted files: ' + IntToStr(Dirs.Count);
      Synchronize(SetLogStatus);

      Infpack := GB_TMPfolder + Mydevice^.Driver_Dir + Mydevice^.Driver_INF;

      LogStatus := 'Inf to install: ' + Infpack;
      // Synchronize(SetLogStatus);

      LogStatus := 'Installing: ' + Infpack;
      Synchronize(SetLogStatus);

      // CurrentOperation:='Óñòàíîâêà äðàéâåðà =>';
      Mydevice^.Driver_status := 2;
      VTV.RepaintNode(Mynode);
      // Synchronize(SetFocus1);

      Devcon_result := '';
      Devcon_result := GetDosOutput(GB_devcon + ' update "' + Infpack + '" "' +
        Mydevice^.Driver_HWID + '"');

      if pos('succes', Devcon_result) > 0 then
      begin
        CurrentOperation := 'Driver succesfly Installed.';
        Mydevice^.Driver_status := 3;
      end
      else
      begin
        CurrentOperation := 'Driver not Installed.';
        Mydevice^.Driver_status := 4;
      end;

      LogStatus := CurrentOperation;
      Synchronize(SetLogStatus);

      // Synchronize(SetFocus1);

      // Synchronize(SetLogStatus);
      // end;
      Mynode := VTV.GetNextVisible(Mynode);

      if VTV.HasChildren[Mynode] then
        Mynode := VTV.GetNextVisible(Mynode);
      if VTV.HasChildren[Mynode] then
        Mynode := VTV.GetNextVisible(Mynode);
    until (Mynode = nil);

EX1:
  // Inputlist.BringToFront;
  // Splitter.Percent:=100;
  // SetupButton.Enabled:=true;
  Form1.ProgressBar1.Hide;
  // Form1.Animation.Animate := False;
  // Form1.Animation.Hide;
  Form1.TimerUnsigned.Enabled := False;
  // âêëþ÷åíèå òàéìåðà çàêðûòèÿ îêíà íåïîäïèñàííûõ äðîâ
  // Terminate;
  // free;

  RefreshProcedure(self);
  // F5button.Click;
  // FreeAndNil(self);

  Terminate;
  WaitFor;
  // self:=nil;
  // form1.timer1.Enabled:=false;
  // form1.PaintBox1.Repaint;

end;

// Ôóíêöèÿ êîòîðàÿ çà ìåñòî çàïÿòîé ñòàâèò ïåðåâîä ñòðîêè.
function SetNormalHWIDS(input: ansiString): Tstringlist;
begin
  // if Assigned(Result) then
  // Result.Free;
  Result := Tstringlist.Create;
  Result.Duplicates := dupIgnore;
  Result.Sorted := true;

  input := Trim(input);
  input := AnsiReplaceStr(input, ' ', '');
  Result.Text := AnsiReplaceStr(input, ',', #13);

end;

// óäàëÿåò ïëîõèå õâèäû
procedure DeleteBADHWDIS(var input: Tstringlist);
var
  i: integer;
begin
  i := 0; // Óäàëÿåò ýëåìåíò åñëè íà âíà÷àëå íàõîäèò ñòðîêó PCI\CC_
  while i <= input.Count - 1 do
  begin
    if (pos('PCI\CC_', input.Strings[i]) > 0)
    { or
      (pos('VEN_',UpperCase( input.Strings[i]))=(length(input.Strings[i])-7)) }
    then
    begin
      input.Delete(i);
      Continue;
    end;

    Inc(i)
  end;
end;

function GetStringSAapi(DeviceListHandle: HDEVINFO;
  DeviceInfoData: SP_DEVINFO_DATA; PropertyCode: integer): ansiString;
var
  dwPropertyRegDataType, dwRequiredSize: DWORD;
begin
  Result := '';
  dwRequiredSize := 0;
  dwPropertyRegDataType := REG_SZ;
  SetupDiGetDeviceRegistryPropertyA(DeviceListHandle, DeviceInfoData,
    PropertyCode, dwPropertyRegDataType, nil, 0, dwRequiredSize);
  if not(dwPropertyRegDataType in [REG_SZ, REG_MULTI_SZ]) then
    exit;
  if GetLastError = ERROR_INSUFFICIENT_BUFFER then
  begin
    SetLength(Result, dwRequiredSize);
    SetupDiGetDeviceRegistryPropertyA(DeviceListHandle, DeviceInfoData,
      PropertyCode, dwPropertyRegDataType, @Result[1], dwRequiredSize,
      dwRequiredSize);
  end;
  case dwPropertyRegDataType of
    REG_SZ:
      Result := Pansichar(Result);
    REG_MULTI_SZ:
      Result := ExtractMultiString(Result);
  end;
end;

function GetGuidSapi(DeviceListHandle: HDEVINFO;
  DeviceInfoData: SP_DEVINFO_DATA; PropertyCode: integer): TGUID;
var
  dwPropertyRegDataType, dwRequiredSize: DWORD;
  StringGUID: ansiString;
begin
  ZeroMemory(@Result, sizeof(TGUID));
  StringGUID := GetStringSAapi(DeviceListHandle, DeviceInfoData, PropertyCode);
  if StringGUID = '' then
  begin
    dwRequiredSize := 0;
    dwPropertyRegDataType := REG_BINARY;
    SetupDiGetDeviceRegistryPropertyA(DeviceListHandle, DeviceInfoData,
      PropertyCode, dwPropertyRegDataType, nil, 0, dwRequiredSize);
    if GetLastError = ERROR_INSUFFICIENT_BUFFER then
    begin
      SetupDiGetDeviceRegistryPropertyA(DeviceListHandle, DeviceInfoData,
        PropertyCode, dwPropertyRegDataType, @Result, dwRequiredSize,
        dwRequiredSize);
    end;
  end
  else
    Result := StringToGUID(StringGUID);
end;

function DeviceClassDescription(DeviceTypeGUID: TGUID): ansiString;
var
  dwRequiredSize: DWORD;
begin
  Result := '';
  dwRequiredSize := 0;
  SetupDiGetClassDescriptionA(DeviceTypeGUID, nil, 0, @dwRequiredSize);
  if GetLastError = ERROR_INSUFFICIENT_BUFFER then
  begin
    SetLength(Result, dwRequiredSize);
    SetupDiGetClassDescriptionA(DeviceTypeGUID, @Result[1], dwRequiredSize,
      @dwRequiredSize);
  end;
  Result := Pansichar(Result);
end;

function FindRootNode(const DeviceClassName: String): TTreeNode;
var
  i: integer;
begin
  Result := nil;
  for i := 0 to Form1.tvDevices.items.Count - 1 do
    if Form1.tvDevices.items[i].Level = 0 then
      if Form1.tvDevices.items[i].Text = DeviceClassName then
      begin
        Result := Form1.tvDevices.items[i];
        break;
      end;
end;

procedure TForm1.FormCreate(Sender: TObject);
// var
// buff:array[0..512] of char;
// hkey1:HKEY;
// dwsize:DWORD;

var
  i: integer;
begin
  // test1.AutoSize:=true;

  Progress_INDEX.Text := 'Indexation in '#13'progress';
  Progress_INDEX.Hide;

  // try

  Application.ShowHint := true;

  // JvHint1.
  PageControl1.ActivePageIndex := 0;

  Bmp := TBitmap.Create;
  bmp2 := TBitmap.Create;

  // âðåìÿ ïîäñêàçêè
  Application.HintHidePause := 7000;
  // Application.HintColor:=RGB(255,250,219);
  Caption := Application.Title;

  // try
  InitializeGB(); // ôóíêöèÿ Èíèöèàëèçèðóåò Ãëîáàëüíûå ïåðåìåííûå
  // except showmessage('InitializeGB()'); end;

  CopyOEMfile;

  if GB_restorepoint then
    CreateRestorePoint();

  ModifyMenu(MainMenu1.Handle, OS_label.MenuIndex, MF_BYPOSITION or MF_HELP or
    MF_POPUP, OS_label.Handle, Pchar(OS_label.Caption));

  if GB_Write_allowed then
  begin
    checkDRPfolders();
    // CheckBases();
  end;

  // try
  LoadHashMAPS_OBJ;
  // except ShowMessage('Îøèáêà çàãðóçêè áàç!!') end;

  // except showmessage('Create'); end;
end;

function GetDPclasstype(dpname: string): integer;
var
  i: integer;
begin
  dpname := UpperCase(dpname);
  Result := 0;

  for i := low(DpStringTypes) to high(DpStringTypes) do
    if pos(DpStringTypes[i], dpname) > 0 then
    begin
      Result := DpStringResult[i];
      exit;
    end;

end;

function GETDP_OS(input: string): string;
var
  k: integer;
  res1, res2: integer;
const
  NT_BIT: array [0 .. 2] of string = ('X86', 'X32', 'X64');
  NT_WNT: array [0 .. 2] of string = ('WXP', 'WNT5', 'WNT6');
begin
  input := UpperCase(input);
  Result := '';
  res1 := -1;
  res2 := -1;

  for k := 0 to 2 do
    if pos(NT_BIT[k], input) > 0 then
      res1 := k;

  for k := 0 to 2 do
    if pos(NT_WNT[k], input) > 0 then
      res2 := k;

  if res2 in [0, 1] then
    Result := 'NT5'
  else
    Result := 'NT6';

  if res1 in [0, 1] then
    Result := Result + '_32BIT'
  else
    Result := Result + '_64BIT';

end;

procedure TIndexThread.Execute();
var
  Filelist: Tstringlist;
  L: integer;
  mymemo: Tstringlist;
  mymemoTEST: Tstringlist;
  OS_ByDP: ansiString;
  I_DP: integer;
  HasIndexed: boolean;
  CUR_int, i: integer;
  Dbname: string;
  // ALStrings: array [0 .. 5] of Tstringlist;
  emptyMANS: ansiString;

  source, dest: string;

  Current_INF: Tinf_dict;
  Current_hwid: ansiString;
  FileStreams: TDIctionary<ansiString, Tfilestream>;
  TypeOs: ansiString;
  FS: Tfilestream;
  bufer: ansiString;
  zeroEnd: array [0 .. 2] of ansichar;
  zero: array [0 .. 0] of ansichar;
  strDP: ansiString;
begin
  // Concat()
  zero := concat(#0);
  zeroEnd := concat(#0#13#10);

  Form1.ProgressBar1.Show;
  // Form1.Animation.Animate := true;
  // Form1.Animation.Show;
  // form1.timer1.Enabled:=true;//âêëþ÷åíèå òàéìåðà îòðèñîâêè àíèìàöèè
  IndexTime := time;

  CUR_int := 0;
  MyMaxValue2 := Myselected.Count;
  mymemoTEST := Tstringlist.Create;

  HasIndexed := False;

  for I_DP := 0 to Myselected.Count - 1 DO
  BEGIN
    CurrentDP := I_DP;

    CurrentNode := Pointer(Myselected.Objects[I_DP]);
    CurrentData := Form1.VST_DP.GetNodeData(CurrentNode);
    Form1.VST_DP.ScrollIntoView(CurrentNode, true, true);
    // Synchronize(GetNodeData);
    CurrentData.isextracting := true;
    // ShowMessage(Myselected.Strings[I_DP]);

    Inc(CUR_int);

    MyValue2 := CUR_int - 1;
    Synchronize(Setprogress);
    // ShowMessage('111');
    // CurrentDP:=StrToInt(Myselected.ValueFromIndex[I_DP]);
    Synchronize(SetFocus);

    CurrentStatus := '[1] Ðàñïàêîâêà: ' +
      ExtractFileName(Myselected.Strings[I_DP]);

    // try

    // Filelist:=ExtractInf(TMPfolder ,FIlearchive);

    Filelist := ExtractInf(GB_TMPfolder + CurrentData.name + '\',
      Myselected.Strings[I_DP]);

    // Filelist:=ExtractInf(GB_TMPfolder,GB_Appdir+ListView1.items.Item[I_DP].SubItems.Strings[0]+'\'+ListView1.items.Item[I_DP].Caption);
    { except
      showmessage('Îøèáêà ðàñïàêîâêè !!!'+#13+'Âûõîä èç ïðîöåäóðû !!!');
      memo1.Lines.Add('Îøèáêà ðàñïàêîâêè !!! Âûõîä èç ïðîöåäóðû !!!');
      exit;
      end; }

    CurrentStatus := '[2] Èíäåêñàöèÿ INF ôàéëîâ ïàêåòà: ' +
      ExtractFileName(Myselected.names[I_DP]);

    mymemo := Tstringlist.Create;
    // mymemo.Add('Version5;');

    // Dbname:=GB_DevDB+ExtractFileName(SET_DP_OS(Myselected.names[I_DP]));
    // Dbname := GB_DevDB + ChangeFileExt(ExtractFileName(Myselected.Strings[I_DP]
    // ), INI_ext);

    // ShowMessage(dbname);
    // INI1:=TIniFile.Create(dbname);
    // INI2:=TMemIniFile.Create(dbname);
    // ini2.
    OS_ByDP := GETDP_OS(ExtractFileName(Myselected.Strings[I_DP]));
    // ShowMessage('2222');
    // for i := 0 to 5 do
    // ALStrings[i] := Tstringlist.Create;

    FileStreams := TDIctionary<ansiString, Tfilestream>.Create;

    MyMaxValue := Filelist.Count;
    CurrentData.isextracting := False;
    for L := 0 to Filelist.Count - 1 do
    begin
      MyValue := L + 1;
      Synchronize(Setprogress);

      // emptyMANS := '';
      // IndexInfwithEmptyMFG(ALStrings, GB_TMPfolder, Filelist.Strings[L], OS_ByDP,emptyMANS);
      Current_INF := NewIndexInf(GB_TMPfolder + '\' + CurrentData.name + '\',
        Filelist.Strings[L]);
      // tolog(Filelist.Strings[L]);

      if Current_INF <> nil then
        for TypeOs in Current_INF.Keys do
        begin
          if FileStreams.ContainsKey(TypeOs) then
            FS := FileStreams.items[TypeOs]
          else
          begin
            Dbname := GB_DevDB + ExtractFileName(Myselected.Strings[I_DP]) + '\'
              + TypeOs + INI_ext;

            // ShowMessage(Dbname);
            ForceDirectories(ExtractFileDir(Dbname));
            FS := Tfilestream.Create(Dbname, fmCreate + fmOpenWrite);

            FileStreams.Add(TypeOs, FS);

          end;

          for Current_hwid in Current_INF.items[TypeOs].Keys do
          begin
            // fs.Seek(0,soEnd);
            FS.Write(Current_hwid[1], length(Current_hwid));
            FS.Write(zero, sizeof(zero));

            FS.Write(Current_INF.items[TypeOs].items[Current_hwid].DRV_infdir
              [1], length(Current_INF.items[TypeOs].items[Current_hwid]
              .DRV_infdir));
            FS.Write(zero, sizeof(zero));

            FS.Write(Current_INF.items[TypeOs].items[Current_hwid].DRV_filename
              [1], length(Current_INF.items[TypeOs].items[Current_hwid]
              .DRV_filename));
            FS.Write(zero, sizeof(zero));

            FS.Write(Current_INF.items[TypeOs].items[Current_hwid].DRV_MFG[1],
              length(Current_INF.items[TypeOs].items[Current_hwid].DRV_MFG));
            FS.Write(zero, sizeof(zero));

            FS.Write(Current_INF.items[TypeOs].items[Current_hwid].DRV_Date[1],
              length(Current_INF.items[TypeOs].items[Current_hwid].DRV_Date));
            FS.Write(zero, sizeof(zero));

            FS.Write(Current_INF.items[TypeOs].items[Current_hwid].DRV_Ver[1],
              length(Current_INF.items[TypeOs].items[Current_hwid].DRV_Ver));
            FS.Write(zero, sizeof(zero));

            FS.Write(Current_INF.items[TypeOs].items[Current_hwid].DRV_NAME[1],
              length(Current_INF.items[TypeOs].items[Current_hwid].DRV_NAME));
            // FS.Write(zero, sizeof(zero));

            FS.Write(zeroEnd, sizeof(zeroEnd));
          end;

        end;


      // for Current_hwid in Current_INF.Keys. do

      // NewIndexInf


      // if emptyMANS <> '' then
      // mymemoTEST.Add(emptyMANS);
      // mymemoTEST.add(Myselected.Strings[I_DP]+'='+Filelist.Strings[L]);

      // IndexInf(DictHASH,GB_TMPfolder,Filelist.Strings[L]);
    end;

    // for i := 0 to 5 do
    // if ALStrings[i].Count > 0 then
    // begin
    // // ALStrings[i].Duplicates:=dupAccept;
    // // ALStrings[i].Sort;
    //
    // mymemo.Add('[' + NT_ALL[i] + ']' + #0);
    // mymemo.AddStrings(ALStrings[i]);
    // end;
    //
    // mymemo.SaveToFile(Dbname);

    // FreeAndNil(IndexList);
    // Synchronize(SetUchecked);

    for strDP in FileStreams.Keys do
      FileStreams.items[strDP].Free;

    FileStreams.Free;

    HasIndexed := true;
    CurrentData.indexed := true;
    Form1.VST_DP.InvalidateNode(CurrentNode);
  END; // öèêë çàêðûòèÿ äðàéâåð ïàêîâ

  // mymemoTEST.SaveToFile('C:\EMPTY MFG.txt');

  { for I := 0 to mymemotest.count-1 do
    begin
    ForceDirectories(ExtractFilePath('C:\DX\'+ExtractFileName(mymemoTEST.Names[I])+'\'+mymemoTEST.ValueFromIndex[I]));
    source:=GB_TMPfolder+mymemoTEST.ValueFromIndex[I];
    dest:='c:\DX\'+ExtractFileName(mymemoTEST.Names[I])+'\'+mymemoTEST.ValueFromIndex[I];
    Copyfile(pwidechar(source),pwidechar(dest),true);
    end;
  }

  mymemoTEST.SaveToFile('C:\All MFG.txt');

  if HasIndexed then
  begin
    CurrentStatus := '[4] Óäàëåíèå âðåìåííîé ïàïêè. DriverX';
    // RemoveFolder2(GB_TMPfolder);
    IndexTime := IndexTime - time;
    // ShowMessage('HIE BUG');
    Synchronize(SetTHEend);

    // Synchronize(SetFillDrpList2);

    Form1.FillDRPLIST3; //
    LoadHashMAPS_OBJ;
  end;

  // form1.timer1.Enabled:=false;
  // form1.PaintBox1.Repaint;

  // form1.IndexTime.Caption:=

end;

procedure TForm1.Label2Click(Sender: TObject);
begin
  ShellExecute(0, Pchar('open'), Pchar('http://WWW.DTS.Idhost.KZ'), Nil,
    Nil, SW_SHOW);
  // OpenPage(self, 'http://dts.idhost.kz/download.php#');

end;

Function BaseExist2(base: string): boolean;
var
  // i:integer;
  BaseTX: string;
begin
  // ShowMessage(base);
  // For i:=3 downto 1 do
  // if pos(GB_DRP_DIRS[0]+'\'+GB_DRP_DIRS[i]+'\',base)>0 then
  // begin
  // ShowMessage(GB_DRP_DIRS[0]+'\'+GB_DRP_DIRS[i]+'\'+#13+base);

  // BaseTX := ChangeFileExt(base, INI_ext);
  BaseTX := GB_DevDB + ExtractFileName(base);
  // ShowMessage(BaseTX);
  // ShowMessage(ExtractFileName(BaseTX));
  // ShowMessage(BaseTX);

  // break;
  // end;

  Result := DirectoryExists(BaseTX);

end;

procedure TIndexThread.Setprogress();
// var
// k:^integer;
begin

  // if Assigned(Currentdata) then
  CurrentNode := Pointer(Myselected.Objects[CurrentDP]);
  CurrentData := Form1.VST_DP.GetNodeData(CurrentNode);

  // try
  if (MyValue > 0) and (MyMaxValue > 0) then

    CurrentData.progress := Round(MyValue / (MyMaxValue / 100));
  // except
  // end;
  Form1.VST_DP.RepaintNode(CurrentNode);

  // try
  /// k:=form1.ListView1.Items.Item[CurrentDP].Data;
  // form1.ListView1.Items.Item[CurrentDP].StateIndex:=round(MyValue/(MyMaxValue/100));
  // except end;//ShowMessage('Max'+IntToStr(MyMaxValue)+'  val'+IntToStr(MyValue)) end;
  // form1.ListView1.Canvas.i Invalidate;

  Form1.Progress_INDEX.MaxValue := MyMaxValue2;
  Form1.Progress_INDEX.progress := MyValue2;
end;

procedure TIndexThread.GetNodeData;
begin
  // sss
  // if Myselected.Objects[CurrentDP]<>nil then
  // showmessage('sasss');
  // CurrentNode:=pointer(Myselected.Objects[CurrentDP]);

  // CurrentData := form1.VST_DP.GetNodeData(CurrentNode);

end;

procedure TIndexThread.SetFocus();
begin
  // form1.ListView1.ItemIndex:=CurrentDP;
  // form1.ListView1.Items.Item[CurrentDP].MakeVisible(true);

  // form1.VST_DP.ScrollIntoView(CurrentNode,true,true);

  { for i:=0 to SelectedStrings.Count-1 do
    begin
    NextNode:=pointer(SelectedStrings.Objects[i]);
    PhoneNode := VST_DP.GetNodeData(NextNode);
    VST_DP.ScrollIntoView(NextNode,true,true);
    for L:=1 to 10 do
    begin
    PhoneNode.progress:=round(L*10);
    VST_DP.RepaintNode(NextNode);
    Application.ProcessMessages;
    sleep(200);
    end;
    end; }
end;

procedure TIndexThread.SetTHEend();
begin
  // Form1.ListBox1.items.Add();
  TOLOG(TimeToStr(time) + #9 + 'Spent Indexation time: ' +
    TimeToStr(IndexTime));
  // form1.JvComboBox1.ItemIndex:=form1.JvComboBox1.Items.Count-1;
  Form1.ProgressBar1.Hide;
  // Form1.Animation.Animate := False;
  // Form1.Animation.Hide;
  Form1.RzBitBtn11.Hide;
  Form1.Progress_INDEX.Hide;
  Form1.RzBitBtn12.Enabled := true;
  Form1.RzBitBtn10.Show;
end;

procedure TIndexThread.ArchiveProgress(Sender: TObject;
  const Value, MaxValue: Int64);
// var

begin
  MyValue := Value;
  MyMaxValue := MaxValue;
  while MyMaxValue > High(word) do
  begin
    MyMaxValue := MyMaxValue shr 8;
    MyValue := MyValue shr 8;
  end;
  // ProgressBar1.Max := MyMaxValue;
  // ProgressBar1.Position := MyValue;


  // Gauge1.MaxValue := MyMaxValue;
  // Gauge1.Progress := MyValue;

  Synchronize(Setprogress);

end;

function TIndexThread.ExtractInf(Extractdir: string; ArchiveFilename: string)
  : Tstringlist;
var
  AFormat: TJclDecompressArchiveClass;
  i: integer;
  posInf: integer;
  FArchive: TJclCompressionArchive;

begin
  Result := Tstringlist.Create;

  AFormat := GetArchiveFormats.FindDecompressFormat(ArchiveFilename);

  if AFormat <> nil then
  begin

    FArchive := AFormat.Create(ArchiveFilename, 0, False);
    FArchive.OnProgress := ArchiveProgress;

    if FArchive is TJclDecompressArchive then
      TJclDecompressArchive(FArchive).ListFiles
    else if FArchive is TJclUpdateArchive then
      TJclUpdateArchive(FArchive).ListFiles;

    for i := 0 to FArchive.ItemCount - 1 do
    begin

      if ExtractFileExt(AnsiUpperCase(FArchive.items[i].PackedName)) = '.INF'
      then
      begin
        Result.Add(FArchive.items[i].PackedName);
        FArchive.items[i].Selected := true;
      end;
    end;

    if FArchive is TJclDecompressArchive then
    begin
      TJclDecompressArchive(FArchive).ExtractSelected(Extractdir, true);
    end
    else if FArchive is TJclUpdateArchive then
    begin
      TJclUpdateArchive(FArchive).ExtractSelected(Extractdir, true);
      // Application.ProcessMessages;
    end
  end
  else
    ShowMessage('Ôîðìàò Àðõèâà íå ïîääåðæèâàåòñÿ');

  FreeAndNil(FArchive); // çàêðûòèå ÀÐÕÈÂÀ
end;

function Write_allowed(): boolean;
var
  TFS: Tfilestream;
  Lockname: string;
begin
  Lockname := ParamStr(0) + '.lock';
  // Result:=false;
  try
    TFS := Tfilestream.Create(Lockname, fmCreate or fmOpenWrite);
    Result := true;
  except
    Result := False;
  end;

  // TFS.Write('Write_allowed',14);

  // except
  // ShowMessage('finally');
  if Assigned(TFS) then
    TFS.Free;
  DeleteFile(Lockname);
  // end;
  // ShowMessage('END');
end;

function Check_Write(): boolean;
begin
  Result := GB_Write_allowed;

  if not(GB_Write_allowed) then
    MessageDlg('Çàïèñü íåäîñòóïíà'#13'Ïîïðîáóéòå çàïóñòèòü ñ äð. íîñèòåëÿ!',
      mtError, [mbOk], 0);

end;

procedure TForm1.InitializeGB();
var
  VI: TOSVersionInfo;
  Ininfile: TIniFile;
  osemul: string;
begin
  try
    GB_Write_allowed := Write_allowed();
  except
  end;
  // except ShowMessage('KABOO') end;
  // then ShowMessage('W ALOWED');

  GB_Oses := Tstringlist.Create;

  GB_Oses.Add('5.1=Windows XP');
  GB_Oses.Add('6.0=Windows Vista');
  GB_Oses.Add('6.1=Windows 7');
  GB_Oses.Add('6.2=Windows 8');

  GB_Appdir := ExtractFileDir(ParamStr(0));
  GB_TMPfolder := GetTempDirectory() + 'DriverX\';
  GB_64bit := IsOnWow64;

  VI.dwOSVersionInfoSize := sizeof(TOSVersionInfo);
  GetVersionEx(VI);
  GB_Major := VI.dwMajorVersion;
  GB_Minor := VI.dwMinorVersion;

  OS_label.Caption := ('Windows ' + IntToStr(VI.dwMajorVersion) + '.' +
    IntToStr(VI.dwMinorVersion) + ' ' + VI.szCSDVersion + ' Build:' +
    IntToStr(VI.dwBuildNumber));

  if GB_64bit then
    OS_label.Caption := OS_label.Caption + '  64-BIT'
  else
    OS_label.Caption := OS_label.Caption + ' X86 (32-BIT)';

  if GB_64bit then
    GB_devcon := '.\tools\devcon64.exe'
  else
    GB_devcon := '.\tools\devcon.exe';

  // ShowMessage(GB_Appdir);
  GB_INI_PATH := GB_Appdir + '\tools\driverX.ini';
  // ShowMessage(GB_INI_PATH);
  GB_IGNORE := Tstringlist.Create;

  if FileExists(GB_INI_PATH) then
  begin

    Ininfile := TIniFile.Create(GB_INI_PATH);
    GB_DRP_DIR := UpperCase(Ininfile.Readstring('Path', 'DRPDIR', 'DRP'));

    GB_IGNORE.Text := UpperCase(Ininfile.Readstring('window', 'IGNORELS', ''));
    GB_IGNORE.Text := AnsiReplaceStr(GB_IGNORE.Text, ',', #13#10);

    GB_DevDB := GB_Appdir + '\' + Ininfile.Readstring('Path', 'DEV_DB',
      'DEV_DB') + '\';

    TabSheet2.TabVisible := Ininfile.ReadBool('window', 'devmanager', true);
    N7.Checked := TabSheet2.TabVisible;

    TabSheet5.TabVisible := Ininfile.ReadBool('window', 'updatebase', true);
    N8.Checked := TabSheet5.TabVisible;

    ShowDP.Checked := Ininfile.ReadBool('Window', 'DP-HWIDS', False);

    GB_1HWID := Ininfile.ReadBool('EXPERT', '1hwid', False);
    GB_restorepoint := Ininfile.ReadBool('EXPERT', 'Restorepoint', False);
    GB_Oem_install := Ininfile.ReadBool('EXPERT', 'OEM_install', False);

    RzCheckGroup2.OnChange := nil;
    RzCheckGroup1.OnChange := nil;
    RzCheckGroup2.ItemChecked[0] := Ininfile.ReadBool('VIEW',
      'SetupDubles', False);
    RzCheckGroup1.ItemChecked[0] := Ininfile.ReadBool('VIEW',
      'UpdateInstalled', False);
    RzCheckGroup1.ItemChecked[1] := Ininfile.ReadBool('VIEW',
      'UpdateDubles', False);

    RzCheckGroup1.OnChange := RzCheckGroup1Change;
    RzCheckGroup2.OnChange := RzCheckGroup2Change;

    GB_toEmulate := Ininfile.ReadBool('emulation', 'Emulate', False);

    if GB_toEmulate then
    begin
      GB_64bit := boolean(Ininfile.readInteger('emulation', 'Arch', 0));
      GB_Major := strtoint(Ininfile.Readstring('emulation', 'System',
        '5.1')[1]);

      GB_Minor := strtoint(Ininfile.Readstring('emulation', 'System',
        '5.1')[3]);

      osemul := Ininfile.Readstring('emulation', 'System', '5.1');

      OS_label.Caption := 'EMULATION >>>>:' + GB_Oses.ValueFromIndex
        [GB_Oses.IndexOfName(osemul)] + ' ' + GB_Oses.names
        [GB_Oses.IndexOfName(osemul)];

      if GB_64bit then
        OS_label.Caption := OS_label.Caption + '  64-BIT'
      else
        OS_label.Caption := OS_label.Caption + ' X86 (32-BIT)';

    end;

  end
  else // if FileExists(GB_ini_path) then
    if GB_Write_allowed then
    begin
      ForceDirectories(ExtractFilePath(GB_INI_PATH));
      Ininfile := TIniFile.Create(GB_INI_PATH);
      Ininfile.WriteString('Path', 'DRPDIR', 'DRP');
      Ininfile.WriteString('Path', 'DEV_DB', 'DEV_DB');

      Ininfile.WriteString('window', 'IGNORELS', '');

      GB_DRP_DIR := Ininfile.Readstring('Path', 'DRPDIR', 'DRP');

      GB_DevDB := GB_Appdir + '\' + Ininfile.Readstring('Path', 'DEV_DB',
        'DEV_DB') + '\';

    end;

  // GB_DevDB:=GB_Appdir+'\DEV_DB\';
  if GB_Write_allowed then
    if not(FileExists(GB_DevDB)) then
      CreateDir(GB_DevDB);




  // GB_DriverList := GetDeviceList();

  if Assigned(Ininfile) then
    Ininfile.Free;

end;

procedure TForm1.FormShow(Sender: TObject);
var
  cnt: integer;
begin
  cnt := 0;
  ProgressBar1.Hide;


  // Button8Click(sender);

  // Btn3Click(Sender);
  // Button7Click(sender);
  // BitBtn1Click(sender);
  cnt := FillDRPLIST3();
  if cnt > 0 then
    if mrYes = MessageDlg(IntToStr(cnt) +
      ' Драйверпак(ов) не проиндесированы'#13'Вы хотите проиндесировать пакеты ?',
      mtConfirmation, [mbYes, mbNo], 0) then
    begin
      PageControl1.ActivePage := TabSheet5;
      TabSheet5.Show;
      RzBitBtn9.Click;
      RzBitBtn10.Click;

    end;

end;

procedure TForm1.Button7Click(Sender: TObject);
var
  i, L, X: integer;
  curS: Tstringlist;
  cur: ansiString;

  obj: TDrivers;
  tick1: DWORD;
  Cur_DR_list: TDrivers;
  // cur_index:TDriverIndex;
  // IS_ADDED:boolean;
  Mydevice: Pdevice;
  Mynode: PVirtualNode;
begin
  if not(Sender is TThread) then
    if UpdateThread1 <> nil then
      if not(UpdateThread1.Terminated) then
        exit;

  if GB_hashdict.Count = 0 then
    exit;
  // Application.ProcessMessages;
  if Assigned(GB_DriverList) then
    GB_DriverList.Free;

  ShortDateFormat := 'MM/DD/YYYY';
  DateSeparator := '/';

  tick1 := GetTickCount;
  GB_DriverList := GetDeviceList;


  // tick1:=GetTickCount-tick1;
  // JvComboBox1.Items.Add();

  VTV_setup.Clear;
  VTV_setup.NodeDataSize := sizeof(TDevice);

  // Application.ProcessMessages;
  VTV_setup.BeginUpdate;
  // MemoUpdate.Lines.BeginUpdate;
  for i := 0 to GB_DriverList.Count - 1 do
    if GB_DriverList.items[i].Problem in [1, 10, 28, 39, 31] then
      if length(GB_DriverList.items[i].SPDRP_HARDWAREID) > 0 then
      begin

        cur := GB_DriverList.items[i].SPDRP_HARDWAREID;
        if length(GB_DriverList.items[i].SPDRP_COMPATIBLEIDS) > 0 then
          cur := cur + ',' + GB_DriverList.items[i].SPDRP_COMPATIBLEIDS;
        if length(GB_DriverList.items[i].MatchingDeviceId) > 0 then
          cur := cur + ',' + GB_DriverList.items[i].MatchingDeviceId;

        curS := SetNormalHWIDS(cur);

        Cur_DR_list := TDrivers.Create;

        // ShowMessage('11');

        // Ïîèñê è äîáàâëåíèå Óòñðîéñòâ â Cur_DR_list
        for L := curS.Count - 1 downto 0 do
        begin

          obj := TDrivers(GB_hashdict.Item[curS.Strings[L]]);
          if Assigned(obj) then
            for X := 0 to obj.Count - 1 do
            begin
              try
                Cur_DR_list.Add2(obj.items[X]).Hwid :=
                  Pansichar(curS.Strings[L]);

              except
                ShowMessage('EX1');
              end;
            end;
        end;
        Cur_DR_list.SortbyVER;

        if Cur_DR_list.Count > 0 then
          for X := 0 to Cur_DR_list.Count - 1 do
          begin

            Mynode := AddVSTDevice(VTV_setup, nil, Cur_DR_list.items[X],
              Mydevice, RzCheckGroup2.ItemChecked[0]);
            // Mydevice.Driver_image :=
            // GetDPclasstype(GB_DEV_BASES.names[Cur_DR_list.Items[X].DP]);
            Mydevice.Device_index := i;
            // Mydevice.Driver_Pack := GB_DEV_BASES.ValueFromIndex
            // [Cur_DR_list.Items[X].DP];
            Mydevice.Device_date :=
              DateToStr(GB_DriverList.items[i].DriverDate);
            Mydevice.Device_Ver := GB_DriverList.items[i].DriverVersion;
            Mydevice.Device_HWID := GB_DriverList.items[i].SPDRP_HARDWAREID;
            Mydevice.Driver_Progress := 0;
            VTV_setup.InvalidateNode(Mynode);

            if (RzCheckGroup2.ItemChecked[0] = False) then
              break;

          end
        else // Åñkè óñòðîéñòâà íåò â Áàçå!!!
        begin

          Mynode := VTV_setup.AddChild(nil);
          Mydevice := VTV_setup.GetNodeData(Mynode);

          if GB_DriverList.items[i].SPDRP_FRIENDLYNAME <> '' then
            Mydevice.Driver_NAME := GB_DriverList.items[i].SPDRP_FRIENDLYNAME;

          if GB_DriverList.items[i].SPDRP_DEVICEDESC <> '' then
            Mydevice.Driver_NAME := GB_DriverList.items[i].SPDRP_DEVICEDESC;

          // Mydevice.Driver_NAME:='Îòñóòñâóåò â Áàçå';

          Mydevice.Driver_ver := 'Îòñóòñâóåò â Áàçå';
          Mydevice.Driver_HWID := GB_DriverList.items[i].SPDRP_HARDWAREID;
          Mydevice.Device_HWID := Mydevice.Driver_HWID;

          Mydevice.Driver_image := 19;
          // GetDPclasstype(GB_DEV_BASES.names[Cur_DR_list.Items[X].DP]);
          Mydevice.Device_index := i;
          // Mydevice.Driver_Pack:=GB_DEV_BASES.ValueFromIndex[Cur_DR_list.Items[X].DP];
          // Mydevice.Device_date:=DateToStr(GB_DriverList.Items[i].DriverDate);
          // Mydevice.Device_Ver:=GB_DriverList.Items[i].DriverVersion;
          // Mydevice.Device_HWID:=GB_DriverList.Items[i].SPDRP_HARDWAREID;
          Mydevice.Driver_Progress := 0;

          VTV_setup.ValidateNode(Mynode, False);

          VTV_setup.ReinitNode(Mynode, False);
          VTV_setup.InvalidateNode(Mynode);
        end;

        Cur_DR_list.Free;

      end;

  VTV_setup.EndUpdate;
end;

procedure TForm1.N4Click(Sender: TObject);
begin
  ShellExecute(0, Pchar('open'), Pchar('devmgmt.msc'), '', Nil, SW_SHOW);

end;

procedure TForm1.N2Click(Sender: TObject);
begin
  close;
end;

function CheckThreadIsAlive(Thread: TThread): boolean;
begin
  Result := WaitForSingleObject(Thread.Handle, 0) = WAIT_OBJECT_0;
end;

function Is2realyonger(D1: tdate; D2: Pansichar): boolean;
var
  date2: tdate;
begin
  // try
  // if (GB_DriverList.Items[i].DriverDate <=StrToDate( Cur_DR_list.Items[X].Date)) then  Is_added:=true

  ShortDateFormat := 'MM/DD/YYYY';
  DateSeparator := '/';

  if length(D2) > 2 then
    date2 := StrToDate(D2)
  else
    date2 := 0;

  if D1 < date2 then
    Result := true
  else
    Result := False;
end;

function Is2yonger(D1: tdate; D2: Pansichar): boolean;
var
  date2: tdate;
begin
  // try
  // if (GB_DriverList.Items[i].DriverDate <=StrToDate( Cur_DR_list.Items[X].Date)) then  Is_added:=true

  ShortDateFormat := 'MM/DD/YYYY';
  DateSeparator := '/';

  if length(D2) > 2 then
    date2 := StrToDate(D2)
  else
    date2 := 0;

  if D1 <= date2 then
    Result := true
  else
    Result := False;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  i, L, X: integer;
  curS: Tstringlist;
  cur: ansiString;

  obj: TDrivers;
  /// tick1:dword;
  Cur_DR_list: TDrivers;
  // cur_index:TDriverIndex;
  // NewItemDevice:Tlistitem;
  IS_ADDED: boolean;
  // DATA_Index:^integer;
  // Index_D:integer;
  Ils: integer;
  times: DWORD;
  // times_ALL:dword;

  Bydate, Larger2: boolean;
  Mydevice: Pdevice;

  DP_node: PVirtualNode;
  DP_data: Pdevice;

begin
  // memo1.Clear;
  // Ïðîâåðêà ðàáî÷åãî ïîòîêà åñëè ïîòîê ðàáîòàåò
  // òî íå îáíîâëÿåì ñïèñîê, à âûõîäèì èç ïðîöåäóðû
  if not(Sender is TThread) then
    if UpdateThread2 <> nil then
      if not(UpdateThread2.Terminated) then
        exit;

  ShortDateFormat := 'MM/DD/YYYY';
  DateSeparator := '/';

  // try
  { if GB_hashdict.Count = 0 then
    ShowMessage('haskdict 0');
  }
  times := GetTickCount;

  if LoadDevices1.Checked then
  begin
    GB_DriverList.Clear;
    GB_DriverList.Loadfromfile('c:\devices.ini');
  end
  else
    GB_DriverList := GetDeviceList;

  // ShowMessage(IntToStr(GB_DriverList.Count));

  // ShowMessage(GB_DriverList.Items[55].SPDRP_HARDWAREID);
  times := GetTickCount - times;

  StaticText1.Caption := IntToStr(times);

  VTV_update.Clear;
  VTV_update.NodeDataSize := sizeof(TDevice);

  VTV_update.BeginUpdate;

  for i := 0 to GB_DriverList.Count - 1 do
    if not(GB_DriverList.items[i].Problem in [1, 10, 28]) and
      (length(GB_DriverList.items[i].SPDRP_HARDWAREID) > 0) then
    begin

      cur := GB_DriverList.items[i].SPDRP_HARDWAREID;
      if length(GB_DriverList.items[i].SPDRP_COMPATIBLEIDS) > 0 then
        cur := cur + ',' + GB_DriverList.items[i].SPDRP_COMPATIBLEIDS;
      if length(GB_DriverList.items[i].MatchingDeviceId) > 0 then
        cur := cur + ',' + GB_DriverList.items[i].MatchingDeviceId;

      curS := SetNormalHWIDS(cur);
      DeleteBADHWDIS(curS);

      // if i=27 then
      { begin
        memo1.Lines.Add(IntToStr(I)+'  '+GB_DriverList.Items[i].SPDRP_DEVICEDESC +' '+cur);

        end; }

      { if GB_DriverList.Items[i].SPDRP_FRIENDLYNAME<>'' then
        memo1.Lines.add(GB_DriverList.Items[i].SPDRP_FRIENDLYNAME)
        else
        memo1.Lines.add(GB_DriverList.Items[i].SPDRP_DEVICEDESC); }


      // memo1.Lines.add(curs.Text);

      // Ïðîâåðêà åñòü âåðñèÿ äðàéâåðà ó óñòðîéñòâà
      Bydate := False;
      if length(GB_DriverList.items[i].DriverVersion) < 1 then
        Bydate := true;

      // Óäàëÿåì ÕÂÈÄÛ êîòîðûå âõîäÿò â Èãíîð Ëèñò.
      for Ils := 0 to GB_IGNORE.Count - 1 do
        if curS.IndexOf(GB_IGNORE.Strings[Ils]) > -1 then
        begin
          curS.Delete(curS.IndexOf(GB_IGNORE.Strings[Ils]));
        end;

      Cur_DR_list := TDrivers.Create;

      // Ïîèñê è äîáàâëåíèå Óòñðîéñòâ â Cur_DR_list
      for L := curS.Count - 1 downto 0 do
      begin

        obj := TDrivers(GB_hashdict.Item[curS.Strings[L]]);
        if Assigned(obj) then
          for X := 0 to obj.Count - 1 do
            Cur_DR_list.Add2(obj.items[X]);

      end;

      // memo1.Lines.Add('STEP 1');

      { for X:=0 to Cur_DR_list.count-1 do
        begin
        memo1.Lines.Add(IntToStr(I)+' '+Cur_DR_list.Items[x].Date);

        end; }
      // try
      // åñëè âåðñèè íåò òî òåêóùèé ñïèñîê äëÿ óñòðîñòâà äîëæåí ñîðòèðîâàòñÿ ïî äàòå.
      if Bydate then
        Cur_DR_list.SortByDate
      else
        Cur_DR_list.SortbyVER;

      // memo1.Lines.Add('STEP 2');

      // except end;

      DP_node := nil;
      if Cur_DR_list.Count > 0 then
        for X := 0 to Cur_DR_list.Count - 1 do
        begin
          IS_ADDED := False;
          Larger2 := False;
          Larger2 := Is2Larger(GetTver(GB_DriverList.items[i].DriverVersion),
            GetTver(Cur_DR_list.items[X].Ver));

          // try
          case RzCheckGroup1.ItemChecked[0] of
            /// ////////////////////////////////////////////////
            true:
              begin
                if Bydate then
                begin
                  if Is2yonger(GB_DriverList.items[i].DriverDate,
                    Cur_DR_list.items[X].Date) then
                    IS_ADDED := true
                end
                else if not(Larger2) then
                  IS_ADDED := true;
              end;
            /// /////////////////////////////////////////////////
            False:
              begin
                if Bydate then
                begin
                  if not(Is2realyonger(GB_DriverList.items[i].DriverDate,
                    Cur_DR_list.items[X].Date)) then
                    IS_ADDED := true
                end
                else if Larger2 then
                  IS_ADDED := true;
              end

          end; // END CASE
          // except  end;

          if IS_ADDED then
          begin

            if (RzCheckGroup1.ItemChecked[1]) then
            begin
              if not(Assigned(DP_node)) then
              begin
                DP_node := VTV_update.AddChild(nil);
                DP_node.CheckType := ctCheckBox;
                DP_data := VTV_update.GetNodeData(DP_node);
                if GB_DriverList.items[i].SPDRP_FRIENDLYNAME <> '' then
                  DP_data.Driver_NAME := GB_DriverList.items[i]
                    .SPDRP_FRIENDLYNAME
                else
                  DP_data.Driver_NAME := GB_DriverList.items[i]
                    .SPDRP_DEVICEDESC;
                // DP_data.Driver_NAME:=ExtractFilename(GB_DEV_BASES.ValueFromIndex[Cur_DR_list.Items[X].DP]);
                VTV_update.ValidateNode(DP_node, False);
              end;
            end

            else
            begin
              DP_node := nil;
              { DP_node := FindNode(VTV_update, VTV_update.RootNode,
                ExtractFileName(GB_DEV_BASES.ValueFromIndex
                [Cur_DR_list.items[X].DP])); }

              DP_node := FindNode(VTV_update, VTV_update.RootNode,
                ExtractFileName(Cur_DR_list.items[X].DPack));

              if not Assigned(DP_node) then
              // AddVSTDevice(VTV_update,DP_node,Cur_DR_list.Items[X],MyDevice)
              // else
              begin
                DP_node := VTV_update.AddChild(nil);
                DP_node.CheckType := ctTriStateCheckBox;
                DP_data := VTV_update.GetNodeData(DP_node);
                { DP_data.Driver_NAME :=
                  ExtractFileName(GB_DEV_BASES.ValueFromIndex
                  [Cur_DR_list.items[X].DP]); }

                DP_data.Driver_NAME :=
                  ExtractFileName(Cur_DR_list.items[X].DPack);

                VTV_update.ValidateNode(DP_node, False);
              end;
            end;

            AddVSTDevice(VTV_update, DP_node, Cur_DR_list.items[X], Mydevice,
              RzCheckGroup1.ItemChecked[1]);

            Mydevice.Driver_image := GetDPclasstype(Cur_DR_list.items[X].DPack);
            Mydevice.Device_index := i;
            { Mydevice.Driver_Pack := GB_DEV_BASES.ValueFromIndex
              [Cur_DR_list.items[X].DP]; }

            Mydevice.Driver_Pack := Cur_DR_list.items[X].DPack;

            // ShowMessage(Mydevice.Driver_Pack);

            Mydevice.Device_date :=
              DateToStr(GB_DriverList.items[i].DriverDate);
            Mydevice.Device_Ver := GB_DriverList.items[i].DriverVersion;
            Mydevice.Device_HWID := GB_DriverList.items[i].SPDRP_HARDWAREID;
            Mydevice.Device_HWID_compatible := GB_DriverList.items[i]
              .SPDRP_COMPATIBLEIDS;
            Mydevice.Driver_Progress := 0;
          end;

          if (RzCheckGroup1.ItemChecked[1] = False) and IS_ADDED then
            break;

          // MemoUpdate.Lines.Add(Cur_DR_list.Items[0].HWID);

        end;

      // Cur_DR_list.Free;

    end; // for i:=0 to GB_DriverList.Count-1 do

  // InstallPresent(ListUpdate);
  // ListUpdate.Items.EndUpdate;
  // end;
  // except ShowMessage('HIE DIAS') end;
  VTV_update.Header.SortDirection := sdAscending;
  VTV_update.SortTree(55, VTV_update.Header.SortDirection, true);
  VTV_update.EndUpdate;
  VTV_update.FullExpand(nil);

end;

procedure ClickUpdate(Sender: TObject);
begin
  Form1.BitBtn1Click(Sender);
end;

procedure ClickSetup(Sender: TObject);
begin
  Form1.Button7Click(Sender);
end;

procedure TForm1.Button4Click(Sender: TObject);
var
  Dnode, Ynode: PVirtualNode;

begin
  if Assigned(UpdateThread2) then
    if UpdateThread2.Terminated = False then
      exit;

  Ynode := VTV_update.GetFirstChecked(csCheckedNormal, False);
  if Ynode = nil then
  begin
    MessageDlg('No Drivers Are selected!'#13'Please Select the driver!',
      mtError, [mbOk], 0);
    exit;
  end;

  Ynode := VTV_update.GetFirstChecked(csunCheckedNormal);
  repeat
    VTV_update.DeleteNode(Ynode, true);
    Ynode := VTV_update.GetNextChecked(nil, csunCheckedNormal);
  until Ynode = nil;

  UpdateThread2 := TUpdateThread.Create(False);
  UpdateThread2.VTV := VTV_update;
  UpdateThread2.FreeOnTerminate := true;
  UpdateThread2.Priority := tpNormal;

  UpdateThread2.RefreshProcedure := ClickUpdate;

end;

procedure TForm1.BitBtn3Click(Sender: TObject);
const
  PINVALID_HANDLE_VALUE = Pointer(INVALID_HANDLE_VALUE);
var
  ClassImageListData: TSPClassImageListData;
  // i:integer;
  // node1:ttreenode;//////
  dwFlags: DWORD;

  dwIndex: DWORD;
  DeviceInfoData: SP_DEVINFO_DATA;
  DeviceName, DeviceClassName: ansiString;
  tvRoot: TTreeNode;
  ClassGUID: TGUID;
  // DeviceClassesCount, DevicesCount: Integer;
  ImageIndexVar: integer;
begin
  tvDevices.items.Clear;
  // tvDevices.AlphaSort;
  ZeroMemory(@ClassImageListData, sizeof(TSPClassImageListData));
  ClassImageListData.cbSize := sizeof(TSPClassImageListData);
  if SetupDiGetClassImageList(ClassImageListData) then
    ilDevices.Handle := ClassImageListData.ImageList;

  // Óñòàíàâëèâàåì íåîáõîäèìûå ôëàãè ïåðåä âûçîâîì ôóíêöèè
  dwFlags := DIGCF_ALLCLASSES or DIGCF_PRESENT;
  // or DIGCF_DEVICEINTERFACE; // îòîáðàæàåì òîëüêî óñòàíîâëåííûå óñòðîéñòâà

  // Ñîçäàåì è çàïîëíÿåì DIS (Device Information Sets)
  // èíôîðìàöèåé ïî âñåì óñòàíîâëåííûì óñòðîéñòâàì
  Devices_global := SetupDiGetClassDevsExA(nil, nil, 0, dwFlags, nil, nil, nil);
  if Devices_global = PINVALID_HANDLE_VALUE then
    RaiseLastOSError;
  // DeviceHelper.DeviceListHandle := hAllDevices;

  { for i:=0 to ilDevices.Count-1
    do
    begin
    node1:=TreeView1.Items.Add(nil,IntToStr(i));
    node1.ImageIndex:=i;
    end; }

  tvDevices.items.BeginUpdate;
  try
    dwIndex := 0;
    // DeviceClassesCount := 0;
    // DevicesCount := 0;

    // Ïîäãîòàâëèâàåì ñòðóêòóðó äëÿ ïîëó÷åíèÿ èíôîðìàöèè
    ZeroMemory(@DeviceInfoData, sizeof(SP_DEVINFO_DATA));
    DeviceInfoData.cbSize := sizeof(SP_DEVINFO_DATA);

    // Ïîëó÷àåì äàííûå ïî êàæäîìó óñòðîéñòâó â DIS
    // Íîìåð óñòðîéñòâà ñîäåðæèòñÿ â dwIndex
    while SetupDiEnumDeviceInfo(Devices_global, dwIndex, DeviceInfoData) do
    begin
      Application.ProcessMessages;
      // Èíèçèàëèçèðóåì íàø DeviceHelper,
      // äàëüíåéøàÿ ðàáîòà ñ SP_DEVINFO_DATA áóäåò ïðîèñõîäèòü
      // ïðè ïîìîùè ìåòîäîâ äàííîãî êëàññà
      // DeviceHelper.DeviceInfoData := DeviceInfoData;

      // Ïîëó÷àåì ðàñøèðåííîå èìÿ óñòðîéñòâà
      // DeviceName := DeviceHelper.FriendlyName;
      DeviceName := GetStringSAapi(Devices_global, DeviceInfoData,
        SPDRP_FRIENDLYNAME);
      // Åñëè ðàñøèðåííîãî èìåíè íåò -
      // ïîëó÷àåì èìÿ óñòðîéñòâà ïî óìîë÷àíèþ
      if DeviceName = '' then
        DeviceName := GetStringSAapi(Devices_global, DeviceInfoData,
          SPDRP_DEVICEDESC);

      // Ïîëó÷àåì GUID êëàññà, ê êîòîðîìó îòíîñèòñÿ óñòðîéñòâî
      ClassGUID := GetGuidSapi(Devices_global, DeviceInfoData, SPDRP_CLASSGUID);
      // Ïîëó÷àåì èìÿ êëàññà, ê êîòîðîìó îòíîñèòñÿ óñòðîéñòâî
      DeviceClassName := DeviceClassDescription(ClassGUID);

      // Èùåì âåòâü, â êîòîðóþ çàíîñÿòñÿ âñå äàííûå ïî êëàññó
      tvRoot := FindRootNode(DeviceClassName);
      if tvRoot = nil then
      begin
        Application.ProcessMessages;
        // Åñëè íå íàøëè, ñîçäàåì åå
        tvRoot := tvDevices.items.Add(nil, DeviceClassName);
        // Îïðåäåëÿåì èíäåêñ èêîíêè ïî GUID-ó êëàññà
        ImageIndexVar := -1;
        // Ïîëó÷àåì èíäåêñ èêîíêè äëÿ êîíêðåòíîãî óñòðîéñòâà
        SetupDiGetClassImageIndex(ClassImageListData, ClassGUID, ImageIndexVar);
        tvRoot.ImageIndex := ImageIndexVar;
        tvRoot.SelectedIndex := ImageIndexVar;
        tvRoot.StateIndex := -1;
        // Inc(DeviceClassesCount);
      end;

      // Äîáàâëÿåì ê âåòâè êëàññà íîâîå óñòðîéñòâî
      with tvDevices.items.AddChild(tvRoot, DeviceName) do
      begin
        // Îïðåäåëÿåì èíäåêñ èêîíêè ïî GUID-ó óñòðîéñòâà
        ImageIndexVar := -1;
        // Ïîëó÷àåì èíäåêñ èêîíêè äëÿ êîíêðåòíîãî óñòðîéñòâà
        SetupDiGetClassImageIndex(ClassImageListData, ClassGUID, ImageIndexVar);
        ImageIndex := ImageIndexVar;
        SelectedIndex := ImageIndex;
        // StateIndex áóäåò ñîäåðæàòü èíäåêñ óñòðîéñòâà â DIS
        // ýòî ïîíàäîáèòñÿ äëÿ äàëüíåéøåé ðàáîòû ñî ñïèñêîì
        StateIndex := integer(dwIndex);
        // Inc(DevicesCount);
      end;

      // Ïåðåõîäèì ê ñëåäóþùåìó óñòðîñòâó
      Inc(dwIndex);
    end;
    Application.ProcessMessages;
    tvDevices.AlphaSort;
    // StatusBar.Panels[0].Text := 'DeviceClasses Count: ' +  IntToStr(DeviceClassesCount);
    // StatusBar.Panels[1].Text := 'Devices Count: ' +  IntToStr(DevicesCount);

  finally
    tvDevices.items.EndUpdate;

  end;

end;

procedure ShowDeviceAdvancedInfo(const DeviceIndex: integer);
var
  DeviceInfoData: SP_DEVINFO_DATA;
  EmptyGUID: TGUID;
  // dwData: DWORD;
  str1: ansiString;
  classstring: ansiString;

  hkey1: HKEY;
  dwSize, dwType: Cardinal;
  BUFF: array [0 .. 511] of ansichar;
  posdot: integer;
begin
  Form1.RichEdit1.Lines.Clear;
  ZeroMemory(@EmptyGUID, sizeof(TGUID));
  // Ïîäãîòàâëèâàåì ñòðóêòóðó äëÿ ïîëó÷åíèÿ èíôîðìàöèè
  ZeroMemory(@DeviceInfoData, sizeof(SP_DEVINFO_DATA));
  DeviceInfoData.cbSize := sizeof(SP_DEVINFO_DATA);

  // Ïîëó÷àåì äàííûå ïî èñòðîéñòâó
  if not SetupDiEnumDeviceInfo(Devices_global, DeviceIndex, DeviceInfoData) then
    exit;

  str1 := GetStringSAapi(Devices_global, DeviceInfoData, SPDRP_FRIENDLYNAME);
  if length(str1) <= 0 then
    str1 := GetStringSAapi(Devices_global, DeviceInfoData, SPDRP_DEVICEDESC);

  Form1.RichEdit1.SelAttributes.Style := [fsBold];
  Form1.RichEdit1.Lines.Append('Device name');
  Form1.RichEdit1.SelAttributes.Style := [];
  Form1.RichEdit1.Lines.Append(str1);

  str1 := GetStringSAapi(Devices_global, DeviceInfoData, SPDRP_HARDWAREID);

  if GB_1HWID then
  begin
    posdot := pos(',', str1);
    if posdot > 0 then
      str1 := copy(str1, 0, posdot);
  end;

  str1 := StringReplace(str1, ',', #13#10, [rfReplaceAll]);
  str1 := StringReplace(str1, #32, '', [rfReplaceAll]);

  Form1.RichEdit1.SelAttributes.Style := [fsBold];
  Form1.RichEdit1.Lines.Append('Hardware IDs');
  Form1.RichEdit1.SelAttributes.Style := [];

  Form1.RichEdit1.Lines.Append(str1);

  str1 := GetStringSAapi(Devices_global, DeviceInfoData, SPDRP_COMPATIBLEIDS);
  str1 := StringReplace(str1, ',', #13#10, [rfReplaceAll]);
  str1 := StringReplace(str1, #32, '', [rfReplaceAll]);

  Form1.RichEdit1.SelAttributes.Style := [fsBold];
  Form1.RichEdit1.Lines.Append('COMPATIBLE IDs');
  Form1.RichEdit1.SelAttributes.Style := [];
  Form1.RichEdit1.Lines.Append(str1);

  str1 := GetStringSAapi(Devices_global, DeviceInfoData, SPDRP_MFG);

  Form1.RichEdit1.SelAttributes.Style := [fsBold];
  Form1.RichEdit1.Lines.Append('Manufacture');
  Form1.RichEdit1.SelAttributes.Style := [];
  Form1.RichEdit1.Lines.Append(str1);

  str1 := GetStringSAapi(Devices_global, DeviceInfoData, SPDRP_SERVICE);

  Form1.RichEdit1.SelAttributes.Style := [fsBold];
  Form1.RichEdit1.Lines.Append('Service');
  Form1.RichEdit1.SelAttributes.Style := [];
  Form1.RichEdit1.Lines.Append(str1);

  str1 := GetStringSAapi(Devices_global, DeviceInfoData, SPDRP_DRIVER);
  classstring := 'SYSTEM\CurrentControlSet\Control\Class\' + str1;
  if RegOpenKeyExA(HKEY_LOCAL_MACHINE, Pansichar(classstring), 0,
    KEY_QUERY_VALUE or KEY_WOW64_32KEY, hkey1) = ERROR_SUCCESS then
  begin
    dwType := REG_SZ;
    dwSize := 512;

    if RegQueryValueExA(hkey1, DriverDate, nil, @dwType, @BUFF, @dwSize) = ERROR_SUCCESS
    then
    begin

      Form1.RichEdit1.SelAttributes.Style := [fsBold];
      Form1.RichEdit1.Lines.Append('Driver Date');
      Form1.RichEdit1.SelAttributes.Style := [];
      Form1.RichEdit1.Lines.Append(BUFF);
    end;

    dwSize := 512;
    if RegQueryValueExA(hkey1, InfPath, nil, @dwType, @BUFF, @dwSize) = ERROR_SUCCESS
    then
    begin

      Form1.RichEdit1.SelAttributes.Style := [fsBold];
      Form1.RichEdit1.Lines.Append('INF File');
      Form1.RichEdit1.SelAttributes.Style := [];
      Form1.RichEdit1.Lines.Append(BUFF);
    end;

    // else ShowMessage('Îøèáêà ÷òåíèÿ äàòû'+IntToStr(RegQueryValueEx(hkey1,DriverDate, nil, @dwType, @bufF, @dwSize)));
    dwSize := 512;
    if RegQueryValueExA(hkey1, DriverVersion, nil, @dwType, @BUFF, @dwSize) = ERROR_SUCCESS
    then
    begin
      Form1.RichEdit1.SelAttributes.Style := [fsBold];
      Form1.RichEdit1.Lines.Append('Driver Version');
      Form1.RichEdit1.SelAttributes.Style := [];
      Form1.RichEdit1.Lines.Append(BUFF);
    end;

    dwSize := 512;
    if RegQueryValueExA(hkey1, 'MatchingDeviceId', nil, @dwType, @BUFF, @dwSize)
      = ERROR_SUCCESS then
    begin

      Form1.RichEdit1.SelAttributes.Style := [fsBold];
      Form1.RichEdit1.Lines.Append('MatchingDeviceId');
      Form1.RichEdit1.SelAttributes.Style := [];
      Form1.RichEdit1.Lines.Append(BUFF);
    end;

  end;

end;

procedure TForm1.tvDevicesChange(Sender: TObject; Node: TTreeNode);
var
  ANode: TTreeNode;
begin
  try
    RichEdit1.Clear;
    ANode := tvDevices.Selected;
    if Assigned(ANode) then
      if ANode.StateIndex >= 0 then
        ShowDeviceAdvancedInfo(ANode.StateIndex);
  except
  end;

end;

procedure CopyToClipboard(const Value: String);
begin
  Clipboard.Open;
  Clipboard.SetTextBuf(Pchar(Value));
  Clipboard.close;
end;

procedure TForm1.Button10Click(Sender: TObject);
var // item:Tlistitem;
  DeviceInfoData: SP_DEVINFO_DATA;
  EmptyGUID: TGUID;
  str1: string;
  // hkey1:HKEY;
  posdot, DeviceIndex: integer;
begin
  ZeroMemory(@EmptyGUID, sizeof(TGUID));
  // Ïîäãîòàâëèâàåì ñòðóêòóðó äëÿ ïîëó÷åíèÿ èíôîðìàöèè
  ZeroMemory(@DeviceInfoData, sizeof(SP_DEVINFO_DATA));
  DeviceInfoData.cbSize := sizeof(SP_DEVINFO_DATA);

  try
    DeviceIndex := tvDevices.Selected.StateIndex;
  except
    exit
  end;

  // Ïîëó÷àåì äàííûå ïî èñòðîéñòâó
  if not SetupDiEnumDeviceInfo(Devices_global, DeviceIndex, DeviceInfoData) then
    exit;

  str1 := GetStringSAapi(Devices_global, DeviceInfoData, SPDRP_HARDWAREID);

  if GB_1HWID then
  begin
    posdot := pos(',', str1);
    if posdot > 0 then
      str1[posdot] := #0;
  end;

  CopyToClipboard(str1);
  // ShowMessage('Ñíà÷àëà íåîáõîäèìî âûáðàòü óñòðîéñòâî!');

end;

procedure TForm1.N5Click(Sender: TObject);
begin
  ShellExecute(0, Pchar('open'), Pchar('services.msc'),
    // <--- ????? ??????? ???
    '', Nil, SW_SHOW);

end;

procedure TForm1.DirectX1Click(Sender: TObject);
begin
  ShellExecute(0, Pchar('open'), Pchar('dxdiag.exe'),
    // <--- ????? ??????? ???
    '', Nil, SW_SHOW);

end;

procedure TForm1.N7Click(Sender: TObject);
var
  Inifile0: TIniFile;
begin
  // ShowMessage(GB_INI_PATH);
  Inifile0 := TIniFile.Create(GB_INI_PATH);

  case N7.Checked of
    true:
      begin
        TabSheet2.TabVisible := False;
        N7.Checked := False;
        if GB_Write_allowed then
          Inifile0.WriteBool('Window', 'DevManager', False);
      end;
    False:
      begin
        TabSheet2.TabVisible := true;
        N7.Checked := true;
        if GB_Write_allowed then
          Inifile0.WriteBool('Window', 'DevManager', true);
      end
  end;
  Inifile0.Free;
end;

procedure TForm1.N8Click(Sender: TObject);
var
  Inifile: TIniFile;
begin
  Inifile := TIniFile.Create(GB_INI_PATH);
  case N8.Checked of
    true:
      begin
        TabSheet5.TabVisible := False;
        N8.Checked := False;
        if GB_Write_allowed then
          Inifile.WriteBool('Window', 'UpdateBase', False);
      end;
    False:
      begin
        TabSheet5.TabVisible := true;
        N8.Checked := true;
        if GB_Write_allowed then
          Inifile.WriteBool('Window', 'UpdateBase', true);
      end
  end;
  Inifile.Free;
end;

procedure TForm1.Label6MouseEnter(Sender: TObject);
begin
  (Sender as TLabel).Font.Color := $00149BF0;
  (Sender as TLabel).Font.Style := [fsBold];
end;

procedure TForm1.Label6MouseLeave(Sender: TObject);
begin
  (Sender as TLabel).Font.Color := clWindow;
end;

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: integer;
  Rect: TRect; State: TOwnerDrawState);
var
  foo: integer;
begin
  // rect.Height:=rect.Height+1;
  with TListBox(Control).Canvas do
  begin
    if odSelected in State then
    begin
      Brush.Color := TListBox(Control).Color;
      Font.Color := clWhite;
    end
    else
    begin
      Brush.Color := TListBox(Control).Color;
      Font.Color := clWhite;
    end;
    ListBox1.Canvas.FillRect(Rect);

    // if odDefault in State then
    // begin
    // Brush.Color := clred;

    // ListBox1.Canvas.FillRect(Rect);

    // end;


    // TextOut(Rect.Left, Rect.Top, TListBox(Control).items[Index]);

    { DrawGradient(ListBox1.Canvas, Rect, $00553929,$007D5A46,
      gdTopBottom); }
    SetBkMode(ListBox1.Canvas.Handle, TRANSPARENT);
    TabbedTextOut(TListBox(Control).Canvas.Handle, Rect.Left + 2, Rect.Top + 1,
      Pchar(TListBox(Control).items[Index]),
      length(TListBox(Control).items[Index]), 0, foo, 0);

    // рамку затираем только на выделенной строке
    if (odSelected in State) then
    begin
      // ListBox1.Canvas.FillRect(Rect);
      DrawGradient(ListBox1.Canvas, Rect, $00553929, $007D5A46, gdTopBottom);

      ListBox1.Canvas.Brush.Style := bsClear;
      SetBkMode(ListBox1.Canvas.Handle, TRANSPARENT);
      TabbedTextOut(TListBox(Control).Canvas.Handle, Rect.Left + 2,
        Rect.Top + 1, Pchar(TListBox(Control).items[Index]),
        length(TListBox(Control).items[Index]), 0, foo, 0);

      // TextOut(Rect.Left, Rect.Top, TListBox(Control).items[Index]);

    end;

    if (odFocused in State) then // только если элемент под фокусом
    begin

      ListBox1.Canvas.DrawFocusRect(Rect);

    end;
    // DrawFocusRect (Rect);
  end;
end;

procedure TForm1.ListBox1Exit(Sender: TObject);
begin
  RzPanel1.Height := 20;
  Logbutton.Tag := 0;
  ListBox1.TopIndex := ListBox1.Count - 1;
end;

procedure DrawProgressStatus(ACanvas: TCanvas; CellRect: TRect;
  ProgressCount: integer; status: integer);
var
  ProgressBarRect: TRect;
  Percents: real;

begin

  if (ProgressCount < 1) or (status = 0) then
    exit;
  Percents := ProgressCount / 100; // 33,3%

  begin
    ProgressBarRect.Left := CellRect.Left + 1;
    ProgressBarRect.Top := CellRect.Top + 1;
    // ProgressBarRect.Right := round((CellRect.Right - CellRect.Left) * Percents)  + CellRect.Left;
    ProgressBarRect.Right := CellRect.Right;
    ProgressBarRect.Bottom := CellRect.Bottom - 1;
    if (ProgressBarRect.Right - ProgressBarRect.Left) > 0 then
    begin
      case status of
        1, 2:
          ACanvas.Pen.Color := RGB(172, 160, 211);

        3:
          ACanvas.Pen.Color := RGB(116, 199, 73);
        4:
          ACanvas.Pen.Color := RGB(255, 60, 117);

      end;
      // ACanvas.Pen.Color:=RGB(112,93,180);
      // TargetCanvas.Pen.Width:=2;

      ACanvas.Brush.Color := clWindow;
      // TargetCanvas.FillRect(ProgressBarRect);
      ACanvas.Rectangle(ProgressBarRect);

    end;
    Inc(ProgressBarRect.Left);
    Inc(ProgressBarRect.Top);
    ProgressBarRect.Right := Round((CellRect.Right - CellRect.Left) * Percents)
      + CellRect.Left;
    dec(ProgressBarRect.Right);
    dec(ProgressBarRect.Bottom);
    if (ProgressBarRect.Right - ProgressBarRect.Left) > 0 then
    begin
      case status of
        1, 2:
          begin
            // ACanvas.Brush.Color := RGB(172,160,211);
            // DrawGradient(ACanvas, ProgressBarRect, False,
            // [$00F5F5F5, $00D3A0AC, $00D9AAB5]); // $00B35A6E]);
            DrawGradient(ACanvas, ProgressBarRect, $00F5F5F5, $00D3A0AC,
              gdTopBottom);
          end;
        3:
          begin
            // ACanvas.Brush.Color := RGB(116,199,73);
            // DrawGradient(ACanvas, ProgressBarRect, False,
            // [RGB(243, 250, 240), RGB(174, 222, 148), RGB(183, 226, 161)]);
            // $00B35A6E]);
          end;
        4:
          begin
            // ACanvas.Brush.Color := RGB(116,199,73);
            // DrawGradient(ACanvas, ProgressBarRect, False,
            // [RGB(255, 255, 255), RGB(255, 141, 174), RGB(255, 155, 184)]);
            // $00B35A6E]);
          end;

      end;
      {
        1: CellText := 'Ðàñïàêîâêà Äðàéâåðà';
        2: CellText := 'Óñòàíîâêà Äðàéâåðà';
        3: CellText := 'Äðàéâåð óñòàíîâëåí';
        4: CellText := 'Äðàéâåð íå óñòàíîâëåí'; }
      // f3faf0
    end;
  end;
end;

procedure TForm1.DrawProgressBar(ACanvas: TCanvas; CellRect: TRect;
  ProgressCount: integer);
var
  ProgressBarRect: TRect;
  Percents: real;

begin

  Percents := ProgressCount / 100; // 33,3%

  begin
    ProgressBarRect.Left := CellRect.Left + 1;
    ProgressBarRect.Top := CellRect.Top + 1;
    // ProgressBarRect.Right := round((CellRect.Right - CellRect.Left) * Percents)  + CellRect.Left;
    ProgressBarRect.Right := CellRect.Right;
    ProgressBarRect.Bottom := CellRect.Bottom - 1;
    if (ProgressBarRect.Right - ProgressBarRect.Left) > 0 then
    begin
      ACanvas.Pen.Color := RGB(112, 93, 180);
      // TargetCanvas.Pen.Width:=2;

      ACanvas.Brush.Color := clWindow;
      // TargetCanvas.FillRect(ProgressBarRect);
      ACanvas.Rectangle(ProgressBarRect);

    end;
    Inc(ProgressBarRect.Left);
    Inc(ProgressBarRect.Top);
    ProgressBarRect.Right := Round((CellRect.Right - CellRect.Left) * Percents)
      + CellRect.Left;
    dec(ProgressBarRect.Right);
    dec(ProgressBarRect.Bottom);
    if (ProgressBarRect.Right - ProgressBarRect.Left) > 0 then
    begin
      ACanvas.Brush.Color := RGB(172, 160, 211); //

      DrawGradient(ACanvas, ProgressBarRect, $00D3A0AC, $00B35A6E, gdTopBottom);

      // DrawGradient(ACanvas, ProgressBarRect, False,
      // [$00F5F5F5, $00D3A0AC, $00D9AAB5]); // $00B35A6E]);
      // ACanvas.FillRect(ProgressBarRect);
    end;
  end;
end;

{
  procedure TForm1.Label2MouseLeave(Sender: TObject);
  begin
  (Sender as TLabel).Font.Color:=$00B35A6E;
  (Sender as TLabel).Font.Style:=[fsbold];

  end; }

procedure TForm1.N9Click(Sender: TObject);
begin
  Button10Click(Sender);
end;

procedure TForm1.OpenDriverInarchive1Click(Sender: TObject);
var
  VTV: TBaseVirtualTree;
  Node1: PVirtualNode;
  Mydevice: Pdevice;
  file1: ansiString;
  folder: ansiString;
begin

  if PageControl1.ActivePageIndex = 1 then
    VTV := VTV_update
  else
    VTV := VTV_setup;

  // List0:=TListView(TPopupMenu ((Sender as TMenuItem).GetParentMenu).PopupComponent);
  Node1 := VTV.GetFirstSelected(true);
  if Node1 = nil then
    exit;

  Mydevice := VTV.GetNodeData(Node1);
  // form3.DPdir := ExtractFilePath();
  file1 := Mydevice^.Driver_Pack + '\' + Mydevice^.Driver_Dir;
  folder := Mydevice^.Driver_Dir;

  // file1:=file1+'\'+Mydevice^.Driver_Dir;
  // tolog(Mydevice^.Driver_Pack);
  // tolog(Mydevice^.Driver_Dir);
  // ShowMessage(Mydevice^.Driver_Dir);
  ShellExecuteA(0, 'open', Pansichar('7zfm'), Pansichar(file1), nil, SW_SHOW);

end;

procedure TForm1.OS_labelClick(Sender: TObject);
begin
  form4.showmodal;
end;

function GetField(InpString: String; fieldpos: integer): String;
var
  c: Char;
  curpos, i: integer;
begin
  curpos := 1;
  for i := 1 to fieldpos do
  begin
    Result := '';
    if curpos > length(InpString) then
      break;
    repeat
      c := InpString[curpos];
      Inc(curpos, 1);
      // if (c = '"') or (c = #13) or (c = #10) then c := ' ';
      if c <> chr(9) then
        Result := Result + c;
    until (c = chr(9)) or (curpos > length(InpString));
  end;

  if (curpos > length(InpString)) and (i < fieldpos) then
    Result := '';
  // result := Trim(result);

end;

procedure TForm1.N10Click(Sender: TObject);
begin
  form2.showmodal;

end;

procedure TForm1.N12Click(Sender: TObject);
var
  DP: string;
  dpbase: string;
  i: integer;
  Data1: PTreeDP;
  Node1: PVirtualNode;
begin
  // if ListView1.Selected=nil then  Exit;
  Node1 := VST_DP.GetFirstSelected(true);
  if Node1 = nil then
    exit;
  if Node1.Parent = VST_DP.RootNode then
    exit;

  Data1 := VST_DP.GetNodeData(Node1);

  if Data1.Filename = '' then
    DP := Data1.name
  else
    DP := Data1.Filename;

  i := MessageDlg('Âû õîòèòå óäàëèòü ïàêåò è áàçó ?' + #13 + Data1.name,
    mtConfirmation, [mbYes, mbNo], 0);
  if not(i = mrYes) then
    exit;

  dpbase := DP;
  dpbase := ChangeFileExt(dpbase, INI_ext);

  DeleteFile(DP);
  DeleteFile(dpbase);
  // node1.
  VST_DP.DeleteNode(Node1, False);
  // ListView1.Selected.Delete;
  // showmessage(dp+#13+dpbase);
end;

procedure TForm1.Button9Click(Sender: TObject);
var
  Ynode: PVirtualNode;

begin
  if Assigned(UpdateThread1) then
    if UpdateThread1.Terminated = False then
      exit;

  Ynode := VTV_setup.GetFirstChecked(csCheckedNormal, False);
  if Ynode = nil then
  begin
    MessageDlg
      ('Íå âûáðàíî íè îäíîãî äðàéâåðà!'#13'Ïîæàëóéñòà âûáåðèòå äðàéâåð!',
      mtError, [mbOk], 0);
    exit;
  end;

  Ynode := VTV_setup.GetFirst(true);
  repeat
    // data1:=VTV_update.GetNodeData(ynode);
    if not(Ynode.CheckState = csCheckedNormal) then
      VTV_setup.FullyVisible[Ynode] := False;

    Ynode := VTV_setup.GetNext(Ynode, true);
  until Ynode = nil;

  UpdateThread1 := TUpdateThread.Create(False);
  UpdateThread1.VTV := VTV_setup;
  UpdateThread1.FreeOnTerminate := true;
  UpdateThread1.Priority := tpNormal;
  UpdateThread1.RefreshProcedure := ClickSetup;

end;

procedure TForm1.RzBitBtn1Click(Sender: TObject);
var
  Ynode: PVirtualNode;
begin
  case VTV_update.Tag of
    0:
      begin
        VTV_update.Tag := 1;
        Ynode := VTV_update.GetFirst(true);
        repeat
          Ynode.CheckState := csCheckedNormal;
          VTV_update.RepaintNode(Ynode);
          Ynode := VTV_update.GetNext(Ynode, true);
        until Ynode = nil;
      end;

    1:
      begin
        VTV_update.Tag := 0;
        VTV_update.ClearChecked;
      end;
  end;

end;

procedure TForm1.TabSheet6Show(Sender: TObject);
begin
  // ListUpdate.SetFocus;
  BitBtn1Click(Sender);
end;

procedure TForm1.TabSheet1Show(Sender: TObject);
begin

  Button7Click(Sender);
end;

procedure TForm1.CategoryButtons1DrawButton(Sender: TObject;
  const Button: TButtonItem; Canvas: TCanvas; Rect: TRect;
  State: TButtonDrawState);
begin
  // GradVertical(Canvas,rect,clYellow,clBlue);

  // DrawGradient(Canvas, Rect, true, [clBlue, clwhite]);
  dec(Rect.Right, 5);
  Canvas.DrawFocusRect(Rect);
end;

procedure TForm1.CheckBases();
var
  searchResult: TSearchRec;
  Index: integer;
  DP_TXT, dp_files: Tstringlist;
  // DP_This:string;
begin
  DP_TXT := Tstringlist.Create;
  dp_files := Tstringlist.Create;

  if FindFirst(GB_DevDB + '*' + INI_ext, faAnyFile, searchResult) = 0 then
  begin
    repeat
      DP_TXT.Add(UpperCase(searchResult.name));
    until FindNext(searchResult) <> 0;
    FindClose(searchResult);
  end;

  ScanDir(GB_Appdir + '\' + GB_DRP_DIR + '\', ZIP7_ext, true, dp_files);

  for index := 0 to dp_files.Count - 1 do
    dp_files.Strings[index] :=
      ExtractFileName(UpperCase(dp_files.names[index]));

  // ShowMessage(DP_TXT.Text);

  for index := 0 to DP_TXT.Count - 1 do
    if dp_files.IndexOf(UpperCase(ChangeFileExt(DP_TXT.Strings[index], ZIP7_ext)
      )) = -1 then
    begin
      // DP_TXT.Delete(index);
      DeleteFile(GB_DevDB + DP_TXT.Strings[index]);
    end;
end;

procedure TForm1.TabSheet2Show(Sender: TObject);
begin
  tvDevices.SetFocus;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  IninfileSET: TIniFile;
  // Ils:string;
  // i:integer;
begin

  if GB_Write_allowed then
  begin
    IninfileSET := TIniFile.Create(GB_INI_PATH);
    IninfileSET.WriteBool('VIEW', 'SetupDubles', RzCheckGroup2.ItemChecked[0]);
    IninfileSET.WriteBool('VIEW', 'UpdateInstalled',
      RzCheckGroup1.ItemChecked[0]);
    IninfileSET.WriteBool('VIEW', 'UpdateDubles', RzCheckGroup1.ItemChecked[1]);
  end;

  if UpdateThread2 <> nil then
    UpdateThread2.Terminate;
  if UpdateThread1 <> nil then
    UpdateThread1.Terminate;

  if DirectoryExists(GB_TMPfolder) then
  begin
    RzPanel6.BringToFront;
    RzPanel6.Invalidate;
    Application.ProcessMessages;
    RemoveFolder2(GB_TMPfolder);
  end;
  AnimateWindow(Handle, 400, AW_BLEND or AW_HIDE);

end;

procedure TForm1.N16Click(Sender: TObject);
var
  // l:^integer;
  dvInst: DEVINST;
  // status: CONFIGRET;

  VTV: TBaseVirtualTree;
  Node1: PVirtualNode;
  Mydevice: Pdevice;
  Deleted: boolean;
begin

  if PageControl1.ActivePageIndex = 1 then
    VTV := VTV_update // list0:=listsetup
  else
    VTV := VTV_setup;

  Node1 := VTV.GetFirstSelected(true);
  if Node1 = nil then
    exit;
  Mydevice := VTV.GetNodeData(Node1);

  if DeleteDevice(Mydevice^.Device_index, Mydevice^.Device_HWID) then
    Deleted := true // Test1.Add(TimeToStr(time) + #9 + 'Óñòðîéñòâî Óäàëåíî')
  else
    Deleted := False;
  // Test1.Add(TimeToStr(time) + #9 + 'Óñòðîéñòâî ÍÅ Óäàëåíî');

  CM_Locate_DevNodeA(dvInst, nil, CM_LOCATE_DEVNODE_NORMAL);

  CM_Reenumerate_DevNode(dvInst, 0);
  // if status = CR_SUCCESS then
  // showMessage('CMReenumerateDevNode Óñïåøíî');

  if VTV = VTV_update then
    BitBtn1.Click;

end;

procedure TForm1.N17Click(Sender: TObject);
var
  DP: string;
  Dir: string;
  Data1: PTreeDP;
  Node1: PVirtualNode;
begin
  // if ListView1.Selected=nil then  Exit;
  Node1 := VST_DP.GetFirstSelected(true);
  if Node1 = nil then
    exit;

  Data1 := VST_DP.GetNodeData(Node1);

  if Data1.Filename = '' then
    DP := Data1.name
  else
    DP := Data1.Filename;
  // dp:=GB_Appdir+'\'+GetItemGroup(ListView1.Selected.Index)+'\'+ListView1.Selected.Caption;
  Dir := ExtractFileDir(DP);
  // ShowMessage(dp);
  ShellExecute(0, 'open', Pchar(DP), nil, Pchar(Dir), SW_SHOW);
end;

procedure TForm1.N19Click(Sender: TObject);
var

  VTV: TBaseVirtualTree;
  Node1: PVirtualNode;
  Mydevice: Pdevice;
begin

  if PageControl1.ActivePageIndex = 1 then
    VTV := VTV_update
  else
    VTV := VTV_setup;

  // List0:=TListView(TPopupMenu ((Sender as TMenuItem).GetParentMenu).PopupComponent);
  Node1 := VTV.GetFirstSelected(true);
  if Node1 = nil then
    exit;

  Mydevice := VTV.GetNodeData(Node1);
  // if List0.Selected=nil then exit;
  CopyToClipboard(Mydevice^.Driver_HWID);

end;

procedure TForm1.N20Click(Sender: TObject);
var

  VTV: TBaseVirtualTree;
  Node1: PVirtualNode;
  Mydevice: Pdevice;
begin

  if PageControl1.ActivePageIndex = 1 then
    VTV := VTV_update
  else
    VTV := VTV_setup;

  // List0:=TListView(TPopupMenu ((Sender as TMenuItem).GetParentMenu).PopupComponent);
  Node1 := VTV.GetFirstSelected(true);
  if Node1 = nil then
    exit;

  Mydevice := VTV.GetNodeData(Node1);
  // if List0.Selected=nil then exit;
  CopyToClipboard(Mydevice^.Device_HWID);
end;

procedure TForm1.ShowDPClick(Sender: TObject);
var
  Inifile: TIniFile;
begin
  VTV_update.InvalidateColumn(1);
  VTV_setup.InvalidateColumn(1);

  Inifile := TIniFile.Create(GB_INI_PATH);
  if GB_Write_allowed then
    Inifile.WriteBool('Window', 'DP-HWIDS', ShowDP.Checked);

end;

procedure TForm1.RzCheckGroup1Change(Sender: TObject; Index: integer;
  NewState: TCheckBoxState);
begin
  BitBtn1Click(Sender);

end;

procedure TForm1.N22Click(Sender: TObject);
var

  VTV: TBaseVirtualTree;
  Node1: PVirtualNode;
  Mydevice: Pdevice;
begin

  if PageControl1.ActivePageIndex = 1 then
    VTV := VTV_update
  else
    VTV := VTV_setup;

  // List0:=TListView(TPopupMenu ((Sender as TMenuItem).GetParentMenu).PopupComponent);
  Node1 := VTV.GetFirstSelected(true);
  if Node1 = nil then
    exit;

  Mydevice := VTV.GetNodeData(Node1);

  form3.DP := Mydevice^.Driver_Pack;
  form3.DPdir := ExtractFilePath(Mydevice^.Driver_Dir);

  form3.showmodal;
end;

function ExecuteAndWait(Filename: string; HideApplication: boolean): boolean;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  exitc: Cardinal;
  params: string;
  pos1: integer;
begin
  FillChar(StartupInfo, sizeof(StartupInfo), 0);
  with StartupInfo do
  begin
    cb := sizeof(StartupInfo);
    dwFlags := STARTF_USESHOWWINDOW;
    wShowWindow := SW_SHOW;
  end;
  pos1 := pos('.EXE', UpperCase(Filename));

  if pos1 < length(Filename) - 3 then
  begin
    params := copy(Filename, pos1 + 4, 220);
    // ShowMessage(FileName);
  end;

  if not CreateProcess(nil, Pchar(Filename), nil, nil, False,
    CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo,
    ProcessInfo) then
    Result := False
  else
  begin
    if HideApplication then
    begin
      Application.Minimize;
      ShowWindow(Application.Handle, SW_HIDE);
      WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    end
    else
      while WaitForSingleObject(ProcessInfo.hProcess, 10) = WAIT_TIMEOUT do
      begin
        Application.ProcessMessages;
        if Application.Terminated then
          TerminateProcess(ProcessInfo.hProcess, 0);
      end;
    GetExitCodeProcess(ProcessInfo.hProcess, exitc);
    Result := (exitc = 0);
    if HideApplication then
    begin
      ShowWindow(Application.Handle, SW_SHOW);
      Application.Restore;
      Application.BringToFront;
    end;
  end;
end;

procedure TForm1.N24Click(Sender: TObject);
begin
  CreateRestorePoint;
end;

function GetColorBetween(StartColor, EndColor: TColor;
  Pointvalue, Von, bis: Extended): TColor;
var
  F: Extended;
  r1, r2, r3, g1, g2, g3, b1, b2, b3: Byte;
  function CalcColorBytes(fb1, fb2: Byte): Byte;
  begin
    Result := fb1;
    if fb1 < fb2 then
      Result := fb1 + Trunc(F * (fb2 - fb1));
    if fb1 > fb2 then
      Result := fb1 - Trunc(F * (fb1 - fb2));
  end;

begin
  if Pointvalue <= Von then
  begin
    Result := StartColor;
    exit;
  end;
  if Pointvalue >= bis then
  begin
    Result := EndColor;
    exit;
  end;
  F := (Pointvalue - Von) / (bis - Von);
  asm
    mov EAX, Startcolor
    cmp EAX, EndColor
    je @@exit
    mov r1, AL
    shr EAX,8
    mov g1, AL
    shr Eax,8
    mov b1, AL
    mov Eax, Endcolor
    mov r2, AL
    shr EAX,8
    mov g2, AL
    shr EAX,8
    mov b2, AL
    push ebp
    mov al, r1
    mov dl, r2
    call CalcColorBytes
    pop ecx
    push ebp
    Mov r3, al
    mov dL, g2
    mov al, g1
    call CalcColorBytes
    pop ecx
    push ebp
    mov g3, Al
    mov dL, B2
    mov Al, B1
    call CalcColorBytes
    pop ecx
    mov b3, al
    XOR EAX,EAX
    mov AL, B3
    SHL EAX,8
    mov AL, G3
    SHL EAX,8
    mov AL, R3
  @@Exit:
    mov @result, eax
  end;
end;

procedure GetTreeDirs(Root: string; OutPaper: TStrings);
var
  i: integer;
  s: string;

  procedure InsDirs(s: string; ind: integer; Path: string; OPaper: TStrings);
  var
    sr: TSearchRec;
    attr: integer;
  begin
    // attr := 0;
    attr := faAnyFile;
    if DirectoryExists(Path) then
      if FindFirst(IncludeTrailingBackslash(Path) + '*.*', attr, sr) = 0 then
      begin
        repeat
          if DirectoryExists(IncludeTrailingBackslash(Path) + sr.name) and
            (sr.name[length(sr.name)] <> '.') then
            OPaper.Add(s + sr.name);
        until (FindNext(sr) <> 0);
        FindClose(sr);
      end
  end;

begin

  if not DirectoryExists(Root) then
    exit;

  if Root[length(Root)] <> '\' then
    InsDirs(Root + '\', OutPaper.Count, Root, OutPaper)
  else
    InsDirs(Root, OutPaper.Count, Root, OutPaper);
  i := 0;

  if OutPaper.Count > 0 then

    repeat
      s := OutPaper[i];
      InsDirs(s + '\', i, OutPaper[i], OutPaper);
      Inc(i);
    until (i = OutPaper.Count);
end;

function TForm1.FillDRPLIST3(): integer;
var
  i, L: integer;
  dp_files: Tstringlist;
  DP_dirs: Tstringlist;
  TreeDP: TTreeDP;
  ParentN: PVirtualNode;
begin
  Result := 0;
  VST_DP.Clear;
  DP_dirs := Tstringlist.Create;

  // try
  // ShowMessage(GB_Appdir + '\' + GB_DRP_DIR + '\');
  GetTreeDirs(GB_Appdir + '\' + GB_DRP_DIR + '\', DP_dirs);
  // except
  // ShowMessage('ASSAS');
  // end; // ShowMessage('ÁÀÃ');  end;
  DP_dirs.Add(GB_Appdir + '\' + GB_DRP_DIR + '\');
  // ShowMessage(GB_Appdir + '\' + GB_DRP_DIR + '\');

  VST_DP.NodeDataSize := sizeof(TTreeDP);

  if DP_dirs.Count > 0 then
    for i := 0 to DP_dirs.Count - 1 do
    begin
      dp_files := Tstringlist.Create;
      ScanDir(DP_dirs.Strings[i], ZIP7_ext, False, dp_files);

      DP_dirs.Strings[i] := AnsiReplaceStr(DP_dirs.Strings[i],
        GB_Appdir + '\', '');
      TreeDP.name := (DP_dirs.Strings[i]); // 'Node-Nummer: '+IntToStr(I);
      TreeDP.image := 20;
      // TreeDP.Number:=false;
      if dp_files.Count > 0 then
        ParentN := AddVSTStructure(VST_DP, nil, TreeDP);

      // ShowMessage(dp_files.Text);

      // DP_dirs.Strings[i]:=AnsiReplaceStr(DP_dirs.strings[i],GB_Appdir+'\','');
      // ListView1.Items.Add.Caption:=DP_dirs.Strings[i];

      for L := 0 to dp_files.Count - 1 do
      begin
        TreeDP.name := ExtractFileName(dp_files.names[L]);
        TreeDP.Filename := dp_files.names[L];
        TreeDP.size := strtoint(dp_files.ValueFromIndex[L]);
        TreeDP.image := GetDPclasstype(TreeDP.name);
        TreeDP.progress := -1;
        // ShowMessage(dp_files.names[L]);
        TreeDP.indexed := BaseExist2(dp_files.names[L]);

        if TreeDP.indexed = False then
          Inc(Result);

        AddVSTStructure(VST_DP, ParentN, TreeDP);
      end;

    end;

end;

function ChangeInput(Keys: array of word; doOn: boolean): Cardinal;
var
  i: integer;
  sInput: tagINPUT;
begin
  Result := 0;
  for i := 0 to length(Keys) - 1 do
  begin
    sInput.Itype := INPUT_KEYBOARD;
    sInput.ki.wVk := Keys[i];
    sInput.ki.wScan := 0;
    if not doOn then
      sInput.ki.dwFlags := KEYEVENTF_KEYUP
    else
      sInput.ki.dwFlags := 0;
    sInput.ki.time := 0;
    sInput.ki.dwExtraInfo := 0;
    Result := Result + SendInput(1, sInput, sizeof(tagINPUT));
    Application.ProcessMessages;
  end;
end;

procedure TForm1.RzBitBtn4Click(Sender: TObject);
begin
  PopupSet_N_Upd.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);

end;

procedure TForm1.DEVID1Click(Sender: TObject);
var
  Hwid: string;
  dot: integer;
  VTV: TBaseVirtualTree;
  Node1: PVirtualNode;
  Mydevice: Pdevice;
begin

  if PageControl1.ActivePageIndex = 1 then
    VTV := VTV_update
  else
    VTV := VTV_setup;

  Node1 := VTV.GetFirstSelected(true);
  if Node1 = nil then
    exit;
  Mydevice := VTV.GetNodeData(Node1);

  Hwid := Mydevice^.Device_HWID;

  dot := pos(',', Hwid);

  if dot > 0 then
    Hwid := copy(Hwid, 0, dot - 1);

  Hwid := AnsiReplaceText(Hwid, '&', '%26');

  ShellExecute(0, Pchar('open'), Pchar('http://devid.info/search.php?text=' +
    Hwid), Nil, Nil, SW_SHOW);

end;

procedure TForm1.MS1Click(Sender: TObject);
var

  Hwid: string;
  dot: integer;
  VTV: TBaseVirtualTree;
  Node1: PVirtualNode;
  Mydevice: Pdevice;
begin

  if PageControl1.ActivePageIndex = 1 then
    VTV := VTV_update
  else
    VTV := VTV_setup;

  Node1 := VTV.GetFirstSelected(true);
  if Node1 = nil then
    exit;
  Mydevice := VTV.GetNodeData(Node1);

  Hwid := Mydevice^.Device_HWID;

  dot := pos(',', Hwid);

  if dot > 0 then
    Hwid := copy(Hwid, 0, dot - 1);

  Hwid := AnsiReplaceText(Hwid, '&', '%26');

  ShellExecute(0, Pchar('open'), Pchar('"http://www.google.com/search?q=driver '
    + Hwid + '"'), Nil, Nil, SW_SHOW);

end;

procedure TForm1.N29Click(Sender: TObject);
begin
  aboutbox.showmodal;
end;

procedure TForm1.RzCheckGroup2Change(Sender: TObject; Index: integer;
  NewState: TCheckBoxState);
begin
  Button7Click(Sender);
end;

procedure TForm1.LogbuttonClick(Sender: TObject);
var
  Style: LongInt;
begin
  case Logbutton.Tag of
    1:
      begin
        // listbox1.Visible := False;
        RzPanel1.Height := 20;
        Logbutton.Tag := 0;
        ListBox1.TopIndex := ListBox1.Count - 1;
      end;
    0:
      begin
        // listbox1.Visible := true;
        RzPanel1.Height := 80;
        Logbutton.Tag := 1;
      end;

  end;

end;

procedure TForm1.RzBitBtn11Click(Sender: TObject);
begin
  TerminateThread(NewThread.Handle, 0);
  NewThread.Free;

  // form1.timer1.Enabled:=false;
  // form1.PaintBox1.Repaint;

  FillDRPLIST3();
  LoadHashMAPS_OBJ;
  RzBitBtn11.Hide;
  Progress_INDEX.Hide;
  RzBitBtn12.Enabled := true;
  RzBitBtn10.Show;
  ProgressBar1.Hide;
end;

function EnumChildWindowsProc(Wnd: HWND; Mywindow: Pointer): Bool; export;
{$IFDEF Win32} stdcall; {$ENDIF}
var
  Buffer: array [0 .. 99] of Char;
  WClass: array [0 .. 255] of Char;
begin
  GetWindowText(Wnd, Buffer, 100);
  // if StrLen(Buffer)  0 then
  if StrPas(Buffer) = '' then
    Buffer := 'Empty';
  new(AWindows);
  with AWindows^ do
  begin
    WindowHandle := Wnd;
    WindowText := StrPas(Buffer);
  end;

  GetClassName(AWindows^.WindowHandle, WClass, 256);
  if WClass = 'Button' then
  begin
    if HWND(Mywindow^) = 51 then
    begin
      HWND(Mywindow^) := AWindows^.WindowHandle;
      Result := False;
      exit;
    end;

    // form1.memo1.Lines.Add( AWindows^.WindowText + ':' +
    // IntToHex(AWindows^.WindowHandle, 8));
    // hwnd(Mywindow^):=awindows^. WindowHandle;
  end;

  if GetWindow(Wnd, GW_CHILD) = 0 then
  begin
    // PNode := CNode;
    Enumchildwindows(Wnd, @EnumChildWindowsProc, 0);
  end;
  Result := true;
end;

procedure TForm1.TimerUnsignedTimer(Sender: TObject);
var
  hwnd1, Mywindow: HWND;
  // Buffer: array[0..99] of Char;
  // WClass: array[0..255] of Char;

begin
  // hwnd1:=0;
  Mywindow := 0;

  hwnd1 := FindWindow(nil, 'Áåçîïàñíîñòü Windows');
  Mywindow := 61; // Çíà÷èò ýòî âñå òàêè SEVEN èëè 6 âåðñèÿ âèíäû

  // label6.Caption:=IntToStr(hwnd1)+'__'+inttostr(mywindow);
  if hwnd1 = 0 then
  begin
    hwnd1 := FindWindow(nil, 'Óñòàíîâêà îáîðóäîâàíèÿ');
    Mywindow := 51; // Òàê ìû äàäèì ôóíêöèè ïîíÿòü ÷òî ýòî NT 5.1
  end;

  if hwnd1 <> 0 then
  begin
    // memo1.Clear;
    Enumchildwindows(hwnd1, @EnumChildWindowsProc, LParam(@Mywindow));


    // GetWindowText(mywindow, Buffer, 100);
    // ShowMessage(IntToHex(mywindow,8)+buffer);
    // label6.Caption:=TimeToStr(time)+'___'+IntToStr(mywindow);

    if AWindows.WindowHandle <> 0 then
      PostMessage(AWindows.WindowHandle, BM_CLICK, 0, 0);
    // FindWindowEx()
    // CloseWindow(hwnd1);
  end;
  // ShowMessage('TRUE');
end;

procedure TForm1.VST_DPGetImageIndex(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
  var Ghosted: boolean; var ImageIndex: integer);
var
  data: PTreeDP;
begin
  if Column <> 0 then
    exit;

  data := Sender.GetNodeData(Node);
  ImageIndex := data^.image;

end;

procedure TForm1.VST_DPGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  data: PTreeDP;
begin
  data := Sender.GetNodeData(Node);

  if Node.Parent = Sender.RootNode then
  begin
    if Column = 0 then
      CellText := data^.name
    else
      CellText := '';
  end
  else
    case Column of
      0:
        CellText := data^.name;
      1: // CellText := IntToStr(Data^.size) ;
        CellText := Floattostr(RoundTo(data^.size / 1000000, -1)) + ' MB';
      2:
        if data^.indexed then
          CellText := 'YES'
        else
          CellText := 'NO';
      3:
        begin
          if data^.progress > 1 then
          begin
            if data^.isextracting then
              CellText := 'Extracting'
            else
              CellText := 'Indexing';
          end
          else
            CellText := '';
        end;
    end

end;

procedure TForm1.VST_DPPaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
var
  DeviceNODE: PTreeDP;
begin
  DeviceNODE := Sender.GetNodeData(Node);

  if Column = 2 then
  begin
    TargetCanvas.Font.Style := [fsBold];
    if DeviceNODE.indexed then
      TargetCanvas.Font.Color := clgreen
    else
      TargetCanvas.Font.Color := clred;

  end;

end;

procedure TForm1.VST_DPBeforeCellPaint(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect);
var
  data: PTreeDP;
begin
  data := Sender.GetNodeData(Node);

  if not(Node.Parent = Sender.RootNode) then
    if ((Node.Index + 1) div 2) = ((Node.Index + 1) / 2) then
    begin
      TargetCanvas.Brush.Color := $00F5F5F5;
      TargetCanvas.FillRect(CellRect);
    end;

  if Column = 3 then
    if not(Node.Parent = Sender.RootNode) then
      DrawProgressBar(TargetCanvas, CellRect, data^.progress);

end;

procedure TForm1.RzBitBtn12Click(Sender: TObject);
begin
  FillDRPLIST3;
end;

procedure TForm1.TabSheet5Show(Sender: TObject);
begin
  VST_DP.SetFocus;
end;

procedure TForm1.RzBitBtn10Click(Sender: TObject);
var
  SelectedStrings: Tstringlist;

  NextNode: PVirtualNode;
  PhoneNode: PTreeDP;
  i: integer;
begin
  if not(Check_Write) then
    exit;

  NextNode := VST_DP.GetFirstChecked(csCheckedNormal, False);
  if NextNode = nil then
  begin
    MessageDlg('Не выбрано ни одного пакета!'#13'Пожалуйста выберите пакеты!2222',
      mtInformation, [mbOk], 0);
    exit;
  end;

  SelectedStrings := Tstringlist.Create;
  if NextNode <> nil then
    repeat
      PhoneNode := VST_DP.GetNodeData(NextNode);
      // NextNode.States:=[vsSelected,vsVisible,vsToggling];
      // VST_DP.Selected[NextNode]:=true;
      // VST_DP.ScrollIntoView(NextNode,true,true);
      if NextNode.Parent <> VST_DP.RootNode then
        SelectedStrings.AddObject(PhoneNode^.Filename, Pointer(NextNode));
      // ShowMessage(SelectedStrings.Text);
      // str1:=str1+phonenode^.name+#13#10;

      NextNode := VST_DP.GetNextChecked(NextNode, csCheckedNormal, False);
    until (NextNode = nil);

  RzBitBtn11.Show;
  (Sender as tcontrol).Hide;
  RzBitBtn12.Enabled := False;

  // PanelStatus.Show;
  Progress_INDEX.Show;
  // try
  UnLoadHashMAPS_OBJ();
  // except showmessage('Îøèáêà âûãðóçê ÁÀÇ  ') end;
  NewThread := TIndexThread.Create(False);
  // NewThread.FIlearchive:=GB_Appdir+ListView1.items.Item[I_DP].SubItems.Strings[0]+'\'+ListView1.items.Item[I_DP].Caption;
  // NewThread.TMPfolder:=GB_TMPfolder;
  NewThread.Myselected := SelectedStrings;
  NewThread.Priority := tpNormal;

end;

procedure TForm1.RzBitBtn3Click(Sender: TObject);
var
  Ynode: PVirtualNode;
begin
  case VST_DP.Tag of
    0:
      begin
        VST_DP.Tag := 1;
        Ynode := VST_DP.GetFirst(true);
        repeat
          Ynode.CheckState := csCheckedNormal;
          VST_DP.RepaintNode(Ynode);
          Ynode := VST_DP.GetNext(Ynode, true);
        until Ynode = nil;
      end;

    1:
      begin
        VST_DP.Tag := 0;
        VST_DP.ClearChecked;
      end;
  end;

end;

procedure TForm1.RzBitBtn9Click(Sender: TObject);
var
  Ynode: PVirtualNode;
  Data1: PTreeDP;

begin
  VST_DP.ClearChecked;
  Ynode := VST_DP.GetFirst(true);
  if Ynode = nil then
    exit;

  repeat
    Data1 := VST_DP.GetNodeData(Ynode);

    if (Data1.indexed = False) and not(Ynode.Parent = VST_DP.RootNode) then
    begin

      Ynode.CheckState := csCheckedNormal;
      VST_DP.RepaintNode(Ynode);
    end;

    Ynode := VST_DP.GetNext(Ynode, true);
  until Ynode = nil;

end;

procedure TForm1.VTV_updateGetImageIndex(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
  var Ghosted: boolean; var ImageIndex: integer);
var
  data: Pdevice;
begin
  if Column <> 0 then
    exit;

  data := Sender.GetNodeData(Node);
  ImageIndex := data^.Driver_image;
end;

procedure TForm1.VTV_updateGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);

var
  data: Pdevice;
begin
  data := Sender.GetNodeData(Node);

  case Column of
    0:
      begin
        CellText := data^.Driver_NAME;
        // CellText := AnsiReplaceStr(CellText, 'DP_', '');
        // CellText := AnsiReplaceStr(CellText, ZIP7_ext, '');

        { if vsselected in  node.States then
          CellText:=CellText+#13+ExtractFileName(Data^.Driver_Pack); }

        // node.NodeHeight:= (Sender as TVirtualStringTree).ComputeNodeHeight((Sender as TVirtualStringTree).Canvas, Node, 0);

      end;
    1:
      begin
        if not(Sender.HasChildren[Node]) then

          if ShowDP.Checked then
            CellText := ExtractFileName(data^.Driver_Pack) // 'Pack_not_woking'
            /// CellText := AnsiReplaceStr(data^.Driver_Pack,
            // GB_Appdir + '\' + GB_DRP_DIR + '\', '')
          else
          begin
            CellText := data^.Driver_HWID;
            // ShowMessage(data^.Driver_HWID);
          end;
        { if vsselected in  node.States then
          CellText:=CellText+#13+Data^.Driver_Dir+Data^.Driver_INF;// 'Hie DIAS' }
      end;

    2:

      case data^.Driver_status of
        0:
          begin
            CellText := data^.Driver_date + '  ' + data^.Driver_ver;
            { if vsselected in  node.States then
              CellText:=CellText+#13+Data^.Driver_MFG; }
          end;
        1:
          CellText := 'Extracting Driver';
        2:
          CellText := 'Installing Driver';
        3:
          CellText := 'Driver Installed';
        4:
          CellText := 'Driver NOT Installed';
      end;

  end;
end;

procedure TForm1.VTV_updateBeforeCellPaint(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect);
var
  Myrect: TRect;
  PhoneNode: Pdevice;
begin

  if Sender.HasChildren[Node] then
    if Column = 0 then
    begin
      PhoneNode := Sender.GetNodeData(Node);

      Myrect := CellRect;
      Myrect.Top := ((Myrect.Bottom - Myrect.Top) div 2);
      Myrect.Bottom := Myrect.Top + 1;
      TargetCanvas.Font.Style := [fsBold];
      Myrect.Left := Myrect.Left + TargetCanvas.TextWidth
        (PhoneNode^.Driver_NAME) + 50;
      // $00F1F1F1
      // data^.Driver_NAME
      DrawGradient(TargetCanvas, Myrect, $00F1F1F1, clWhite, gdLeftRight);
    end;

end;

procedure TForm1.VTV_updateGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle;
  var HintText: String);
var
  DeviceNODE: Pdevice;
  DP_shortname: string;
  Text: string;
  text2: string;
begin
  // HintText:='asdf'#13+'Ïðèâåò'+IntToStr(Column)+'__node '+IntToStr(node.index);

  if Sender.HasChildren[Node] then
    exit;

  DeviceNODE := Sender.GetNodeData(Node);

  case Column of
    0:
      begin
        DP_shortname := DeviceNODE^.Driver_Pack;
        Delete(DP_shortname, 1, length(GB_Appdir + GB_DRP_DIR) + 2);
        HintText := 'DriverPack:       '#9 + DP_shortname + #13 +
          'INF Path:           ' + DeviceNODE^.Driver_Dir +
          DeviceNODE^.Driver_INF + #13 + 'Manufacturer   [' +
          DeviceNODE^.Driver_MFG + ']';

      end;

    1:
      begin
        Text := StringReplace(DeviceNODE^.Device_HWID, ',', #9#13,
          [rfReplaceAll]);
        Text := StringReplace(Text, ' ', '', [rfReplaceAll]);
        Text := StringReplace(Text, '&', '$', [rfReplaceAll]);

        text2 := StringReplace(DeviceNODE^.Device_HWID_compatible, ',', #9#13,
          [rfReplaceAll]);
        text2 := StringReplace(text2, ' ', '', [rfReplaceAll]);
        text2 := StringReplace(text2, '&', '$', [rfReplaceAll]);

        if pos('SUBSYS', DeviceNODE^.Driver_HWID) > 0 then
        begin
          // ShowMessage(DeviceNODE^.Device_HWID);

          HintText := #9 + '100% Compatible Driver'#13'Installed HWID'#13 + Text
            + #13 + 'Compatible' + #13 + text2;
          // ShowMessage(HintText);
        end
        else
        begin
          HintText := #9 + 'Simple compatible Driver'#13'Istalled HWID'#13 +
            Text + #13 + 'Compatible' + #13 + text2;
        end;
      end;

    2:
      begin
        // RzBalloonHints1.font.Color:=$00A0495C;
        HintText := 'Installed Version' + #13 + DeviceNODE^.Device_date + '  ' +
          DeviceNODE^.Device_Ver;
      end;

  end;

end;

procedure TForm1.VTV_updatePaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
var
  DeviceNODE: Pdevice;
  // DP_shortname:string;

begin

  DeviceNODE := Sender.GetNodeData(Node);
  if not(Sender.Selected[Node]) then
    if Column = 1 then
      if pos('SUBSYS', DeviceNODE^.Driver_HWID) > 0 then
        TargetCanvas.Font.Color := clgreen
      else
        Sender.Font.Color := clWindowText;

  if Sender.HasChildren[Node] then
  begin
    // TargetCanvas.Font.Color:=clwhite;
    TargetCanvas.Font.Style := [fsBold];
    TargetCanvas.Font.Color := $007D5A46;
  end;

end;

procedure TForm1.VTV_updateDrawText(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  const Text: String; const CellRect: TRect; var DefaultDraw: boolean);
var
  Mydevice: Pdevice;
  rect1: TRect;
begin
  if Column = 2 then
  begin
    Mydevice := Sender.GetNodeData(Node);

    rect1 := CellRect;
    dec(rect1.Left, 3);
    DrawProgressStatus(TargetCanvas, rect1, Mydevice^.Driver_Progress,
      Mydevice^.Driver_status);
    SetBkMode(TargetCanvas.Handle, TRANSPARENT);
    TargetCanvas.Font.Color := clWindowText;

  end;
  DefaultDraw := true;
end;

procedure TForm1.RzBitBtn2Click(Sender: TObject);
var
  Ynode: PVirtualNode;
begin
  case VTV_setup.Tag of
    0:
      begin
        VTV_setup.Tag := 1;
        Ynode := VTV_setup.GetFirst(true);
        repeat
          if not(Ynode.CheckType = ctNone) then
            Ynode.CheckState := csCheckedNormal;
          VTV_setup.RepaintNode(Ynode);
          Ynode := VTV_setup.GetNext(Ynode, true);
        until Ynode = nil;
      end;

    1:
      begin
        VTV_setup.Tag := 0;
        VTV_setup.ClearChecked;
      end;
  end;
end;

procedure OpenPage(const AParent: TForm; AURL: string);
begin
  ShellExecute(AParent.Handle, 'open', Pchar(AURL), nil, nil, SW_SHOWDEFAULT);
end;

procedure TForm1.VTV_updateDblClick(Sender: TObject);
{ var
  Ynode:PVirtualNode;
  Mydevice:Pdevice;
  VTV0:TVirtualStringTree;
} begin
  { VTV0:=sender as TVirtualStringTree;

    if VTV0=VTV_setup  then
    begin
    if Assigned(UpdateThread1) then
    if UpdateThread1.Terminated=false then  exit;
    end
    else
    begin
    if Assigned(UpdateThread2) then
    if UpdateThread2.Terminated=false then  exit;
    end;

    ynode:=VTV0.GetFirstSelected(false);
    if Ynode=nil then exit;

    Mydevice:=VTV0.GetNodeData(Ynode);

    if Mydevice^.Driver_image= 19 then
    begin
    DEVID1Click(sender);
    exit;
    end
    else
    begin
    VTV0.ClearChecked;

    Ynode.CheckState:=csCheckedNormal;

    if VTV0=VTV_setup then
    Button9Click(nil)
    else
    Button4Click(nil);
    end;

  }

end;

procedure TForm1.VTV_updateCompareNodes(Sender: TBaseVirtualTree;
  Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: integer);
var
  Rec1, Rec2: Pdevice;
begin
  with Sender do
  begin
    Rec1 := GetNodeData(Node1);
    Rec2 := GetNodeData(Node2);
  end;
  case Column of
    55:
      Result := WideCompareText(ExtractFileName(Rec1.Driver_Pack),
        ExtractFileName(Rec2.Driver_Pack));

    0:
      Result := WideCompareText(Rec1.Driver_NAME, Rec2.Driver_NAME);
    1:
      Result := WideCompareText(Rec1.Driver_HWID, Rec2.Driver_HWID);
    2:
      Result := WideCompareText(Rec1.Driver_date, Rec2.Driver_date);
  end;
end;

procedure TForm1.VTV_updateHeaderClick(Sender: TVTHeader; Column: TColumnIndex;
  Button: TMouseButton; Shift: TShiftState; X, Y: integer);
begin
  if Button = mbLeft then
  begin
    if Sender.SortColumn <> Column then
      Sender.SortColumn := Column;
    if Sender.SortDirection = sdAscending then
      Sender.SortDirection := sdDescending
    else
      Sender.SortDirection := sdAscending;
    VTV_update.SortTree(Sender.SortColumn, Sender.SortDirection, true);
  end;
end;

procedure TForm1.RzBitBtn5Click(Sender: TObject);
begin
  VTV_update.Header.SortDirection := sdAscending;
  VTV_update.SortTree(55, VTV_update.Header.SortDirection, true);

end;

procedure TForm1.Edit1Change(Sender: TObject);
var
  Mnode: PVirtualNode;
begin
  Mnode := FindNode(VTV_update, VTV_update.RootNode, 'CHILD');

  if Assigned(Mnode) then
  begin
    // VTV_update.ScrollIntoView(Mnode,true,true);

    VTV_update.ClearSelection;
    VTV_update.FocusedNode := Mnode;

  end;
  // Include(VT.FocusedNode.States, vsSelected);

end;

procedure TForm1.VTV_updateMeasureItem(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; var NodeHeight: integer);
begin
  if Sender.HasChildren[Node] then
    NodeHeight := 24;
end;

procedure TForm1.VTV_updateChecking(Sender: TBaseVirtualTree;
  Node: PVirtualNode; var NewState: TCheckState; var Allowed: boolean);
var
  Ynode: PVirtualNode;
begin // main
  Ynode := Node.FirstChild;
  if Sender.HasChildren[Node] then
  begin // 1
    if NewState = csunCheckedNormal then // IF
      repeat
        Ynode.CheckState := csunCheckedNormal;
        Sender.RepaintNode(Ynode);
        Ynode := Sender.GetNextSibling(Ynode);
      until Ynode = nil

    else // ESLE
      if Ynode.CheckType = ctRadioButton then
      begin // 2
        Ynode.CheckState := csCheckedNormal;
        Sender.RepaintNode(Ynode);
        Ynode := Sender.GetNextSibling(Ynode);
        if Ynode <> nil then
          repeat
            Ynode.CheckState := csunCheckedNormal;
            Sender.RepaintNode(Ynode);
            Ynode := Sender.GetNextSibling(Ynode);
          until Ynode = nil;
      end; // 2
  end; // 1

  if not(Sender.HasChildren[Node]) and (Node.CheckType = ctRadioButton) then
    if NewState = csCheckedNormal then
      Node.Parent.CheckState := csCheckedNormal;

end; // main

procedure TForm1.RzBitBtn8Click(Sender: TObject);
var
  i: integer;
begin

  for i := 0 to GB_DriverList.Count - 1 do
  begin
    // GB_DriverList.Items[i].DriverDate:=0;
    Memo1.Lines.Add(IntToStr(i) + '  ' + DateToStr(GB_DriverList.items[i]
      .DriverDate));
  end;

end;

procedure TForm1.RzBitBtn7Click(Sender: TObject);
begin
  Memo1.Clear;
end;

procedure TForm1.SaveDevices1Click(Sender: TObject);
begin
  GB_DriverList := GetDeviceList;
  GetDeviceList.SaveToFile('c:\Devices.INI');
end;

procedure TForm1.LoadDevices1Click(Sender: TObject);
begin
  case LoadDevices1.Checked of
    true:
      LoadDevices1.Checked := False;
    False:
      LoadDevices1.Checked := true;
  end;

end;

end.
