Проверка на вшивость IUnknown
От: Михаил  
Дата: 19.10.01 18:05
Оценка:
Пожалуйста, помогите решить проблему.
Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит. Чтобы отсеять не нужные. Проблема в том, что часть из них может тормозить или висеть, т.е. не желательно QueryInterface или любое другое обращение к каждому по очереди. Есть ли такие функции в COM или в kernel, которые дадут нужную информацию прямо по значению указателя? Понятно, что Windows сама это делает, иначе не работала бы, но как?!
...А отсюда наливаем, когда рецепт написан совсем неразборчиво...
Re: Проверка на вшивость IUnknown
От: ZORK Россия www.zorkaltsev.com
Дата: 19.10.01 18:27
Оценка:
Здравствуйте Михаил, Вы писали:

М>Пожалуйста, помогите решить проблему.

М>Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит. Чтобы отсеять не нужные. Проблема в том, что часть из них может тормозить или висеть, т.е. не желательно QueryInterface или любое другое обращение к каждому по очереди. Есть ли такие функции в COM или в kernel, которые дадут нужную информацию прямо по значению указателя? Понятно, что Windows сама это делает, иначе не работала бы, но как?!

Так как есть Custom Marshaling, то в общем случае это задача точно не решается. И даже в частном случае — стандартный маршалин, Windows тебе скорее всего не даст этой инфо, это исключительно внутренее, и повода этo показывать нет, а то народ начнет извращаться — как ты это хочешь сделать :))

Если тебе надо выяснить умер ли объект, то надо его пинговать, и при этом IUnknown для этого не подходит, так как он может быть оптимизирован маршалерром и работать даже когда связи с объектом нет. Так что надо какой-то более конкретный интерфейс, со специальным методом, который ничего не делает, и просто проверяет соединение. При это важно уметь прерывать этот вызов, так как иначе он может висеть до бесконечности — я тестировал, весит.

Я раньше дискутировал проблему прерывания, основными результами было:
— посмотреть http://www.optim.ru/cs/2000/4/com_htm/com_2.asp
— использовать IMessageFileter::MessagePending, если это STA (Single Thread Apartment), или
— использовать CoCancelCall (это работает для любой модели апартмента), и при этом если ты программируешь под Windows 2000, чтобы не создавать дополнительных ниток можно использовать Waitable Timer (см. ::CreateWaitableTimer)

И если ты не хочешь последовательно проверять все объекты, то надо создать кучу ниток для проверки их параллельно — так должно быть намного эффективнее, особенно если речь идет о сетевых соединениях.

-Zork
Думать надо ...головой :)
Re[2]: Проверка на вшивость IUnknown
От: Михаил  
Дата: 19.10.01 19:20
Оценка:
Здравствуйте ZORK, Вы писали:

ZORK>И если ты не хочешь последовательно проверять все объекты, то надо создать кучу ниток для проверки их параллельно — так должно быть намного эффективнее, особенно если речь идет о сетевых соединениях.


Я и остановился на этом варианте. Но требуется — всего лишь определить модуль-источник интерфейса! Если это играет роль, уточню задачу. Надо из списка активных объектов т.е. ROT выбрать нужные, и все. Те которые нужны — file moniker'ы (остальные легко отсеиваются по IMoniker->IsSystemMoniker), но не все, а рожденные нужным приложением. Причем имя файла может быть любым, естественно. Парсить имя файла — не годится. Поскольку не определено, какие юзер хочет имена. Какие хочет, такие и будут. Например, юзер может захотеть, чтобы xren.xls был Word'овским документом. В заключение добавлю, что эта операция висит в обновлении окна диалога, т.е. ждать ну совсем не хочется. И задача — _быстро_ узнать, чьи моникеры в ROT. Без опроса их самих. И в общем случае их там может быть много. По-моему, задача типа построения списка открытых (во многих окнах) документов имеет нормальное решение?
...А отсюда наливаем, когда рецепт написан совсем неразборчиво...
Re[2]: Проверка на вшивость IUnknown
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.10.01 19:39
Оценка:
Здравствуйте ZORK, Вы писали:

Zork! Отличное знание COM-а. Особенно для человека пытающегося развизать религиозную войну Java vs MS. :)
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Проверка на вшивость IUnknown
От: ZORK Россия www.zorkaltsev.com
Дата: 22.10.01 01:48
Оценка:
Здравствуйте VladD2, Вы писали:

VD>Здравствуйте ZORK, Вы писали:


VD>Zork! Отличное знание COM-а. Особенно для человека пытающегося развизать религиозную войну Java vs MS. :)


:)) — ну если ты обратишь внимание на мой ответ, то там был концептуальный анализ. Суть которого сводилась: если вы работает с объектами, то и работайте с объектами ...и не надо вдруг вспоминать про то как они устроенны и где лежает. Это кстати называется инкопсуляцией. Потому что если Вы так будет делать, то скорее всего работать у вас это будет как С# Beta 1 — только на компьютере, на котором это было написанно :))

А религиозной войны — поверь, я тут не развожу. А мне зачем?
Думать надо ...головой :)
Re: Проверка на вшивость IUnknown
От: Финченко Юрий  
Дата: 29.10.01 21:27
Оценка:
Здравствуйте Михаил, Вы писали:

М>Пожалуйста, помогите решить проблему.

М>Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит. Чтобы отсеять не нужные. Проблема в том, что часть из них может тормозить или висеть, т.е. не желательно QueryInterface или любое другое обращение к каждому по очереди. Есть ли такие функции в COM или в kernel, которые дадут нужную информацию прямо по значению указателя? Понятно, что Windows сама это делает, иначе не работала бы, но как?!

Ничего если я вклюнюсь.
Решил посмотреть на ROT в Win 2000.
Вызвал EnumRunning
А в ответ получил для номера элемента (Celt) = 1 Oбъект, а при
попытке получить любой другой объект из списка сообщение об ошибке.

CoInitialize(NULL);
res = GetRunningObjectTable (0, &pROT);
res = pROT->EnumRunning(&pEM); // здесь приходит сообщение о том,
// что была ошибка доступа к файлу
// но не фатальная, все продолжает
// работать
for (int i=0; i<10; i++)
{
res = pEM->Next(i, (IMoniker**)&pMon, &iMonCount);
pMon->... // что нибудь делаем
}
pEM->Release();
pROT->Release();
CoUninitialize();

В чем я кардинально не прав ?
Re: Проверка на вшивость IUnknown
От: Snax Россия  
Дата: 30.10.01 03:25
Оценка:
Здравствуйте Михаил, Вы писали:

М>Пожалуйста, помогите решить проблему.

М>Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит


DWORD_PTR *pVTable = ((DWORD_PTR **)pUnk)[0];

HMODULE hModule = NULL;
MEMORY_BASIC_INFORMATION mbi = {0};
DWORD dwRet = ::VirtualQuery(LPVOID(pVTable[0]), &mbi, sizeof(MEMORY_BASIC_INFORMATION));
if (sizeof(MEMORY_BASIC_INFORMATION) == dwRet)
    hModule = (HMODULE)mbi.AllocationBase;
Re[2]: Проверка на вшивость IUnknown
От: Snax Россия  
Дата: 30.10.01 03:41
Оценка:
Здравствуйте Snax, Вы писали:

S>Здравствуйте Михаил, Вы писали:


М>>Пожалуйста, помогите решить проблему.

М>>Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит

В догонку. Для proxy/stub получишь конечно HMODULE этих proxy/stub. Тогда его нужно маршалить в поток с флагом "другой компрьютер"
и смотреть что внутри. Внутри будет имя машины, ID процесса и ID апартмента и cookie, с которого там можно получить IUnknown.
Так что вычислить имя .exe зная имя тачки и ID процесса можно, но если интерфейс лежит в Dll то фиг. Теоретически, если компьютер
тот же самый, можно закинуть в тот процесс свою DLL и если объект с FTM или MTA-шный, можно узнать "родной" HMODULE. Если объект STA-шный
можно попробовать из нашей ловкой DLL создать еще более ловкий STA-объект и он с большой вероятностью попадет в тот же STA. Хотя
может и не попасть. Такие пироги.
Re: Проверка на вшивость IUnknown
От: Финченко Юрий  
Дата: 31.10.01 17:07
Оценка:
Здравствуйте Михаил, Вы писали:

М>Пожалуйста, помогите решить проблему.

М>Есть куча указателей IUnknown, нужно определить ProgId или CLSID приложения, которое их предоставило. Просто имя модуля — уже на 100% устроит. Чтобы отсеять не нужные. Проблема в том, что часть из них может тормозить или висеть, т.е. не желательно QueryInterface или любое другое обращение к каждому по очереди. Есть ли такие функции в COM или в kernel, которые дадут нужную информацию прямо по значению указателя? Понятно, что Windows сама это делает, иначе не работала бы, но как?!


-----------------------------------------
Если имет дело с ActiveX объектами, то они дожны реализовывать IOleObject поидее.
Этот код позволяет узнать какие еще есть элементы на форме, по идее, то же самое и
с ROT

LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
CComPtr<IOleClientSite> pCS;
CComPtr<IOleContainer> pOC;
IUnknown* objectPointer = NULL;
ULONG number = 0, i = 1;
BSTR ddd = SysAllocStringByteLen(NULL, 100);
HRESULT res = ((IOleClientSite*)m_spClientSite)->GetContainer(&pOC);
if (res != S_OK) MessageBox(L"Error get containter");
//res = pCS->GetContainer(&pOC);
if (res == S_OK)
{
CComPtr<IEnumUnknown> reshima;
res = pOC->EnumObjects(OLECONTF_EMBEDDINGS, &reshima);
if (res == S_OK)
{
BOOL stop = FALSE;
while (stop == FALSE)
{
res = reshima->Next(1, &objectPointer, &number);
if (res != S_OK)
{
i--;
stop = TRUE;
}
else
{
IOleObject* pOO = NULL;
CLSID cid;
HRESULT rr = NULL;
rr = objectPointer->QueryInterface(IID_IOleObject,
(void**)&pOO);
if (rr == S_OK)
{
rr = pOO->GetUserClassID(&cid);
if (rr == S_OK)
{
rr = OleRegGetUserType
(cid,USERCLASSTYPE_FULL, &ddd);
if (rr == S_OK)
MessageBox(ddd, L"Information",
MB_OK + MB_ICONINFORMATION);
}
}
pOO->Release();
pOO = NULL;
if (objectPointer != NULL)
{
objectPointer ->Release();
objectPointer = NULL;
}
i++;
}
}
SysFreeString(ddd);
ddd = NULL;
}
}
else
{
MessageBox(L"not implemented IOleContainer");
}
return 0;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.