Fix incorrect sizeof in RtlCreateSecurityDescriptor().
[wine/wine64.git] / dlls / ntdll / sec.c
blobf5fa23fb105692242fc06df2b5757ac9a6a84dd4
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 "winnls.h"
39 #include "winerror.h"
40 #include "winreg.h"
41 #include "winternl.h"
42 #include "ntdll_misc.h"
43 #include "excpt.h"
44 #include "wine/library.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
49 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
51 /* filter for page-fault exceptions */
52 static WINE_EXCEPTION_FILTER(page_fault)
54 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
55 return EXCEPTION_EXECUTE_HANDLER;
56 return EXCEPTION_CONTINUE_SEARCH;
60 * SID FUNCTIONS
63 /******************************************************************************
64 * RtlAllocateAndInitializeSid [NTDLL.@]
67 BOOLEAN WINAPI RtlAllocateAndInitializeSid (
68 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
69 BYTE nSubAuthorityCount,
70 DWORD nSubAuthority0, DWORD nSubAuthority1,
71 DWORD nSubAuthority2, DWORD nSubAuthority3,
72 DWORD nSubAuthority4, DWORD nSubAuthority5,
73 DWORD nSubAuthority6, DWORD nSubAuthority7,
74 PSID *pSid )
77 TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
78 pIdentifierAuthority,nSubAuthorityCount,
79 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
80 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
82 if (!(*pSid = RtlAllocateHeap( GetProcessHeap(), 0,
83 RtlLengthRequiredSid(nSubAuthorityCount))))
84 return FALSE;
86 ((SID*)*pSid)->Revision = SID_REVISION;
88 if (pIdentifierAuthority)
89 memcpy(&((SID*)*pSid)->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
90 *RtlSubAuthorityCountSid(*pSid) = nSubAuthorityCount;
92 if (nSubAuthorityCount > 0)
93 *RtlSubAuthoritySid(*pSid, 0) = nSubAuthority0;
94 if (nSubAuthorityCount > 1)
95 *RtlSubAuthoritySid(*pSid, 1) = nSubAuthority1;
96 if (nSubAuthorityCount > 2)
97 *RtlSubAuthoritySid(*pSid, 2) = nSubAuthority2;
98 if (nSubAuthorityCount > 3)
99 *RtlSubAuthoritySid(*pSid, 3) = nSubAuthority3;
100 if (nSubAuthorityCount > 4)
101 *RtlSubAuthoritySid(*pSid, 4) = nSubAuthority4;
102 if (nSubAuthorityCount > 5)
103 *RtlSubAuthoritySid(*pSid, 5) = nSubAuthority5;
104 if (nSubAuthorityCount > 6)
105 *RtlSubAuthoritySid(*pSid, 6) = nSubAuthority6;
106 if (nSubAuthorityCount > 7)
107 *RtlSubAuthoritySid(*pSid, 7) = nSubAuthority7;
109 return STATUS_SUCCESS;
111 /******************************************************************************
112 * RtlEqualSid [NTDLL.@]
114 * Determine if two SIDs are equal.
116 * PARAMS
117 * pSid1 [I] Source SID
118 * pSid2 [I] SID to compare with
120 * RETURNS
121 * TRUE, if pSid1 is equal to pSid2,
122 * FALSE otherwise.
124 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
126 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
127 return FALSE;
129 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
130 return FALSE;
132 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
133 return FALSE;
135 return TRUE;
138 /******************************************************************************
139 * RtlEqualPrefixSid [NTDLL.@]
141 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
143 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
144 return FALSE;
146 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
147 return FALSE;
149 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
150 return FALSE;
152 return TRUE;
156 /******************************************************************************
157 * RtlFreeSid [NTDLL.@]
159 * Free the resources used by a SID.
161 * PARAMS
162 * pSid [I] SID to Free.
164 * RETURNS
165 * STATUS_SUCCESS.
167 DWORD WINAPI RtlFreeSid(PSID pSid)
169 TRACE("(%p)\n", pSid);
170 RtlFreeHeap( GetProcessHeap(), 0, pSid );
171 return STATUS_SUCCESS;
174 /**************************************************************************
175 * RtlLengthRequiredSid [NTDLL.@]
177 * Determine the amount of memory a SID will use
179 * PARAMS
180 * nrofsubauths [I] Number of Sub Authorities in the SID.
182 * RETURNS
183 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
185 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
187 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
190 /**************************************************************************
191 * RtlLengthSid [NTDLL.@]
193 * Determine the amount of memory a SID is using
195 * PARAMS
196 * pSid [I] SID to ge the size of.
198 * RETURNS
199 * The size, in bytes, of pSid.
201 DWORD WINAPI RtlLengthSid(PSID pSid)
203 TRACE("sid=%p\n",pSid);
204 if (!pSid) return 0;
205 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
208 /**************************************************************************
209 * RtlInitializeSid [NTDLL.@]
211 * Initialise a SID.
213 * PARAMS
214 * pSid [I] SID to initialise
215 * pIdentifierAuthority [I] Identifier Authority
216 * nSubAuthorityCount [I] Number of Sub Authorities
218 * RETURNS
219 * Success: TRUE. pSid is initialised withe the details given.
220 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
222 BOOL WINAPI RtlInitializeSid(
223 PSID pSid,
224 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
225 BYTE nSubAuthorityCount)
227 int i;
228 SID* pisid=pSid;
230 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
231 return FALSE;
233 pisid->Revision = SID_REVISION;
234 pisid->SubAuthorityCount = nSubAuthorityCount;
235 if (pIdentifierAuthority)
236 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
238 for (i = 0; i < nSubAuthorityCount; i++)
239 *RtlSubAuthoritySid(pSid, i) = 0;
241 return TRUE;
244 /**************************************************************************
245 * RtlSubAuthoritySid [NTDLL.@]
247 * Return the Sub Authority of a SID
249 * PARAMS
250 * pSid [I] SID to get the Sub Authority from.
251 * nSubAuthority [I] Sub Authority number.
253 * RETURNS
254 * A pointer to The Sub Authority value of pSid.
256 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
258 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
261 /**************************************************************************
262 * RtlIdentifierAuthoritySid [NTDLL.@]
264 * Return the Identifier Authority of a SID.
266 * PARAMS
267 * pSid [I] SID to get the Identifier Authority from.
269 * RETURNS
270 * A pointer to the Identifier Authority value of pSid.
272 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
274 return &(((SID*)pSid)->IdentifierAuthority);
277 /**************************************************************************
278 * RtlSubAuthorityCountSid [NTDLL.@]
280 * Get the number of Sub Authorities in a SID.
282 * PARAMS
283 * pSid [I] SID to get the count from.
285 * RETURNS
286 * A pointer to the Sub Authority count of pSid.
288 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
290 return &(((SID*)pSid)->SubAuthorityCount);
293 /**************************************************************************
294 * RtlCopySid [NTDLL.@]
296 DWORD WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
298 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
299 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
300 return FALSE;
302 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
303 return FALSE;
305 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
306 return TRUE;
308 /******************************************************************************
309 * RtlValidSid [NTDLL.@]
311 * Determine if a SID is valid.
313 * PARAMS
314 * pSid [I] SID to check
316 * RETURNS
317 * TRUE if pSid is valid,
318 * FALSE otherwise.
320 BOOLEAN WINAPI RtlValidSid( PSID pSid )
322 BOOL ret;
323 __TRY
325 ret = TRUE;
326 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
327 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
329 ret = FALSE;
332 __EXCEPT(page_fault)
334 WARN("(%p): invalid pointer!\n", pSid);
335 return FALSE;
337 __ENDTRY
338 return ret;
343 * security descriptor functions
346 /**************************************************************************
347 * RtlCreateSecurityDescriptor [NTDLL.@]
349 * Initialise a SECURITY_DESCRIPTOR.
351 * PARAMS
352 * lpsd [O] Descriptor to initialise.
353 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
355 * RETURNS:
356 * Success: STATUS_SUCCESS.
357 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
359 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
360 PSECURITY_DESCRIPTOR lpsd,
361 DWORD rev)
363 if (rev!=SECURITY_DESCRIPTOR_REVISION)
364 return STATUS_UNKNOWN_REVISION;
365 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
366 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
367 return STATUS_SUCCESS;
369 /**************************************************************************
370 * RtlValidSecurityDescriptor [NTDLL.@]
372 * Determine if a SECURITY_DESCRIPTOR is valid.
374 * PARAMS
375 * SecurityDescriptor [I] Descriptor to check.
377 * RETURNS
378 * Success: STATUS_SUCCESS.
379 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
381 NTSTATUS WINAPI RtlValidSecurityDescriptor(
382 PSECURITY_DESCRIPTOR SecurityDescriptor)
384 if ( ! SecurityDescriptor )
385 return STATUS_INVALID_SECURITY_DESCR;
386 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
387 return STATUS_UNKNOWN_REVISION;
389 return STATUS_SUCCESS;
392 /**************************************************************************
393 * RtlLengthSecurityDescriptor [NTDLL.@]
395 ULONG WINAPI RtlLengthSecurityDescriptor(
396 PSECURITY_DESCRIPTOR pSecurityDescriptor)
398 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
399 ULONG offset = 0;
400 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
402 if ( lpsd == NULL )
403 return 0;
405 if ( lpsd->Control & SE_SELF_RELATIVE)
406 offset = (ULONG) lpsd;
408 if ( lpsd->Owner != NULL )
409 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
411 if ( lpsd->Group != NULL )
412 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
414 if ( lpsd->Sacl != NULL )
415 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
417 if ( lpsd->Dacl != NULL )
418 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
420 return Size;
423 /******************************************************************************
424 * RtlGetDaclSecurityDescriptor [NTDLL.@]
427 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
428 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
429 OUT PBOOLEAN lpbDaclPresent,
430 OUT PACL *pDacl,
431 OUT PBOOLEAN lpbDaclDefaulted)
433 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
435 TRACE("(%p,%p,%p,%p)\n",
436 pSecurityDescriptor, lpbDaclPresent, *pDacl, lpbDaclDefaulted);
438 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
439 return STATUS_UNKNOWN_REVISION ;
441 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
443 if ( SE_SELF_RELATIVE & lpsd->Control)
444 { *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
446 else
447 { *pDacl = lpsd->Dacl;
451 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
453 return STATUS_SUCCESS;
456 /**************************************************************************
457 * RtlSetDaclSecurityDescriptor [NTDLL.@]
459 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
460 PSECURITY_DESCRIPTOR pSecurityDescriptor,
461 BOOLEAN daclpresent,
462 PACL dacl,
463 BOOLEAN dacldefaulted )
465 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
467 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
468 return STATUS_UNKNOWN_REVISION;
469 if (lpsd->Control & SE_SELF_RELATIVE)
470 return STATUS_INVALID_SECURITY_DESCR;
472 if (!daclpresent)
473 { lpsd->Control &= ~SE_DACL_PRESENT;
474 return TRUE;
477 lpsd->Control |= SE_DACL_PRESENT;
478 lpsd->Dacl = dacl;
480 if (dacldefaulted)
481 lpsd->Control |= SE_DACL_DEFAULTED;
482 else
483 lpsd->Control &= ~SE_DACL_DEFAULTED;
485 return STATUS_SUCCESS;
488 /******************************************************************************
489 * RtlGetSaclSecurityDescriptor [NTDLL.@]
492 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
493 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
494 OUT PBOOLEAN lpbSaclPresent,
495 OUT PACL *pSacl,
496 OUT PBOOLEAN lpbSaclDefaulted)
498 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
500 TRACE("(%p,%p,%p,%p)\n",
501 pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
503 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
504 return STATUS_UNKNOWN_REVISION ;
506 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
508 if ( SE_SELF_RELATIVE & lpsd->Control)
509 { *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Sacl);
511 else
512 { *pSacl = lpsd->Sacl;
516 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
518 return STATUS_SUCCESS;
521 /**************************************************************************
522 * RtlSetSaclSecurityDescriptor [NTDLL.@]
524 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
525 PSECURITY_DESCRIPTOR pSecurityDescriptor,
526 BOOLEAN saclpresent,
527 PACL sacl,
528 BOOLEAN sacldefaulted)
530 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
532 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
533 return STATUS_UNKNOWN_REVISION;
534 if (lpsd->Control & SE_SELF_RELATIVE)
535 return STATUS_INVALID_SECURITY_DESCR;
536 if (!saclpresent) {
537 lpsd->Control &= ~SE_SACL_PRESENT;
538 return 0;
540 lpsd->Control |= SE_SACL_PRESENT;
541 lpsd->Sacl = sacl;
542 if (sacldefaulted)
543 lpsd->Control |= SE_SACL_DEFAULTED;
544 else
545 lpsd->Control &= ~SE_SACL_DEFAULTED;
546 return STATUS_SUCCESS;
549 /**************************************************************************
550 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
552 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
553 PSECURITY_DESCRIPTOR pSecurityDescriptor,
554 PSID *Owner,
555 PBOOLEAN OwnerDefaulted)
557 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
559 if ( !lpsd || !Owner || !OwnerDefaulted )
560 return STATUS_INVALID_PARAMETER;
562 if (lpsd->Owner != NULL)
564 if (lpsd->Control & SE_SELF_RELATIVE)
565 *Owner = (PSID)((LPBYTE)lpsd +
566 (ULONG)lpsd->Owner);
567 else
568 *Owner = lpsd->Owner;
570 if ( lpsd->Control & SE_OWNER_DEFAULTED )
571 *OwnerDefaulted = TRUE;
572 else
573 *OwnerDefaulted = FALSE;
575 else
576 *Owner = NULL;
578 return STATUS_SUCCESS;
581 /**************************************************************************
582 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
584 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
585 PSECURITY_DESCRIPTOR pSecurityDescriptor,
586 PSID owner,
587 BOOLEAN ownerdefaulted)
589 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
591 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
592 return STATUS_UNKNOWN_REVISION;
593 if (lpsd->Control & SE_SELF_RELATIVE)
594 return STATUS_INVALID_SECURITY_DESCR;
596 lpsd->Owner = owner;
597 if (ownerdefaulted)
598 lpsd->Control |= SE_OWNER_DEFAULTED;
599 else
600 lpsd->Control &= ~SE_OWNER_DEFAULTED;
601 return STATUS_SUCCESS;
604 /**************************************************************************
605 * RtlSetGroupSecurityDescriptor [NTDLL.@]
607 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
608 PSECURITY_DESCRIPTOR pSecurityDescriptor,
609 PSID group,
610 BOOLEAN groupdefaulted)
612 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
614 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
615 return STATUS_UNKNOWN_REVISION;
616 if (lpsd->Control & SE_SELF_RELATIVE)
617 return STATUS_INVALID_SECURITY_DESCR;
619 lpsd->Group = group;
620 if (groupdefaulted)
621 lpsd->Control |= SE_GROUP_DEFAULTED;
622 else
623 lpsd->Control &= ~SE_GROUP_DEFAULTED;
624 return STATUS_SUCCESS;
626 /**************************************************************************
627 * RtlGetGroupSecurityDescriptor [NTDLL.@]
629 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
630 PSECURITY_DESCRIPTOR pSecurityDescriptor,
631 PSID *Group,
632 PBOOLEAN GroupDefaulted)
634 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
636 if ( !lpsd || !Group || !GroupDefaulted )
637 return STATUS_INVALID_PARAMETER;
639 if (lpsd->Group != NULL)
641 if (lpsd->Control & SE_SELF_RELATIVE)
642 *Group = (PSID)((LPBYTE)lpsd +
643 (ULONG)lpsd->Group);
644 else
645 *Group = lpsd->Group;
647 if ( lpsd->Control & SE_GROUP_DEFAULTED )
648 *GroupDefaulted = TRUE;
649 else
650 *GroupDefaulted = FALSE;
652 else
653 *Group = NULL;
655 return STATUS_SUCCESS;
658 /**************************************************************************
659 * RtlMakeSelfRelativeSD [NTDLL.@]
661 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
662 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
663 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
664 IN OUT LPDWORD lpdwBufferLength)
666 ULONG offsetRel;
667 ULONG length;
668 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
669 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
671 TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
672 lpdwBufferLength ? *lpdwBufferLength: -1);
674 if (!lpdwBufferLength || !pAbs)
675 return STATUS_INVALID_PARAMETER;
677 length = RtlLengthSecurityDescriptor(pAbs);
678 if (*lpdwBufferLength < length)
680 *lpdwBufferLength = length;
681 return STATUS_BUFFER_TOO_SMALL;
684 if (!pRel)
685 return STATUS_INVALID_PARAMETER;
687 if (pAbs->Control & SE_SELF_RELATIVE)
689 memcpy(pRel, pAbs, length);
690 return STATUS_SUCCESS;
693 pRel->Revision = pAbs->Revision;
694 pRel->Sbz1 = pAbs->Sbz1;
695 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
697 offsetRel = sizeof(SECURITY_DESCRIPTOR);
698 pRel->Owner = (PSID) offsetRel;
699 length = RtlLengthSid(pAbs->Owner);
700 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
702 offsetRel += length;
703 pRel->Group = (PSID) offsetRel;
704 length = RtlLengthSid(pAbs->Group);
705 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
707 if (pRel->Control & SE_SACL_PRESENT)
709 offsetRel += length;
710 pRel->Sacl = (PACL) offsetRel;
711 length = pAbs->Sacl->AclSize;
712 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
714 else
716 pRel->Sacl = NULL;
719 if (pRel->Control & SE_DACL_PRESENT)
721 offsetRel += length;
722 pRel->Dacl = (PACL) offsetRel;
723 length = pAbs->Dacl->AclSize;
724 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
726 else
728 pRel->Dacl = NULL;
731 return STATUS_SUCCESS;
735 /**************************************************************************
736 + * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
737 + */
738 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
739 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
740 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
741 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
742 OUT PACL pDacl,
743 OUT LPDWORD lpdwDaclSize,
744 OUT PACL pSacl,
745 OUT LPDWORD lpdwSaclSize,
746 OUT PSID pOwner,
747 OUT LPDWORD lpdwOwnerSize,
748 OUT PSID pPrimaryGroup,
749 OUT LPDWORD lpdwPrimaryGroupSize)
751 NTSTATUS status = STATUS_SUCCESS;
752 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
753 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
755 if (!pRel ||
756 !lpdwAbsoluteSecurityDescriptorSize ||
757 !lpdwDaclSize ||
758 !lpdwSaclSize ||
759 !lpdwOwnerSize ||
760 !lpdwPrimaryGroupSize ||
761 ~pRel->Control & SE_SELF_RELATIVE)
762 return STATUS_INVALID_PARAMETER;
764 /* Confirm buffers are sufficiently large */
765 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
767 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
768 status = STATUS_BUFFER_TOO_SMALL;
771 if (pRel->Control & SE_DACL_PRESENT &&
772 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
774 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
775 status = STATUS_BUFFER_TOO_SMALL;
778 if (pRel->Control & SE_SACL_PRESENT &&
779 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
781 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
782 status = STATUS_BUFFER_TOO_SMALL;
785 if (pRel->Owner &&
786 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
788 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
789 status = STATUS_BUFFER_TOO_SMALL;
792 if (pRel->Group &&
793 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
795 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
796 status = STATUS_BUFFER_TOO_SMALL;
799 if (status != STATUS_SUCCESS)
800 return status;
802 /* Copy structures */
803 pAbs->Revision = pRel->Revision;
804 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
806 if (pRel->Control & SE_SACL_PRESENT)
808 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
810 memcpy(pSacl, pAcl, pAcl->AclSize);
811 pAbs->Sacl = pSacl;
814 if (pRel->Control & SE_DACL_PRESENT)
816 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
817 memcpy(pDacl, pAcl, pAcl->AclSize);
818 pAbs->Dacl = pDacl;
821 if (pRel->Owner)
823 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
824 memcpy(pOwner, psid, RtlLengthSid(psid));
825 pAbs->Owner = pOwner;
828 if (pRel->Group)
830 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
831 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
832 pAbs->Group = pPrimaryGroup;
835 return status;
839 * access control list's
842 /**************************************************************************
843 * RtlCreateAcl [NTDLL.@]
845 * NOTES
846 * This should return NTSTATUS
848 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
850 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
852 if (rev!=ACL_REVISION)
853 return STATUS_INVALID_PARAMETER;
854 if (size<sizeof(ACL))
855 return STATUS_BUFFER_TOO_SMALL;
856 if (size>0xFFFF)
857 return STATUS_INVALID_PARAMETER;
859 memset(acl,'\0',sizeof(ACL));
860 acl->AclRevision = rev;
861 acl->AclSize = size;
862 acl->AceCount = 0;
863 return STATUS_SUCCESS;
866 /**************************************************************************
867 * RtlFirstFreeAce [NTDLL.@]
868 * looks for the AceCount+1 ACE, and if it is still within the alloced
869 * ACL, return a pointer to it
871 BOOLEAN WINAPI RtlFirstFreeAce(
872 PACL acl,
873 PACE_HEADER *x)
875 PACE_HEADER ace;
876 int i;
878 *x = 0;
879 ace = (PACE_HEADER)(acl+1);
880 for (i=0;i<acl->AceCount;i++) {
881 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
882 return 0;
883 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
885 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
886 return 0;
887 *x = ace;
888 return 1;
891 /**************************************************************************
892 * RtlAddAce [NTDLL.@]
894 NTSTATUS WINAPI RtlAddAce(
895 PACL acl,
896 DWORD rev,
897 DWORD xnrofaces,
898 PACE_HEADER acestart,
899 DWORD acelen)
901 PACE_HEADER ace,targetace;
902 int nrofaces;
904 if (acl->AclRevision != ACL_REVISION)
905 return STATUS_INVALID_PARAMETER;
906 if (!RtlFirstFreeAce(acl,&targetace))
907 return STATUS_INVALID_PARAMETER;
908 nrofaces=0;ace=acestart;
909 while (((DWORD)ace-(DWORD)acestart)<acelen) {
910 nrofaces++;
911 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
913 if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
914 return STATUS_INVALID_PARAMETER;
915 memcpy((LPBYTE)targetace,acestart,acelen);
916 acl->AceCount+=nrofaces;
917 return STATUS_SUCCESS;
920 /**************************************************************************
921 * RtlDeleteAce [NTDLL.@]
923 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
925 NTSTATUS status;
926 PACE_HEADER pAce;
928 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
930 if (STATUS_SUCCESS == status)
932 PACE_HEADER pcAce;
933 DWORD len = 0;
935 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
936 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
938 len += pcAce->AceSize;
939 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
942 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
943 pAcl->AceCount--;
946 return status;
949 /******************************************************************************
950 * RtlAddAccessAllowedAce [NTDLL.@]
952 NTSTATUS WINAPI RtlAddAccessAllowedAce(
953 IN OUT PACL pAcl,
954 IN DWORD dwAceRevision,
955 IN DWORD AccessMask,
956 IN PSID pSid)
958 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
961 /******************************************************************************
962 * RtlAddAccessAllowedAceEx [NTDLL.@]
964 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
965 IN OUT PACL pAcl,
966 IN DWORD dwAceRevision,
967 IN DWORD AceFlags,
968 IN DWORD AccessMask,
969 IN PSID pSid)
971 DWORD dwLengthSid;
972 ACCESS_ALLOWED_ACE * pAaAce;
973 DWORD dwSpaceLeft;
975 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
976 pAcl, dwAceRevision, AccessMask, pSid);
978 if (!RtlValidSid(pSid))
979 return STATUS_INVALID_SID;
980 if (!RtlValidAcl(pAcl))
981 return STATUS_INVALID_ACL;
983 dwLengthSid = RtlLengthSid(pSid);
984 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
985 return STATUS_INVALID_ACL;
987 if (!pAaAce)
988 return STATUS_ALLOTTED_SPACE_EXCEEDED;
990 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
991 if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
992 return STATUS_ALLOTTED_SPACE_EXCEEDED;
994 pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
995 pAaAce->Header.AceFlags = AceFlags;
996 pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
997 pAaAce->Mask = AccessMask;
998 pAcl->AceCount++;
999 RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
1000 return STATUS_SUCCESS;
1003 /******************************************************************************
1004 * RtlAddAccessDeniedAce [NTDLL.@]
1006 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1007 IN OUT PACL pAcl,
1008 IN DWORD dwAceRevision,
1009 IN DWORD AccessMask,
1010 IN PSID pSid)
1012 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1015 /******************************************************************************
1016 * RtlAddAccessDeniedAceEx [NTDLL.@]
1018 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1019 IN OUT PACL pAcl,
1020 IN DWORD dwAceRevision,
1021 IN DWORD AceFlags,
1022 IN DWORD AccessMask,
1023 IN PSID pSid)
1025 DWORD dwLengthSid;
1026 DWORD dwSpaceLeft;
1027 ACCESS_DENIED_ACE * pAdAce;
1029 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1030 pAcl, dwAceRevision, AccessMask, pSid);
1032 if (!RtlValidSid(pSid))
1033 return STATUS_INVALID_SID;
1034 if (!RtlValidAcl(pAcl))
1035 return STATUS_INVALID_ACL;
1037 dwLengthSid = RtlLengthSid(pSid);
1038 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
1039 return STATUS_INVALID_ACL;
1041 if (!pAdAce)
1042 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1044 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1045 if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1046 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1048 pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1049 pAdAce->Header.AceFlags = AceFlags;
1050 pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1051 pAdAce->Mask = AccessMask;
1052 pAcl->AceCount++;
1053 RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1054 return STATUS_SUCCESS;
1057 /******************************************************************************
1058 * RtlValidAcl [NTDLL.@]
1060 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1062 BOOLEAN ret;
1063 TRACE("(%p)\n", pAcl);
1065 __TRY
1067 PACE_HEADER ace;
1068 int i;
1070 if (pAcl->AclRevision != ACL_REVISION)
1071 ret = FALSE;
1072 else
1074 ace = (PACE_HEADER)(pAcl+1);
1075 ret = TRUE;
1076 for (i=0;i<=pAcl->AceCount;i++)
1078 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1080 ret = FALSE;
1081 break;
1083 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1087 __EXCEPT(page_fault)
1089 WARN("(%p): invalid pointer!\n", pAcl);
1090 return 0;
1092 __ENDTRY
1093 return ret;
1096 /******************************************************************************
1097 * RtlGetAce [NTDLL.@]
1099 DWORD WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1101 PACE_HEADER ace;
1103 TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1105 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1106 return STATUS_INVALID_PARAMETER;
1108 ace = (PACE_HEADER)(pAcl + 1);
1109 for (;dwAceIndex;dwAceIndex--)
1110 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1112 *pAce = (LPVOID) ace;
1114 return STATUS_SUCCESS;
1118 * misc
1121 /******************************************************************************
1122 * RtlAdjustPrivilege [NTDLL.@]
1124 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
1126 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
1127 return 0;
1130 /******************************************************************************
1131 * RtlImpersonateSelf [NTDLL.@]
1133 BOOL WINAPI
1134 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1136 FIXME("(%08x), stub\n", ImpersonationLevel);
1137 return TRUE;
1140 /******************************************************************************
1141 * NtAccessCheck [NTDLL.@]
1142 * ZwAccessCheck [NTDLL.@]
1144 NTSTATUS WINAPI
1145 NtAccessCheck(
1146 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1147 IN HANDLE ClientToken,
1148 IN ACCESS_MASK DesiredAccess,
1149 IN PGENERIC_MAPPING GenericMapping,
1150 OUT PPRIVILEGE_SET PrivilegeSet,
1151 OUT PULONG ReturnLength,
1152 OUT PULONG GrantedAccess,
1153 OUT PBOOLEAN AccessStatus)
1155 FIXME("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1156 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1157 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1158 *AccessStatus = TRUE;
1159 return STATUS_SUCCESS;
1162 /******************************************************************************
1163 * NtSetSecurityObject [NTDLL.@]
1165 NTSTATUS WINAPI
1166 NtSetSecurityObject(
1167 IN HANDLE Handle,
1168 IN SECURITY_INFORMATION SecurityInformation,
1169 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1171 FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1172 return STATUS_SUCCESS;
1175 /******************************************************************************
1176 * RtlGetControlSecurityDescriptor (NTDLL.@)
1179 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1180 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1181 PSECURITY_DESCRIPTOR_CONTROL pControl,
1182 LPDWORD lpdwRevision)
1184 FIXME("(%p,%p,%p),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
1185 return STATUS_SUCCESS;
1188 /******************************************************************************
1189 * RtlConvertSidToUnicodeString (NTDLL.@)
1191 * The returned SID is used to access the USER registry hive usually
1193 * the native function returns something like
1194 * "S-1-5-21-0000000000-000000000-0000000000-500";
1196 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1197 PUNICODE_STRING String,
1198 PSID Sid,
1199 BOOLEAN AllocateString)
1201 const char *user = wine_get_user_name();
1202 int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 ) * sizeof(WCHAR);
1204 FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1206 String->Length = len - sizeof(WCHAR);
1207 if (AllocateString)
1209 String->MaximumLength = len;
1210 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1211 return STATUS_NO_MEMORY;
1213 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1215 ntdll_umbstowcs( 0, user, strlen(user)+1, String->Buffer, len/sizeof(WCHAR) );
1216 return STATUS_SUCCESS;
1219 /******************************************************************************
1220 * RtlQueryInformationAcl (NTDLL.@)
1222 NTSTATUS WINAPI RtlQueryInformationAcl(
1223 PACL pAcl,
1224 LPVOID pAclInformation,
1225 DWORD nAclInformationLength,
1226 ACL_INFORMATION_CLASS dwAclInformationClass)
1228 NTSTATUS status = STATUS_SUCCESS;
1230 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1231 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1233 switch (dwAclInformationClass)
1235 case AclRevisionInformation:
1237 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1239 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1240 status = STATUS_INVALID_PARAMETER;
1241 else
1242 paclrev->AclRevision = pAcl->AclRevision;
1244 break;
1247 case AclSizeInformation:
1249 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1251 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1252 status = STATUS_INVALID_PARAMETER;
1253 else
1255 INT i;
1256 PACE_HEADER ace;
1258 paclsize->AceCount = pAcl->AceCount;
1260 paclsize->AclBytesInUse = 0;
1261 ace = (PACE_HEADER) (pAcl + 1);
1263 for (i = 0; i < pAcl->AceCount; i++)
1265 paclsize->AclBytesInUse += ace->AceSize;
1266 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1269 if (pAcl->AclSize < paclsize->AclBytesInUse)
1271 WARN("Acl has %ld bytes free\n", pAcl->AclSize - paclsize->AclBytesInUse);
1272 paclsize->AclBytesFree = 0;
1273 paclsize->AclBytesInUse = pAcl->AclSize;
1275 else
1276 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1279 break;
1282 default:
1283 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1284 status = STATUS_INVALID_PARAMETER;
1287 return status;