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/)
-   -   LookupAccountSidW und Datenbereich zu klein (https://www.delphipraxis.net/87917-lookupaccountsidw-und-datenbereich-zu-klein.html)

Luckie 7. Mär 2007 12:04


LookupAccountSidW und Datenbereich zu klein
 
Wenn ich folgenden Code ausführe:
Delphi-Quellcode:
function StrSIDToName(const StrSID: Widestring; var Name: WideString; var SIDType: DWORD): DWORD;
var
  SID              : PSID;
  Buffer           : PWideChar;
  NameLen, TempLen : Cardinal;
  err              : Boolean;
begin
  SID := nil;
  err := ConvertStringSIDToSID(PWideChar(StrSID), SID);
  if err then
  begin
    NameLen := 0;
    TempLen := 0;
    if LookupAccountSidW(nil, SID, nil, NameLen, nil, TempLen, SIDType) then
    begin
      GetMem(Buffer, NameLen);
      try
        err := LookupAccountSidW(nil, SID, Buffer, NameLen, nil, TempLen, SIDType);
        if err then
        begin
          SetString(Name, Buffer, Namelen);
          SetLastError(0);
        end;
      finally
        FreeMem(Buffer);
      end;
    end;
  end;
  if Assigned(SID) then
    LocalFree(Cardinal(SID));
  result := GetLastError;
end;
fliege ich beim ersten Aufruf von LookupAccountSidW und erhalten den Fehler:
Zitat:

Der an einen Systemaufruf übergebene Datenbereich ist zu klein.
Aber ich will doch die Größe des Datenbereichs ermitteln? Wie kann da der Datenbereich schon zu klein sein?

mirage228 7. Mär 2007 12:07

Re: LookupAccountSidW und Datenbereich zu klein
 
Wird denn für "NameLen" trotzdem was vernünftiges zurückgegeben?

mfG
mirage228

Luckie 7. Mär 2007 12:14

Re: LookupAccountSidW und Datenbereich zu klein
 
Es ist zumindest größer null.

mirage228 7. Mär 2007 12:16

Re: LookupAccountSidW und Datenbereich zu klein
 
Zitat:

Zitat von Luckie
Es ist zumindest größer null.

Hm und so wie ich den MSDN-Eintrag zu der Funktion gelesen habe, könnte man das ggf. auch so intrepetieren, dass die Funktion zwar fehlschlägt, jedoch aufgrund des zu kleinen Datenbereich aber trotzdem die erforderliche Länge in die Variable speichert - denn das verhalten für lpName = NULL ist ja eindeutig festgelegt.

mfG
mriage228

Luckie 7. Mär 2007 12:28

Re: LookupAccountSidW und Datenbereich zu klein
 
So hatte ich es ja auch. Aber marabu meinte hier: http://www.delphipraxis.net/internal...=691800#691800 , dass ich eine falsche Fehlermeldung bekäme, weil ich beim Ermitteln der nötigen Buffergröße den Rückgabewert der Funktion nicht auswerten würde.

Ich habe es jetzt also so:
Delphi-Quellcode:
function StrSIDToName(const StrSID: Widestring; var Name: WideString; var SIDType: DWORD): DWORD;
var
  SID              : PSID;
  Buffer           : PWideChar;
  NameLen, TempLen : Cardinal;
  err              : Boolean;
begin
  SID := nil;
  err := ConvertStringSIDToSID(PWideChar(StrSID), SID);
  if err then
  begin
    NameLen := 0;
    TempLen := 0;
    LookupAccountSidW(nil, SID, nil, NameLen, nil, TempLen, SIDType);
    NameLen := NameLen * 2 + 1;
    GetMem(Buffer, NameLen);
    try
      err := LookupAccountSidW(nil, SID, Buffer, NameLen, nil, TempLen, SIDType);
      if err then
      begin
        SetString(Name, Buffer, Namelen);
        SetLastError(0);
      end;
    finally
      FreeMem(Buffer);
    end;
  end;
  if Assigned(SID) then
    LocalFree(Cardinal(SID));
  result := GetLastError;
end;
Aber jetzt fliege ich beim zweiten Aufruf raus und zwar ganz. Das Programm beendet sich im Debugger. Nehme ich die Ansi-Version der Funktion geht es. :gruebel:

himitsu 7. Mär 2007 12:40

Re: LookupAccountSidW und Datenbereich zu klein
 
Und was wenn du den Rückgabewert berücksichtigst?

Bringt zwar beim Ansi-Wide-Problem nichts, aber marabu sollte zumindestens nicht meckern. :angel:

Delphi-Quellcode:
function StrSIDToName(const StrSID: Widestring; var Name: WideString; var SIDType: DWORD): DWORD;
var
  SID              : PSID;
  Buffer           : PWideChar;
  NameLen, TempLen : Cardinal;
begin
  SID := nil;
  if ConvertStringSIDToSID(PWideChar(StrSID), SID) then begin
    NameLen := 0;
    TempLen := 0;
    if LookupAccountSidW(nil, SID, nil, NameLen, nil, TempLen, SIDType) then
      result := 0 else result := GetLastError;
    if (result = 0) or (result = WasWeißIch) then begin
      GetMem(Buffer, NameLen);
      try
        if LookupAccountSidW(nil, SID, Buffer, NameLen, nil, TempLen, SIDType) then begin
          SetString(Name, Buffer, Namelen);
          result := 0;
        end else result := GetLastError;
      finally
        FreeMem(Buffer);
      end;
    end;
  end else result := GetLastError;
  if Assigned(SID) then LocalFree(Cardinal(SID));
end;

Luckie 7. Mär 2007 12:47

Re: LookupAccountSidW und Datenbereich zu klein
 
Hm, das überlege ich mir noch mal, denn schön sieht es nicht aus. ;)

himitsu 7. Mär 2007 12:54

Re: LookupAccountSidW und Datenbereich zu klein
 
Na es soll doch wohl "nur" funktionieren und nich in 'ner Galerie ausgestellt werden :oops:

Luckie 7. Mär 2007 12:55

Re: LookupAccountSidW und Datenbereich zu klein
 
marabu hat hier http://www.delphipraxis.net/internal...=691954#691954 folgenden Vorscchlag gemacht:
Delphi-Quellcode:
function StrSIDToName(const StrSID: Widestring; var Name: WideString; var SIDType: DWORD): DWORD;
var
  SID              : PSID;
  Buffer           : PWideChar;
  NameLen, TempLen : Cardinal;
  ErrSuccess       : Boolean;
begin
  SID := nil;
  ErrSuccess := ConvertStringSIDToSID(PWideChar(StrSID), SID);
  if ErrSuccess then
  begin
    NameLen := 0;
    TempLen := 0;
    LookupAccountSidW(nil, SID, nil, NameLen, nil, TempLen, SIDType);
    if NameLen > 0 then
    begin
      GetMem(Buffer, NameLen + 2);
      try
        ErrSuccess := LookupAccountSidW(nil, SID, Buffer, NameLen, nil, TempLen, SIDType);
        if ErrSuccess then
        begin
          SetString(Name, Buffer, Namelen);
          SetLastError(0);
        end;
      finally
        FreeMem(Buffer);
      end;
    end;
  end;
  if Assigned(SID) then
    LocalFree(Cardinal(SID));
  result := GetLastError;
end;
Das Problem bleibt aber das gleiche, beim zweiten Aufruf fliege ich einfach ohne Fehlermeldung aus dem Programm.

himitsu 7. Mär 2007 13:15

Re: LookupAccountSidW und Datenbereich zu klein
 
NameLen = Chars
oder
NameLen = Bytes?

:angel:

Delphi-Quellcode:
GetMem(Buffer, (NameLen + 1) * 2);

marabu 7. Mär 2007 13:17

Re: LookupAccountSidW und Datenbereich zu klein
 
Diesen Thread habe ich ganz übersehen, deshalb meine Beiträge im anderen Thread - sorry.

In meinem letzten Beitrag dort hatte ich geschrieben:

Zitat:

Zitat von marabu
... Vermutlich musst du noch die Behandlung der Domänenbezeichnung über TempLen analog NameLen anpassen - ich habe das nicht getestet.

Solange das nicht passiert ist, kann theoretisch auch beim zweiten Aufruf noch BUFFER_TOO_SMALL gemeldet werden.

Freundliche Grüße

Remko 7. Mär 2007 13:19

Re: LookupAccountSidW und Datenbereich zu klein
 
Isn't is meant to work like this (behaviour by design)?

I'm used to doing this (example with LookupAccountName) but behaviour for LookupAccountSid is the same::

Delphi-Quellcode:
  dwSizeSid := 0;
  dwSizeDomain := 0;
  bRes := LookupAccountName(nil, 'Administrator', nil, dwSizeSid, nil, dwSizeDomain, SidType);

  if (not bRes) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
  begin
    // Reserve memory
    AdminSid := AllocMem(dwSizeSid);
    SetLength(Domain, dwSizeDomain);

    // Lookup Sid from Accountname
    // Assuming that the Admin account has not been renamed!
    bRes := LookUpAccountName(nil, 'Administrator', AdminSid, dwSizeSid, PChar(Domain), dwSizeDomain, SidType);

marabu 7. Mär 2007 13:29

Re: LookupAccountSidW und Datenbereich zu klein
 
Hi Remko,

if you refer to the general mechanism for buffer allocation by calling a function twice - you are right for sure.

With regard to the unassigned domain-name-buffer I would expect the very failure described. Can you comment on this?

Regards

Luckie 7. Mär 2007 13:38

Re: LookupAccountSidW und Datenbereich zu klein
 
Ich habe auch schon das probiert:
Delphi-Quellcode:
TempLen := TempLen + 2;
vor dem zweiten Aufruf, hat aber auch nichts geholfen.

Robert Marquardt 7. Mär 2007 13:41

Re: LookupAccountSidW und Datenbereich zu klein
 
NameLen*sizeOf(WideChar)! Es wird in Chars gezaehlt. Das sind bei einer Unicode-Funktion natuerlich Unicode-Chars.
Meine MSDN Doku sagt "in TCHARs". Das heisst eben das man TCHAR nehmen soll fuer seine Puffer und je nach UNICODE-Einstellung wird TCHAR auf Char oder WideChar gemappt.
Versuch es doch mal mit den jedi-apilib Files. Dort ist dieser Mechanismus ebenfalls implementiert. Ich habe auch mal ein Programm geschrieben das mit beiden UNICODE-Eistellungen fehler- und warnungsfrei kompiliert und laeuft.

himitsu 7. Mär 2007 13:45

Re: LookupAccountSidW und Datenbereich zu klein
 
Zitat:

Delphi-Quellcode:
TempLen := TempLen + 2;

Na ja ... wie wäre es mit * ?

Aber gib es lieber direkt bei GetMem an, oder will SetString das auch in Bytes wissen? :gruebel:

Luckie 7. Mär 2007 13:49

Re: LookupAccountSidW und Datenbereich zu klein
 
Hmpf, man darf bei der Unicode-Version nicht nil bei der Domain übergeben. Übergebe ich dort einen Buffer funktioniert es. :wall:


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:40 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz