advapi32/ntdll: MakeRelativeSD should preserve NULL pointers (with testcase).
[wine] / dlls / ntdll / sec.c
1 /*
2  *      Security functions
3  *
4  *      Copyright 1996-1998 Marcus Meissner
5  *      Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6  *
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.
11  *
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.
16  *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
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
34
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
37 #include "windef.h"
38 #include "wine/exception.h"
39 #include "ntdll_misc.h"
40 #include "wine/library.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
45
46 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
47
48 /* helper function to copy an ACL */
49 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
50 {
51     DWORD size;
52
53     if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
54         return FALSE;
55         
56     size = ((ACL *)pSourceAcl)->AclSize;
57     if (nDestinationAclLength < size)
58         return FALSE;
59
60     memmove(pDestinationAcl, pSourceAcl, size);
61     return TRUE;
62 }
63
64 /* generically adds an ACE to an ACL */
65 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
66                                DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
67 {
68     ACE_HEADER *pAceHeader;
69     DWORD dwLengthSid;
70     DWORD dwAceSize;
71     DWORD *pAccessMask;
72     DWORD *pSidStart;
73
74     if (!RtlValidSid(pSid))
75         return STATUS_INVALID_SID;
76
77     if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
78         return STATUS_REVISION_MISMATCH;
79
80     if (!RtlValidAcl(pAcl))
81         return STATUS_INVALID_ACL;
82
83     if (!RtlFirstFreeAce(pAcl, &pAceHeader))
84         return STATUS_INVALID_ACL;
85
86     if (!pAceHeader)
87         return STATUS_ALLOTTED_SPACE_EXCEEDED;
88
89     /* calculate generic size of the ACE */
90     dwLengthSid = RtlLengthSid(pSid);
91     dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
92     if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
93         return STATUS_ALLOTTED_SPACE_EXCEEDED;
94
95     /* fill the new ACE */
96     pAceHeader->AceType = dwAceType;
97     pAceHeader->AceFlags = dwAceFlags;
98     pAceHeader->AceSize = dwAceSize;
99
100     /* skip past the ACE_HEADER of the ACE */
101     pAccessMask = (DWORD *)(pAceHeader + 1);
102     *pAccessMask = dwAccessMask;
103
104     /* skip past ACE->Mask */
105     pSidStart = pAccessMask + 1;
106     RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
107
108     pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
109     pAcl->AceCount++;
110
111     return STATUS_SUCCESS;
112 }
113
114 /*
115  *      SID FUNCTIONS
116  */
117
118 /******************************************************************************
119  *  RtlAllocateAndInitializeSid         [NTDLL.@]
120  *
121  */
122 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
123         PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
124         BYTE nSubAuthorityCount,
125         DWORD nSubAuthority0, DWORD nSubAuthority1,
126         DWORD nSubAuthority2, DWORD nSubAuthority3,
127         DWORD nSubAuthority4, DWORD nSubAuthority5,
128         DWORD nSubAuthority6, DWORD nSubAuthority7,
129         PSID *pSid )
130 {
131     SID *tmp_sid;
132
133     TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
134                 pIdentifierAuthority,nSubAuthorityCount,
135                 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
136                 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
137
138     if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
139
140     if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
141                                     RtlLengthRequiredSid(nSubAuthorityCount))))
142         return STATUS_NO_MEMORY;
143
144     tmp_sid->Revision = SID_REVISION;
145
146     if (pIdentifierAuthority)
147         memcpy(&tmp_sid->IdentifierAuthority, pIdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY));
148     tmp_sid->SubAuthorityCount = nSubAuthorityCount;
149
150     switch( nSubAuthorityCount )
151     {
152         case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
153         case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
154         case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
155         case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
156         case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
157         case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
158         case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
159         case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
160         break;
161     }
162     *pSid = tmp_sid;
163     return STATUS_SUCCESS;
164 }
165
166 /******************************************************************************
167  *  RtlEqualSid         [NTDLL.@]
168  *
169  * Determine if two SIDs are equal.
170  *
171  * PARAMS
172  *  pSid1 [I] Source SID
173  *  pSid2 [I] SID to compare with
174  *
175  * RETURNS
176  *  TRUE, if pSid1 is equal to pSid2,
177  *  FALSE otherwise.
178  */
179 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
180 {
181     if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
182         return FALSE;
183
184     if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
185         return FALSE;
186
187     if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
188         return FALSE;
189
190     return TRUE;
191 }
192
193 /******************************************************************************
194  * RtlEqualPrefixSid    [NTDLL.@]
195  */
196 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
197 {
198     if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
199         return FALSE;
200
201     if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
202         return FALSE;
203
204     if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
205         return FALSE;
206
207     return TRUE;
208 }
209
210
211 /******************************************************************************
212  *  RtlFreeSid          [NTDLL.@]
213  *
214  * Free the resources used by a SID.
215  *
216  * PARAMS
217  *  pSid [I] SID to Free.
218  *
219  * RETURNS
220  *  STATUS_SUCCESS.
221  */
222 DWORD WINAPI RtlFreeSid(PSID pSid)
223 {
224         TRACE("(%p)\n", pSid);
225         RtlFreeHeap( GetProcessHeap(), 0, pSid );
226         return STATUS_SUCCESS;
227 }
228
229 /**************************************************************************
230  * RtlLengthRequiredSid [NTDLL.@]
231  *
232  * Determine the amount of memory a SID will use
233  *
234  * PARAMS
235  *   nrofsubauths [I] Number of Sub Authorities in the SID.
236  *
237  * RETURNS
238  *   The size, in bytes, of a SID with nrofsubauths Sub Authorities.
239  */
240 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
241 {
242         return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
243 }
244
245 /**************************************************************************
246  *                 RtlLengthSid                         [NTDLL.@]
247  *
248  * Determine the amount of memory a SID is using
249  *
250  * PARAMS
251  *  pSid [I] SID to get the size of.
252  *
253  * RETURNS
254  *  The size, in bytes, of pSid.
255  */
256 DWORD WINAPI RtlLengthSid(PSID pSid)
257 {
258         TRACE("sid=%p\n",pSid);
259         if (!pSid) return 0;
260         return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
261 }
262
263 /**************************************************************************
264  *                 RtlInitializeSid                     [NTDLL.@]
265  *
266  * Initialise a SID.
267  *
268  * PARAMS
269  *  pSid                 [I] SID to initialise
270  *  pIdentifierAuthority [I] Identifier Authority
271  *  nSubAuthorityCount   [I] Number of Sub Authorities
272  *
273  * RETURNS
274  *  Success: TRUE. pSid is initialised with the details given.
275  *  Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
276  */
277 BOOL WINAPI RtlInitializeSid(
278         PSID pSid,
279         PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
280         BYTE nSubAuthorityCount)
281 {
282         int i;
283         SID* pisid=pSid;
284
285         if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
286           return FALSE;
287
288         pisid->Revision = SID_REVISION;
289         pisid->SubAuthorityCount = nSubAuthorityCount;
290         if (pIdentifierAuthority)
291           memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
292
293         for (i = 0; i < nSubAuthorityCount; i++)
294           *RtlSubAuthoritySid(pSid, i) = 0;
295
296         return TRUE;
297 }
298
299 /**************************************************************************
300  *                 RtlSubAuthoritySid                   [NTDLL.@]
301  *
302  * Return the Sub Authority of a SID
303  *
304  * PARAMS
305  *   pSid          [I] SID to get the Sub Authority from.
306  *   nSubAuthority [I] Sub Authority number.
307  *
308  * RETURNS
309  *   A pointer to The Sub Authority value of pSid.
310  */
311 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
312 {
313     return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
314 }
315
316 /**************************************************************************
317  * RtlIdentifierAuthoritySid    [NTDLL.@]
318  *
319  * Return the Identifier Authority of a SID.
320  *
321  * PARAMS
322  *   pSid [I] SID to get the Identifier Authority from.
323  *
324  * RETURNS
325  *   A pointer to the Identifier Authority value of pSid.
326  */
327 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
328 {
329     return &(((SID*)pSid)->IdentifierAuthority);
330 }
331
332 /**************************************************************************
333  *                 RtlSubAuthorityCountSid              [NTDLL.@]
334  *
335  * Get the number of Sub Authorities in a SID.
336  *
337  * PARAMS
338  *   pSid [I] SID to get the count from.
339  *
340  * RETURNS
341  *  A pointer to the Sub Authority count of pSid.
342  */
343 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
344 {
345     return &(((SID*)pSid)->SubAuthorityCount);
346 }
347
348 /**************************************************************************
349  *                 RtlCopySid                           [NTDLL.@]
350  */
351 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
352 {
353         if (!pSourceSid || !RtlValidSid(pSourceSid) ||
354             (nDestinationSidLength < RtlLengthSid(pSourceSid)))
355           return FALSE;
356
357         if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
358           return FALSE;
359
360         memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
361         return TRUE;
362 }
363 /******************************************************************************
364  * RtlValidSid [NTDLL.@]
365  *
366  * Determine if a SID is valid.
367  *
368  * PARAMS
369  *   pSid [I] SID to check
370  *
371  * RETURNS
372  *   TRUE if pSid is valid,
373  *   FALSE otherwise.
374  */
375 BOOLEAN WINAPI RtlValidSid( PSID pSid )
376 {
377     BOOL ret;
378     __TRY
379     {
380         ret = TRUE;
381         if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
382             ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
383         {
384             ret = FALSE;
385         }
386     }
387     __EXCEPT_PAGE_FAULT
388     {
389         WARN("(%p): invalid pointer!\n", pSid);
390         return FALSE;
391     }
392     __ENDTRY
393     return ret;
394 }
395
396
397 /*
398  *      security descriptor functions
399  */
400
401 /**************************************************************************
402  * RtlCreateSecurityDescriptor                  [NTDLL.@]
403  *
404  * Initialise a SECURITY_DESCRIPTOR.
405  *
406  * PARAMS
407  *  lpsd [O] Descriptor to initialise.
408  *  rev  [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
409  *
410  * RETURNS
411  *  Success: STATUS_SUCCESS.
412  *  Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
413  */
414 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
415         PSECURITY_DESCRIPTOR lpsd,
416         DWORD rev)
417 {
418         if (rev!=SECURITY_DESCRIPTOR_REVISION)
419                 return STATUS_UNKNOWN_REVISION;
420         memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
421         ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
422         return STATUS_SUCCESS;
423 }
424
425 /**************************************************************************
426  * RtlCopySecurityDescriptor            [NTDLL.@]
427  *
428  * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
429  *
430  * PARAMS
431  *  pSourceSD      [O] SD to copy from.
432  *  pDestinationSD [I] Destination SD.
433  *
434  * RETURNS
435  *  Success: STATUS_SUCCESS.
436  *  Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
437  */
438 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
439 {
440     SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
441     SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
442     PSID Owner, Group;
443     PACL Dacl, Sacl;
444     BOOLEAN defaulted, present;
445     DWORD length;
446     BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
447     
448     if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
449         return STATUS_UNKNOWN_REVISION;
450
451     /* copy initial data */
452     destSD->Revision = srcSD->Revision;
453     destSD->Sbz1 = srcSD->Sbz1;
454     destSD->Control = srcSD->Control;
455
456     /* copy Owner */
457     RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
458     length = RtlLengthSid(Owner);
459
460     if (isSelfRelative)
461     {
462         destSD->Owner = srcSD->Owner;
463         RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
464     }
465     else
466     {
467         destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
468         RtlCopySid(length, destSD->Owner, Owner);
469     }
470
471     /* copy Group */
472     RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
473     length = RtlLengthSid(Group);
474
475     if (isSelfRelative)
476     {
477         destSD->Group = srcSD->Group;
478         RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
479     }
480     else
481     {
482         destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
483         RtlCopySid(length, destSD->Group, Group);
484     }
485
486     /* copy Dacl */
487     if (srcSD->Control & SE_DACL_PRESENT)
488     {
489         RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
490         length = Dacl->AclSize;
491
492         if (isSelfRelative)
493         {
494             destSD->Dacl = srcSD->Dacl;
495             copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl);
496         }
497         else
498         {
499             destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
500             copy_acl(length, destSD->Dacl, Dacl);
501         }
502     }
503
504     /* copy Sacl */
505     if (srcSD->Control & SE_SACL_PRESENT)
506     {
507         RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
508         length = Sacl->AclSize;
509
510         if (isSelfRelative)
511         {
512             destSD->Sacl = srcSD->Sacl;
513             copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl);
514         }
515         else
516         {
517             destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
518             copy_acl(length, destSD->Sacl, Sacl);
519         }
520     }
521
522     return STATUS_SUCCESS;
523 }
524
525 /**************************************************************************
526  * RtlValidSecurityDescriptor                   [NTDLL.@]
527  *
528  * Determine if a SECURITY_DESCRIPTOR is valid.
529  *
530  * PARAMS
531  *  SecurityDescriptor [I] Descriptor to check.
532  *
533  * RETURNS
534  *   Success: STATUS_SUCCESS.
535  *   Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
536  */
537 NTSTATUS WINAPI RtlValidSecurityDescriptor(
538         PSECURITY_DESCRIPTOR SecurityDescriptor)
539 {
540         if ( ! SecurityDescriptor )
541                 return STATUS_INVALID_SECURITY_DESCR;
542         if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
543                 return STATUS_UNKNOWN_REVISION;
544
545         return STATUS_SUCCESS;
546 }
547
548 /**************************************************************************
549  *  RtlLengthSecurityDescriptor                 [NTDLL.@]
550  */
551 ULONG WINAPI RtlLengthSecurityDescriptor(
552         PSECURITY_DESCRIPTOR pSecurityDescriptor)
553 {
554         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
555         ULONG_PTR offset = 0;
556         ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
557
558         if ( lpsd == NULL )
559                 return 0;
560
561         if ( lpsd->Control & SE_SELF_RELATIVE)
562                 offset = (ULONG_PTR) lpsd;
563
564         if ( lpsd->Owner != NULL )
565                 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
566
567         if ( lpsd->Group != NULL )
568                 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
569
570         if ( (lpsd->Control & SE_SACL_PRESENT) &&
571               lpsd->Sacl != NULL )
572                 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
573
574         if ( (lpsd->Control & SE_DACL_PRESENT) &&
575               lpsd->Dacl != NULL )
576                 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
577
578         return Size;
579 }
580
581 /******************************************************************************
582  *  RtlGetDaclSecurityDescriptor                [NTDLL.@]
583  *
584  */
585 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
586         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
587         OUT PBOOLEAN lpbDaclPresent,
588         OUT PACL *pDacl,
589         OUT PBOOLEAN lpbDaclDefaulted)
590 {
591         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
592
593         TRACE("(%p,%p,%p,%p)\n",
594         pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
595
596         if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
597           return STATUS_UNKNOWN_REVISION ;
598
599         if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
600         {
601           if ( SE_SELF_RELATIVE & lpsd->Control)
602             *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl);
603           else
604             *pDacl = lpsd->Dacl;
605
606           *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
607         }
608
609         return STATUS_SUCCESS;
610 }
611
612 /**************************************************************************
613  *  RtlSetDaclSecurityDescriptor                [NTDLL.@]
614  */
615 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
616         PSECURITY_DESCRIPTOR pSecurityDescriptor,
617         BOOLEAN daclpresent,
618         PACL dacl,
619         BOOLEAN dacldefaulted )
620 {
621         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
622
623         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
624                 return STATUS_UNKNOWN_REVISION;
625         if (lpsd->Control & SE_SELF_RELATIVE)
626                 return STATUS_INVALID_SECURITY_DESCR;
627
628         if (!daclpresent)
629         {       lpsd->Control &= ~SE_DACL_PRESENT;
630                 return TRUE;
631         }
632
633         lpsd->Control |= SE_DACL_PRESENT;
634         lpsd->Dacl = dacl;
635
636         if (dacldefaulted)
637                 lpsd->Control |= SE_DACL_DEFAULTED;
638         else
639                 lpsd->Control &= ~SE_DACL_DEFAULTED;
640
641         return STATUS_SUCCESS;
642 }
643
644 /******************************************************************************
645  *  RtlGetSaclSecurityDescriptor                [NTDLL.@]
646  *
647  */
648 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
649         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
650         OUT PBOOLEAN lpbSaclPresent,
651         OUT PACL *pSacl,
652         OUT PBOOLEAN lpbSaclDefaulted)
653 {
654         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
655
656         TRACE("(%p,%p,%p,%p)\n",
657         pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
658
659         if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
660           return STATUS_UNKNOWN_REVISION;
661
662         if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
663         {
664           if (SE_SELF_RELATIVE & lpsd->Control)
665             *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl);
666           else
667             *pSacl = lpsd->Sacl;
668
669           *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
670         }
671
672         return STATUS_SUCCESS;
673 }
674
675 /**************************************************************************
676  * RtlSetSaclSecurityDescriptor                 [NTDLL.@]
677  */
678 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
679         PSECURITY_DESCRIPTOR pSecurityDescriptor,
680         BOOLEAN saclpresent,
681         PACL sacl,
682         BOOLEAN sacldefaulted)
683 {
684         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
685
686         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
687                 return STATUS_UNKNOWN_REVISION;
688         if (lpsd->Control & SE_SELF_RELATIVE)
689                 return STATUS_INVALID_SECURITY_DESCR;
690         if (!saclpresent) {
691                 lpsd->Control &= ~SE_SACL_PRESENT;
692                 return 0;
693         }
694         lpsd->Control |= SE_SACL_PRESENT;
695         lpsd->Sacl = sacl;
696         if (sacldefaulted)
697                 lpsd->Control |= SE_SACL_DEFAULTED;
698         else
699                 lpsd->Control &= ~SE_SACL_DEFAULTED;
700         return STATUS_SUCCESS;
701 }
702
703 /**************************************************************************
704  * RtlGetOwnerSecurityDescriptor                [NTDLL.@]
705  */
706 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
707         PSECURITY_DESCRIPTOR pSecurityDescriptor,
708         PSID *Owner,
709         PBOOLEAN OwnerDefaulted)
710 {
711         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
712
713         if ( !lpsd  || !Owner || !OwnerDefaulted )
714                 return STATUS_INVALID_PARAMETER;
715
716         if (lpsd->Owner != NULL)
717         {
718             if (lpsd->Control & SE_SELF_RELATIVE)
719                 *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner);
720             else
721                 *Owner = lpsd->Owner;
722
723             if ( lpsd->Control & SE_OWNER_DEFAULTED )
724                 *OwnerDefaulted = TRUE;
725             else
726                 *OwnerDefaulted = FALSE;
727         }
728         else
729             *Owner = NULL;
730
731         return STATUS_SUCCESS;
732 }
733
734 /**************************************************************************
735  *                 RtlSetOwnerSecurityDescriptor                [NTDLL.@]
736  */
737 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
738         PSECURITY_DESCRIPTOR pSecurityDescriptor,
739         PSID owner,
740         BOOLEAN ownerdefaulted)
741 {
742         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
743
744         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
745                 return STATUS_UNKNOWN_REVISION;
746         if (lpsd->Control & SE_SELF_RELATIVE)
747                 return STATUS_INVALID_SECURITY_DESCR;
748
749         lpsd->Owner = owner;
750         if (ownerdefaulted)
751                 lpsd->Control |= SE_OWNER_DEFAULTED;
752         else
753                 lpsd->Control &= ~SE_OWNER_DEFAULTED;
754         return STATUS_SUCCESS;
755 }
756
757 /**************************************************************************
758  *                 RtlSetGroupSecurityDescriptor                [NTDLL.@]
759  */
760 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
761         PSECURITY_DESCRIPTOR pSecurityDescriptor,
762         PSID group,
763         BOOLEAN groupdefaulted)
764 {
765         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
766
767         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
768                 return STATUS_UNKNOWN_REVISION;
769         if (lpsd->Control & SE_SELF_RELATIVE)
770                 return STATUS_INVALID_SECURITY_DESCR;
771
772         lpsd->Group = group;
773         if (groupdefaulted)
774                 lpsd->Control |= SE_GROUP_DEFAULTED;
775         else
776                 lpsd->Control &= ~SE_GROUP_DEFAULTED;
777         return STATUS_SUCCESS;
778 }
779
780 /**************************************************************************
781  *                 RtlGetGroupSecurityDescriptor                [NTDLL.@]
782  */
783 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
784         PSECURITY_DESCRIPTOR pSecurityDescriptor,
785         PSID *Group,
786         PBOOLEAN GroupDefaulted)
787 {
788         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
789
790         if ( !lpsd || !Group || !GroupDefaulted )
791                 return STATUS_INVALID_PARAMETER;
792
793         if (lpsd->Group != NULL)
794         {
795             if (lpsd->Control & SE_SELF_RELATIVE)
796                 *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group);
797             else
798                 *Group = lpsd->Group;
799
800             if ( lpsd->Control & SE_GROUP_DEFAULTED )
801                 *GroupDefaulted = TRUE;
802             else
803                 *GroupDefaulted = FALSE;
804         }
805         else
806             *Group = NULL;
807
808         return STATUS_SUCCESS;
809 }
810
811 /**************************************************************************
812  *                 RtlMakeSelfRelativeSD                [NTDLL.@]
813  */
814 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
815         IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
816         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
817         IN OUT LPDWORD lpdwBufferLength)
818 {
819     ULONG_PTR offsetRel;
820     ULONG length;
821     SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
822     SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
823
824     TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
825         lpdwBufferLength ? *lpdwBufferLength: -1);
826
827     if (!lpdwBufferLength || !pAbs)
828         return STATUS_INVALID_PARAMETER;
829
830     length = RtlLengthSecurityDescriptor(pAbs);
831     if (*lpdwBufferLength < length)
832     {
833         *lpdwBufferLength = length;
834         return STATUS_BUFFER_TOO_SMALL;
835     }
836
837     if (!pRel)
838         return STATUS_INVALID_PARAMETER;
839
840     if (pAbs->Control & SE_SELF_RELATIVE)
841     {
842         memcpy(pRel, pAbs, length);
843         return STATUS_SUCCESS;
844     }
845
846     pRel->Revision = pAbs->Revision;
847     pRel->Sbz1 = pAbs->Sbz1;
848     pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
849
850     offsetRel = sizeof(SECURITY_DESCRIPTOR);
851     if (pAbs->Owner)
852     {
853         pRel->Owner = (PSID) offsetRel;
854         length = RtlLengthSid(pAbs->Owner);
855         memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
856         offsetRel += length;
857     }
858     else
859     {
860         pRel->Owner = NULL;
861     }
862
863     if (pAbs->Group)
864     {
865         pRel->Group = (PSID) offsetRel;
866         length = RtlLengthSid(pAbs->Group);
867         memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
868         offsetRel += length;
869     }
870     else
871     {
872         pRel->Group = NULL;
873     }
874
875     if (pAbs->Sacl)
876     {
877         pRel->Sacl = (PACL) offsetRel;
878         length = pAbs->Sacl->AclSize;
879         memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
880         offsetRel += length;
881     }
882     else
883     {
884         pRel->Sacl = NULL;
885     }
886
887     if (pAbs->Dacl)
888     {
889         pRel->Dacl = (PACL) offsetRel;
890         length = pAbs->Dacl->AclSize;
891         memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
892     }
893     else
894     {
895         pRel->Dacl = NULL;
896     }
897
898     return STATUS_SUCCESS;
899 }
900
901
902 /**************************************************************************
903  *                 RtlSelfRelativeToAbsoluteSD [NTDLL.@]
904  */
905 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
906         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
907         OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
908         OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
909         OUT PACL pDacl,
910         OUT LPDWORD lpdwDaclSize,
911         OUT PACL pSacl,
912         OUT LPDWORD lpdwSaclSize,
913         OUT PSID pOwner,
914         OUT LPDWORD lpdwOwnerSize,
915         OUT PSID pPrimaryGroup,
916         OUT LPDWORD lpdwPrimaryGroupSize)
917 {
918     NTSTATUS status = STATUS_SUCCESS;
919     SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
920     SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
921
922     if (!pRel ||
923         !lpdwAbsoluteSecurityDescriptorSize ||
924         !lpdwDaclSize ||
925         !lpdwSaclSize ||
926         !lpdwOwnerSize ||
927         !lpdwPrimaryGroupSize ||
928         ~pRel->Control & SE_SELF_RELATIVE)
929         return STATUS_INVALID_PARAMETER;
930
931     /* Confirm buffers are sufficiently large */
932     if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
933     {
934         *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
935         status = STATUS_BUFFER_TOO_SMALL;
936     }
937
938     if (pRel->Control & SE_DACL_PRESENT &&
939         *lpdwDaclSize  < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
940     {
941         *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
942         status = STATUS_BUFFER_TOO_SMALL;
943     }
944
945     if (pRel->Control & SE_SACL_PRESENT &&
946         *lpdwSaclSize  < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
947     {
948         *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
949         status = STATUS_BUFFER_TOO_SMALL;
950     }
951
952     if (pRel->Owner &&
953         *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
954     {
955         *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
956         status = STATUS_BUFFER_TOO_SMALL;
957     }
958
959     if (pRel->Group &&
960         *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
961     {
962         *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
963         status = STATUS_BUFFER_TOO_SMALL;
964     }
965
966     if (status != STATUS_SUCCESS)
967         return status;
968
969     /* Copy structures, and clear the ones we don't set */
970     pAbs->Revision = pRel->Revision;
971     pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
972     pAbs->Sacl = NULL;
973     pAbs->Dacl = NULL;
974     pAbs->Owner = NULL;
975     pAbs->Group = NULL;
976
977     if (pRel->Control & SE_SACL_PRESENT)
978     {
979         PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
980
981         memcpy(pSacl, pAcl, pAcl->AclSize);
982         pAbs->Sacl = pSacl;
983     }
984
985     if (pRel->Control & SE_DACL_PRESENT)
986     {
987         PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
988         memcpy(pDacl, pAcl, pAcl->AclSize);
989         pAbs->Dacl = pDacl;
990     }
991
992     if (pRel->Owner)
993     {
994         PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
995         memcpy(pOwner, psid, RtlLengthSid(psid));
996         pAbs->Owner = pOwner;
997     }
998
999     if (pRel->Group)
1000     {
1001         PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
1002         memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1003         pAbs->Group = pPrimaryGroup;
1004     }
1005
1006     return status;
1007 }
1008
1009 /******************************************************************************
1010  * RtlGetControlSecurityDescriptor (NTDLL.@)
1011  */
1012 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1013     PSECURITY_DESCRIPTOR pSecurityDescriptor,
1014     PSECURITY_DESCRIPTOR_CONTROL pControl,
1015     LPDWORD lpdwRevision)
1016 {
1017     SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1018
1019     TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1020
1021     *lpdwRevision = lpsd->Revision;
1022
1023     if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1024         return STATUS_UNKNOWN_REVISION;
1025
1026     *pControl = lpsd->Control;
1027
1028     return STATUS_SUCCESS;
1029 }
1030
1031
1032 /**************************************************************************
1033  *                 RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1034  */
1035 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1036     PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1037     PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1038     PULONG BufferLength)
1039 {
1040     SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1041
1042     TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1043           SelfRelativeSecurityDescriptor, BufferLength);
1044
1045     if (abs->Control & SE_SELF_RELATIVE)
1046         return STATUS_BAD_DESCRIPTOR_FORMAT;
1047
1048     return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor, 
1049         SelfRelativeSecurityDescriptor, BufferLength);
1050 }
1051
1052
1053 /*
1054  *      access control list's
1055  */
1056
1057 /**************************************************************************
1058  *                 RtlCreateAcl                         [NTDLL.@]
1059  *
1060  * NOTES
1061  *    This should return NTSTATUS
1062  */
1063 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1064 {
1065         TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1066
1067         if (rev!=ACL_REVISION)
1068                 return STATUS_INVALID_PARAMETER;
1069         if (size<sizeof(ACL))
1070                 return STATUS_BUFFER_TOO_SMALL;
1071         if (size>0xFFFF)
1072                 return STATUS_INVALID_PARAMETER;
1073
1074         memset(acl,'\0',sizeof(ACL));
1075         acl->AclRevision        = rev;
1076         acl->AclSize            = size;
1077         acl->AceCount           = 0;
1078         return STATUS_SUCCESS;
1079 }
1080
1081 /**************************************************************************
1082  *                 RtlFirstFreeAce                      [NTDLL.@]
1083  * looks for the AceCount+1 ACE, and if it is still within the alloced
1084  * ACL, return a pointer to it
1085  */
1086 BOOLEAN WINAPI RtlFirstFreeAce(
1087         PACL acl,
1088         PACE_HEADER *x)
1089 {
1090         PACE_HEADER     ace;
1091         int             i;
1092
1093         *x = 0;
1094         ace = (PACE_HEADER)(acl+1);
1095         for (i=0;i<acl->AceCount;i++) {
1096                 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1097                         return 0;
1098                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1099         }
1100         if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1101                 return 0;
1102         *x = ace;
1103         return 1;
1104 }
1105
1106 /**************************************************************************
1107  *                 RtlAddAce                            [NTDLL.@]
1108  */
1109 NTSTATUS WINAPI RtlAddAce(
1110         PACL acl,
1111         DWORD rev,
1112         DWORD xnrofaces,
1113         PACE_HEADER acestart,
1114         DWORD acelen)
1115 {
1116         PACE_HEADER     ace,targetace;
1117         int             nrofaces;
1118
1119         if (acl->AclRevision != ACL_REVISION)
1120                 return STATUS_INVALID_PARAMETER;
1121         if (!RtlFirstFreeAce(acl,&targetace))
1122                 return STATUS_INVALID_PARAMETER;
1123         nrofaces=0;ace=acestart;
1124         while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1125                 nrofaces++;
1126                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1127         }
1128         if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1129                 return STATUS_INVALID_PARAMETER;
1130         memcpy((LPBYTE)targetace,acestart,acelen);
1131         acl->AceCount+=nrofaces;
1132         return STATUS_SUCCESS;
1133 }
1134
1135 /**************************************************************************
1136  *                 RtlDeleteAce                         [NTDLL.@]
1137  */
1138 NTSTATUS  WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1139 {
1140         NTSTATUS status;
1141         PACE_HEADER pAce;
1142
1143         status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1144
1145         if (STATUS_SUCCESS == status)
1146         {
1147                 PACE_HEADER pcAce;
1148                 DWORD len = 0;
1149
1150                 /* skip over the ACE we are deleting */
1151                 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1152                 dwAceIndex++;
1153
1154                 /* calculate the length of the rest */
1155                 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1156                 {
1157                         len += pcAce->AceSize;
1158                         pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1159                 }
1160
1161                 /* slide them all backwards */
1162                 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1163                 pAcl->AceCount--;
1164         }
1165
1166         TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1167
1168         return status;
1169 }
1170
1171 /******************************************************************************
1172  *  RtlAddAccessAllowedAce              [NTDLL.@]
1173  */
1174 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1175         IN OUT PACL pAcl,
1176         IN DWORD dwAceRevision,
1177         IN DWORD AccessMask,
1178         IN PSID pSid)
1179 {
1180         return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1181 }
1182  
1183 /******************************************************************************
1184  *  RtlAddAccessAllowedAceEx            [NTDLL.@]
1185  */
1186 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1187         IN OUT PACL pAcl,
1188         IN DWORD dwAceRevision,
1189         IN DWORD AceFlags,
1190         IN DWORD AccessMask,
1191         IN PSID pSid)
1192 {
1193    TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1194
1195     return add_access_ace(pAcl, dwAceRevision, AceFlags,
1196                           AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1197 }
1198
1199 /******************************************************************************
1200  *  RtlAddAccessDeniedAce               [NTDLL.@]
1201  */
1202 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1203         IN OUT PACL pAcl,
1204         IN DWORD dwAceRevision,
1205         IN DWORD AccessMask,
1206         IN PSID pSid)
1207 {
1208         return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1209 }
1210
1211 /******************************************************************************
1212  *  RtlAddAccessDeniedAceEx             [NTDLL.@]
1213  */
1214 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1215         IN OUT PACL pAcl,
1216         IN DWORD dwAceRevision,
1217         IN DWORD AceFlags,
1218         IN DWORD AccessMask,
1219         IN PSID pSid)
1220 {
1221    TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1222
1223     return add_access_ace(pAcl, dwAceRevision, AceFlags,
1224                           AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1225 }
1226
1227 /************************************************************************** 
1228  *  RtlAddAuditAccessAce     [NTDLL.@] 
1229  */ 
1230 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1231     IN OUT PACL pAcl, 
1232     IN DWORD dwAceRevision, 
1233     IN DWORD dwAceFlags,
1234     IN DWORD dwAccessMask, 
1235     IN PSID pSid, 
1236     IN BOOL bAuditSuccess, 
1237     IN BOOL bAuditFailure) 
1238
1239     TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1240           pSid,bAuditSuccess,bAuditFailure);
1241
1242     if (bAuditSuccess)
1243         dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1244
1245     if (bAuditFailure)
1246         dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1247
1248     return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1249                           dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1250
1251
1252 /**************************************************************************
1253  *  RtlAddAuditAccessAce     [NTDLL.@]
1254  */
1255 NTSTATUS WINAPI RtlAddAuditAccessAce(
1256     IN OUT PACL pAcl,
1257     IN DWORD dwAceRevision,
1258     IN DWORD dwAccessMask,
1259     IN PSID pSid,
1260     IN BOOL bAuditSuccess,
1261     IN BOOL bAuditFailure)
1262 {
1263     return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1264 }
1265  
1266 /******************************************************************************
1267  *  RtlValidAcl         [NTDLL.@]
1268  */
1269 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1270 {
1271         BOOLEAN ret;
1272         TRACE("(%p)\n", pAcl);
1273
1274         __TRY
1275         {
1276                 PACE_HEADER     ace;
1277                 int             i;
1278
1279                 if (pAcl->AclRevision != ACL_REVISION)
1280                     ret = FALSE;
1281                 else
1282                 {
1283                     ace = (PACE_HEADER)(pAcl+1);
1284                     ret = TRUE;
1285                     for (i=0;i<=pAcl->AceCount;i++)
1286                     {
1287                         if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1288                         {
1289                             ret = FALSE;
1290                             break;
1291                         }
1292                         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1293                     }
1294                 }
1295         }
1296         __EXCEPT_PAGE_FAULT
1297         {
1298                 WARN("(%p): invalid pointer!\n", pAcl);
1299                 return 0;
1300         }
1301         __ENDTRY
1302         return ret;
1303 }
1304
1305 /******************************************************************************
1306  *  RtlGetAce           [NTDLL.@]
1307  */
1308 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1309 {
1310         PACE_HEADER ace;
1311
1312         TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1313
1314         if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1315                 return STATUS_INVALID_PARAMETER;
1316
1317         ace = (PACE_HEADER)(pAcl + 1);
1318         for (;dwAceIndex;dwAceIndex--)
1319                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1320
1321         *pAce = (LPVOID) ace;
1322
1323         return STATUS_SUCCESS;
1324 }
1325
1326 /*
1327  *      misc
1328  */
1329
1330 /******************************************************************************
1331  *  RtlAdjustPrivilege          [NTDLL.@]
1332  *
1333  * Enables or disables a privilege from the calling thread or process.
1334  *
1335  * PARAMS
1336  *  Privilege     [I] Privilege index to change.
1337  *  Enable        [I] If TRUE, then enable the privilege otherwise disable.
1338  *  CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1339  *  Enabled       [O] Whether privilege was previously enabled or disabled.
1340  *
1341  * RETURNS
1342  *  Success: STATUS_SUCCESS.
1343  *  Failure: NTSTATUS code.
1344  *
1345  * SEE ALSO
1346  *  NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1347  *
1348  */
1349 NTSTATUS WINAPI
1350 RtlAdjustPrivilege(ULONG Privilege,
1351                    BOOLEAN Enable,
1352                    BOOLEAN CurrentThread,
1353                    PBOOLEAN Enabled)
1354 {
1355     TOKEN_PRIVILEGES NewState;
1356     TOKEN_PRIVILEGES OldState;
1357     ULONG ReturnLength;
1358     HANDLE TokenHandle;
1359     NTSTATUS Status;
1360
1361     TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1362         CurrentThread ? "TRUE" : "FALSE", Enabled);
1363
1364     if (CurrentThread)
1365     {
1366         Status = NtOpenThreadToken(GetCurrentThread(),
1367                                    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1368                                    FALSE,
1369                                    &TokenHandle);
1370     }
1371     else
1372     {
1373         Status = NtOpenProcessToken(GetCurrentProcess(),
1374                                     TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1375                                     &TokenHandle);
1376     }
1377
1378     if (!NT_SUCCESS(Status))
1379     {
1380         WARN("Retrieving token handle failed (Status %x)\n", Status);
1381         return Status;
1382     }
1383
1384     OldState.PrivilegeCount = 1;
1385
1386     NewState.PrivilegeCount = 1;
1387     NewState.Privileges[0].Luid.LowPart = Privilege;
1388     NewState.Privileges[0].Luid.HighPart = 0;
1389     NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1390
1391     Status = NtAdjustPrivilegesToken(TokenHandle,
1392                                      FALSE,
1393                                      &NewState,
1394                                      sizeof(TOKEN_PRIVILEGES),
1395                                      &OldState,
1396                                      &ReturnLength);
1397     NtClose (TokenHandle);
1398     if (Status == STATUS_NOT_ALL_ASSIGNED)
1399     {
1400         TRACE("Failed to assign all privileges\n");
1401         return STATUS_PRIVILEGE_NOT_HELD;
1402     }
1403     if (!NT_SUCCESS(Status))
1404     {
1405         WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1406         return Status;
1407     }
1408
1409     if (OldState.PrivilegeCount == 0)
1410         *Enabled = Enable;
1411     else
1412         *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1413
1414     return STATUS_SUCCESS;
1415 }
1416
1417 /******************************************************************************
1418  *  RtlImpersonateSelf          [NTDLL.@]
1419  *
1420  * Makes an impersonation token that represents the process user and assigns
1421  * to the current thread.
1422  *
1423  * PARAMS
1424  *  ImpersonationLevel [I] Level at which to impersonate.
1425  *
1426  * RETURNS
1427  *  Success: STATUS_SUCCESS.
1428  *  Failure: NTSTATUS code.
1429  */
1430 NTSTATUS WINAPI
1431 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1432 {
1433     NTSTATUS Status;
1434     OBJECT_ATTRIBUTES ObjectAttributes;
1435     HANDLE ProcessToken;
1436     HANDLE ImpersonationToken;
1437
1438     TRACE("(%08x)\n", ImpersonationLevel);
1439
1440     Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1441                                  &ProcessToken);
1442     if (Status != STATUS_SUCCESS)
1443         return Status;
1444
1445     InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1446
1447     Status = NtDuplicateToken( ProcessToken,
1448                                TOKEN_IMPERSONATE,
1449                                &ObjectAttributes,
1450                                ImpersonationLevel,
1451                                TokenImpersonation,
1452                                &ImpersonationToken );
1453     if (Status != STATUS_SUCCESS)
1454     {
1455         NtClose( ProcessToken );
1456         return Status;
1457     }
1458
1459     Status = NtSetInformationThread( GetCurrentThread(),
1460                                      ThreadImpersonationToken,
1461                                      &ImpersonationToken,
1462                                      sizeof(ImpersonationToken) );
1463
1464     NtClose( ImpersonationToken );
1465     NtClose( ProcessToken );
1466
1467     return Status;
1468 }
1469
1470 /******************************************************************************
1471  *  NtAccessCheck               [NTDLL.@]
1472  *  ZwAccessCheck               [NTDLL.@]
1473  *
1474  * Checks that a user represented by a token is allowed to access an object
1475  * represented by a security descriptor.
1476  *
1477  * PARAMS
1478  *  SecurityDescriptor [I] The security descriptor of the object to check.
1479  *  ClientToken        [I] Token of the user accessing the object.
1480  *  DesiredAccess      [I] The desired access to the object.
1481  *  GenericMapping     [I] Mapping used to transform access rights in the SD to their specific forms.
1482  *  PrivilegeSet       [I/O] Privileges used during the access check.
1483  *  ReturnLength       [O] Number of bytes stored into PrivilegeSet.
1484  *  GrantedAccess      [O] The actual access rights granted.
1485  *  AccessStatus       [O] The status of the access check.
1486  *
1487  * RETURNS
1488  *  NTSTATUS code.
1489  *
1490  * NOTES
1491  *  DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1492  *  the maximum access rights allowed by the SD and returns them in
1493  *  GrantedAccess.
1494  *  The SecurityDescriptor must have a valid owner and groups present,
1495  *  otherwise the function will fail.
1496  */
1497 NTSTATUS WINAPI
1498 NtAccessCheck(
1499     PSECURITY_DESCRIPTOR SecurityDescriptor,
1500     HANDLE ClientToken,
1501     ACCESS_MASK DesiredAccess,
1502     PGENERIC_MAPPING GenericMapping,
1503     PPRIVILEGE_SET PrivilegeSet,
1504     PULONG ReturnLength,
1505     PULONG GrantedAccess,
1506     NTSTATUS *AccessStatus)
1507 {
1508     NTSTATUS status;
1509
1510     TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1511         SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1512         PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1513
1514     SERVER_START_REQ( access_check )
1515     {
1516         struct security_descriptor sd;
1517         PSID owner;
1518         PSID group;
1519         PACL sacl;
1520         PACL dacl;
1521         BOOLEAN defaulted, present;
1522         DWORD revision;
1523         SECURITY_DESCRIPTOR_CONTROL control;
1524
1525         req->handle = ClientToken;
1526         req->desired_access = DesiredAccess;
1527         req->mapping_read = GenericMapping->GenericRead;
1528         req->mapping_write = GenericMapping->GenericWrite;
1529         req->mapping_execute = GenericMapping->GenericExecute;
1530         req->mapping_all = GenericMapping->GenericAll;
1531
1532         /* marshal security descriptor */
1533         RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1534         sd.control = control & ~SE_SELF_RELATIVE;
1535         RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1536         sd.owner_len = RtlLengthSid( owner );
1537         RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1538         sd.group_len = RtlLengthSid( group );
1539         RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1540         sd.sacl_len = (present ? sacl->AclSize : 0);
1541         RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1542         sd.dacl_len = (present ? dacl->AclSize : 0);
1543
1544         wine_server_add_data( req, &sd, sizeof(sd) );
1545         wine_server_add_data( req, owner, sd.owner_len );
1546         wine_server_add_data( req, group, sd.group_len );
1547         wine_server_add_data( req, sacl, sd.sacl_len );
1548         wine_server_add_data( req, dacl, sd.dacl_len );
1549
1550         wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1551
1552         status = wine_server_call( req );
1553
1554         *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1555         PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1556
1557         if (status == STATUS_SUCCESS)
1558         {
1559             *AccessStatus = reply->access_status;
1560             *GrantedAccess = reply->access_granted;
1561         }
1562     }
1563     SERVER_END_REQ;
1564
1565     return status;
1566 }
1567
1568 /******************************************************************************
1569  *  NtSetSecurityObject         [NTDLL.@]
1570  *  ZwSetSecurityObject         [NTDLL.@]
1571  *
1572  * Sets specified parts of the object's security descriptor.
1573  *
1574  * PARAMS
1575  *  Handle              [I] Handle to the object to change security descriptor of.
1576  *  SecurityInformation [I] Specifies which parts of the security descriptor to set.
1577  *  SecurityDescriptor  [I] New parts of a security descriptor for the object.
1578  *
1579  * RETURNS
1580  *  NTSTATUS code.
1581  *
1582  */
1583 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1584         SECURITY_INFORMATION SecurityInformation,
1585         PSECURITY_DESCRIPTOR SecurityDescriptor)
1586 {
1587     NTSTATUS status;
1588     struct security_descriptor sd;
1589     PACL dacl = NULL, sacl = NULL;
1590     PSID owner = NULL, group = NULL;
1591     BOOLEAN defaulted, present;
1592     DWORD revision;
1593     SECURITY_DESCRIPTOR_CONTROL control;
1594
1595     TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1596
1597     if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1598
1599     memset( &sd, 0, sizeof(sd) );
1600     status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1601     if (status != STATUS_SUCCESS) return status;
1602     sd.control = control & ~SE_SELF_RELATIVE;
1603
1604     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1605     {
1606         status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1607         if (status != STATUS_SUCCESS) return status;
1608         if (!(sd.owner_len = RtlLengthSid( owner )))
1609             return STATUS_INVALID_SECURITY_DESCR;
1610     }
1611
1612     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1613     {
1614         status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1615         if (status != STATUS_SUCCESS) return status;
1616         if (!(sd.group_len = RtlLengthSid( group )))
1617             return STATUS_INVALID_SECURITY_DESCR;
1618     }
1619
1620     if (SecurityInformation & SACL_SECURITY_INFORMATION)
1621     {
1622         status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1623         if (status != STATUS_SUCCESS) return status;
1624         sd.sacl_len = (sacl && present) ? sacl->AclSize : 0;
1625         sd.control |= SE_SACL_PRESENT;
1626     }
1627
1628     if (SecurityInformation & DACL_SECURITY_INFORMATION)
1629     {
1630         status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1631         if (status != STATUS_SUCCESS) return status;
1632         sd.dacl_len = (dacl && present) ? dacl->AclSize : 0;
1633         sd.control |= SE_DACL_PRESENT;
1634     }
1635
1636     SERVER_START_REQ( set_security_object )
1637     {
1638         req->handle = Handle;
1639         req->security_info = SecurityInformation;
1640
1641         wine_server_add_data( req, &sd, sizeof(sd) );
1642         wine_server_add_data( req, owner, sd.owner_len );
1643         wine_server_add_data( req, group, sd.group_len );
1644         wine_server_add_data( req, sacl, sd.sacl_len );
1645         wine_server_add_data( req, dacl, sd.dacl_len );
1646         status = wine_server_call( req );
1647     }
1648     SERVER_END_REQ;
1649
1650     return status;
1651 }
1652
1653 /******************************************************************************
1654  * RtlConvertSidToUnicodeString (NTDLL.@)
1655  *
1656  * The returned SID is used to access the USER registry hive usually
1657  *
1658  * the native function returns something like
1659  * "S-1-5-21-0000000000-000000000-0000000000-500";
1660  */
1661 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1662        PUNICODE_STRING String,
1663        PSID pSid,
1664        BOOLEAN AllocateString)
1665 {
1666     static const WCHAR formatW[] = {'-','%','u',0};
1667     WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1668     WCHAR *p = buffer;
1669     const SID *sid = (const SID *)pSid;
1670     DWORD i, len;
1671
1672     *p++ = 'S';
1673     p += sprintfW( p, formatW, sid->Revision );
1674     p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1675                                                    sid->IdentifierAuthority.Value[4] ),
1676                                          MAKEWORD( sid->IdentifierAuthority.Value[3],
1677                                                    sid->IdentifierAuthority.Value[2] )));
1678     for (i = 0; i < sid->SubAuthorityCount; i++)
1679         p += sprintfW( p, formatW, sid->SubAuthority[i] );
1680
1681     len = (p + 1 - buffer) * sizeof(WCHAR);
1682
1683     String->Length = len - sizeof(WCHAR);
1684     if (AllocateString)
1685     {
1686         String->MaximumLength = len;
1687         if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1688             return STATUS_NO_MEMORY;
1689     }
1690     else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1691
1692     memcpy( String->Buffer, buffer, len );
1693     return STATUS_SUCCESS;
1694 }
1695
1696 /******************************************************************************
1697  * RtlQueryInformationAcl (NTDLL.@)
1698  */
1699 NTSTATUS WINAPI RtlQueryInformationAcl(
1700     PACL pAcl,
1701     LPVOID pAclInformation,
1702     DWORD nAclInformationLength,
1703     ACL_INFORMATION_CLASS dwAclInformationClass)
1704 {
1705     NTSTATUS status = STATUS_SUCCESS;
1706
1707     TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n", 
1708         pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1709
1710     switch (dwAclInformationClass)
1711     {
1712         case AclRevisionInformation:
1713         {
1714             PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1715
1716             if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1717                 status = STATUS_INVALID_PARAMETER;
1718             else
1719                 paclrev->AclRevision = pAcl->AclRevision;
1720
1721             break;
1722         }
1723
1724         case AclSizeInformation:
1725         {
1726             PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1727
1728             if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1729                 status = STATUS_INVALID_PARAMETER;
1730             else
1731             {
1732                 INT i;
1733                 PACE_HEADER ace;
1734
1735                 paclsize->AceCount = pAcl->AceCount;
1736
1737                 paclsize->AclBytesInUse = 0;
1738                 ace = (PACE_HEADER) (pAcl + 1);
1739
1740                 for (i = 0; i < pAcl->AceCount; i++)
1741                 {
1742                     paclsize->AclBytesInUse += ace->AceSize;
1743                     ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1744                 }
1745
1746                 if (pAcl->AclSize < paclsize->AclBytesInUse)
1747                 {
1748                     WARN("Acl has %d bytes free\n", paclsize->AclBytesFree);
1749                     paclsize->AclBytesFree = 0;
1750                     paclsize->AclBytesInUse = pAcl->AclSize;
1751                 }
1752                 else
1753                     paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1754             }
1755
1756             break;
1757         }
1758
1759         default:
1760             WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1761             status = STATUS_INVALID_PARAMETER;
1762     }
1763
1764     return status;
1765 }