![]() |
TreeResetNamedSecurityInfoW-Aufrufproblem
Hi,
Tja, also das setzten von Rechten unter XP ist nicht so ganz trivial, insbesondere wenn gleich ein ganzer Baum bearbeitet werden soll. Also warum nicht die API nutzen. Leider bekomme ich beim Aufruf immer "Falscher Parameter !". Hier mal ein bischen Code dazu:
Delphi-Quellcode:
NewOwner,NewGroup,NewDACL,NewSACL werden vorher entsprechend befüllt, ein Aufruf von SetNamedSecurityInfoW mit den gleichen Variablen funktioniert ohne Probleme.
procedure DoTreeProgress(
pObjectName: LPWSTR; // name of object just processed Status: DWORD; // status of operation on object var pInvokeSetting: PPROG_INVOKE_SETTING; // Never, always, Args: PVOID; // Caller specific data SecuritySet: BOOL );Stdcall; begin if (Args <> NIL) then begin if Assigned(TFileSecurityInformation(Args).fOnProgress) then TFileSecurityInformation(args).fOnProgress(PObjectName,SecuritySet); end; end; var NewSI : SECURITY_INFORMATION; NewOwner,NewGroup : PSID; NewDACL,NewSACL : PACL; CallBack : FN_PROGRESS; : CallBack := DoTreeProgress; dErr := TreeResetNamedSecurityInfoW(PWidechar(ffilename), SE_FILE_OBJECT, NewSI, NewOwner, NewGroup, NewDACL, NewSACL, FALSE, CallBack, ProgressInvokeNever,NIL); if (dErr <> ERROR_SUCCESS) then DoError(dErr); : ProgressInvokeNever ist eine Konstante. Der Link zur API-Funktion (MSDN): ![]() Da zwischen SetNamedSecurityInfoW und TreeResetNamedSecurityInfoW nur die letzten 4 Parameter unterschiedlich sind, nehme ich an das einer nicht passt. Welcher ist nun falsch und wie müsste er richtig aussehen ? |
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
Setz vor die Callback-Funktionsparameter mal ein "@". Das muss, meiner Meinung nach, ein Zeiger auf die Callback-Funktion sein.
|
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
Habs grad mit @ ausprobiert. Leider kommt der Fehler nach wie vor.
|
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
Ich hab noch mal verschiedene Varianten der Übergabe der CallBack-Funktion ausprobiert (mit Cast hier, Zeiger da usw.)..leider ohne Erfolg.
Auch die API-Umsetzung (Jedi-API) hab ich gecheckt, die stimmt. Jemand noch ne Idee ? (EDIT) Hab noch einen C++-Source aufgetrieben. Allerdings sagt der mir nicht viel.
Code:
dwErr = this->pfnTreeResetNamedSecurityInfo(m_ObjectName, this->SeObjectType, psi, SidOwner, SidGroup, NewDAcl,
NewSAcl, this->KeepExplicit, reinterpret_cast<FN_PROGRESS>(reinterpret_cast<void *>(TreeCallBackFunc)), ProgressInvokeEveryObject, reinterpret_cast<void *>(this)); |
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
Noch keiner diese API-Funktion benutzt ?
|
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
*mal nach oben schieben*
Keiner eine Idee ? |
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
Ich muss mir das naher mal genauer ansehen, aber "var pInvokeSetting: PPROG_INVOKE_SETTING;" sieht verdaechtig aus.
|
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
Guten Morgen,
mit den gegebenen Informationen scheint mir der letzte Parameter von TreeResetNamedSecurityInfo() der einzige zu sein, der als ungültig gemeldet werden kann. Nur die letzten vier Parameter sind laut Ghostwalker verdächtig, KeepExplicit ist über jeden Zweifel erhaben, die Adresse der CallBack-Funktion kann irgendeine Adresse sein und ProgressInvokeSetting ist eine einfache Konstante. Bleibt der untypisierte Zeiger auf Args. Im gezeigten C++-Code wird ja ein untypisierter Zeiger auf ein Objekt (this) übergeben. Wahrscheinlich darf dieser Zeiger nie NULL sein. Kann es leider nicht testen. Freundliche Grüße |
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
Delphi-Quellcode:
Ist ffilename string oder WideString? Besser WideString.
procedure DoTreeProgress(
pObjectName: LPWSTR; // name of object just processed Status: DWORD; // status of operation on object var pInvokeSetting: PROG_INVOKE_SETTING; // Never, always, Args: PVOID; // Caller specific data SecuritySet: BOOL );Stdcall; var NewSI : SECURITY_INFORMATION; NewOwner,NewGroup : SID; NewDACL,NewSACL : ACL; CallBack : FN_PROGRESS; dErr := TreeResetNamedSecurityInfoW(PWidechar(ffilename), SE_FILE_OBJECT, NewSI, @NewOwner, @NewGroup, @NewDACL, @NewSACL, FALSE, NIL, ProgressInvokeNever,NIL); Ich habe oben mal meine Vermutungen eingesetzt. NewOwner, NewGroup, NewDACL und NewSACL sind vermutlich ausgefuellte Strukturen. Es koenne aber auch Zeiger sein, die andere Funktinoen angeliefert haben, dann ist meine Veraenderung mit @ falsch. Die Dokumentation sagt das man NIL fuer den Callback angeben soll, wenn man ProgressInvokeNever benutzt. Wie vermutet ist der Parameter pInvokeSetting falsch deklariert. var macht bereits die Indirektion. Es muss also der Struktur-Typ nicht der Zeiger-auf-Struktur-Typ gewaehlt werden. |
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
You're using ProgressInvokeNever in which case you should probably pass nil for the fnProgress parameter (MSDN: If no progress function is to be used, set this parameter to NULL). What variable type is ffilename? If it's a string try PWideChar(WideString(ffilename)).
I think Luckie is right about the @: // // Progress Function: // Caller of tree operation implements this Progress function, then // passes its function pointer to tree operation. // Tree operation invokes Progress function to provide progress and error // information to the caller during the potentially long execution // of the tree operation. Tree operation provides the name of the object // last processed and the error status of the operation on that object. // Tree operation also passes the current InvokeSetting value. // Caller may change the InvokeSetting value, for example, from "Always" // to "Only On Error." // Edit: Robert posted while I was writing mine, missed that sorry |
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
:wall:
Da ich absolut keine Plan mehr habe, was noch falsch sein könnte, poste ich mal die komplette Routine
Delphi-Quellcode:
Die Progress-Routine hab ich, wie Robert es gesagt hat, angepasst
function TFileSecurityInformation.SetSecurity(
SecurityInformation: SECURITY_INFORMATION; pSecurityDescriptor: PSECURITY_DESCRIPTOR): HRESULT; var dErr : DWORD; aclPresent : BOOL; aclDefault : BOOL; SDRevision : DWORD; psd : SECURITY_DESCRIPTOR_CONTROL; NewSecurityDescriptor : PSECURITY_DESCRIPTOR; os : TOsVersion; AbsDACL,AbsSACL,NewDACL,NewSACL : PACL; AbsGroup,AbsOwner,NewGroup,NewOwner :PSID; dwSizes : array[0..4] of DWORD; nsdRel : PSECURITY_DESCRIPTOR; NewSI : SECURITY_INFORMATION; procedure MakeControlBits; begin aclPresent := FALSE; aclDefault := FALSE; SDRevision := 0; psd := 0; if not (GetSecurityDescriptorControl(pSecurityDescriptor,psd,SDRevision)) then DoError(GetLastError); if ((Securityinformation and DACL_SECURITY_INFORMATION) = DACL_SECURITY_INFORMATION) then begin if ((psd and SE_DACL_PROTECTED) = SE_DACL_PROTECTED) then begin SecurityInformation := SecurityInformation or PROTECTED_DACL_SECURITY_INFORMATION; NewSI := NewSI or PROTECTED_DACL_SECURITY_INFORMATION; if not (SetSecurityDescriptorControl(NewSecurityDescriptor,SE_DACL_PROTECTED,SE_DACL_PROTECTED)) then DoError(GetLastError); end; if ((psd and SE_DACL_AUTO_INHERIT_REQ) = SE_DACL_AUTO_INHERIT_REQ) then begin SecurityInformation := SecurityInformation or UNPROTECTED_DACL_SECURITY_INFORMATION; NewSI := NewSI or UNPROTECTED_DACL_SECURITY_INFORMATION; if not (SetSecurityDescriptorControl(NewSecurityDescriptor,SE_DACL_AUTO_INHERIT_REQ,SE_DACL_AUTO_INHERIT_REQ)) then DoError(GetLastError); end; end; if ((SecurityInformation and SACL_SECURITY_INFORMATION) = SACL_SECURITY_INFORMATION) then begin if ((psd and SE_SACL_PROTECTED) = SE_SACL_PROTECTED) then begin SecurityInformation := SecurityInformation or PROTECTED_SACL_SECURITY_INFORMATION; NewSI := NewSI or PROTECTED_SACL_SECURITY_INFORMATION; if not (SetSecurityDescriptorControl(NewSecurityDescriptor,SE_SACL_PROTECTED,SE_SACL_PROTECTED)) then DoError(GetLastError); end; if ((psd and SE_SACL_AUTO_INHERIT_REQ) = SE_SACL_AUTO_INHERIT_REQ) then begin SecurityInformation := SecurityInformation or UNPROTECTED_SACL_SECURITY_INFORMATION; NewSI := NewSI or UNPROTECTED_SACL_SECURITY_INFORMATION; if not (SetSecurityDescriptorControl(NewSecurityDescriptor,SE_SACL_AUTO_INHERIT_REQ,SE_SACL_AUTO_INHERIT_REQ)) then DoError(GetLastError); end; end; end; begin //some checks if user can change anything os := GetWindowsVersion; if (pSecurityDescriptor = NIL) then begin RESULT := E_POINTER; EXIT; end; if (do_SI_READONLY in foptions) then begin RESULT := E_ACCESSDENIED; EXIT; end; NewSI := 0; nsdRel := NIL; //ok..user can //We first get the "old" Descriptor for merging the new values to it dERR := GetNamedSecurityInfow(pwidechar(ffilename), SE_FILE_OBJECT, SecurityInformation, NIL, NIL, NIL, NIL, nsdRel); //Make a absolut Descriptor AbsDACL := NIL; AbsSACL := NIL; AbsOwner := NIL; AbsGroup := NIL; NewDACL := NIL; NewSACL := NIL; NewOwner := NIL; NewGroup := NIL; NewSecurityDescriptor := NIL; fillchar(dwsizes,sizeof(dwsizes),0); //First we need the sizes for allocations MakeAbsoluteSD(nsdREL, NIL, dwSizes[0], NIL, dwSizes[1], nil, dwSizes[2], nil, dwSizes[3], nil, dwSizes[4]); GetMem(NewSecurityDescriptor,dwSizes[0]); GetMem(AbsDACL,dwSizes[1]); GetMem(AbsSACL,dwSizes[2]); GetMem(AbsOwner,dwSizes[3]); GetMem(AbsGroup,dwSizes[4]); //Now translate from self realtiv to absolute if not (MakeAbsoluteSD(nsdRel, NewSecurityDescriptor, dwSizes[0], AbsDACL, dwSizes[1], AbsSACL, dwSizes[2], AbsOwner, dwSizes[3], AbsGroup, dwSizes[4])) then DoError(GetLastError); LocalFree(Cardinal(nsdrel)); //Make a new SD //Set the corresponding Controlbits MakeControlBits; //Get the new information from the given SD and merge them if ((SecurityInformation and DACL_SECURITY_INFORMATION)=DACL_SECURITY_INFORMATION) then begin if not (GetSecurityDescriptorDACL(pSecurityDescriptor,aclPresent,NewDacl,aclDefault)) then DoError(GetLastError); if not (SetSecurityDescriptorDACL(NewSecurityDescriptor,aclPresent,NewDACL,acldefault)) then DoError(GetLastError); newSI := NewSI or DACL_SECURITY_INFORMATION; end; if ((SecurityInformation and SACL_SECURITY_INFORMATION)=SACL_SECURITY_INFORMATION) then begin if not (GetSecurityDescriptorSACL(pSecurityDescriptor,aclPresent,NewSacl,aclDefault)) then DoError(GetLastError); if not (SetSecurityDescriptorSACL(NewSecurityDescriptor,aclPresent,NewSACL,acldefault)) then DoError(GetLastError); newSI := NewSI or SACL_SECURITY_INFORMATION; end; if ((SecurityInformation and GROUP_SECURITY_INFORMATION) = GROUP_SECURITY_INFORMATION) then begin if not (GetSecurityDescriptorGroup(pSecurityDescriptor,NewGroup,@aclDefault)) then DoError(GetLastError); if not (SetSecurityDescriptorGroup(NewSecurityDescriptor,NewGroup,aclDefault)) then DoError(GetLastError); newSI := NewSI or GROUP_SECURITY_INFORMATION; end; if ((SecurityInformation and OWNER_SECURITY_INFORMATION) = OWNER_SECURITY_INFORMATION) then begin if not (GetSecurityDescriptorOwner(pSecurityDescriptor,NewOwner,@aclDefault)) then DoError(GetLastError); if not (SetSecurityDescriptorOwner(NewSecurityDescriptor,NewOwner,aclDefault)) then DoError(GetLastError); newSI := NewSI or OWNER_SECURITY_INFORMATION; end; //Check if we need to recurse throug a tree if (((SecurityInformation AND SI_OWNER_RECURSE) = SI_OWNER_RECURSE) or ((SecurityInformation AND SI_RESET_DACL_TREE) = SI_RESET_DACL_TREE) or ((SecurityInformation AND SI_RESET_SACL_TREE) = SI_RESET_SACL_TREE)) AND fIsDir then begin //For new Systems use the appropriated API-Calls if (os = ovXP) or (os = ov2003) or (os = ovVista) then begin dErr := TreeResetNamedSecurityInfoW(Pwidechar(ffilename), SE_FILE_OBJECT, NewSI, NewOwner, NewGroup, NewDACL, NewSACL, FALSE, @DoTreeProgress, ProgressInvokeEveryObject, SELF); if (dErr <> ERROR_SUCCESS) then DoError(dErr); end else begin //Use alternativ Method for 2000, because no API available end; end else begin dErr := SetNamedSecurityInfoW(Pwidechar(ffilename),SE_FILE_OBJECT,SecurityInformation,NewOwner,NewGroup,NewDACL,NewSACL); end; FreeMem(NewSecurityDescriptor,dwSizes[0]); FreeMem(AbsDACL,dwSizes[1]); FreeMem(AbsSACL,dwSizes[2]); FreeMem(AbsOwner,dwSizes[3]); FreeMem(AbsOwner,dwSizes[4]); if (dErr = ERROR_SUCCESS) then begin result := S_OK; fchanges := TRUE; end else result := E_FAIL; end;
Delphi-Quellcode:
ffilename ist natürlich vom Typ Widestringprocedure DoTreeProgress( pObjectName: LPWSTR; // name of object just processed Status: DWORD; // status of operation on object var pInvokeSetting: PROG_INVOKE_SETTING; // Never, always, Args: PVOID; // Caller specific data SecuritySet: BOOL );Stdcall; In der Zwischenzeit hab ich so ziemlich alle Varianten des Aufrufs durch. Aber egal was ich bei Callback und den InvokeSettings und dem letzten Parameter angebe, ich bekomme immer "falscher Parameter" (87) zurück. Ich bin echt am Verzweifeln. |
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
Just be to be sure, why not change this line
NewSI := NewSI or PROTECTED_DACL_SECURITY_INFORMATION; to NewSI := PROTECTED_DACL_SECURITY_INFORMATION; because NewSi has not been given a value yet... You're passing SELF as the Args parameter, are you doing something with this in the callback? If not, just pass nil. Do you get the same error when using nil and ProgressInvokeNever? |
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
I init the NewSI with 0, because i've to check, witch information the user has changed :)
It makes no sense, to include PROTECTED_DACL_SECURITY_INFORMATION if the user has not changed the DACL :) In my test i don't use this last parameter (Self). It makes no difference if i pass nil or self to it. I tried the NIL/ProgressInvokeNever combination, but the error is the same in this case. i also checked the conversion of the call in the jwaaclapi-unit, and, comparing to MSDN, it seems to be right. |
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
@NewSi, I meant the first time, NewSi is either nil or 0, 0 and PROTECTED_DACL_SECURITY_INFORMATION = PROTECTED_DACL_SECURITY_INFORMATION :gruebel:
Yes Jedi conversion seems correct (my version is v1.10 2006/01/27 21:48:11) |
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
@NewSI
Yes, but only, if the given SecurityInformation contains DACL_SECURITY_INFORMATION :) It's senseless to protect something that is never given :) |
Re: TreeResetNamedSecurityInfoW-Aufrufproblem
Strike :) Problem gelöst.
Ursache war ein falsch gesetztes Flag bei den SecurityInformations. Der Fehler lag genau in der Routine MakeControlBits, und dieser Fehler ist auch in meiner C++-Vorlage. Jetzt sieht die Routine wie folgt aus:
Delphi-Quellcode:
Zur Optimierung hab ich NewSI noch rausgeschmissen und dafür SecurityInformation vor dem Aufruf
procedure MakeControlBits;
begin aclPresent := False; aclDefault := False; SDRevision := 0; psd := 0; if not (GetSecurityDescriptorControl(pSecurityDescriptor, psd, SDRevision)) then DoError(GetLastError); if ((SecurityInformation and DACL_SECURITY_INFORMATION) = DACL_SECURITY_INFORMATION) then begin if ((psd and SE_DACL_PROTECTED) = SE_DACL_PROTECTED) then begin SecurityInformation := SecurityInformation or PROTECTED_DACL_SECURITY_INFORMATION; if not (SetSecurityDescriptorControl(NewSecurityDescriptor, SE_DACL_PROTECTED, SE_DACL_PROTECTED)) then DoError(GetLastError); end else begin if ((psd and SE_DACL_AUTO_INHERIT_REQ) = SE_DACL_AUTO_INHERIT_REQ) then begin SecurityInformation := SecurityInformation or UNPROTECTED_DACL_SECURITY_INFORMATION; if not (SetSecurityDescriptorControl(NewSecurityDescriptor, SE_DACL_AUTO_INHERIT_REQ, SE_DACL_AUTO_INHERIT_REQ)) then DoError(GetLastError); end; end; end; if ((SecurityInformation and SACL_SECURITY_INFORMATION) = SACL_SECURITY_INFORMATION) then begin if ((psd and SE_SACL_PROTECTED) = SE_SACL_PROTECTED) then begin SecurityInformation := SecurityInformation or PROTECTED_SACL_SECURITY_INFORMATION; if not (SetSecurityDescriptorControl(NewSecurityDescriptor, SE_SACL_PROTECTED, SE_SACL_PROTECTED)) then DoError(GetLastError); end else begin if ((psd and SE_SACL_AUTO_INHERIT_REQ) = SE_SACL_AUTO_INHERIT_REQ) then begin SecurityInformation := SecurityInformation or UNPROTECTED_SACL_SECURITY_INFORMATION; if not (SetSecurityDescriptorControl(NewSecurityDescriptor, SE_SACL_AUTO_INHERIT_REQ, SE_SACL_AUTO_INHERIT_REQ)) then DoError(GetLastError); end; end; end; end; noch korregiert:
Delphi-Quellcode:
Jetzt funktioniert das ganze. Sogar die Callback-Routine wird aufgerufen.
SecurityInformation := SecurityInformation and not (SI_OWNER_RECURSE or SI_RESET_DACL_TREE or SI_RESET_SACL_TREE);
dErr := TreeResetNamedSecurityInfoW(pwidechar(ffilename), SE_FILE_OBJECT, SecurityInformation, NewOwner, NewGroup, NewDACL, NewSACL, True, @DoTreeProgress, ProgressInvokeEveryObject, SELF); Danke an alle die hier mitgeholfen haben. Thanks to all they helped here :) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:43 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