{*******************************************************}
{                                                       }
{       Tocsg.Safe                                      }
{                                                       }
{       Copyright (C) 2022 kkuzil                       }
{                                                       }
{*******************************************************}

unit Tocsg.Safe;

interface

uses
  WinApi.Windows;

type
  TSafeObject = class(TInterfacedObject)
  private
    obj_: TObject;
  public
    Constructor Create(obj: TObject);
    Destructor Destroy; override;
  end;

  TSafePointer = class(TInterfacedObject)
  private
    ptr_: Pointer;
  public
    Constructor Create(aPointer: Pointer);
    Destructor Destroy; override;
  end;

  function Guard(out ref; aInstance: TObject): IUnknown; overload;
  function Guard(out ref; aPointer: Pointer): IUnknown; overload;
  function Guard(aPointer: Pointer): IUnknown; overload;

implementation

{ TSafeObject }

Constructor TSafeObject.Create(obj: TObject);
begin
  Inherited Create;
  obj_ := obj;
end;

Destructor TSafeObject.Destroy;
begin
  if Assigned(obj_) then
    obj_.Free;
  Inherited;
end;

{ TSafePointer }

Constructor TSafePointer.Create(aPointer: Pointer);
begin
  Inherited Create;
  ptr_ := aPointer;
end;

Destructor TSafePointer.Destroy;
begin
  if ptr_ <> nil then
    FreeMem(ptr_);
  Inherited;
end;

function Guard(out ref; aInstance: TObject): IUnknown;
begin
  Result := nil;
  if Assigned(aInstance) then
  begin
    Result := TSafeObject.Create(aInstance);
    TObject(ref) := aInstance;
  end;
end;

function Guard(out ref; aPointer: Pointer): IUnknown;
begin
  Result := nil;
  if Assigned(aPointer) then
  begin
    Result := TSafePointer.Create(aPointer);
    Pointer(ref) := aPointer;
  end;
end;

function Guard(aPointer: Pointer): IUnknown;
begin
  Result := TSafePointer.Create(aPointer);
end;

end.
