IMessageFilterを使う

AutoCAD2012を外部からコントロールして自動処理するプログラムを作成してて遭遇したんですが、不定期なタイミングでRPC_E_CALL_REJECTEDが発生するんです。
調べて見るとAutoCAD2010のSP1かな?辺りから発生するようになっているようで、IMessageFilter(COMのインターフェースの方です)を実装してリトライ掛けるようにすれば解決するという事なんで実装してみました。

HandleInComingCallは、COMサーバー側で呼ばれる関数らしい。MessagePendingは、良く判りません。
RetryRejectedCallは、COMサーバーのHandleInComingCallからSERVERCALL_REJECTEDかSERVERCALL_RETRYLATERが返ってきた時に呼ばれる関数らしい。0以上の値を返すと処理のリトライを出来るようなので、dwRejectTypeがSERVERCALL_RETRYLATERの時に1000を返してリトライを実行するようにしたらエラーも出なくなりました。

uses
  Classes, Windows, ActiveX;
type
  TMessageFilter = class(TInterfacedObject, IMessageFilter)
  private
    FOldFilter: IMessageFilter;
  public
    constructor Create;

    // フィルタの登録
    procedure RegisterFilter;
    // フィルタの登録解除
    procedure RevokeFilter;

    function HandleInComingCall(dwCallType: Longint; htaskCaller: HTask;
      dwTickCount: Longint; lpInterfaceInfo: PInterfaceInfo): Longint;
      stdcall;
    function RetryRejectedCall(htaskCallee: HTask; dwTickCount: Longint;
      dwRejectType: Longint): Longint; stdcall;
    function MessagePending(htaskCallee: HTask; dwTickCount: Longint;
      dwPendingType: Longint): Longint; stdcall;
  end;

implementation

constructor TMessageFilter .Create;
begin
  inherited;
  FOldFilter := Nil;
end;

function TMessageFilter .HandleInComingCall(dwCallType: Integer;
  htaskCaller: HTask; dwTickCount: Integer;
  lpInterfaceInfo: PInterfaceInfo): Longint;
begin
  Result := 0;
end;

function TMessageFilter .MessagePending(htaskCallee: HTask; dwTickCount,
  dwPendingType: Integer): Longint;
begin
  Result := PENDINGMSG_WAITNOPROCESS;
end;

procedure TMessageFilter.RegisterFilter;
begin
  CoRegisterMessageFilter(Self, FOldFilter);
end;

function TMessageFilter .RetryRejectedCall(htaskCallee: HTask; dwTickCount,
  dwRejectType: Integer): Longint;
begin
  if dwRejectType = SERVERCALL_RETRYLATER then
    Result := 1000
  else
    Result := -1;
end;

procedure TMessageFilter.RevokeFilter;
var
  dmy: IMessageFilter;
begin
  CoRegisterMessageFilter(FOldFilter, dmy);
end;