Unit ObjectInfoForm;

{
  V tomto souboru je implementovan formular, ktery zobrazuje ruzne
  podrobne informace o zadanem objektu. Take se stara o ziskavani
  techto udaju.
}

Interface

Uses
  Windows, Messages, SysUtils, Variants, Classes,
  Graphics, Controls, Forms,
  Dialogs, ComCtrls, Objects, StdCtrls;

Type
  TForm2 = Class (TForm)
    PageControl1: TPageControl;
    ObjectHeaderTabSheet: TTabSheet;
    ObjectHandleInfoTabSheet: TTabSheet;
    ObjectNameInfoTabSheet: TTabSheet;
    ObjectQuotaInfoTabSheet: TTabSheet;
    ObjectTypeTabSheet: TTabSheet;
    EventObjectInfoTabSheet: TTabSheet;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    CheckBox4: TCheckBox;
    CheckBox5: TCheckBox;
    CheckBox6: TCheckBox;
    CheckBox7: TCheckBox;
    CheckBox8: TCheckBox;
    ListView1: TListView;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    CheckBox1: TCheckBox;
    CheckBox9: TCheckBox;
    CheckBox10: TCheckBox;
    CheckBox11: TCheckBox;
    CheckBox12: TCheckBox;
    CheckBox13: TCheckBox;
    CheckBox14: TCheckBox;
    ListView2: TListView;
    Label9: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Label12: TLabel;
    Label13: TLabel;
    Label14: TLabel;
    Label15: TLabel;
    Label16: TLabel;
    Label17: TLabel;
    Label18: TLabel;
    Label19: TLabel;
    Label20: TLabel;
    Label21: TLabel;
    Label22: TLabel;
    Label23: TLabel;
    Label24: TLabel;
    Label25: TLabel;
    Label26: TLabel;
    Label27: TLabel;
    Label28: TLabel;
    Label29: TLabel;
    Label30: TLabel;
    HandleInfoListView: TListView;
    Label31: TLabel;
    Label32: TLabel;
    Label33: TLabel;
    Label34: TLabel;
    Label35: TLabel;
    Label36: TLabel;
    Label37: TLabel;
    Label38: TLabel;
    Label39: TLabel;
    Label40: TLabel;
    Label41: TLabel;
    Label42: TLabel;
    Label43: TLabel;
    Label44: TLabel;
    Label45: TLabel;
    Label46: TLabel;
    SemaphoreObjectInfoTabSheet: TTabSheet;
    MutantObjectInfoTabSheet: TTabSheet;
    TypeObjectInfoTabSheet: TTabSheet;
    Label47: TLabel;
    Label48: TLabel;
    Label49: TLabel;
    Label50: TLabel;
    Label51: TLabel;
    Label52: TLabel;
    Label53: TLabel;
    Label54: TLabel;
    Label55: TLabel;
    Label56: TLabel;
    Label57: TLabel;
    Label58: TLabel;
    Label59: TLabel;
    Label60: TLabel;
    CheckBox15: TCheckBox;
    CheckBox16: TCheckBox;
    CheckBox17: TCheckBox;
    CheckBox18: TCheckBox;
    CheckBox19: TCheckBox;
    CheckBox20: TCheckBox;
    CheckBox21: TCheckBox;
    Label61: TLabel;
    Label62: TLabel;
    ListView4: TListView;
    Label63: TLabel;
    Label64: TLabel;
    Label65: TLabel;
    Label66: TLabel;
    Label67: TLabel;
    Label68: TLabel;
    Label69: TLabel;
    Label70: TLabel;
    Label71: TLabel;
    Label72: TLabel;
    Label73: TLabel;
    Label74: TLabel;
    Label75: TLabel;
    Label76: TLabel;
    Label77: TLabel;
    Label78: TLabel;
    Label79: TLabel;
    Label80: TLabel;
    Label81: TLabel;
    Label82: TLabel;
    DirectoryObjectInfoTabSheet: TTabSheet;
    DirectoryObjectInfoListView: TListView;
    Procedure FormCreate(Sender: TObject);
    Procedure DirectoryObjectInfoListViewCompare(Sender: TObject; Item1,
      Item2: TListItem; Data: Integer; var Compare: Integer);
    Procedure DirectoryObjectInfoListViewColumnClick(Sender: TObject;
      Column: TListColumn);
    Procedure HandleInfoListViewColumnClick(Sender: TObject;
      Column: TListColumn);
    Procedure HandleInfoListViewCompare(Sender: TObject; Item1,
      Item2: TListItem; Data: Integer; var Compare: Integer);
  Private
    FObjectName : WideString;
    FObjectHandle : Int64;
    FTypeInfo : OBJECT_TYPE_INFO;
    FHeaderInfo : OBJECT_HEADER_INFO;
    FHandleInfo : POBJECT_HANDLE_INFO;
    FQuotaInfo : OBJECT_QUOTA_INFO;
    FEventObjectInfo : OBJECT_EVENT_INFO;
    FSemaphoreObjectInfo : OBJECT_SEMAPHORE_INFO;
    FMutantObjectInfo : OBJECT_MUTANT_INFO;
    FTypeObjectInfo : OBJECT_TYPE_INFO;
    FDirectoryObjectInfo : TStrings;
    FName : WideString;
    FFullName : WideString;
    FPointerLength : Integer;

    FHandleDBSortColumn : Integer;
    FHandleDBSortAscend : Boolean;

    FDirectorySortColumn : Integer;
    FDirectorySortAscend : Boolean;

    FMajorVersion : Cardinal;
    FMinorVersion : Cardinal;
    FBuildNumber : Cardinal;
    Procedure DisplayHeaderInfo;
    Procedure DisplayTypeInfo;
    Procedure DisplayHandleInfo;
    Procedure DisplayQuotaInfo;
    Procedure DisplayNameInfo;
    Procedure DisplayEventObjectInfo;
    Procedure DisplaySemaphoreObjectInfo;
    Procedure DisplayMutantObjectInfo;
    Procedure DisplayTypeObjectInfo;
    Procedure DisplayDirectoryObjectInfo;
  Public
    Constructor Create(AOwner:TComponent; AObjectName:WideString); Reintroduce; Virtual;
    Destructor Destroy; Override;
  end;

Implementation

{$R *.DFM}

Uses
  Utils;

Constructor TForm2.Create(AOwner:TComponent; AObjectName:WideString);
begin
Inherited Create(AOwner);
FPointerLength := GetPointerLength;
FObjectName := AObjectName;
FObjectHandle := ObjectOpen(FObjectName);
If FObjectHandle = 0 Then
  Raise Exception.Create(Format('Failed to open object %s', [FObjectName]));
end;

Destructor TForm2.Destroy;
begin
If FObjectHandle <> 0 Then
  ObjectClose(FObjectHandle);

Inherited Destroy;
end;

Procedure TForm2.DisplayEventObjectInfo;
begin
Label48.Caption := Format('%s (%d)', [EventTypeToStr(FEventObjectInfo.EventType), FEventObjectInfo.EventType]);
Label50.Caption := IntToStr(FEventObjectInfo.Signaled And 1);
end;

Procedure TForm2.DisplaySemaphoreObjectInfo;
begin
Label52.Caption := IntToStr(Int64(FSemaphoreObjectInfo.Counter));
Label54.Caption := IntToStr(Int64(FSemaphoreObjectInfo.Limit));
end;

Procedure TForm2.DisplayMutantObjectInfo;
begin
Label58.Caption := IntToStr(FMutantObjectInfo.Signaled And 1);
Label59.Caption := '<žádný>';
If FMutantObjectInfo.OwnerThreadId <> 0 Then
  Label59.Caption := Format('%d:%d (%s)', [GetThreadProcessId(FMutantObjectInfo.OwnerThreadId), FMutantObjectInfo.OwnerThreadId, GetProcessName(GetThreadProcessId(FMutantObjectInfo.OwnerThreadId))]);

Label60.Caption := IntToStr(Int64(FMutantObjectInfo.Abandoned));
end;

Procedure TForm2.DisplayTypeObjectInfo;
Var
  Tag : Packed Array [0..3] Of Char;
begin
CheckBox21.Checked := FTypeObjectInfo.InitializerFlags.CaseSensitive <> 0;
CheckBox20.Checked := FTypeObjectInfo.InitializerFlags.UseDefaultObject <> 0;
CheckBox19.Checked := FTypeObjectInfo.InitializerFlags.MaintainHandleCount <> 0;
CheckBox18.Checked := FTypeObjectInfo.InitializerFlags.MaintainTypeList <> 0;
CheckBox17.Checked := FTypeObjectInfo.InitializerFlags.UnnamedObjectsOnly <> 0;
CheckBox15.Checked := FTypeObjectInfo.InitializerFlags.SupportsObjectCallbacks <> 0;
CheckBox16.Checked := FTypeObjectInfo.InitializerFlags.SecurityRequired <> 0;
ListView4.Items[0].SubItems[0] := '0x' + IntToHex(Int64(FTypeObjectInfo.InitializerMethods.Open), FPointerLength * 2);
ListView4.Items[1].SubItems[0] := '0x' + IntToHex(Int64(FTypeObjectInfo.InitializerMethods.Close), FPointerLength * 2);
ListView4.Items[2].SubItems[0] := '0x' + IntToHex(Int64(FTypeObjectInfo.InitializerMethods.OkayToClose), FPointerLength * 2);
ListView4.Items[3].SubItems[0] := '0x' + IntToHex(Int64(FTypeObjectInfo.InitializerMethods.Delete), FPointerLength * 2);
ListView4.Items[4].SubItems[0] := '0x' + IntToHex(Int64(FTypeObjectInfo.InitializerMethods.Security), FPointerLength * 2);
ListView4.Items[5].SubItems[0] := '0x' + IntToHex(Int64(FTypeObjectInfo.InitializerMethods.QueryName), FPointerLength * 2);
ListView4.Items[6].SubItems[0] := '0x' + IntToHex(Int64(FTypeObjectInfo.InitializerMethods.Parse), FPointerLength * 2);
ListView4.Items[7].SubItems[0] := '0x' + IntToHex(Int64(FTypeObjectInfo.InitializerMethods.Dump), FPointerLength * 2);
Label78.Caption := IntToStr(Int64(FTypeObjectInfo.TypeStatistics.TotalNumberOfObjects));
Label77.Caption := IntToStr(Int64(FTypeObjectInfo.TypeStatistics.HighWaterNumberOfObjects));
Label76.Caption := IntToStr(Int64(FTypeObjectInfo.TypeStatistics.TotalNumberOfHandles));
Label75.Caption := IntToStr(Int64(FTypeObjectInfo.TypeStatistics.HighWaterNumberOfHandles));
Label72.Caption := FTypeObjectInfo.Name;
Label73.Caption := IntToStr(Int64(FTypeObjectInfo.Index));
Tag[0] := Chr(FTypeObjectInfo.Key And $FF);
Tag[1] := Chr((FTypeObjectInfo.Key And $FF00) Shr 8);
Tag[2] := Chr((FTypeObjectInfo.Key And $FF0000) Shr 16);
Tag[3] := Chr((FTypeObjectInfo.Key And $FF000000) Shr 24);
Label74.Caption := Tag;
Label67.Caption := '0x' + IntToHex(FTypeObjectInfo.DefaultObject, FPointerLength * 2);
Label66.Caption := IntToStr(Int64(FTypeObjectInfo.InitializerOtherInfo.DefaultPagedPoolCharge));
Label63.Caption := IntToStr(Int64(FTypeObjectInfo.InitializerOtherInfo.DefaultNonPagedPoolCharge));
Case FTypeObjectInfo.InitializerOtherInfo.PoolType Of
  0 : Label62.Caption := 'Nestránkovaný';
  1 : Label62.Caption := 'Stránkkovaný';
  Else Label62.Caption := '<neznámý>';
  end;
end;

Procedure TForm2.DirectoryObjectInfoListViewColumnClick(Sender: TObject;
  Column: TListColumn);
begin
DirectoryObjectInfoListView.SortType := stNone;
If Column.Index <> FDirectorySortColumn Then
  begin
  FDirectorySortColumn := Column.Index;
  FDirectorySortAscend := True;
  end
Else FDirectorySortAscend := Not FDirectorySortAscend;
DirectoryObjectInfoListView.SortType := stText;
end;

Procedure TForm2.DirectoryObjectInfoListViewCompare(Sender: TObject; Item1,
  Item2: TListItem; Data: Integer; var Compare: Integer);
Var
  S1, S2 : WideString;
begin
Case FDirectorySortColumn Of
  0 : begin
  S1 := Item1.Caption;
  S2 := Item2.Caption;
  end;
  1 : begin
    S1 := Item1.SubItems[0];
    S2 := Item2.SubItems[0];
    end;
  end;

Compare := StrComp(PWideChar(S1), PWideChar(S2));
If Not FDirectorySortAscend Then
  Compare := -Compare;
end;

Procedure TForm2.DisplayDirectoryObjectInfo;
Var
  I : Integer;
  OHandle : Int64;
  FullOName : WideString;
  ObjectTypeName : WideString;
  OTI : OBJECT_TYPE_INFO;
begin
DirectoryObjectInfoListView.Items.BeginUpdate;
For I := 0 To FDirectoryObjectInfo.Count - 1 Do
  begin
  With DirectoryObjectInfoListView.Items.Add Do
    begin
    Caption := FDirectoryObjectInfo[I];
    ObjectTypeName := '<nezjisteno>';
    If FObjectName <> '\' Then
      FullOName := Format('%s\%s', [FObjectName, FDirectoryObjectInfo[I]])
    Else FullOName := Format('\%s', [FDirectoryObjectInfo[I]]);

    OHandle := ObjectOpen(FullOName);
    If OHandle > 0 Then
      begin
      If ObjectGetTypeInfo(OHandle, @OTI) Then
        ObjectTypeName := OTI.Name;

      ObjectClose(OHandle);
      end;

    SubItems.Add(ObjectTypeName);
    end;
  end;

DirectoryObjectInfoListView.Items.EndUpdate;
end;

Procedure TForm2.DisplayNameInfo;
begin
Label45.Caption := FName;
Label46.Caption := FFullName;
end;

Procedure TForm2.DisplayQuotaInfo;
begin
Label40.Caption := IntToStr(Int64(FQuotaInfo.PagedPoolCharge));
Label39.Caption := IntToStr(Int64(FQuotaInfo.NonPagedPoolCharge));
Label38.Caption := IntToStr(Int64(FQuotaInfo.SecurityDescriptorCharge));
If (FMajorVersion < 6) Or (FMinorVersion < 1) Then
  begin
  Label42.Caption := '<žádný>';
  If FQuotaInfo.ExclusiveProcessId <> 0 Then
    Label42.Caption := Format('%s (%d)', [GetProcessName(FQuotaInfo.ExclusiveProcessId), FQuotaInfo.ExclusiveProcessId]);
  end
Else begin
  Label41.Visible := False;
  Label42.Visible := False;
  end;
end;

Procedure TForm2.DisplayHandleInfo;
Var
  I : Integer;
begin
For I := 0 To FHandleInfo.Count - 1 Do
  begin
  If FHandleInfo.Entries[I].ProcessId <> 0 Then
    begin
    With HandleInfoListView.Items.Add Do
      begin
      Caption := Format('%s (%d)', [GetProcessName(FHandleInfo.Entries[I].ProcessId), FHandleInfo.Entries[I].ProcessId]);
      SubItems.Add(IntToStr(Int64(FHandleInfo.Entries[I].HandleCount)));
      end;
    end;
  end;
end;

Procedure TForm2.DisplayTypeInfo;
Var
  Tag : Packed Array [0..3] Of Char;
begin
CheckBox1.Checked := FTypeInfo.InitializerFlags.CaseSensitive <> 0;
CheckBox9.Checked := FTypeInfo.InitializerFlags.UseDefaultObject <> 0;
CheckBox10.Checked := FTypeInfo.InitializerFlags.MaintainHandleCount <> 0;
CheckBox11.Checked := FTypeInfo.InitializerFlags.MaintainTypeList <> 0;
CheckBox12.Checked := FTypeInfo.InitializerFlags.UnnamedObjectsOnly <> 0;
CheckBox13.Checked := FTypeInfo.InitializerFlags.SupportsObjectCallbacks <> 0;
CheckBox14.Checked := FTypeInfo.InitializerFlags.SecurityRequired <> 0;
ListView2.Items[0].SubItems[0] := '0x' + IntToHex(FTypeInfo.InitializerMethods.Open, FPointerLength * 2);
ListView2.Items[1].SubItems[0] := '0x' + IntToHex(FTypeInfo.InitializerMethods.Close, FPointerLength * 2);
ListView2.Items[2].SubItems[0] := '0x' + IntToHex(FTypeInfo.InitializerMethods.OkayToClose, FPointerLength * 2);
ListView2.Items[3].SubItems[0] := '0x' + IntToHex(FTypeInfo.InitializerMethods.Delete, FPointerLength * 2);
ListView2.Items[4].SubItems[0] := '0x' + IntToHex(FTypeInfo.InitializerMethods.Security, FPointerLength * 2);
ListView2.Items[5].SubItems[0] := '0x' + IntToHex(FTypeInfo.InitializerMethods.QueryName, FPointerLength * 2);
ListView2.Items[6].SubItems[0] := '0x' + IntToHex(FTypeInfo.InitializerMethods.Parse, FPointerLength * 2);
ListView2.Items[7].SubItems[0] := '0x' + IntToHex(FTypeInfo.InitializerMethods.Dump, FPointerLength * 2);
Label13.Caption := IntToStr(Int64(FTypeInfo.TypeStatistics.TotalNumberOfObjects));
Label14.Caption := IntToStr(Int64(FTypeInfo.TypeStatistics.HighWaterNumberOfObjects));
Label15.Caption := IntToStr(Int64(FTypeInfo.TypeStatistics.TotalNumberOfHandles));
Label16.Caption := IntToStr(Int64(FTypeInfo.TypeStatistics.HighWaterNumberOfHandles));
Label24.Caption := FTypeInfo.Name;
Label23.Caption := IntToStr(Int64(FTypeInfo.Index));
Tag[0] := Chr(FTypeInfo.Key And $FF);
Tag[1] := Chr((FTypeInfo.Key And $FF00) Shr 8);
Tag[2] := Chr((FTypeInfo.Key And $FF0000) Shr 16);
Tag[3] := Chr((FTypeInfo.Key And $FF000000) Shr 24);
Label22.Caption := Tag;
Label21.Caption := '0x' + IntToHex(FTypeInfo.DefaultObject, FPointerLength * 2);
Label30.Caption := IntToStr(Int64(FTypeInfo.InitializerOtherInfo.DefaultPagedPoolCharge));
Label29.Caption := IntToStr(Int64(FTypeInfo.InitializerOtherInfo.DefaultNonPagedPoolCharge));
Case FTypeInfo.InitializerOtherInfo.PoolType Of
  0 : Label28.Caption := 'Nestránkovaný';
  1 : Label28.Caption := 'Stránkovaný';
  Else Label28.Caption := '<neznámý>';
  end;
end;

Procedure TForm2.DisplayHeaderInfo;
Var
  CreatorOffset : Integer;
begin
Label4.Caption := IntToStr(FHeaderInfo.PointerCount);
Label3.Caption := IntToStr(FHeaderInfo.HandleCount);
CheckBox2.Checked := (FHeaderInfo.Flags And OB_FLAG_NEW_OBJECT) > 0;
CheckBox3.Checked := (FHeaderInfo.Flags And OB_FLAG_KERNEL_OBJECT) > 0;
CheckBox4.Checked := (FHeaderInfo.Flags And OB_FLAG_CREATOR_INFO) > 0;
CheckBox5.Checked := (FHeaderInfo.Flags And OB_FLAG_EXCLUSIVE_OBJECT) > 0;
CheckBox6.Checked := (FHeaderInfo.Flags And OB_FLAG_PERMANENT_OBJECT) > 0;
CheckBox7.Checked := (FHeaderInfo.Flags And OB_FLAG_DEFAULT_SECURITY_QUOTA) > 0;
CheckBox8.Checked := (FHeaderInfo.Flags And OB_FLAG_SINGLE_HANDLE_ENTRY) > 0;
ListView1.Items[0].SubItems[0] := '0x' + IntToHex(FHeaderInfo.CreatorInfoOffset, 2);
Listview1.Items[1].SubItems[0] := '0x' + IntToHex(FHeaderInfo.NameInfoOffset, 2);
Listview1.Items[2].SubItems[0] := '0x' + IntToHex(FHeaderInfo.HandleInfoOffset, 2);
Listview1.Items[3].SubItems[0] := '0x' + IntToHex(FHeaderInfo.QuotaInfoOffset, 2);
Listview1.Items[4].SubItems[0] := '0x' + IntToHex(FHeaderInfo.ProcessInfoOffset, 2);
Label7.Caption := '0x' + IntToHex(FHeaderInfo.Flags, 8);
If (FMajorVersion < 6) Or (FMinorVersion < 1) Then
  begin
  Label6.Visible := False;
  Label8.Visible := False;
  end
Else Label8.Caption := '0x' + IntToHex(FHeaderInfo.InfoMask, 2);

Label32.Caption := '<ne>';
If FHeaderInfo.ExclusiveProcessId <> 0 Then
  Label32.Caption := Format('%s (%d)', [GetProcessName(FHeaderInfo.ExclusiveProcessId), FHeaderInfo.ExclusiveProcessId]);

Label34.Caption := 'N / A';
If FHeaderInfo.CreatorProcessId <> 0 Then
  Label34.Caption := Format('%s (%d)', [GetProcessName(FHeaderInfo.CreatorProcessId), FHeaderInfo.CreatorProcessId]);
end;

Procedure TForm2.FormCreate(Sender: TObject);
Var
  I : Integer;
  Ret : Boolean;
begin
GetOSVersion(FMajorVersion, FMinorVersion, FBuildNumber);
FHandleDBSortColumn := 0;
FHandleDBSortAscend := True;
FDirectorySortColumn := 0;
FDirectorySortAscend := True;
Caption := FObjectName;
For I := 0 To PageControl1.PageCount - 1 Do
  PageControl1.Pages[I].Enabled := False;

Ret := ObjectGetHeaderInfo(FObjectHandle, @FHeaderInfo);
ObjectHeaderTabSheet.Enabled := Ret;
ObjectHandleInfoTabSheet.Enabled := Ret;
ObjectNameInfoTabSheet.Enabled := Ret;
ObjectQuotaInfoTabSheet.Enabled := Ret;
If Ret Then
  begin
  ObjectHandleInfoTabSheet.Enabled := FHeaderInfo.HandleInfoOffset <> 0;
  ObjectNameInfoTabSheet.Enabled := FHeaderInfo.NameInfoOffset <> 0;
  ObjectQuotaInfoTabSheet.Enabled := FHeaderInfo.QuotaInfoOffset <> 0;
  DisplayHeaderInfo;
  end
Else Error('Failed to get object header info');

If ObjectHandleInfoTabSheet.Enabled Then
  begin
  Ret := ObjectGetHandleInfo(FObjectHandle, FHandleInfo);
  ObjectHandleInfoTabSheet.Enabled := Ret;
  If Ret Then
    begin
    DisplayHandleInfo;
    HeapFree(GetProcessHeap, 0, FHandleInfo);
    end
  Else Error('Failed to get object handle info');
  end;

If ObjectQuotaInfoTabSheet.Enabled Then
  begin
  Ret := ObjectGetQuotaInfo(FObjectHandle, @FQuotaInfo);
  ObjectQuotaInfoTabSheet.Enabled := Ret;
  If Ret Then
    DisplayQuotaInfo
  Else Error('Failed to get object quota charge information. ' + SysErrorMessage(GetLastError));
  end;

If ObjectNameInfoTabSheet.Enabled Then
  begin
  FName := '<none>';
  FFullName := '<none>';
  Ret := ObjectGetNameInfo(FObjectHandle, FName, FFullName);
  ObjectNameInfoTabSheet.Enabled := Ret;
  If Ret Then
    DisplayNameInfo
  Else Error(Format('Failed to get object name information. Error %s (%d)', [SysErrorMessage(GetLastError), GetLastError]));
  end;

Ret := ObjectGetTypeInfo(FObjectHandle, @FTypeInfo);
ObjectTypeTabSheet.Enabled := Ret;
If Ret Then
  DisplayTypeInfo
Else Error('Failed to get object type information');

If ObjectTypeTabSheet.Enabled Then
  begin
  If FTypeInfo.Name = 'Type' Then
    begin
    Ret := ObjectTypeGetSpecificInfo(FObjectHandle, @FTypeObjectInfo);
    TypeObjectInfoTabSheet.Enabled := Ret;
    If Ret Then
      DisplayTypeObjectInfo;
    end
  Else If FTypeInfo.Name = 'Event' Then
    begin
    Ret := ObjectEventGetSpecificInfo(FObjectHandle, @FEventObjectInfo);
    EventObjectInfoTabSheet.Enabled := Ret;
    If Ret Then
      DisplayEventObjectInfo;
    end
  Else If FTypeInfo.Name = 'Semaphore' Then
    begin
    Ret := ObjectSemaphoreGetSpecificInfo(FObjectHandle, @FSemaphoreObjectInfo);
    SemaphoreObjectInfoTabSheet.Enabled := Ret;
    If Ret Then
      DisplaySemaphoreObjectInfo;
    end
  Else If FTypeInfo.Name = 'Mutant' Then
    begin
    Ret := ObjectMutantGetSpecificInfo(FObjectHandle, @FMutantObjectInfo);
    MutantObjectInfoTabSheet.Enabled := Ret;
    If Ret Then
      DisplayMutantObjectInfo;
    end
  Else If FTypeInfo.Name = 'Directory' Then
    begin
    FDirectoryObjectInfo := DirectoryEnumerate(FObjectHandle);
    Ret := Assigned(FDirectoryObjectInfo);
    DirectoryObjectInfoTabSheet.Enabled := Ret;
    If Ret Then
      DisplayDirectoryObjectInfo;
    end;
  end;

For I := PageControl1.PageCount - 1 DownTo 0 Do
  begin
  If Not PageControl1.Pages[I].Enabled Then
    PageControl1.Pages[I].TabVisible := False;
  end;
end;

Procedure TForm2.HandleInfoListViewColumnClick(Sender: TObject;
  Column: TListColumn);
begin
HandleInfoListView.SortType := stNone;
If Column.Index <> FHandleDBSortColumn Then
  begin
  FHandleDBSortColumn := Column.Index;
  FHandleDBSortAscend := False;
  end
Else FHandleDBSortAscend := Not FHandleDBSortAscend;
HandleInfoListView.SortType := stText;
end;

Procedure TForm2.HandleInfoListViewCompare(Sender: TObject; Item1,
  Item2: TListItem; Data: Integer; var Compare: Integer);
Var
  S1, S2 : WideString;
begin
Case FHandleDBSortColumn Of
  0 : begin
    S1 := Item1.Caption;
    S2 := Item2.Caption;
    end;
  1 : begin
    S1 := Item1.SubItems[0];
    S2 := Item2.SubItems[0];
    end;
  end;

Compare := StrComp(PWideChar(S1), PWideChar(S2));
If Not FHandleDBSortAscend Then
  Compare := -Compare;
end;

End.

