Unit Objects;

{
  Tento soubor tvori vrstvu nad souborem DriverCommands.paas. Jeho
  hlavnim ukolem je odstranit zavislost na platforme (x86, x64) a
  dovolit tak kodu o uroven vyse pracovat s jednotne definovanymi
  strukturami pro libovolnou verzi Windows.

  Kod v tomto souboru tedy na zaklade platformy vola kod bud pro 32bitovou,
  nebo pro 64bitovou platformu.
}

Interface

Uses
  Windows, Classes, DriverCommands;

Const
  // Priznaky v hlavicce objektu
  OB_FLAG_NEW_OBJECT = $01;
  OB_FLAG_KERNEL_OBJECT = $02;
  OB_FLAG_CREATOR_INFO = $04;
  OB_FLAG_EXCLUSIVE_OBJECT = $08;
  OB_FLAG_PERMANENT_OBJECT = $10;
  OB_FLAG_DEFAULT_SECURITY_QUOTA = $20;
  OB_FLAG_SINGLE_HANDLE_ENTRY = $40;
  OB_FLAG_DELETED_INLINE = $80;

Type
  // Jednotna definice informaci o hlavicce objektu
  OBJECT_HEADER_INFO = Record
    NameInfoOffset : DWORD;
    HandleInfoOffset : DWORD;
    QuotaInfoOffset : DWORD;
    CreatorInfoOffset : DWORD;
    ProcessInfoOffset : DWORD;
    InfoMask : DWORD;
    HandleCount : Int64;
    PointerCount : Int64;
    Flags : DWORD;
    ExclusiveProcessId : Int64;
    CreatorProcessId : Int64;
    end;
  POBJECT_HEADER_INFO = ^OBJECT_HEADER_INFO;

  // Informace o narocnosti objektu na kvotu procesu
  OBJECT_QUOTA_INFO = Record
    PagedPoolCharge : DWORD;
    NonPagedPoolCharge : DWORD;
    SecurityDescriptorCharge : DWORD;
    ExclusiveProcessId : Int64;
    end;
  POBJECT_QUOTA_INFO = ^OBJECT_QUOTA_INFO;

  // Polozka databaze handle
  OBJECT_HANDLE_ENTRY = Record
    ProcessId : Int64;
    HandleCount : Int64;
    end;
  POBJECT_HANDLE_ENTRY = ^OBJECT_HANDLE_ENTRY;

  // Hlavicka databaze handle
  OBJECT_HANDLE_INFO = Record
    Count : Int64;
    Entries : Array [0..1] Of OBJECT_HANDLE_ENTRY;
    end;
  POBJECT_HANDLE_INFO = ^OBJECT_HANDLE_INFO;

  OBJECT_INITIALIZER_FLAGS = OBJECT_INITIALIZER_FLAGS_64;

  OBJECT_INITIALIZER_METHODS = Record
    Open : Int64;
    Close : Int64;
    OkayToClose : Int64;
    Delete : Int64;
    Parse : Int64;
    QueryName : Int64;
    Security : Int64;
    Dump : Int64;
    end;

  OBJECT_INITIALIZER_OTHER_INFO = OBJECT_INITIALIZER_OTHER_INFO_64;

  OBJECT_TYPE_STATISTICS = OBJECT_TYPE_STATISTICS_64;

  OBJECT_TYPE_INFO = Record
    InitializerFlags : OBJECT_INITIALIZER_FLAGS;
    InitializerMethods : OBJECT_INITIALIZER_METHODS;
    InitializerOtherInfo : OBJECT_INITIALIZER_OTHER_INFO;
    TypeStatistics : OBJECT_TYPE_STATISTICS;
    Index : DWORD;
    Key : DWORD;
    DefaultObject : Int64;
    Name : WideString;
    end;
  POBJECT_TYPE_INFO = ^OBJECT_TYPE_INFO;

  OBJECT_EVENT_INFO = Record
    EventType : DWORD;
    Signaled : DWORD;
    end;
  POBJECT_EVENT_INFO = ^OBJECT_EVENT_INFO;

  OBJECT_SEMAPHORE_INFO = Record
    Counter : DWORD;
    Limit : DWORD;
    end;
  POBJECT_SEMAPHORE_INFO = ^OBJECT_SEMAPHORE_INFO;

  OBJECT_MUTANT_INFO = Record
    OwnerThreadId : Int64;
    Signaled : DWORD;
    Abandoned : Boolean;
    end;
  POBJECT_MUTANT_INFO = ^OBJECT_MUTANT_INFO;

Function DirectoryEnumerate(ObjectHandle:Int64):TStrings;
Function ObjectOpen(ObjectName:WideString):Int64;
Function ObjectClose(ObjectHandle:Int64):Boolean;
Function ObjectGetTypeInfo(ObjectHandle:Int64; Info:POBJECT_TYPE_INFO):Boolean;
Function ObjectGetHeaderInfo(ObjectHandle:Int64; Info:POBJECT_HEADER_INFO):Boolean;
Function ObjectGetHandleInfo(ObjectHandle:Int64; Var Info:POBJECT_HANDLE_INFO):Boolean;
Function ObjectGetQuotaInfo(ObjectHandle:Int64; Info:POBJECT_QUOTA_INFO):Boolean;
Function ObjectGetNameInfo(ObjectHandle:Int64; Var Name:WideString; Var FullName:WideString):Boolean;

Function ObjectTypeGetSpecificInfo(ObjectHandle:Int64; Info:POBJECT_TYPE_INFO):Boolean;
Function ObjectEventGetSpecificInfo(ObjectHandle:Int64; Info:POBJECT_EVENT_INFO):Boolean;
Function ObjectSemaphoreGetSpecificInfo(ObjectHandle:Int64; Info:POBJECT_SEMAPHORE_INFO):Boolean;
Function ObjectMutantGetSpecificInfo(ObjectHandle:Int64; Info:POBJECT_MUTANT_INFO):Boolean;

Implementation

Uses
  Driver, Utils, SysUtils;

Function DirectoryEnumerate(ObjectHandle:Int64):TStrings;
{
  Zjisti obsah adresare a vrati jej jako seznam retezcu (trida TStrings).
  Rutina predpoklada, ze cilovy objekt je opravdu adresar.
}
Var
  SpecOutLength : Integer;
  SPecOut : PWideChar;
  Tmp : PWideChar;
  I : Integer;
  Str : WideString;
  Error : Boolean;
begin
Result := Nil;
SpecOut := Nil;
SpecOutLength := 1024;
Error := True;
While Error Do
  begin
  SpecOutLength := SpecOutLength * 2;
  If Assigned(SpecOut) Then
    HeapFree(GetProcessHeap, 0, SpecOut);

  SpecOut := HeapAlloc(GetProcessHeap, 0, SpecOutLength);
  If Assigned(SpecOut) Then
    begin
    Case GetOSType Of
      ost32bit : Error := Not ObjviewGetSpecificInfo32(ObjectHandle, SpecOut, SpecOutLength);
      ost64bit : Error := Not ObjviewGetSpecificInfo64(ObjectHandle, SpecOut, SpecOutLength);
      end;

    If (Error) And (GetLastError <> 122) Then
      begin
      Utils.Error(Format('Driver I/O error: %s (%d)', [SysErrorMessage(GetLastError), GetLastError]));
      Break;
      end;
    end
  Else Break;
  end;

If Not Error Then
  begin
  Result := TStringList.Create;
  Tmp := SpecOut;
  Repeat
  Str := '';
  While Tmp^ <> #0 Do
    begin
    Str := Str + Tmp^;
    Inc(Tmp);
    end;

  Inc(Tmp);
  If Str <> '' Then
    Result.Add(Str);
  Until Str = '';
  end;

If Assigned(SpecOut) Then
  HeapFree(GetProcessHeap, 0, SpecOut);
end;

Function ObjectGetTypeInfo(ObjectHandle:Int64; Info:POBJECT_TYPE_INFO):Boolean;
Var
  TIOut : Pointer;
  TIOut32 : POBJVIEW_GET_TYPE_INFO_OUT_32;
  TIOut64 : POBJVIEW_GET_TYPE_INFO_OUT_64;
  TIOutLength : Integer;
  Error : Boolean;
begin
Result := False;
Info.Name := '';
TIOutLength := 512;
Error := True;
TIOut := Nil;
While Error Do
  begin
  TIOutLength := TIOutLength * 2;
  If Assigned(TIOUT) Then
    HeapFree(GetProcessHeap, 0, TIOut);

  TIOut := HeapAlloc(GetProcessHeap, 0, TIOutLength);
  If Assigned(TIOut) Then
    begin
    Case GetOSType Of
      ost32bit : begin
        Error := Not ObjviewGetTypeInfo32(ObjectHandle, TIOut, TIOutLength);
        If Not Error Then
          TIOut32 := TIOut;
        end;
      ost64bit : begin
        Error := Not ObjviewGetTypeInfo64(ObjectHandle, TIOut, TIOutLength);
        If Not Error Then
          TIOut64 := TIOut;
        end;
      end;

    If (Error) And (GetLastError <> 122) Then
      begin
      Utils.Error(Format('Driver I/O error: %s (%d)', [SysErrorMessage(GetLastError), GetLastError]));
      Break;
      end;
    end
  Else Break;
  end;

Result := Not Error;
If Result Then
  begin
  Case GetOSType Of
    ost32bit : begin
      Info.InitializerFlags := TIOut32.InitializerFlags;
      Info.InitializerMethods.Open := DWORD(TIOut32.InitializerMethods.Open);
      Info.InitializerMethods.Close := DWORD(TIOut32.InitializerMethods.Close);
      Info.InitializerMethods.OkayToClose := DWORD(TIOut32.InitializerMethods.OkayToClose);
      Info.InitializerMethods.Delete := DWORD(TIOut32.InitializerMethods.Delete);
      Info.InitializerMethods.Parse := DWORD(TIOut32.InitializerMethods.Parse);
      Info.InitializerMethods.QueryName := DWORD(TIOut32.InitializerMethods.QueryName);
      Info.InitializerMethods.Security := DWORD(TIOut32.InitializerMethods.Security);
      Info.InitializerMethods.Dump := DWORD(TIOut32.InitializerMethods.Dump);
      Info.InitializerOtherInfo := TIOut32.InitializerOtherInfo;
      Info.TypeStatistics := TIOut32.TypeStatistics;
      Info.Index := TIOut32.Index;
      Info.Key := TIOut32.Key;
      Info.DefaultObject := DWORD(TIOut32.DefaultObject);
      Info.Name := Copy(PWideChar(@TIOut32.Name), 1 , TIOut32.NameLength DIv SizeOf(WideChar));
      end;
    ost64bit : begin
      Info.InitializerFlags := TIOut64.InitializerFlags;
      Info.InitializerMethods.Open := TIOut64.InitializerMethods.Open;
      Info.InitializerMethods.Close := TIOut64.InitializerMethods.Close;
      Info.InitializerMethods.OkayToClose := TIOut64.InitializerMethods.OkayToClose;
      Info.InitializerMethods.Delete := TIOut64.InitializerMethods.Delete;
      Info.InitializerMethods.Parse := TIOut64.InitializerMethods.Parse;
      Info.InitializerMethods.QueryName := TIOut64.InitializerMethods.QueryName;
      Info.InitializerMethods.Security := TIOut64.InitializerMethods.Security;
      Info.InitializerMethods.Dump := TIOut64.InitializerMethods.Dump;
      Info.InitializerOtherInfo := TIOut64.InitializerOtherInfo;
      Info.TypeStatistics := TIOut64.TypeStatistics;
      Info.Index := TIOut64.Index;
      Info.Key := TIOut64.Key;
      Info.DefaultObject := TIOut64.DefaultObject;
      Info.Name := Copy(PWideChar(@TIOut64.Name), 1 , TIOut64.NameLength DIv SizeOf(WideChar));
      end;
    end;
  end;

If Assigned(TIOut) Then
  HeapFree(GetProcessHeap, 0, TIOut);
end;

Function ObjectGetHeaderInfo(ObjectHandle:Int64; Info:POBJECT_HEADER_INFO):Boolean;
Var
  HeaderInfo32 : OBJVIEW_GET_HEADER_OUT_32;
  HeaderInfo64 : OBJVIEW_GET_HEADER_OUT_64;
begin
Case GetOSType Of
  ost32bit : begin
    ZeroMemory(@HeaderInfo32, SizeOf(HeaderInfo32));
    Result := ObjviewGetObjectHeader32(ObjectHandle, @HeaderInfo32);
    end;
  ost64bit : begin
    ZeroMemory(@HeaderInfo64, SizeOf(HeaderInfo64));
    Result := ObjviewGetObjectHeader64(ObjectHandle, @HeaderInfo64);
    end;
  end;

If Result Then
  begin
  Case GetOSType Of
    ost32bit : begin
      Info.NameInfoOffset := HeaderInfo32.NameInfoOffset;
      Info.HandleInfoOffset := HeaderInfo32.HandleInfoOffset;
      Info.QuotaInfoOffset := HeaderInfo32.QuotaInfoOffset;
      Info.CreatorInfoOffset := HeaderInfo32.CreatorInfoOffset;
      Info.ProcessInfoOffset := HeaderInfo32.ProcessInfoOffset;
      Info.InfoMask := HeaderInfo32.InfoMask;
      Info.HandleCount := HeaderInfo32.HandleCount;
      Info.PointerCount := HeaderInfo32.PointerCount;
      Info.Flags := HeaderInfo32.Flags;
      Info.ExclusiveProcessId := HeaderInfo32.ExclusiveProcessId;
      Info.CreatorProcessId := HeaderInfo32.CreatorProcessId;
      end;
    ost64bit : begin
      Info.NameInfoOffset := HeaderInfo64.NameInfoOffset;
      Info.HandleInfoOffset := HeaderInfo64.HandleInfoOffset;
      Info.QuotaInfoOffset := HeaderInfo64.QuotaInfoOffset;
      Info.CreatorInfoOffset := HeaderInfo64.CreatorInfoOffset;
      Info.ProcessInfoOffset := HeaderInfo64.ProcessInfoOffset;
      Info.InfoMask := HeaderInfo64.InfoMask;
      Info.HandleCount := HeaderInfo64.HandleCount;
      Info.PointerCount := HeaderInfo64.PointerCount;
      Info.Flags := HeaderInfo64.Flags;
      Info.ExclusiveProcessId := HeaderInfo64.ExclusiveProcessId;
      Info.CreatorProcessId := HeaderInfo64.CreatorProcessId;
      end;
    end;
  end;
end;

Function ObjectGetHandleInfo(ObjectHandle:Int64; Var Info:POBJECT_HANDLE_INFO):Boolean;
Var
  I : Integer;
  Error : Boolean;
  HandleInfoLength : DWORD;
  HandleInfo : Pointer;
  HandleInfo32 : POBJVIEW_GET_HANDLE_INFO_OUT_32;
  HandleInfo64 : POBJVIEW_GET_HANDLE_INFO_OUT_64;
begin
Info := Nil;
HandleInfo := Nil;
Result := False;
Error := True;
HandleInfoLength := 128;
While Error Do
  begin
  If Assigned(HandleInfo) Then
    HeapFree(GetProcessHeap, 0, HandleInfo);

  HandleInfoLength := HandleInfoLength * 2;
  HandleInfo := HeapAlloc(GetProcessHeap, 0, HandleInfoLength);
  If Assigned(HandleInfo) Then
    begin
    Case GetOSType Of
      ost32bit : begin
        Error := Not ObjviewGetHandleInfo32(ObjectHandle, HandleInfo, HandleInfoLength);
        HandleInfo32 := HandleInfo;
        end;
      ost64bit : begin
        Error := Not ObjviewGetHandleInfo64(ObjectHandle, HandleInfo, HandleInfoLength);
        HandleInfo64 := HandleInfo;
        end;
      end;

    If (Error) And (GetLastError <> 122) Then
      begin
      Utils.Error(Format('Driver I/O error: %s (%d)', [SysErrorMessage(GetLastError), GetLastError]));
      Break;
      end;
    end
  Else Break;
  end;

Result := Not Error;
If Result Then
  begin
  Info := HeapAlloc(GetProcessHeap, 0, HandleInfoLength);
  Result := Assigned(Info);
  If Result Then
    begin
    Case GetOSType Of
      ost32bit : begin
        Info.Count := HandleInfo32.Count;
        For I := 0 To Info.Count - 1 Do
          begin
          Info.Entries[I].ProcessId := HandleInfo32.Entries[I].ProcessId;
          Info.Entries[I].HandleCount := HandleInfo32.Entries[I].HandleCount
          end;
        end;
      ost64bit : begin
        Info.Count := HandleInfo64.Count;
        For I := 0 To Info.Count - 1 Do
          begin
          Info.Entries[I].ProcessId := HandleInfo64.Entries[I].ProcessId;
          Info.Entries[I].HandleCount := HandleInfo64.Entries[I].HandleCount
          end;
        end;
      end;
    end;
  end;

If Assigned(HandleInfo) Then
  HeapFree(GetProcessHeap, 0, HandleInfo);
end;

Function ObjectGetQuotaInfo(ObjectHandle:Int64; Info:POBJECT_QUOTA_INFO):Boolean;
Var
  QuotaInfo32 : OBJVIEW_GET_QUOTA_INFO_OUT_32;
  QuotaInfo64 : OBJVIEW_GET_QUOTA_INFO_OUT_64;
begin
Case GetOSType Of
  ost32bit : begin
    ZeroMemory(@QuotaInfo32, SizeOf(QuotaInfo32));
    Result := ObjviewGetObjectQuotaInfo32(ObjectHandle, @QuotaInfo32);
    end;
  ost64bit : begin
    ZeroMemory(@QuotaInfo64, SizeOf(QuotaInfo64));
    Result := ObjviewGetObjectQuotaInfo64(ObjectHandle, @QuotaInfo64);
    end;
  end;

If Result Then
  begin
  Case GetOSType Of
    ost32bit : begin
      Info.PagedPoolCharge := QuotaInfo32.PagedPoolCharge;
      Info.NonPagedPoolCharge := QuotaInfo32.NonPagedPoolCharge;
      Info.SecurityDescriptorCharge := QuotaInfo32.SecurityDescriptorCharge;
      Info.ExclusiveProcessId := QuotaInfo32.ExclusiveProcessId;
      end;
    ost64bit : begin
      Info.PagedPoolCharge := QuotaInfo64.PagedPoolCharge;
      Info.NonPagedPoolCharge := QuotaInfo64.NonPagedPoolCharge;
      Info.SecurityDescriptorCharge := QuotaInfo64.SecurityDescriptorCharge;
      Info.ExclusiveProcessId := QuotaInfo64.ExclusiveProcessId;
      end;
    end;
  end;
end;

Function ObjectGetNameInfo(ObjectHandle:Int64; Var Name:WideString; Var FullName:WideString):Boolean;
begin
Case GetOSType Of
  ost32bit : Result := ObjviewGetNameInfo32(ObjectHandle, Name, FullName);
  ost64bit : Result := ObjviewGetNameInfo64(ObjectHandle, Name, FullName);
  end;
end;

Function ObjectOpen(ObjectName:WideString):Int64;
begin
Case GetOSType Of
  ost32bit : Result := ObjviewOpenObject32(ObjectName);
  ost64bit : Result := ObjviewOpenObject64(ObjectName);
  end;
end;

Function ObjectClose(ObjectHandle:Int64):Boolean;
begin
Case GetOSType Of
  ost32bit : Result := ObjviewCloseObject32(ObjectHandle);
  ost64bit : Result := ObjviewCloseObject64(ObjectHandle);
  end;
end;


Function ObjectTypeGetSpecificInfo(ObjectHandle:Int64; Info:POBJECT_TYPE_INFO):Boolean;
Var
  TIOut : Pointer;
  TIOut32 : POBJVIEW_GET_TYPE_SPECIFIC_INFO_OUT_32;
  TIOut64 : POBJVIEW_GET_TYPE_SPECIFIC_INFO_OUT_64;
  TIOutLength : Integer;
  Error : Boolean;
begin
Result := False;
Info.Name := '';
TIOutLength := 512;
Error := True;
TIOut := Nil;
While Error Do
  begin
  TIOutLength := TIOutLength * 2;
  If Assigned(TIOUT) Then
    HeapFree(GetProcessHeap, 0, TIOut);

  TIOut := HeapAlloc(GetProcessHeap, 0, TIOutLength);
  If Assigned(TIOut) Then
    begin
    Case GetOSType Of
      ost32bit : begin
        Error := Not ObjviewGetSpecificInfo32(ObjectHandle, TIOut, TIOutLength);
        If Not Error Then
          TIOut32 := TIOut;
        end;
      ost64bit : begin
        Error := Not ObjviewGetSpecificInfo64(ObjectHandle, TIOut, TIOutLength);
        If Not Error Then
          TIOut64 := TIOut;
        end;
      end;

    If (Error) And (GetLastError = 122) Then
      begin
      Utils.Error(Format('Driver I/O error: %s (%d)', [SysErrorMessage(GetLastError), GetLastError]));
      Break;
      end;
    end
  Else Break;
  end;

Result := Not Error;
If Result Then
  begin
  Case GetOSType Of
    ost32bit : begin
      Info.InitializerFlags := TIOut32.InitializerFlags;
      Info.InitializerMethods.Open := DWORD(TIOut32.InitializerMethods.Open);
      Info.InitializerMethods.Close := DWORD(TIOut32.InitializerMethods.Close);
      Info.InitializerMethods.OkayToClose := DWORD(TIOut32.InitializerMethods.OkayToClose);
      Info.InitializerMethods.Delete := DWORD(TIOut32.InitializerMethods.Delete);
      Info.InitializerMethods.Parse := DWORD(TIOut32.InitializerMethods.Parse);
      Info.InitializerMethods.QueryName := DWORD(TIOut32.InitializerMethods.QueryName);
      Info.InitializerMethods.Security := DWORD(TIOut32.InitializerMethods.Security);
      Info.InitializerMethods.Dump := DWORD(TIOut32.InitializerMethods.Dump);
      Info.InitializerOtherInfo := TIOut32.InitializerOtherInfo;
      Info.TypeStatistics := TIOut32.TypeStatistics;
      Info.Index := TIOut32.Index;
      Info.Key := TIOut32.Key;
      Info.DefaultObject := TIOut32.DefaultObject;
      Info.Name := Copy(PWideChar(@TIOut32.Name), 1 , TIOut32.NameLength DIv SizeOf(WideChar));
      end;
    ost64bit : begin
      Info.InitializerFlags := TIOut64.InitializerFlags;
      Info.InitializerMethods.Open := TIOut64.InitializerMethods.Open;
      Info.InitializerMethods.Close := TIOut64.InitializerMethods.Close;
      Info.InitializerMethods.OkayToClose := TIOut64.InitializerMethods.OkayToClose;
      Info.InitializerMethods.Delete := TIOut64.InitializerMethods.Delete;
      Info.InitializerMethods.Parse := TIOut64.InitializerMethods.Parse;
      Info.InitializerMethods.QueryName := TIOut64.InitializerMethods.QueryName;
      Info.InitializerMethods.Security := TIOut64.InitializerMethods.Security;
      Info.InitializerMethods.Dump := TIOut64.InitializerMethods.Dump;
      Info.InitializerOtherInfo := TIOut64.InitializerOtherInfo;
      Info.TypeStatistics := TIOut64.TypeStatistics;
      Info.Index := TIOut64.Index;
      Info.Key := TIOut64.Key;
      Info.DefaultObject := TIOut64.DefaultObject;
      Info.Name := Copy(PWideChar(@TIOut64.Name), 1 , TIOut64.NameLength DIv SizeOf(WideChar));
      end;
    end;
  end;

If Assigned(TIOut) Then
  HeapFree(GetProcessHeap, 0, TIOut);
end;

Function ObjectEventGetSpecificInfo(ObjectHandle:Int64; Info:POBJECT_EVENT_INFO):Boolean;
Var
  Info32 : OBJVIEW_GET_EVENT_SPECIFIC_INFO_OUT_32;
  Info64 : OBJVIEW_GET_EVENT_SPECIFIC_INFO_OUT_64;
begin
Result := False;
Case GetOSType Of
  ost32bit : Result := ObjviewGetSpecificInfo32(ObjectHandle, @Info32, SizeOf(Info32));
  ost64bit : Result := ObjviewGetSpecificInfo64(ObjectHandle, @Info64, SizeOf(Info64));
  end;

If Result Then
  begin
  Case GetOSType Of
    ost32bit : begin
      Info.EventType := Info32.EventType;
      Info.Signaled := Info32.Signaled;
      end;
    ost64bit : begin
      Info.EventType := Info64.EventType;
      Info.Signaled := Info64.Signaled;
      end;
    end;
  end;
end;

Function ObjectSemaphoreGetSpecificInfo(ObjectHandle:Int64; Info:POBJECT_SEMAPHORE_INFO):Boolean;
Var
  Info32 : OBJVIEW_GET_SEMAPHORE_SPECIFIC_INFO_OUT_32;
  Info64 : OBJVIEW_GET_SEMAPHORE_SPECIFIC_INFO_OUT_64;
begin
Result := False;
Case GetOSType Of
  ost32bit : Result := ObjviewGetSpecificInfo32(ObjectHandle, @Info32, SizeOf(Info32));
  ost64bit : Result := ObjviewGetSpecificInfo64(ObjectHandle, @Info64, SizeOf(Info64));
  end;

If Result Then
  begin
  Case GetOSType Of
    ost32bit : begin
      Info.Counter := Info32.Counter;
      Info.Limit := Info32.Limit;
      end;
    ost64bit : begin
      Info.Counter := Info64.Counter;
      Info.Limit := Info64.Limit;
      end;
    end;
  end;
end;

Function ObjectMutantGetSpecificInfo(ObjectHandle:Int64; Info:POBJECT_MUTANT_INFO):Boolean;
Var
  Info32 : OBJVIEW_GET_MUTANT_SPECIFIC_INFO_OUT_32;
  Info64 : OBJVIEW_GET_MUTANT_SPECIFIC_INFO_OUT_64;
begin
Result := False;
Case GetOSType Of
  ost32bit : Result := ObjviewGetSpecificInfo32(ObjectHandle, @Info32, SizeOf(Info32));
  ost64bit : Result := ObjviewGetSpecificInfo64(ObjectHandle, @Info64, SizeOf(Info64));
  end;

If Result Then
  begin
  Case GetOSType Of
    ost32bit : begin
      Info.OwnerThreadId := Info32.OwnerThreadId;
      Info.Signaled := Info32.Signaled;
      Info.Abandoned := Info32.Abandoned;
      end;
    ost64bit : begin
      Info.OwnerThreadId := Info64.OwnerThreadId;
      Info.Signaled := Info64.Signaled;
      Info.Abandoned := Info64.Abandoned;
      end;
    end;
  end;
end;

End.

