Конференция "WinAPI" » AppInit_Dll - механизм работы.
 
  • Riply © (04.07.08 23:41) [0]
    Здравствуйте !
    Подскажите, пожалуйста, каким образом подгружаются библиотеки из AppInit_Dll ?
    Интересует не как подгрузить с помощью ключа, а сам механизм.
    Например, один из вариантов:
    Создается Suspended процесс.
    В нем создается нить, загружающая Dll-ку.
    Процесс будится.
    Но это домыслы, а как все реализовано "на самом деле" ?
  • Игорь Шевченко © (05.07.08 13:38) [1]

    > а сам механизм.


    Сам механизм прост - LoadLibrary.

    Каждый процесс, загружающий какие-либо DLL, вызывает при этом DllEntryPoint от этих DLL, надеюсь, этот механизм не надо пояснять ?

    В процессе выполнения DllEntryPoint выполняются какие-либо действия. В частности, одним из действий в DllEntryPoint у user32.dll является сканирование ключа реестра AppInit_Dll и загрузка всех перечисленных в нем Dll в память процесса (и вызов их инициализации).

    Если приложение не использует user32.dll, то никакие AppInit_Dll в его адресное пространство не загрузятся (например, в SMSS.EXE ничего не загружается, а вот в WinLogon.EXE - загружается)

    На самом деле все немного хитрее происходит, но суть примерно такая.
  • Riply © (05.07.08 14:54) [2]
    > [1] Игорь Шевченко ©   (05.07.08 13:38)

    Спасибо.
  • Игорь Шевченко © (05.07.08 17:05) [3]

    > На самом деле все немного хитрее происходит


    На самом деле в этом еще участвует процесс csrss.exe, к которому user32.dll обращается в процессе инициализации.
  • Riply © (05.07.08 17:28) [4]
    > [3] Игорь Шевченко ©   (05.07.08 17:05)
    > На самом деле в этом еще участвует процесс csrss.exe, к которому user32.dll обращается в процессе инициализации.

    А он зачем понадобился ?
    Вроде в [1] Игорь Шевченко © все и без него неплохо получается.
    Или там какая-нибудь таблица Handl`ов ?
  • Игорь Шевченко © (05.07.08 20:46) [5]
    Riply ©   (05.07.08 17:28) [4]

    Процедурам в user32.dll нужен адрес разделяемой области Win32 (в частности, там находятся все-все Handles подсистемы Win32, относящиеся к окнам, меню, хукам, все, кроме GDI - у GDI своя таблица). Адрес этой разделяемой области формирует (для каждого процесса) ядерная часть подсистемы Win32 - win32k.sys, для того, чтобы она сформировала, ее надо вызывать. Вызывается она внутри CSRSS, а DllEntryPoint от user32 соединяется с процессом csrss, запрашивая инициализацию всего-всего.
    Зачем так сделано - очевидно, к моменту загрузки AppInit_DLL структуры процесса относящиеся к подсистеме Win32, должны быть должным образом проинциализированы, иначе будет невозможно даже зарегистрировать оконный класс (чем по логике MS должны заниматься DLL, перечисленные в AppInit_DLL).
  • Сергей М. © (05.07.08 21:11) [6]

    > библиотеки из AppInit_Dll


    Из какой такой дыры они выскакивают ? Что еще за AppInit_Dll ?)
  • Riply © (05.07.08 21:36) [7]
    > [6] Сергей М. ©   (05.07.08 21:11)
    > Из какой такой дыры они выскакивают ? Что еще за AppInit_Dll ?)

    Sorry. Допустила ошибку (писала по памяти).
    Првавильное имя: AppInit_DLLs
    Это из HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
  • Игорь Шевченко © (05.07.08 21:37) [8]

    > Из какой такой дыры они выскакивают ? Что еще за AppInit_Dll
    > ?)


    да ладно тебе буквоедствовать :)
  • Игорь Шевченко © (05.07.08 21:38) [9]
    Кстати, на самом деле процесс еще более хитрый - точка входа в user32.dll, которая загружает эти DLL, вызывается для каждого потока. Она так и называется ClientThreadSetup
  • Riply © (05.07.08 21:53) [10]
    > [5] Игорь Шевченко ©   (05.07.08 20:46)
    > [9] Игорь Шевченко ©   (05.07.08 21:38)
    > Кстати, на самом деле процесс еще более хитрый

    Оказывается, иногда, черт страшнее чем его малюют :)
    Спасибо.
  • Игорь Шевченко © (05.07.08 22:25) [11]
    Riply ©   (05.07.08 21:53) [10]

    На здоровье. Но у меня встречный вопрос - а с какой целью интересуетесь ?
  • Германн © (06.07.08 00:43) [12]

    > Но у меня встречный вопрос - а с какой целью интересуетесь
    > ?
    >

    :))))
  • Riply © (06.07.08 01:34) [13]
    > [11] Игорь Шевченко © (05.07.08 22:25)
    > Но у меня встречный вопрос - а с какой целью интересуетесь ?

    А у Вас все вопросы такие каверзные ? :)
    Ну да делать нечего, попробую ответить.
    Началось все с того, что мне понадобился класс(структура) в С++, который
    инициализируется "самым первым" и последним финализируется.
    Один из советов, данных мне, был, примерно, таким:
    "код инициализации поместить в DLL-ку, при компиляции указать на необходимость загрузки этой DLL первой
    не знаю как это реализовано в PE, но в Linux через DT_FLAGS=initfirst в секции .dynamic *.so файла
    думаю, в PE как-то аналогично"

    Осознав, что я ничерта в этом не понимаю, решила попробовать разобраться и полезла в дебри загрузки :)
    Т.е. понадобились ответы на следующие вопросы:
    Является ли этот путь тем, кем стоит заниматься ?
    Если да, то как это реализовать ?
    Какие ограничения при этом накладываются на нашу Dll-ку ?
    (Просто вспомнила, что загрузка через AppInit_DLLs накладывает на Dll серьезные ограничения,
    которые удалось обойти только через создание доп. Dll - загрузчика (она то и прописывается в AppInit_DLLs),
    которая только и делает, что при помощи QueueUserAPC загружает "настоящую" библиотеку).
    Ну а раз так, то не помешало бы понимать, что же там происходит "на самом деле".
    Вот так мы и скатились до такой жизни :)
  • Riply © (06.07.08 01:36) [14]
    > [12] Германн ©   (06.07.08 00:43)
    > :))))

    Не вижу ничего смешного :)))
  • Германн © (06.07.08 01:48) [15]

    > Riply ©   (06.07.08 01:36) [14]
    >
    > > [12] Германн ©   (06.07.08 00:43)
    > > :))))
    >
    > Не вижу ничего смешного :)))
    >

    Ну тогда :((((
    Увы нет смайлика, который в полной мере отображал бы чувства, возникающие при чтении твоих постов.
  • Riply © (06.07.08 01:53) [16]
    > [15] Германн ©   (06.07.08 01:48)
    > Ну тогда :((((

    Эт еще хуже :)
    Риторический вопрос: и куда делись ветки, где можно пофлудить ?
    Здесь боюсь - могут зарезать ветку раньше, чем я получу ответы :)
  • Германн © (06.07.08 02:39) [17]

    > Риторический вопрос: и куда делись ветки, где можно пофлудить
    > ?

    Так ни куда они не делись. Где они были, там и остались.
  • Riply © (06.07.08 02:43) [18]
    > [17] Германн ©   (06.07.08 02:39)
    > Так ни куда они не делись. Где они были, там и остались.

    А я уж который день (ночь) ищу и не могу найти.
    Везде, вроде, не флудят, а говорят "по теме".
    А то я бы с удовольствием подключилась :)
  • Германн © (06.07.08 03:03) [19]

    > Riply ©   (06.07.08 02:43) [18]
    >
    > > [17] Германн ©   (06.07.08 02:39)
    > > Так ни куда они не делись. Где они были, там и остались.
    >
    >
    > А я уж который день (ночь) ищу и не могу найти.
    > Везде, вроде, не флудят, а говорят "по теме".
    > А то я бы с удовольствием подключилась :)
    >

    Обратись ко мне на почту.
    Или вспомни  арифметику. :)
  • guav © (06.07.08 12:02) [20]
    Можно сказать, что все статически импортированные dll загрузятся до кода ехе, однако с порядком их загрузки сложнее. Так, в своей DllMain не рекомендуют вызывать код работы с реестром, потому что advapi32.dll может быть загружена и позже (здесь  http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx ).

    Теперь по сути. Для dll здесть http://support.microsoft.com/kb/94248 в Section 2 описана возможность объявить точку входа в dll не как DllMain, а как DllEntryPoint, при этом инициализация CRT и вызов конструкторов глобальных объектов будет делаться явным вызовом _CRT_INIT. Разумеется, можно что-то своё сделать до _CRT_INIT, не используя при этом CRT.
    ДУмаю что-то подобное возможно и для ехе.
  • guav © (06.07.08 12:06) [21]
    http://msdn.microsoft.com/en-us/library/f9t8842e(VS.71).aspx
    The function must be defined with the __stdcall calling convention. The parameters and return value must be defined as documented in the Win32 API for WinMain (for an .exe file) or DllEntryPoint (for a DLL). It is recommended that you let the linker set the entry point so that the C run-time library is initialized correctly, and C++ constructors for static objects are executed.
    Насколько я понял, можно не сделать то что recomended и инициализировать CRT явно.
  • Игорь Шевченко © (06.07.08 14:26) [22]

    > Началось все с того, что мне понадобился класс(структура)
    > в С++, который
    > инициализируется "самым первым" и последним финализируется.
    >


    AppInit_DLLs для этого не подходит
 
Конференция "WinAPI" » AppInit_Dll - механизм работы.
Есть новые Нет новых   [134434   +27][b:0][p:0.001]