Microsoft Antivirus API

'

How to use IOfficeAntiVirus interface and develop antivirus program for MS Office

Microsoft Antivirus API enables software developers to develop applications that scan Microsoft Office documents before opening them.

The Antivirus API also supports scanning Microsoft IE code downloads, such as ActiveX controls.

The primary purpose of this API is to give a software developers the ability to design and implement antivirus software that can be used by all applications.

The antivirus component is a standard ActiveX component you register as an in-process server that supports the MSOfficeAntiVirus component category (CATID_MSOfficeAntiVirus : TGUID = '{56FFCC30-D398-11d0-B2AE-00A0C908FA49}').

IE and MS Office implement the antivirus component as follows:

{The Antivirus API enables software vendors to develop applications that scan
 Microsoft Office documents before opening them. The API also supports
 scanning Microsoft® Internet Explorer 5 code downloads, such as ActiveXControls
 or installs. However, be aware that the Internet Explorer scanning support
 applies only to automatic code downloads and not to file downloads or
 HTML documents.
 The primary purpose of this API is to give independent software vendors (ISVs)
 the ability to design and implement scanning software that can be used by
 all applications.}


unit msoav;

interface

uses Windows, SysUtils, ActiveX, ComObj, Classes;

const



IID_IOfficeAntiVirus : TGUID =    '{56FFCC30-D398-11d0-B2AE-00A0C908FA49}';
//DEFINE_GUID(IID_IOfficeAntiVirus,
//0x56ffcc30, 0xd398, 0x11d0, 0xb2, 0xae, 0x0, 0xa0, 0xc9, 0x8, 0xfa, 0x49);

CATID_MSOfficeAntiVirus : TGUID = '{56FFCC30-D398-11d0-B2AE-00A0C908FA49}';
//DEFINE_GUID(CATID_MSOfficeAntiVirus,
//0x56ffcc30, 0xd398, 0x11d0, 0xb2, 0xae, 0x0, 0xa0, 0xc9, 0x8, 0xfa, 0x49);


type

 TInfoStruct = record
  fIsFile : boolean;
  fIsReadOnly : boolean;
  fIsInstalled : boolean;
  fIsHTTPDownload : boolean;
 end;

 //Contains information about the file to be scanned.
{
 * cbSize      - Integer value that specifies the size of an MSOAVINFO structure.
 * hWnd        - Handle to the parent window of the Microsoft® Office 2000 
 *               application.
 * pwzFullPath - Address of a wide character string that contains the full
                  path of the file about to be opened.
 * lpStg       - Address of the OLE storage location of the file about to be 
 *               opened.
 * pwzHostName - Address of a wide character string that contains the host
                 application name for the antivirus scanner user interface.
 * pwzOrigURL  - Address of a wide character string that contains the URL of the
                 origin of a downloaded file.
}

 TMsoavinfo = record
  cbSize : integer;
  info   : ULONG;
  wnd : HWND;
  FullPath : Pointer;
  pwzHostName : PWChar;
  pwzOrigURL  : PWChar;
 end;

 //This is the interface an antivirus scanner uses to interact with a host 
 //application.
 IOfficeAntiVirus = interface(IUnknown)
 ['{56FFCC30-D398-11d0-B2AE-00A0C908FA49}']
  function Scan(pmsoavinfo : PChar) : HResult; stdcall;
 end;

function TestBit(const Value: Cardinal; const Bit: byte): Boolean;
procedure GetRegisteredAntiviruses(ProgIDs: TStrings);


implementation

function TestBit(const Value: Cardinal; const Bit: byte): Boolean;
begin
  Result := (Value and (1 shl (Bit mod 32))) <> 0;
end;


procedure GetRegisteredAntiviruses(ProgIDs: TStrings);
var
  CatInformation: ICatInformation;
  Enum: IEnumGUID;
  CLSID: TGUID;
  nFetched: Cardinal;
  CatId: TGUID;
begin
  CatInformation := CreateComObject(CLSID_StdComponentCategoryMgr) 
                                            as ICatInformation;
  CatId := CATID_MSOfficeAntiVirus;
  OleCheck(CatInformation.EnumClassesOfCategories(1, @CatId, 0, nil, Enum));
  ProgIDs.BeginUpdate;
  try
    ProgIDs.Clear;
    while (Enum.Next(1, CLSID, nFetched) = S_OK) do begin
      ProgIDs.Add(GuidToString(clsid));
    end;
  finally
    ProgIDs.EndUpdate;
  end;
end;

end.

Now I will show a small example how to use IOfficeAntiVirus interface to implement own antivirus program for Microsoft Office.

  library msoavtest;

uses
 
ComServ,
  msoav,
  umsoavtest;

exports
 
DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer;

begin
end
.

unit umsoavtest;

interface

uses
  Windows, ActiveX, ComObj, ShlObj, Dialogs, msoav;

type
  TMSOTest = class(TComObject, IOfficeAntiVirus)
  protected
   function Scan(pmsoavinfo : PChar) : HResult; stdcall;
  end;


const
  Class_MsoTest: TGUID = '{F56BE781-C8BE-11D7-8601-00E0184D1E9D}';

implementation

uses ComServ, SysUtils, ShellApi, Registry;


procedure UpdateCat(Register: Boolean;  const ClassID:  string);
const
  SCatImplBaseKey = 'CLSID\%s\Implemented Categories';
  SCatImplKey = SCatImplBaseKey + '\%s';

var
  CatReg: ICatRegister;
  Rslt: HResult;
  CatInfo: TCATEGORYINFO;
  Description: string;
begin
  Rslt := CoCreateInstance(CLSID_StdComponentCategoryMgr, nil,
    CLSCTX_INPROC_SERVER, ICatRegister, CatReg);
  if Succeeded(Rslt) then
  begin
    if Register then
    begin
      CatInfo.catid := CATID_MSOfficeAntiVirus;
      CatInfo.lcid := $0409;
      StringToWideChar('', CatInfo.szDescription,
        Length('') + 1);
      OleCheck(CatReg.RegisterCategories(1, @CatInfo));
      OleCheck(CatReg.RegisterClassImplCategories(StringToGUID(ClassID), 1, @CATID_MSOfficeAntiVirus));
    end else
    begin
      OleCheck(CatReg.UnRegisterClassImplCategories(StringToGUID(ClassID), 1, @CATID_MSOfficeAntiVirus));
      DeleteRegKey(Format(SCatImplBaseKey, [ClassID]));
    end;
  end else
  begin
    if Register then
    begin
      CreateRegKey('Component Categories\' + GUIDToString(CATID_MSOfficeAntiVirus), '409', '');
      CreateRegKey(Format(SCatImplKey, [ClassID, GUIDToString(CATID_MSOfficeAntiVirus)]), '', '');
    end else
    begin
      DeleteRegKey(Format(SCatImplKey, [ClassID, GUIDToString(CATID_MSOfficeAntiVirus)]));
      DeleteRegKey(Format(SCatImplBaseKey, [ClassID]));
    end;
  end;
  if Register then
  begin
    Description := GetRegStringValue('CLSID\' + ClassID, '');
    CreateRegKey('AppID\' + ClassID, '', Description);
    CreateRegKey('CLSID\' + ClassID, 'AppID', ClassID);
  end else
    DeleteRegKey('AppID\' + ClassID);
end;

{ TMSOTest }

function TMSOTest.Scan(pmsoavinfo: PChar): HResult;
var
 Info   : TMsoavinfo;
 Struct : TInfoStruct;
 p : pointer;
begin
  p := pointer(pmsoavinfo);
  if not Assigned(p) then
   begin
     //no information available
     Result := S_OK;
     Exit;
   end;

  Move(P^, Info, SizeOf(Tmsoavinfo));
  if Info.cbSize <> SizeOf(Tmsoavinfo) then
   begin
     //wrong size of the structure
     Result := S_OK;
     Exit;
   end;
  Struct.fIsFile := TestBit(Info.Info, 0);
  Struct.fIsReadOnly := TestBit(Info.Info, 1);
  Struct.fIsInstalled := TestBit(Info.Info, 2);
  Struct.fIsHTTPDownload :=  TestBit(Info.Info, 3);
  if struct.fIsFile then
   begin
     MessageDlg(PWChar(Info.FullPath), mtWarning, [mbOK], 0);
   end;
  Result := S_OK;
end;


type
  TMSOAvFactory = class(TComObjectFactory)
  public
    procedure UpdateRegistry(Register: Boolean); override;
  end;


procedure TMSOAVFactory.UpdateRegistry(Register: Boolean);
var
  ClassID: string;
begin
  ClassID := GUIDToString(Class_MsoTest);
  if Register then
  begin
    inherited UpdateRegistry(Register);
    UpdateCat(true, ClassID);
  end
  else
  begin
    UpdateCat(false, ClassID);
    inherited UpdateRegistry(Register);
  end;
end;

initialization
  TComObjectFactory.Create(ComServer, TMsoTest, Class_MsoTest,
    'MsoTest', '', ciMultiInstance, tmApartment);
end.

This tutorial was kindly provided by serge perevoznyk


Google
Web www.Delphi-Central.com
Delphi Central - Delphi Programming Tutorials, Hints and Tips