Wenn eine Datei oder ein Prozess auf eine andere Datei zugreifen, wird die Veränderung oder das Löschen dieser Datei von Windows blockiert. Dabei liefert Windows nur einen Fehlerbericht, dass der Zugriff auf diese Datei verweigert wird, weil ein anderes Programm darauf zugreift.
Mit dem folgenden Code kann man ermitteln, auf welche Art und Weise auf die besagte Datei zugegriffen wird, welcher Prozess gerade zugreift und auch den Dateipfad des Programms, welcher zugreift.
const // Data für die Art der Ermittlung des Zugriffs
FILE_READ_DATA = $0001; // file & pipe
FILE_LIST_DIRECTORY = $0001; // directory
FILE_WRITE_DATA = $0002; // file & pipe
FILE_ADD_FILE = $0002; // directory
FILE_APPEND_DATA = $0004; // file
FILE_ADD_SUBDIRECTORY = $0004; // directory
FILE_CREATE_PIPE_INSTANCE = $0004; // named pipe
FILE_READ_EA = $0008; // file & directory
FILE_WRITE_EA = $0010; // file & directory
FILE_EXECUTE = $0020; // file
FILE_TRAVERSE = $0020; // directory
FILE_DELETE_CHILD = $0040; // directory
FILE_READ_ATTRIBUTES = $0080; // all
FILE_WRITE_ATTRIBUTES = $0100; // all
FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $1FF;
FILE_GENERIC_READ = STANDARD_RIGHTS_READ or FILE_READ_DATA or FILE_READ_ATTRIBUTES or FILE_READ_EA or SYNCHRONIZE;
FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE or FILE_WRITE_DATA or FILE_WRITE_ATTRIBUTES or FILE_WRITE_EA or
FILE_APPEND_DATA or SYNCHRONIZE;
FILE_GENERIC_EXECUTE = STANDARD_RIGHTS_EXECUTE or FILE_READ_ATTRIBUTES or FILE_EXECUTE or SYNCHRONIZE;
//
function CheckAccessToFile(DesiredAccess: DWORD; const FileName: WideString): Boolean;
const
GenericFileMapping : TGenericMapping = (
GenericRead: FILE_GENERIC_READ;
GenericWrite: FILE_GENERIC_WRITE;
GenericExecute: FILE_GENERIC_EXECUTE;
GenericAll: FILE_ALL_ACCESS
);
var
LastError : DWORD;
LengthNeeded : DWORD;
SecurityDescriptor : PSecurityDescriptor;
ClientToken : THandle;
AccessMask : DWORD;
PrivilegeSet : TPrivilegeSet;
PrivilegeSetLength : DWORD;
GrantedAccess : DWORD;
AccessStatus : BOOL;
begin
Result := False;
LastError := GetLastError;
if not GetFileSecurityW(PWideChar(FileName), OWNER_SECURITY_INFORMATION or
GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION, nil, 0,
LengthNeeded) and (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then
Exit;
SetLastError(LastError);
Inc(LengthNeeded, $1000);
SecurityDescriptor := PSecurityDescriptor(LocalAlloc(LPTR, LengthNeeded));
if not Assigned(SecurityDescriptor) then
Exit;
try
if not GetFileSecurityW(PWideChar(FileName), OWNER_SECURITY_INFORMATION or
GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION,
SecurityDescriptor, LengthNeeded, LengthNeeded) then
Exit;
if not ImpersonateSelf(SecurityImpersonation) then
Exit;
try
if not OpenThreadToken(GetCurrentThread, TOKEN_QUERY or
TOKEN_IMPERSONATE or TOKEN_DUPLICATE, False, ClientToken) then
Exit;
try
AccessMask := DesiredAccess;
MapGenericMask(AccessMask, GenericFileMapping);
PrivilegeSetLength := SizeOf(TPrivilegeSet);
if AccessCheck(SecurityDescriptor, ClientToken, AccessMask,
GenericFileMapping, PrivilegeSet, PrivilegeSetLength, GrantedAccess,
AccessStatus) then
Result := AccessStatus;
finally
CloseHandle(ClientToken);
end;
finally
RevertToSelf;
end;
finally
LocalFree(HLOCAL(SecurityDescriptor));
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
ShowMessage(BoolToStr(CheckAccessToFile(GENERIC_WRITE, // check for generic write access
OpenDialog1.FileName), True) +
': ' +
SysErrorMessage(GetLastError));
end;
Keine Kommentare:
Kommentar veröffentlichen