Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Prism File Owner mittels GetNamedSecurityInfo - Hilfe! (https://www.delphipraxis.net/46307-file-owner-mittels-getnamedsecurityinfo-hilfe.html)

FragKing 22. Mai 2005 15:14


File Owner mittels GetNamedSecurityInfo - Hilfe!
 
Hi Leute!

Ich bin ziemlich "frisch" mit Delphi am herumtüfteln und werkeln. Es funktioniert soweit ganz gut, ist wirklich einfach das zeugs...
Nur habe ich jetzt etwas was weder mit Delphi selber noch mit dem .net Framework implementiert ist (Im .net v2.0 wirds dann drin sein hab ich gelesen ;)

Und zwar geht es darum den Owner eines files herauszufinden, und zwar benötige ich eigentlich nur die SID, Domain&Account wären dann noch zusatz-gimmicks.
Das ganze mache ich laut Platform SDK mittels des Win32 API calls "GetNamedSecurityInfo" (MSDN).

Ich habe bereits zahlreiche newsgroups / foren durchkämmt, habe aber entweder nur Delphi für Win32 solutions gefunden (mit GetMem FreeMem calls etc -> nicht .net kompatibel) oder dann nur für andere Sprachen (z.b. hier). Ich habe das ganze mal soweit zusammengestiefelt dass ich (zumindest dachte) es sollte funktionieren, tut es aber nicht :coder2:

Für ein funktionierendes Beispiel wäre ich sehr dankbar, und mit einigen erläuterungen verstehe ich das nachher hoffentlich auch noch ;)

Danke schonmal im voraus!

Hier der Code:

Delphi-Quellcode:
unit Unit1;

{$UNSAFECODE ON}
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, System.Text;

  type
  SE_OBJECT_TYPE = (
    SE_UNKNOWN_OBJECT_TYPE,
    SE_FILE_OBJECT,
    SE_SERVICE,
    SE_PRINTER,
    SE_REGISTRY_KEY,
    SE_LMSHARE,
    SE_KERNEL_OBJECT,
    SE_WINDOW_OBJECT,
    SE_DS_OBJECT,
    SE_DS_OBJECT_ALL,
    SE_PROVIDER_DEFINED_OBJECT,
    SE_WMIGUID_OBJECT
  );

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);

  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

function GetNamedSecurityInfo(var pObjectName: String; const ObjectType: SE_OBJECT_TYPE; const SecurityInfo: SECURITY_INFORMATION; ppsidOwner: PSID; ppsidGroup: IntPtr; ppDacl: IntPtr; ppSacl: IntPtr; ppSecurityDescriptor: PSecurity_Descriptor): Integer; cdecl; unsafe;

var
  Form1: TForm1;

implementation

const advapi32 = 'advapi32.dll';

function GetNamedSecurityInfo(var pObjectName: String; const ObjectType: SE_OBJECT_TYPE; const SecurityInfo: SECURITY_INFORMATION; ppsidOwner: PSID; ppsidGroup: IntPtr; ppDacl: IntPtr; ppSacl: IntPtr; ppSecurityDescriptor: PSecurity_Descriptor): Integer; cdecl; unsafe;
external advapi32 name 'GetNamedSecurityInfo';

{$R *.nfm}

procedure TForm1.FormCreate(Sender: TObject); unsafe;
var ssid: PSID;
    user, domainname: string;
    acctype: IntPtr;
    blah: DWORD;
    dir: String;
    dirchar: Char;
    stringsid: String;
    error: Integer;

    sspointer: PSecurity_Descriptor;
begin
dir := ('c:\Test.txt');
error := GetNamedSecurityInfo(dir, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, ssid, nil, nil, nil, sspointer);

if error <> 0 then
ShowMessage(SysErrorMessage(error));
ShowMessage(SysErrorMessage(System.Runtime.InteropServices.Marshal.GetLastWin32Error));

ShowMessage(ssid.ToString);

end;

end.

Olli 23. Mai 2005 04:40

Re: File Owner mittels GetNamedSecurityInfo - Hilfe!
 
Autsch, woher hast du denn den obigen Prototypen?
Code:
function GetNamedSecurityInfoA( [color=red]pObjectName: PWideChar[/color]; ObjectType: SE_OBJECT_TYPE; SecurityInfo: SECURITY_INFORMATION; [color=red]var[/color] ppsidOwner: PSID; [color=red]var[/color] ppsidGroup: PSID; [color=red]var[/color] ppDacl: PACL; [color=red]var[/color] ppSacl: PACL; [color=red]var[/color] ppSecurityDescriptor: PSecurity_Descriptor): DWORD; [color=red]stdcall;[/color] external 'Advapi32.dll';

function GetNamedSecurityInfoW(pObjectName: PWideChar; ObjectType: SE_OBJECT_TYPE; SecurityInfo: SECURITY_INFORMATION; var ppsidOwner: PSID; var ppsidGroup: PSID; var ppDacl: PACL; var ppSacl: PACL; var ppSecurityDescriptor: PSecurity_Descriptor): DWORD; stdcall; external 'Advapi32.dll';
Wenn PACL bei dir nicht definiert ist, benutzt du einfach Pointer oder einen untypisierten Pointertypen - keine Ahnung was das bei Delphi.NET ist.

Luckie 23. Mai 2005 05:05

Re: File Owner mittels GetNamedSecurityInfo - Hilfe!
 
Du hast den Beitrag mit .NET gekennzeichnet, bist du sicher dass das richtig war? Das was du da gepsotet hast, sieht mir mehr nach einem herkömlichen Win32 Delphi Programm aus.

Olli 23. Mai 2005 05:07

Re: File Owner mittels GetNamedSecurityInfo - Hilfe!
 
Zitat:

Zitat von Luckie
Du hast den Beitrag mit .NET gekennzeichnet, bist du sicher dass das richtig war? Das was du da gepsotet hast, sieht mir mehr nach einem herkömlichen Win32 Delphi Programm aus.

Ich denke das war schon korrekt. Er will mit Delphi.NET auf Win32-APIs zugreifen:

Delphi-Quellcode:
ShowMessage(SysErrorMessage(error));
ShowMessage(SysErrorMessage(System.Runtime.InteropServices.Marshal.GetLastWin32Error));
Und dann die vielen Stellen mit "unsafe". Also das kenne ich vom traditionellen Delphi her nicht.

FragKing 23. Mai 2005 07:33

Re: File Owner mittels GetNamedSecurityInfo - Hilfe!
 
Nein, es ist schon korrekt dass es Delphi.NET ist.
Ich möchte wie Olli sagt von Delphi.NET her auf Win32-API's zugreiffen.

Der Prototyp ist von mir. Habe viel hin und her geübt mit dem ding ;)
Ich probiere deinen Vorschlag so schnell wie möglich, danke! Werd mich melden ob's geklappt hat.

Grüsse
Michel

Olli 23. Mai 2005 07:44

Re: File Owner mittels GetNamedSecurityInfo - Hilfe!
 
Zitat:

Zitat von FragKing
Der Prototyp ist von mir. Habe viel hin und her geübt mit dem ding ;)
Ich probiere deinen Vorschlag so schnell wie möglich, danke! Werd mich melden ob's geklappt hat.

Na dann noch ein paar Hinweise. Guck mal hier.

Wenn man einen Pointer auf eine Struktur hat (PStruktur = ^TStruktur) kann man C
Code:
void bla(PStruktur x);
nach Delphi
Code:
procedure bla(var x:TStruktur);
oder
Code:
procedure bla(x:PStruktur);
übersetzen. Entsprechend ergibt sich für den Pointer auf den Pointer auf eine Struktur (Dopplung beachten) von C
Code:
void bla(PStruktur *x);
in Delphi
Code:
procedure bla(var x:PStruktur);
oder, wenn PPStruktur = ^PStruktur, dann
Code:
procedure bla(x:PPStruktur);
.

Hoffe du siehst dabei durch. Obige Vorkommen von var können auch durch const oder out ersetzt werden, wenn dies Sinn macht. Es ist nur wichtig zu verstehen, daß bei var, const und out unter Delphi die Übergabe "by reference" (also als Pointer auf übergebenen Typ) geschieht. Hingegen in den Win32-C/C++-Headern ist OUT nur ein "leeres" Makro, welches als Anhaltspunkt für den Programmierer dient.

Ach ja: alle WINAPIs sind in stdcall. Alle klingt etwas übertrieben (ist es auch), aber bis auf wenige dokumentierte Ausnahmen (meist C-Lib oder ähnliche Funktionen), sind alle stdcall, nicht cdecl!

Robert_G 23. Mai 2005 12:02

Re: File Owner mittels GetNamedSecurityInfo - Hilfe!
 
Kennst du den Reflector? Sau geiles Teil.
Du nimmst deinen C#/Delphi.Net/Chrome/Eifel/whatsoever - Samplecode und kompostierst ihn auch in dem Compiler.
Die entstandene Assembly jagst du durch den Reflector und wählst deine Sprache ala Darstellung aus.
*Fump* Schon findest du den Cod ein deiner Sprache... :shock:

Der Beispielcode bei P/Invoke ist übrigens falsch, da ihre Version von xxx mit einem anderen Typen für den pSid-Parameter arbeitet. Dieses hier geht. ;)

Ich habe es einfach in eine neue C#-ClassLib kopiert, ein wenig rum-ReSharpert (damit man es auch lesen kann :? ) und kompiliert.
Code:
using System;
using System.Runtime.InteropServices;
using System.Text;

namespace FileOwnerDings
{
    public class SecurityDescriptor
    {
        [DllImport("advapi32.dll", SetLastError=true)]
        static extern int GetNamedSecurityInfo(string pObjectName,
                                               SeObjectType ObjectType,
                                               SecurityInformation SecurityInfo,
                                               out IntPtr ppsidOwner,
                                               out IntPtr ppsidGroup,
                                               out IntPtr ppDacl,
                                               out IntPtr ppSacl,
                                               out IntPtr ppSecurityDescriptor);

        [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
        static extern int LookupAccountSid(string systemName,
                                           IntPtr psid,
                                           StringBuilder accountName,
                                           ref int cbAccount,
                                           [Out] StringBuilder domainName,
                                           ref int cbDomainName,
                                           out int use);

        public static string GetFileObjectOwner(string objectName)
        {
            IntPtr pZero = IntPtr.Zero;
            IntPtr pSid = pZero;
            IntPtr psd = pZero; // Not used here
            int errorReturn = GetNamedSecurityInfo(objectName,
                                                   SeObjectType.FileObject,
                                                   SecurityInformation.Owner,
                                                   out pSid,
                                                   out pZero,
                                                   out pZero,
                                                   out pZero,
                                                   out psd);
            if (errorReturn != 0)
            {
                throw new Exception(string.Format("GetNamedSecurityInfo has exited with code {0}. (last error is {0})",
                                                  errorReturn,
                                                  Marshal.GetLastWin32Error()));
            }
            int bufferSize = 64;
            StringBuilder buffer = new StringBuilder();
            int accounLength = bufferSize;
            int domainLength = bufferSize;
            int sidNameUse = 0;
            StringBuilder account = new StringBuilder(bufferSize);
            StringBuilder domain = new StringBuilder(bufferSize);
            errorReturn = LookupAccountSid(null,
                                           pSid,
                                           account,
                                           ref accounLength,
                                           domain,
                                           ref domainLength,
                                           out sidNameUse);
            if (errorReturn == 0)
            {
                throw new Exception(string.Format("LookupAccountSid has exited with code 0. (last error is {0})",
                                                  Marshal.GetLastWin32Error()));
            }
            buffer.Append(domain);
            buffer.Append(@"\");
            buffer.Append(account);
            return buffer.ToString();
        }
    }
}
Die Enums:
Code:
    [Flags]
    public enum SecurityInformation
    {
        Owner = 1,
        Group = 2,
        DACL = 4,
        SACL = 8
    }
Code:
   public enum SeObjectType
    {
        UnknownObjectType = 0,
        FileObject,
        Service,
        Printer,
        RegistryKey,
        LMShare,
        KernelObject,
        WindowObject,
        DsObject,
        DsObjectAll,
        ProviderDefinedObject,
        WMIGUIDObject,
        RegistryWOW64Key
    }
Mangels eines Delphi.Net Komposters nahm ich das Chrome PlugIn für den Reflector und ieß mir Chrome Code erzeugen. (Ist ja sehr ähnlich zu Delphi.Net)
Nachdem ich die lokalen Variablen umbenannt habe (DIe werden von der IL nicht wirklich benannt ;) ) und auch hier einen Formatter drüberrennen ließ, sah es so aus:

Delphi-Quellcode:
namespace FileOwnerDings;

interface
uses
   System,
   System.Runtime.InteropServices,
   System.Text;

type
  SecurityDescriptor = public class
  private
    [DllImport('advapi32.dll', SetLastError := True)]
    class method GetNamedSecurityInfo(pObjectName: string;
                                      ObjectType: SeObjectType;
                                      SecurityInfo: SecurityInformation;
                                      out ppsidOwner,
                                          ppsidGroup,
                                          ppDacl,
                                          ppSacl,
                                          ppSecurityDescriptor: IntPtr): Integer; external;
    [DllImport('advapi32.dll', CharSet := CharSet.Auto, SetLastError := True)]
    class method LookupAccountSid(systemName: string;
                                   psid: IntPtr;
                                   accountName: StringBuilder;
                                   var cbAccount: Integer;
                                   [&Out] domainName: StringBuilder;
                                   var cbDomainName: Integer;
                                   out use: Integer): Integer; external;
  public
    class method GetFileObjectOwner(objectName: string): string;
  end;


implementation

class method SecurityDescriptor.GetFileObjectOwner(objectName: string): string;
var
  pZero, pSid, psd : IntPtr;
  errorReturn     : Integer;
  bufferSize      : Integer;
  accountLength   : Integer;
  domainLength    : Integer;
  sidNameUse      : Integer;
  buffer          : StringBuilder;
  account         : StringBuilder;
  domain          : StringBuilder;
begin
  pZero := IntPtr.Zero;
  pSid := IntPtr.Zero;
  psd := pZero;
  errorReturn := SecurityDescriptor.GetNamedSecurityInfo(objectName,
                                                         SeObjectType.FileObject,
                                                         SecurityInformation.Owner,
                                                         pSid,
                                                         pZero,
                                                         pZero,
                                                         pZero,
                                                         psd);
  if (errorReturn <> 0) then
    raise new Exception(string.Format('GetNamedSecurityInfo excited with code {0}. (last error is {0})',
                                      errorReturn,
                                      Marshal.GetLastWin32Error));

  bufferSize   := 64;
  accountLength := bufferSize;
  domainLength := bufferSize;
  sidNameUse   := 0;
 
  buffer := new StringBuilder;
  account := new StringBuilder(bufferSize);
  domain := new StringBuilder(bufferSize);
 
  errorReturn := SecurityDescriptor.LookupAccountSid(nil,
                                                     pSid,
                                                     account,
                                                     accountLength,
                                                     domain,
                                                     domainLength,
                                                     sidNameUse);
  if (errorReturn = 0) then
    raise new Exception(string.Format('LookupAccountSid excited with code 0. (last error is {0})',
                                      Marshal.GetLastWin32Error));

  buffer.Append(domain);
  buffer.Append('\');
  buffer.Append(account);
  Result := buffer.ToString;
end;

end.
Ab hier sollte eine Konvertierung zu D.Net easy sein. ;)

Der zeitaufwendigste Part an allem war das Schreiben dieses Beitrages. :mrgreen: Also -> Schau dir den Reflector mal an.
Es macht auch Spass die Microsoft Assemblies damit auseinanderzunehmen. ;)

Olli 23. Mai 2005 12:22

Re: File Owner mittels GetNamedSecurityInfo - Hilfe!
 
Zitat:

Zitat von Robert_G
Delphi-Quellcode:
    [DllImport('advapi32.dll', SetLastError := True)]
    class method GetNamedSecurityInfo(pObjectName: string;
                                      ObjectType: SeObjectType;
                                      SecurityInfo: SecurityInformation;
                                      out ppsidOwner,
                                          ppsidGroup,
                                          ppDacl,
                                          ppSacl,
                                          ppSecurityDescriptor: IntPtr): Integer; external;

Ich verspüre den Drang zu ulfen :kotz:

Sorry, @FragKing, ich konnte nicht wissen, daß auch eine solche Verballhornung von ObjectPascal existiert. Aber zumindest das out (siehe var, const, out) hat sich erhalten. Nur string für den ersten Parameter befremdet mich leicht. Aber wird schon richtig sein, ist schließlich die .NETte Version.

FragKing 23. Mai 2005 12:27

Re: File Owner mittels GetNamedSecurityInfo - Hilfe!
 
Das String, so habe ich gelesen, wird vom compiller selber in ein brauchbares format umgewandelt

Ich probiere das ganze mal, danke vielmals! Und das mit diesem Reflector klingt wirklich hervorragend!
Danke euch allen für die Hilfe! So sollts doch sicher klappen =)

Melde mich wieder!

Gruss
Michel

Robert_G 23. Mai 2005 13:04

Re: File Owner mittels GetNamedSecurityInfo - Hilfe!
 
Zitat:

Zitat von Olli
Sorry, @FragKing, ich konnte nicht wissen, daß auch eine solche Verballhornung von ObjectPascal existiert. Aber zumindest das out (siehe var, const, out) hat sich erhalten. Nur string für den ersten Parameter befremdet mich leicht.

Hmpf? :shock:
Was ist an der Zeile anders als in Delphi.Net? :gruebel: (Mal abgesehen davon, dass es in Chrome method statt function/procedure heißt)...
Zitat:

Zitat von Olli
Aber wird schon richtig sein, ist schließlich die .NETte Version.

Das wird vom Marshaler übersetzt. ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:01 Uhr.
Seite 1 von 2  1 2      

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