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