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