Registriert seit: 3. Sep 2004
434 Beiträge
Delphi 10.4 Sydney
|
[JwSCL] Exception bei TJwSecurityDescriptorDialog.SetSecurity
19. Okt 2015, 11:41
Hallo zusammen,
obwohl ja die JwSCL insgesamt einfach bedienbar ist -wenn man mal den Einstieg geschafft hat- bin ich hier an der Stelle ein wenig festgefahren und weiß nicht, ob es an mangelndem Wissen scheitert, oder ein Fehler in der JwSCL Unit an sich vorhanden ist.
Folgender Sachverhalt:
Wenn ich mit dem ACL-Editor einen neuen SecurityDescriptor bearbeite, habe ich kein Problem.
Wenn ich mit dem ACL-Editor einen SecurityDescriptor ("SD") bearbeite, der geladen wurde (also ein neuer SD, der als Parameter einen Plain-Text-Wert übergeben bekommt) kommt eine Exception, sobald ich den ACL-Editor mit "Ok" beende.
Dazu muss man wissen:
-Der "geladene" SD ist generell gültig; man kann damit arbeiten und im ACL-Editor werden die geladenen Benutzer & Rechte auch korrekt angezeigt; daran sollte es also nicht liegen.
-Im folgenden Beispiel wird der SD mit dem Text "" geladen (also leerer Text, für dieses Beispiel hier). Dies ist meines Wissens ebenfalls gültig und sollte somit nicht die Ursache für das Problem sein.
-In der angehängten Funktion "TJwSecurityDescriptorDialog.SetSecurity" gibt es an der Stelle "MergeSD.Free" die Exception
Zitat:
---------------------------
Benachrichtigung über Debugger- Exception
---------------------------
Im Projekt Beispiel.exe ist eine Exception der Klasse EInvalidPointer mit der Meldung 'Ungültige Zeigeroperation' aufgetreten.
---------------------------
Anhalten Fortsetzen Hilfe
---------------------------
Das Programm ist nun richtig hart abgestürzt und lässt sich auch nicht mehr fortsetzen, da nach jedem "F9" nur noch kommt:
Zitat:
---------------------------
Benachrichtigung über Debugger-Problem
---------------------------
In Projekt ...\Beispiel.exe trat ein Problem mit folgender Meldung auf: ' access violation at 0x00000000: read of address 0x00000000'. Prozess angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK
---------------------------
Als Laie vermute ich nun mal, dass es sich hier um ein "Multi-Free"-Problem handelt. Nachdem der Editor mit "Ok" geschlossen werden soll, werden ja alle GUI-Einstellungen auf die Variable übertragen, und die "Erlauben" und "Verweigern"-Listen zu einer kombiniert. Hier scheint das Problem zu sein, dass die Variablen "SD" und "MergeSD" auf die selbe (nicht die gleiche!) DACL im Arbeitsspeicher zugreifen. Wird nun die SD-Variable freigegeben, wird die DACL im RAM gelöscht, und kann nicht nochmal gelöscht werden, wenn die MergeSD freigegeben wird.
Zitat:
In der JwSCL- Unit, direkt vor "SD.Free":
Wert SD:
(nil, nil, nil, True, (JwsclDescriptor.TJwSecurityDescriptor.hashCode,$5 301D4), True, True, False, False, False, True, False, False, [sdcDaclPresent,sdcDaclAutoInheritReq], $9B14FD0, $9E3CE10, True, aclpUnprotected, aclpUnprotected, 0)
Wert MergedSD
(nil, $2B2BDA0, $2B2BE60, True, (JwsclDescriptor.TJwSecurityDescriptor.hashCode,$5 301D4), True, True, False, False, False, False, False, False, [sdcDaclAutoInheritReq], $9B14FD0, $9E3D108, True, aclpUnprotected, aclpUnprotected, 0)
Hier sieht man, dass zumindest $9B14FD0 in beiden Objekten verwendet wird, was die DACL (fDACL: TJwDAccessControlList) ist. Wer jetzt hier der eigentliche Owner ist oder sein sollte, kann ich nicht sagen. Hat das seine Richtigkeit?
-Wenn ich übrigens bei "SD.Free; MergedSD.Free;" try..except drum mache, kann ich das Programm zumindest fortsetzen.
-Der ACLEditor schaltet mit dem bearbeiten bei dem SD immer die Variablen "OwnOwner" und "OwnPrimaryGroup" selbständig auf True. Ich kann nicht einschätzen in wie weit das mit dem Problem zusammenhängt, und was man dagegen tun kann/soll. Die Variablen werden ja auch mit dem "neu erzeugtem" SD auf True gesetzt, und dort gibt es das Problem nicht.
-Ist das schlimm, wenn ich als behelf einfach die try..except Lösung verwende? Klar, das ist keine saubere Lösung, aber bevor mein Programm gar nicht geht und ich hier nicht weiterkomme ...?
Code:
"Neuer" SD, keine Probleme:
SD-Variable vor dem ACL Editor:
(nil, $2A3ABA0, $2A3ABA0, False, (JwsclDescriptor.TJwSecurityDescriptor.hashCode,$5301D4), False, False, False, False, False, False, False, False, [], $2A8AD60, $9B98B70, True, aclpUnprotected, aclpUnprotected, 0)
SD-Variable nach dem ACL-Editor:
(nil, $2A3C3A0, $2A3E410, False, (JwsclDescriptor.TJwSecurityDescriptor.hashCode,$5301D4), True, True, False, False, False, False, False, False, [], $2A8AD60, $9B98B70, True, aclpUnprotected, aclpUnprotected, 0)
"Geladener" SD, Problem:
SD-Variable vor dem ACL Editor:
(nil, $27ABB30, $27ABB90, False, (JwsclDescriptor.TJwSecurityDescriptor.hashCode,$5301D4), False, False, False, False, False, False, False, False, [], nil, $9918B70, True, aclpUnprotected, aclpUnprotected, 0)
SD-Variable nach dem ACL-Editor:
(nil, $27AAE70, $27AC400, False, (JwsclDescriptor.TJwSecurityDescriptor.hashCode,$5301D4), True, True, False, False, False, False, False, False, [], $99A6698, $9918B70, True, aclpUnprotected, aclpUnprotected, 0)
Delphi-Quellcode:
procedure TfrmZugriffsrechte.Button1Click(Sender: TObject);
var
sd: TjwSecurityDescriptor;
ACLEditor : TJwSecurityDescriptorDialog;
begin
// Funktioniert ohne Probleme
sd := TjwSecurityDescriptor.Create;
// Problem mit ACLEditor
sd := TjwSecurityDescriptor.Create('');
with sd do begin
PrimaryGroup := JwNullSID;
Owner := JwNullSID;
OwnDACL := False;
OwnOwner := False;
OwnPrimaryGroup := False;
DACLInherited := False;
AuditInherited := False;
Control := [];
end;
// Editor erzeugen
ACLEditor := TJwSecurityDescriptorDialog.Create(GetActiveWindow);
// Zum testen in dieser Demo erstmal Alles freischalten (Erweitert-Button, alle Karteikarten, etc.)
ACLEditor.Flags := [sdfEditOwner];
// sdfAdvanced, sdfEditDacl, sdfEditEffective, sdfNoAdditionalPermission, sdfEditSacl
// Caption des Dialogs, bzw. der "Objektes", für das gerade die Sicherheit verändert wird. Nehmt zur Not euren Programmnamen oder so...
ACLEditor.ObjectName := Caption;
ACLEditor.ServerName := '';
try
try
ACLEditor.Mapping := TMyMapping;
ACLEditor.SecurityDescriptor.Assign(sd);
ACLEditor.OnSetSecurity := OnSetSecurity;
// Editor anzeigen. Das Programm pausiert, bis der Dialog geschlossen wird.
// Wenn der Dialog mit "Ok" beendet wurde:
if ACLEditor.ShowModal then
begin
Sleep(0); // wenn wir hier ankommen, alles Ok!
// Den kompletten SD wieder in unsere Variable zurückkopieren
sd.Assign(ACLEditor.SecurityDescriptor);
end;
except
sleep(0); // Keine Chance, das Problem hierüber zu behandeln!
end;
finally
try
ACLEditor.Free;
except
sleep(0); // Keine Chance, das Problem hierüber zu behandeln!
end;
end;
end;
procedure TfrmZugriffsrechte.OnSetSecurity(Sender: TJwSecurityDescriptorDialog;
SecurityType: TJwSecurityInformationFlagSet;
SecurityDialogFlags: TJwSecurityDialogFlags;
SecurityResetType: TJwSecurityResetTypes;
Settings: TJwSecurityDescriptorControlSet; NewSecurityDescriptor,
MergedSecurityDescriptor: TJwSecurityDescriptor; var bSuccess: boolean);
begin
bSuccess := true;
end;
Delphi-Quellcode:
function TJwSecurityDescriptorDialog.SetSecurity(
SecurityInformation: SECURITY_INFORMATION;
pSecurityDescriptor: PSECURITY_DESCRIPTOR): HRESULT;
var
secInfo: TJwSecurityInformationFlagSet;
secControl: TJwSecurityDescriptorControlSet;
MergedSD, SD: TJwSecurityDescriptor;
SecurityResetTypes: TJwSecurityResetTypes;
secInfoEx: TJwSecurityDialogFlags;
bSuccess: boolean;
begin
secInfo := TJwEnumMap.ConvertSecurityInformation(
SecurityInformation);
secControl := TJwEnumMap.ConvertSecurityControl(
pSecurityDescriptor.Control);
secInfoEx := TJwEnumMap.ConvertFlags(SecurityInformation);
//create new SD that contains the changed security information
SD := TJwSecurityDescriptor.Create(pSecurityDescriptor);
//create new SD that contains the default SD and will receive the new one
MergedSD := TJwSecurityDescriptor.Create(fSD);
//replace Owner
if siOwnerSecurityInformation in secInfo then
begin
MergedSD.OwnOwner := True;
MergedSD.Owner := SD.Owner; //simply copy owner
end;
//replace group
if siGroupSecurityInformation in secInfo then
begin
MergedSD.OwnPrimaryGroup := True;
MergedSD.PrimaryGroup := SD.PrimaryGroup; //simply copy group
end;
//replace DACL
if siDaclSecurityInformation in secInfo then
begin
MergedSD.OwnDACL := True;
MergedSD.DACL := SD.DACL; //simply copy DACL
end;
//replace SACL
if siSaclSecurityInformation in secInfo then
begin
MergedSD.SACL := SD.SACL; //simply copy SACL
end;
if siDaclSecurityInformation in secInfo then
begin
//protect DACL from inheritance
if sdcDaclProtected in SD.Control then
begin
Include(secInfo, siProtectedDaclSecurityInformation);
MergedSD.Control := MergedSD.Control + [sdcDaclProtected];
end;
//unprotect DACL so inheritance can flow
if sdcDaclAutoInheritReq in SD.Control then
begin
Include(secInfo, siUnprotectedDaclSecurityInformation);
MergedSD.Control := MergedSD.Control + [sdcDaclAutoInheritReq];
end;
end;
if siSaclSecurityInformation in secInfo then
begin
//protect SACL from inheritance
if sdcSaclProtected in SD.Control then
begin
Include(secInfo, siProtectedSaclSecurityInformation);
MergedSD.Control := MergedSD.Control + [sdcSaclProtected];
end;
//unprotect SACL so inheritance can flow
if sdcSaclAutoInheritReq in SD.Control then
begin
Include(secInfo, siUnprotectedSaclSecurityInformation);
MergedSD.Control := MergedSD.Control + [sdcSaclAutoInheritReq];
end;
end;
//set reset state, so user can easily see whether he must reset all children
SecurityResetTypes := [];
if (SecurityInformation and SI_OWNER_RECURSE = SI_OWNER_RECURSE) then
Include(SecurityResetTypes, srtOwner);
if (SecurityInformation and SI_RESET_DACL_TREE = SI_RESET_DACL_TREE) then
Include(SecurityResetTypes, srtDacl);
if (SecurityInformation and SI_RESET_SACL_TREE = SI_RESET_SACL_TREE) then
Include(SecurityResetTypes, srtSacl);
bSuccess := False;
try
if Assigned(fOnSetSecurity) then
fOnSetSecurity(Self, secInfo, secInfoEx,
SecurityResetTypes,
SD.Control, SD, MergedSD, bSuccess);
if bSuccess then
fSD.Assign(MergedSD);
finally
// try
SD.Free;
MergedSD.Free; // <-- hier gibt es die eigentliche Exception
// except end;
end;
if bSuccess then
Result := S_OK
else
Result := S_FALSE;
end;
|