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