Нарушение прав доступа приведения IDispatch в XE2
Мы используем какой-то старый код (ComLib.pas, созданный Бин Ли), чтобы мы могли использовать интерфейс перечисления для объекта (OleVariant):
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 }
Этот код работает на Delphi 2010 и 2007, но не на XE2. На строке, отмеченной выше (с комментарием "RAISES EXCEPTION"), мы получаем исключение:
Project x.exe поднял класс исключения $C0000005 с сообщением "нарушение прав доступа по адресу 0xbaadf00d: чтение адреса 0xbaadf00d".
Переданный объект имеет интерфейс TDispNewEnum, поэтому исключение вызывать не следует (как в случае с Delphi 2010 и 2007).
Предложения? Благодарю.
1 ответ
0xbaadf00d
адрес памяти - это адрес псевдопамяти, что означает "ПЛОХАЯ ПИЩА" (посмотрите на гекса-символы). Обычно это используется кодом, когда вы запрашиваете недопустимые интерфейсы или вызовы.
Что если вы измените строку на:
pDisp: TDispNewEnum;
...
if (Succeeded (Unknown.QueryInterface (IDispatch, pDisp))) then
begin
_NewEnumPropFailed := False;
try
//property _NewEnum
Unknown:= pDisp._NewEnum;
...
что имеет смысл для меня.
Я заметил некоторые недокументированные изменения в привязке интерфейса XE2. Возможно, предыдущий код с принудительной приведением типа (TDispNewEnum(pDisp)
) больше не работает из-за этого.