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