Fixed MediaSample passing. This is the upstream filter that releases
[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 BOOLEAN 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 FALSE;
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 ge 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 withe 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 DWORD 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->Sacl != NULL )
412                 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
413
414         if ( lpsd->Dacl != NULL )
415                 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
416
417         return Size;
418 }
419
420 /******************************************************************************
421  *  RtlGetDaclSecurityDescriptor                [NTDLL.@]
422  *
423  */
424 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
425         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
426         OUT PBOOLEAN lpbDaclPresent,
427         OUT PACL *pDacl,
428         OUT PBOOLEAN lpbDaclDefaulted)
429 {
430         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
431
432         TRACE("(%p,%p,%p,%p)\n",
433         pSecurityDescriptor, lpbDaclPresent, *pDacl, lpbDaclDefaulted);
434
435         if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
436           return STATUS_UNKNOWN_REVISION ;
437
438         if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
439         {
440           if ( SE_SELF_RELATIVE & lpsd->Control)
441           { *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
442           }
443           else
444           { *pDacl = lpsd->Dacl;
445           }
446         }
447
448         *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
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           }
508           else
509           { *pSacl = lpsd->Sacl;
510           }
511         }
512
513         *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
514
515         return STATUS_SUCCESS;
516 }
517
518 /**************************************************************************
519  * RtlSetSaclSecurityDescriptor                 [NTDLL.@]
520  */
521 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
522         PSECURITY_DESCRIPTOR pSecurityDescriptor,
523         BOOLEAN saclpresent,
524         PACL sacl,
525         BOOLEAN sacldefaulted)
526 {
527         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
528
529         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
530                 return STATUS_UNKNOWN_REVISION;
531         if (lpsd->Control & SE_SELF_RELATIVE)
532                 return STATUS_INVALID_SECURITY_DESCR;
533         if (!saclpresent) {
534                 lpsd->Control &= ~SE_SACL_PRESENT;
535                 return 0;
536         }
537         lpsd->Control |= SE_SACL_PRESENT;
538         lpsd->Sacl = sacl;
539         if (sacldefaulted)
540                 lpsd->Control |= SE_SACL_DEFAULTED;
541         else
542                 lpsd->Control &= ~SE_SACL_DEFAULTED;
543         return STATUS_SUCCESS;
544 }
545
546 /**************************************************************************
547  * RtlGetOwnerSecurityDescriptor                [NTDLL.@]
548  */
549 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
550         PSECURITY_DESCRIPTOR pSecurityDescriptor,
551         PSID *Owner,
552         PBOOLEAN OwnerDefaulted)
553 {
554         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
555
556         if ( !lpsd  || !Owner || !OwnerDefaulted )
557                 return STATUS_INVALID_PARAMETER;
558
559         if (lpsd->Owner != NULL)
560         {
561             if (lpsd->Control & SE_SELF_RELATIVE)
562                 *Owner = (PSID)((LPBYTE)lpsd +
563                                 (ULONG)lpsd->Owner);
564             else
565                 *Owner = lpsd->Owner;
566
567             if ( lpsd->Control & SE_OWNER_DEFAULTED )
568                 *OwnerDefaulted = TRUE;
569             else
570                 *OwnerDefaulted = FALSE;
571         }
572         else
573             *Owner = NULL;
574
575         return STATUS_SUCCESS;
576 }
577
578 /**************************************************************************
579  *                 RtlSetOwnerSecurityDescriptor                [NTDLL.@]
580  */
581 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
582         PSECURITY_DESCRIPTOR pSecurityDescriptor,
583         PSID owner,
584         BOOLEAN ownerdefaulted)
585 {
586         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
587
588         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
589                 return STATUS_UNKNOWN_REVISION;
590         if (lpsd->Control & SE_SELF_RELATIVE)
591                 return STATUS_INVALID_SECURITY_DESCR;
592
593         lpsd->Owner = owner;
594         if (ownerdefaulted)
595                 lpsd->Control |= SE_OWNER_DEFAULTED;
596         else
597                 lpsd->Control &= ~SE_OWNER_DEFAULTED;
598         return STATUS_SUCCESS;
599 }
600
601 /**************************************************************************
602  *                 RtlSetGroupSecurityDescriptor                [NTDLL.@]
603  */
604 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
605         PSECURITY_DESCRIPTOR pSecurityDescriptor,
606         PSID group,
607         BOOLEAN groupdefaulted)
608 {
609         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
610
611         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
612                 return STATUS_UNKNOWN_REVISION;
613         if (lpsd->Control & SE_SELF_RELATIVE)
614                 return STATUS_INVALID_SECURITY_DESCR;
615
616         lpsd->Group = group;
617         if (groupdefaulted)
618                 lpsd->Control |= SE_GROUP_DEFAULTED;
619         else
620                 lpsd->Control &= ~SE_GROUP_DEFAULTED;
621         return STATUS_SUCCESS;
622 }
623 /**************************************************************************
624  *                 RtlGetGroupSecurityDescriptor                [NTDLL.@]
625  */
626 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
627         PSECURITY_DESCRIPTOR pSecurityDescriptor,
628         PSID *Group,
629         PBOOLEAN GroupDefaulted)
630 {
631         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
632
633         if ( !lpsd || !Group || !GroupDefaulted )
634                 return STATUS_INVALID_PARAMETER;
635
636         if (lpsd->Group != NULL)
637         {
638             if (lpsd->Control & SE_SELF_RELATIVE)
639                 *Group = (PSID)((LPBYTE)lpsd +
640                                 (ULONG)lpsd->Group);
641             else
642                 *Group = lpsd->Group;
643
644             if ( lpsd->Control & SE_GROUP_DEFAULTED )
645                 *GroupDefaulted = TRUE;
646             else
647                 *GroupDefaulted = FALSE;
648         }
649         else
650             *Group = NULL;
651
652         return STATUS_SUCCESS;
653 }
654
655 /**************************************************************************
656  *                 RtlMakeSelfRelativeSD                [NTDLL.@]
657  */
658 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
659         IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
660         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
661         IN OUT LPDWORD lpdwBufferLength)
662 {
663     ULONG offsetRel;
664     ULONG length;
665     SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
666     SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
667
668     TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
669         lpdwBufferLength ? *lpdwBufferLength: -1);
670
671     if (!lpdwBufferLength || !pAbs)
672         return STATUS_INVALID_PARAMETER;
673
674     length = RtlLengthSecurityDescriptor(pAbs);
675     if (*lpdwBufferLength < length)
676     {
677         *lpdwBufferLength = length;
678         return STATUS_BUFFER_TOO_SMALL;
679     }
680
681     if (!pRel)
682         return STATUS_INVALID_PARAMETER;
683
684     if (pAbs->Control & SE_SELF_RELATIVE)
685     {
686         memcpy(pRel, pAbs, length);
687         return STATUS_SUCCESS;
688     }
689
690     pRel->Revision = pAbs->Revision;
691     pRel->Sbz1 = pAbs->Sbz1;
692     pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
693
694     offsetRel = sizeof(SECURITY_DESCRIPTOR);
695     pRel->Owner = (PSID) offsetRel;
696     length = RtlLengthSid(pAbs->Owner);
697     memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
698
699     offsetRel += length;
700     pRel->Group = (PSID) offsetRel;
701     length = RtlLengthSid(pAbs->Group);
702     memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
703
704     if (pRel->Control & SE_SACL_PRESENT)
705     {
706         offsetRel += length;
707         pRel->Sacl = (PACL) offsetRel;
708         length = pAbs->Sacl->AclSize;
709         memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
710     }
711     else
712     {
713         pRel->Sacl = NULL;
714     }
715
716     if (pRel->Control & SE_DACL_PRESENT)
717     {
718         offsetRel += length;
719         pRel->Dacl = (PACL) offsetRel;
720         length = pAbs->Dacl->AclSize;
721         memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
722     }
723     else
724     {
725         pRel->Dacl = NULL;
726     }
727
728     return STATUS_SUCCESS;
729 }
730
731
732 /**************************************************************************
733 + *                 RtlSelfRelativeToAbsoluteSD [NTDLL.@]
734 + */
735 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
736         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
737         OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
738         OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
739         OUT PACL pDacl,
740         OUT LPDWORD lpdwDaclSize,
741         OUT PACL pSacl,
742         OUT LPDWORD lpdwSaclSize,
743         OUT PSID pOwner,
744         OUT LPDWORD lpdwOwnerSize,
745         OUT PSID pPrimaryGroup,
746         OUT LPDWORD lpdwPrimaryGroupSize)
747 {
748     NTSTATUS status = STATUS_SUCCESS;
749     SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
750     SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
751
752     if (!pRel ||
753         !lpdwAbsoluteSecurityDescriptorSize ||
754         !lpdwDaclSize ||
755         !lpdwSaclSize ||
756         !lpdwOwnerSize ||
757         !lpdwPrimaryGroupSize ||
758         ~pRel->Control & SE_SELF_RELATIVE)
759         return STATUS_INVALID_PARAMETER;
760
761     /* Confirm buffers are sufficiently large */
762     if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
763     {
764         *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
765         status = STATUS_BUFFER_TOO_SMALL;
766     }
767
768     if (pRel->Control & SE_DACL_PRESENT &&
769         *lpdwDaclSize  < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
770     {
771         *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
772         status = STATUS_BUFFER_TOO_SMALL;
773     }
774
775     if (pRel->Control & SE_SACL_PRESENT &&
776         *lpdwSaclSize  < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
777     {
778         *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
779         status = STATUS_BUFFER_TOO_SMALL;
780     }
781
782     if (pRel->Owner &&
783         *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
784     {
785         *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
786         status = STATUS_BUFFER_TOO_SMALL;
787     }
788
789     if (pRel->Group &&
790         *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
791     {
792         *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
793         status = STATUS_BUFFER_TOO_SMALL;
794     }
795
796     if (status != STATUS_SUCCESS)
797         return status;
798
799     /* Copy structures */
800     pAbs->Revision = pRel->Revision;
801     pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
802
803     if (pRel->Control & SE_SACL_PRESENT)
804     {
805         PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
806
807         memcpy(pSacl, pAcl, pAcl->AclSize);
808         pAbs->Sacl = pSacl;
809     }
810
811     if (pRel->Control & SE_DACL_PRESENT)
812     {
813         PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
814         memcpy(pDacl, pAcl, pAcl->AclSize);
815         pAbs->Dacl = pDacl;
816     }
817
818     if (pRel->Owner)
819     {
820         PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
821         memcpy(pOwner, psid, RtlLengthSid(psid));
822         pAbs->Owner = pOwner;
823     }
824
825     if (pRel->Group)
826     {
827         PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
828         memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
829         pAbs->Group = pPrimaryGroup;
830     }
831
832     return status;
833 }
834
835 /*
836  *      access control list's
837  */
838
839 /**************************************************************************
840  *                 RtlCreateAcl                         [NTDLL.@]
841  *
842  * NOTES
843  *    This should return NTSTATUS
844  */
845 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
846 {
847         TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
848
849         if (rev!=ACL_REVISION)
850                 return STATUS_INVALID_PARAMETER;
851         if (size<sizeof(ACL))
852                 return STATUS_BUFFER_TOO_SMALL;
853         if (size>0xFFFF)
854                 return STATUS_INVALID_PARAMETER;
855
856         memset(acl,'\0',sizeof(ACL));
857         acl->AclRevision        = rev;
858         acl->AclSize            = size;
859         acl->AceCount           = 0;
860         return STATUS_SUCCESS;
861 }
862
863 /**************************************************************************
864  *                 RtlFirstFreeAce                      [NTDLL.@]
865  * looks for the AceCount+1 ACE, and if it is still within the alloced
866  * ACL, return a pointer to it
867  */
868 BOOLEAN WINAPI RtlFirstFreeAce(
869         PACL acl,
870         PACE_HEADER *x)
871 {
872         PACE_HEADER     ace;
873         int             i;
874
875         *x = 0;
876         ace = (PACE_HEADER)(acl+1);
877         for (i=0;i<acl->AceCount;i++) {
878                 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
879                         return 0;
880                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
881         }
882         if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
883                 return 0;
884         *x = ace;
885         return 1;
886 }
887
888 /**************************************************************************
889  *                 RtlAddAce                            [NTDLL.@]
890  */
891 NTSTATUS WINAPI RtlAddAce(
892         PACL acl,
893         DWORD rev,
894         DWORD xnrofaces,
895         PACE_HEADER acestart,
896         DWORD acelen)
897 {
898         PACE_HEADER     ace,targetace;
899         int             nrofaces;
900
901         if (acl->AclRevision != ACL_REVISION)
902                 return STATUS_INVALID_PARAMETER;
903         if (!RtlFirstFreeAce(acl,&targetace))
904                 return STATUS_INVALID_PARAMETER;
905         nrofaces=0;ace=acestart;
906         while (((DWORD)ace-(DWORD)acestart)<acelen) {
907                 nrofaces++;
908                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
909         }
910         if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
911                 return STATUS_INVALID_PARAMETER;
912         memcpy((LPBYTE)targetace,acestart,acelen);
913         acl->AceCount+=nrofaces;
914         return STATUS_SUCCESS;
915 }
916
917 /**************************************************************************
918  *                 RtlDeleteAce                         [NTDLL.@]
919  */
920 NTSTATUS  WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
921 {
922         NTSTATUS status;
923         PACE_HEADER pAce;
924
925         status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
926
927         if (STATUS_SUCCESS == status)
928         {
929                 PACE_HEADER pcAce;
930                 DWORD len = 0;
931
932                 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
933                 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
934                 {
935                         len += pcAce->AceSize;
936                         pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
937                 }
938
939                 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
940                 pAcl->AceCount--;
941         }
942
943         return status;
944 }
945
946 /******************************************************************************
947  *  RtlAddAccessAllowedAce              [NTDLL.@]
948  */
949 NTSTATUS WINAPI RtlAddAccessAllowedAce(
950         IN OUT PACL pAcl,
951         IN DWORD dwAceRevision,
952         IN DWORD AccessMask,
953         IN PSID pSid)
954 {
955         return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
956 }
957  
958 /******************************************************************************
959  *  RtlAddAccessAllowedAceEx            [NTDLL.@]
960  */
961 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
962         IN OUT PACL pAcl,
963         IN DWORD dwAceRevision,
964         IN DWORD AceFlags,
965         IN DWORD AccessMask,
966         IN PSID pSid)
967 {
968         DWORD dwLengthSid;
969         ACCESS_ALLOWED_ACE * pAaAce;
970         DWORD dwSpaceLeft;
971
972         TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
973                 pAcl, dwAceRevision, AccessMask, pSid);
974
975         if (!RtlValidSid(pSid))
976                 return STATUS_INVALID_SID;
977         if (!RtlValidAcl(pAcl))
978                 return STATUS_INVALID_ACL;
979
980         dwLengthSid = RtlLengthSid(pSid);
981         if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
982                 return STATUS_INVALID_ACL;
983
984         if (!pAaAce)
985                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
986
987         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
988         if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
989                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
990
991         pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
992         pAaAce->Header.AceFlags = AceFlags;
993         pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
994         pAaAce->Mask = AccessMask;
995         pAcl->AceCount++;
996         RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
997         return STATUS_SUCCESS;
998 }
999
1000 /******************************************************************************
1001  *  RtlAddAccessDeniedAce               [NTDLL.@]
1002  */
1003 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1004         IN OUT PACL pAcl,
1005         IN DWORD dwAceRevision,
1006         IN DWORD AccessMask,
1007         IN PSID pSid)
1008 {
1009         return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1010 }
1011
1012 /******************************************************************************
1013  *  RtlAddAccessDeniedAceEx             [NTDLL.@]
1014  */
1015 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1016         IN OUT PACL pAcl,
1017         IN DWORD dwAceRevision,
1018         IN DWORD AceFlags,
1019         IN DWORD AccessMask,
1020         IN PSID pSid)
1021 {
1022         DWORD dwLengthSid;
1023         DWORD dwSpaceLeft;
1024         ACCESS_DENIED_ACE * pAdAce;
1025
1026         TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1027                 pAcl, dwAceRevision, AccessMask, pSid);
1028
1029         if (!RtlValidSid(pSid))
1030                 return STATUS_INVALID_SID;
1031         if (!RtlValidAcl(pAcl))
1032                 return STATUS_INVALID_ACL;
1033
1034         dwLengthSid = RtlLengthSid(pSid);
1035         if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
1036                 return STATUS_INVALID_ACL;
1037
1038         if (!pAdAce)
1039                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1040
1041         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1042         if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1043                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1044
1045         pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1046         pAdAce->Header.AceFlags = AceFlags;
1047         pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1048         pAdAce->Mask = AccessMask;
1049         pAcl->AceCount++;
1050         RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1051         return STATUS_SUCCESS;
1052 }
1053
1054 /******************************************************************************
1055  *  RtlValidAcl         [NTDLL.@]
1056  */
1057 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1058 {
1059         BOOLEAN ret;
1060         TRACE("(%p)\n", pAcl);
1061
1062         __TRY
1063         {
1064                 PACE_HEADER     ace;
1065                 int             i;
1066
1067                 if (pAcl->AclRevision != ACL_REVISION)
1068                     ret = FALSE;
1069                 else
1070                 {
1071                     ace = (PACE_HEADER)(pAcl+1);
1072                     ret = TRUE;
1073                     for (i=0;i<=pAcl->AceCount;i++)
1074                     {
1075                         if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1076                         {
1077                             ret = FALSE;
1078                             break;
1079                         }
1080                         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1081                     }
1082                 }
1083         }
1084         __EXCEPT(page_fault)
1085         {
1086                 WARN("(%p): invalid pointer!\n", pAcl);
1087                 return 0;
1088         }
1089         __ENDTRY
1090         return ret;
1091 }
1092
1093 /******************************************************************************
1094  *  RtlGetAce           [NTDLL.@]
1095  */
1096 DWORD WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1097 {
1098         PACE_HEADER ace;
1099
1100         TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1101
1102         if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1103                 return STATUS_INVALID_PARAMETER;
1104
1105         ace = (PACE_HEADER)(pAcl + 1);
1106         for (;dwAceIndex;dwAceIndex--)
1107                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1108
1109         *pAce = (LPVOID) ace;
1110
1111         return STATUS_SUCCESS;
1112 }
1113
1114 /*
1115  *      misc
1116  */
1117
1118 /******************************************************************************
1119  *  RtlAdjustPrivilege          [NTDLL.@]
1120  */
1121 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
1122 {
1123         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
1124         return 0;
1125 }
1126
1127 /******************************************************************************
1128  *  RtlImpersonateSelf          [NTDLL.@]
1129  */
1130 BOOL WINAPI
1131 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1132 {
1133         FIXME("(%08x), stub\n", ImpersonationLevel);
1134         return TRUE;
1135 }
1136
1137 /******************************************************************************
1138  *  NtAccessCheck               [NTDLL.@]
1139  *  ZwAccessCheck               [NTDLL.@]
1140  */
1141 NTSTATUS WINAPI
1142 NtAccessCheck(
1143         IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1144         IN HANDLE ClientToken,
1145         IN ACCESS_MASK DesiredAccess,
1146         IN PGENERIC_MAPPING GenericMapping,
1147         OUT PPRIVILEGE_SET PrivilegeSet,
1148         OUT PULONG ReturnLength,
1149         OUT PULONG GrantedAccess,
1150         OUT PBOOLEAN AccessStatus)
1151 {
1152         FIXME("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1153           SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1154           PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1155         *AccessStatus = TRUE;
1156         return STATUS_SUCCESS;
1157 }
1158
1159 /******************************************************************************
1160  *  NtSetSecurityObject         [NTDLL.@]
1161  */
1162 NTSTATUS WINAPI
1163 NtSetSecurityObject(
1164         IN HANDLE Handle,
1165         IN SECURITY_INFORMATION SecurityInformation,
1166         IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1167 {
1168         FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1169         return STATUS_SUCCESS;
1170 }
1171
1172 /******************************************************************************
1173  * RtlGetControlSecurityDescriptor (NTDLL.@)
1174  */
1175
1176 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1177         PSECURITY_DESCRIPTOR  pSecurityDescriptor,
1178         PSECURITY_DESCRIPTOR_CONTROL pControl,
1179         LPDWORD lpdwRevision)
1180 {
1181         FIXME("(%p,%p,%p),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
1182         return STATUS_SUCCESS;
1183 }
1184
1185 /******************************************************************************
1186  * RtlConvertSidToUnicodeString (NTDLL.@)
1187  *
1188  * The returned SID is used to access the USER registry hive usually
1189  *
1190  * the native function returns something like
1191  * "S-1-5-21-0000000000-000000000-0000000000-500";
1192  */
1193 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1194        PUNICODE_STRING String,
1195        PSID Sid,
1196        BOOLEAN AllocateString)
1197 {
1198     const char *user = wine_get_user_name();
1199     int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 ) * sizeof(WCHAR);
1200
1201     FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1202
1203     String->Length = len - sizeof(WCHAR);
1204     if (AllocateString)
1205     {
1206         String->MaximumLength = len;
1207         if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1208             return STATUS_NO_MEMORY;
1209     }
1210     else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1211
1212     ntdll_umbstowcs( 0, user, strlen(user)+1, String->Buffer, len/sizeof(WCHAR) );
1213     return STATUS_SUCCESS;
1214 }
1215
1216 /******************************************************************************
1217  * RtlQueryInformationAcl (NTDLL.@)
1218  */
1219 NTSTATUS WINAPI RtlQueryInformationAcl(
1220     PACL pAcl,
1221     LPVOID pAclInformation,
1222     DWORD nAclInformationLength,
1223     ACL_INFORMATION_CLASS dwAclInformationClass)
1224 {
1225     NTSTATUS status = STATUS_SUCCESS;
1226
1227     TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n", 
1228         pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1229
1230     switch (dwAclInformationClass)
1231     {
1232         case AclRevisionInformation:
1233         {
1234             PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1235
1236             if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1237                 status = STATUS_INVALID_PARAMETER;
1238             else
1239                 paclrev->AclRevision = pAcl->AclRevision;
1240
1241             break;
1242         }
1243
1244         case AclSizeInformation:
1245         {
1246             PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1247
1248             if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1249                 status = STATUS_INVALID_PARAMETER;
1250             else
1251             {
1252                 INT i;
1253                 PACE_HEADER ace;
1254
1255                 paclsize->AceCount = pAcl->AceCount;
1256
1257                 paclsize->AclBytesInUse = 0;
1258                 ace = (PACE_HEADER) (pAcl + 1);
1259
1260                 for (i = 0; i < pAcl->AceCount; i++)
1261                 {
1262                     paclsize->AclBytesInUse += ace->AceSize;
1263                     ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1264                 }
1265
1266                 if (pAcl->AclSize < paclsize->AclBytesInUse)
1267                 {
1268                     WARN("Acl has %ld bytes free\n", pAcl->AclSize - paclsize->AclBytesInUse);
1269                     paclsize->AclBytesFree = 0;
1270                     paclsize->AclBytesInUse = pAcl->AclSize;
1271                 }
1272                 else
1273                     paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1274             }
1275
1276             break;
1277         }
1278
1279         default:
1280             WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1281             status = STATUS_INVALID_PARAMETER;
1282     }
1283
1284     return status;
1285 }