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