Вопрос № 70949: Добрый вечер, уважаемые эксперты.
Хотел задать вопрос вот по какой проблеме. Я захотел написать программу, которая загружалась бы вместе с Виндой (ХР), но так, чтобы пользователь об этом не знал. Знаю, что задача стандартная, но всё-таки как реши...
Вопрос № 70.949
Добрый вечер, уважаемые эксперты.
Хотел задать вопрос вот по какой проблеме. Я захотел написать программу, которая загружалась бы вместе с Виндой (ХР), но так, чтобы пользователь об этом не знал. Знаю, что задача стандартная, но всё-таки как решил сделать эту реализацию я. Как именно?
Я решил создать библиотеку, которая будет загружаться вместе с виндой. Плюс этого - это то, что по крайней мере в autorun и taskmgr её не будет. Я прикинул, что в принципе меня это устраивает. А для автом. загрузки я решил использовать средства winlogon.exe, а именно через NOTIFY. В реестре прописывается имя библиотеки и указываются события по которым её экспортируемая функция вызывается (HLMSOFTWAREMicrosoftWindows NTCurrentVersionWinlogonNotify)
Мне необходимо, чтобы моя программа запускалась один раз, точнее делала некую "вещь", и всё. Для проверки на "единичность" запуска я решил использовать простой АТОМ, который регистрирую глобальным и далее просто проверяю его на наличие.
После того, как winlogon подключает библиотеку, то она автоматически считается используемой, и как выгрузить я не знаю, то есть её ни стриеть - ничего из ЭТИХ виндов не сделать. Для этого я проверяю реестр на некий ключ, который можно создать вручную, и если программа находит этот ключ и сравнивает его параметр (CanLoad == No), то в функции DllMain я просто возвращаю false, и тем самым своего рода запрещаю загрузку библиотеки: см. 1.
Сама функция CanLoad() организована след образом: см. 2.
Одна из проблем состоит в том, что сама по себе библиотека на загруженных виндах работает так как надо то есть когда надо - грузиться, или нет, в зависимости от параметра. То есть реестр "опрашивается" корректно, но в момент запуска winlogon у меня возникает искл. ситуация в момент открытия параметра CanLoad с помощью функции RegQueryValueEx. То есть вроде "по логу" сам ключ в software я открываю удачно. RegQueryValue - устаревшая функция, а RegGetValue - вообще для других виндов. Такое ощущение,
что то ли реестр не дозагружен, то ли ещё что-нибудь. Я не понимаю почему мой ключ не считывается, ведь вроде бы я не пишу в него а просто опрашиваю, то есть безопасность не нарушается.
Возникает ещё один вопрос, когда я в Notify прописываю фразы типа:
Startup PseudoStartupEvent
Shutdown PseudoShutdownEvent
Logon PseudoLogonEvent
Logoff PseudoLogoffEvent
То есть я задаю экспортируемые функции, вида:
extern "C" void __declspec(dllexport) PseudoStartupEvent();
в качестве реакций на соотв. события.
Когда библиотека загружается, ей в DllMain посылаются след. параметры:
DLL_PROCESS_ATTACH и DLL_PROCESS_DETACH (когда отключается)
в Winlogon ещё добавляется КУЧА DLL_THREAD_ATTACH и ...DETACH. И что самое интересное, я не могу отследить вызов моих функций, я сначала думал что они не вызываются (хотя строка вида rundll32.exe pseudodll.dll,PseudoStartupEvent работает и происходит вызов DllMain, то есть библиотека загружается, затем запускается функция, и потом она выгружается), но когда я случайно сделал ошибку в коде экспортируемой функции на startup, то чуть не попротил весь Windows, так как winlogon.exe не мог понят почему моя библиотека
выкидывает искл. ситуацию, и он не знал как её обработать о чем писал мне большими буквами, вплоть до синего экрана :)
Получается след. картина, что winlogon как-то либо подгружает библиоеку и не выгружает никогда, но тогда я не вижу в своём логе ровным счётом ничего, или же он вызывает соотв. функцию в тихую.
Могу конечно прислать код программы целиком, но там используется много лишних для вопроса механизмов, своего рода копирования библиотеки, регистрирования в системе и т.д.
Надеюсь после всей той повести, что я написал вам, вы уделите своё время на ответ, буду рад хотя бы некоторым тонкостям по соотв. рода проблеме или ссылкам. Сам лог - представляет собой перенаправленный поток из stdout в файл с помощью функции:
FILE* hLog = NULL; // глобальная
err = _wfreopen_s(&hLog, logPath, _TEXT("a"), stdout);
только вот при вызове функций-событий, это хэндл, теоретически равен нулю, так как я ничего не получаю в файле, это раз, и если я не проверяю его на ноль, то срабатывает ошибка...
Среда написания в данном вопросе не особо важна, сам я пишу на MSVS 2005, с использованием чистого winapi, так как другие классы мне особо не нужны, задач таких нет.
Спасибо большое, заранее...
Приложение:
Отправлен: 14.01.2007, 22:51
Вопрос задал: Vest (статус: 3-ий класс)
Всего ответов: 2 Мини-форум вопроса >>> (сообщений: 0)
Отвечает: Vaga
Здравствуйте, Vest!
а не проще ли воспользоваться веткой реестра для запуска приложения
HKLMSoftwareMicrosoftWindowsCurrentVersionRun ?
--------- Ошибка становится ошибкой, когда рождается как истина. Станислав Ежи Лец
Ответ отправил: Vaga (статус: 6-ой класс)
Ответ отправлен: 15.01.2007, 04:07 Оценка за ответ: 3 Комментарий оценки: Извини конечно за тройку, спасибо за ответ, но это всё-таки не тот ответ, который я ожидал получить. Но всё-равно спасибо.
Отвечает: Решетник Д
Здравствуйте, Vest!
ИМХО Вы выбрали далеко не самый лучший вариант для автоматической загрузки ДЛЛ.
Но решать Вам. Предложенный вариант Vaga получше да и полегче. В крайнем случае можете скрывать процесс или инжектировать длл в процесс, в тот же winlogon. Я, например, инжектировал. Немного гемора, но длл работает на ВСЕХ ОС и ее никто не может убить (если ОЧЕНЬ не постараться).. Но у каждого свои цели.
Попробуйте сервис. Если такие варианты вам не подходят, кидайте код в студию...
К слову, насколько я знаю
"Получается след. картина, что winlogon как-то либо подгружает библиоеку и не выгружает никогд"
ДЛЛ сами не выгружаются. Может конечно в winlogon свой механизм и все автоматизировано...
Но для каждого LoadLibrary должен быть свой FreeLibrary.
И еще одно. Может у Вас такого не случится. Но когда длл работает от winlogon, то она работает на другом рабочем столе. То есть, вы не сможете обратиться ни к одному из окон....
--------- Жизнь коротка, чтобы писать на ассемблере
Ответ отправил: Решетник Д (статус: 10-ый класс)
Ответ отправлен: 15.01.2007, 12:09 Оценка за ответ: 4 Комментарий оценки: Спасибо за ответ, теперь появилась новая проблема - "инжектирования". Признаюсь это для меня ново. Ну а насчёт моего, извините, гемора, то это же способ изучения всей гаммы Windows программирования :)