Use Interlocked* functions in AddRef and Release.
[wine/multimedia.git] / dlls / ntdll / sec.c
blob180de031a71d5b30d6b1249582c02ed1b0204171
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 ge 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 withe 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->Sacl != NULL )
412 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
414 if ( lpsd->Dacl != NULL )
415 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
417 return Size;
420 /******************************************************************************
421 * RtlGetDaclSecurityDescriptor [NTDLL.@]
424 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
425 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
426 OUT PBOOLEAN lpbDaclPresent,
427 OUT PACL *pDacl,
428 OUT PBOOLEAN lpbDaclDefaulted)
430 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
432 TRACE("(%p,%p,%p,%p)\n",
433 pSecurityDescriptor, lpbDaclPresent, *pDacl, lpbDaclDefaulted);
435 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
436 return STATUS_UNKNOWN_REVISION ;
438 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
440 if ( SE_SELF_RELATIVE & lpsd->Control)
441 { *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
443 else
444 { *pDacl = lpsd->Dacl;
448 *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);
508 else
509 { *pSacl = lpsd->Sacl;
513 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
515 return STATUS_SUCCESS;
518 /**************************************************************************
519 * RtlSetSaclSecurityDescriptor [NTDLL.@]
521 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
522 PSECURITY_DESCRIPTOR pSecurityDescriptor,
523 BOOLEAN saclpresent,
524 PACL sacl,
525 BOOLEAN sacldefaulted)
527 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
529 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
530 return STATUS_UNKNOWN_REVISION;
531 if (lpsd->Control & SE_SELF_RELATIVE)
532 return STATUS_INVALID_SECURITY_DESCR;
533 if (!saclpresent) {
534 lpsd->Control &= ~SE_SACL_PRESENT;
535 return 0;
537 lpsd->Control |= SE_SACL_PRESENT;
538 lpsd->Sacl = sacl;
539 if (sacldefaulted)
540 lpsd->Control |= SE_SACL_DEFAULTED;
541 else
542 lpsd->Control &= ~SE_SACL_DEFAULTED;
543 return STATUS_SUCCESS;
546 /**************************************************************************
547 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
549 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
550 PSECURITY_DESCRIPTOR pSecurityDescriptor,
551 PSID *Owner,
552 PBOOLEAN OwnerDefaulted)
554 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
556 if ( !lpsd || !Owner || !OwnerDefaulted )
557 return STATUS_INVALID_PARAMETER;
559 if (lpsd->Owner != NULL)
561 if (lpsd->Control & SE_SELF_RELATIVE)
562 *Owner = (PSID)((LPBYTE)lpsd +
563 (ULONG)lpsd->Owner);
564 else
565 *Owner = lpsd->Owner;
567 if ( lpsd->Control & SE_OWNER_DEFAULTED )
568 *OwnerDefaulted = TRUE;
569 else
570 *OwnerDefaulted = FALSE;
572 else
573 *Owner = NULL;
575 return STATUS_SUCCESS;
578 /**************************************************************************
579 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
581 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
582 PSECURITY_DESCRIPTOR pSecurityDescriptor,
583 PSID owner,
584 BOOLEAN ownerdefaulted)
586 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
588 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
589 return STATUS_UNKNOWN_REVISION;
590 if (lpsd->Control & SE_SELF_RELATIVE)
591 return STATUS_INVALID_SECURITY_DESCR;
593 lpsd->Owner = owner;
594 if (ownerdefaulted)
595 lpsd->Control |= SE_OWNER_DEFAULTED;
596 else
597 lpsd->Control &= ~SE_OWNER_DEFAULTED;
598 return STATUS_SUCCESS;
601 /**************************************************************************
602 * RtlSetGroupSecurityDescriptor [NTDLL.@]
604 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
605 PSECURITY_DESCRIPTOR pSecurityDescriptor,
606 PSID group,
607 BOOLEAN groupdefaulted)
609 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
611 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
612 return STATUS_UNKNOWN_REVISION;
613 if (lpsd->Control & SE_SELF_RELATIVE)
614 return STATUS_INVALID_SECURITY_DESCR;
616 lpsd->Group = group;
617 if (groupdefaulted)
618 lpsd->Control |= SE_GROUP_DEFAULTED;
619 else
620 lpsd->Control &= ~SE_GROUP_DEFAULTED;
621 return STATUS_SUCCESS;
623 /**************************************************************************
624 * RtlGetGroupSecurityDescriptor [NTDLL.@]
626 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
627 PSECURITY_DESCRIPTOR pSecurityDescriptor,
628 PSID *Group,
629 PBOOLEAN GroupDefaulted)
631 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
633 if ( !lpsd || !Group || !GroupDefaulted )
634 return STATUS_INVALID_PARAMETER;
636 if (lpsd->Group != NULL)
638 if (lpsd->Control & SE_SELF_RELATIVE)
639 *Group = (PSID)((LPBYTE)lpsd +
640 (ULONG)lpsd->Group);
641 else
642 *Group = lpsd->Group;
644 if ( lpsd->Control & SE_GROUP_DEFAULTED )
645 *GroupDefaulted = TRUE;
646 else
647 *GroupDefaulted = FALSE;
649 else
650 *Group = NULL;
652 return STATUS_SUCCESS;
655 /**************************************************************************
656 * RtlMakeSelfRelativeSD [NTDLL.@]
658 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
659 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
660 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
661 IN OUT LPDWORD lpdwBufferLength)
663 ULONG offsetRel;
664 ULONG length;
665 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
666 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
668 TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
669 lpdwBufferLength ? *lpdwBufferLength: -1);
671 if (!lpdwBufferLength || !pAbs)
672 return STATUS_INVALID_PARAMETER;
674 length = RtlLengthSecurityDescriptor(pAbs);
675 if (*lpdwBufferLength < length)
677 *lpdwBufferLength = length;
678 return STATUS_BUFFER_TOO_SMALL;
681 if (!pRel)
682 return STATUS_INVALID_PARAMETER;
684 if (pAbs->Control & SE_SELF_RELATIVE)
686 memcpy(pRel, pAbs, length);
687 return STATUS_SUCCESS;
690 pRel->Revision = pAbs->Revision;
691 pRel->Sbz1 = pAbs->Sbz1;
692 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
694 offsetRel = sizeof(SECURITY_DESCRIPTOR);
695 pRel->Owner = (PSID) offsetRel;
696 length = RtlLengthSid(pAbs->Owner);
697 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
699 offsetRel += length;
700 pRel->Group = (PSID) offsetRel;
701 length = RtlLengthSid(pAbs->Group);
702 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
704 if (pRel->Control & SE_SACL_PRESENT)
706 offsetRel += length;
707 pRel->Sacl = (PACL) offsetRel;
708 length = pAbs->Sacl->AclSize;
709 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
711 else
713 pRel->Sacl = NULL;
716 if (pRel->Control & SE_DACL_PRESENT)
718 offsetRel += length;
719 pRel->Dacl = (PACL) offsetRel;
720 length = pAbs->Dacl->AclSize;
721 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
723 else
725 pRel->Dacl = NULL;
728 return STATUS_SUCCESS;
732 /**************************************************************************
733 + * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
734 + */
735 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
736 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
737 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
738 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
739 OUT PACL pDacl,
740 OUT LPDWORD lpdwDaclSize,
741 OUT PACL pSacl,
742 OUT LPDWORD lpdwSaclSize,
743 OUT PSID pOwner,
744 OUT LPDWORD lpdwOwnerSize,
745 OUT PSID pPrimaryGroup,
746 OUT LPDWORD lpdwPrimaryGroupSize)
748 NTSTATUS status = STATUS_SUCCESS;
749 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
750 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
752 if (!pRel ||
753 !lpdwAbsoluteSecurityDescriptorSize ||
754 !lpdwDaclSize ||
755 !lpdwSaclSize ||
756 !lpdwOwnerSize ||
757 !lpdwPrimaryGroupSize ||
758 ~pRel->Control & SE_SELF_RELATIVE)
759 return STATUS_INVALID_PARAMETER;
761 /* Confirm buffers are sufficiently large */
762 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
764 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
765 status = STATUS_BUFFER_TOO_SMALL;
768 if (pRel->Control & SE_DACL_PRESENT &&
769 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
771 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
772 status = STATUS_BUFFER_TOO_SMALL;
775 if (pRel->Control & SE_SACL_PRESENT &&
776 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
778 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
779 status = STATUS_BUFFER_TOO_SMALL;
782 if (pRel->Owner &&
783 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
785 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
786 status = STATUS_BUFFER_TOO_SMALL;
789 if (pRel->Group &&
790 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
792 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
793 status = STATUS_BUFFER_TOO_SMALL;
796 if (status != STATUS_SUCCESS)
797 return status;
799 /* Copy structures */
800 pAbs->Revision = pRel->Revision;
801 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
803 if (pRel->Control & SE_SACL_PRESENT)
805 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
807 memcpy(pSacl, pAcl, pAcl->AclSize);
808 pAbs->Sacl = pSacl;
811 if (pRel->Control & SE_DACL_PRESENT)
813 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
814 memcpy(pDacl, pAcl, pAcl->AclSize);
815 pAbs->Dacl = pDacl;
818 if (pRel->Owner)
820 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
821 memcpy(pOwner, psid, RtlLengthSid(psid));
822 pAbs->Owner = pOwner;
825 if (pRel->Group)
827 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
828 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
829 pAbs->Group = pPrimaryGroup;
832 return status;
836 * access control list's
839 /**************************************************************************
840 * RtlCreateAcl [NTDLL.@]
842 * NOTES
843 * This should return NTSTATUS
845 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
847 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
849 if (rev!=ACL_REVISION)
850 return STATUS_INVALID_PARAMETER;
851 if (size<sizeof(ACL))
852 return STATUS_BUFFER_TOO_SMALL;
853 if (size>0xFFFF)
854 return STATUS_INVALID_PARAMETER;
856 memset(acl,'\0',sizeof(ACL));
857 acl->AclRevision = rev;
858 acl->AclSize = size;
859 acl->AceCount = 0;
860 return STATUS_SUCCESS;
863 /**************************************************************************
864 * RtlFirstFreeAce [NTDLL.@]
865 * looks for the AceCount+1 ACE, and if it is still within the alloced
866 * ACL, return a pointer to it
868 BOOLEAN WINAPI RtlFirstFreeAce(
869 PACL acl,
870 PACE_HEADER *x)
872 PACE_HEADER ace;
873 int i;
875 *x = 0;
876 ace = (PACE_HEADER)(acl+1);
877 for (i=0;i<acl->AceCount;i++) {
878 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
879 return 0;
880 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
882 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
883 return 0;
884 *x = ace;
885 return 1;
888 /**************************************************************************
889 * RtlAddAce [NTDLL.@]
891 NTSTATUS WINAPI RtlAddAce(
892 PACL acl,
893 DWORD rev,
894 DWORD xnrofaces,
895 PACE_HEADER acestart,
896 DWORD acelen)
898 PACE_HEADER ace,targetace;
899 int nrofaces;
901 if (acl->AclRevision != ACL_REVISION)
902 return STATUS_INVALID_PARAMETER;
903 if (!RtlFirstFreeAce(acl,&targetace))
904 return STATUS_INVALID_PARAMETER;
905 nrofaces=0;ace=acestart;
906 while (((DWORD)ace-(DWORD)acestart)<acelen) {
907 nrofaces++;
908 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
910 if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
911 return STATUS_INVALID_PARAMETER;
912 memcpy((LPBYTE)targetace,acestart,acelen);
913 acl->AceCount+=nrofaces;
914 return STATUS_SUCCESS;
917 /**************************************************************************
918 * RtlDeleteAce [NTDLL.@]
920 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
922 NTSTATUS status;
923 PACE_HEADER pAce;
925 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
927 if (STATUS_SUCCESS == status)
929 PACE_HEADER pcAce;
930 DWORD len = 0;
932 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
933 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
935 len += pcAce->AceSize;
936 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
939 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
940 pAcl->AceCount--;
943 return status;
946 /******************************************************************************
947 * RtlAddAccessAllowedAce [NTDLL.@]
949 NTSTATUS WINAPI RtlAddAccessAllowedAce(
950 IN OUT PACL pAcl,
951 IN DWORD dwAceRevision,
952 IN DWORD AccessMask,
953 IN PSID pSid)
955 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
958 /******************************************************************************
959 * RtlAddAccessAllowedAceEx [NTDLL.@]
961 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
962 IN OUT PACL pAcl,
963 IN DWORD dwAceRevision,
964 IN DWORD AceFlags,
965 IN DWORD AccessMask,
966 IN PSID pSid)
968 DWORD dwLengthSid;
969 ACCESS_ALLOWED_ACE * pAaAce;
970 DWORD dwSpaceLeft;
972 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
973 pAcl, dwAceRevision, AccessMask, pSid);
975 if (!RtlValidSid(pSid))
976 return STATUS_INVALID_SID;
977 if (!RtlValidAcl(pAcl))
978 return STATUS_INVALID_ACL;
980 dwLengthSid = RtlLengthSid(pSid);
981 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
982 return STATUS_INVALID_ACL;
984 if (!pAaAce)
985 return STATUS_ALLOTTED_SPACE_EXCEEDED;
987 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
988 if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
989 return STATUS_ALLOTTED_SPACE_EXCEEDED;
991 pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
992 pAaAce->Header.AceFlags = AceFlags;
993 pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
994 pAaAce->Mask = AccessMask;
995 pAcl->AceCount++;
996 RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
997 return STATUS_SUCCESS;
1000 /******************************************************************************
1001 * RtlAddAccessDeniedAce [NTDLL.@]
1003 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1004 IN OUT PACL pAcl,
1005 IN DWORD dwAceRevision,
1006 IN DWORD AccessMask,
1007 IN PSID pSid)
1009 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1012 /******************************************************************************
1013 * RtlAddAccessDeniedAceEx [NTDLL.@]
1015 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1016 IN OUT PACL pAcl,
1017 IN DWORD dwAceRevision,
1018 IN DWORD AceFlags,
1019 IN DWORD AccessMask,
1020 IN PSID pSid)
1022 DWORD dwLengthSid;
1023 DWORD dwSpaceLeft;
1024 ACCESS_DENIED_ACE * pAdAce;
1026 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1027 pAcl, dwAceRevision, AccessMask, pSid);
1029 if (!RtlValidSid(pSid))
1030 return STATUS_INVALID_SID;
1031 if (!RtlValidAcl(pAcl))
1032 return STATUS_INVALID_ACL;
1034 dwLengthSid = RtlLengthSid(pSid);
1035 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
1036 return STATUS_INVALID_ACL;
1038 if (!pAdAce)
1039 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1041 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1042 if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1043 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1045 pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1046 pAdAce->Header.AceFlags = AceFlags;
1047 pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1048 pAdAce->Mask = AccessMask;
1049 pAcl->AceCount++;
1050 RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1051 return STATUS_SUCCESS;
1054 /******************************************************************************
1055 * RtlValidAcl [NTDLL.@]
1057 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1059 BOOLEAN ret;
1060 TRACE("(%p)\n", pAcl);
1062 __TRY
1064 PACE_HEADER ace;
1065 int i;
1067 if (pAcl->AclRevision != ACL_REVISION)
1068 ret = FALSE;
1069 else
1071 ace = (PACE_HEADER)(pAcl+1);
1072 ret = TRUE;
1073 for (i=0;i<=pAcl->AceCount;i++)
1075 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1077 ret = FALSE;
1078 break;
1080 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1084 __EXCEPT(page_fault)
1086 WARN("(%p): invalid pointer!\n", pAcl);
1087 return 0;
1089 __ENDTRY
1090 return ret;
1093 /******************************************************************************
1094 * RtlGetAce [NTDLL.@]
1096 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1098 PACE_HEADER ace;
1100 TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1102 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1103 return STATUS_INVALID_PARAMETER;
1105 ace = (PACE_HEADER)(pAcl + 1);
1106 for (;dwAceIndex;dwAceIndex--)
1107 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1109 *pAce = (LPVOID) ace;
1111 return STATUS_SUCCESS;
1115 * misc
1118 /******************************************************************************
1119 * RtlAdjustPrivilege [NTDLL.@]
1121 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
1123 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
1124 return 0;
1127 /******************************************************************************
1128 * RtlImpersonateSelf [NTDLL.@]
1130 BOOL WINAPI
1131 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1133 FIXME("(%08x), stub\n", ImpersonationLevel);
1134 return TRUE;
1137 /******************************************************************************
1138 * NtAccessCheck [NTDLL.@]
1139 * ZwAccessCheck [NTDLL.@]
1141 NTSTATUS WINAPI
1142 NtAccessCheck(
1143 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1144 IN HANDLE ClientToken,
1145 IN ACCESS_MASK DesiredAccess,
1146 IN PGENERIC_MAPPING GenericMapping,
1147 OUT PPRIVILEGE_SET PrivilegeSet,
1148 OUT PULONG ReturnLength,
1149 OUT PULONG GrantedAccess,
1150 OUT NTSTATUS *AccessStatus)
1152 FIXME("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1153 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1154 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1155 *AccessStatus = STATUS_SUCCESS;
1156 return STATUS_SUCCESS;
1159 /******************************************************************************
1160 * NtSetSecurityObject [NTDLL.@]
1162 NTSTATUS WINAPI
1163 NtSetSecurityObject(
1164 IN HANDLE Handle,
1165 IN SECURITY_INFORMATION SecurityInformation,
1166 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1168 FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1169 return STATUS_SUCCESS;
1172 /******************************************************************************
1173 * RtlGetControlSecurityDescriptor (NTDLL.@)
1176 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1177 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1178 PSECURITY_DESCRIPTOR_CONTROL pControl,
1179 LPDWORD lpdwRevision)
1181 FIXME("(%p,%p,%p),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
1182 return STATUS_SUCCESS;
1185 /******************************************************************************
1186 * RtlConvertSidToUnicodeString (NTDLL.@)
1188 * The returned SID is used to access the USER registry hive usually
1190 * the native function returns something like
1191 * "S-1-5-21-0000000000-000000000-0000000000-500";
1193 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1194 PUNICODE_STRING String,
1195 PSID Sid,
1196 BOOLEAN AllocateString)
1198 const char *user = wine_get_user_name();
1199 int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 ) * sizeof(WCHAR);
1201 FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1203 String->Length = len - sizeof(WCHAR);
1204 if (AllocateString)
1206 String->MaximumLength = len;
1207 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1208 return STATUS_NO_MEMORY;
1210 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1212 ntdll_umbstowcs( 0, user, strlen(user)+1, String->Buffer, len/sizeof(WCHAR) );
1213 return STATUS_SUCCESS;
1216 /******************************************************************************
1217 * RtlQueryInformationAcl (NTDLL.@)
1219 NTSTATUS WINAPI RtlQueryInformationAcl(
1220 PACL pAcl,
1221 LPVOID pAclInformation,
1222 DWORD nAclInformationLength,
1223 ACL_INFORMATION_CLASS dwAclInformationClass)
1225 NTSTATUS status = STATUS_SUCCESS;
1227 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1228 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1230 switch (dwAclInformationClass)
1232 case AclRevisionInformation:
1234 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1236 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1237 status = STATUS_INVALID_PARAMETER;
1238 else
1239 paclrev->AclRevision = pAcl->AclRevision;
1241 break;
1244 case AclSizeInformation:
1246 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1248 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1249 status = STATUS_INVALID_PARAMETER;
1250 else
1252 INT i;
1253 PACE_HEADER ace;
1255 paclsize->AceCount = pAcl->AceCount;
1257 paclsize->AclBytesInUse = 0;
1258 ace = (PACE_HEADER) (pAcl + 1);
1260 for (i = 0; i < pAcl->AceCount; i++)
1262 paclsize->AclBytesInUse += ace->AceSize;
1263 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1266 if (pAcl->AclSize < paclsize->AclBytesInUse)
1268 WARN("Acl has %ld bytes free\n", pAcl->AclSize - paclsize->AclBytesInUse);
1269 paclsize->AclBytesFree = 0;
1270 paclsize->AclBytesInUse = pAcl->AclSize;
1272 else
1273 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1276 break;
1279 default:
1280 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1281 status = STATUS_INVALID_PARAMETER;
1284 return status;