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