3

We're using some old code (ComLib.pas created by Binh Ly) so we can use the enumeration interface on an (OleVariant) object:

type
  TDispNewEnum = dispinterface
    ['{97079E31-6957-11D2-9154-0000B4552A26}'] // dummy
    property _NewEnum: IUnknown readonly dispid -4; // DISPID_NEWENUM
    function _NewEnumFunc: IUnknown; dispid -4; // DISPID_NEWENUM
  end;

procedure TEnumVariant.AttachUnknown (const Unk: IUnknown);
var
  pDisp: IDispatch;
  _NewEnumPropFailed: boolean;
  Unknown: IUnknown;
begin
  Detach;
  Unknown := Unk;
  { extract IEnumVariant }
  if (Unknown <> nil) then
  begin
    { try IEnumVariant }
    if not (Succeeded (Unknown.QueryInterface (IEnumVariant, FEnumVariant))) then
    begin
      FEnumVariant := nil;  // safety!

      { test _NewEnum prop and _NewEnum func }
      if (Succeeded (Unknown.QueryInterface (IDispatch, pDisp))) then
      begin
        _NewEnumPropFailed := False;
        try
          //property _NewEnum
          Unknown:=TDispNewEnum(pDisp)._NewEnum; // <---- RAISES EXCEPTION -----
          if not (Succeeded(Unknown.QueryInterface(IEnumVariant, FEnumVariant))) then
            FEnumVariant := nil;  // safety!
        except
          _NewEnumPropFailed := True;
        end;  { except }

This code is working on Delphi 2010 and 2007, but not with XE2. On the line marked above (with the comment "RAISES EXCEPTION"), we get an exception:

Project x.exe raised exception class $C0000005 with message 'access violation at 0xbaadf00d: read of address 0xbaadf00d'.

The object passed in does have the TDispNewEnum interface so no exception should be raised (as is the case with Delphi 2010 and 2007).

Suggestions? Thanks.

Mick
  • 846
  • 2
  • 7
  • 18

1 Answers1

5

The 0xbaadf00d memory address is a pseudo memory address, meaning "BAD FOOD" (look at the hexa chars). This is used usually by code when you ask for invalid interfaces or calls.

What if you change the line into:

pDisp: TDispNewEnum;
...
if (Succeeded (Unknown.QueryInterface (IDispatch, pDisp))) then
begin
   _NewEnumPropFailed := False;
   try
     //property _NewEnum
     Unknown:= pDisp._NewEnum; 
...

which makes better sense to me.

I've noticed some undocumented changes in the XE2 interface binding. Perhaps the previous code with a forced typecast (TDispNewEnum(pDisp)) is not working any more because of that.

Arnaud Bouchez
  • 42,305
  • 3
  • 71
  • 159
  • I've used "FEnumVariant:=IUnknown(UnkV._NewEnum) as IEnumVariant" wrapped in try/except, and it appears to be working. – Mick Oct 24 '11 at 14:13
  • @Arnaud I've currently got a problem with XE2 and my Excel add-in based on Add-In Express. Calls to the Excel COM interfaces that worked in 2010 are now failing when compiled in XE2. I suspect that the XE2 COM layer is the thing that has changed and your comments in this answer make me suspect that your observations are related to my problem. Have you written up what you have discovered about XE2 and COM anywhere? – David Heffernan Oct 24 '11 at 16:30
  • 3
    This sounds exactly like what is stated in http://stackoverflow.com/questions/7886116 – Arnaud Bouchez Oct 25 '11 at 12:31