В этом случае моя динамически загружаемая dll загружается проводником Windows для добавления новой таблицы свойств (новой вкладки) на страницу свойств файла / папки.
Простым примером этого является StrmExt.dll ( источник загрузки ).В этом примере (источник предоставлен Microsoft) dll НЕ использует локальное хранилище потоков (TLS) и поэтому вызывает серьезные проблемы при загрузке нескольких страниц свойств одновременно.
При просмотре источника dll требуется один поток-base переменная (путь к файлу файла) ...
static TCHAR g_szFile[MAX_PATH];
Изменение этой строки кода на:
_declspec (thread) TCHAR g_szFile[MAX_PATH];
... позволило DLL поддерживать несколько потокови, следовательно, несколько экземпляров таблицы свойств.Тем не менее, я знал, что это изменение будет поддерживаться только Windows Vista и более новыми (тесты на Windows 7 были очень положительными).XP, например, не будет поддерживать это для динамически загружаемой библиотеки ... и известно, что вызывает сбой приложения .(см. последний абзац).
Для запуска на XP я не мог использовать это объявление.Я подозревал, что мне нужно было улучшить их точку входа DLL с:
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
_Module.Init(ObjectMap, hInstance, &LIBID_STRMEXTLib);
DisableThreadLibraryCalls(hInstance);
}
else if (dwReason == DLL_PROCESS_DETACH)
_Module.Term();
return TRUE; // ok
}
... до чего-то подобного ... как мы видели ранее здесь
struct ThreadData {
static TCHAR g_szFile[MAX_PATH];
};
...
DWORD g_dwThreadIndex;
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance,
DWORD dwReason, LPVOID /*pReserved*/)
{
ThreadData* pData;
switch (dwReason) {
case DLL_PROCESS_ATTACH:
g_dwThreadIndex = ::TlsAlloc();
if (g_dwThreadIndex == TLS_OUT_OF_INDEXES)
return FALSE;
// execute the DLL_THREAD_ATTACH code
case DLL_THREAD_ATTACH:
// allocate memory for this thread
pData = (ThreadData*) ::LocalAlloc(LPTR, sizeof(ThreadData));
if (pData == 0)
return FALSE;
::TlsSetValue(g_dwThreadIndex, (LPVOID) pData);
break;
case DLL_THREAD_DETACH:
// release memory for this thread
pData = (ThreadData*) ::TlsGetValue(g_dwThreadIndex);
if (pData != 0)
::LocalFree((HLOCAL) pData);
break;
case DLL_PROCESS_DETACH:
// release memory for this thread
pData = (ThreadData*) ::TlsGetValue(g_dwThreadIndex);
if (pData != 0)
::LocalFree((HLOCAL) pData);
// release the TLS index
::TlsFree(g_dwThreadIndex);
break;
}
return TRUE;
}
Это прекрасно работает во время первой загрузки DLL, независимо от того, создаю ли я 1 или 2 потока.После освобождения библиотеки DLL при следующей загрузке библиотеки происходит сбой Explorer.
Что я неправильно понимаю?Я заметил, что оригинальный разработчик намеренно отключил уведомление о потоке при уведомлении о прикреплении процесса к dll.Зачем?
DisableThreadLibraryCalls(hInstance);
Спасибо заранее.