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.
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.
来源:https://stackoverflow.com/questions/7874995/access-violation-casting-idispatch-in-xe2