Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Speicher freigeben, der noch gebraucht wird (https://www.delphipraxis.net/95376-speicher-freigeben-der-noch-gebraucht-wird.html)

Luckie 5. Jul 2007 22:49


Speicher freigeben, der noch gebraucht wird
 
Folgende Funktion:
Delphi-Quellcode:
function GetProcessOwner(PID: DWord; var SID: PSID): Boolean;
var
  hProcess         : THandle;
  ppsidOwner       : PSID;
  SecDescriptor    : PSECURITY_DESCRIPTOR;
  err              : DWord;

const
  SE_UNKNOWN_OBJECT_TYPE: DWord = 0;
  SE_FILE_OBJECT   : DWord = 1;
  SE_SERVICE       : DWord = 2;
  SE_PRINTER       : DWord = 3;
  SE_REGISTRY_KEY  : DWord = 4;
  SE_LMSHARE       : DWord = 5;
  SE_KERNEL_OBJECT : DWord = 6;
  SE_WINDOW_OBJECT : DWord = 7;

begin
  hProcess := 0;
  err := 0;
  try
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or GENERIC_READ, False, pid);
    if (hProcess <> 0) then
    begin
      err := GetSecurityInfo(hProcess, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, @ppsidOwner, nil, nil, nil,
        @SecDescriptor);
      if (err = 0) then
      begin
        SID := ppsidOwner;
        //LocalFree(Cardinal(SecDescriptor));
      end;
      CloseHandle(hProcess);
    end;
  except
  end;
  Result := (err = 0) and (hProcess <> 0);
end;
Wenn ich den Zeiger SecDescriptor in der Funktion freigeben ist der Rückgabewert natürlich ungülig. aber wie und wo geben ich den Speicher wieder frei bzw. wie bekomme ich den Zeiger als Ergebnis ohne mir ein Speicherleck einzuhandeln?

Muetze1 6. Jul 2007 00:03

Re: Speicher freigeben, der noch gebraucht wird
 
Kopie erstellen. Kopiere den Inhalt in den SSID Zeiger, welchen du übergibst.

Luckie 6. Jul 2007 00:10

Re: Speicher freigeben, der noch gebraucht wird
 
Das wäre dann MemCopy oder wie heißt die Funktion?

Muetze1 6. Jul 2007 00:12

Re: Speicher freigeben, der noch gebraucht wird
 
Joa, MemCopy oder das gute alte Pascal Move(), etc

Nochmals im Detail:

Grundlegend: Du hast Speicheradresse angegeben welcher er einen Zeiger auf von ihm alloziierten Speicher zurück gibt. Genauso bekommt deine Funktion beim Aufruf einen Zeiger auf einen vom Aufrufer bereitgestellten Speicherplatz zur Verfügung. Nun hast du zwei Speicherplätze von denen du einen füllen sollst und den anderen musst du wieder freigeben. Du könntest natürlich auf das freigeben verzichten und einfach den Zeiger von dem Aufrufer auf den anderen Speicher zeigen lassen. Damit wäre dann der vom Aufrufer bereitgestellte Speicher verloren und der Aufrufer bekommt seine Daten im fremden Speicher. Von daher: kopieren.

Das du den Pointer des Aufrufers (SSID) überhaupt verbiegen kannst ist eigentlich schon bedenklich. Im Normalfall sollte das konstant sein und dadurch kann sich der Aufrufer sicher sein, dass sein beim Aufruf angegebener Speicher auch nach dem Aufruf immernoch der gleiche ist.

Luckie 6. Jul 2007 00:28

Re: Speicher freigeben, der noch gebraucht wird
 
Ich hatte es erst so:
Delphi-Quellcode:
function GetProcessOwner(PID: DWord; var SID: PSID): Boolean;
var
  hProcess         : THandle;
  pSIDDummy        : PSID;
  SecDescriptor    : PSECURITY_DESCRIPTOR;
  err              : DWord;

const
  SE_UNKNOWN_OBJECT_TYPE: DWord = 0;
  SE_FILE_OBJECT   : DWord = 1;
  SE_SERVICE       : DWord = 2;
  SE_PRINTER       : DWord = 3;
  SE_REGISTRY_KEY  : DWord = 4;
  SE_LMSHARE       : DWord = 5;
  SE_KERNEL_OBJECT : DWord = 6;
  SE_WINDOW_OBJECT : DWord = 7;

begin
  hProcess := 0;
  err := 0;
  try
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or GENERIC_READ, False, pid);
    if (hProcess <> 0) then
    begin
      err := GetSecurityInfo(hProcess, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, @pSIDDummy, nil, nil, nil,
        @SecDescriptor);
      if (err = 0) then
      begin
        SID := pSIDDummy;
        //LocalFree(Cardinal(SecDescriptor));
      end;
      CloseHandle(hProcess);
    end;
  except
  end;
  // Successfull if err = 0 AND hProcess <> 0
  Result := (err = 0) and (hProcess <> 0);
end;
Ich übergebe eigentlich gerne var Paramter, damit ich den Rückgabewert zum Überprüfen, ob die Funktion erfolgreich war oder nicht nutzen kann.

Wie würdest du es denn machen?

Muetze1 6. Jul 2007 00:41

Re: Speicher freigeben, der noch gebraucht wird
 
Zitat:

Zitat von Luckie
Ich übergebe eigentlich gerne var Paramter, damit ich den Rückgabewert zum Überprüfen, ob die Funktion erfolgreich war oder nicht nutzen kann.

Ok, aber die Funktion die du aufrufst dürfte doch nichts in der Struktur verändern, wenn der Aufruf fehlschlägt, oder? Ist zumindest im Normalfall so, also warum gibst du nicht einfach direkt den übergebenen Speicher?

Von daher würde ich es so machen:

Delphi-Quellcode:
function GetProcessOwner(const PID: DWord; const SID: PSID): Boolean;
var
  hProcess         : THandle;
  SecDescriptor    : PSECURITY_DESCRIPTOR;
  err              : DWord;

const
  SE_UNKNOWN_OBJECT_TYPE: DWord = 0;
  SE_FILE_OBJECT   : DWord = 1;
  SE_SERVICE       : DWord = 2;
  SE_PRINTER       : DWord = 3;
  SE_REGISTRY_KEY  : DWord = 4;
  SE_LMSHARE       : DWord = 5;
  SE_KERNEL_OBJECT : DWord = 6;
  SE_WINDOW_OBJECT : DWord = 7;

begin
  Result := false;
  try
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or GENERIC_READ, False, pid);
    try
      if (hProcess <> 0) then
      begin
        err := GetSecurityInfo(hProcess, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, @SID, nil, nil, nil, @SecDescriptor);
        try
            // was du hier auch immer noch mit dem SecDescriptor machen willst, tue es hier...

          Result := ( err = 0 ); // am Ende. Wenn irgendwas schiefgeht springt er in finally und diese Zuweisung wird nie ausgeführt...
        finally
          LocalFree(SecDescriptor);
        end;
      end;
    finally
      CloseHandle(hProcess);
    end;
  except
    ; // böses Karma...
  end;
end;
Warum gibst du überhaupt den SecDescriptor an, wenn du ihn nicht nutzt? Dann würde ein NIL dort auch vollkommen reichen. Aber ich gehe mal davon aus, dass du ihn später noch nutzen willst, von daher gebe ich ihn mit frei.

Grundsätzlich programmiere ich solche Funktionen, welche viele Bedingunen haben bis sie zum endgültigen Aufruf kommen, so, dass ich Result auf false setze und bei erfolgreicher Ausführung der Funktion in der tiefen Bedingung kann ich True setzen. Damit ist bei allen anderen Fehlern, Exceptions etc ein False als Result. Damit spare ich mir auch das zuweisen von lokalen Variablen auf einen initialisierten Wert, die dann eh immer zugewiesen werden (siehe hProcess).

So, gute Nacht!

Luckie 6. Jul 2007 09:09

Re: Speicher freigeben, der noch gebraucht wird
 
Also, dass man dort auch nil angeben kann, habe ich nicht gewusst. Geht aber. Und da ich ihn eigentlich gar nicht weiter brauche, gebe ich da jetzt auch nil an und habe keinen Ärger mit dem Speicher. Allerdings den Parametr als const angeben geht nicht, denn dann kann in ihn nichts geschrieben werden und er bleibt leer. ;)

Danke noch mal für deine Hilfe.

Muetze1 6. Jul 2007 10:10

Re: Speicher freigeben, der noch gebraucht wird
 
Zitat:

Zitat von Luckie
Allerdings den Parametr als const angeben geht nicht, denn dann kann in ihn nichts geschrieben werden und er bleibt leer. ;)

Aso, stimmt - da habe ich mich heute morgen "verzeigert". Ich war der Meinung, dass der übergeben Zeiger nicht verändert wird, aber das stimmt nicht. Schliesslich soll genau der Zeiger geändert werden. Da hat C(++) wieder zugeschlagen (const *para bzw. *const para). Und das mit dem NIL habe ich von GetSecurityInfo(), da der Parameter als optional gekennzeichnet ist.

Christian Seehase 6. Jul 2007 13:34

Re: Speicher freigeben, der noch gebraucht wird
 
Moin Michael,

Zitat:

Zitat von Luckie
Allerdings den Parametr als const angeben geht nicht, denn dann kann in ihn nichts geschrieben werden und er bleibt leer. ;-)

C kennt ja keine Var-Parameter, und kann Werte in Parametern zurückgeben, wie, z.B., die Funktion GetSecurityInfo ;-)
Delphi kapselt die Vorgehensweise ja nur.

SirThornberry 6. Jul 2007 14:06

Re: Speicher freigeben, der noch gebraucht wird
 
Zitat:

Zitat von Christian Seehase
...C kennt ja keine Var-Parameter...

Ich hoffe ich hab da was falsch verstanden, denn das c keine var-Parameter kennt ist mir neu.
Code:
void ChangeIt(int &i)
{
  i = 5;
}
[...]
{
  int i = 0;
  ChangeIt(i);
  [...]
}


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

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