Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   AV bei LookupAccountSidW (https://www.delphipraxis.net/97078-av-bei-lookupaccountsidw.html)

marabu 4. Aug 2007 18:10

Re: AV bei LookupAccountSidW
 
Hallo,

ich habe von deinen Tests gelesen.

Ist dabei verwertbarer Code entstanden, den du hier veröffentlichen möchtest?

Freundliche Grüße

Dezipaitor 4. Aug 2007 18:29

Re: AV bei LookupAccountSidW
 
Zitat:

Zitat von marabu
Hallo,

ich habe von deinen Tests gelesen.

Ist dabei verwertbarer Code entstanden, den du hier veröffentlichen möchtest?

Freundliche Grüße

Ich hab Luckies Code genommen und ausgeführt und dabei festgestellt, dass der Puffer für den Domainname immer mit angegeben werden muss. Sobald man den SID-Name in den Puffer kopieren will, darf der Domainpuffer NICHT nil sein.
Ich habe es nicht hinbekommen, dass die Funktion TRUE geliefert hat, wenn der Domainpuffer nil war (und dessen Längen-Begleiter).
ODER: Die Funktion scheitert zwar nicht mit einer AV, jedoch gibt sie eben auch kein TRUE zurück.

Delphi-Quellcode:

uses
  JclDebug,
  jwaWindows,
  jwaSddl,
  Windows;

function StrSIDToName(const StrSID: widestring; var Name: wideString; var SIDType: DWORD): Boolean;
var
  SID              : PSID;
  Buffer,B2            : PwideChar;
  NameLen, TempLen : Cardinal;
  success           : Boolean;
  TS : TSecurityID;
  res : Integer;
begin
  SID := nil;
  success := true;

  success := ConvertStringSidToSidW(PWideChar(StrSID), jwaWindows.PSID(SID));
  if success then
  begin
    NameLen := 0;
    TempLen := 0;
    SetLastError(0);
    if not LookupAccountSidW(nil, SID, nil, NameLen, nil, TempLen, SIDType) and
       (GetLastError() = ERROR_INSUFFICIENT_BUFFER) then
    begin
      GetMem(Buffer, NameLen * sizeOf(wideChar));
      GetMem(B2, TempLen * sizeOf(wideChar));


      if (Buffer <> nil) then
      try
        SetLastError(0);
        success := LookupAccountSidW(nil, SID, Buffer, NameLen, B2, TempLen, SIDType);
        if not success then
          RaiseLastOSError;
        if success then
          SetString(Name, Buffer, Namelen);
      finally
        FreeMem(Buffer);
        FreeMem(B2);
      end;
    end
    else
      RaiseLastOSError;
  end
  else
    RaiseLastOSError;

  LocalFree(HLOCAL(SID));
  result := success;
end;
In meiner Security Library habe ich übrigens diesen Code in etwa auch so drin. Und den verwende ich ständig :D, besonders auch, da SIDs eigentlich überall gebraucht werden.

marabu 4. Aug 2007 19:05

Re: AV bei LookupAccountSidW
 
Hallo,

ich kann leider momentan nicht testen, aber nach Aktenlage würde die Funktion bei mir etwa so aussehen:

Delphi-Quellcode:
function StrSIDToName(const StrSID: WideString; var Name: WideString; var SIDType: DWORD): Boolean;
var
  SID: PSID;
  bufName, bufDomain: PWideChar;
  sizeName, sizeDomain: Cardinal;
begin
  SID := nil;
  if ConvertStringSidToSidW(PWideChar(StrSID), SID) then
  begin
    sizeName := 0;
    sizeDomain := 0;
    SetLastError(0);
    Result := LookupAccountSidW(nil, SID, nil, sizeName, nil, sizeDomain, SIDType);
    if not Result and (GetLastError() = ERROR_INSUFFICIENT_BUFFER) then
    begin
      GetMem(bufName, sizeName * SizeOf(WideChar));
      GetMem(bufDomain, sizeDomain * SizeOf(WideChar));
      SetLastError(0);
      Result := LookupAccountSidW(nil, SID, bufName, sizeName, bufDomain, sizeDomain, SIDType);
      if Result
        then Name := WideString(bufName)
        else Name := '';
      FreeMem(bufName);
      FreeMem(bufDomain);
    end;
  end;
  LocalFree(HLOCAL(SID));
  Result := True;
end;
GetLastError() würde ich außerhalb verwenden, sonst macht Result keinen Sinn mehr und man könnte gleich eine Prozedur verwenden.

Freundliche Grüße

Dezipaitor 4. Aug 2007 19:23

Re: AV bei LookupAccountSidW
 
Zitat:

Zitat von marabu
Hallo,

GetLastError() würde ich außerhalb verwenden, sonst macht Result keinen Sinn mehr und man könnte gleich eine Prozedur verwenden.

hä?

Christian Seehase 4. Aug 2007 19:48

Re: AV bei LookupAccountSidW
 
Moin Zusammen,

ich hab' mir das Ganze gerade mal im CPU-Fenster angesehen.
Einmal mit LookupAccountSidA, einmal mit LookupAccountSidW.
In beiden Fällen war die Länge für ReferencedDomainName ermittelt, als Buffer aber nil übergeben worden.
(Also der zweite Aufruf)

Der Witz ist:
Nachdem die Funktionen den Stack mit Parametern gefüllt haben, laufen sie an der gleichen Stelle weiter (so etwas passiert ja öfter, bei Funktionen, die es in beiden Varianten gibt).
Beim Aufruf von RtlCopyUnicodeString schlägt dann die Unicode-Version fehl, die andere läuft durch. :gruebel:
Ich hatte jetzt allerdings nicht den Nerv mir herauszusuchen, wie nil für ReferencedDomainName nach Unicode umgewandelt wird, so dass der Aufruf nicht fehlschlägt, obwohl kein Buffer angegeben wird.

Luckie 4. Aug 2007 22:20

Re: AV bei LookupAccountSidW
 
Mann. Das ist ja ein Krampf mit der Funktion. Wer hat denn da jetzt Mist gebaut? Borland oder Microsoft?

Dezipaitor 4. Aug 2007 22:38

Re: AV bei LookupAccountSidW
 
Ich tippe auf MS. Das scheint entweder nicht dokumentiert zu sein - keiner hat die KB durchgesucht danach - oder es weiß einfach keiner :D

Wenn ich ne LiveID hätte, dann würde ich nen Kommentar zum MSDN Eintrag schreiben und warnen :D

Christian Seehase 5. Aug 2007 01:59

Re: AV bei LookupAccountSidW
 
Moin Dezipaitor,

Zitat:

Zitat von Dezipaitor
Ich tippe auf MS.

Da tippst Du richtig.
Ich habe das Ganze mal im Visual Studio 2005 Express nachgebaut:
LookupAccountSidW mit dem Parameter Domain auf nil (bzw. NULL) schlägt, wie gehabt, fehl (AV: Zugriff verweigert beim Zugriff auf Adresse 0), wohingegen LookupAccountSidA klaglos ausgeführt wird. Das ist dann auch daran zu sehen, dass der Name korrekt gefüllt ist.

Dezipaitor 5. Aug 2007 13:36

Re: AV bei LookupAccountSidW
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hu, gewonnen!

Man daran hab ich garnet gedacht. Also das Zeugs in C++ zu machen :D - oder ich war einfach zu faul dafür.

---

Ich mach mal ne Konklusion/Schlussfolgerung:

Verwende niemals nil in der Unicodevariante von LookupAccountSid (=LookupAccountSidW) für den Parameter lpReferencedDomainName alleine. Entweder du setzt den Parameter lpName UND lpReferencedDomainName auf nil und übergibst über eine Variable 0 an
cchReferencedDomainName und cchName, oder du erstellst einen Puffer (mit GetMem) mit der korrekten Größe für beide Parameter.

Ein funktionierendes Beispiel findest du entweder von marabu oder von meiner Wenigkeit.

Alles andere ist schlecht :D


Ich würde ja einen Kommentar in die MSDN für LookupAccountSid schreiben, wenn ich eine LiveID hätte oder mich einschreiben könnte. Da jedoch derzeit jedesmal "We're unable to complete your request Windows Live ID is experiencing technical difficulties. Please try again later." geht es nicht. Also freiwillige vor?

P.S.
Hat das jemand mal unter Vista probiert?

Anbei ein Testprogramm nebst Quelltext zum Testen.

---
Delphi-Quellcode:
zweiter Aufruf von RtlCopyUnicodeString
--------------------------------
movzx  eax, word ptr [eax]
cmp    ax, cx
push   edi
mov    edi, [edx+$04]
mov    [ebp+$08], edi
jnbe   +$0000FC37
mov    ecx, eax
mov    ebx, ecx
shr    ecx, $02
mov    [edx], ax
rep    movsd                 ; hier EXCEPTION

mov    ecx, ebx
and    ecx, +$03
rep
movsb
mov    cx, word ptr [edx]
cmp    cx, word ptr [edx+$02]
pop    edi
pop    esi
pop    ebx
Vor der Exception wird versucht an Speicherposition [EDI] zu schreiben. Da dies jedoch 0 ist, schlägt der Zugriff fehl. Ich hab das Register mal umgebogen auf ne andere Adresse und schon hatte ich die Exception mit genau der Adresse von EDI - also liegt es daran.


Hier das Problem mit RtlCopyUnicodeString

Delphi-Quellcode:
var us,u2 : TUnicodeString;
begin
  us.Length := 4; //Pufferlänge! nicht Stringlänge
  us.MaximumLength := 4;
  us.Buffer := WideString('a1'#0#0);

  u2.Length := 0;
  u2.MaximumLength := 2;
  GetMem(u2.Buffer,4*sizeof(WideChar));
 

  RtlCopyUnicodeString(@u2,@us); //ok

  p := nil;

  try
    RtlCopyUnicodeString(p,@us); // Exception
  except
    on E : EAccessViolation do
     Writeln(E.Message);
  end;

Dezipaitor 6. Aug 2007 18:02

Re: AV bei LookupAccountSidW
 
*push*


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:19 Uhr.
Seite 2 von 3     12 3      

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