d3dxof: Remove 'recursive registry key delete' function.
[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     pRel->Owner = (PSID) offsetRel;
852     length = RtlLengthSid(pAbs->Owner);
853     memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
854
855     offsetRel += length;
856     pRel->Group = (PSID) offsetRel;
857     length = RtlLengthSid(pAbs->Group);
858     memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
859
860     if (pRel->Control & SE_SACL_PRESENT)
861     {
862         offsetRel += length;
863         pRel->Sacl = (PACL) offsetRel;
864         length = pAbs->Sacl->AclSize;
865         memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
866     }
867     else
868     {
869         pRel->Sacl = NULL;
870     }
871
872     if (pRel->Control & SE_DACL_PRESENT)
873     {
874         offsetRel += length;
875         pRel->Dacl = (PACL) offsetRel;
876         length = pAbs->Dacl->AclSize;
877         memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
878     }
879     else
880     {
881         pRel->Dacl = NULL;
882     }
883
884     return STATUS_SUCCESS;
885 }
886
887
888 /**************************************************************************
889  *                 RtlSelfRelativeToAbsoluteSD [NTDLL.@]
890  */
891 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
892         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
893         OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
894         OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
895         OUT PACL pDacl,
896         OUT LPDWORD lpdwDaclSize,
897         OUT PACL pSacl,
898         OUT LPDWORD lpdwSaclSize,
899         OUT PSID pOwner,
900         OUT LPDWORD lpdwOwnerSize,
901         OUT PSID pPrimaryGroup,
902         OUT LPDWORD lpdwPrimaryGroupSize)
903 {
904     NTSTATUS status = STATUS_SUCCESS;
905     SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
906     SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
907
908     if (!pRel ||
909         !lpdwAbsoluteSecurityDescriptorSize ||
910         !lpdwDaclSize ||
911         !lpdwSaclSize ||
912         !lpdwOwnerSize ||
913         !lpdwPrimaryGroupSize ||
914         ~pRel->Control & SE_SELF_RELATIVE)
915         return STATUS_INVALID_PARAMETER;
916
917     /* Confirm buffers are sufficiently large */
918     if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
919     {
920         *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
921         status = STATUS_BUFFER_TOO_SMALL;
922     }
923
924     if (pRel->Control & SE_DACL_PRESENT &&
925         *lpdwDaclSize  < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
926     {
927         *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
928         status = STATUS_BUFFER_TOO_SMALL;
929     }
930
931     if (pRel->Control & SE_SACL_PRESENT &&
932         *lpdwSaclSize  < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
933     {
934         *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
935         status = STATUS_BUFFER_TOO_SMALL;
936     }
937
938     if (pRel->Owner &&
939         *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
940     {
941         *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
942         status = STATUS_BUFFER_TOO_SMALL;
943     }
944
945     if (pRel->Group &&
946         *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
947     {
948         *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
949         status = STATUS_BUFFER_TOO_SMALL;
950     }
951
952     if (status != STATUS_SUCCESS)
953         return status;
954
955     /* Copy structures, and clear the ones we don't set */
956     pAbs->Revision = pRel->Revision;
957     pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
958     pAbs->Sacl = NULL;
959     pAbs->Dacl = NULL;
960     pAbs->Owner = NULL;
961     pAbs->Group = NULL;
962
963     if (pRel->Control & SE_SACL_PRESENT)
964     {
965         PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
966
967         memcpy(pSacl, pAcl, pAcl->AclSize);
968         pAbs->Sacl = pSacl;
969     }
970
971     if (pRel->Control & SE_DACL_PRESENT)
972     {
973         PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
974         memcpy(pDacl, pAcl, pAcl->AclSize);
975         pAbs->Dacl = pDacl;
976     }
977
978     if (pRel->Owner)
979     {
980         PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
981         memcpy(pOwner, psid, RtlLengthSid(psid));
982         pAbs->Owner = pOwner;
983     }
984
985     if (pRel->Group)
986     {
987         PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
988         memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
989         pAbs->Group = pPrimaryGroup;
990     }
991
992     return status;
993 }
994
995 /******************************************************************************
996  * RtlGetControlSecurityDescriptor (NTDLL.@)
997  */
998 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
999     PSECURITY_DESCRIPTOR pSecurityDescriptor,
1000     PSECURITY_DESCRIPTOR_CONTROL pControl,
1001     LPDWORD lpdwRevision)
1002 {
1003     SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1004
1005     TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1006
1007     *lpdwRevision = lpsd->Revision;
1008
1009     if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1010         return STATUS_UNKNOWN_REVISION;
1011
1012     *pControl = lpsd->Control;
1013
1014     return STATUS_SUCCESS;
1015 }
1016
1017
1018 /**************************************************************************
1019  *                 RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1020  */
1021 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1022     PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1023     PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1024     PULONG BufferLength)
1025 {
1026     SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1027
1028     TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1029           SelfRelativeSecurityDescriptor, BufferLength);
1030
1031     if (abs->Control & SE_SELF_RELATIVE)
1032         return STATUS_BAD_DESCRIPTOR_FORMAT;
1033
1034     return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor, 
1035         SelfRelativeSecurityDescriptor, BufferLength);
1036 }
1037
1038
1039 /*
1040  *      access control list's
1041  */
1042
1043 /**************************************************************************
1044  *                 RtlCreateAcl                         [NTDLL.@]
1045  *
1046  * NOTES
1047  *    This should return NTSTATUS
1048  */
1049 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1050 {
1051         TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1052
1053         if (rev!=ACL_REVISION)
1054                 return STATUS_INVALID_PARAMETER;
1055         if (size<sizeof(ACL))
1056                 return STATUS_BUFFER_TOO_SMALL;
1057         if (size>0xFFFF)
1058                 return STATUS_INVALID_PARAMETER;
1059
1060         memset(acl,'\0',sizeof(ACL));
1061         acl->AclRevision        = rev;
1062         acl->AclSize            = size;
1063         acl->AceCount           = 0;
1064         return STATUS_SUCCESS;
1065 }
1066
1067 /**************************************************************************
1068  *                 RtlFirstFreeAce                      [NTDLL.@]
1069  * looks for the AceCount+1 ACE, and if it is still within the alloced
1070  * ACL, return a pointer to it
1071  */
1072 BOOLEAN WINAPI RtlFirstFreeAce(
1073         PACL acl,
1074         PACE_HEADER *x)
1075 {
1076         PACE_HEADER     ace;
1077         int             i;
1078
1079         *x = 0;
1080         ace = (PACE_HEADER)(acl+1);
1081         for (i=0;i<acl->AceCount;i++) {
1082                 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1083                         return 0;
1084                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1085         }
1086         if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1087                 return 0;
1088         *x = ace;
1089         return 1;
1090 }
1091
1092 /**************************************************************************
1093  *                 RtlAddAce                            [NTDLL.@]
1094  */
1095 NTSTATUS WINAPI RtlAddAce(
1096         PACL acl,
1097         DWORD rev,
1098         DWORD xnrofaces,
1099         PACE_HEADER acestart,
1100         DWORD acelen)
1101 {
1102         PACE_HEADER     ace,targetace;
1103         int             nrofaces;
1104
1105         if (acl->AclRevision != ACL_REVISION)
1106                 return STATUS_INVALID_PARAMETER;
1107         if (!RtlFirstFreeAce(acl,&targetace))
1108                 return STATUS_INVALID_PARAMETER;
1109         nrofaces=0;ace=acestart;
1110         while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1111                 nrofaces++;
1112                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1113         }
1114         if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1115                 return STATUS_INVALID_PARAMETER;
1116         memcpy((LPBYTE)targetace,acestart,acelen);
1117         acl->AceCount+=nrofaces;
1118         return STATUS_SUCCESS;
1119 }
1120
1121 /**************************************************************************
1122  *                 RtlDeleteAce                         [NTDLL.@]
1123  */
1124 NTSTATUS  WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1125 {
1126         NTSTATUS status;
1127         PACE_HEADER pAce;
1128
1129         status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1130
1131         if (STATUS_SUCCESS == status)
1132         {
1133                 PACE_HEADER pcAce;
1134                 DWORD len = 0;
1135
1136                 /* skip over the ACE we are deleting */
1137                 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1138                 dwAceIndex++;
1139
1140                 /* calculate the length of the rest */
1141                 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1142                 {
1143                         len += pcAce->AceSize;
1144                         pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1145                 }
1146
1147                 /* slide them all backwards */
1148                 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1149                 pAcl->AceCount--;
1150         }
1151
1152         TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1153
1154         return status;
1155 }
1156
1157 /******************************************************************************
1158  *  RtlAddAccessAllowedAce              [NTDLL.@]
1159  */
1160 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1161         IN OUT PACL pAcl,
1162         IN DWORD dwAceRevision,
1163         IN DWORD AccessMask,
1164         IN PSID pSid)
1165 {
1166         return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1167 }
1168  
1169 /******************************************************************************
1170  *  RtlAddAccessAllowedAceEx            [NTDLL.@]
1171  */
1172 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1173         IN OUT PACL pAcl,
1174         IN DWORD dwAceRevision,
1175         IN DWORD AceFlags,
1176         IN DWORD AccessMask,
1177         IN PSID pSid)
1178 {
1179    TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1180
1181     return add_access_ace(pAcl, dwAceRevision, AceFlags,
1182                           AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1183 }
1184
1185 /******************************************************************************
1186  *  RtlAddAccessDeniedAce               [NTDLL.@]
1187  */
1188 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1189         IN OUT PACL pAcl,
1190         IN DWORD dwAceRevision,
1191         IN DWORD AccessMask,
1192         IN PSID pSid)
1193 {
1194         return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1195 }
1196
1197 /******************************************************************************
1198  *  RtlAddAccessDeniedAceEx             [NTDLL.@]
1199  */
1200 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1201         IN OUT PACL pAcl,
1202         IN DWORD dwAceRevision,
1203         IN DWORD AceFlags,
1204         IN DWORD AccessMask,
1205         IN PSID pSid)
1206 {
1207    TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1208
1209     return add_access_ace(pAcl, dwAceRevision, AceFlags,
1210                           AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1211 }
1212
1213 /************************************************************************** 
1214  *  RtlAddAuditAccessAce     [NTDLL.@] 
1215  */ 
1216 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1217     IN OUT PACL pAcl, 
1218     IN DWORD dwAceRevision, 
1219     IN DWORD dwAceFlags,
1220     IN DWORD dwAccessMask, 
1221     IN PSID pSid, 
1222     IN BOOL bAuditSuccess, 
1223     IN BOOL bAuditFailure) 
1224
1225     TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1226           pSid,bAuditSuccess,bAuditFailure);
1227
1228     if (bAuditSuccess)
1229         dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1230
1231     if (bAuditFailure)
1232         dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1233
1234     return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1235                           dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1236
1237
1238 /**************************************************************************
1239  *  RtlAddAuditAccessAce     [NTDLL.@]
1240  */
1241 NTSTATUS WINAPI RtlAddAuditAccessAce(
1242     IN OUT PACL pAcl,
1243     IN DWORD dwAceRevision,
1244     IN DWORD dwAccessMask,
1245     IN PSID pSid,
1246     IN BOOL bAuditSuccess,
1247     IN BOOL bAuditFailure)
1248 {
1249     return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1250 }
1251  
1252 /******************************************************************************
1253  *  RtlValidAcl         [NTDLL.@]
1254  */
1255 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1256 {
1257         BOOLEAN ret;
1258         TRACE("(%p)\n", pAcl);
1259
1260         __TRY
1261         {
1262                 PACE_HEADER     ace;
1263                 int             i;
1264
1265                 if (pAcl->AclRevision != ACL_REVISION)
1266                     ret = FALSE;
1267                 else
1268                 {
1269                     ace = (PACE_HEADER)(pAcl+1);
1270                     ret = TRUE;
1271                     for (i=0;i<=pAcl->AceCount;i++)
1272                     {
1273                         if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1274                         {
1275                             ret = FALSE;
1276                             break;
1277                         }
1278                         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1279                     }
1280                 }
1281         }
1282         __EXCEPT_PAGE_FAULT
1283         {
1284                 WARN("(%p): invalid pointer!\n", pAcl);
1285                 return 0;
1286         }
1287         __ENDTRY
1288         return ret;
1289 }
1290
1291 /******************************************************************************
1292  *  RtlGetAce           [NTDLL.@]
1293  */
1294 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1295 {
1296         PACE_HEADER ace;
1297
1298         TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1299
1300         if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1301                 return STATUS_INVALID_PARAMETER;
1302
1303         ace = (PACE_HEADER)(pAcl + 1);
1304         for (;dwAceIndex;dwAceIndex--)
1305                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1306
1307         *pAce = (LPVOID) ace;
1308
1309         return STATUS_SUCCESS;
1310 }
1311
1312 /*
1313  *      misc
1314  */
1315
1316 /******************************************************************************
1317  *  RtlAdjustPrivilege          [NTDLL.@]
1318  *
1319  * Enables or disables a privilege from the calling thread or process.
1320  *
1321  * PARAMS
1322  *  Privilege     [I] Privilege index to change.
1323  *  Enable        [I] If TRUE, then enable the privilege otherwise disable.
1324  *  CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1325  *  Enabled       [O] Whether privilege was previously enabled or disabled.
1326  *
1327  * RETURNS
1328  *  Success: STATUS_SUCCESS.
1329  *  Failure: NTSTATUS code.
1330  *
1331  * SEE ALSO
1332  *  NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1333  *
1334  */
1335 NTSTATUS WINAPI
1336 RtlAdjustPrivilege(ULONG Privilege,
1337                    BOOLEAN Enable,
1338                    BOOLEAN CurrentThread,
1339                    PBOOLEAN Enabled)
1340 {
1341     TOKEN_PRIVILEGES NewState;
1342     TOKEN_PRIVILEGES OldState;
1343     ULONG ReturnLength;
1344     HANDLE TokenHandle;
1345     NTSTATUS Status;
1346
1347     TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1348         CurrentThread ? "TRUE" : "FALSE", Enabled);
1349
1350     if (CurrentThread)
1351     {
1352         Status = NtOpenThreadToken(GetCurrentThread(),
1353                                    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1354                                    FALSE,
1355                                    &TokenHandle);
1356     }
1357     else
1358     {
1359         Status = NtOpenProcessToken(GetCurrentProcess(),
1360                                     TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1361                                     &TokenHandle);
1362     }
1363
1364     if (!NT_SUCCESS(Status))
1365     {
1366         WARN("Retrieving token handle failed (Status %x)\n", Status);
1367         return Status;
1368     }
1369
1370     OldState.PrivilegeCount = 1;
1371
1372     NewState.PrivilegeCount = 1;
1373     NewState.Privileges[0].Luid.LowPart = Privilege;
1374     NewState.Privileges[0].Luid.HighPart = 0;
1375     NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1376
1377     Status = NtAdjustPrivilegesToken(TokenHandle,
1378                                      FALSE,
1379                                      &NewState,
1380                                      sizeof(TOKEN_PRIVILEGES),
1381                                      &OldState,
1382                                      &ReturnLength);
1383     NtClose (TokenHandle);
1384     if (Status == STATUS_NOT_ALL_ASSIGNED)
1385     {
1386         TRACE("Failed to assign all privileges\n");
1387         return STATUS_PRIVILEGE_NOT_HELD;
1388     }
1389     if (!NT_SUCCESS(Status))
1390     {
1391         WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1392         return Status;
1393     }
1394
1395     if (OldState.PrivilegeCount == 0)
1396         *Enabled = Enable;
1397     else
1398         *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1399
1400     return STATUS_SUCCESS;
1401 }
1402
1403 /******************************************************************************
1404  *  RtlImpersonateSelf          [NTDLL.@]
1405  *
1406  * Makes an impersonation token that represents the process user and assigns
1407  * to the current thread.
1408  *
1409  * PARAMS
1410  *  ImpersonationLevel [I] Level at which to impersonate.
1411  *
1412  * RETURNS
1413  *  Success: STATUS_SUCCESS.
1414  *  Failure: NTSTATUS code.
1415  */
1416 NTSTATUS WINAPI
1417 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1418 {
1419     NTSTATUS Status;
1420     OBJECT_ATTRIBUTES ObjectAttributes;
1421     HANDLE ProcessToken;
1422     HANDLE ImpersonationToken;
1423
1424     TRACE("(%08x)\n", ImpersonationLevel);
1425
1426     Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1427                                  &ProcessToken);
1428     if (Status != STATUS_SUCCESS)
1429         return Status;
1430
1431     InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1432
1433     Status = NtDuplicateToken( ProcessToken,
1434                                TOKEN_IMPERSONATE,
1435                                &ObjectAttributes,
1436                                ImpersonationLevel,
1437                                TokenImpersonation,
1438                                &ImpersonationToken );
1439     if (Status != STATUS_SUCCESS)
1440     {
1441         NtClose( ProcessToken );
1442         return Status;
1443     }
1444
1445     Status = NtSetInformationThread( GetCurrentThread(),
1446                                      ThreadImpersonationToken,
1447                                      &ImpersonationToken,
1448                                      sizeof(ImpersonationToken) );
1449
1450     NtClose( ImpersonationToken );
1451     NtClose( ProcessToken );
1452
1453     return Status;
1454 }
1455
1456 /******************************************************************************
1457  *  NtAccessCheck               [NTDLL.@]
1458  *  ZwAccessCheck               [NTDLL.@]
1459  *
1460  * Checks that a user represented by a token is allowed to access an object
1461  * represented by a security descriptor.
1462  *
1463  * PARAMS
1464  *  SecurityDescriptor [I] The security descriptor of the object to check.
1465  *  ClientToken        [I] Token of the user accessing the object.
1466  *  DesiredAccess      [I] The desired access to the object.
1467  *  GenericMapping     [I] Mapping used to transform access rights in the SD to their specific forms.
1468  *  PrivilegeSet       [I/O] Privileges used during the access check.
1469  *  ReturnLength       [O] Number of bytes stored into PrivilegeSet.
1470  *  GrantedAccess      [O] The actual access rights granted.
1471  *  AccessStatus       [O] The status of the access check.
1472  *
1473  * RETURNS
1474  *  NTSTATUS code.
1475  *
1476  * NOTES
1477  *  DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1478  *  the maximum access rights allowed by the SD and returns them in
1479  *  GrantedAccess.
1480  *  The SecurityDescriptor must have a valid owner and groups present,
1481  *  otherwise the function will fail.
1482  */
1483 NTSTATUS WINAPI
1484 NtAccessCheck(
1485     PSECURITY_DESCRIPTOR SecurityDescriptor,
1486     HANDLE ClientToken,
1487     ACCESS_MASK DesiredAccess,
1488     PGENERIC_MAPPING GenericMapping,
1489     PPRIVILEGE_SET PrivilegeSet,
1490     PULONG ReturnLength,
1491     PULONG GrantedAccess,
1492     NTSTATUS *AccessStatus)
1493 {
1494     NTSTATUS status;
1495
1496     TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1497         SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1498         PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1499
1500     SERVER_START_REQ( access_check )
1501     {
1502         struct security_descriptor sd;
1503         PSID owner;
1504         PSID group;
1505         PACL sacl;
1506         PACL dacl;
1507         BOOLEAN defaulted, present;
1508         DWORD revision;
1509         SECURITY_DESCRIPTOR_CONTROL control;
1510
1511         req->handle = ClientToken;
1512         req->desired_access = DesiredAccess;
1513         req->mapping_read = GenericMapping->GenericRead;
1514         req->mapping_write = GenericMapping->GenericWrite;
1515         req->mapping_execute = GenericMapping->GenericExecute;
1516         req->mapping_all = GenericMapping->GenericAll;
1517
1518         /* marshal security descriptor */
1519         RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1520         sd.control = control & ~SE_SELF_RELATIVE;
1521         RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1522         sd.owner_len = RtlLengthSid( owner );
1523         RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1524         sd.group_len = RtlLengthSid( group );
1525         RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1526         sd.sacl_len = (present ? sacl->AclSize : 0);
1527         RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1528         sd.dacl_len = (present ? dacl->AclSize : 0);
1529
1530         wine_server_add_data( req, &sd, sizeof(sd) );
1531         wine_server_add_data( req, owner, sd.owner_len );
1532         wine_server_add_data( req, group, sd.group_len );
1533         wine_server_add_data( req, sacl, sd.sacl_len );
1534         wine_server_add_data( req, dacl, sd.dacl_len );
1535
1536         wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1537
1538         status = wine_server_call( req );
1539
1540         *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1541         PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1542
1543         if (status == STATUS_SUCCESS)
1544         {
1545             *AccessStatus = reply->access_status;
1546             *GrantedAccess = reply->access_granted;
1547         }
1548     }
1549     SERVER_END_REQ;
1550
1551     return status;
1552 }
1553
1554 /******************************************************************************
1555  *  NtSetSecurityObject         [NTDLL.@]
1556  *  ZwSetSecurityObject         [NTDLL.@]
1557  *
1558  * Sets specified parts of the object's security descriptor.
1559  *
1560  * PARAMS
1561  *  Handle              [I] Handle to the object to change security descriptor of.
1562  *  SecurityInformation [I] Specifies which parts of the security descriptor to set.
1563  *  SecurityDescriptor  [I] New parts of a security descriptor for the object.
1564  *
1565  * RETURNS
1566  *  NTSTATUS code.
1567  *
1568  */
1569 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1570         SECURITY_INFORMATION SecurityInformation,
1571         PSECURITY_DESCRIPTOR SecurityDescriptor)
1572 {
1573     NTSTATUS status;
1574     struct security_descriptor sd;
1575     PACL dacl = NULL, sacl = NULL;
1576     PSID owner = NULL, group = NULL;
1577     BOOLEAN defaulted, present;
1578     DWORD revision;
1579     SECURITY_DESCRIPTOR_CONTROL control;
1580
1581     TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1582
1583     if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1584
1585     memset( &sd, 0, sizeof(sd) );
1586     status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1587     if (status != STATUS_SUCCESS) return status;
1588     sd.control = control & ~SE_SELF_RELATIVE;
1589
1590     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1591     {
1592         status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1593         if (status != STATUS_SUCCESS) return status;
1594         if (!(sd.owner_len = RtlLengthSid( owner )))
1595             return STATUS_INVALID_SECURITY_DESCR;
1596     }
1597
1598     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1599     {
1600         status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1601         if (status != STATUS_SUCCESS) return status;
1602         if (!(sd.group_len = RtlLengthSid( group )))
1603             return STATUS_INVALID_SECURITY_DESCR;
1604     }
1605
1606     if (SecurityInformation & SACL_SECURITY_INFORMATION)
1607     {
1608         status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1609         if (status != STATUS_SUCCESS) return status;
1610         sd.sacl_len = (sacl && present) ? sacl->AclSize : 0;
1611         sd.control |= SE_SACL_PRESENT;
1612     }
1613
1614     if (SecurityInformation & DACL_SECURITY_INFORMATION)
1615     {
1616         status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1617         if (status != STATUS_SUCCESS) return status;
1618         sd.dacl_len = (dacl && present) ? dacl->AclSize : 0;
1619         sd.control |= SE_DACL_PRESENT;
1620     }
1621
1622     SERVER_START_REQ( set_security_object )
1623     {
1624         req->handle = Handle;
1625         req->security_info = SecurityInformation;
1626
1627         wine_server_add_data( req, &sd, sizeof(sd) );
1628         wine_server_add_data( req, owner, sd.owner_len );
1629         wine_server_add_data( req, group, sd.group_len );
1630         wine_server_add_data( req, sacl, sd.sacl_len );
1631         wine_server_add_data( req, dacl, sd.dacl_len );
1632         status = wine_server_call( req );
1633     }
1634     SERVER_END_REQ;
1635
1636     return status;
1637 }
1638
1639 /******************************************************************************
1640  * RtlConvertSidToUnicodeString (NTDLL.@)
1641  *
1642  * The returned SID is used to access the USER registry hive usually
1643  *
1644  * the native function returns something like
1645  * "S-1-5-21-0000000000-000000000-0000000000-500";
1646  */
1647 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1648        PUNICODE_STRING String,
1649        PSID pSid,
1650        BOOLEAN AllocateString)
1651 {
1652     static const WCHAR formatW[] = {'-','%','u',0};
1653     WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1654     WCHAR *p = buffer;
1655     const SID *sid = (const SID *)pSid;
1656     DWORD i, len;
1657
1658     *p++ = 'S';
1659     p += sprintfW( p, formatW, sid->Revision );
1660     p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1661                                                    sid->IdentifierAuthority.Value[4] ),
1662                                          MAKEWORD( sid->IdentifierAuthority.Value[3],
1663                                                    sid->IdentifierAuthority.Value[2] )));
1664     for (i = 0; i < sid->SubAuthorityCount; i++)
1665         p += sprintfW( p, formatW, sid->SubAuthority[i] );
1666
1667     len = (p + 1 - buffer) * sizeof(WCHAR);
1668
1669     String->Length = len - sizeof(WCHAR);
1670     if (AllocateString)
1671     {
1672         String->MaximumLength = len;
1673         if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1674             return STATUS_NO_MEMORY;
1675     }
1676     else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1677
1678     memcpy( String->Buffer, buffer, len );
1679     return STATUS_SUCCESS;
1680 }
1681
1682 /******************************************************************************
1683  * RtlQueryInformationAcl (NTDLL.@)
1684  */
1685 NTSTATUS WINAPI RtlQueryInformationAcl(
1686     PACL pAcl,
1687     LPVOID pAclInformation,
1688     DWORD nAclInformationLength,
1689     ACL_INFORMATION_CLASS dwAclInformationClass)
1690 {
1691     NTSTATUS status = STATUS_SUCCESS;
1692
1693     TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n", 
1694         pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1695
1696     switch (dwAclInformationClass)
1697     {
1698         case AclRevisionInformation:
1699         {
1700             PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1701
1702             if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1703                 status = STATUS_INVALID_PARAMETER;
1704             else
1705                 paclrev->AclRevision = pAcl->AclRevision;
1706
1707             break;
1708         }
1709
1710         case AclSizeInformation:
1711         {
1712             PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1713
1714             if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1715                 status = STATUS_INVALID_PARAMETER;
1716             else
1717             {
1718                 INT i;
1719                 PACE_HEADER ace;
1720
1721                 paclsize->AceCount = pAcl->AceCount;
1722
1723                 paclsize->AclBytesInUse = 0;
1724                 ace = (PACE_HEADER) (pAcl + 1);
1725
1726                 for (i = 0; i < pAcl->AceCount; i++)
1727                 {
1728                     paclsize->AclBytesInUse += ace->AceSize;
1729                     ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1730                 }
1731
1732                 if (pAcl->AclSize < paclsize->AclBytesInUse)
1733                 {
1734                     WARN("Acl has %d bytes free\n", paclsize->AclBytesFree);
1735                     paclsize->AclBytesFree = 0;
1736                     paclsize->AclBytesInUse = pAcl->AclSize;
1737                 }
1738                 else
1739                     paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1740             }
1741
1742             break;
1743         }
1744
1745         default:
1746             WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1747             status = STATUS_INVALID_PARAMETER;
1748     }
1749
1750     return status;
1751 }