[Trick] DllMain нотификации без DLL
От: remark Россия http://www.1024cores.net/
Дата: 29.03.08 10:26
Оценка: 30 (2)
Задача: получать нотификации DLL_THREAD_ATTACH и DLL_THREAD_DETACH без создания собственной DLL.
Вопрос неоднократно встречался на этом форуме, но ответа не было.
Вот минимальный код. Проверил на MSVC2005/2008, в release/debug конфигурациях, со статическим и динамическим ран-таймом. Должно так же работать и на MSVC2003 и на MSVC6 (с небольшими изменениями). Единственная засада — со статическим ран-таймом не ловится нотификация DLL_PROCESS_ATTACH, но я думаю с этим можно жить.

#define _WIN32_WINNT 0x0500
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>

typedef void (NTAPI _TLSCB)(HINSTANCE, DWORD, PVOID);
_TLSCB on_tls_callback;

#pragma data_seg(push, old_seg)
#pragma data_seg(".CRT$XLB")
_TLSCB* p_thread_callback = on_tls_callback;
#pragma data_seg(pop, old_seg)

void NTAPI on_tls_callback(HINSTANCE, DWORD dwReason, PVOID)
{
  _TLSCB* volatile use_callback = p_thread_callback;
  static __declspec(thread) int volatile use_tls;
  use_tls = 0;

  static char const* ev[] = {"DLL_PROCESS_DETACH", "DLL_PROCESS_ATTACH", "DLL_THREAD_ATTACH", "DLL_THREAD_DETACH"};
  printf("%s (%d)\n", ev[dwReason], GetCurrentThreadId());
}

unsigned __stdcall thread(void*)
{
  printf("THREAD (%d)\n", GetCurrentThreadId());
  return 0;
}

int main()
{
  WaitForSingleObject((HANDLE)_beginthreadex(0, 0, &thread, 0, 0, 0), INFINITE);
  WaitForSingleObject((HANDLE)_beginthreadex(0, 0, &thread, 0, 0, 0), INFINITE);
}


Вывод:

DLL_PROCESS_ATTACH (3056)
DLL_THREAD_ATTACH (176)
THREAD (176)
DLL_THREAD_DETACH (176)
DLL_THREAD_ATTACH (2664)
THREAD (2664)
DLL_THREAD_DETACH (2664)
DLL_PROCESS_DETACH (3056)



Информация взята отсюда:
http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: [Trick] DllMain нотификации без DLL
От: gear nuke  
Дата: 29.03.08 23:05
Оценка:
Здравствуйте, remark, Вы писали:

R> static __declspec(thread) int volatile use_tls;


Мда, жаль, что MS сами не доделали... всего-то нужно убрать ограничение "Only POD classes may be instantiated using __declspec(thread)".


По поводу DLL_PROCESS_ATTACH — может быть просто с логированием проблемы? Хотя если и так используется CRT (всё же решение не чистое WinAPI, где вручную определяется IMAGE_TLS_DIRECTORY) вот фрагмент _cinit:
#ifndef CRTDLL
        /*
         * If we have any dynamically initialized __declspec(thread)
         * variables, then invoke their initialization for the thread on
         * which the DLL is being loaded, by calling __dyn_tls_init through
         * a callback defined in tlsdyn.obj.  We can't rely on the OS
         * calling __dyn_tls_init with DLL_PROCESS_ATTACH because, on
         * Win2K3 and before, that call happens before the CRT is
         * initialized.
         */
        if (__dyn_tls_init_callback != NULL &&
            _IsNonwritableInCurrentImage((PBYTE)&__dyn_tls_init_callback))
        {
            __dyn_tls_init_callback(NULL, DLL_THREAD_ATTACH, NULL);
        }
#endif  /* CRTDLL */

То есть можно посмотреть tlsdyn.c и вместо нового TLS callback зарегистрировать поинтер ".CRT$XDU", который будет вызван из __dyn_tls_init (и кода выше).
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.