PDA

Просмотр полной версии : Текущий вход в систему



Absurd
26.02.2004, 13:30
А как процесс может определить, под каким логином он запущен?

Eugie
26.02.2004, 18:35
Например, так


#include <windows.h>
#include <lmcons.h>

TCHAR name[UNLEN+1];
DWORD size = sizeof(name);

GetUserName(
name, // name buffer
&size // size of name buffer
);

Absurd
27.02.2004, 12:19
Я не правильно сформулировал вопрос...
Процесс запускается шедюлером под одним и тем же логином, с одними и теми же привилегиями.
Надо определить, кто на данный момент залогинен локально, и залогинен ли кто-нибудь.

Andy
27.02.2004, 14:45
Процесс запускается шедюлером под одним и тем же логином, с одними и теми же привилегиями.
Надо определить, кто на данный момент залогинен локально, и залогинен ли кто-нибудь.
Ну дык ведь подсказали же - юзай API GetUserName/GetUserNameEx :-)

Absurd
27.02.2004, 16:32
Ну дык ведь подсказали же - юзай API GetUserName/GetUserNameEx :-)

Если в шедулере стоит, что процесс запускается от пользователя "Администратор" , то функция GetUserName() будет всегда возвращать "Администратор", даже если в момент запуска за компьютером залогинен и сидит , например, ВасяПупкин. А помощью GetUserNameEx() я получу что-то типа OurSys\Администратор (в различных форматах) что тоже не годится. Мне надо определить имя залогиненного пользователя, а не пользователя, от которого запускается процесс.

Eugie
29.02.2004, 23:44
Тогда используй функцию NetWkstaUserGetInfo. Она возвращает информацию именно о текущем залогиненном пользователе, см. пример:



#include <windows.h>
#include <lm.h>
#include <iostream>

using namespace std;

int wmain(void)
{
LPWKSTA_USER_INFO_1 pBuf = NULL;

if (NetWkstaUserGetInfo(NULL, 1, (LPBYTE *)&pBuf) == NERR_Success)
{
wcout << L"User:\t" << (LPCWSTR) pBuf->wkui1_username << endl;
wcout << L"Domain:\t" << (LPCWSTR) pBuf->wkui1_logon_domain << endl;
wcout << L"Other Domains:\t" << (LPCWSTR) pBuf->wkui1_oth_domains << endl;
wcout << L"Logon Server:\t" << (LPCWSTR) pBuf->wkui1_logon_server << endl;
NetApiBufferFree(pBuf);
}

return 0;
}

Absurd
02.03.2004, 11:25
Тогда используй функцию NetWkstaUserGetInfo. Она возвращает информацию именно о текущем залогиненном пользователе, см. пример:
Опять немного не то... надо определить, какому пользователю принадлежит десктоп, и принадлежит ли он кому-нубудь.
Более конкретно, процессу 'yyy' надо знать, может ли процесс, запущенный от пользователя 'xxx', рисовать чего-нибудь на экране. Процесс 'yyy' запускается через шедулер от пользователя 'xxx'.

Eugie
03.03.2004, 14:11
Опять немного не то... надо определить, какому пользователю принадлежит десктоп, и принадлежит ли он кому-нубудь.
Более конкретно, процессу 'yyy' надо знать, может ли процесс, запущенный от пользователя 'xxx', рисовать чего-нибудь на экране. Процесс 'yyy' запускается через шедулер от пользователя 'xxx'.


Absurd, вопрос несколько отклонился от первоначального, однако :)

В WinNT/2000/XP есть специальные объекты для безопасного разделения доступа к системным ресурсам процессов, запущенных под разными логинами (в основном, сервисов): window stations
(терминалы) и desktops (рабочие столы). В рамках ОС могут существовать одновременно несколько терминалов, но только один из них - интерактивный - является видимым и именно с ним
взаимодействует пользователь. У каждого терминала может быть одновременно несколько десктопов, но
только один из них - активный - является видимым и служит для взаимодействия с пользователем. При создании процесса ОС назначает ему терминал, при этом сам процесс также может переназначить себе терминал. По умолчанию, доступ к активному десктопу интерактивного терминала получают только процессы, запущенные под логином текущего пользователя и сервисы под учетной записью LocalSystem. Процессам, запущенным под другими логинами, по умолчанию назначаются неинтерактивные терминалы, но при выполнении некоторых условий они также могут получит доступ к интерактивному.

Теперь от теории к практике. Task Scheduler как раз поступает в соответствии с умолчаниями: если процесс запускается под текущим логоном, ему назначается интерактивный терминал, а если под другим логоном - неинтерактивный. Поэтому в простейшем случае, если сам процесс не переназначил себе терминал и десктоп, достаточно узнать логин, под которым он запущен. В противном случае нужно непосредственно получать текущий десктоп в контексте интересующего процесса и сравнивать с десктопом интерактивного процесса.

К сожалению, простого способа получить десктоп/терминал нетекущего процесса WinAPI не предоставляет. Я могу предложить такие варианты: создать тред в контексте интересующего процесса, 1) и уже для нее использовать GetThreadDesktop, 2) либо в ThreadFunc вызывать GetProcessWindowStation.

Absurd
03.03.2004, 18:17
А как узнать - тот терминал, который мне предоставила система, - интерактивен или нет?
Чего - то я там не нашел ничего вроде GetWindowStationInfo()/GetWindowStationStatus() ...

Eugie
03.03.2004, 18:46
Так я же не обещал, что будет легко :)

На самом деле, в том и проблема, что нет в API функции, которая выдает терминал для произвольного процесса - есть только GetProcessWindowStation, но она работает только для процесса, в контексте которого вызвана. Поэтому я не знаю/вижу другого способа, кроме как создать тред в контексте нужного процесса (CreateRemoteThread) и уже либо в нем вызывать GetProcessWindowStation, либо юзать для него GetThreadDesktop. Будет ли так работать - ??? Попробуй ;)

Absurd
04.03.2004, 00:35
То есть надо инжектнуть свой код внутрь процесса, гарантированно подключенного к активному терминалу, получить его хендл терминала, и сравнить этот хендл со своим хендлом терминала?
Какой процесс годится на эту роль?

PS: Короче, если OpenWindowStation("winsta0",...) возвращает NULL, то порисовать видимо не удастся. Я остановился на этом.

Eugie
04.03.2004, 14:41
Absurd, все-таки для какого процесса тебе нужно узнать терминал?

Если для своего (возможно, запущенного под чужим логином), то это просто:



HWINSTA hWinSta;
TCHAR name[100];
DWORD dwNeededSize;

hWinSta = GetProcessWindowStation();
if (GetUserObjectInformation(
hWinSta, // handle to object
UOI_NAME, // type of information to retrieve
(PVOID)name, // information buffer
sizeof(name), // size of the buffer
&dwNeededSize // receives required buffer size
))
{
cout << "Current process window station name:\t" << name << endl;

// Note: "winsta0" - standard name for an interactive window station

if (lstrcmpi(name, "winsta0") == 0)
cout << "Current process window station is interactive" << endl;
else
cout << "Current process window station is not interactive" << endl;
}


А вот для произвольного процесса в системе все сложнее...

Насчет того, какой процесс гарантированно выполняется на интерактивном терминале - любой, запущенный залогиненным в данный момент пользователем, либо сервис, запущенный под локальным системным аккаунтом с флагом SERVICE_INTERACTIVE_PROCESS.

Absurd
04.03.2004, 15:42
Спасибо, именно это (100%) мне и надо.