WaveHdr prepare/unprepare/submit now gets handled within the context of the
[reactos.git] / reactos / lib / rtl / acl.c
1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS system libraries
3 * PURPOSE: Security manager
4 * FILE: lib/rtl/acl.c
5 * PROGRAMER: David Welch <welch@cwcom.net>
6 */
7
8 /* INCLUDES *****************************************************************/
9
10 #include <rtl.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 /* FUNCTIONS ***************************************************************/
16
17 BOOLEAN NTAPI
18 RtlFirstFreeAce(PACL Acl,
19 PACE* Ace)
20 {
21 PACE Current;
22 ULONG_PTR AclEnd;
23 ULONG i;
24
25 PAGED_CODE_RTL();
26
27 Current = (PACE)(Acl + 1);
28 *Ace = NULL;
29
30 if (Acl->AceCount == 0)
31 {
32 *Ace = Current;
33 return(TRUE);
34 }
35
36 i = 0;
37 AclEnd = (ULONG_PTR)Acl + Acl->AclSize;
38 do
39 {
40 if ((ULONG_PTR)Current >= AclEnd)
41 {
42 return(FALSE);
43 }
44 if (Current->Header.AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE &&
45 Acl->AclRevision < ACL_REVISION3)
46 {
47 return(FALSE);
48 }
49 Current = (PACE)((ULONG_PTR)Current + Current->Header.AceSize);
50 }
51 while (++i < Acl->AceCount);
52
53 if ((ULONG_PTR)Current < AclEnd)
54 {
55 *Ace = Current;
56 }
57
58 return(TRUE);
59 }
60
61
62 /*
63 * @implemented
64 */
65 NTSTATUS NTAPI
66 RtlGetAce(PACL Acl,
67 ULONG AceIndex,
68 PVOID *Ace)
69 {
70 ULONG i;
71
72 PAGED_CODE_RTL();
73
74 if (Acl->AclRevision < MIN_ACL_REVISION ||
75 Acl->AclRevision > MAX_ACL_REVISION ||
76 AceIndex >= Acl->AceCount)
77 {
78 return(STATUS_INVALID_PARAMETER);
79 }
80
81 *Ace = (PVOID)((PACE)(Acl + 1));
82
83 for (i = 0; i < AceIndex; i++)
84 {
85 if ((ULONG_PTR)*Ace >= (ULONG_PTR)Acl + Acl->AclSize)
86 {
87 return(STATUS_INVALID_PARAMETER);
88 }
89 *Ace = (PVOID)((PACE)((ULONG_PTR)(*Ace) + ((PACE)(*Ace))->Header.AceSize));
90 }
91
92 if ((ULONG_PTR)*Ace >= (ULONG_PTR)Acl + Acl->AclSize)
93 {
94 return(STATUS_INVALID_PARAMETER);
95 }
96
97 return(STATUS_SUCCESS);
98 }
99
100
101 static NTSTATUS
102 RtlpAddKnownAce (PACL Acl,
103 ULONG Revision,
104 ULONG Flags,
105 ACCESS_MASK AccessMask,
106 GUID *ObjectTypeGuid OPTIONAL,
107 GUID *InheritedObjectTypeGuid OPTIONAL,
108 PSID Sid,
109 ULONG Type)
110 {
111 PACE Ace;
112 PSID SidStart;
113 ULONG AceSize, InvalidFlags;
114 ULONG AceObjectFlags = 0;
115
116 PAGED_CODE_RTL();
117
118 #if DBG
119 /* check if RtlpAddKnownAce was called incorrectly */
120 if (ObjectTypeGuid != NULL || InheritedObjectTypeGuid != NULL)
121 {
122 ASSERT(Type == ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE ||
123 Type == ACCESS_ALLOWED_OBJECT_ACE_TYPE ||
124 Type == ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE ||
125 Type == ACCESS_DENIED_OBJECT_ACE_TYPE ||
126 Type == SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE ||
127 Type == SYSTEM_AUDIT_OBJECT_ACE_TYPE);
128 }
129 else
130 {
131 ASSERT(Type != ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE &&
132 Type != ACCESS_ALLOWED_OBJECT_ACE_TYPE &&
133 Type != ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE &&
134 Type != ACCESS_DENIED_OBJECT_ACE_TYPE &&
135 Type != SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE &&
136 Type != SYSTEM_AUDIT_OBJECT_ACE_TYPE);
137 }
138 #endif
139
140 if (!RtlValidSid(Sid))
141 {
142 return(STATUS_INVALID_SID);
143 }
144
145 if (Type == SYSTEM_MANDATORY_LABEL_ACE_TYPE)
146 {
147 static const SID_IDENTIFIER_AUTHORITY MandatoryLabelAuthority = {SECURITY_MANDATORY_LABEL_AUTHORITY};
148
149 /* The SID's identifier authority must be SECURITY_MANDATORY_LABEL_AUTHORITY! */
150 if (RtlCompareMemory(&((PISID)Sid)->IdentifierAuthority,
151 &MandatoryLabelAuthority,
152 sizeof(MandatoryLabelAuthority)) != sizeof(MandatoryLabelAuthority))
153 {
154 return STATUS_INVALID_PARAMETER;
155 }
156 }
157
158 if (Acl->AclRevision > MAX_ACL_REVISION ||
159 Revision > MAX_ACL_REVISION)
160 {
161 return(STATUS_UNKNOWN_REVISION);
162 }
163 if (Revision < Acl->AclRevision)
164 {
165 Revision = Acl->AclRevision;
166 }
167
168 /* Validate the flags */
169 if (Type == SYSTEM_AUDIT_ACE_TYPE ||
170 Type == SYSTEM_AUDIT_OBJECT_ACE_TYPE ||
171 Type == SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE)
172 {
173 InvalidFlags = Flags & ~(VALID_INHERIT_FLAGS |
174 SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG);
175 }
176 else
177 {
178 InvalidFlags = Flags & ~VALID_INHERIT_FLAGS;
179 }
180
181 if (InvalidFlags != 0)
182 {
183 return(STATUS_INVALID_PARAMETER);
184 }
185
186 if (!RtlFirstFreeAce(Acl, &Ace))
187 {
188 return(STATUS_INVALID_ACL);
189 }
190 if (Ace == NULL)
191 {
192 return(STATUS_ALLOTTED_SPACE_EXCEEDED);
193 }
194
195 /* Calculate the size of the ACE */
196 AceSize = RtlLengthSid(Sid) + sizeof(ACE);
197 if (ObjectTypeGuid != NULL)
198 {
199 AceObjectFlags |= ACE_OBJECT_TYPE_PRESENT;
200 AceSize += sizeof(GUID);
201 }
202 if (InheritedObjectTypeGuid != NULL)
203 {
204 AceObjectFlags |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
205 AceSize += sizeof(GUID);
206 }
207
208 if (AceObjectFlags != 0)
209 {
210 /* Don't forget the ACE object flags
211 (corresponds to the Flags field in the *_OBJECT_ACE structures) */
212 AceSize += sizeof(ULONG);
213 }
214
215 if ((ULONG_PTR)Ace + AceSize >
216 (ULONG_PTR)Acl + Acl->AclSize)
217 {
218 return(STATUS_ALLOTTED_SPACE_EXCEEDED);
219 }
220
221 /* initialize the header and common fields */
222 Ace->Header.AceFlags = Flags;
223 Ace->Header.AceType = Type;
224 Ace->Header.AceSize = (WORD)AceSize;
225 Ace->AccessMask = AccessMask;
226
227 if (AceObjectFlags != 0)
228 {
229 /* Write the ACE flags to the ACE
230 (corresponds to the Flags field in the *_OBJECT_ACE structures) */
231 *(PULONG)(Ace + 1) = AceObjectFlags;
232 SidStart = (PSID)((ULONG_PTR)(Ace + 1) + sizeof(ULONG));
233 }
234 else
235 SidStart = (PSID)(Ace + 1);
236
237 /* copy the GUIDs */
238 if (ObjectTypeGuid != NULL)
239 {
240 RtlCopyMemory(SidStart,
241 ObjectTypeGuid,
242 sizeof(GUID));
243 SidStart = (PSID)((ULONG_PTR)SidStart + sizeof(GUID));
244 }
245 if (InheritedObjectTypeGuid != NULL)
246 {
247 RtlCopyMemory(SidStart,
248 InheritedObjectTypeGuid,
249 sizeof(GUID));
250 SidStart = (PSID)((ULONG_PTR)SidStart + sizeof(GUID));
251 }
252
253 /* copy the SID */
254 RtlCopySid(RtlLengthSid(Sid),
255 SidStart,
256 Sid);
257 Acl->AceCount++;
258 Acl->AclRevision = Revision;
259 return(STATUS_SUCCESS);
260 }
261
262
263 /*
264 * @implemented
265 */
266 NTSTATUS NTAPI
267 RtlAddAccessAllowedAce (IN OUT PACL Acl,
268 IN ULONG Revision,
269 IN ACCESS_MASK AccessMask,
270 IN PSID Sid)
271 {
272 PAGED_CODE_RTL();
273
274 return RtlpAddKnownAce (Acl,
275 Revision,
276 0,
277 AccessMask,
278 NULL,
279 NULL,
280 Sid,
281 ACCESS_ALLOWED_ACE_TYPE);
282 }
283
284
285 /*
286 * @implemented
287 */
288 NTSTATUS NTAPI
289 RtlAddAccessAllowedAceEx (IN OUT PACL Acl,
290 IN ULONG Revision,
291 IN ULONG Flags,
292 IN ACCESS_MASK AccessMask,
293 IN PSID Sid)
294 {
295 PAGED_CODE_RTL();
296
297 return RtlpAddKnownAce (Acl,
298 Revision,
299 Flags,
300 AccessMask,
301 NULL,
302 NULL,
303 Sid,
304 ACCESS_ALLOWED_ACE_TYPE);
305 }
306
307
308 /*
309 * @implemented
310 */
311 NTSTATUS NTAPI
312 RtlAddAccessAllowedObjectAce (IN OUT PACL Acl,
313 IN ULONG Revision,
314 IN ULONG Flags,
315 IN ACCESS_MASK AccessMask,
316 IN GUID *ObjectTypeGuid OPTIONAL,
317 IN GUID *InheritedObjectTypeGuid OPTIONAL,
318 IN PSID Sid)
319 {
320 ULONG Type;
321
322 PAGED_CODE_RTL();
323
324 /* make sure we call RtlpAddKnownAce correctly */
325 if (ObjectTypeGuid != NULL || InheritedObjectTypeGuid != NULL)
326 Type = ACCESS_ALLOWED_OBJECT_ACE_TYPE;
327 else
328 Type = ACCESS_ALLOWED_ACE_TYPE;
329
330 return RtlpAddKnownAce (Acl,
331 Revision,
332 Flags,
333 AccessMask,
334 ObjectTypeGuid,
335 InheritedObjectTypeGuid,
336 Sid,
337 Type);
338 }
339
340
341 /*
342 * @implemented
343 */
344 NTSTATUS NTAPI
345 RtlAddAccessDeniedAce (PACL Acl,
346 ULONG Revision,
347 ACCESS_MASK AccessMask,
348 PSID Sid)
349 {
350 PAGED_CODE_RTL();
351
352 return RtlpAddKnownAce (Acl,
353 Revision,
354 0,
355 AccessMask,
356 NULL,
357 NULL,
358 Sid,
359 ACCESS_DENIED_ACE_TYPE);
360 }
361
362
363 /*
364 * @implemented
365 */
366 NTSTATUS NTAPI
367 RtlAddAccessDeniedAceEx (IN OUT PACL Acl,
368 IN ULONG Revision,
369 IN ULONG Flags,
370 IN ACCESS_MASK AccessMask,
371 IN PSID Sid)
372 {
373 PAGED_CODE_RTL();
374
375 return RtlpAddKnownAce (Acl,
376 Revision,
377 Flags,
378 AccessMask,
379 NULL,
380 NULL,
381 Sid,
382 ACCESS_DENIED_ACE_TYPE);
383 }
384
385
386 /*
387 * @implemented
388 */
389 NTSTATUS NTAPI
390 RtlAddAccessDeniedObjectAce (IN OUT PACL Acl,
391 IN ULONG Revision,
392 IN ULONG Flags,
393 IN ACCESS_MASK AccessMask,
394 IN GUID *ObjectTypeGuid OPTIONAL,
395 IN GUID *InheritedObjectTypeGuid OPTIONAL,
396 IN PSID Sid)
397 {
398 ULONG Type;
399
400 PAGED_CODE_RTL();
401
402 /* make sure we call RtlpAddKnownAce correctly */
403 if (ObjectTypeGuid != NULL || InheritedObjectTypeGuid != NULL)
404 Type = ACCESS_DENIED_OBJECT_ACE_TYPE;
405 else
406 Type = ACCESS_DENIED_ACE_TYPE;
407
408 return RtlpAddKnownAce (Acl,
409 Revision,
410 Flags,
411 AccessMask,
412 ObjectTypeGuid,
413 InheritedObjectTypeGuid,
414 Sid,
415 Type);
416 }
417
418
419 static VOID
420 RtlpAddData(PVOID AceList,
421 ULONG AceListLength,
422 PVOID Ace,
423 ULONG Offset)
424 {
425 if (Offset > 0)
426 {
427 RtlCopyMemory((PVOID)((ULONG_PTR)Ace + AceListLength),
428 Ace,
429 Offset);
430 }
431
432 if (AceListLength != 0)
433 {
434 RtlCopyMemory(Ace,
435 AceList,
436 AceListLength);
437 }
438 }
439
440
441 /*
442 * @implemented
443 */
444 NTSTATUS NTAPI
445 RtlAddAce(PACL Acl,
446 ULONG AclRevision,
447 ULONG StartingIndex,
448 PVOID AceList,
449 ULONG AceListLength)
450 {
451 PACE Ace;
452 PACE Current;
453 ULONG NewAceCount;
454 ULONG Index;
455
456 PAGED_CODE_RTL();
457
458 if (Acl->AclRevision < MIN_ACL_REVISION ||
459 Acl->AclRevision > MAX_ACL_REVISION ||
460 !RtlFirstFreeAce(Acl, &Ace))
461 {
462 return(STATUS_INVALID_PARAMETER);
463 }
464
465 if (Acl->AclRevision <= AclRevision)
466 {
467 AclRevision = Acl->AclRevision;
468 }
469
470 if (((ULONG_PTR)AceList + AceListLength) <= (ULONG_PTR)AceList)
471 {
472 return(STATUS_INVALID_PARAMETER);
473 }
474
475 for (Current = AceList, NewAceCount = 0;
476 (ULONG_PTR)Current < ((ULONG_PTR)AceList + AceListLength);
477 Current = (PACE)((ULONG_PTR)Current + Current->Header.AceSize),
478 ++NewAceCount)
479 {
480 if (((PACE)AceList)->Header.AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE &&
481 AclRevision < ACL_REVISION3)
482 {
483 return(STATUS_INVALID_PARAMETER);
484 }
485 }
486
487 if (Ace == NULL ||
488 ((ULONG_PTR)Ace + AceListLength) > ((ULONG_PTR)Acl + Acl->AclSize))
489 {
490 return(STATUS_BUFFER_TOO_SMALL);
491 }
492
493 Current = (PACE)(Acl + 1);
494 for (Index = 0; Index < StartingIndex && Index < Acl->AceCount; Index++)
495 {
496 Current = (PACE)((ULONG_PTR)Current + Current->Header.AceSize);
497 }
498
499 RtlpAddData(AceList,
500 AceListLength,
501 Current,
502 (ULONG)((ULONG_PTR)Ace - (ULONG_PTR)Current));
503 Acl->AceCount = Acl->AceCount + NewAceCount;
504 Acl->AclRevision = AclRevision;
505
506 return(STATUS_SUCCESS);
507 }
508
509
510 /*
511 * @implemented
512 */
513 NTSTATUS NTAPI
514 RtlAddAuditAccessAce(PACL Acl,
515 ULONG Revision,
516 ACCESS_MASK AccessMask,
517 PSID Sid,
518 BOOLEAN Success,
519 BOOLEAN Failure)
520 {
521 ULONG Flags = 0;
522
523 PAGED_CODE_RTL();
524
525 if (Success)
526 {
527 Flags |= SUCCESSFUL_ACCESS_ACE_FLAG;
528 }
529
530 if (Failure)
531 {
532 Flags |= FAILED_ACCESS_ACE_FLAG;
533 }
534
535 return RtlpAddKnownAce (Acl,
536 Revision,
537 Flags,
538 AccessMask,
539 NULL,
540 NULL,
541 Sid,
542 SYSTEM_AUDIT_ACE_TYPE);
543 }
544
545
546 /*
547 * @implemented
548 */
549 NTSTATUS NTAPI
550 RtlAddAuditAccessAceEx(PACL Acl,
551 ULONG Revision,
552 ULONG Flags,
553 ACCESS_MASK AccessMask,
554 PSID Sid,
555 BOOLEAN Success,
556 BOOLEAN Failure)
557 {
558 if (Success)
559 {
560 Flags |= SUCCESSFUL_ACCESS_ACE_FLAG;
561 }
562
563 if (Failure)
564 {
565 Flags |= FAILED_ACCESS_ACE_FLAG;
566 }
567
568 return RtlpAddKnownAce (Acl,
569 Revision,
570 Flags,
571 AccessMask,
572 NULL,
573 NULL,
574 Sid,
575 SYSTEM_AUDIT_ACE_TYPE);
576 }
577
578
579 /*
580 * @implemented
581 */
582 NTSTATUS NTAPI
583 RtlAddAuditAccessObjectAce(PACL Acl,
584 ULONG Revision,
585 ULONG Flags,
586 ACCESS_MASK AccessMask,
587 IN GUID *ObjectTypeGuid OPTIONAL,
588 IN GUID *InheritedObjectTypeGuid OPTIONAL,
589 PSID Sid,
590 BOOLEAN Success,
591 BOOLEAN Failure)
592 {
593 ULONG Type;
594
595 if (Success)
596 {
597 Flags |= SUCCESSFUL_ACCESS_ACE_FLAG;
598 }
599
600 if (Failure)
601 {
602 Flags |= FAILED_ACCESS_ACE_FLAG;
603 }
604
605 /* make sure we call RtlpAddKnownAce correctly */
606 if (ObjectTypeGuid != NULL || InheritedObjectTypeGuid != NULL)
607 Type = SYSTEM_AUDIT_OBJECT_ACE_TYPE;
608 else
609 Type = SYSTEM_AUDIT_ACE_TYPE;
610
611 return RtlpAddKnownAce (Acl,
612 Revision,
613 Flags,
614 AccessMask,
615 ObjectTypeGuid,
616 InheritedObjectTypeGuid,
617 Sid,
618 Type);
619 }
620
621
622 /*
623 * @implemented
624 */
625 NTSTATUS NTAPI
626 RtlAddMandatoryAce(IN OUT PACL Acl,
627 IN ULONG Revision,
628 IN ULONG Flags,
629 IN ULONG MandatoryFlags,
630 IN ULONG AceType,
631 IN PSID LabelSid)
632 {
633 if (MandatoryFlags & ~SYSTEM_MANDATORY_LABEL_VALID_MASK)
634 return STATUS_INVALID_PARAMETER;
635
636 if (AceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE)
637 return STATUS_INVALID_PARAMETER;
638
639 return RtlpAddKnownAce (Acl,
640 Revision,
641 Flags,
642 (ACCESS_MASK)MandatoryFlags,
643 NULL,
644 NULL,
645 LabelSid,
646 AceType);
647 }
648
649
650 static VOID
651 RtlpDeleteData(PVOID Ace,
652 ULONG AceSize,
653 ULONG Offset)
654 {
655 if (AceSize < Offset)
656 {
657 RtlMoveMemory(Ace,
658 (PVOID)((ULONG_PTR)Ace + AceSize),
659 Offset - AceSize);
660 }
661
662 if (Offset - AceSize < Offset)
663 {
664 RtlZeroMemory((PVOID)((ULONG_PTR)Ace + Offset - AceSize),
665 AceSize);
666 }
667 }
668
669
670 /*
671 * @implemented
672 */
673 NTSTATUS NTAPI
674 RtlDeleteAce(PACL Acl,
675 ULONG AceIndex)
676 {
677 PACE Ace;
678 PACE Current;
679
680 PAGED_CODE_RTL();
681
682 if (Acl->AclRevision < MIN_ACL_REVISION ||
683 Acl->AclRevision > MAX_ACL_REVISION ||
684 Acl->AceCount <= AceIndex ||
685 !RtlFirstFreeAce(Acl, &Ace))
686 {
687 return(STATUS_INVALID_PARAMETER);
688 }
689
690 Current = (PACE)(Acl + 1);
691
692 while(AceIndex--)
693 {
694 Current = (PACE)((ULONG_PTR)Current + Current->Header.AceSize);
695 }
696
697 RtlpDeleteData(Current,
698 Current->Header.AceSize,
699 (ULONG)((ULONG_PTR)Ace - (ULONG_PTR)Current));
700 Acl->AceCount--;
701
702 return(STATUS_SUCCESS);
703 }
704
705
706 /*
707 * @implemented
708 */
709 NTSTATUS NTAPI
710 RtlCreateAcl(PACL Acl,
711 ULONG AclSize,
712 ULONG AclRevision)
713 {
714 PAGED_CODE_RTL();
715
716 if (AclSize < sizeof(ACL))
717 {
718 return(STATUS_BUFFER_TOO_SMALL);
719 }
720
721 if (AclRevision < MIN_ACL_REVISION ||
722 AclRevision > MAX_ACL_REVISION ||
723 AclSize > 0xffff)
724 {
725 return(STATUS_INVALID_PARAMETER);
726 }
727
728 AclSize = ROUND_UP(AclSize, 4);
729 Acl->AclSize = AclSize;
730 Acl->AclRevision = AclRevision;
731 Acl->AceCount = 0;
732 Acl->Sbz1 = 0;
733 Acl->Sbz2 = 0;
734
735 return(STATUS_SUCCESS);
736 }
737
738
739 /*
740 * @implemented
741 */
742 NTSTATUS NTAPI
743 RtlQueryInformationAcl(PACL Acl,
744 PVOID Information,
745 ULONG InformationLength,
746 ACL_INFORMATION_CLASS InformationClass)
747 {
748 PACE Ace;
749
750 PAGED_CODE_RTL();
751
752 if (Acl->AclRevision < MIN_ACL_REVISION ||
753 Acl->AclRevision > MAX_ACL_REVISION)
754 {
755 return(STATUS_INVALID_PARAMETER);
756 }
757
758 switch (InformationClass)
759 {
760 case AclRevisionInformation:
761 {
762 PACL_REVISION_INFORMATION Info = (PACL_REVISION_INFORMATION)Information;
763
764 if (InformationLength < sizeof(ACL_REVISION_INFORMATION))
765 {
766 return(STATUS_BUFFER_TOO_SMALL);
767 }
768 Info->AclRevision = Acl->AclRevision;
769 }
770 break;
771
772 case AclSizeInformation:
773 {
774 PACL_SIZE_INFORMATION Info = (PACL_SIZE_INFORMATION)Information;
775
776 if (InformationLength < sizeof(ACL_SIZE_INFORMATION))
777 {
778 return(STATUS_BUFFER_TOO_SMALL);
779 }
780
781 if (!RtlFirstFreeAce(Acl, &Ace))
782 {
783 return(STATUS_INVALID_PARAMETER);
784 }
785
786 Info->AceCount = Acl->AceCount;
787 if (Ace != NULL)
788 {
789 Info->AclBytesInUse = (DWORD)((ULONG_PTR)Ace - (ULONG_PTR)Acl);
790 Info->AclBytesFree = Acl->AclSize - Info->AclBytesInUse;
791 }
792 else
793 {
794 Info->AclBytesInUse = Acl->AclSize;
795 Info->AclBytesFree = 0;
796 }
797 }
798 break;
799
800 default:
801 return(STATUS_INVALID_INFO_CLASS);
802 }
803
804 return(STATUS_SUCCESS);
805 }
806
807
808 /*
809 * @implemented
810 */
811 NTSTATUS NTAPI
812 RtlSetInformationAcl(PACL Acl,
813 PVOID Information,
814 ULONG InformationLength,
815 ACL_INFORMATION_CLASS InformationClass)
816 {
817 PAGED_CODE_RTL();
818
819 if (Acl->AclRevision < MIN_ACL_REVISION ||
820 Acl->AclRevision > MAX_ACL_REVISION)
821 {
822 return(STATUS_INVALID_PARAMETER);
823 }
824
825 switch (InformationClass)
826 {
827 case AclRevisionInformation:
828 {
829 PACL_REVISION_INFORMATION Info = (PACL_REVISION_INFORMATION)Information;
830
831 if (InformationLength < sizeof(ACL_REVISION_INFORMATION))
832 {
833 return(STATUS_BUFFER_TOO_SMALL);
834 }
835
836 if (Acl->AclRevision >= Info->AclRevision)
837 {
838 return(STATUS_INVALID_PARAMETER);
839 }
840
841 Acl->AclRevision = Info->AclRevision;
842 }
843 break;
844
845 default:
846 return(STATUS_INVALID_INFO_CLASS);
847 }
848
849 return(STATUS_SUCCESS);
850 }
851
852
853 /*
854 * @implemented
855 */
856 BOOLEAN NTAPI
857 RtlValidAcl (PACL Acl)
858 {
859 PACE Ace;
860 USHORT Size;
861
862 PAGED_CODE_RTL();
863
864 Size = ROUND_UP(Acl->AclSize, 4);
865
866 if (Acl->AclRevision < MIN_ACL_REVISION ||
867 Acl->AclRevision > MAX_ACL_REVISION)
868 {
869 return(FALSE);
870 }
871
872 if (Size != Acl->AclSize)
873 {
874 return(FALSE);
875 }
876
877 return(RtlFirstFreeAce(Acl, &Ace));
878 }
879
880 /* EOF */