Fix segmentation fault caused by incorrect referencing of client audio
[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 /**************************************************************************
836  *                 RtlAbsoluteToSelfRelativeSD [NTDLL.@]
837  */
838 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
839     PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
840     PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
841     PULONG BufferLength)
842 {
843     FIXME("%p %p %p\n", AbsoluteSecurityDescriptor,
844           SelfRelativeSecurityDescriptor, BufferLength);
845     return STATUS_NOT_IMPLEMENTED;
846 }
847
848
849 /*
850  *      access control list's
851  */
852
853 /**************************************************************************
854  *                 RtlCreateAcl                         [NTDLL.@]
855  *
856  * NOTES
857  *    This should return NTSTATUS
858  */
859 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
860 {
861         TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
862
863         if (rev!=ACL_REVISION)
864                 return STATUS_INVALID_PARAMETER;
865         if (size<sizeof(ACL))
866                 return STATUS_BUFFER_TOO_SMALL;
867         if (size>0xFFFF)
868                 return STATUS_INVALID_PARAMETER;
869
870         memset(acl,'\0',sizeof(ACL));
871         acl->AclRevision        = rev;
872         acl->AclSize            = size;
873         acl->AceCount           = 0;
874         return STATUS_SUCCESS;
875 }
876
877 /**************************************************************************
878  *                 RtlFirstFreeAce                      [NTDLL.@]
879  * looks for the AceCount+1 ACE, and if it is still within the alloced
880  * ACL, return a pointer to it
881  */
882 BOOLEAN WINAPI RtlFirstFreeAce(
883         PACL acl,
884         PACE_HEADER *x)
885 {
886         PACE_HEADER     ace;
887         int             i;
888
889         *x = 0;
890         ace = (PACE_HEADER)(acl+1);
891         for (i=0;i<acl->AceCount;i++) {
892                 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
893                         return 0;
894                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
895         }
896         if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
897                 return 0;
898         *x = ace;
899         return 1;
900 }
901
902 /**************************************************************************
903  *                 RtlAddAce                            [NTDLL.@]
904  */
905 NTSTATUS WINAPI RtlAddAce(
906         PACL acl,
907         DWORD rev,
908         DWORD xnrofaces,
909         PACE_HEADER acestart,
910         DWORD acelen)
911 {
912         PACE_HEADER     ace,targetace;
913         int             nrofaces;
914
915         if (acl->AclRevision != ACL_REVISION)
916                 return STATUS_INVALID_PARAMETER;
917         if (!RtlFirstFreeAce(acl,&targetace))
918                 return STATUS_INVALID_PARAMETER;
919         nrofaces=0;ace=acestart;
920         while (((DWORD)ace-(DWORD)acestart)<acelen) {
921                 nrofaces++;
922                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
923         }
924         if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
925                 return STATUS_INVALID_PARAMETER;
926         memcpy((LPBYTE)targetace,acestart,acelen);
927         acl->AceCount+=nrofaces;
928         return STATUS_SUCCESS;
929 }
930
931 /**************************************************************************
932  *                 RtlDeleteAce                         [NTDLL.@]
933  */
934 NTSTATUS  WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
935 {
936         NTSTATUS status;
937         PACE_HEADER pAce;
938
939         status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
940
941         if (STATUS_SUCCESS == status)
942         {
943                 PACE_HEADER pcAce;
944                 DWORD len = 0;
945
946                 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
947                 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
948                 {
949                         len += pcAce->AceSize;
950                         pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
951                 }
952
953                 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
954                 pAcl->AceCount--;
955         }
956
957         TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl, dwAceIndex, status);
958
959         return status;
960 }
961
962 /******************************************************************************
963  *  RtlAddAccessAllowedAce              [NTDLL.@]
964  */
965 NTSTATUS WINAPI RtlAddAccessAllowedAce(
966         IN OUT PACL pAcl,
967         IN DWORD dwAceRevision,
968         IN DWORD AccessMask,
969         IN PSID pSid)
970 {
971         return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
972 }
973  
974 /******************************************************************************
975  *  RtlAddAccessAllowedAceEx            [NTDLL.@]
976  */
977 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
978         IN OUT PACL pAcl,
979         IN DWORD dwAceRevision,
980         IN DWORD AceFlags,
981         IN DWORD AccessMask,
982         IN PSID pSid)
983 {
984         DWORD dwLengthSid;
985         ACCESS_ALLOWED_ACE * pAaAce;
986         DWORD dwSpaceLeft;
987
988         TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
989                 pAcl, dwAceRevision, AccessMask, pSid);
990
991         if (!RtlValidSid(pSid))
992                 return STATUS_INVALID_SID;
993         if (!RtlValidAcl(pAcl))
994                 return STATUS_INVALID_ACL;
995
996         dwLengthSid = RtlLengthSid(pSid);
997         if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
998                 return STATUS_INVALID_ACL;
999
1000         if (!pAaAce)
1001                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1002
1003         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
1004         if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
1005                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1006
1007         pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
1008         pAaAce->Header.AceFlags = AceFlags;
1009         pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
1010         pAaAce->Mask = AccessMask;
1011         pAcl->AceCount++;
1012         RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
1013         return STATUS_SUCCESS;
1014 }
1015
1016 /******************************************************************************
1017  *  RtlAddAccessDeniedAce               [NTDLL.@]
1018  */
1019 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1020         IN OUT PACL pAcl,
1021         IN DWORD dwAceRevision,
1022         IN DWORD AccessMask,
1023         IN PSID pSid)
1024 {
1025         return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1026 }
1027
1028 /******************************************************************************
1029  *  RtlAddAccessDeniedAceEx             [NTDLL.@]
1030  */
1031 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1032         IN OUT PACL pAcl,
1033         IN DWORD dwAceRevision,
1034         IN DWORD AceFlags,
1035         IN DWORD AccessMask,
1036         IN PSID pSid)
1037 {
1038         DWORD dwLengthSid;
1039         DWORD dwSpaceLeft;
1040         ACCESS_DENIED_ACE * pAdAce;
1041
1042         TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1043                 pAcl, dwAceRevision, AccessMask, pSid);
1044
1045         if (!RtlValidSid(pSid))
1046                 return STATUS_INVALID_SID;
1047         if (!RtlValidAcl(pAcl))
1048                 return STATUS_INVALID_ACL;
1049
1050         dwLengthSid = RtlLengthSid(pSid);
1051         if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
1052                 return STATUS_INVALID_ACL;
1053
1054         if (!pAdAce)
1055                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1056
1057         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1058         if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1059                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1060
1061         pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1062         pAdAce->Header.AceFlags = AceFlags;
1063         pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1064         pAdAce->Mask = AccessMask;
1065         pAcl->AceCount++;
1066         RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1067         return STATUS_SUCCESS;
1068 }
1069
1070 /******************************************************************************
1071  *  RtlValidAcl         [NTDLL.@]
1072  */
1073 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1074 {
1075         BOOLEAN ret;
1076         TRACE("(%p)\n", pAcl);
1077
1078         __TRY
1079         {
1080                 PACE_HEADER     ace;
1081                 int             i;
1082
1083                 if (pAcl->AclRevision != ACL_REVISION)
1084                     ret = FALSE;
1085                 else
1086                 {
1087                     ace = (PACE_HEADER)(pAcl+1);
1088                     ret = TRUE;
1089                     for (i=0;i<=pAcl->AceCount;i++)
1090                     {
1091                         if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1092                         {
1093                             ret = FALSE;
1094                             break;
1095                         }
1096                         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1097                     }
1098                 }
1099         }
1100         __EXCEPT(page_fault)
1101         {
1102                 WARN("(%p): invalid pointer!\n", pAcl);
1103                 return 0;
1104         }
1105         __ENDTRY
1106         return ret;
1107 }
1108
1109 /******************************************************************************
1110  *  RtlGetAce           [NTDLL.@]
1111  */
1112 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1113 {
1114         PACE_HEADER ace;
1115
1116         TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1117
1118         if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1119                 return STATUS_INVALID_PARAMETER;
1120
1121         ace = (PACE_HEADER)(pAcl + 1);
1122         for (;dwAceIndex;dwAceIndex--)
1123                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1124
1125         *pAce = (LPVOID) ace;
1126
1127         return STATUS_SUCCESS;
1128 }
1129
1130 /*
1131  *      misc
1132  */
1133
1134 /******************************************************************************
1135  *  RtlAdjustPrivilege          [NTDLL.@]
1136  */
1137 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
1138 {
1139         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
1140         return 0;
1141 }
1142
1143 /******************************************************************************
1144  *  RtlImpersonateSelf          [NTDLL.@]
1145  */
1146 BOOL WINAPI
1147 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1148 {
1149         FIXME("(%08x), stub\n", ImpersonationLevel);
1150         return TRUE;
1151 }
1152
1153 /******************************************************************************
1154  *  NtAccessCheck               [NTDLL.@]
1155  *  ZwAccessCheck               [NTDLL.@]
1156  */
1157 NTSTATUS WINAPI
1158 NtAccessCheck(
1159         IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1160         IN HANDLE ClientToken,
1161         IN ACCESS_MASK DesiredAccess,
1162         IN PGENERIC_MAPPING GenericMapping,
1163         OUT PPRIVILEGE_SET PrivilegeSet,
1164         OUT PULONG ReturnLength,
1165         OUT PULONG GrantedAccess,
1166         OUT NTSTATUS *AccessStatus)
1167 {
1168         FIXME("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1169           SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1170           PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1171         *AccessStatus = STATUS_SUCCESS;
1172         return STATUS_SUCCESS;
1173 }
1174
1175 /******************************************************************************
1176  *  NtSetSecurityObject         [NTDLL.@]
1177  */
1178 NTSTATUS WINAPI
1179 NtSetSecurityObject(
1180         IN HANDLE Handle,
1181         IN SECURITY_INFORMATION SecurityInformation,
1182         IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1183 {
1184         FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1185         return STATUS_SUCCESS;
1186 }
1187
1188 /******************************************************************************
1189  * RtlGetControlSecurityDescriptor (NTDLL.@)
1190  */
1191
1192 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1193         PSECURITY_DESCRIPTOR  pSecurityDescriptor,
1194         PSECURITY_DESCRIPTOR_CONTROL pControl,
1195         LPDWORD lpdwRevision)
1196 {
1197         FIXME("(%p,%p,%p),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
1198         return STATUS_SUCCESS;
1199 }
1200
1201 /******************************************************************************
1202  * RtlConvertSidToUnicodeString (NTDLL.@)
1203  *
1204  * The returned SID is used to access the USER registry hive usually
1205  *
1206  * the native function returns something like
1207  * "S-1-5-21-0000000000-000000000-0000000000-500";
1208  */
1209 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1210        PUNICODE_STRING String,
1211        PSID Sid,
1212        BOOLEAN AllocateString)
1213 {
1214     const char *user = wine_get_user_name();
1215     int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 ) * sizeof(WCHAR);
1216
1217     FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1218
1219     String->Length = len - sizeof(WCHAR);
1220     if (AllocateString)
1221     {
1222         String->MaximumLength = len;
1223         if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1224             return STATUS_NO_MEMORY;
1225     }
1226     else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1227
1228     ntdll_umbstowcs( 0, user, strlen(user)+1, String->Buffer, len/sizeof(WCHAR) );
1229     return STATUS_SUCCESS;
1230 }
1231
1232 /******************************************************************************
1233  * RtlQueryInformationAcl (NTDLL.@)
1234  */
1235 NTSTATUS WINAPI RtlQueryInformationAcl(
1236     PACL pAcl,
1237     LPVOID pAclInformation,
1238     DWORD nAclInformationLength,
1239     ACL_INFORMATION_CLASS dwAclInformationClass)
1240 {
1241     NTSTATUS status = STATUS_SUCCESS;
1242
1243     TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n", 
1244         pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1245
1246     switch (dwAclInformationClass)
1247     {
1248         case AclRevisionInformation:
1249         {
1250             PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1251
1252             if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1253                 status = STATUS_INVALID_PARAMETER;
1254             else
1255                 paclrev->AclRevision = pAcl->AclRevision;
1256
1257             break;
1258         }
1259
1260         case AclSizeInformation:
1261         {
1262             PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1263
1264             if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1265                 status = STATUS_INVALID_PARAMETER;
1266             else
1267             {
1268                 INT i;
1269                 PACE_HEADER ace;
1270
1271                 paclsize->AceCount = pAcl->AceCount;
1272
1273                 paclsize->AclBytesInUse = 0;
1274                 ace = (PACE_HEADER) (pAcl + 1);
1275
1276                 for (i = 0; i < pAcl->AceCount; i++)
1277                 {
1278                     paclsize->AclBytesInUse += ace->AceSize;
1279                     ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1280                 }
1281
1282                 if (pAcl->AclSize < paclsize->AclBytesInUse)
1283                 {
1284                     WARN("Acl has %ld bytes free\n", paclsize->AclBytesFree);
1285                     paclsize->AclBytesFree = 0;
1286                     paclsize->AclBytesInUse = pAcl->AclSize;
1287                 }
1288                 else
1289                     paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1290             }
1291
1292             break;
1293         }
1294
1295         default:
1296             WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1297             status = STATUS_INVALID_PARAMETER;
1298     }
1299
1300     return status;
1301 }