unit UnitFileInUse;

{///////////////}
{//}interface{//}
{///////////////}
uses Windows, ActiveX, Vcl.Oleauto;

const
  IID_IFileIsInUse: TGUID = (
    D1:$64a1cbf0; D2:$3a1a; D3:$4461; D4:($91,$58,$37,$69,$69,$69,$39,$50));

type
  {$ALIGN 4}
  tagFILE_USAGE_TYPE = (
    FUT_PLAYING = 0,
    FUT_EDITING = 1,
    FUT_GENERIC = 2
  );
  FILE_USAGE_TYPE = tagFILE_USAGE_TYPE;
  TFileUsageType = FILE_USAGE_TYPE;

const
  OF_CAP_CANSWITCHTO     = $0001;
  OF_CAP_CANCLOSE        = $0002;

type
  IFileIsInUse = interface(IUnknown)
    ['{64a1cbf0-3a1a-4461-9158-376969693950}']
    function GetAppName(out ppszName: LPWSTR) : HRESULT; stdcall;
    function GetUsage(out pfut : FILE_USAGE_TYPE) : HRESULT; stdcall;
    function GetCapabilities(out pdwCapFlags : DWORD) : HRESULT; stdcall;
    function GetSwitchToHWND(out phwnd : HWND) : HRESULT; stdcall;
    function CloseFile() : HRESULT; stdcall;
  end;


function GetAppName(const FileName : WideString) : string;
function GetFileInUseInfo(const FileName : WideString) : IFileIsInUse;
{////////////////////}
{//}implementation{//}
{////////////////////}
uses ShlObj;

function GetAppName(const FileName : WideString) : string;
var
    fiiu : IFileIsInUse;
    str : LPWSTR;
begin
    fiiu := GetFileInUseInfo(FileName);
    fiiu.GetAppName( str );
    result := String(str);
end;
function GetFileInUseInfo(const FileName : WideString) : IFileIsInUse;
var
  ROT : IRunningObjectTable;
  mFile, enumIndex, Prefix : IMoniker;
  enumMoniker : IEnumMoniker;
  MonikerType : LongInt;
  unkInt  : IInterface;
begin
  result := nil;

  OleCheck(GetRunningObjectTable(0, ROT));
  OleCheck(CreateFileMoniker(PWideChar(FileName), mFile));

  OleCheck(ROT.EnumRunning(enumMoniker));

  while (enumMoniker.Next(1, enumIndex, nil) = S_OK) do
  begin
    OleCheck(enumIndex.IsSystemMoniker(MonikerType));
    if MonikerType = MKSYS_FILEMONIKER then
    begin
      if Succeeded(mFile.CommonPrefixWith(enumIndex, Prefix)) and
         (mFile.IsEqual(Prefix) = S_OK) then
      begin
       if Succeeded(ROT.GetObject(enumIndex, unkInt)) then
        begin
          if Succeeded(unkInt.QueryInterface(IID_IFileIsInUse, result)) then
          begin
            result := unkInt as IFileIsInUse;
            exit;
          end;
        end;
      end;
    end;
  end;
end;


end.
