wined3d: Keep track of what fixed function texture stages are in use.
[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 RtlAddAuditAccessAce( 
1217     IN OUT PACL pAcl, 
1218     IN DWORD dwAceRevision, 
1219     IN DWORD dwAccessMask, 
1220     IN PSID pSid, 
1221     IN BOOL bAuditSuccess, 
1222     IN BOOL bAuditFailure) 
1223
1224     DWORD dwAceFlags = 0;
1225
1226     TRACE("(%p,%d,%d,%p,%u,%u)\n",pAcl,dwAceRevision,dwAccessMask,
1227           pSid,bAuditSuccess,bAuditFailure);
1228
1229     if (bAuditSuccess)
1230         dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1231
1232     if (bAuditFailure)
1233         dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1234
1235     return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1236                           dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1237
1238  
1239 /******************************************************************************
1240  *  RtlValidAcl         [NTDLL.@]
1241  */
1242 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1243 {
1244         BOOLEAN ret;
1245         TRACE("(%p)\n", pAcl);
1246
1247         __TRY
1248         {
1249                 PACE_HEADER     ace;
1250                 int             i;
1251
1252                 if (pAcl->AclRevision != ACL_REVISION)
1253                     ret = FALSE;
1254                 else
1255                 {
1256                     ace = (PACE_HEADER)(pAcl+1);
1257                     ret = TRUE;
1258                     for (i=0;i<=pAcl->AceCount;i++)
1259                     {
1260                         if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1261                         {
1262                             ret = FALSE;
1263                             break;
1264                         }
1265                         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1266                     }
1267                 }
1268         }
1269         __EXCEPT_PAGE_FAULT
1270         {
1271                 WARN("(%p): invalid pointer!\n", pAcl);
1272                 return 0;
1273         }
1274         __ENDTRY
1275         return ret;
1276 }
1277
1278 /******************************************************************************
1279  *  RtlGetAce           [NTDLL.@]
1280  */
1281 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1282 {
1283         PACE_HEADER ace;
1284
1285         TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1286
1287         if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1288                 return STATUS_INVALID_PARAMETER;
1289
1290         ace = (PACE_HEADER)(pAcl + 1);
1291         for (;dwAceIndex;dwAceIndex--)
1292                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1293
1294         *pAce = (LPVOID) ace;
1295
1296         return STATUS_SUCCESS;
1297 }
1298
1299 /*
1300  *      misc
1301  */
1302
1303 /******************************************************************************
1304  *  RtlAdjustPrivilege          [NTDLL.@]
1305  *
1306  * Enables or disables a privilege from the calling thread or process.
1307  *
1308  * PARAMS
1309  *  Privilege     [I] Privilege index to change.
1310  *  Enable        [I] If TRUE, then enable the privilege otherwise disable.
1311  *  CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1312  *  Enabled       [O] Whether privilege was previously enabled or disabled.
1313  *
1314  * RETURNS
1315  *  Success: STATUS_SUCCESS.
1316  *  Failure: NTSTATUS code.
1317  *
1318  * SEE ALSO
1319  *  NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1320  *
1321  */
1322 NTSTATUS WINAPI
1323 RtlAdjustPrivilege(ULONG Privilege,
1324                    BOOLEAN Enable,
1325                    BOOLEAN CurrentThread,
1326                    PBOOLEAN Enabled)
1327 {
1328     TOKEN_PRIVILEGES NewState;
1329     TOKEN_PRIVILEGES OldState;
1330     ULONG ReturnLength;
1331     HANDLE TokenHandle;
1332     NTSTATUS Status;
1333
1334     TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1335         CurrentThread ? "TRUE" : "FALSE", Enabled);
1336
1337     if (CurrentThread)
1338     {
1339         Status = NtOpenThreadToken(GetCurrentThread(),
1340                                    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1341                                    FALSE,
1342                                    &TokenHandle);
1343     }
1344     else
1345     {
1346         Status = NtOpenProcessToken(GetCurrentProcess(),
1347                                     TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1348                                     &TokenHandle);
1349     }
1350
1351     if (!NT_SUCCESS(Status))
1352     {
1353         WARN("Retrieving token handle failed (Status %x)\n", Status);
1354         return Status;
1355     }
1356
1357     OldState.PrivilegeCount = 1;
1358
1359     NewState.PrivilegeCount = 1;
1360     NewState.Privileges[0].Luid.LowPart = Privilege;
1361     NewState.Privileges[0].Luid.HighPart = 0;
1362     NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1363
1364     Status = NtAdjustPrivilegesToken(TokenHandle,
1365                                      FALSE,
1366                                      &NewState,
1367                                      sizeof(TOKEN_PRIVILEGES),
1368                                      &OldState,
1369                                      &ReturnLength);
1370     NtClose (TokenHandle);
1371     if (Status == STATUS_NOT_ALL_ASSIGNED)
1372     {
1373         TRACE("Failed to assign all privileges\n");
1374         return STATUS_PRIVILEGE_NOT_HELD;
1375     }
1376     if (!NT_SUCCESS(Status))
1377     {
1378         WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1379         return Status;
1380     }
1381
1382     if (OldState.PrivilegeCount == 0)
1383         *Enabled = Enable;
1384     else
1385         *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1386
1387     return STATUS_SUCCESS;
1388 }
1389
1390 /******************************************************************************
1391  *  RtlImpersonateSelf          [NTDLL.@]
1392  *
1393  * Makes an impersonation token that represents the process user and assigns
1394  * to the current thread.
1395  *
1396  * PARAMS
1397  *  ImpersonationLevel [I] Level at which to impersonate.
1398  *
1399  * RETURNS
1400  *  Success: STATUS_SUCCESS.
1401  *  Failure: NTSTATUS code.
1402  */
1403 NTSTATUS WINAPI
1404 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1405 {
1406     NTSTATUS Status;
1407     OBJECT_ATTRIBUTES ObjectAttributes;
1408     HANDLE ProcessToken;
1409     HANDLE ImpersonationToken;
1410
1411     TRACE("(%08x)\n", ImpersonationLevel);
1412
1413     Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1414                                  &ProcessToken);
1415     if (Status != STATUS_SUCCESS)
1416         return Status;
1417
1418     InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1419
1420     Status = NtDuplicateToken( ProcessToken,
1421                                TOKEN_IMPERSONATE,
1422                                &ObjectAttributes,
1423                                ImpersonationLevel,
1424                                TokenImpersonation,
1425                                &ImpersonationToken );
1426     if (Status != STATUS_SUCCESS)
1427     {
1428         NtClose( ProcessToken );
1429         return Status;
1430     }
1431
1432     Status = NtSetInformationThread( GetCurrentThread(),
1433                                      ThreadImpersonationToken,
1434                                      &ImpersonationToken,
1435                                      sizeof(ImpersonationToken) );
1436
1437     NtClose( ImpersonationToken );
1438     NtClose( ProcessToken );
1439
1440     return Status;
1441 }
1442
1443 /******************************************************************************
1444  *  NtAccessCheck               [NTDLL.@]
1445  *  ZwAccessCheck               [NTDLL.@]
1446  *
1447  * Checks that a user represented by a token is allowed to access an object
1448  * represented by a security descriptor.
1449  *
1450  * PARAMS
1451  *  SecurityDescriptor [I] The security descriptor of the object to check.
1452  *  ClientToken        [I] Token of the user accessing the object.
1453  *  DesiredAccess      [I] The desired access to the object.
1454  *  GenericMapping     [I] Mapping used to transform access rights in the SD to their specific forms.
1455  *  PrivilegeSet       [I/O] Privileges used during the access check.
1456  *  ReturnLength       [O] Number of bytes stored into PrivilegeSet.
1457  *  GrantedAccess      [O] The actual access rights granted.
1458  *  AccessStatus       [O] The status of the access check.
1459  *
1460  * RETURNS
1461  *  NTSTATUS code.
1462  *
1463  * NOTES
1464  *  DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1465  *  the maximum access rights allowed by the SD and returns them in
1466  *  GrantedAccess.
1467  *  The SecurityDescriptor must have a valid owner and groups present,
1468  *  otherwise the function will fail.
1469  */
1470 NTSTATUS WINAPI
1471 NtAccessCheck(
1472     PSECURITY_DESCRIPTOR SecurityDescriptor,
1473     HANDLE ClientToken,
1474     ACCESS_MASK DesiredAccess,
1475     PGENERIC_MAPPING GenericMapping,
1476     PPRIVILEGE_SET PrivilegeSet,
1477     PULONG ReturnLength,
1478     PULONG GrantedAccess,
1479     NTSTATUS *AccessStatus)
1480 {
1481     NTSTATUS status;
1482
1483     TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1484         SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1485         PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1486
1487     SERVER_START_REQ( access_check )
1488     {
1489         struct security_descriptor sd;
1490         PSID owner;
1491         PSID group;
1492         PACL sacl;
1493         PACL dacl;
1494         BOOLEAN defaulted, present;
1495         DWORD revision;
1496         SECURITY_DESCRIPTOR_CONTROL control;
1497
1498         req->handle = ClientToken;
1499         req->desired_access = DesiredAccess;
1500         req->mapping_read = GenericMapping->GenericRead;
1501         req->mapping_write = GenericMapping->GenericWrite;
1502         req->mapping_execute = GenericMapping->GenericExecute;
1503         req->mapping_all = GenericMapping->GenericAll;
1504
1505         /* marshal security descriptor */
1506         RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1507         sd.control = control & ~SE_SELF_RELATIVE;
1508         RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1509         sd.owner_len = RtlLengthSid( owner );
1510         RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1511         sd.group_len = RtlLengthSid( group );
1512         RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1513         sd.sacl_len = (present ? sacl->AclSize : 0);
1514         RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1515         sd.dacl_len = (present ? dacl->AclSize : 0);
1516
1517         wine_server_add_data( req, &sd, sizeof(sd) );
1518         wine_server_add_data( req, owner, sd.owner_len );
1519         wine_server_add_data( req, group, sd.group_len );
1520         wine_server_add_data( req, sacl, sd.sacl_len );
1521         wine_server_add_data( req, dacl, sd.dacl_len );
1522
1523         wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1524
1525         status = wine_server_call( req );
1526
1527         *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1528         PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1529
1530         if (status == STATUS_SUCCESS)
1531         {
1532             *AccessStatus = reply->access_status;
1533             *GrantedAccess = reply->access_granted;
1534         }
1535     }
1536     SERVER_END_REQ;
1537
1538     return status;
1539 }
1540
1541 /******************************************************************************
1542  *  NtSetSecurityObject         [NTDLL.@]
1543  *  ZwSetSecurityObject         [NTDLL.@]
1544  *
1545  * Sets specified parts of the object's security descriptor.
1546  *
1547  * PARAMS
1548  *  Handle              [I] Handle to the object to change security descriptor of.
1549  *  SecurityInformation [I] Specifies which parts of the security descriptor to set.
1550  *  SecurityDescriptor  [I] New parts of a security descriptor for the object.
1551  *
1552  * RETURNS
1553  *  NTSTATUS code.
1554  *
1555  */
1556 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1557         SECURITY_INFORMATION SecurityInformation,
1558         PSECURITY_DESCRIPTOR SecurityDescriptor)
1559 {
1560     NTSTATUS status;
1561     struct security_descriptor sd;
1562     PACL dacl = NULL, sacl = NULL;
1563     PSID owner = NULL, group = NULL;
1564     BOOLEAN defaulted, present;
1565     DWORD revision;
1566     SECURITY_DESCRIPTOR_CONTROL control;
1567
1568     TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1569
1570     if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1571
1572     memset( &sd, 0, sizeof(sd) );
1573     status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1574     if (status != STATUS_SUCCESS) return status;
1575     sd.control = control & ~SE_SELF_RELATIVE;
1576
1577     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1578     {
1579         status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1580         if (status != STATUS_SUCCESS) return status;
1581         if (!(sd.owner_len = RtlLengthSid( owner )))
1582             return STATUS_INVALID_SECURITY_DESCR;
1583     }
1584
1585     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1586     {
1587         status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1588         if (status != STATUS_SUCCESS) return status;
1589         if (!(sd.group_len = RtlLengthSid( group )))
1590             return STATUS_INVALID_SECURITY_DESCR;
1591     }
1592
1593     if (SecurityInformation & SACL_SECURITY_INFORMATION)
1594     {
1595         status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1596         if (status != STATUS_SUCCESS) return status;
1597         sd.sacl_len = (sacl && present) ? sacl->AclSize : 0;
1598         sd.control |= SE_SACL_PRESENT;
1599     }
1600
1601     if (SecurityInformation & DACL_SECURITY_INFORMATION)
1602     {
1603         status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1604         if (status != STATUS_SUCCESS) return status;
1605         sd.dacl_len = (dacl && present) ? dacl->AclSize : 0;
1606         sd.control |= SE_DACL_PRESENT;
1607     }
1608
1609     SERVER_START_REQ( set_security_object )
1610     {
1611         req->handle = Handle;
1612         req->security_info = SecurityInformation;
1613
1614         wine_server_add_data( req, &sd, sizeof(sd) );
1615         wine_server_add_data( req, owner, sd.owner_len );
1616         wine_server_add_data( req, group, sd.group_len );
1617         wine_server_add_data( req, sacl, sd.sacl_len );
1618         wine_server_add_data( req, dacl, sd.dacl_len );
1619         status = wine_server_call( req );
1620     }
1621     SERVER_END_REQ;
1622
1623     return status;
1624 }
1625
1626 /******************************************************************************
1627  * RtlConvertSidToUnicodeString (NTDLL.@)
1628  *
1629  * The returned SID is used to access the USER registry hive usually
1630  *
1631  * the native function returns something like
1632  * "S-1-5-21-0000000000-000000000-0000000000-500";
1633  */
1634 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1635        PUNICODE_STRING String,
1636        PSID pSid,
1637        BOOLEAN AllocateString)
1638 {
1639     static const WCHAR formatW[] = {'-','%','u',0};
1640     WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1641     WCHAR *p = buffer;
1642     const SID *sid = (const SID *)pSid;
1643     DWORD i, len;
1644
1645     *p++ = 'S';
1646     p += sprintfW( p, formatW, sid->Revision );
1647     p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1648                                                    sid->IdentifierAuthority.Value[4] ),
1649                                          MAKEWORD( sid->IdentifierAuthority.Value[3],
1650                                                    sid->IdentifierAuthority.Value[2] )));
1651     for (i = 0; i < sid->SubAuthorityCount; i++)
1652         p += sprintfW( p, formatW, sid->SubAuthority[i] );
1653
1654     len = (p + 1 - buffer) * sizeof(WCHAR);
1655
1656     String->Length = len - sizeof(WCHAR);
1657     if (AllocateString)
1658     {
1659         String->MaximumLength = len;
1660         if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1661             return STATUS_NO_MEMORY;
1662     }
1663     else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1664
1665     memcpy( String->Buffer, buffer, len );
1666     return STATUS_SUCCESS;
1667 }
1668
1669 /******************************************************************************
1670  * RtlQueryInformationAcl (NTDLL.@)
1671  */
1672 NTSTATUS WINAPI RtlQueryInformationAcl(
1673     PACL pAcl,
1674     LPVOID pAclInformation,
1675     DWORD nAclInformationLength,
1676     ACL_INFORMATION_CLASS dwAclInformationClass)
1677 {
1678     NTSTATUS status = STATUS_SUCCESS;
1679
1680     TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n", 
1681         pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1682
1683     switch (dwAclInformationClass)
1684     {
1685         case AclRevisionInformation:
1686         {
1687             PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1688
1689             if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1690                 status = STATUS_INVALID_PARAMETER;
1691             else
1692                 paclrev->AclRevision = pAcl->AclRevision;
1693
1694             break;
1695         }
1696
1697         case AclSizeInformation:
1698         {
1699             PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1700
1701             if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1702                 status = STATUS_INVALID_PARAMETER;
1703             else
1704             {
1705                 INT i;
1706                 PACE_HEADER ace;
1707
1708                 paclsize->AceCount = pAcl->AceCount;
1709
1710                 paclsize->AclBytesInUse = 0;
1711                 ace = (PACE_HEADER) (pAcl + 1);
1712
1713                 for (i = 0; i < pAcl->AceCount; i++)
1714                 {
1715                     paclsize->AclBytesInUse += ace->AceSize;
1716                     ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1717                 }
1718
1719                 if (pAcl->AclSize < paclsize->AclBytesInUse)
1720                 {
1721                     WARN("Acl has %d bytes free\n", paclsize->AclBytesFree);
1722                     paclsize->AclBytesFree = 0;
1723                     paclsize->AclBytesInUse = pAcl->AclSize;
1724                 }
1725                 else
1726                     paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1727             }
1728
1729             break;
1730         }
1731
1732         default:
1733             WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1734             status = STATUS_INVALID_PARAMETER;
1735     }
1736
1737     return status;
1738 }