![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
проблемка с LsaGetLogonSessionData...
istok © (2010-09-27 23:40:00)нижеприведенная программка является демкой определения времени старта сессии юзера.
всё бы хорошо, но в одном случае оно работает некорректно:
если искомая сессия является консольной сессией на сервере (windows server 2003), то почему-то вместо sessionData.Session=0 LsaGetLogonSessionData пишет другой номер сессии..
итак, вот код:
const
WTS_CURRENT_SERVER_HANDLE = 0;
type
PTOKEN_USER = ^TOKEN_USER;
_TOKEN_USER = record
User: TSidAndAttributes;
end;
TOKEN_USER = _TOKEN_USER;
USHORT = word;
_LSA_UNICODE_STRING = record
Length: USHORT;
MaximumLength: USHORT;
Buffer: LPWSTR;
end;
LSA_UNICODE_STRING = _LSA_UNICODE_STRING;
PLuid = ^LUID;
_LUID = record
LowPart: DWORD;
HighPart: LongInt;
end;
LUID = _LUID;
_SECURITY_LOGON_TYPE = (
seltFiller0, seltFiller1,
Interactive,
Network,
Batch,
Service,
Proxy,
Unlock,
NetworkCleartext,
NewCredentials,
RemoteInteractive,
CachedInteractive,
CachedRemoteInteractive);
SECURITY_LOGON_TYPE = _SECURITY_LOGON_TYPE;
PSECURITY_LOGON_SESSION_DATA = ^SECURITY_LOGON_SESSION_DATA;
_SECURITY_LOGON_SESSION_DATA = record
Size: ULONG;
LogonId: LUID;
UserName: LSA_UNICODE_STRING;
LogonDomain: LSA_UNICODE_STRING;
AuthenticationPackage: LSA_UNICODE_STRING;
LogonType: SECURITY_LOGON_TYPE;
Session: ULONG;
Sid: PSID;
LogonTime: LARGE_INTEGER;
LogonServer: LSA_UNICODE_STRING;
DnsDomainName: LSA_UNICODE_STRING;
Upn: LSA_UNICODE_STRING;
end;
SECURITY_LOGON_SESSION_DATA = _SECURITY_LOGON_SESSION_DATA;
_WTS_INFO_CLASS = (
WTSInitialProgram,
WTSApplicationName,
WTSWorkingDirectory,
WTSOEMId,
WTSSessionId,
WTSUserName,
WTSWinStationName,
WTSDomainName,
WTSConnectState,
WTSClientBuildNumber,
WTSClientName,
WTSClientDirectory,
WTSClientProductId,
WTSClientHardwareId,
WTSClientAddress,
WTSClientDisplay,
WTSClientProtocolType);
WTS_INFO_CLASS = _WTS_INFO_CLASS;
_WTS_CONNECTSTATE_CLASS = (
WTSActive, // User logged on to WinStation
WTSConnected, // WinStation connected to client
WTSConnectQuery, // In the process of connecting to client
WTSShadow, // Shadowing another WinStation
WTSDisconnected, // WinStation logged on without client
WTSIdle, // Waiting for client to connect
WTSListen, // WinStation is listening for connection
WTSReset, // WinStation is being reset
WTSDown, // WinStation is down due to error
WTSInit); // WinStation in initialization
WTS_CONNECTSTATE_CLASS = _WTS_CONNECTSTATE_CLASS;
function LsaFreeReturnBuffer(Buffer: pointer): Integer; stdcall;
function WTSGetActiveConsoleSessionId: DWORD; external 'Kernel32.dll';
function LsaGetLogonSessionData(LogonId: PLUID;
var ppLogonSessionData: PSECURITY_LOGON_SESSION_DATA): LongInt; stdcall;
external 'Secur32.dll';
function LsaNtStatusToWinError(Status: cardinal): ULONG; stdcall;
external 'Advapi32.dll';
function LsaEnumerateLogonSessions(Count: PULONG; List: PLUID): LongInt;
stdcall; external 'Secur32.dll';
function WTSQuerySessionInformationA(hServer: THandle; SessionId: DWORD;
WTSInfoClass: WTS_INFO_CLASS; var pBuffer: Pointer;
var pBytesReturned: DWORD): BOOL; stdcall; external 'Wtsapi32.dll';
var
Form1: TForm1;
implementation
uses DateUtils;
{$R *.dfm}
function LSAUnicodeStringToStr(const lsaStr : LSA_UNICODE_STRING) : string;
var
len : Integer;
begin
len := lsaStr.Length div sizeof (WideChar);
SetLength (result, len);
WideCharToMultiByte (CP_ACP, 0, lsaStr.Buffer, len, PChar (result), len, Nil, Nil);
end;
function GMTToLocalTime(GMTTime: TDateTime): TDateTime;
var
GMTST: Windows.TSystemTime;
LocalST: Windows.TSystemTime;
begin
SysUtils.DateTimeToSystemTime(GMTTime, GMTST);
SysUtils.Win32Check(Windows.SystemTimeToTzSpecificLocalTime(nil, GMTST, LocalST));
Result := SysUtils.SystemTimeToDateTime(LocalST);
end;
function LsaFreeReturnBuffer; external 'secur32.dll' name 'LsaFreeReturnBuffer';
function GetUserLogonTime(ASessionId: Integer): TDateTime;
var
Count: cardinal;
List: PLUID;
sessionData: PSECURITY_LOGON_SESSION_DATA;
i1: integer;
SizeNeeded, SizeNeeded2: DWORD;
OwnerName, DomainName: PChar;
OwnerType: SID_NAME_USE;
pBuffer: Pointer;
pBytesreturned: DWord;
ft: TFileTime;
st: TSystemTime;
dt: TDateTime;
begin
result:= 0;
Form1.Memo1.Lines.Add('---- '+inttostr(ASessionId));
i1:= lsaNtStatusToWinError(LsaEnumerateLogonSessions(@Count, @List));
try
if i1 = 0 then
begin
i1:= -1;
if Count > 0 then
begin // Form1.Memo1.Lines.Add('Count > 0');
repeat
inc(i1);
LsaGetLogonSessionData(List, sessionData);
if ((sessionData.LogonType = Interactive) or (sessionData.LogonType = RemoteInteractive)) and (sessionData.Session = ASessionId) then
Form1.Memo1.Lines.Add('found');
ft.dwLowDateTime := sessionData.LogonTime.LowPart;
ft.dwHighDateTime := sessionData.LogonTime.HighPart;
FileTimeToSystemTime(ft, st);
dt := EncodeDateTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
dt := GMTToLocalTime(dt);
result := dt;
Form1.Memo1.Lines.Add(format('i1=%d, user = %s, Count = %d, sessionData.LogonType=%d, sessionData.Session=%d, time = %s',
[i1, LSAUnicodeStringToStr(sessionData.UserName), Count, integer(sessionData.LogonType), sessionData.Session,
datetimetostr(result)]));
inc(List);
try
LSAFreeReturnBuffer(sessionData);
except
end;
until (i1 = Count-1) {or (result <> 0)};
end;
end;
finally
LSAFreeReturnBuffer(List);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ppLogonSessionData: PSECURITY_LOGON_SESSION_DATA;
c: ULONG;
l: PLUID;
begin
memo1.lines.add('GetCurrentSessionID = '+inttostr(GetCurrentSessionID));
memo1.lines.add(datetimetostr(GetUserLogonTime(GetCurrentSessionID)));
end;
han_malign (2010-09-29 13:36:00) [1]
> Значит, надо сказать Соломону
MSDN - Август 2006
Terminal Services: WTSQuerySessionInformation
...
Windows Server 2003 and Windows XP: Session zero might not be attached to the physical console. This is because session zero can be attached to a remote session.Additionally, fast user switching is implemented using Terminal Services sessions. The first user to log on uses session zero, the next user to log on uses session one, and so on. To determine if your application is running on the physical console, call the WTSGetActiveConsoleSessionId function as follows:
(CurrentSessionId == WTSGetActiveConsoleSessionId ())
Windows 2000Server and Windows 2000 Professional: Session zero will be attached only to the physical console.
А начиная с Vista - нулевой сессии наглухо обломали доступ к физической консоли... В том числе, кажется, и разные хитрые манипуляции с модификацией жетона, олицетворением и т.п. ...
Игорь Шевченко (2010-09-29 13:11:00) [2]han_malign (29.09.10 12:26) [8]
Значит, надо сказать Соломону, чтобы исправил опечатку. Цитата оттуда, из "Внутреннего устройства Windows"
han_malign (2010-09-29 12:26:00) [3]
> но почему-то её id возвращается как 3 а не 0.
The WTSGetActiveConsoleSessionIdfunction retrieves the Terminal Services sessioncurrently attached to the physical console. The physical consoleis the monitor, keyboard, and mouse. Note that it is not necessary that Terminal Services be running for this function to succeed.
> Удаленная сессия не может быть нулевой.
> "Первый сеанс входа на физической консоли компьютера считается нулевой сессией"
MSDN: Terminal Services Sessions
The console session on the Terminal Server is assigned the session ID 0.
- где тут physical?
KB: Q278845 ( http://support.microsoft.com/kb/278845)
В Windows Server 2003 при использовании служб терминалов вы можете подключаться к сеансу консоли (сеанс 0) и одновременно открывать параллельный сеанс (если вы подключаетесь из сеанса не на консоли). Эта дополнительная функция позволит удаленно выполнять вход на сервер Windows Server 2003, на котором запущена служба терминалов, и подключаться к сеансу 0, как если бы вы физически находились за консолью компьютера. Этот сеанс можно также запускать параллельно, чтобы удаленный и локальный пользователи могли работать в одном сеансе.
Eraser (2010-09-29 02:25:00) [4]> [5] istok (28.09.10 07:48)
ну значит 0, а в чем проблема то не понятно?
Anatoly Podgoretsky (2010-09-28 08:52:00) [5]Кто же будет читать эту портянку?
istok (2010-09-28 07:48:00) [6]а как быть с тем, что вот эта функция возвращает 0 ? и в диспетчере задач в юзерах код сеанса тоже 0.
function GetCurrentSessionID: Integer;
// Getting the session id from the current process
type
TProcessIdToSessionId = function(dwProcessId: DWORD; pSessionId: DWORD): BOOL; stdcall;
var
ProcessIdToSessionId: TProcessIdToSessionId;
hWTSapi32dll: THandle;
Lib : THandle;
pSessionId : DWord;
begin
Result := 0;
Lib := GetModuleHandle('kernel32');
if Lib <> 0 then
begin
ProcessIdToSessionId := GetProcAddress(Lib, 'ProcessIdToSessionId');
if Assigned(ProcessIdToSessionId) then
begin
ProcessIdToSessionId(GetCurrentProcessId(), DWORD(@pSessionId));
Result:= pSessionId;
end;
end;
end;
Eraser (2010-09-28 00:23:00) [7]> [3] Игорь Шевченко © (28.09.10 00:11)
> Удаленная сессия не может быть нулевой.
Еще как может.
Игорь Шевченко (2010-09-28 00:11:00) [8]Удаленная сессия не может быть нулевой.
"Первый сеанс входа на физической консоли компьютера считается нулевой сессией"
istok (2010-09-27 23:54:00) [9]поправка: ровно такая же проблема воспроизвелась с консольной сессией на другом сервере. с remote сессиями проблем нет.
в консольную сессию вхожу через mstsc.exe -admin из win7 (или /console из 2003ей) - может в этом дело? т.е. сессия консольная (нулевая), но удалённая..
istok (2010-09-27 23:40:00) [10]результат выполнения:
GetCurrentSessionID = 0
---- 0
i1=0, user = АНОНИМНЫЙ ВХОД, Count = 10, sessionData.LogonType=3, sessionData.Session=0, time = 23.09.2010 9:40:45
i1=1, user = NETWORK SERVICE, Count = 10, sessionData.LogonType=5, sessionData.Session=0, time = 23.09.2010 9:40:08
i1=2, user = ademko, Count = 10, sessionData.LogonType=10, sessionData.Session=3, time = 27.09.2010 23:20:03
i1=3, user = ademko, Count = 10, sessionData.LogonType=10, sessionData.Session=5, time = 27.09.2010 12:47:40
i1=4, user = ademko, Count = 10, sessionData.LogonType=10, sessionData.Session=7, time = 24.09.2010 17:06:02
i1=5, user = ademko, Count = 10, sessionData.LogonType=10, sessionData.Session=2, time = 23.09.2010 11:51:39
i1=6, user = ashestakov, Count = 10, sessionData.LogonType=10, sessionData.Session=1, time = 23.09.2010 9:41:44
i1=7, user = LOCAL SERVICE, Count = 10, sessionData.LogonType=5, sessionData.Session=5, time = 23.09.2010 9:40:08
i1=8, user = , Count = 10, sessionData.LogonType=0, sessionData.Session=0, time = 23.09.2010 9:40:08
i1=9, user = BELG-STUDENT$, Count = 10, sessionData.LogonType=0, sessionData.Session=0, time = 23.09.2010 9:40:08
23.09.2010 9:40:08
выделенная сессия является искомой, но почему-то её id возвращается как 3 а не 0.
вопрос - почему???
в других системах такая проблема пока больше не воспроизводилась.