Здравствуйте George Seryakov, Вы писали:
GS>Привет!
GS>Тут мы (не я, кстати) пытаемя получить поддержку из MS, и получили в ответ "<..> components are marked as “Both”. If they are created by DCOM clients they will be bound to the MTA." Речь идет про MTS/COM+ компонент. Чушь, по моему. Но как это проверить? Как можно в коде компонента найти в каком апартменте он создан, причем для STA — в каком именно STA — host, main или ином, и как-то идентифицировать апартмент (по хендлу окна?) нельзя ли?
По смещению 0F80h в TEB находится адрес структуры, которая определяет параметры апартамента. Если указатель равен нулю, СОМ не инициализированна. Если инициализированна, по смещению 12 в этой структуре находится переменная, по значению которой можно определить тип аппартамента.
Пример кода:
int k;
__asm{
mov eax,fs:[18h];
mov eax,[eax+0F80h];
mov ebx,[eax+0Ch];
mov k,ebx
}
if (k == 0x81){
//STA
}
else if (k == 0x141){
//MTA
}
А пользоваться документированными функциями любой сможет! Шутка!
Здравствуйте George Seryakov, Вы писали:
GS>Привет!
GS>Тут мы (не я, кстати) пытаемя получить поддержку из MS, и получили в ответ "<..> components are marked as “Both”. If they are created by DCOM clients they will be bound to the MTA." Речь идет про MTS/COM+ компонент. Чушь, по моему. Но как это проверить? Как можно в коде компонента найти в каком апартменте он создан, причем для STA — в каком именно STA — host, main или ином, и как-то идентифицировать апартмент (по хендлу окна?) нельзя ли?
Можно использовать HRESULT CoGetApartmentID(DWORD dwFlag, DWORD* pID);
dwFlag надо передавать -1
Функция недокументированная.
Находится в ole32.dll
С ее помощью всегда можно определить в каком апартменте мы сейчас находимся
Здравствуйте George Seryakov, Вы писали:
GS>Тут мы (не я, кстати) пытаемя получить поддержку из MS, и получили в ответ "<..> components are marked as “Both”. If they are created by DCOM clients they will be bound to the MTA." Речь идет про MTS/COM+ компонент. Чушь, по моему. Но как это проверить? Как можно в коде компонента найти в каком апартменте он создан, причем для STA — в каком именно STA — host, main или ином, и как-то идентифицировать апартмент (по хендлу окна?) нельзя ли?
Попробуй прогнать CoInitializeEx и смотри сообщение об ошибке:
S_FALSE — The COM library is already initialized on the calling thread.
RPC_E_CHANGED_MODE — A previous call to CoInitializeEx specified a different concurrency model for the calling thread. If running Windows 2000, this could also mean that a change from neutral threaded apartment to single threaded apartment occurred.
Здравствуйте Алекс, Вы писали:
А>По смещению 0F80h в TEB находится адрес структуры, которая определяет параметры апартамента. Если указатель равен нулю, СОМ не инициализированна. Если инициализированна, по смещению 12 в этой структуре находится переменная, по значению которой можно определить тип аппартамента.
А>
GS>Попробовал я. В MTA там действительно 0x141. А вот при вызове из-под STA, сгенеренного VC клиентом — имеем 0x89, a VB клиентом — 0x8b.
Поправочка: когда из-под дебаггера — 0x8b, из-под компилированного кода (и скрипта) — 0x89. Дровишки я, кстати, нашел в MSDN. Вот только бы найти еще описание COM TLS structure.
0x80 — это маска апартментной модели (0x140 — MTA), а вот за что отвечает 9-ка и 11-ка?
Тут мы (не я, кстати) пытаемя получить поддержку из MS, и получили в ответ "<..> components are marked as “Both”. If they are created by DCOM clients they will be bound to the MTA." Речь идет про MTS/COM+ компонент. Чушь, по моему. Но как это проверить? Как можно в коде компонента найти в каком апартменте он создан, причем для STA — в каком именно STA — host, main или ином, и как-то идентифицировать апартмент (по хендлу окна?) нельзя ли?
Здравствуйте VladD2, Вы писали:
VD>Здравствуйте George Seryakov, Вы писали:
GS>>Тут мы (не я, кстати) пытаемя получить поддержку из MS, и получили в ответ "<..> components are marked as “Both”. If they are created by DCOM clients they will be bound to the MTA." Речь идет про MTS/COM+ компонент. Чушь, по моему. Но как это проверить? Как можно в коде компонента найти в каком апартменте он создан, причем для STA — в каком именно STA — host, main или ином, и как-то идентифицировать апартмент (по хендлу окна?) нельзя ли?
VD>Попробуй прогнать CoInitializeEx и смотри сообщение об ошибке:
VD>S_FALSE — The COM library is already initialized on the calling thread.
VD>RPC_E_CHANGED_MODE — A previous call to CoInitializeEx specified a different concurrency model for the calling thread. If running Windows 2000, this could also mean that a change from neutral threaded apartment to single threaded apartment occurred.
VD>
When an object that is configured to run in the neutral threaded apartment (NTA) is called by a thread that is in either an STA or the MTA, that thread transfers to the NTA. If this thread subsequently calls CoInitializeEx, the call fails and returns RPC_E_CHANGED_MODE.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте George Seryakov, Вы писали:
GS>Привет!
GS>Тут мы (не я, кстати) пытаемя получить поддержку из MS, и получили в ответ "<..> components are marked as “Both”. If they are created by DCOM clients they will be bound to the MTA." Речь идет про MTS/COM+ компонент. Чушь, по моему. Но как это проверить? Как можно в коде компонента найти в каком апартменте он создан, причем для STA — в каком именно STA — host, main или ином, и как-то идентифицировать апартмент (по хендлу окна?) нельзя ли?
Конечно можно. Используй TLS, так как аппартаменты всё равно привязаны к TLS, то этот способ самый надёжный и простой (его по моему и ком использует)
Здравствуйте George Seryakov, Вы писали:
GS>Тут мы (не я, кстати) пытаемя получить поддержку из MS, и получили в ответ "<..> components are marked as “Both”. If they are created by DCOM clients they will be bound to the MTA." Речь идет про MTS/COM+ компонент. Чушь, по моему. Но как это проверить? Как можно в коде компонента найти в каком апартменте он создан, причем для STA — в каком именно STA — host, main или ином, и как-то идентифицировать апартмент (по хендлу окна?) нельзя ли?
Да нет, видимо не чушь. Мы тут вчера тоже наступили на грабли, когда случайно установили пулинг для COM+ — приложения, объекты которого держат внутренние ссылки на другие объекты. На втором вызове компонента стабильно получаем "Interface was marshaled from a different thread". В STA такого бы не было.
Здравствуйте Lexey, Вы писали:
GS>>Тут мы (не я, кстати) пытаемя получить поддержку из MS, и получили в ответ "<..> components are marked as “Both”. If they are created by DCOM clients they will be bound to the MTA." Речь идет про MTS/COM+ компонент. Чушь, по моему. Но как это проверить? Как можно в коде компонента найти в каком апартменте он создан, причем для STA — в каком именно STA — host, main или ином, и как-то идентифицировать апартмент (по хендлу окна?) нельзя ли?
L>Да нет, видимо не чушь. Мы тут вчера тоже наступили на грабли, когда случайно установили пулинг для COM+ — приложения, объекты которого держат внутренние ссылки на другие объекты. На втором вызове компонента стабильно получаем "Interface was marshaled from a different thread". В STA такого бы не было.
Да, отнюдь не чушь. Вот что я напроверял. Компонент — под COM+/ конфигурированный. Строки — вызовы из, соответственно, STA и MTA (CoInitializeEx(NULL, COINIT_APARTMENTTHREADED или COINIT_MULTITHREADED)). Стоблцы — параметр ThreadingModel в реджистри. На пересечении — результат: STA, если CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) отозвался S_FALSE и MTA, соответвенно. NTA — оба вызова отозвались как RPC_E_CHANGED_MODE. Цифры — значение двух байтов по смещению 0xC в COM TLS structure. Для Both компонент ведет себя как Free.
Apartment Free no Neutral
STA STA, 0x8a MTA, 0x1002 STA, 0x208a NTA, 0x1802
MTA STA, 0x8a MTA, 0x1002 STA, 0x208a NTA, 0x1802
Пулинг и прочее я не трогал. Этот МасЛеод знал заранее, что под компласом все куда хитрее...
Здравствуйте TK, Вы писали:
TK>When an object that is configured to run in the neutral threaded apartment (NTA) is called by a thread that is in either an STA or the MTA, that thread transfers to the NTA. If this thread subsequently calls CoInitializeEx, the call fails and returns RPC_E_CHANGED_MODE.
Здравствуйте VladD2, Вы писали:
TK>>When an object that is configured to run in the neutral threaded apartment (NTA) is called by a thread that is in either an STA or the MTA, that thread transfers to the NTA. If this thread subsequently calls CoInitializeEx, the call fails and returns RPC_E_CHANGED_MODE.
VD>Ну, и?
Признаком NTA будет отлуп RPC_E_CHANGED_MODE из STA и MTA.
Здравствуйте George Seryakov, Вы писали: TK>>>When an object that is configured to run in the neutral threaded apartment (NTA) is called by a thread that is in either an STA or the MTA, that thread transfers to the NTA. If this thread subsequently calls CoInitializeEx, the call fails and returns RPC_E_CHANGED_MODE.
VD>>Ну, и?
GS>Признаком NTA будет отлуп RPC_E_CHANGED_MODE из STA и MTA.
Здравствуйте, мы писали:
GS>Да, отнюдь не чушь. Вот что я напроверял. Компонент — под COM+/ конфигурированный. Строки — вызовы из, соответственно, STA и MTA (CoInitializeEx(NULL, COINIT_APARTMENTTHREADED или COINIT_MULTITHREADED)). Стоблцы — параметр ThreadingModel в реджистри. На пересечении — результат: STA, если CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) отозвался S_FALSE и MTA, соответвенно. NTA — оба вызова отозвались как RPC_E_CHANGED_MODE. Цифры — значение двух байтов по смещению 0xC в COM TLS structure. Для Both компонент ведет себя как Free.
GS>
Здравствуйте Ivan, Вы писали:
I>Здравствуйте George Seryakov, Вы писали:
хъ
I>Можно использовать HRESULT CoGetApartmentID(DWORD dwFlag, DWORD* pID); I>dwFlag надо передавать -1 I>Функция недокументированная. I>Находится в ole32.dll I>С ее помощью всегда можно определить в каком апартменте мы сейчас находимся
Интересная функция! По ней можно всю COM TLS изучить!
Здравствуйте Tom, Вы писали:
Tom>[skip] Tom>Может ещё какие дровишки есть ?
Смотря о чем речь
Если из недокументированного , могу предложить CoGetCurrentLogicalThreadID — возвращает ID текущего логического потока (учитывает переключения потоков при пересечении границы апартмента)
Здравствуйте Ivan, Вы писали:
I>Здравствуйте Tom, Вы писали:
Tom>>[skip] Tom>>Может ещё какие дровишки есть ?
I>Смотря о чем речь I>Если из недокументированного , могу предложить CoGetCurrentLogicalThreadID — возвращает ID текущего логического потока (учитывает переключения потоков при пересечении границы апартмента)
Ну эту хрень я у себя в MSDN нашёл...
Здравствуйте Ivan, Вы писали:
I>Здравствуйте Tom, Вы писали:
Tom>>Ну эту хрень я у себя в MSDN нашёл... I>Это что за MSDN такой ? У меня в July 2002 описания нет
July 2001. и то описание в Win CE и написано всего: "This function is not yet supported."
Здравствуйте Ivan, Вы писали:
I>Можно использовать HRESULT CoGetApartmentID(DWORD dwFlag, DWORD* pID); I>dwFlag надо передавать -1 I>Функция недокументированная. I>Находится в ole32.dll I>С ее помощью всегда можно определить в каком апартменте мы сейчас находимся
Работает, позволяет увидеть смену апартмента в тех случаях, когда он заведомо должен меняться. Под dllhost показывает MTA как 0xcccccccc. Вот только насчет "каком апартменте" — непонятно. Не видно как по номеру апартмента получить его тип. Кроме апартмента 0xcccccccc для конфигурированных компонент.
Здравствуйте Алекс, Вы писали:
I>>Можно использовать HRESULT CoGetApartmentID(DWORD dwFlag, DWORD* pID);
А>Интересная функция! По ней можно всю COM TLS изучить!
В смысле рассматривая ее винарный код? Поделись, что нарыл. А исходники wine ты посмотрел — там есть нечто, выдаваемое за структуру COM TSL.