У меня одна проблема, которая случилась однажды, и я до сих пор не знаю, как ее исправить.У меня есть служба Windows, когда служба запускается, она сначала должна олицетворять вошедшего в систему пользователя (активного пользователя), чтобы загрузить некоторые пути и настройки, которые сохраняются в папке данных приложения пользователя.Код, который я использую, прекрасно работает каждый раз, когда новый пользователь входит в Windows, за исключением одного раза, когда служба неправильно выдавала себя за себя и выдавала себя за системный сеанс вместо actie.Как я уже сказал, это произошло только один раз, но я не могу точно сказать, почему.
Вот как я проверяю, что такое активный сеанс и как выполняется олицетворение:
сначала, когда служба обнаруживаетсобытие входа в систему запрашивает идентификатор активной сессии, вызывая
WTSGetActiveConsoleSessionId();
, затем проверяет, активен ли сеанс (подключен), вызывая WTSQuerySessionInformation следующим образом:
WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;
DWORD bytes_returned = 0;
if (::WTSQuerySessionInformation(
WTS_CURRENT_SERVER_HANDLE,
session_id,
WTSConnectState,
reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
&bytes_returned))
{
ASSERT(bytes_returned == sizeof(*ptr_wts_connect_state));
wts_connect_state = *ptr_wts_connect_state;
::WTSFreeMemory(ptr_wts_connect_state);
return (WTSActive == wts_connect_state);
}
, где session_id - этоИдентификатор сеанса, возвращаемый WTSGetActiveConsoleSessionId ().
Затем я запрашиваю токен пользователя, используя WTSQueryUserToken
Затем, если это успешно, служба вызывает GetTokenInformation
следующим образом:
DWORD neededSize = 0;
HANDLE *realToken = new HANDLE;
if(GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize))
{
CloseHandle(hImpersonationToken);
hImpersonationToken = *realToken;
}
где hImpersonationToken - токен, полученный из GetTokenInformation
. И если все вышеперечисленное завершается успешно, он вызывает
DuplicateTokenEx( hImpersonationToken,
0,
NULL,
SecurityImpersonation,
TokenPrimary,
phUserToken );
CloseHandle( hImpersonationToken );
и, если это удается, то подражает извлеченному токену
ImpersonateLoggedOnUser(phUserToken);
Мой сервис записывает в файл журнала и в соответствии с журналом все предыдущие вызовы, где все еще успешно, после олицетворения служба загрузила системупрофиль вместо пользователя.
Теперь эта проблема произошла однажды, когда я перезапустил свой компьютер, но я даже не воспроизводил его снова, и я пытался в течение нескольких недель.
Яне уверен, насколько возможно, чтобы сессия профиля системы была активной сессией.Я просто хочу знать, делаю ли я что-то не так, не уверен, что использую неправильный класс информации, когда запрашиваю информацию о сеансе или что-то в этом роде.
Также хочу узнать, возможно ли этоопределить, действительно ли запрашиваемый сеанс является системным сеансом, прежде чем выдавать себя за возвращенный токен, чтобы можно было повторить олицетворение?
Как я уже говорил, все упомянутые вызовы проверяют свои объекты возврата и коды перед переходом к следующемушаг, чтобы не было никаких ошибок от звонков, поскольку это не должно продолжаться с олицетворением, все же это сделало: (
Был бы признателен за любую возможную помощь ... спасибо.