Проблемы с ATL 7.0
От: KlimHawk Россия  
Дата: 11.04.03 08:57
Оценка:
Очередные грабли от 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 объекты, да как-то
странно это . Может у кого-нибудь есть идеи как побороть ситуацию.
Заранее благодарен за любую помощь.
KlimHawk
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.