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

unit Tocsg.Win32;

interface

uses
  Tocsg.Obj, System.Classes, Winapi.Windows;

type
  TMutexState = (msUnknown, msCreateOk, msAlreadyExist, msFail);
  TTgMutex = class(TTgObject)
  private
    sName_: String;
    hMutex_: THandle;
    MutexState_: TMutexState;
  public
    Constructor Create(const sName: String);
    Destructor Destroy; override;

    property MutexName: String read sName_;
    property MutexState: TMutexState read MutexState_;

    property LastError;
  end;

function MutexExists(const sMutex: String): Boolean;

implementation

function MutexExists(const sMutex: String): Boolean;
var
  h: THandle;
begin
  Result := false;
//  h := OpenMutex(MUTEX_ALL_ACCESS, true, PChar(sMutex));
  h := OpenMutex(SYNCHRONIZE, false, PChar(sMutex));
  if h <> 0 then
  begin
    CloseHandle(h);
    Result := true;
  end;
end;

{ TTgMutex }

Constructor TTgMutex.Create(const sName: String);

  procedure InitCreateMutex;
  var
    sd: SECURITY_DESCRIPTOR;
    sa: SECURITY_ATTRIBUTES;
  begin
    InitializeSecurityDescriptor(@sd, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(@sd, true, nil, false);

    ZeroMemory(@sa, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength := sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor := @sd;
    sa.bInheritHandle := false;

    hMutex_ := CreateMutex(@sa, false, PChar(sName_));
    nLastError_ := GetLastError;
    if hMutex_ > 0 then
    begin
      if nLastError_ = ERROR_ALREADY_EXISTS then
        MutexState_ := msAlreadyExist
      else
        MutexState_ := msCreateOk;
    end else
      MutexState_ := msFail;
  end;

begin
  Inherited Create;
  ASSERT(sName <> '', 'no mutex name..');

  hMutex_ := 0;
  sName_ := sName;
  MutexState_ := msUnknown;

  InitCreateMutex;
end;

Destructor TTgMutex.Destroy;
begin
  if hMutex_ > 0 then
    CloseHandle(hMutex_);

  Inherited;
end;

end.
