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