Очередные грабли от Microsoft. При попытке сгенерить достаточно простой проект на
ATL 7.0 (с аттрибутами, с помощью VS .Net) возникет совершенно безумный вариант поведения кода.
Вариант 1 (безумный). Простейший COM объект с поддержкой событий.
Значение this при входе в реализацию метода test().
this - 0x00EF4D60
Дамп памяти по this
0x00EF4D60 cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
0x00EF4D77 cd 78 d3 ed 00 50 d3 ed 00 00 00 00 00 00 00 00 00 28 d3 ed 00 10 d3 ÍxÓí.PÓí.........(Óí..Ó
// Disassembly кода метода
STDMETHODIMP CATLMini::test(BSTR* str)
{
00EB5470 push ebp
00EB5471 mov ebp,esp
00EB5473 sub esp,0D0h
00EB5479 push ebx
00EB547A push esi
00EB547B push edi
00EB547C lea edi,[ebp-0D0h]
00EB5482 mov ecx,34h
00EB5487 mov eax,0CCCCCCCCh
00EB548C rep stos dword ptr [edi]
test2(str);
00EB548E mov esi,esp
00EB5490 mov eax,dword ptr [str]
00EB5493 push eax
00EB5494 mov ecx,dword ptr [this]
00EB5497 mov edx,dword ptr [ecx]
00EB5499 mov eax,dword ptr [this]
00EB549C push eax
00EB549D call dword ptr [edx+18h] // edx = 0xcdcdcdcdcd
00EB54A0 cmp esi,esp
00EB54A2 call @ILT+3015(__RTC_CheckEsp) (0EB3BCCh)
...
// IATLMini
[
object,
uuid(3D6E6725-F60A-46EE-95BF-DF4E4D573436),
dual,
helpstring("IATLMini Interface"),
pointer_default(unique)
]
__interface IATLMini : public IDispatch
{
[id(1), helpstring("method test")] HRESULT test(BSTR* str);
};
// CATLMini
[
coclass,
threading("apartment"),
vi_progid("ATLMinimal.ATLMini"),
progid("ATLMinimal.ATLMini.1"),
version(1.0),
uuid("163E5AED-7A46-4B88-995F-BE02863E6307"),
helpstring("ATLMini Class"),
event_source("com"),// поддержка событий
registration_script("control.rgs")
]
class ATL_NO_VTABLE CATLMini :
public IATLMini
{
public:
CATLMini(){}
__event __interface _IATLMiniEvents;// поддержка событий
public:
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct(){return S_OK;}
void FinalRelease(){}
STDMETHOD(test)(BSTR* str);
STDMETHOD(test1)(BSTR* str);
STDMETHOD(test2)(BSTR* str);
};
Вариант 2 (рабочий). Простейший COM объект без поддержки событий.
Значение this при входе в реализацию метода test().
this - 0x00EF4D60
Дамп памяти по this
0x00EF4D60 fc 52 ed 00 e8 52 ed 00 01 00 00 00 fd fd fd fd ab ab ab ab üRí.èRí.....ýýýý««««
0x00EF4D74 ab ab ab ab 00 00 00 00 00 00 00 00 50 00 09 00 00 14 ee fe ««««........P.....îþ
// Disassembly кода метода
STDMETHODIMP CATLMini::test(BSTR* str)
{
00EB3010 push ebp
00EB3011 mov ebp,esp
00EB3013 sub esp,0D0h
00EB3019 push ebx
00EB301A push esi
00EB301B push edi
00EB301C lea edi,[ebp-0D0h]
00EB3022 mov ecx,34h
00EB3027 mov eax,0CCCCCCCCh
00EB302C rep stos dword ptr [edi]
test2(str);
00EB302E mov esi,esp
00EB3030 mov eax,dword ptr [str]
00EB3033 push eax
00EB3034 mov ecx,dword ptr [this]
00EB3037 mov edx,dword ptr [ecx]
00EB3039 mov eax,dword ptr [this]
00EB303C push eax
00EB303D call dword ptr [edx+24h] // edx = 0x00ed52fc
00EB3040 cmp esi,esp
00EB3042 call @ILT+2575(__RTC_CheckEsp) (0EB1A14h)
...
// IATLMini
[
object,
uuid(3D6E6725-F60A-46EE-95BF-DF4E4D573436),
dual,
helpstring("IATLMini Interface"),
pointer_default(unique)
]
__interface IATLMini : public IDispatch
{
[id(1), helpstring("method test")] HRESULT test(BSTR* str);
};
// CATLMini
[
coclass,
threading("apartment"),
vi_progid("ATLMinimal.ATLMini"),
progid("ATLMinimal.ATLMini.1"),
version(1.0),
uuid("163E5AED-7A46-4B88-995F-BE02863E6307"),
helpstring("ATLMini Class"),
//event_source("com"),
registration_script("control.rgs")
]
class ATL_NO_VTABLE CATLMini :
public IATLMini
{
public:
CATLMini(){}
//__event __interface _IATLMiniEvents;
public:
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct(){return S_OK;}
void FinalRelease(){}
STDMETHOD(test)(BSTR* str);
STDMETHOD(test1)(BSTR* str);
STDMETHOD(test2)(BSTR* str);
};
// Реализация метода test()
STDMETHODIMP CATLMini::test(BSTR* str)
{
test2(str);
*str = CComBSTR("Hello World!").Detach();
return S_OK;
}
Таким образом нормально вызываются только методы унаследованных интерфейсов (в коклассе).
Возникают аналогичные проблемы при попытке аггрегировать внешние COM объекты, да как-то
странно это
. Может у кого-нибудь есть идеи как побороть ситуацию.
Заранее благодарен за любую помощь.