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