//Записываем строку лога в файл
if (!WriteFile(hFile, buf, wcslen(buf) * sizeof(WCHAR),
&dwWritten, NULL))
::MessageBeep(MB_ICONASTERISK);
//Заканчиваем работу с файлом
CloseHandle(hFile);
}Теперь осталось написать функции-обработчики событий. Ради удобства назовем их так же, как показано в таблице 1.
extern "C" void __stdcall
WLEventLogon(PWLX_NOTIFICATION_INFO pInfo)
{
WriteLog(L"user logon", pInfo);
}
extern "C" void __stdcall
WLEventLogoff(PWLX_NOTIFICATION_INFO pInfo)
{
WriteLog(L"user logoff", pInfo);
}
extern "C" void __stdcall
WLEventStartup(PWLX_NOTIFICATION_INFO pInfo)
{
WriteLog(L"system startup", pInfo);
}
extern "C" void __stdcall
WLEventShutdown(PWLX_NOTIFICATION_INFO pInfo)
{
WriteLog(L"system shutdown", pInfo);
}
extern "C" void __stdcall
WLEventStartScreenSaver(PWLX_NOTIFICATION_INFO pInfo)
{
WriteLog(L"screen saver started", pInfo);
}
extern "C" void __stdcall
WLEventStopScreenSaver(PWLX_NOTIFICATION_INFO pInfo)
{
WriteLog(L"screen saver stopped", pInfo);
}
extern "C" void __stdcall
WLEventLock(PWLX_NOTIFICATION_INFO pInfo)
{
WriteLog(L"Workstation locked", pInfo);
}
extern "C" void __stdcall
WLEventUnlock(PWLX_NOTIFICATION_INFO pInfo)
{
WriteLog(L"Workstation unlocked", pInfo);
}
extern "C" void __stdcall
WLEventStartShell(PWLX_NOTIFICATION_INFO pInfo)
{
WriteLog(L"User already loged on and network"
L" resouces are avaliable", pInfo);
}Теперь необходимо экспортировать эти функции для других приложений. Для этого создадим файл Notify.def и добавим его в проект. В единственной секции EXPORTS укажем экспортируемые функции
EXPORTS
WLEventLogon
WLEventLogoff
WLEventStartup
WLEventShutdown
WLEventStartScreenSaver
WLEventStopScreenSaver
WLEventLock
WLEventUnlock
WLEventStartShellПосле успешной компиляции необходимо подписаться на события Winlogon.
ПРЕДУПРЕЖДЕНИЕ
Необходимо помнить, что dll исполняется в адресном пространстве процесса, который ее вызывает. Если dll спровоцирует исключительную ситуацию, тогда, если не обработать ошибку, работа процесса будет прекращена. Процесс Winlogon.exe очень чувствителен к таким вещам. При возникновении ошибки он покажет синий экран смерти, а в случае наличия соответствующих настроек перегрузит систему. Поэтому настойчиво рекомендуется тестировать программу на виртуальном компьютере.Для этого зайдем в реестр и отыщем ключ:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify
Создадим в нем подключ MyNotify и значения, как показано на рисунке ниже.
Рисунок 1.
Для удобства поместим файл Notify.dll по указанному пути. После перезагрузки системы приложение начнет создавать логи.
ПРИМЕЧАНИЕ
Если логи не создаются, проверьте, не используется ли Notify.dll другим процессом (если файл не удается переименовать значит, кто-то его использует). Если Notify.dll используется, а логов нет, скорее всего, неправильно задано одно из значений в названиях функций-обработчиков, или такие функции не экспортируются динамической библиотекой. Если Notify.dll не используется, проверьте, правильно ли задан ключ DllName с названием библиотеки. Возможно, библиотека не зарегистрирована в системе, или не может быть загружена.Заключение
Winlogon notification package может пригодиться в совершенно неожиданных местах. Например, если из системной службы необходимо получить имена пользователей, работающих в системе. Все, что нужно это написать и зарегистрировать в системе dll, которая по запросу передаст данные в службу (или сама будет передавать эти данные в ответ на некоторые нужные события).
Надеюсь, что данная статья расширит знания читателя об интерфейсах Winlogon, а также поможет использовать полученные знания на практике.
Список литературы
Для подготовки данной работы были использованы материалы с сайта http://www.rsdn.ru/