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