Author: Marin Atanasov
I saw an article that helps setting NTFS security on file or folder. There are many
problems with different NTFS (NT4, NT2000, XP) especially with inheritance. The
code I am posting is too long, but works fine.
Answer:
Some constants and type definitions are copied from JCL, some from Microsoft C++
headers, but unit doesn't need of any additional code to be compiled. Try it on
your own risk. There are additional functions that can help: IsNT, IsNT4, IsAdmin,
etc. Some constants are not used.
1 unit NTSecurityU;
2
3 interface
4 uses Windows, AclApi, AccCtrl;
5
6 const
7
8 SECURITY_NULL_SID_AUTHORITY: _SID_IDENTIFIER_AUTHORITY = (Value: (0, 0, 0, 0, 0,
9 0));
10 SECURITY_WORLD_SID_AUTHORITY: _SID_IDENTIFIER_AUTHORITY = (Value: (0, 0, 0, 0, 0,
11 1));
12 SECURITY_LOCAL_SID_AUTHORITY: _SID_IDENTIFIER_AUTHORITY = (Value: (0, 0, 0, 0, 0,
13 2));
14 SECURITY_CREATOR_SID_AUTHORITY: _SID_IDENTIFIER_AUTHORITY = (Value: (0, 0, 0, 0,
15 0,
16 3));
17 SECURITY_NON_UNIQUE_AUTHORITY: _SID_IDENTIFIER_AUTHORITY = (Value: (0, 0, 0, 0, 0,
18 4));
19 SECURITY_NT_AUTHORITY: _SID_IDENTIFIER_AUTHORITY = (Value: (0, 0, 0, 0, 0, 5));
20
21 SECURITY_WORLD_RID: CARDINAL = $00000000;
22 SECURITY_BUILTIN_DOMAIN_RID: CARDINAL = $00000020;
23 DOMAIN_ALIAS_RID_ADMINS: CARDINAL = $00000220;
24 DOMAIN_ALIAS_RID_USERS: CARDINAL = $00000221;
25 DOMAIN_ALIAS_RID_GUESTS: CARDINAL = $00000222;
26
27 STANDARD_RIGHTS_ALL: CARDINAL = $001F0000;
28 ACL_REVISION: CARDINAL = 2; // current revision;
29
30 const
31 ACCESS_MIN_MS_ACE_TYPE = ($0);
32 {$EXTERNALSYM ACCESS_MIN_MS_ACE_TYPE}
33 ACCESS_ALLOWED_ACE_TYPE = ($0);
34 {$EXTERNALSYM ACCESS_ALLOWED_ACE_TYPE}
35 ACCESS_DENIED_ACE_TYPE = ($1);
36 {$EXTERNALSYM ACCESS_DENIED_ACE_TYPE}
37 SYSTEM_AUDIT_ACE_TYPE = ($2);
38 {$EXTERNALSYM SYSTEM_AUDIT_ACE_TYPE}
39 SYSTEM_ALARM_ACE_TYPE = ($3);
40 {$EXTERNALSYM SYSTEM_ALARM_ACE_TYPE}
41 ACCESS_MAX_MS_V2_ACE_TYPE = ($3);
42 {$EXTERNALSYM ACCESS_MAX_MS_V2_ACE_TYPE}
43
44 ACCESS_ALLOWED_COMPOUND_ACE_TYPE = ($4);
45 {$EXTERNALSYM ACCESS_ALLOWED_COMPOUND_ACE_TYPE}
46 ACCESS_MAX_MS_V3_ACE_TYPE = ($4);
47 {$EXTERNALSYM ACCESS_MAX_MS_V3_ACE_TYPE}
48
49 ACCESS_MIN_MS_OBJECT_ACE_TYPE = ($5);
50 {$EXTERNALSYM ACCESS_MIN_MS_OBJECT_ACE_TYPE}
51 ACCESS_ALLOWED_OBJECT_ACE_TYPE = ($5);
52 {$EXTERNALSYM ACCESS_ALLOWED_OBJECT_ACE_TYPE}
53 ACCESS_DENIED_OBJECT_ACE_TYPE = ($6);
54 {$EXTERNALSYM ACCESS_DENIED_OBJECT_ACE_TYPE}
55 SYSTEM_AUDIT_OBJECT_ACE_TYPE = ($7);
56 {$EXTERNALSYM SYSTEM_AUDIT_OBJECT_ACE_TYPE}
57 SYSTEM_ALARM_OBJECT_ACE_TYPE = ($8);
58 {$EXTERNALSYM SYSTEM_ALARM_OBJECT_ACE_TYPE}
59 ACCESS_MAX_MS_OBJECT_ACE_TYPE = ($8);
60 {$EXTERNALSYM ACCESS_MAX_MS_OBJECT_ACE_TYPE}
61
62 ACCESS_MAX_MS_V4_ACE_TYPE = ($8);
63 {$EXTERNALSYM ACCESS_MAX_MS_V4_ACE_TYPE}
64 ACCESS_MAX_MS_ACE_TYPE = ($8);
65 {$EXTERNALSYM ACCESS_MAX_MS_ACE_TYPE}
66
67 ACCESS_ALLOWED_CALLBACK_ACE_TYPE = $9;
68 {$EXTERNALSYM ACCESS_ALLOWED_CALLBACK_ACE_TYPE}
69 ACCESS_DENIED_CALLBACK_ACE_TYPE = $A;
70 {$EXTERNALSYM ACCESS_DENIED_CALLBACK_ACE_TYPE}
71 ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE = $B;
72 {$EXTERNALSYM ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE}
73 ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE = $C;
74 {$EXTERNALSYM ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE}
75 SYSTEM_AUDIT_CALLBACK_ACE_TYPE = $D;
76 {$EXTERNALSYM SYSTEM_AUDIT_CALLBACK_ACE_TYPE}
77 SYSTEM_ALARM_CALLBACK_ACE_TYPE = $E;
78 {$EXTERNALSYM SYSTEM_ALARM_CALLBACK_ACE_TYPE}
79 SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE = $F;
80 {$EXTERNALSYM SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE}
81 SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE = $10;
82 {$EXTERNALSYM SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE}
83
84 ACCESS_MAX_MS_V5_ACE_TYPE = $10;
85 {$EXTERNALSYM ACCESS_MAX_MS_V5_ACE_TYPE}
86
87 SUCCESSFUL_ACCESS_ACE_FLAG = ($40);
88 {$EXTERNALSYM SUCCESSFUL_ACCESS_ACE_FLAG}
89 FAILED_ACCESS_ACE_FLAG = ($80);
90 {$EXTERNALSYM FAILED_ACCESS_ACE_FLAG}
91
92 type
93
94 PACE_HEADER = ^ACE_HEADER;
95 _ACE_HEADER = record
96 AceType: Byte;
97 AceFlags: Byte;
98 AceSize: Word;
99 end;
100
101 ACE_HEADER = _ACE_HEADER;
102
103 TAceHeader = ACE_HEADER;
104 PAceHeader = PACE_HEADER;
105
106 //Access Allowed ACE
107 PAccessAllowedAce = ^TAccessAllowedAce;
108 _ACCESS_ALLOWED_ACE = record
109 Header: ACE_HEADER;
110 Mask: DWORD;
111 SidStart: DWORD;
112 end;
113 TAccessAllowedAce = _ACCESS_ALLOWED_ACE;
114
115 type
116 //=== ACL (Access Control List)==============================
117 //Size information
118 PACL_SIZE_INFORMATION = ^ACL_SIZE_INFORMATION;
119 _ACL_SIZE_INFORMATION = record
120 AceCount,
121 AclBytesInUse,
122 AclBytesFree: DWORD
123 end;
124 ACL_SIZE_INFORMATION = _ACL_SIZE_INFORMATION;
125 TAclSizeInformation = ACL_SIZE_INFORMATION;
126 PAclSizeInformation = PACL_SIZE_INFORMATION;
127
128 //Revision Information
129 PACL_REVISION_INFORMATION = ^ACL_REVISION_INFORMATION;
130 _ACL_REVISION_INFORMATION = record
131 AclRevision: DWORD
132 end;
133 ACL_REVISION_INFORMATION = _ACL_REVISION_INFORMATION;
134 TAclRevisionInformation = ACL_REVISION_INFORMATION;
135 PAclRevisionInformation = PACL_REVISION_INFORMATION;
136
137 function IsAdmin: Boolean; stdcall; //is logged user is member of admins or
138 //domain admins
139 function IsNT: Boolean; stdcall; //is system NT based
140 function IsNT4: Boolean; stdcall; //is system NT 4
141 function GetEveryOneSid: Pointer; stdcall; //Security identifier of well known
142 // group Everyone
143 function GetAccountSID(anAccountName: string): Pointer; stdcall;
144
145 function SetFileObjectAccessRights(aFileObject: string;
146 aSID: Pointer; anAccess: CARDINAL; isInheritedAccess: BOOLEAN): BOOLEAN; stdcall;
147
148 function SetFileObjectAndSubobjectsAccessRights(aFileObject: string;
149 aSID: Pointer; anAccess: CARDINAL): BOOLEAN; stdcall;
150
151 function SetEveryoneRWEDAccessToFileOrFolder(aFileOrFolder: string): BOOLEAN;
152 stdcall;
153 function SetEveryoneRWEDAccessToFileOrFolderAndSubobjects(aFileOrFolder: string):
154 BOOLEAN; stdcall;
155
156 function VolumeSupportsPersistentACLs(aPath: string): Boolean; stdcall;
157
158 implementation
159 uses
160 SysUtils, ComObj;
161
162 function VolumeSupportsPersistentACLs(aPath: string): Boolean;
163 var
164 maxClen,
165 driveFlags: Cardinal;
166 i: Integer;
167 VolName, FSysName: array[0..MAX_PATH] of Char;
168 begin
169 aPath := ExtractFileDrive(aPath) + '\';
170 Result := FALSE;
171 if GetVolumeInformation(
172 PChar(aPath),
173 VolName,
174 SizeOf(VolName),
175 nil,
176 maxClen,
177 driveFlags,
178 FsysName,
179 SizeOf(FsysName)
180 ) then
181 Result := driveFlags and FS_PERSISTENT_ACLS = FS_PERSISTENT_ACLS;
182 end;
183
184 function CheckCARDINALRslt(aCardinal: DWORD): Boolean;
185 begin
186 Result := aCardinal = ERROR_SUCCESS;
187 if not Result then
188 SetLastError(aCardinal);
189 end;
190
191 function IsAdmin: Boolean;
192 var
193 ntauth: SID_IDENTIFIER_AUTHORITY;
194 psidAdmin: Pointer;
195 bIsAdmin: Boolean;
196 htok: THandle;
197 cb: DWORD;
198 ptg: ^TOKEN_GROUPS;
199 i: Integer;
200 grp: PSIDAndAttributes;
201 begin
202 Result := FALSE;
203 if not IsNT then
204 Result := TRUE
205 else
206 begin
207 bIsAdmin := FALSE;
208 ntauth := SECURITY_NT_AUTHORITY;
209 psidAdmin := nil;
210 AllocateAndInitializeSid(
211 ntauth, 2,
212 SECURITY_BUILTIN_DOMAIN_RID,
213 DOMAIN_ALIAS_RID_ADMINS,
214 0, 0, 0, 0, 0, 0, psidAdmin
215 );
216
217 htok := 0;
218 OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, htok);
219 GetTokenInformation(htok, TokenGroups, nil, 0, cb);
220 GetMem(ptg, cb);
221 GetTokenInformation(htok, TokenGroups, ptg, cb, cb);
222
223 grp := @(ptg.Groups[0]);
224
225 for i := 0 to ptg.GroupCount - 1 do
226 begin
227 if EqualSid(psidAdmin, grp.Sid) then
228 begin
229 bIsAdmin := TRUE;
230 Break;
231 end;
232 Inc(grp); //, SizeOf( TSIDAndAttributes));
233 end;
234 freemem(ptg);
235 CloseHandle(htok);
236 FreeSid(psidAdmin);
237 Result := bIsAdmin;
238 end; // else of : if not IsNT
239 end;
240
241 function IsNT: Boolean;
242 var
243 ovi: TOSVersionInfo;
244 begin
245 FillChar(ovi, SizeOf(Ovi), 0);
246 ovi.dwOSVersionInfoSize := SizeOf(Ovi);
247 GetVersionEx(ovi);
248 Result := ovi.dwPlatformId = VER_PLATFORM_WIN32_NT;
249 end;
250
251 function IsNT4: Boolean;
252 var
253 ovi: TOSVersionInfo;
254 begin
255 FillChar(ovi, SizeOf(Ovi), 0);
256 ovi.dwOSVersionInfoSize := SizeOf(Ovi);
257 GetVersionEx(ovi);
258 Result := (ovi.dwPlatformId = VER_PLATFORM_WIN32_NT) and (ovi.dwMajorVersion = 4);
259 end;
260
261 function GetEveryOneSid: Pointer;
262 begin
263 AllocateAndInitializeSid(
264 SECURITY_WORLD_SID_AUTHORITY,
265 1,
266 SECURITY_WORLD_RID,
267 0,
268 0, 0, 0, 0, 0, 0,
269 Result
270 );
271 end;
272
273 function GetAccountSID(anAccountName: string): Pointer;
274 var
275 cb: CARDINAL;
276 refDomainName: array[0..1024] of Char;
277 cbRefDomainName: Cardinal;
278 peUse: Cardinal;
279 SD: Pointer;
280 begin
281 SD := nil;
282 try
283 cbRefDomainName := SizeOf(refDomainName);
284 FillChar(refDomainName, cbRefDomainName, 0);
285 cb := 0;
286 LookupAccountName(nil, PChar(anAccountName), nil, cb, refDomainName,
287 cbRefDomainName, peUse);
288 if cb > 0 then
289 begin
290 GetMem(SD, cb);
291 FillChar(SD^, cb, 0);
292 if not LookupAccountName(nil, PChar(anAccountName), SD, cb, refDomainName,
293 cbRefDomainName, peUse) then
294 begin
295 FreeMem(SD, cb);
296 SD := nil;
297 end;
298 end
299 else
300 begin
301 SD := nil;
302 end;
303 finally
304 Result := SD;
305 end;
306 end;
307
308 function SetFileObjectAndSubobjectsAccessRights(aFileObject: string;
309 aSID: Pointer; anAccess: CARDINAL): BOOLEAN;
310 function RecursiveSet(aPath: string): Boolean;
311 var
312 F: TSearchRec;
313 i: Integer;
314 begin
315 Result := SetFileObjectAccessRights(aPath, aSID, anAccess, TRUE);
316 i := FindFirst(aPath + '\*.*', faAnyFile, F);
317 try
318 while i = 0 do
319 begin
320 if (F.Name <> '') and (F.Name[1] <> '.') then
321 begin
322 if F.Attr and faDirectory = faDirectory then
323 Result := Result and RecursiveSet(aPath + '\' + F.Name)
324 else
325 Result := Result and SetFileObjectAccessRights(aPath + '\' + F.Name,
326 aSID,
327 anAccess, TRUE);
328 if not Result then
329 Exit;
330 end;
331 i := FindNext(F);
332 end;
333 finally
334 FindClose(F);
335 end;
336 end;
337
338 begin
339 Result := FALSE;
340 aFileObject := TRIM(aFileObject);
341 if aFileObject <> '' then
342 begin
343 if DirectoryExists(aFileObject) then
344 begin
345 if aFileObject[Length(aFileObject)] = '\' then
346 Delete(aFileObject, Length(aFileObject), 1);
347 Result := RecursiveSet(aFileObject);
348 Result := Result and SetFileObjectAccessRights(aFileObject, aSID, anAccess,
349 FALSE);
350 end
351 else
352 Result := SetFileObjectAccessRights(aFileObject, aSID, anAccess, FALSE);
353 end;
354 end;
355
356 function SetEveryoneRWEDAccessToFileOrFolder(aFileOrFolder: string): BOOLEAN;
357 var
358 SID: Pointer;
359 begin
360 Result := FALSE;
361 AllocateAndInitializeSid(
362 SECURITY_WORLD_SID_AUTHORITY,
363 1,
364 SECURITY_WORLD_RID,
365 0,
366 0, 0, 0, 0, 0, 0,
367 SID
368 );
369 if IsValidSid(SID) then
370 try
371 Result := SetFileObjectAccessRights(aFileOrFolder,
372 SID,
373 GENERIC_READ + GENERIC_WRITE + GENERIC_EXECUTE + _DELETE,
374 FALSE
375 );
376 finally
377 FreeSid(SID);
378 end;
379 end;
380
381 function SetEveryoneRWEDAccessToFileOrFolderAndSubobjects(aFileOrFolder: string):
382 BOOLEAN;
383 var
384 SID: Pointer;
385 begin
386 SID := GetEveryOneSid;
387 try
388 Result := SetFileObjectAndSubobjectsAccessRights(aFileOrFolder,
389 SID,
390 GENERIC_READ + GENERIC_WRITE + GENERIC_EXECUTE + _DELETE
391 );
392 finally
393 FreeSid(SID);
394 end;
395 end;
396
397 function SetFileObjectAccessRights(aFileObject: string;
398 aSID: Pointer; anAccess: CARDINAL; isInheritedAccess: BOOLEAN): BOOLEAN;
399 var
400 PPACL, PPACL2: PACL;
401 newDacl: PACL;
402 SecDescPtr, SD2: PSECURITY_DESCRIPTOR;
403 needed: Cardinal;
404 SD_Control: WORD;
405 SD_Revision: Cardinal;
406 aTrustee: TRUSTEE;
407 expAccess: PExplicit_Access;
408 isFile: Boolean;
409 CurACEBr, CurACEInd: CARDINAL;
410 OldAclSI: TAclSizeInformation;
411 OldAclRI: TAclRevisionInformation;
412 anACE: PAccessAllowedAce;
413 i: Integer;
414 oldACLSize, newACLSize, newACESize: Cardinal;
415 bPresent, bDefaulted: LongBool;
416 begin
417 Result := false;
418 if not IsValidSid(aSID) then
419 Exit;
420
421 isFile := FileExists(aFileObject);
422
423 PPACL := nil;
424 if not IsNT4 then
425 begin
426 if not CheckCardinalRslt(
427 GetNamedSecurityInfo(PChar(aFileObject), SE_FILE_OBJECT,
428 DACL_SECURITY_INFORMATION, nil, nil, PACL(@PPACL), nil, SecDescPtr)
429 ) then
430 Exit;
431 end
432 else
433 begin
434 GetFileSecurity(PChar(aFileObject), DACL_SECURITY_INFORMATION, nil, 0, needed);
435 GetMem(SecDescPtr, needed);
436 FillChar(SecDescPtr^, needed, 0);
437 if not GetFileSecurity(PChar(aFileObject), DACL_SECURITY_INFORMATION,
438 SecDescPtr,
439 needed, needed) then
440 Exit;
441 if not GetSecurityDescriptorDacl(SecDescPtr, bPresent, PPACL, bDefaulted) then
442 Exit;
443 end;
444 try
445 if not Assigned(PPACL) then
446 Exit;
447 if not GetSecurityDescriptorControl(SecDescPtr, SD_Control, SD_Revision) then
448 Exit;
449 if SD_Control and SE_DACL_PRESENT <> SE_DACL_PRESENT then
450 Exit;
451
452 if not GetAclInformation(PPACL^, @oldAclSI, SizeOF(TAclSizeInformation),
453 AclSizeInformation) then
454 Exit;
455 if not GetAclInformation(PPACL^, @oldAclRI, SizeOf(TAclRevisionInformation),
456 AclRevisionInformation) then
457 Exit;
458
459 //Delete previous ACE, for a given aSID
460 CurACEBr := oldAclSI.AceCount;
461 for i := oldAclSI.AceCount - 1 downto 0 do
462 begin
463 if GetAce(PPACL^, i, Pointer(anAce)) then
464 begin
465 if EqualSID(@(anACE.SidStart), aSID) then
466 begin
467 DeleteAce(PPACL^, i);
468 CurACEBr := CurACEBr - 1;
469 end;
470 end;
471 end;
472
473 if not GetAclInformation(PPACL^, @oldAclSI, SizeOF(TAclSizeInformation),
474 AclSizeInformation) then
475 Exit;
476 if not GetAclInformation(PPACL^, @oldAclRI, SizeOf(TAclRevisionInformation),
477 AclRevisionInformation) then
478 Exit;
479
480 NewACESize := SizeOf(TAccessAllowedACE) + GetLengthSid(aSID) - SizeOf(DWORD);
481 OldACLSize := oldAclSI.AclBytesInUse + oldAclSI.AclBytesFree;
482 NewACLSize := oldAclSI.AclBytesInUse + NewAceSize * 2 - oldAclSI.AclBytesFree;
483
484 if NewAclSize < OldAclSize then
485 NewAclSize := OldAclSize;
486
487 GetMem(PPACL2, NewACLSize);
488 try
489 FillChar(PPACL2^, NewACLSize, 0);
490
491 Move(PPACL^, PPACL2^, oldACLSize);
492 PPACL2.AclSize := newACLSize;
493
494 if not GetAclInformation(PPACL2^, @oldAclSI, SizeOF(TAclSizeInformation),
495 AclSizeInformation) then
496 Exit;
497
498 CurACEInd := 0;
499
500 if not IsNT4 then
501 begin
502 //Construct Our Ace
503 GetMem(anACE, newACESize);
504 try
505 FillChar(anACE^, newACESize, 0);
506 anACE.Header.AceType := ACCESS_ALLOWED_ACE_TYPE;
507
508 if not isFile then //demek e folder
509 begin
510 anACE.Header.AceFlags := SUB_CONTAINERS_ONLY_INHERIT +
511 SUB_OBJECTS_ONLY_INHERIT;
512 end;
513 if isInheritedAccess then
514 begin
515 if not IsNt4 then
516 anACE.Header.AceFlags := anACE.Header.AceFlags +
517 INHERITED_ACCESS_ENTRY;
518 end;
519
520 anACE.Header.AceSize := newACESize;
521 anAce.Mask := anAccess;
522 Move(aSID^, anAce.SidStart, GetLengthSid(aSID));
523
524 if not AddAce(PPACL2^, OldAclRI.AclRevision, CurACEInd, anACE, newACESize)
525 then
526 Exit;
527 finally
528 FreeMem(anACE, newACESize);
529 end;
530 end
531 else
532 begin
533 CurACEInd := 0;
534 if not isFile then
535 begin
536 GetMem(anACE, newACESize);
537 try
538 FillChar(anACE^, newACESize, 0);
539 anACE.Header.AceType := ACCESS_ALLOWED_ACE_TYPE;
540
541 anACE.Header.AceFlags := SUB_CONTAINERS_ONLY_INHERIT +
542 SUB_OBJECTS_ONLY_INHERIT + INHERIT_ONLY;
543
544 anACE.Header.AceSize := newACESize;
545 anAce.Mask := anAccess;
546 Move(aSID^, anAce.SidStart, GetLengthSid(aSID));
547
548 if not AddAce(PPACL2^, OldAclRI.AclRevision, CurACEInd, anACE,
549 newACESize)
550 then
551 Exit;
552 finally
553 FreeMem(anACE, newACESize);
554 end;
555 end;
556
557 //Add ACE for Files
558 GetMem(anACE, newACESize);
559 try
560 FillChar(anACE^, newACESize, 0);
561 anACE.Header.AceType := ACCESS_ALLOWED_ACE_TYPE;
562
563 anACE.Header.AceFlags := 0; // Empty flags, but ACE
564 anACE.Header.AceSize := newACESize;
565 anAce.Mask := anAccess;
566 Move(aSID^, anAce.SidStart, GetLengthSid(aSID));
567
568 if not AddAce(PPACL2^, OldAclRI.AclRevision, CurACEInd, anACE, newACESize)
569 then
570 Exit;
571 finally
572 FreeMem(anACE, newACESize);
573 end;
574 end;
575
576 if not GetAclInformation(PPACL2^, @oldAclSI, SizeOF(TAclSizeInformation),
577 AclSizeInformation) then
578 Exit;
579
580 if not IsNT4 then
581 begin
582 Result := CheckCARDINALRslt(
583 SetNamedSecurityInfo(PChar(aFileObject), SE_FILE_OBJECT,
584 DACL_SECURITY_INFORMATION, nil, nil, PPACL2, nil)
585 );
586 end
587 else
588 begin
589 GetMem(SD2, SizeOf(TSecurityDescriptor));
590 try
591 if not InitializeSecurityDescriptor(SD2, SECURITY_DESCRIPTOR_REVISION)
592 then
593 Exit;
594 if not SetSecurityDescriptorDacl(SD2, bPresent, PPACL2, bDefaulted) then
595 Exit;
596 Result := SetFileSecurity(PChar(aFileObject), DACL_SECURITY_INFORMATION,
597 SD2);
598 finally
599 FreeMem(SD2, SizeOf(TSecurityDescriptor));
600 end;
601 end;
602 finally
603 FreeMem(PPACL2, NewACLSize);
604 end;
605 finally
606 LocalFree(HLOCAL(SecDescPtr));
607 end;
608 end;
609
610 end.
|