Delphi Outlook add-in using ExchExt cannot add menu item

I have just started writing an Outlook add-in DLL using the
ExchExt.pas from Dmitry.

My problem is that I am unable to create a new menu item.

I have searched the newsgroups but I can find no answer (at least not
one I can understand!). The MSDN C examples implement the
QueryInterface function, but from what I can gather this isn't
necessary for Delphi.

I have attached the code below, any pointers (or answers/examples in C
or preferably Delphi ) would be greatefully received.

So far I have established that the DLL is being loaded (the
Showmessage call is showing all changes of context). The
InstallCommands function does not appear to be called. I am using
Outlook 97.

TIA

Aaron

< --- SNIP --- >
REGEDIT4

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\Client\Extensions]
"SHIPS Extensions"="4.0;d:\\delphi5\\delphi5\\projects\\outlookext\\outlookext.dll;1"

< --- SNIP --- >
library OutlookExt;

uses
    SysUtils,
    Classes,
    Windows,
    Dialogs,
    ExchExt,
    OutlookExtInterface in 'OutlookExtInterface.pas';

{$R *.RES}

var gExchEntryPoint: pointer = nil;

function ExchEntryPoint: Pointer; stdcall;
begin
    Result := nil;
    { create it only once }
    if (gExchEntryPoint=nil) then gExchEntryPoint :=
Pointer(TOutlookExt.Create);
    IUnknown(Result) := TOutlookExt(gExchEntryPoint) as IExchExt;
end;

exports
    ExchEntryPoint index 1;

begin
end.    

< --- SNIP --->

unit OutlookExtInterface;

interface

uses    Windows, SysUtils, ActiveX, Dialogs, ExchExt, CommCtrl;

type

TOutlookExt = class(TInterfacedObject, IExchExt)
    private
        FCallback:  IExchExtCallback;
        FContext:   longint;
        FCommandID: UINT;
        FMenu:      HWND;
    public
        function Install(lpeecb: IExchExtCallback; eecontext: longint;
ulFlags: longint): HRESULT; stdcall;
        function InstallCommands(lpeecb: IEXCHEXTCALLBACK; hwnd: HWND;
hmenu: HMENU; var lpcmdidBase: UINT; lptbeArray : LPTBENTRY_Array;
ctbe: UINT; ulFlags: ULONG): HRESULT; stdcall;
        procedure InitMenu(lpeecb : IExchExtCallback);stdcall;
        function DoCommand(lpeecb : IExchExtCallback; cmdid :
UINT):HRESULT;stdcall;
        constructor create;
        destructor destroy; override;
end;

implementation

uses Forms, MapiDefs;

constructor TOutlookExt.Create;
begin
    inherited create;
end;

destructor TOutlookExt.Destroy;
begin
    inherited;
end;

function TOutlookExt.Install(lpeecb: IExchExtCallback; eecontext,
ulFlags: Integer): HRESULT;
var msg:            String;
    hwndExchange:   HWND;
begin
    { if you want to show any UI in your extension , you need to get a
handle }
    { to the (parent) window of OutLook and set Application.Handle
before you }
    { show any UI otherwise VCL will create one and all your windows
and }
    { dialogs will be independent windows with an ugly button on the
task bar }
    if  (eecontext = EECONTEXT_VIEWER)
    and (lpeecb.GetWindow(hwndExchange) = S_OK) then
        Application.Handle := hwndExchange;

    Result := S_OK;

    { save these for later }
    FCallback   := lpeecb;
    FContext    := eecontext;

    { show some info }
    case FContext of
        EECONTEXT_SESSION:              msg := 'SESSION';
        EECONTEXT_VIEWER:               msg := 'VIEWER';
        EECONTEXT_REMOTEVIEWER:         msg := 'REMOTEVIEWER';
        EECONTEXT_SEARCHVIEWER:         msg := 'SEARCHVIEWER';
        EECONTEXT_ADDRBOOK:             msg := 'ADDRBOOK';
        EECONTEXT_SENDNOTEMESSAGE:      msg := 'SENDNOTEMESSAGE';
        EECONTEXT_READNOTEMESSAGE:      msg := 'READNOTEMESSAGE';
        EECONTEXT_SENDPOSTMESSAGE:      msg := 'SENDPOSTMESSAGE';
        EECONTEXT_READPOSTMESSAGE:      msg := 'READPOSTMESSAGE';
        EECONTEXT_READREPORTMESSAGE:    msg := 'READREPORTMESSAGE';
        EECONTEXT_SENDRESENDMESSAGE:    msg := 'SENDRESENDMESSAGE';
        EECONTEXT_PROPERTYSHEETS:       msg := 'PROPERTYSHEETS';
        EECONTEXT_ADVANCEDCRITERIA:     msg := 'ADVANCEDCRITERIA';
        EECONTEXT_TASK:                 msg := 'TASK';
    else
        msg := IntToStr(eecontext);
    end;

    if (Application.Handle>0) then begin
        ShowMessage(format('TOutlookExt.Install(): %s
%x',[msg,Application.Handle]));
    end;

end;

function TOutlookExt.InstallCommands(lpeecb: IExchExtCallback; hwnd:
HWND; hmenu: HMENU; var lpcmdidBase: UINT; lptbeArray :
LPTBENTRY_Array; ctbe: UINT; ulFlags: ULONG): HRESULT; stdcall;
var hMenuTools: Windows.HMENU; posMin, posMax: longint;
begin

    Result := S_FALSE;
    if (FContext = EECONTEXT_VIEWER) then begin
        ShowMessage(format('TOutlookExt.InstallCommands():
%x',[FContext]));
        FMenu := hwnd;
        lpeecb.GetMenuPos(EECMDID_ToolsOptions, hMenuTools, posMin,
posMax, 0);
        AppendMenu(hMenuTools,MF_SEPARATOR,0,nil);
        AppendMenu(hMenuTools,MF_BYPOSITION or
MF_STRING,lpcmdidBase,'SHIPS TOOLS');
        FCommandID := lpcmdidBase;
        Inc(lpcmdidBase);
    end;
end;

procedure TOutlookExt.InitMenu(lpeecb : IExchExtCallback);stdcall;
begin
    { do nothing }
end;

function TOutlookExt.DoCommand(lpeecb : IExchExtCallback; cmdid :
UINT):HRESULT;stdcall;
begin
    Result := S_FALSE;
    if (cmdid = FCommandID) then begin
        ShowMessage('SHIPS NAMES');
        Result := S_OK;
    end;
end;

end.