Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   GetUsernameEx (https://www.delphipraxis.net/181394-getusernameex.html)

kuba 11. Aug 2014 15:31

GetUsernameEx
 
Hallo,

seit Stunden versuche ich herauszufinden was an meinem Programm nicht funktioniert. Ich möchte den Benutzernamen des am Desktop angemeldeten Benutzer aus einem NT-Service ermitteln. Dabei verwende ich folgenden Code:

Delphi-Quellcode:
const
  NameUnknown      = 0; // Unknown name type.
  NameFullyQualifiedDN = 1; // Fully qualified distinguished name
  NameSamCompatible = 2; // Windows NT® 4.0 account name
  NameDisplay      = 3; // A "friendly" display name
  NameUniqueId     = 6; // GUID string that the IIDFromString function returns
  NameCanonical    = 7; // Complete canonical name
  NameUserPrincipal = 8; // User principal name
  NameCanonicalEx  = 9;
  NameServicePrincipal = 10; // Generalized service principal name
  DNSDomainName    = 11; // DNS domain name, plus the user name

function GetUserNameExString(ANameFormat: DWORD): string;
var
  Buf: array[0..256] of Char;
  BufSize: DWORD;
  GetUserNameEx: function (NameFormat: DWORD; lpNameBuffer: LPSTR;
    var nSize: ULONG): BOOL; stdcall;
begin
  Result := '';
  BufSize := SizeOf(Buf) div SizeOf(Buf[0]);
  GetUserNameEx := GetProcAddress(GetModuleHandle('secur32.dll'), 'GetUserNameExW');
  if Assigned(GetUserNameEx) then
    if GetUserNameEx(ANameFormat, @Buf[0], BufSize) then
      Result := Buf;
end;
Als Ergebnis erhalte ich jedoch nicht den Benutzernamen sondern die Workgroup und den PC-Namen im Format WORKGROUP\PC-Name

Aufruf:
Delphi-Quellcode:
showmessage(GetUserNameExString(NameSamCompatible));

Delphi XE2/64Bit. Was könnte da falsch laufen ??

KUBA

himitsu 11. Aug 2014 15:43

AW: GetUsernameEx
 
Ich hätte jetzt vermutet, daß die Funktion maximal den Namen zurückgeben kann, von dem Account, in welchem der Service läuft.
Und das wird vermutlich nicht der Account des Bentzters sein. :stupid:

Die Funktion heißt ja praktisch "gib die Infos von meinem Account" (mein = von dem Programm)


Vermutlich wird man irgendwie rausfinden müssen welcher "Desktop" aktuell auf dem Monitor angezeigt wird und liest dann von Diesem den Account aus.

hoika 11. Aug 2014 16:02

AW: GetUsernameEx
 
Hallo,

vielleicht hilft dir das

http://www.delphipages.com/forum/arc.../t-203396.html

Dort suchen nach
alee
SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, PChar(appPath));


Heiko

JYPDWhite 11. Aug 2014 17:36

AW: GetUsernameEx
 
So funktioniert es bei uns:
Delphi-Quellcode:
procedure GetUserNameEx(NameFormat: DWORD;lpNameBuffer: LPSTR; nSize: PULONG);
          stdcall; external 'secur32.dll' Name 'GetUserNameExW';



procedure UsernameAuslesen();
var
  UserName_array: array[0..250] of char;
  szUserName : array[0..99] of Char;
  Size: DWORD;
begin
    FillChar(szUserName, SizeOf(szUserName), 0);
     Size := SizeOf(szUserName);
    GetUserName(szUserName, Size); // das holt erstmal die GID des aktuellen Nutzers
    UserNameLogin:= Uppercase(szUserName);
    Size := 250;
    GetUserNameEx(3, @UserName_array, @Size); // das ließt dann vorname nachname usw aus
end;
Das ist jetzt aus nem größeren Teil Code zusammenkopiert. Kann also sein dass es jetzt nicht Copy&Paste funktioniert ;-)

sx2008 11. Aug 2014 21:14

AW: GetUsernameEx
 
Zitat:

Zitat von JYPDWhite (Beitrag 1268368)
Das ist jetzt aus nem größeren Teil Code zusammenkopiert

Das ist doch ein kleiner Wink dass der größere Codeteil nicht optimal gebaut ist.
Es passiert zuviel innerhalb einer Funktion bzw. Methode.
Solange man aus einem größeren Codeblock nützliche Funktionen isolieren kann ist der Sourcecode noch nicht richtig sauber.

JYPDWhite 11. Aug 2014 21:25

AW: GetUsernameEx
 
OT: Ich weiß... Aber wie du warscheinlich ebenfals aus der Praxis weißt kann man nicht einfach ein ganzes Programm was man übernommen hat direkt komplett umbauen sondern kann das allenfalls nach und nach machen, wer soll das den sonst bezahlen ;-)

Sir Rufo 11. Aug 2014 21:37

AW: GetUsernameEx
 
Zitat:

Zitat von JYPDWhite (Beitrag 1268402)
OT: Ich weiß... Aber wie du warscheinlich ebenfals aus der Praxis weißt kann man nicht einfach ein ganzes Programm was man übernommen hat direkt komplett umbauen sondern kann das allenfalls nach und nach machen, wer soll das den sonst bezahlen ;-)

Aber du hast den Code doch jetzt in den Fingern, da bietet sich doch direkt ein Refactoring an ;)

kuba 11. Aug 2014 21:48

AW: GetUsernameEx
 
Zitat:

Zitat von himitsu (Beitrag 1268347)
Vermutlich wird man irgendwie rausfinden müssen welcher "Desktop" aktuell auf dem Monitor angezeigt wird und liest dann von Diesem den Account aus.

Super Idee, so "ähnlich" habe ich es jetzt für meine Zwecke gelöst. Wenn der richtige Benutzer angemeldet ist läuft eine bestimmte Anwendung im Hintergrund, das reicht mir vollkommen :wink:

Vielen Dank für die Anregungen.

KUBA

Kurt56 25. Nov 2014 14:06

AW: GetUsernameEx
 
Ich habe das Problem, den Usernamen zu finden, so gelöst:

Delphi-Quellcode:
procedure TMainForm.FormCreate(Sender: TObject);
var
    lpbuff : pchar;
    nSize : dword;
begin

lpbuff:=PChar(AllocMem(30));
getusername(lpbuff, nsize);
//showmessage(lpbuff);
getusername(lpbuff, nsize);
//showmessage(lpbuff);
end;
Leider erhalte ich bei dem ersten Aufruf von "getusername" nur einen leeren String.
Doch mit dem gleich darauf folgenden Aufruf erhalte ich den Usernamen, der sich aktuell angemeldet hat.

Warum der 1. Aufruf noch nicht zum Ziel führt, habe ich nie untersucht, Hauptsache ich komme so an den Usernamen.

Kurt

Bernhard Geyer 25. Nov 2014 14:09

AW: GetUsernameEx
 
Zitat:

Zitat von Kurt56 (Beitrag 1281035)
Leider erhalte ich bei dem ersten Aufruf von "getusername" nur einen leeren String.
Doch mit dem gleich darauf folgenden Aufruf erhalte ich den Usernamen, der sich aktuell angemeldet hat.

Warum der 1. Aufruf noch nicht zum Ziel führt, habe ich nie untersucht, Hauptsache ich komme so an den Usernamen.

Da brauchst du nix untersuchen, einfach die Funktionsbeschreibung durchlesen.
Der zweite Parameter ist ein In/Out-parameter. Rein gibtst du die Buffergröße, raus bekommst du die nötige Buffergröße.
Also beim ersten Aufruf geht du mit größe 0 rein, raus kommt die nötige größe und beim zweiten aufruf hast du diese als in-Wert.

Uwe Raabe 25. Nov 2014 14:15

AW: GetUsernameEx
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1281036)
Also beim ersten Aufruf geht du mit größe 0 rein

Das ist aber bei einer lokalen Variable eher Zufall. Steht auf dem Stack an der Position von nWord irgendein gültiger Wert, kann das auch mal zu einem Bufferoverflow führen.

hathor 25. Nov 2014 14:48

AW: GetUsernameEx
 
Delphi-Quellcode:
function GetUser: String;
const
   MAX_USERNAME_LENGTH = 256;
var
    Buffer: Array[0..MAX_USERNAME_LENGTH] of WIDEChar;
    Size: DWord;
begin
    Size := Pred(SizeOf(Buffer));
    Winapi.Windows.GetUserName(Buffer, Size);
    Result := StrPas(Buffer);
end;

Uwe Raabe 25. Nov 2014 15:09

AW: GetUsernameEx
 
Zitat:

Zitat von hathor (Beitrag 1281040)
Wozu Platz verschwenden: MAX_COMPUTERNAME_LENGTH = 15 !

Wobei es hier ja nicht um den Computernamen sondern um den Usernamen geht - der kann bis zu 256 Zeichen lang sein!

Bernhard Geyer 25. Nov 2014 15:25

AW: GetUsernameEx
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1281037)
Das ist aber bei einer lokalen Variable eher Zufall.

Wobei wir schon fast wieder hier wären: http://www.delphipraxis.net/182840-w...reeandnil.html

DeddyH 25. Nov 2014 15:38

AW: GetUsernameEx
 
Ich mach da einfach 2 Aufrufe wie von Bernhard schon angedeutet, siehe hier: http://forum.delphi-treff.de/index.p...tzer-auslesen/

hathor 25. Nov 2014 15:40

AW: GetUsernameEx
 
@Uwe Raabe:
Du hast recht.
Ich habe mich bei den Constanten vergriffen...
Was mein DELPHI nicht kennt, muss ich dann eben selbst definieren:

const
MAX_USERNAME_LENGTH = 256;

himitsu 25. Nov 2014 16:07

AW: GetUsernameEx
 
@hator: SizeOf .... Length ... Du mußt aufpassen, ob die API die Größe in Byte oder Chars haben will und ob die Größenangabe inklusive oder exclusive der abschließenden #0 ist.

hathor 25. Nov 2014 16:33

AW: GetUsernameEx
 
Bei
const
MAX_USERNAME_LENGTH = 256;
var
Buffer: Array[0..MAX_USERNAME_LENGTH] of WIDEChar;


ist alles ALL INCLUSIVE.

Aber sooo lange UserNames hat wohl keiner...
da würde auch Buffer: Array[0..10] of WIDEChar; reichen..:-D

hathor 25. Nov 2014 16:36

AW: GetUsernameEx
 
OFFTOPIC:

Was ist das eigentlich für ein seltsamer Absturz?
Gerade ist mein WIN 8.1 abgestürzt.
Nach dem Booten war FIREFOX wieder vollständig da, incl. dem Edit-Fenster von der DP.:!::!::!:

himitsu 25. Nov 2014 16:55

AW: GetUsernameEx
 
Zitat:

Delphi-Quellcode:
MAX_USERNAME_LENGTH = 256;
var
Buffer: Array[0..MAX_USERNAME_LENGTH] of WIDEChar;

Das Array ist 257 Zeichen lang, der API wird SizeOf übergeben, also 257*2 aka 514 Byte, was die API aber als Char interpretiert und somit ein Bufferoverrun vorprogrammiert ist. (bei Unicode)
Dann erwartet die API die Größe exkl. der #0, womit sie mochmal weitere 2 Byte überschreiben könnte.

Die API würde zwar nicht außerhalb des Puffers schreiben, aber wenn man ihr eine falsche Größe nennt, dann kann sie natürlich nichts dafür.
0..10 ... bei 11 bis 22 Chars würde es also Spaß machen. :roll:

Kurt56 26. Nov 2014 09:13

AW: GetUsernameEx
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1281036)
Da brauchst du nix untersuchen, einfach die Funktionsbeschreibung durchlesen.
Der zweite Parameter ist ein In/Out-parameter. Rein gibtst du die Buffergröße, raus bekommst du die nötige Buffergröße.
Also beim ersten Aufruf geht du mit größe 0 rein, raus kommt die nötige größe und beim zweiten aufruf hast du diese als in-Wert.

Oh, Asche auf mein Haupt. Vielen Dank für den Hinweis.


Als USERNAME habe ich bisher erlebt, dass der Nachname 12 Stellen hatte. Da mehrere Personen der Familie einen Account hatten, kam noch der Vorname dazu.
10 Stellen sind da nicht gut ausreichend.

Luckie 26. Nov 2014 09:49

AW: GetUsernameEx
 
Äh? Der Anmeldebenutzername unterscheidet nicht zwischen Vor- und Nachname. Das ist der Kontoname. Im Benutzerprofil kann man zwischen Vor- und Nachnamen unterscheiden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:20 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