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