Unit CollectThread;

{
  Implementuje vlakno sbirajici zaznamy udalosti nad registrem
  z utrob ovladace registrymon.sys. Vlakno tyto udalosti cacheuje
  a predava hlavnimu formulari, ktery je zobrazuje.
}

Interface

Uses
  Classes;

Type
  TCollectThread = Class (TThread)
    Private
      FList : TList;
      Procedure CollectEvents;
      Procedure ParseEvents;
    Protected
      Procedure Execute; Override;
    end;


Implementation

Uses
  MainForm, SysUtils, Utils,
  Windows, RegEvents, DriverCommands;

Procedure TCollectThread.Execute;
{
  Hlavni smycka vlakna. Vzdy vterinu pocka,
  nacte vsechny udalosti, ktere ovladac za tu dobu vygeneroval
  a prida je do seznamu udalosti na hlavnim formulari.
}
begin
FreeOnTerminate := False;
FList := TList.Create;
While Not Terminated Do
  begin
  Sleep(1000);
  CollectEvents;
  Synchronize(ParseEvents);
  FList.Clear;
  end;

FList.Free;
end;

Procedure TCollectThread.ParseEvents;
{
  Tato metoda je volana v ramci Synchronize, vykonava se tedy
  v primarnim vlakne, ktere je take jedinym vlaknem obsluhujicim
  GUI.
}
begin
Form1.AddEvents(FList);
end;

Procedure TCollectThread.CollectEvents;
{
  Zajisti presunuti zaznamu o udalostech nad registrem do vlastniho
  seznamu vlakna. Zkopirovane udalosti si ovladac ze sveho seznamu
  automaticky maze.
}
Var
  EventSize : Integer;
  U : PUM_EVENT;
  OI : PREG_EVENT_GENERAL_INFO;
  Ret : Boolean;
begin
EventSize := 512;
U := MemAlloc(EventSize);
Ret := Assigned(U);
While Ret Do
  begin
  ZeroMemory(U, EventSize);
  U.EventSize := EventSize;
  Ret := RegistrymonDriverGetEvent(U, EventSize);
  If Ret Then
    begin
    EventSize := 512;
    FList.Add(U);
    U := MemAlloc(EventSize);
    Ret := Assigned(U);
    end
  Else if GetLastError = ERROR_INSUFFICIENT_BUFFER Then
    begin
    // Alokovana pamet je prilis mala. Je treba ji realokovat, aby
    // se do ni zaznam o operaci nad registrem vesel.
    EventSize := EventSize * 2;
    MemFree(U);
    U := MemAlloc(EventSize);
    Ret := Assigned(U);
    end
  Else If GetLastError = ERROR_NO_MORE_ITEMS Then
    begin
    Ret := True;
    Break;
    end
  Else If GetLastError <> ERROR_INVALID_HANDLE then
    Utils.Error(Format('%s (%d)', [SysErrorMessage(GetLastError), GetLastError]));
  end;
end;


Initialization
IsMultiThread := True;
End.

