Don't open device if already open.
[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),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
845
846     if ( !lpsd  || !pControl || !lpdwRevision )
847             return STATUS_INVALID_PARAMETER;
848
849     *lpdwRevision = lpsd->Revision;
850     *pControl = lpsd->Control;
851
852     return STATUS_SUCCESS;
853 }
854
855
856 /**************************************************************************
857  *                 RtlAbsoluteToSelfRelativeSD [NTDLL.@]
858  */
859 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
860     PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
861     PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
862     PULONG BufferLength)
863 {
864     FIXME("%p %p %p\n", AbsoluteSecurityDescriptor,
865           SelfRelativeSecurityDescriptor, BufferLength);
866     return STATUS_NOT_IMPLEMENTED;
867 }
868
869
870 /*
871  *      access control list's
872  */
873
874 /**************************************************************************
875  *                 RtlCreateAcl                         [NTDLL.@]
876  *
877  * NOTES
878  *    This should return NTSTATUS
879  */
880 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
881 {
882         TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
883
884         if (rev!=ACL_REVISION)
885                 return STATUS_INVALID_PARAMETER;
886         if (size<sizeof(ACL))
887                 return STATUS_BUFFER_TOO_SMALL;
888         if (size>0xFFFF)
889                 return STATUS_INVALID_PARAMETER;
890
891         memset(acl,'\0',sizeof(ACL));
892         acl->AclRevision        = rev;
893         acl->AclSize            = size;
894         acl->AceCount           = 0;
895         return STATUS_SUCCESS;
896 }
897
898 /**************************************************************************
899  *                 RtlFirstFreeAce                      [NTDLL.@]
900  * looks for the AceCount+1 ACE, and if it is still within the alloced
901  * ACL, return a pointer to it
902  */
903 BOOLEAN WINAPI RtlFirstFreeAce(
904         PACL acl,
905         PACE_HEADER *x)
906 {
907         PACE_HEADER     ace;
908         int             i;
909
910         *x = 0;
911         ace = (PACE_HEADER)(acl+1);
912         for (i=0;i<acl->AceCount;i++) {
913                 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
914                         return 0;
915                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
916         }
917         if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
918                 return 0;
919         *x = ace;
920         return 1;
921 }
922
923 /**************************************************************************
924  *                 RtlAddAce                            [NTDLL.@]
925  */
926 NTSTATUS WINAPI RtlAddAce(
927         PACL acl,
928         DWORD rev,
929         DWORD xnrofaces,
930         PACE_HEADER acestart,
931         DWORD acelen)
932 {
933         PACE_HEADER     ace,targetace;
934         int             nrofaces;
935
936         if (acl->AclRevision != ACL_REVISION)
937                 return STATUS_INVALID_PARAMETER;
938         if (!RtlFirstFreeAce(acl,&targetace))
939                 return STATUS_INVALID_PARAMETER;
940         nrofaces=0;ace=acestart;
941         while (((DWORD)ace-(DWORD)acestart)<acelen) {
942                 nrofaces++;
943                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
944         }
945         if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
946                 return STATUS_INVALID_PARAMETER;
947         memcpy((LPBYTE)targetace,acestart,acelen);
948         acl->AceCount+=nrofaces;
949         return STATUS_SUCCESS;
950 }
951
952 /**************************************************************************
953  *                 RtlDeleteAce                         [NTDLL.@]
954  */
955 NTSTATUS  WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
956 {
957         NTSTATUS status;
958         PACE_HEADER pAce;
959
960         status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
961
962         if (STATUS_SUCCESS == status)
963         {
964                 PACE_HEADER pcAce;
965                 DWORD len = 0;
966
967                 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
968                 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
969                 {
970                         len += pcAce->AceSize;
971                         pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
972                 }
973
974                 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
975                 pAcl->AceCount--;
976         }
977
978         TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl, dwAceIndex, status);
979
980         return status;
981 }
982
983 /******************************************************************************
984  *  RtlAddAccessAllowedAce              [NTDLL.@]
985  */
986 NTSTATUS WINAPI RtlAddAccessAllowedAce(
987         IN OUT PACL pAcl,
988         IN DWORD dwAceRevision,
989         IN DWORD AccessMask,
990         IN PSID pSid)
991 {
992         return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
993 }
994  
995 /******************************************************************************
996  *  RtlAddAccessAllowedAceEx            [NTDLL.@]
997  */
998 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
999         IN OUT PACL pAcl,
1000         IN DWORD dwAceRevision,
1001         IN DWORD AceFlags,
1002         IN DWORD AccessMask,
1003         IN PSID pSid)
1004 {
1005         DWORD dwLengthSid;
1006         ACCESS_ALLOWED_ACE * pAaAce;
1007         DWORD dwSpaceLeft;
1008
1009         TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1010                 pAcl, dwAceRevision, AccessMask, pSid);
1011
1012         if (!RtlValidSid(pSid))
1013                 return STATUS_INVALID_SID;
1014         if (!RtlValidAcl(pAcl))
1015                 return STATUS_INVALID_ACL;
1016
1017         dwLengthSid = RtlLengthSid(pSid);
1018         if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
1019                 return STATUS_INVALID_ACL;
1020
1021         if (!pAaAce)
1022                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1023
1024         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
1025         if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
1026                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1027
1028         pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
1029         pAaAce->Header.AceFlags = AceFlags;
1030         pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
1031         pAaAce->Mask = AccessMask;
1032         pAcl->AceCount++;
1033         RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
1034         return STATUS_SUCCESS;
1035 }
1036
1037 /******************************************************************************
1038  *  RtlAddAccessDeniedAce               [NTDLL.@]
1039  */
1040 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1041         IN OUT PACL pAcl,
1042         IN DWORD dwAceRevision,
1043         IN DWORD AccessMask,
1044         IN PSID pSid)
1045 {
1046         return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1047 }
1048
1049 /******************************************************************************
1050  *  RtlAddAccessDeniedAceEx             [NTDLL.@]
1051  */
1052 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1053         IN OUT PACL pAcl,
1054         IN DWORD dwAceRevision,
1055         IN DWORD AceFlags,
1056         IN DWORD AccessMask,
1057         IN PSID pSid)
1058 {
1059         DWORD dwLengthSid;
1060         DWORD dwSpaceLeft;
1061         ACCESS_DENIED_ACE * pAdAce;
1062
1063         TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1064                 pAcl, dwAceRevision, AccessMask, pSid);
1065
1066         if (!RtlValidSid(pSid))
1067                 return STATUS_INVALID_SID;
1068         if (!RtlValidAcl(pAcl))
1069                 return STATUS_INVALID_ACL;
1070
1071         dwLengthSid = RtlLengthSid(pSid);
1072         if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
1073                 return STATUS_INVALID_ACL;
1074
1075         if (!pAdAce)
1076                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1077
1078         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1079         if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1080                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1081
1082         pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1083         pAdAce->Header.AceFlags = AceFlags;
1084         pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1085         pAdAce->Mask = AccessMask;
1086         pAcl->AceCount++;
1087         RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1088         return STATUS_SUCCESS;
1089 }
1090
1091 /******************************************************************************
1092  *  RtlValidAcl         [NTDLL.@]
1093  */
1094 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1095 {
1096         BOOLEAN ret;
1097         TRACE("(%p)\n", pAcl);
1098
1099         __TRY
1100         {
1101                 PACE_HEADER     ace;
1102                 int             i;
1103
1104                 if (pAcl->AclRevision != ACL_REVISION)
1105                     ret = FALSE;
1106                 else
1107                 {
1108                     ace = (PACE_HEADER)(pAcl+1);
1109                     ret = TRUE;
1110                     for (i=0;i<=pAcl->AceCount;i++)
1111                     {
1112                         if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1113                         {
1114                             ret = FALSE;
1115                             break;
1116                         }
1117                         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1118                     }
1119                 }
1120         }
1121         __EXCEPT(page_fault)
1122         {
1123                 WARN("(%p): invalid pointer!\n", pAcl);
1124                 return 0;
1125         }
1126         __ENDTRY
1127         return ret;
1128 }
1129
1130 /******************************************************************************
1131  *  RtlGetAce           [NTDLL.@]
1132  */
1133 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1134 {
1135         PACE_HEADER ace;
1136
1137         TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1138
1139         if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1140                 return STATUS_INVALID_PARAMETER;
1141
1142         ace = (PACE_HEADER)(pAcl + 1);
1143         for (;dwAceIndex;dwAceIndex--)
1144                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1145
1146         *pAce = (LPVOID) ace;
1147
1148         return STATUS_SUCCESS;
1149 }
1150
1151 /*
1152  *      misc
1153  */
1154
1155 /******************************************************************************
1156  *  RtlAdjustPrivilege          [NTDLL.@]
1157  */
1158 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
1159 {
1160         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
1161         return 0;
1162 }
1163
1164 /******************************************************************************
1165  *  RtlImpersonateSelf          [NTDLL.@]
1166  */
1167 BOOL WINAPI
1168 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1169 {
1170         FIXME("(%08x), stub\n", ImpersonationLevel);
1171         return TRUE;
1172 }
1173
1174 /******************************************************************************
1175  *  NtAccessCheck               [NTDLL.@]
1176  *  ZwAccessCheck               [NTDLL.@]
1177  *
1178  * Checks that a user represented by a token is allowed to access an object
1179  * represented by a security descriptor.
1180  *
1181  * PARAMS
1182  *  SecurityDescriptor [I] The security descriptor of the object to check.
1183  *  ClientToken        [I] Token of the user accessing the object.
1184  *  DesiredAccess      [I] The desired access to the object.
1185  *  GenericMapping     [I] Mapping used to transform access rights in the SD to their specific forms.
1186  *  PrivilegeSet       [I/O] Privileges used during the access check.
1187  *  ReturnLength       [O] Number of bytes stored into PrivilegeSet.
1188  *  GrantedAccess      [O] The actual access rights granted.
1189  *  AccessStatus       [O] The status of the access check.
1190  *
1191  * RETURNS
1192  *  NTSTATUS code.
1193  *
1194  * NOTES
1195  *  DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1196  *  the maximum access rights allowed by the SD and returns them in
1197  *  GrantedAccess.
1198  *  The SecurityDescriptor must have a valid owner and groups present,
1199  *  otherwise the function will fail.
1200  */
1201 NTSTATUS WINAPI
1202 NtAccessCheck(
1203     PSECURITY_DESCRIPTOR SecurityDescriptor,
1204     HANDLE ClientToken,
1205     ACCESS_MASK DesiredAccess,
1206     PGENERIC_MAPPING GenericMapping,
1207     PPRIVILEGE_SET PrivilegeSet,
1208     PULONG ReturnLength,
1209     PULONG GrantedAccess,
1210     NTSTATUS *AccessStatus)
1211 {
1212     NTSTATUS status;
1213
1214     TRACE("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1215         SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1216         PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1217
1218     SERVER_START_REQ( access_check )
1219     {
1220         struct security_descriptor sd;
1221         PSID owner;
1222         PSID group;
1223         PACL sacl;
1224         PACL dacl;
1225         BOOLEAN defaulted, present;
1226         DWORD revision;
1227         SECURITY_DESCRIPTOR_CONTROL control;
1228
1229         req->handle = ClientToken;
1230         req->desired_access = DesiredAccess;
1231         req->mapping_read = GenericMapping->GenericRead;
1232         req->mapping_write = GenericMapping->GenericWrite;
1233         req->mapping_execute = GenericMapping->GenericExecute;
1234         req->mapping_all = GenericMapping->GenericAll;
1235
1236         /* marshal security descriptor */
1237         RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1238         sd.control = control & ~SE_SELF_RELATIVE;
1239         RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1240         sd.owner_len = RtlLengthSid( owner );
1241         RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1242         sd.group_len = RtlLengthSid( group );
1243         RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1244         sd.sacl_len = (present ? sacl->AclSize : 0);
1245         RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1246         sd.dacl_len = (present ? dacl->AclSize : 0);
1247
1248         wine_server_add_data( req, &sd, sizeof(sd) );
1249         wine_server_add_data( req, owner, sd.owner_len );
1250         wine_server_add_data( req, group, sd.group_len );
1251         wine_server_add_data( req, sacl, sd.sacl_len );
1252         wine_server_add_data( req, dacl, sd.dacl_len );
1253
1254         wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1255
1256         status = wine_server_call( req );
1257
1258         *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1259         PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1260
1261         if (status == STATUS_SUCCESS)
1262             *AccessStatus = reply->access_status;
1263         *GrantedAccess = reply->access_granted;
1264     }
1265     SERVER_END_REQ;
1266
1267     return status;
1268 }
1269
1270 /******************************************************************************
1271  *  NtSetSecurityObject         [NTDLL.@]
1272  */
1273 NTSTATUS WINAPI
1274 NtSetSecurityObject(
1275         IN HANDLE Handle,
1276         IN SECURITY_INFORMATION SecurityInformation,
1277         IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1278 {
1279         FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1280         return STATUS_SUCCESS;
1281 }
1282
1283 /******************************************************************************
1284  * RtlConvertSidToUnicodeString (NTDLL.@)
1285  *
1286  * The returned SID is used to access the USER registry hive usually
1287  *
1288  * the native function returns something like
1289  * "S-1-5-21-0000000000-000000000-0000000000-500";
1290  */
1291 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1292        PUNICODE_STRING String,
1293        PSID Sid,
1294        BOOLEAN AllocateString)
1295 {
1296     const char *user = wine_get_user_name();
1297     int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 ) * sizeof(WCHAR);
1298
1299     FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1300
1301     String->Length = len - sizeof(WCHAR);
1302     if (AllocateString)
1303     {
1304         String->MaximumLength = len;
1305         if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1306             return STATUS_NO_MEMORY;
1307     }
1308     else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1309
1310     ntdll_umbstowcs( 0, user, strlen(user)+1, String->Buffer, len/sizeof(WCHAR) );
1311     return STATUS_SUCCESS;
1312 }
1313
1314 /******************************************************************************
1315  * RtlQueryInformationAcl (NTDLL.@)
1316  */
1317 NTSTATUS WINAPI RtlQueryInformationAcl(
1318     PACL pAcl,
1319     LPVOID pAclInformation,
1320     DWORD nAclInformationLength,
1321     ACL_INFORMATION_CLASS dwAclInformationClass)
1322 {
1323     NTSTATUS status = STATUS_SUCCESS;
1324
1325     TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n", 
1326         pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1327
1328     switch (dwAclInformationClass)
1329     {
1330         case AclRevisionInformation:
1331         {
1332             PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1333
1334             if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1335                 status = STATUS_INVALID_PARAMETER;
1336             else
1337                 paclrev->AclRevision = pAcl->AclRevision;
1338
1339             break;
1340         }
1341
1342         case AclSizeInformation:
1343         {
1344             PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1345
1346             if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1347                 status = STATUS_INVALID_PARAMETER;
1348             else
1349             {
1350                 INT i;
1351                 PACE_HEADER ace;
1352
1353                 paclsize->AceCount = pAcl->AceCount;
1354
1355                 paclsize->AclBytesInUse = 0;
1356                 ace = (PACE_HEADER) (pAcl + 1);
1357
1358                 for (i = 0; i < pAcl->AceCount; i++)
1359                 {
1360                     paclsize->AclBytesInUse += ace->AceSize;
1361                     ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1362                 }
1363
1364                 if (pAcl->AclSize < paclsize->AclBytesInUse)
1365                 {
1366                     WARN("Acl has %ld bytes free\n", paclsize->AclBytesFree);
1367                     paclsize->AclBytesFree = 0;
1368                     paclsize->AclBytesInUse = pAcl->AclSize;
1369                 }
1370                 else
1371                     paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1372             }
1373
1374             break;
1375         }
1376
1377         default:
1378             WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1379             status = STATUS_INVALID_PARAMETER;
1380     }
1381
1382     return status;
1383 }