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