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