Implement NtAccessCheck.
[wine/gsoc-2012-control.git] / dlls / ntdll / sec.c
blobb85c0c862ff48f7615e5815c0a3031c765204a95
1 /*
2 * Security functions
4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <ctype.h>
30 #include <math.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
35 #include "windef.h"
36 #include "winbase.h"
37 #include "wine/exception.h"
38 #include "winreg.h"
39 #include "ntdll_misc.h"
40 #include "excpt.h"
41 #include "wine/library.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
46 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
48 /* filter for page-fault exceptions */
49 static WINE_EXCEPTION_FILTER(page_fault)
51 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
52 return EXCEPTION_EXECUTE_HANDLER;
53 return EXCEPTION_CONTINUE_SEARCH;
57 * SID FUNCTIONS
60 /******************************************************************************
61 * RtlAllocateAndInitializeSid [NTDLL.@]
64 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
65 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
66 BYTE nSubAuthorityCount,
67 DWORD nSubAuthority0, DWORD nSubAuthority1,
68 DWORD nSubAuthority2, DWORD nSubAuthority3,
69 DWORD nSubAuthority4, DWORD nSubAuthority5,
70 DWORD nSubAuthority6, DWORD nSubAuthority7,
71 PSID *pSid )
74 TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
75 pIdentifierAuthority,nSubAuthorityCount,
76 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
77 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
79 if (!(*pSid = RtlAllocateHeap( GetProcessHeap(), 0,
80 RtlLengthRequiredSid(nSubAuthorityCount))))
81 return STATUS_NO_MEMORY;
83 ((SID*)*pSid)->Revision = SID_REVISION;
85 if (pIdentifierAuthority)
86 memcpy(&((SID*)*pSid)->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
87 *RtlSubAuthorityCountSid(*pSid) = nSubAuthorityCount;
89 if (nSubAuthorityCount > 0)
90 *RtlSubAuthoritySid(*pSid, 0) = nSubAuthority0;
91 if (nSubAuthorityCount > 1)
92 *RtlSubAuthoritySid(*pSid, 1) = nSubAuthority1;
93 if (nSubAuthorityCount > 2)
94 *RtlSubAuthoritySid(*pSid, 2) = nSubAuthority2;
95 if (nSubAuthorityCount > 3)
96 *RtlSubAuthoritySid(*pSid, 3) = nSubAuthority3;
97 if (nSubAuthorityCount > 4)
98 *RtlSubAuthoritySid(*pSid, 4) = nSubAuthority4;
99 if (nSubAuthorityCount > 5)
100 *RtlSubAuthoritySid(*pSid, 5) = nSubAuthority5;
101 if (nSubAuthorityCount > 6)
102 *RtlSubAuthoritySid(*pSid, 6) = nSubAuthority6;
103 if (nSubAuthorityCount > 7)
104 *RtlSubAuthoritySid(*pSid, 7) = nSubAuthority7;
106 return STATUS_SUCCESS;
108 /******************************************************************************
109 * RtlEqualSid [NTDLL.@]
111 * Determine if two SIDs are equal.
113 * PARAMS
114 * pSid1 [I] Source SID
115 * pSid2 [I] SID to compare with
117 * RETURNS
118 * TRUE, if pSid1 is equal to pSid2,
119 * FALSE otherwise.
121 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
123 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
124 return FALSE;
126 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
127 return FALSE;
129 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
130 return FALSE;
132 return TRUE;
135 /******************************************************************************
136 * RtlEqualPrefixSid [NTDLL.@]
138 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
140 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
141 return FALSE;
143 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
144 return FALSE;
146 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
147 return FALSE;
149 return TRUE;
153 /******************************************************************************
154 * RtlFreeSid [NTDLL.@]
156 * Free the resources used by a SID.
158 * PARAMS
159 * pSid [I] SID to Free.
161 * RETURNS
162 * STATUS_SUCCESS.
164 DWORD WINAPI RtlFreeSid(PSID pSid)
166 TRACE("(%p)\n", pSid);
167 RtlFreeHeap( GetProcessHeap(), 0, pSid );
168 return STATUS_SUCCESS;
171 /**************************************************************************
172 * RtlLengthRequiredSid [NTDLL.@]
174 * Determine the amount of memory a SID will use
176 * PARAMS
177 * nrofsubauths [I] Number of Sub Authorities in the SID.
179 * RETURNS
180 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
182 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
184 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
187 /**************************************************************************
188 * RtlLengthSid [NTDLL.@]
190 * Determine the amount of memory a SID is using
192 * PARAMS
193 * pSid [I] SID to get the size of.
195 * RETURNS
196 * The size, in bytes, of pSid.
198 DWORD WINAPI RtlLengthSid(PSID pSid)
200 TRACE("sid=%p\n",pSid);
201 if (!pSid) return 0;
202 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
205 /**************************************************************************
206 * RtlInitializeSid [NTDLL.@]
208 * Initialise a SID.
210 * PARAMS
211 * pSid [I] SID to initialise
212 * pIdentifierAuthority [I] Identifier Authority
213 * nSubAuthorityCount [I] Number of Sub Authorities
215 * RETURNS
216 * Success: TRUE. pSid is initialised with the details given.
217 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
219 BOOL WINAPI RtlInitializeSid(
220 PSID pSid,
221 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
222 BYTE nSubAuthorityCount)
224 int i;
225 SID* pisid=pSid;
227 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
228 return FALSE;
230 pisid->Revision = SID_REVISION;
231 pisid->SubAuthorityCount = nSubAuthorityCount;
232 if (pIdentifierAuthority)
233 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
235 for (i = 0; i < nSubAuthorityCount; i++)
236 *RtlSubAuthoritySid(pSid, i) = 0;
238 return TRUE;
241 /**************************************************************************
242 * RtlSubAuthoritySid [NTDLL.@]
244 * Return the Sub Authority of a SID
246 * PARAMS
247 * pSid [I] SID to get the Sub Authority from.
248 * nSubAuthority [I] Sub Authority number.
250 * RETURNS
251 * A pointer to The Sub Authority value of pSid.
253 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
255 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
258 /**************************************************************************
259 * RtlIdentifierAuthoritySid [NTDLL.@]
261 * Return the Identifier Authority of a SID.
263 * PARAMS
264 * pSid [I] SID to get the Identifier Authority from.
266 * RETURNS
267 * A pointer to the Identifier Authority value of pSid.
269 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
271 return &(((SID*)pSid)->IdentifierAuthority);
274 /**************************************************************************
275 * RtlSubAuthorityCountSid [NTDLL.@]
277 * Get the number of Sub Authorities in a SID.
279 * PARAMS
280 * pSid [I] SID to get the count from.
282 * RETURNS
283 * A pointer to the Sub Authority count of pSid.
285 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
287 return &(((SID*)pSid)->SubAuthorityCount);
290 /**************************************************************************
291 * RtlCopySid [NTDLL.@]
293 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
295 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
296 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
297 return FALSE;
299 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
300 return FALSE;
302 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
303 return TRUE;
305 /******************************************************************************
306 * RtlValidSid [NTDLL.@]
308 * Determine if a SID is valid.
310 * PARAMS
311 * pSid [I] SID to check
313 * RETURNS
314 * TRUE if pSid is valid,
315 * FALSE otherwise.
317 BOOLEAN WINAPI RtlValidSid( PSID pSid )
319 BOOL ret;
320 __TRY
322 ret = TRUE;
323 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
324 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
326 ret = FALSE;
329 __EXCEPT(page_fault)
331 WARN("(%p): invalid pointer!\n", pSid);
332 return FALSE;
334 __ENDTRY
335 return ret;
340 * security descriptor functions
343 /**************************************************************************
344 * RtlCreateSecurityDescriptor [NTDLL.@]
346 * Initialise a SECURITY_DESCRIPTOR.
348 * PARAMS
349 * lpsd [O] Descriptor to initialise.
350 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
352 * RETURNS:
353 * Success: STATUS_SUCCESS.
354 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
356 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
357 PSECURITY_DESCRIPTOR lpsd,
358 DWORD rev)
360 if (rev!=SECURITY_DESCRIPTOR_REVISION)
361 return STATUS_UNKNOWN_REVISION;
362 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
363 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
364 return STATUS_SUCCESS;
366 /**************************************************************************
367 * RtlValidSecurityDescriptor [NTDLL.@]
369 * Determine if a SECURITY_DESCRIPTOR is valid.
371 * PARAMS
372 * SecurityDescriptor [I] Descriptor to check.
374 * RETURNS
375 * Success: STATUS_SUCCESS.
376 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
378 NTSTATUS WINAPI RtlValidSecurityDescriptor(
379 PSECURITY_DESCRIPTOR SecurityDescriptor)
381 if ( ! SecurityDescriptor )
382 return STATUS_INVALID_SECURITY_DESCR;
383 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
384 return STATUS_UNKNOWN_REVISION;
386 return STATUS_SUCCESS;
389 /**************************************************************************
390 * RtlLengthSecurityDescriptor [NTDLL.@]
392 ULONG WINAPI RtlLengthSecurityDescriptor(
393 PSECURITY_DESCRIPTOR pSecurityDescriptor)
395 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
396 ULONG offset = 0;
397 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
399 if ( lpsd == NULL )
400 return 0;
402 if ( lpsd->Control & SE_SELF_RELATIVE)
403 offset = (ULONG) lpsd;
405 if ( lpsd->Owner != NULL )
406 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
408 if ( lpsd->Group != NULL )
409 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
411 if ( (lpsd->Control & SE_SACL_PRESENT) &&
412 lpsd->Sacl != NULL )
413 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
415 if ( (lpsd->Control & SE_DACL_PRESENT) &&
416 lpsd->Dacl != NULL )
417 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
419 return Size;
422 /******************************************************************************
423 * RtlGetDaclSecurityDescriptor [NTDLL.@]
426 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
427 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
428 OUT PBOOLEAN lpbDaclPresent,
429 OUT PACL *pDacl,
430 OUT PBOOLEAN lpbDaclDefaulted)
432 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
434 TRACE("(%p,%p,%p,%p)\n",
435 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
437 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
438 return STATUS_UNKNOWN_REVISION ;
440 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
442 if ( SE_SELF_RELATIVE & lpsd->Control)
443 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
444 else
445 *pDacl = lpsd->Dacl;
447 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
450 return STATUS_SUCCESS;
453 /**************************************************************************
454 * RtlSetDaclSecurityDescriptor [NTDLL.@]
456 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
457 PSECURITY_DESCRIPTOR pSecurityDescriptor,
458 BOOLEAN daclpresent,
459 PACL dacl,
460 BOOLEAN dacldefaulted )
462 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
464 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
465 return STATUS_UNKNOWN_REVISION;
466 if (lpsd->Control & SE_SELF_RELATIVE)
467 return STATUS_INVALID_SECURITY_DESCR;
469 if (!daclpresent)
470 { lpsd->Control &= ~SE_DACL_PRESENT;
471 return TRUE;
474 lpsd->Control |= SE_DACL_PRESENT;
475 lpsd->Dacl = dacl;
477 if (dacldefaulted)
478 lpsd->Control |= SE_DACL_DEFAULTED;
479 else
480 lpsd->Control &= ~SE_DACL_DEFAULTED;
482 return STATUS_SUCCESS;
485 /******************************************************************************
486 * RtlGetSaclSecurityDescriptor [NTDLL.@]
489 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
490 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
491 OUT PBOOLEAN lpbSaclPresent,
492 OUT PACL *pSacl,
493 OUT PBOOLEAN lpbSaclDefaulted)
495 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
497 TRACE("(%p,%p,%p,%p)\n",
498 pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
500 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
501 return STATUS_UNKNOWN_REVISION;
503 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
505 if (SE_SELF_RELATIVE & lpsd->Control)
506 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Sacl);
507 else
508 *pSacl = lpsd->Sacl;
510 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
513 return STATUS_SUCCESS;
516 /**************************************************************************
517 * RtlSetSaclSecurityDescriptor [NTDLL.@]
519 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
520 PSECURITY_DESCRIPTOR pSecurityDescriptor,
521 BOOLEAN saclpresent,
522 PACL sacl,
523 BOOLEAN sacldefaulted)
525 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
527 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
528 return STATUS_UNKNOWN_REVISION;
529 if (lpsd->Control & SE_SELF_RELATIVE)
530 return STATUS_INVALID_SECURITY_DESCR;
531 if (!saclpresent) {
532 lpsd->Control &= ~SE_SACL_PRESENT;
533 return 0;
535 lpsd->Control |= SE_SACL_PRESENT;
536 lpsd->Sacl = sacl;
537 if (sacldefaulted)
538 lpsd->Control |= SE_SACL_DEFAULTED;
539 else
540 lpsd->Control &= ~SE_SACL_DEFAULTED;
541 return STATUS_SUCCESS;
544 /**************************************************************************
545 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
547 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
548 PSECURITY_DESCRIPTOR pSecurityDescriptor,
549 PSID *Owner,
550 PBOOLEAN OwnerDefaulted)
552 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
554 if ( !lpsd || !Owner || !OwnerDefaulted )
555 return STATUS_INVALID_PARAMETER;
557 if (lpsd->Owner != NULL)
559 if (lpsd->Control & SE_SELF_RELATIVE)
560 *Owner = (PSID)((LPBYTE)lpsd +
561 (ULONG)lpsd->Owner);
562 else
563 *Owner = lpsd->Owner;
565 if ( lpsd->Control & SE_OWNER_DEFAULTED )
566 *OwnerDefaulted = TRUE;
567 else
568 *OwnerDefaulted = FALSE;
570 else
571 *Owner = NULL;
573 return STATUS_SUCCESS;
576 /**************************************************************************
577 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
579 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
580 PSECURITY_DESCRIPTOR pSecurityDescriptor,
581 PSID owner,
582 BOOLEAN ownerdefaulted)
584 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
586 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
587 return STATUS_UNKNOWN_REVISION;
588 if (lpsd->Control & SE_SELF_RELATIVE)
589 return STATUS_INVALID_SECURITY_DESCR;
591 lpsd->Owner = owner;
592 if (ownerdefaulted)
593 lpsd->Control |= SE_OWNER_DEFAULTED;
594 else
595 lpsd->Control &= ~SE_OWNER_DEFAULTED;
596 return STATUS_SUCCESS;
599 /**************************************************************************
600 * RtlSetGroupSecurityDescriptor [NTDLL.@]
602 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
603 PSECURITY_DESCRIPTOR pSecurityDescriptor,
604 PSID group,
605 BOOLEAN groupdefaulted)
607 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
609 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
610 return STATUS_UNKNOWN_REVISION;
611 if (lpsd->Control & SE_SELF_RELATIVE)
612 return STATUS_INVALID_SECURITY_DESCR;
614 lpsd->Group = group;
615 if (groupdefaulted)
616 lpsd->Control |= SE_GROUP_DEFAULTED;
617 else
618 lpsd->Control &= ~SE_GROUP_DEFAULTED;
619 return STATUS_SUCCESS;
622 /**************************************************************************
623 * RtlGetGroupSecurityDescriptor [NTDLL.@]
625 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
626 PSECURITY_DESCRIPTOR pSecurityDescriptor,
627 PSID *Group,
628 PBOOLEAN GroupDefaulted)
630 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
632 if ( !lpsd || !Group || !GroupDefaulted )
633 return STATUS_INVALID_PARAMETER;
635 if (lpsd->Group != NULL)
637 if (lpsd->Control & SE_SELF_RELATIVE)
638 *Group = (PSID)((LPBYTE)lpsd +
639 (ULONG)lpsd->Group);
640 else
641 *Group = lpsd->Group;
643 if ( lpsd->Control & SE_GROUP_DEFAULTED )
644 *GroupDefaulted = TRUE;
645 else
646 *GroupDefaulted = FALSE;
648 else
649 *Group = NULL;
651 return STATUS_SUCCESS;
654 /**************************************************************************
655 * RtlMakeSelfRelativeSD [NTDLL.@]
657 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
658 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
659 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
660 IN OUT LPDWORD lpdwBufferLength)
662 ULONG offsetRel;
663 ULONG length;
664 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
665 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
667 TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
668 lpdwBufferLength ? *lpdwBufferLength: -1);
670 if (!lpdwBufferLength || !pAbs)
671 return STATUS_INVALID_PARAMETER;
673 length = RtlLengthSecurityDescriptor(pAbs);
674 if (*lpdwBufferLength < length)
676 *lpdwBufferLength = length;
677 return STATUS_BUFFER_TOO_SMALL;
680 if (!pRel)
681 return STATUS_INVALID_PARAMETER;
683 if (pAbs->Control & SE_SELF_RELATIVE)
685 memcpy(pRel, pAbs, length);
686 return STATUS_SUCCESS;
689 pRel->Revision = pAbs->Revision;
690 pRel->Sbz1 = pAbs->Sbz1;
691 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
693 offsetRel = sizeof(SECURITY_DESCRIPTOR);
694 pRel->Owner = (PSID) offsetRel;
695 length = RtlLengthSid(pAbs->Owner);
696 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
698 offsetRel += length;
699 pRel->Group = (PSID) offsetRel;
700 length = RtlLengthSid(pAbs->Group);
701 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
703 if (pRel->Control & SE_SACL_PRESENT)
705 offsetRel += length;
706 pRel->Sacl = (PACL) offsetRel;
707 length = pAbs->Sacl->AclSize;
708 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
710 else
712 pRel->Sacl = NULL;
715 if (pRel->Control & SE_DACL_PRESENT)
717 offsetRel += length;
718 pRel->Dacl = (PACL) offsetRel;
719 length = pAbs->Dacl->AclSize;
720 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
722 else
724 pRel->Dacl = NULL;
727 return STATUS_SUCCESS;
731 /**************************************************************************
732 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
734 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
735 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
736 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
737 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
738 OUT PACL pDacl,
739 OUT LPDWORD lpdwDaclSize,
740 OUT PACL pSacl,
741 OUT LPDWORD lpdwSaclSize,
742 OUT PSID pOwner,
743 OUT LPDWORD lpdwOwnerSize,
744 OUT PSID pPrimaryGroup,
745 OUT LPDWORD lpdwPrimaryGroupSize)
747 NTSTATUS status = STATUS_SUCCESS;
748 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
749 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
751 if (!pRel ||
752 !lpdwAbsoluteSecurityDescriptorSize ||
753 !lpdwDaclSize ||
754 !lpdwSaclSize ||
755 !lpdwOwnerSize ||
756 !lpdwPrimaryGroupSize ||
757 ~pRel->Control & SE_SELF_RELATIVE)
758 return STATUS_INVALID_PARAMETER;
760 /* Confirm buffers are sufficiently large */
761 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
763 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
764 status = STATUS_BUFFER_TOO_SMALL;
767 if (pRel->Control & SE_DACL_PRESENT &&
768 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
770 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
771 status = STATUS_BUFFER_TOO_SMALL;
774 if (pRel->Control & SE_SACL_PRESENT &&
775 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
777 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
778 status = STATUS_BUFFER_TOO_SMALL;
781 if (pRel->Owner &&
782 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
784 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
785 status = STATUS_BUFFER_TOO_SMALL;
788 if (pRel->Group &&
789 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
791 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
792 status = STATUS_BUFFER_TOO_SMALL;
795 if (status != STATUS_SUCCESS)
796 return status;
798 /* Copy structures */
799 pAbs->Revision = pRel->Revision;
800 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
802 if (pRel->Control & SE_SACL_PRESENT)
804 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
806 memcpy(pSacl, pAcl, pAcl->AclSize);
807 pAbs->Sacl = pSacl;
810 if (pRel->Control & SE_DACL_PRESENT)
812 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
813 memcpy(pDacl, pAcl, pAcl->AclSize);
814 pAbs->Dacl = pDacl;
817 if (pRel->Owner)
819 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
820 memcpy(pOwner, psid, RtlLengthSid(psid));
821 pAbs->Owner = pOwner;
824 if (pRel->Group)
826 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
827 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
828 pAbs->Group = pPrimaryGroup;
831 return status;
835 /**************************************************************************
836 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
838 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
839 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
840 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
841 PULONG BufferLength)
843 FIXME("%p %p %p\n", AbsoluteSecurityDescriptor,
844 SelfRelativeSecurityDescriptor, BufferLength);
845 return STATUS_NOT_IMPLEMENTED;
850 * access control list's
853 /**************************************************************************
854 * RtlCreateAcl [NTDLL.@]
856 * NOTES
857 * This should return NTSTATUS
859 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
861 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
863 if (rev!=ACL_REVISION)
864 return STATUS_INVALID_PARAMETER;
865 if (size<sizeof(ACL))
866 return STATUS_BUFFER_TOO_SMALL;
867 if (size>0xFFFF)
868 return STATUS_INVALID_PARAMETER;
870 memset(acl,'\0',sizeof(ACL));
871 acl->AclRevision = rev;
872 acl->AclSize = size;
873 acl->AceCount = 0;
874 return STATUS_SUCCESS;
877 /**************************************************************************
878 * RtlFirstFreeAce [NTDLL.@]
879 * looks for the AceCount+1 ACE, and if it is still within the alloced
880 * ACL, return a pointer to it
882 BOOLEAN WINAPI RtlFirstFreeAce(
883 PACL acl,
884 PACE_HEADER *x)
886 PACE_HEADER ace;
887 int i;
889 *x = 0;
890 ace = (PACE_HEADER)(acl+1);
891 for (i=0;i<acl->AceCount;i++) {
892 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
893 return 0;
894 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
896 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
897 return 0;
898 *x = ace;
899 return 1;
902 /**************************************************************************
903 * RtlAddAce [NTDLL.@]
905 NTSTATUS WINAPI RtlAddAce(
906 PACL acl,
907 DWORD rev,
908 DWORD xnrofaces,
909 PACE_HEADER acestart,
910 DWORD acelen)
912 PACE_HEADER ace,targetace;
913 int nrofaces;
915 if (acl->AclRevision != ACL_REVISION)
916 return STATUS_INVALID_PARAMETER;
917 if (!RtlFirstFreeAce(acl,&targetace))
918 return STATUS_INVALID_PARAMETER;
919 nrofaces=0;ace=acestart;
920 while (((DWORD)ace-(DWORD)acestart)<acelen) {
921 nrofaces++;
922 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
924 if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
925 return STATUS_INVALID_PARAMETER;
926 memcpy((LPBYTE)targetace,acestart,acelen);
927 acl->AceCount+=nrofaces;
928 return STATUS_SUCCESS;
931 /**************************************************************************
932 * RtlDeleteAce [NTDLL.@]
934 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
936 NTSTATUS status;
937 PACE_HEADER pAce;
939 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
941 if (STATUS_SUCCESS == status)
943 PACE_HEADER pcAce;
944 DWORD len = 0;
946 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
947 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
949 len += pcAce->AceSize;
950 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
953 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
954 pAcl->AceCount--;
957 TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl, dwAceIndex, status);
959 return status;
962 /******************************************************************************
963 * RtlAddAccessAllowedAce [NTDLL.@]
965 NTSTATUS WINAPI RtlAddAccessAllowedAce(
966 IN OUT PACL pAcl,
967 IN DWORD dwAceRevision,
968 IN DWORD AccessMask,
969 IN PSID pSid)
971 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
974 /******************************************************************************
975 * RtlAddAccessAllowedAceEx [NTDLL.@]
977 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
978 IN OUT PACL pAcl,
979 IN DWORD dwAceRevision,
980 IN DWORD AceFlags,
981 IN DWORD AccessMask,
982 IN PSID pSid)
984 DWORD dwLengthSid;
985 ACCESS_ALLOWED_ACE * pAaAce;
986 DWORD dwSpaceLeft;
988 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
989 pAcl, dwAceRevision, AccessMask, pSid);
991 if (!RtlValidSid(pSid))
992 return STATUS_INVALID_SID;
993 if (!RtlValidAcl(pAcl))
994 return STATUS_INVALID_ACL;
996 dwLengthSid = RtlLengthSid(pSid);
997 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
998 return STATUS_INVALID_ACL;
1000 if (!pAaAce)
1001 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1003 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
1004 if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
1005 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1007 pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
1008 pAaAce->Header.AceFlags = AceFlags;
1009 pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
1010 pAaAce->Mask = AccessMask;
1011 pAcl->AceCount++;
1012 RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
1013 return STATUS_SUCCESS;
1016 /******************************************************************************
1017 * RtlAddAccessDeniedAce [NTDLL.@]
1019 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1020 IN OUT PACL pAcl,
1021 IN DWORD dwAceRevision,
1022 IN DWORD AccessMask,
1023 IN PSID pSid)
1025 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1028 /******************************************************************************
1029 * RtlAddAccessDeniedAceEx [NTDLL.@]
1031 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1032 IN OUT PACL pAcl,
1033 IN DWORD dwAceRevision,
1034 IN DWORD AceFlags,
1035 IN DWORD AccessMask,
1036 IN PSID pSid)
1038 DWORD dwLengthSid;
1039 DWORD dwSpaceLeft;
1040 ACCESS_DENIED_ACE * pAdAce;
1042 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1043 pAcl, dwAceRevision, AccessMask, pSid);
1045 if (!RtlValidSid(pSid))
1046 return STATUS_INVALID_SID;
1047 if (!RtlValidAcl(pAcl))
1048 return STATUS_INVALID_ACL;
1050 dwLengthSid = RtlLengthSid(pSid);
1051 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
1052 return STATUS_INVALID_ACL;
1054 if (!pAdAce)
1055 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1057 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1058 if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1059 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1061 pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1062 pAdAce->Header.AceFlags = AceFlags;
1063 pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1064 pAdAce->Mask = AccessMask;
1065 pAcl->AceCount++;
1066 RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1067 return STATUS_SUCCESS;
1070 /******************************************************************************
1071 * RtlValidAcl [NTDLL.@]
1073 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1075 BOOLEAN ret;
1076 TRACE("(%p)\n", pAcl);
1078 __TRY
1080 PACE_HEADER ace;
1081 int i;
1083 if (pAcl->AclRevision != ACL_REVISION)
1084 ret = FALSE;
1085 else
1087 ace = (PACE_HEADER)(pAcl+1);
1088 ret = TRUE;
1089 for (i=0;i<=pAcl->AceCount;i++)
1091 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1093 ret = FALSE;
1094 break;
1096 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1100 __EXCEPT(page_fault)
1102 WARN("(%p): invalid pointer!\n", pAcl);
1103 return 0;
1105 __ENDTRY
1106 return ret;
1109 /******************************************************************************
1110 * RtlGetAce [NTDLL.@]
1112 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1114 PACE_HEADER ace;
1116 TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1118 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1119 return STATUS_INVALID_PARAMETER;
1121 ace = (PACE_HEADER)(pAcl + 1);
1122 for (;dwAceIndex;dwAceIndex--)
1123 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1125 *pAce = (LPVOID) ace;
1127 return STATUS_SUCCESS;
1131 * misc
1134 /******************************************************************************
1135 * RtlAdjustPrivilege [NTDLL.@]
1137 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
1139 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
1140 return 0;
1143 /******************************************************************************
1144 * RtlImpersonateSelf [NTDLL.@]
1146 BOOL WINAPI
1147 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1149 FIXME("(%08x), stub\n", ImpersonationLevel);
1150 return TRUE;
1153 /******************************************************************************
1154 * NtAccessCheck [NTDLL.@]
1155 * ZwAccessCheck [NTDLL.@]
1157 * Checks that a user represented by a token is allowed to access an object
1158 * represented by a security descriptor.
1160 * PARAMS
1161 * SecurityDescriptor [I] The security descriptor of the object to check.
1162 * ClientToken [I] Token of the user accessing the object.
1163 * DesiredAccess [I] The desired access to the object.
1164 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1165 * PrivilegeSet [I/O] Privileges used during the access check.
1166 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1167 * GrantedAccess [O] The actual access rights granted.
1168 * AccessStatus [O] The status of the access check.
1170 * RETURNS
1171 * NTSTATUS code.
1173 * NOTES
1174 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1175 * the maximum access rights allowed by the SD and returns them in
1176 * GrantedAccess.
1177 * The SecurityDescriptor must have a valid owner and groups present,
1178 * otherwise the function will fail.
1180 NTSTATUS WINAPI
1181 NtAccessCheck(
1182 PSECURITY_DESCRIPTOR SecurityDescriptor,
1183 HANDLE ClientToken,
1184 ACCESS_MASK DesiredAccess,
1185 PGENERIC_MAPPING GenericMapping,
1186 PPRIVILEGE_SET PrivilegeSet,
1187 PULONG ReturnLength,
1188 PULONG GrantedAccess,
1189 NTSTATUS *AccessStatus)
1191 NTSTATUS status;
1193 TRACE("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1194 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1195 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1197 SERVER_START_REQ( access_check )
1199 struct security_descriptor sd;
1200 const SECURITY_DESCRIPTOR * RealSD = (const SECURITY_DESCRIPTOR *)SecurityDescriptor;
1202 req->handle = ClientToken;
1203 req->desired_access = DesiredAccess;
1204 req->mapping_read = GenericMapping->GenericRead;
1205 req->mapping_write = GenericMapping->GenericWrite;
1206 req->mapping_execute = GenericMapping->GenericExecute;
1207 req->mapping_all = GenericMapping->GenericAll;
1209 /* marshal security descriptor */
1210 sd.control = RealSD->Control;
1211 sd.owner_len = RtlLengthSid( RealSD->Owner );
1212 sd.group_len = RtlLengthSid( RealSD->Group );
1213 sd.sacl_len = (RealSD->Sacl ? RealSD->Sacl->AclSize : 0);
1214 sd.dacl_len = (RealSD->Dacl ? RealSD->Dacl->AclSize : 0);
1215 wine_server_add_data( req, &sd, sizeof(sd) );
1216 wine_server_add_data( req, RealSD->Owner, sd.owner_len );
1217 wine_server_add_data( req, RealSD->Group, sd.group_len );
1218 wine_server_add_data( req, RealSD->Sacl, sd.sacl_len );
1219 wine_server_add_data( req, RealSD->Dacl, sd.dacl_len );
1221 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1223 status = wine_server_call( req );
1225 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1226 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1228 if (status == STATUS_SUCCESS)
1229 *AccessStatus = reply->access_status;
1230 *GrantedAccess = reply->access_granted;
1232 SERVER_END_REQ;
1234 return status;
1237 /******************************************************************************
1238 * NtSetSecurityObject [NTDLL.@]
1240 NTSTATUS WINAPI
1241 NtSetSecurityObject(
1242 IN HANDLE Handle,
1243 IN SECURITY_INFORMATION SecurityInformation,
1244 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1246 FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1247 return STATUS_SUCCESS;
1250 /******************************************************************************
1251 * RtlGetControlSecurityDescriptor (NTDLL.@)
1254 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1255 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1256 PSECURITY_DESCRIPTOR_CONTROL pControl,
1257 LPDWORD lpdwRevision)
1259 FIXME("(%p,%p,%p),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
1260 return STATUS_SUCCESS;
1263 /******************************************************************************
1264 * RtlConvertSidToUnicodeString (NTDLL.@)
1266 * The returned SID is used to access the USER registry hive usually
1268 * the native function returns something like
1269 * "S-1-5-21-0000000000-000000000-0000000000-500";
1271 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1272 PUNICODE_STRING String,
1273 PSID Sid,
1274 BOOLEAN AllocateString)
1276 const char *user = wine_get_user_name();
1277 int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 ) * sizeof(WCHAR);
1279 FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1281 String->Length = len - sizeof(WCHAR);
1282 if (AllocateString)
1284 String->MaximumLength = len;
1285 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1286 return STATUS_NO_MEMORY;
1288 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1290 ntdll_umbstowcs( 0, user, strlen(user)+1, String->Buffer, len/sizeof(WCHAR) );
1291 return STATUS_SUCCESS;
1294 /******************************************************************************
1295 * RtlQueryInformationAcl (NTDLL.@)
1297 NTSTATUS WINAPI RtlQueryInformationAcl(
1298 PACL pAcl,
1299 LPVOID pAclInformation,
1300 DWORD nAclInformationLength,
1301 ACL_INFORMATION_CLASS dwAclInformationClass)
1303 NTSTATUS status = STATUS_SUCCESS;
1305 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1306 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1308 switch (dwAclInformationClass)
1310 case AclRevisionInformation:
1312 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1314 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1315 status = STATUS_INVALID_PARAMETER;
1316 else
1317 paclrev->AclRevision = pAcl->AclRevision;
1319 break;
1322 case AclSizeInformation:
1324 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1326 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1327 status = STATUS_INVALID_PARAMETER;
1328 else
1330 INT i;
1331 PACE_HEADER ace;
1333 paclsize->AceCount = pAcl->AceCount;
1335 paclsize->AclBytesInUse = 0;
1336 ace = (PACE_HEADER) (pAcl + 1);
1338 for (i = 0; i < pAcl->AceCount; i++)
1340 paclsize->AclBytesInUse += ace->AceSize;
1341 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1344 if (pAcl->AclSize < paclsize->AclBytesInUse)
1346 WARN("Acl has %ld bytes free\n", paclsize->AclBytesFree);
1347 paclsize->AclBytesFree = 0;
1348 paclsize->AclBytesInUse = pAcl->AclSize;
1350 else
1351 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1354 break;
1357 default:
1358 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1359 status = STATUS_INVALID_PARAMETER;
1362 return status;