Текущий вход в систему

Общие вопросы, не зависящие от языка реализации.

Модераторы: Duncon, Eugie, Romeo, Hawk

Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

26 фев 2004, 13:30

А как процесс может определить, под каким логином он запущен?
Eugie
Сообщения: 707
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

26 фев 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
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

27 фев 2004, 12:19

Я не правильно сформулировал вопрос...
Процесс запускается шедюлером под одним и тем же логином, с одними и теми же привилегиями.
Надо определить, кто на данный момент залогинен локально, и залогинен ли кто-нибудь.
Andy
Сообщения: 238
Зарегистрирован: 17 фев 2004, 08:15
Откуда: Минск

27 фев 2004, 14:45

Процесс запускается шедюлером под одним и тем же логином, с одними и теми же привилегиями.
Надо определить, кто на данный момент залогинен локально, и залогинен ли кто-нибудь.
Ну дык ведь подсказали же - юзай API GetUserName/GetUserNameEx :-)
Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

27 фев 2004, 16:32

Andy писал(а): Ну дык ведь подсказали же - юзай API GetUserName/GetUserNameEx :-)
Если в шедулере стоит, что процесс запускается от пользователя "Администратор" , то функция GetUserName() будет всегда возвращать "Администратор", даже если в момент запуска за компьютером залогинен и сидит , например, ВасяПупкин. А помощью GetUserNameEx() я получу что-то типа OurSys\Администратор (в различных форматах) что тоже не годится. Мне надо определить имя залогиненного пользователя, а не пользователя, от которого запускается процесс.
Eugie
Сообщения: 707
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

29 фев 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
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

02 мар 2004, 11:25

Тогда используй функцию NetWkstaUserGetInfo. Она возвращает информацию именно о текущем залогиненном пользователе, см. пример:
Опять немного не то... надо определить, какому пользователю принадлежит десктоп, и принадлежит ли он кому-нубудь.
Более конкретно, процессу 'yyy' надо знать, может ли процесс, запущенный от пользователя 'xxx', рисовать чего-нибудь на экране. Процесс 'yyy' запускается через шедулер от пользователя 'xxx'.
Eugie
Сообщения: 707
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

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
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

03 мар 2004, 18:17

А как узнать - тот терминал, который мне предоставила система, - интерактивен или нет?
Чего - то я там не нашел ничего вроде GetWindowStationInfo()/GetWindowStationStatus() ...
Eugie
Сообщения: 707
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

03 мар 2004, 18:46

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

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