AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi LsaEnumerateLogonSessions gibt nicht eingeloggte User in Liste aus
Thema durchsuchen
Ansicht
Themen-Optionen

LsaEnumerateLogonSessions gibt nicht eingeloggte User in Liste aus

Offene Frage von "virus82"
Ein Thema von virus82 · begonnen am 6. Jan 2012 · letzter Beitrag vom 9. Jan 2012
Antwort Antwort
virus82

Registriert seit: 29. Jun 2007
Ort: Leipzig
34 Beiträge
 
Delphi 2009 Professional
 
#1

LsaEnumerateLogonSessions gibt nicht eingeloggte User in Liste aus

  Alt 6. Jan 2012, 10:41
Hallo,

ich hab ein Problem mit LsaEnumerateLogonSessions. Ich hab hier das Forum schon durchwühlt und war froh, als ich Informationen gefunden habe, wie ich die eingeloggten User Sessions auflisten kann. Das habe ich dann mit Hilfe des Forums und der MSDN umgesetzt und vorerst auch keinen Fehler festgestellt.

Dann musste ich allerdings feststellen, das nicht immer das richtige Ergebniss ausgegeben wird. Und zwar immer dann wenn ein User (Benutzer1) sich anmeldet, abmeldet und ein anderer User (Benutzer2) sich anmeldet. Wenn Benutzer2 jetzt mein Programm ausführt, liefert mir LsaEnumerateLogonSessions auch noch Benutzer1 in der Liste mit.

Kann man mit LsaEnumerateLogonSessions auch herausbekommen welche User sich abgemeldet haben? Ich dachte es werden nur die angemeldeten User angezeigt.

Hier mein Code (in meinem Formular nutze ich AllocConsole um mit WriteLn die Infos ausgeben zu lassen:

Delphi-Quellcode:

uses
  Windows, SysUtils;

type
  PLuid = ^LUID;
  _LUID = record
    LowPart: DWORD;
    HighPart: LongInt;
  end;
  LUID = _LUID;

  USHORT = Word;

  _LSA_UNICODE_STRING = record
    Length: USHORT;
    MaximumLength: USHORT;
    Buffer: LPWSTR;
  end;
  LSA_UNICODE_STRING = _LSA_UNICODE_STRING;

  _SECURITY_LOGON_TYPE = (
    Interactive = 2,
    Network,
    Batch,
    Service,
    Proxy,
    Unlock,
    NetworkCleartext,
    NewCredentials,
    RemoteInteractive,
    CachedInteractive,
    CachedRemoteInteractive);
  SECURITY_LOGON_TYPE = _SECURITY_LOGON_TYPE;
  TSecurityLogonType = 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;
  TSecurityLogonSessionData = SECURITY_LOGON_SESSION_DATA;

function LsaNtStatusToWinError(Status: cardinal): ULONG; stdcall; external 'Advapi32.dll';
function LsaEnumerateLogonSessions(LogonSessionCount: PULONG; LogonSessionList: PLUID): LongInt; stdcall; external 'Secur32.dll';
function LsaGetLogonSessionData(LogonId: PLUID; var ppLogonSessionData: PSECURITY_LOGON_SESSION_DATA): ULONG; stdcall; external 'Secur32.dll';
function LsaFreeReturnBuffer(Buffer: Pointer): ULONG; stdcall; external 'Secur32.dll';

implementation

...


procedure TForm1.Button3Click(Sender: TObject);
var
   iRes: Integer;
   Count: Cardinal;
   List: PLUID;
   Test: LUID;
   SessionData: PSECURITY_LOGON_SESSION_DATA;
   i: Integer;
   tc64: Int64;
   ldt: TDateTime;
   SIDInfo: TSIDInfo;
begin
  // based on
  // http://www.delphipraxis.net/90606-den-aktiven-benutzer-bzw-status-des-benutzers-bekommen.html

  // get list of sessions
  iRes:= LsaNtStatusToWinError(LsaEnumerateLogonSessions(@Count, @List));
  // check result of list
  if (iRes = ERROR_SUCCESS) then
  begin
    // no error
    // check count of list
    if (Count > 0) then
    begin
      // min 1 session
      WriteLn(Format('Count: %d', [Count]));
      WriteLn('');
      // enumerate list
      for i := 0 to Count - 1 do
      begin
        // for each item in list get session data
        iRes := LsaNtStatusToWinError(LsaGetLogonSessionData(List, SessionData));
        // test, display item in list, also if result is not successfull
        Test := List^;
        Writeln(Format('Session %d: %u %u', [i, Test.LowPart, Test.HighPart]));
        // check result of sessiondata
        if (iRes = ERROR_SUCCESS) then
        begin
          // only interactive users
          if SessionData.LogonType in [Interactive] then
          begin
            // write infos
            WriteLn(Format(' LogonId: %d', [Int64(SessionData.LogonId)]));
            WriteLn(Format(' UserName: %s', [String(SessionData.UserName.Buffer)]));
            WriteLn(Format(' LogonDomain: %s', [String(SessionData.LogonDomain.Buffer)]));
            WriteLn(Format(' Session: %d', [SessionData.Session]));
            WriteLn(Format(' SID: %s %s', [SIDToName(SessionData.Sid), SIDToStrSID(SessionData.Sid)]));
            WriteLn(Format(' LogonServer: %s', [String(SessionData.LogonServer.Buffer)]));
            WriteLn(Format(' LogonType: %d', [Integer(SessionData.LogonType)]));
            tc64 := GetTickCount64;
            ldt := FileTimeToDateTime(SessionData.LogonTime);
            WriteLn(Format(' LogonTime: DateTime: %s Unix: %u', [DateTimeToStr(ldt), DateTimeToUnixTrunc(ldt)]));
            WriteLn(Format(' TickCount: ms: %u', [tc64]));
            // get sid info
            if GetSIDInfo(SessionData.Sid, SIDInfo) then
            begin
              // is user
              if (SIDInfo.SIDType = SidTypeUser) then
              begin
                // write sid infos
                WriteLn(Format(' SIDInfo.Name: %s', [SIDInfo.Name]));
                WriteLn(Format(' SIDInfo.ReferenceDomainName: %s', [SIDInfo.ReferenceDomainName]));
                WriteLn(Format(' SIDInfo.SIDType: %u', [Integer(SIDInfo.SIDType)]));
              end;
            end;
          end;
          // free sessiondata
          iRes := LsaNtStatusToWinError(LsaFreeReturnBuffer(SessionData));
          if (iRes <> ERROR_SUCCESS) then
          begin
            // error free sessiondata
            WriteLn(SysErrorMessage(iRes));
          end;
        end else
        begin
          // error sessiondata
          WriteLn(SysErrorMessage(iRes));
        end;
        // space
        WriteLn('');
        // inc list
        Inc(List);
      end;
    end else
    begin
      // no sessions found
      WriteLn('No Sessions');
    end;
    // free list
    iRes := LsaNtStatusToWinError(LsaFreeReturnBuffer(List));
    if (iRes <> ERROR_SUCCESS) then
    begin
      // error free list
      WriteLn(SysErrorMessage(iRes));
    end;
  end else
  begin
    // error list sessions
    WriteLn(SysErrorMessage(iRes));
  end;
end;
Im Anhang das Ergebnis der Console, wo beide User angezeigt werden. Ich möchte gern nur das Ergebnis aus dem TaskManager haben, der nur die angemeldeten User anzeigt.

Kann mir jemand helfen oder mir Erklären was da LsaEnumerateLogonSessions macht. Ich habe LsaEnumerateLogonSessions genommen, da ich mit LsaGetLogonSessionData auch die LogOn Zeit ermitteln kann. Jetzt müsste ich nur noch alle aktiven Sessions herausfiltern. Nur wie???

Nachvollziehen kann ich das unter WinXP SP3 und Win7 SP1 mit Delphi 2009.

Gruß, Marco.
Angehängte Grafiken
Dateityp: jpg console.JPG (52,0 KB, 29x aufgerufen)
Dateityp: jpg taskmgr.JPG (34,9 KB, 23x aufgerufen)
Marco

Geändert von virus82 ( 6. Jan 2012 um 11:30 Uhr)
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#2

AW: LsaEnumerateLogonSessions gibt nicht eingeloggte User in Liste aus

  Alt 6. Jan 2012, 19:00
Teste mal logonsessions.exe von Sysinternals.
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
virus82

Registriert seit: 29. Jun 2007
Ort: Leipzig
34 Beiträge
 
Delphi 2009 Professional
 
#3

AW: LsaEnumerateLogonSessions gibt nicht eingeloggte User in Liste aus

  Alt 6. Jan 2012, 19:28
Ok hab ich gemacht. Ist das gleiche Resultat.

Ich denke das LsaEnumerateLogonSessions für mich nicht die Richtige funktion ist. Ich möchte gern alle Sessions der zur Zeit angemeldeten Benutzer mit Namen und Uhrzeit des Logons ermittel. Und LsaEnumerateLogonSessions liefert mir leider auch Sessions, deren Benutzer schon längst abgemeldet sind.
Marco
  Mit Zitat antworten Zitat
ASM

Registriert seit: 15. Aug 2004
165 Beiträge
 
Delphi 7 Enterprise
 
#4

AW: LsaEnumerateLogonSessions gibt nicht eingeloggte User in Liste aus

  Alt 6. Jan 2012, 22:12
Ich möchte gern alle Sessions der zur Zeit angemeldeten Benutzer mit Namen und Uhrzeit des Logons ermittel. Und LsaEnumerateLogonSessions liefert mir leider auch Sessions, deren Benutzer schon längst abgemeldet sind.
Mit Hilfe der NetAPI Funktion NetWkstaUserEnum() geht es.
Hier noch ohne Uhrzeit des Logins; aber die lässt sich - etwas aufwändiger zwar - anders ermitteln:
Code:
type
  TWKSTA_USER_INFO_0 = record
    username: PWideChar;
  end;
  PTWKSTA_USER_INFO_0 = ^TWKSTA_USER_INFO_0;

function NetWkstaUserEnum(servername: PWideChar; level: DWORD; var bufptr: Pointer;
  prefmaxlen: DWORD; var entriesread: PDWord; var totalentries: PDWord;
  var resumehandle: PDWord): Longint;
  stdcall; external 'netapi32.dll' Name 'NetWkstaUserEnum';

function EnumNetUsers(Users: TStrings): TWKSTA_USER_INFO_0;
const
  STR_ERROR_ACCESS_DENIED = 'User does not have access to the requested information.';
  STR_ERROR_MORE_DATA = 'Specify a buffer large enough to receive all entries.';
  STR_ERROR_INVALID_LEVEL = 'Parameter "level" has been set invalid.';
var
  UI: PTWKSTA_USER_INFO_0;
  HostInfo: Pointer;
  ElTotal: PDWord;
  ElCount: PDWord;
  Resume: PDWord;
  Error: Longint;
  i: Integer;
begin
  Resume := 0;
  NetWkstaUserEnum(nil, 0, HostInfo, 0, ElCount, ElTotal, Resume);
  Error := NetWkstaUserEnum(nil, 0, HostInfo, 256 * Integer(ElTotal),
    ElCount, ElTotal, Resume);
  case Error of
    ERROR_ACCESS_DENIED: Result.UserName := STR_ERROR_ACCESS_DENIED;
    ERROR_MORE_DATA: Result.UserName := STR_ERROR_MORE_DATA;
    ERROR_INVALID_LEVEL: Result.UserName := STR_ERROR_INVALID_LEVEL;
  else
    if HostInfo <> nil then
    begin
      Result := TWKSTA_USER_INFO_0(HostInfo^);
      UI := PTWKSTA_USER_INFO_0(HostInfo);
      for i := 1 to DWord(ElCount) do
      begin
        Users.Add(UI^.username);
        inc(UI);
      end;
    end
    else
    begin
      Result.UserName := '<???>';
    end;
  end;
end;
Beispiel:
Code:
procedure TForm1.Button1Click(Sender: TObject);
var
  HostInfo: TWKSTA_USER_INFO_0;
  ActiveUsers: TStringlist;
  i: integer;
  wrkstr: string;
begin
  ActiveUsers := TStringlist.Create;
  try
    HostInfo := EnumNetUsers(ActiveUsers);
    wrkstr := 'Users currently logged in:'#13#10;
    for i := 1 to ActiveUsers.count - 1 do
      wrkstr := wrkstr + ActiveUsers[i] + #13#10;
    Showmessage(wrkstr);
  finally
    ActiveUsers.Free;
  end;
end;
  Mit Zitat antworten Zitat
virus82

Registriert seit: 29. Jun 2007
Ort: Leipzig
34 Beiträge
 
Delphi 2009 Professional
 
#5

AW: LsaEnumerateLogonSessions gibt nicht eingeloggte User in Liste aus

  Alt 7. Jan 2012, 00:16
Ich hab gerade versucht alles mit WTSEnumerateSessions nachzubauen. Da bekomme ich auch nur die richtigen Sessions zurück. Da dachte ich nun ok ich hole mir dann mit WTSQuerySessionInformation und dem Parameter WTSSessionInfoEx auch die Logon Zeit mit, aber in der MSDN steht das
Zitat:
Windows Server 2008, Windows Vista, Windows Server 2003, Windows XP, and Windows 2000: This value is not supported.
. Irgendwie nicht mein Tag.

Naja ich werd auf eine Kombination mit LsaEnumerateLogonSessions und WTSEnumerateSessions zurückgreifen. Mit LsaEnumerateLogonSessions alle Sessions und Zeiten holen und mit WTSEnumerateSessions die angemeldeten User filtern. Irgendwie nicht zufriedenstellend.

Ich denke das auch NetWkstaUserEnum nicht ganz das richtige ist.
Zitat:
The NetWkstaUserEnum function lists information about all users currently logged on to the workstation. This list includes interactive, service and batch logons.
Irgendwie müsste ich die dann noch unterscheiden.

Wenn jemand ne bessere Idee hat nur immer her damit. Ärgerlich das bei LsaEnumerateLogonSessions keine LOGOFF Zeit ermittelt werden kann.
Marco
  Mit Zitat antworten Zitat
virus82

Registriert seit: 29. Jun 2007
Ort: Leipzig
34 Beiträge
 
Delphi 2009 Professional
 
#6

AW: LsaEnumerateLogonSessions gibt nicht eingeloggte User in Liste aus

  Alt 7. Jan 2012, 02:26
Hab grad gesehen das sich die Sessions von LsaEnumerateLogonSessions nur durch die LogonId unterscheden und die SessionID gleich bleibt. So kann ich ja nicht einmal anhand der Sessions von WTSEnumerateSessions die Sessions filtern.

Kennt sich jemand mit der LogonID aus? Ist das eine fortlaufende Nummer? Kann man immer von der höchsten Nummer auf die letzte Session eines User schließen? Wäre sehr dankbar für informationen.

...
Marco
  Mit Zitat antworten Zitat
ASM

Registriert seit: 15. Aug 2004
165 Beiträge
 
Delphi 7 Enterprise
 
#7

AW: LsaEnumerateLogonSessions gibt nicht eingeloggte User in Liste aus

  Alt 7. Jan 2012, 08:02
Ich denke das auch NetWkstaUserEnum nicht ganz das richtige ist.
Zitat:
The NetWkstaUserEnum function lists information about all users currently logged on to the workstation. This list includes interactive, service and batch logons.
Irgendwie müsste ich die dann noch unterscheiden.

In der NetAPI Funktion NetWkstaUserEnum() kannst Du über den Parameter "level" 2 Optionen steuern:
Mit level = 0 werden explizit alle gerade aktiv am lokalen Rechner angemeldeten Benutzer ermittelt; die zwar grundsätzlich am System angemeldeten, aber gerade nicht aktiv eingeloggten Benutzer werden nicht berücksichtigt.
Mit level=1 dagegen wird nur der zum aktiven Desktop gehörige Benutzer und dieser mit zusätzlichen Angaben ausgegeben.
Absolut wichtig zu beachten ist dabei nur die richtige Verwendung der jeweiligen Records zur Auswertung der zurückgelieferten Bufferpointer.

Die mit level 0 erreichbare Option war doch genau Dein (ursprüngliches) Anliegen ? Wo liegt also jetzt Dein Problem ?
Hast Du das denn, so wie in meinem Beispiel vorgeschlagen, wenigstens einmal praktisch versucht, bevor Du die Verwendung von NetWkstaUserEnum() allein mit Hinweis auf das MS-Zitat verwirfst ?

Leider sind mit NetWkstaUserEnum() aber keine Angaben zur LogonTime des jeweiligen Benutzers zu erhalten. Eine Möglichkeit dazu wäre jedoch durch gegenseitigen Abgleich der beiden, mit NetWkstaUserEnum() und mit LsaEnumerateLogonSessions() erhaltenen Listen. Die LsaEnumerateLogonSessions()-Liste filterst Du nach den Benutzernamen, die in der NetWkstaUserEnum()-Liste ausgeworfen sind, und kämest somit über die zugehörigen Details der LsaEnumerateLogonSessions()-Liste an die jeweiligen LogonTime(s) aller aktiv angemeldeten Benutzer.
Nachteil dieses Weges: um an die Details der Sessions in der LsaEnumerateLogonSessions()-Liste zu kommen, muss man diese Funktion mit Adminrechten vornehmen. NetWkstaUserEnum() dagegen benötigt keine Adminrechte.
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:46 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz