Run length and ascii85 encode image data.
[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 "winnls.h"
39 #include "winerror.h"
40 #include "winreg.h"
41 #include "winternl.h"
42 #include "ntdll_misc.h"
43 #include "excpt.h"
44 #include "wine/library.h"
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
48
49 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
50
51 /* filter for page-fault exceptions */
52 static WINE_EXCEPTION_FILTER(page_fault)
53 {
54     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
55         return EXCEPTION_EXECUTE_HANDLER;
56     return EXCEPTION_CONTINUE_SEARCH;
57 }
58
59 /*
60  *      SID FUNCTIONS
61  */
62
63 /******************************************************************************
64  *  RtlAllocateAndInitializeSid         [NTDLL.@]
65  *
66  */
67 BOOLEAN WINAPI RtlAllocateAndInitializeSid (
68         PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
69         BYTE nSubAuthorityCount,
70         DWORD nSubAuthority0, DWORD nSubAuthority1,
71         DWORD nSubAuthority2, DWORD nSubAuthority3,
72         DWORD nSubAuthority4, DWORD nSubAuthority5,
73         DWORD nSubAuthority6, DWORD nSubAuthority7,
74         PSID *pSid )
75 {
76         TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
77                 pIdentifierAuthority,nSubAuthorityCount,
78                 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
79                 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
80
81         if (!(*pSid = RtlAllocateHeap( ntdll_get_process_heap(), 0,
82                                        RtlLengthRequiredSid(nSubAuthorityCount))))
83           return FALSE;
84
85         (*pSid)->Revision = SID_REVISION;
86
87         if (pIdentifierAuthority)
88           memcpy(&(*pSid)->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
89         *RtlSubAuthorityCountSid(*pSid) = nSubAuthorityCount;
90
91         if (nSubAuthorityCount > 0)
92           *RtlSubAuthoritySid(*pSid, 0) = nSubAuthority0;
93         if (nSubAuthorityCount > 1)
94           *RtlSubAuthoritySid(*pSid, 1) = nSubAuthority1;
95         if (nSubAuthorityCount > 2)
96           *RtlSubAuthoritySid(*pSid, 2) = nSubAuthority2;
97         if (nSubAuthorityCount > 3)
98           *RtlSubAuthoritySid(*pSid, 3) = nSubAuthority3;
99         if (nSubAuthorityCount > 4)
100           *RtlSubAuthoritySid(*pSid, 4) = nSubAuthority4;
101         if (nSubAuthorityCount > 5)
102           *RtlSubAuthoritySid(*pSid, 5) = nSubAuthority5;
103         if (nSubAuthorityCount > 6)
104           *RtlSubAuthoritySid(*pSid, 6) = nSubAuthority6;
105         if (nSubAuthorityCount > 7)
106           *RtlSubAuthoritySid(*pSid, 7) = nSubAuthority7;
107
108         return STATUS_SUCCESS;
109 }
110 /******************************************************************************
111  *  RtlEqualSid         [NTDLL.@]
112  *
113  * Determine if two SIDs are equal.
114  *
115  * PARAMS
116  *  pSid1 [I] Source SID
117  *  pSid2 [I] SID to compare with
118  *
119  * RETURNS
120  *  TRUE, if pSid1 is equal to pSid2,
121  *  FALSE otherwise.
122  */
123 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
124 {
125     if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
126         return FALSE;
127
128     if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
129         return FALSE;
130
131     if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
132         return FALSE;
133
134     return TRUE;
135 }
136
137 /******************************************************************************
138  * RtlEqualPrefixSid    [NTDLL.@]
139  */
140 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
141 {
142     if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
143         return FALSE;
144
145     if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
146         return FALSE;
147
148     if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(pSid1->SubAuthorityCount - 1)) != 0)
149         return FALSE;
150
151     return TRUE;
152 }
153
154
155 /******************************************************************************
156  *  RtlFreeSid          [NTDLL.@]
157  *
158  * Free the resources used by a SID.
159  *
160  * PARAMS
161  *  pSid [I] SID to Free.
162  *
163  * RETURNS
164  *  STATUS_SUCCESS.
165  */
166 DWORD WINAPI RtlFreeSid(PSID pSid)
167 {
168         TRACE("(%p)\n", pSid);
169         RtlFreeHeap( ntdll_get_process_heap(), 0, pSid );
170         return STATUS_SUCCESS;
171 }
172
173 /**************************************************************************
174  * RtlLengthRequiredSid [NTDLL.@]
175  *
176  * Determine the amount of memory a SID will use
177  *
178  * PARAMS
179  *   nrofsubauths [I] Number of Sub Authorities in the SID.
180  *
181  * RETURNS
182  *   The size, in bytes, of a SID with nrofsubauths Sub Authorities.
183  */
184 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
185 {
186         return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
187 }
188
189 /**************************************************************************
190  *                 RtlLengthSid                         [NTDLL.@]
191  *
192  * Determine the amount of memory a SID is using
193  *
194  * PARAMS
195  *  pSid [I] SID to ge the size of.
196  *
197  * RETURNS
198  *  The size, in bytes, of pSid.
199  */
200 DWORD WINAPI RtlLengthSid(PSID pSid)
201 {
202         TRACE("sid=%p\n",pSid);
203         if (!pSid) return 0;
204         return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
205 }
206
207 /**************************************************************************
208  *                 RtlInitializeSid                     [NTDLL.@]
209  *
210  * Initialise a SID.
211  *
212  * PARAMS
213  *  pSid                 [I] SID to initialise
214  *  pIdentifierAuthority [I] Identifier Authority
215  *  nSubAuthorityCount   [I] Number of Sub Authorities
216  *
217  * RETURNS
218  *  Success: TRUE. pSid is initialised withe the details given.
219  *  Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
220  */
221 BOOL WINAPI RtlInitializeSid(
222         PSID pSid,
223         PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
224         BYTE nSubAuthorityCount)
225 {
226         int i;
227         if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
228           return FALSE;
229
230         pSid->Revision = SID_REVISION;
231         pSid->SubAuthorityCount = nSubAuthorityCount;
232         if (pIdentifierAuthority)
233           memcpy(&pSid->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 &(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 &(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 &(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 < (pSourceSid->SubAuthorityCount*4+8))
300           return FALSE;
301
302         memmove(pDestinationSid, pSourceSid, 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 || pSid->Revision != SID_REVISION ||
324             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(*lpsd));
363         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 ( 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 SecurityDescriptor)
394 {
395         ULONG offset = 0;
396         ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
397
398         if ( SecurityDescriptor == NULL )
399                 return 0;
400
401         if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
402                 offset = (ULONG) SecurityDescriptor;
403
404         if ( SecurityDescriptor->Owner != NULL )
405                 Size += RtlLengthSid((PSID)((LPBYTE)SecurityDescriptor->Owner + offset));
406
407         if ( SecurityDescriptor->Group != NULL )
408                 Size += RtlLengthSid((PSID)((LPBYTE)SecurityDescriptor->Group + offset));
409
410         if ( SecurityDescriptor->Sacl != NULL )
411                 Size += ((PACL)((LPBYTE)SecurityDescriptor->Sacl + offset))->AclSize;
412
413         if ( SecurityDescriptor->Dacl != NULL )
414                 Size += ((PACL)((LPBYTE)SecurityDescriptor->Dacl + offset))->AclSize;
415
416         return Size;
417 }
418
419 /******************************************************************************
420  *  RtlGetDaclSecurityDescriptor                [NTDLL.@]
421  *
422  */
423 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
424         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
425         OUT PBOOLEAN lpbDaclPresent,
426         OUT PACL *pDacl,
427         OUT PBOOLEAN lpbDaclDefaulted)
428 {
429         TRACE("(%p,%p,%p,%p)\n",
430         pSecurityDescriptor, lpbDaclPresent, *pDacl, lpbDaclDefaulted);
431
432         if (pSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
433           return STATUS_UNKNOWN_REVISION ;
434
435         if ( (*lpbDaclPresent = (SE_DACL_PRESENT & pSecurityDescriptor->Control) ? 1 : 0) )
436         {
437           if ( SE_SELF_RELATIVE & pSecurityDescriptor->Control)
438           { *pDacl = (PACL) ((LPBYTE)pSecurityDescriptor + (DWORD)pSecurityDescriptor->Dacl);
439           }
440           else
441           { *pDacl = pSecurityDescriptor->Dacl;
442           }
443         }
444
445         *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & pSecurityDescriptor->Control ) ? 1 : 0);
446
447         return STATUS_SUCCESS;
448 }
449
450 /**************************************************************************
451  *  RtlSetDaclSecurityDescriptor                [NTDLL.@]
452  */
453 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
454         PSECURITY_DESCRIPTOR lpsd,
455         BOOLEAN daclpresent,
456         PACL dacl,
457         BOOLEAN dacldefaulted )
458 {
459         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
460                 return STATUS_UNKNOWN_REVISION;
461         if (lpsd->Control & SE_SELF_RELATIVE)
462                 return STATUS_INVALID_SECURITY_DESCR;
463
464         if (!daclpresent)
465         {       lpsd->Control &= ~SE_DACL_PRESENT;
466                 return TRUE;
467         }
468
469         lpsd->Control |= SE_DACL_PRESENT;
470         lpsd->Dacl = dacl;
471
472         if (dacldefaulted)
473                 lpsd->Control |= SE_DACL_DEFAULTED;
474         else
475                 lpsd->Control &= ~SE_DACL_DEFAULTED;
476
477         return STATUS_SUCCESS;
478 }
479
480 /******************************************************************************
481  *  RtlGetSaclSecurityDescriptor                [NTDLL.@]
482  *
483  */
484 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
485         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
486         OUT PBOOLEAN lpbSaclPresent,
487         OUT PACL *pSacl,
488         OUT PBOOLEAN lpbSaclDefaulted)
489 {
490         TRACE("(%p,%p,%p,%p)\n",
491         pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
492
493         if (pSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
494           return STATUS_UNKNOWN_REVISION ;
495
496         if ( (*lpbSaclPresent = (SE_SACL_PRESENT & pSecurityDescriptor->Control) ? 1 : 0) )
497         {
498           if ( SE_SELF_RELATIVE & pSecurityDescriptor->Control)
499           { *pSacl = (PACL) ((LPBYTE)pSecurityDescriptor + (DWORD)pSecurityDescriptor->Sacl);
500           }
501           else
502           { *pSacl = pSecurityDescriptor->Sacl;
503           }
504         }
505
506         *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & pSecurityDescriptor->Control ) ? 1 : 0);
507
508         return STATUS_SUCCESS;
509 }
510
511 /**************************************************************************
512  * RtlSetSaclSecurityDescriptor                 [NTDLL.@]
513  */
514 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
515         PSECURITY_DESCRIPTOR lpsd,
516         BOOLEAN saclpresent,
517         PACL sacl,
518         BOOLEAN sacldefaulted)
519 {
520         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
521                 return STATUS_UNKNOWN_REVISION;
522         if (lpsd->Control & SE_SELF_RELATIVE)
523                 return STATUS_INVALID_SECURITY_DESCR;
524         if (!saclpresent) {
525                 lpsd->Control &= ~SE_SACL_PRESENT;
526                 return 0;
527         }
528         lpsd->Control |= SE_SACL_PRESENT;
529         lpsd->Sacl = sacl;
530         if (sacldefaulted)
531                 lpsd->Control |= SE_SACL_DEFAULTED;
532         else
533                 lpsd->Control &= ~SE_SACL_DEFAULTED;
534         return STATUS_SUCCESS;
535 }
536
537 /**************************************************************************
538  * RtlGetOwnerSecurityDescriptor                [NTDLL.@]
539  */
540 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
541         PSECURITY_DESCRIPTOR SecurityDescriptor,
542         PSID *Owner,
543         PBOOLEAN OwnerDefaulted)
544 {
545         if ( !SecurityDescriptor  || !Owner || !OwnerDefaulted )
546                 return STATUS_INVALID_PARAMETER;
547
548         if (SecurityDescriptor->Owner != NULL)
549         {
550             if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
551                 *Owner = (PSID)((LPBYTE)SecurityDescriptor +
552                                 (ULONG)SecurityDescriptor->Owner);
553             else
554                 *Owner = SecurityDescriptor->Owner;
555
556             if ( SecurityDescriptor->Control & SE_OWNER_DEFAULTED )
557                 *OwnerDefaulted = TRUE;
558             else
559                 *OwnerDefaulted = FALSE;
560         }
561         else
562             *Owner = NULL;
563
564         return STATUS_SUCCESS;
565 }
566
567 /**************************************************************************
568  *                 RtlSetOwnerSecurityDescriptor                [NTDLL.@]
569  */
570 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
571         PSECURITY_DESCRIPTOR lpsd,
572         PSID owner,
573         BOOLEAN ownerdefaulted)
574 {
575         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
576                 return STATUS_UNKNOWN_REVISION;
577         if (lpsd->Control & SE_SELF_RELATIVE)
578                 return STATUS_INVALID_SECURITY_DESCR;
579
580         lpsd->Owner = owner;
581         if (ownerdefaulted)
582                 lpsd->Control |= SE_OWNER_DEFAULTED;
583         else
584                 lpsd->Control &= ~SE_OWNER_DEFAULTED;
585         return STATUS_SUCCESS;
586 }
587
588 /**************************************************************************
589  *                 RtlSetGroupSecurityDescriptor                [NTDLL.@]
590  */
591 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
592         PSECURITY_DESCRIPTOR lpsd,
593         PSID group,
594         BOOLEAN groupdefaulted)
595 {
596         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
597                 return STATUS_UNKNOWN_REVISION;
598         if (lpsd->Control & SE_SELF_RELATIVE)
599                 return STATUS_INVALID_SECURITY_DESCR;
600
601         lpsd->Group = group;
602         if (groupdefaulted)
603                 lpsd->Control |= SE_GROUP_DEFAULTED;
604         else
605                 lpsd->Control &= ~SE_GROUP_DEFAULTED;
606         return STATUS_SUCCESS;
607 }
608 /**************************************************************************
609  *                 RtlGetGroupSecurityDescriptor                [NTDLL.@]
610  */
611 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
612         PSECURITY_DESCRIPTOR SecurityDescriptor,
613         PSID *Group,
614         PBOOLEAN GroupDefaulted)
615 {
616         if ( !SecurityDescriptor || !Group || !GroupDefaulted )
617                 return STATUS_INVALID_PARAMETER;
618
619         if (SecurityDescriptor->Group != NULL)
620         {
621             if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
622                 *Group = (PSID)((LPBYTE)SecurityDescriptor +
623                                 (ULONG)SecurityDescriptor->Group);
624             else
625                 *Group = SecurityDescriptor->Group;
626
627             if ( SecurityDescriptor->Control & SE_GROUP_DEFAULTED )
628                 *GroupDefaulted = TRUE;
629             else
630                 *GroupDefaulted = FALSE;
631         }
632         else
633             *Group = NULL;
634
635         return STATUS_SUCCESS;
636 }
637
638 /**************************************************************************
639  *                 RtlMakeSelfRelativeSD                [NTDLL.@]
640  */
641 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
642         IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
643         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
644         IN OUT LPDWORD lpdwBufferLength)
645 {
646     ULONG offsetRel;
647     ULONG length;
648     PSECURITY_DESCRIPTOR pAbs = pAbsoluteSecurityDescriptor;
649     PSECURITY_DESCRIPTOR pRel = pSelfRelativeSecurityDescriptor;
650
651     TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
652         lpdwBufferLength ? *lpdwBufferLength: -1);
653
654     if (!lpdwBufferLength || !pAbs)
655         return STATUS_INVALID_PARAMETER;
656
657     length = RtlLengthSecurityDescriptor(pAbs);
658     if (*lpdwBufferLength < length)
659     {
660         *lpdwBufferLength = length;
661         return STATUS_BUFFER_TOO_SMALL;
662     }
663
664     if (!pRel)
665         return STATUS_INVALID_PARAMETER;
666
667     if (pAbs->Control & SE_SELF_RELATIVE)
668     {
669         memcpy(pRel, pAbs, length);
670         return STATUS_SUCCESS;
671     }
672
673     pRel->Revision = pAbs->Revision;
674     pRel->Sbz1 = pAbs->Sbz1;
675     pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
676
677     offsetRel = sizeof(SECURITY_DESCRIPTOR);
678     pRel->Owner = (PSID) offsetRel;
679     length = RtlLengthSid(pAbs->Owner);
680     memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
681
682     offsetRel += length;
683     pRel->Group = (PSID) offsetRel;
684     length = RtlLengthSid(pAbs->Group);
685     memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
686
687     if (pRel->Control & SE_SACL_PRESENT)
688     {
689         offsetRel += length;
690         pRel->Sacl = (PACL) offsetRel;
691         length = pAbs->Sacl->AclSize;
692         memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
693     }
694     else
695     {
696         pRel->Sacl = NULL;
697     }
698
699     if (pRel->Control & SE_DACL_PRESENT)
700     {
701         offsetRel += length;
702         pRel->Dacl = (PACL) offsetRel;
703         length = pAbs->Dacl->AclSize;
704         memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
705     }
706     else
707     {
708         pRel->Dacl = NULL;
709     }
710
711     return STATUS_SUCCESS;
712 }
713
714
715 /**************************************************************************
716 + *                 RtlSelfRelativeToAbsoluteSD [NTDLL.@]
717 + */
718 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
719         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
720         OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
721         OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
722         OUT PACL pDacl,
723         OUT LPDWORD lpdwDaclSize,
724         OUT PACL pSacl,
725         OUT LPDWORD lpdwSaclSize,
726         OUT PSID pOwner,
727         OUT LPDWORD lpdwOwnerSize,
728         OUT PSID pPrimaryGroup,
729         OUT LPDWORD lpdwPrimaryGroupSize)
730 {
731     NTSTATUS status = STATUS_SUCCESS;
732     PSECURITY_DESCRIPTOR pAbs = pAbsoluteSecurityDescriptor;
733     PSECURITY_DESCRIPTOR pRel = pSelfRelativeSecurityDescriptor;
734
735     if (!pRel ||
736         !lpdwAbsoluteSecurityDescriptorSize ||
737         !lpdwDaclSize ||
738         !lpdwSaclSize ||
739         !lpdwOwnerSize ||
740         !lpdwPrimaryGroupSize ||
741         ~pRel->Control & SE_SELF_RELATIVE)
742         return STATUS_INVALID_PARAMETER;
743
744     /* Confirm buffers are sufficiently large */
745     if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
746     {
747         *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
748         status = STATUS_BUFFER_TOO_SMALL;
749     }
750
751     if (pRel->Control & SE_DACL_PRESENT &&
752         *lpdwDaclSize  < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
753     {
754         *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
755         status = STATUS_BUFFER_TOO_SMALL;
756     }
757
758     if (pRel->Control & SE_SACL_PRESENT &&
759         *lpdwSaclSize  < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
760     {
761         *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
762         status = STATUS_BUFFER_TOO_SMALL;
763     }
764
765     if (pRel->Owner &&
766         *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
767     {
768         *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
769         status = STATUS_BUFFER_TOO_SMALL;
770     }
771
772     if (pRel->Group &&
773         *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
774     {
775         *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
776         status = STATUS_BUFFER_TOO_SMALL;
777     }
778
779     if (status != STATUS_SUCCESS)
780         return status;
781
782     /* Copy structures */
783     pAbs->Revision = pRel->Revision;
784     pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
785
786     if (pRel->Control & SE_SACL_PRESENT)
787     {
788         PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
789
790         memcpy(pSacl, pAcl, pAcl->AclSize);
791         pAbs->Sacl = pSacl;
792     }
793
794     if (pRel->Control & SE_DACL_PRESENT)
795     {
796         PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
797         memcpy(pDacl, pAcl, pAcl->AclSize);
798         pAbs->Dacl = pDacl;
799     }
800
801     if (pRel->Owner)
802     {
803         PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
804         memcpy(pOwner, psid, RtlLengthSid(psid));
805         pAbs->Owner = pOwner;
806     }
807
808     if (pRel->Group)
809     {
810         PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
811         memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
812         pAbs->Group = pPrimaryGroup;
813     }
814
815     return status;
816 }
817
818 /*
819  *      access control list's
820  */
821
822 /**************************************************************************
823  *                 RtlCreateAcl                         [NTDLL.@]
824  *
825  * NOTES
826  *    This should return NTSTATUS
827  */
828 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
829 {
830         TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
831
832         if (rev!=ACL_REVISION)
833                 return STATUS_INVALID_PARAMETER;
834         if (size<sizeof(ACL))
835                 return STATUS_BUFFER_TOO_SMALL;
836         if (size>0xFFFF)
837                 return STATUS_INVALID_PARAMETER;
838
839         memset(acl,'\0',sizeof(ACL));
840         acl->AclRevision        = rev;
841         acl->AclSize            = size;
842         acl->AceCount           = 0;
843         return STATUS_SUCCESS;
844 }
845
846 /**************************************************************************
847  *                 RtlFirstFreeAce                      [NTDLL.@]
848  * looks for the AceCount+1 ACE, and if it is still within the alloced
849  * ACL, return a pointer to it
850  */
851 BOOLEAN WINAPI RtlFirstFreeAce(
852         PACL acl,
853         PACE_HEADER *x)
854 {
855         PACE_HEADER     ace;
856         int             i;
857
858         *x = 0;
859         ace = (PACE_HEADER)(acl+1);
860         for (i=0;i<acl->AceCount;i++) {
861                 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
862                         return 0;
863                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
864         }
865         if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
866                 return 0;
867         *x = ace;
868         return 1;
869 }
870
871 /**************************************************************************
872  *                 RtlAddAce                            [NTDLL.@]
873  */
874 NTSTATUS WINAPI RtlAddAce(
875         PACL acl,
876         DWORD rev,
877         DWORD xnrofaces,
878         PACE_HEADER acestart,
879         DWORD acelen)
880 {
881         PACE_HEADER     ace,targetace;
882         int             nrofaces;
883
884         if (acl->AclRevision != ACL_REVISION)
885                 return STATUS_INVALID_PARAMETER;
886         if (!RtlFirstFreeAce(acl,&targetace))
887                 return STATUS_INVALID_PARAMETER;
888         nrofaces=0;ace=acestart;
889         while (((DWORD)ace-(DWORD)acestart)<acelen) {
890                 nrofaces++;
891                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
892         }
893         if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
894                 return STATUS_INVALID_PARAMETER;
895         memcpy((LPBYTE)targetace,acestart,acelen);
896         acl->AceCount+=nrofaces;
897         return STATUS_SUCCESS;
898 }
899
900 /**************************************************************************
901  *                 RtlDeleteAce                         [NTDLL.@]
902  */
903 NTSTATUS  WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
904 {
905         NTSTATUS status;
906         PACE_HEADER pAce;
907
908         status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
909
910         if (STATUS_SUCCESS == status)
911         {
912                 PACE_HEADER pcAce;
913                 DWORD len = 0;
914
915                 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
916                 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
917                 {
918                         len += pcAce->AceSize;
919                         pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
920                 }
921
922                 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
923                 pAcl->AceCount--;
924         }
925
926         return status;
927 }
928
929 /******************************************************************************
930  *  RtlAddAccessAllowedAce              [NTDLL.@]
931  */
932 NTSTATUS WINAPI RtlAddAccessAllowedAce(
933         IN OUT PACL pAcl,
934         IN DWORD dwAceRevision,
935         IN DWORD AccessMask,
936         IN PSID pSid)
937 {
938         return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
939 }
940  
941 /******************************************************************************
942  *  RtlAddAccessAllowedAceEx            [NTDLL.@]
943  */
944 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
945         IN OUT PACL pAcl,
946         IN DWORD dwAceRevision,
947         IN DWORD AceFlags,
948         IN DWORD AccessMask,
949         IN PSID pSid)
950 {
951         DWORD dwLengthSid;
952         ACCESS_ALLOWED_ACE * pAaAce;
953         DWORD dwSpaceLeft;
954
955         TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
956                 pAcl, dwAceRevision, AccessMask, pSid);
957
958         if (!RtlValidSid(pSid))
959                 return STATUS_INVALID_SID;
960         if (!RtlValidAcl(pAcl))
961                 return STATUS_INVALID_ACL;
962
963         dwLengthSid = RtlLengthSid(pSid);
964         if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
965                 return STATUS_INVALID_ACL;
966
967         if (!pAaAce)
968                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
969
970         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
971         if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
972                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
973
974         pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
975         pAaAce->Header.AceFlags = AceFlags;
976         pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
977         pAaAce->Mask = AccessMask;
978         pAcl->AceCount++;
979         RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
980         return STATUS_SUCCESS;
981 }
982
983 /******************************************************************************
984  *  RtlAddAccessDeniedAce               [NTDLL.@]
985  */
986 NTSTATUS WINAPI RtlAddAccessDeniedAce(
987         IN OUT PACL pAcl,
988         IN DWORD dwAceRevision,
989         IN DWORD AccessMask,
990         IN PSID pSid)
991 {
992         return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
993 }
994
995 /******************************************************************************
996  *  RtlAddAccessDeniedAceEx             [NTDLL.@]
997  */
998 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
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         DWORD dwSpaceLeft;
1007         ACCESS_DENIED_ACE * pAdAce;
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 *) &pAdAce))
1019                 return STATUS_INVALID_ACL;
1020
1021         if (!pAdAce)
1022                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1023
1024         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1025         if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1026                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1027
1028         pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1029         pAdAce->Header.AceFlags = AceFlags;
1030         pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1031         pAdAce->Mask = AccessMask;
1032         pAcl->AceCount++;
1033         RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1034         return STATUS_SUCCESS;
1035 }
1036
1037 /******************************************************************************
1038  *  RtlValidAcl         [NTDLL.@]
1039  */
1040 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1041 {
1042         BOOLEAN ret;
1043         TRACE("(%p)\n", pAcl);
1044
1045         __TRY
1046         {
1047                 PACE_HEADER     ace;
1048                 int             i;
1049
1050                 if (pAcl->AclRevision != ACL_REVISION)
1051                     ret = FALSE;
1052                 else
1053                 {
1054                     ace = (PACE_HEADER)(pAcl+1);
1055                     ret = TRUE;
1056                     for (i=0;i<=pAcl->AceCount;i++)
1057                     {
1058                         if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1059                         {
1060                             ret = FALSE;
1061                             break;
1062                         }
1063                         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1064                     }
1065                 }
1066         }
1067         __EXCEPT(page_fault)
1068         {
1069                 WARN("(%p): invalid pointer!\n", pAcl);
1070                 return 0;
1071         }
1072         __ENDTRY
1073         return ret;
1074 }
1075
1076 /******************************************************************************
1077  *  RtlGetAce           [NTDLL.@]
1078  */
1079 DWORD WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1080 {
1081         PACE_HEADER ace;
1082
1083         TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1084
1085         if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1086                 return STATUS_INVALID_PARAMETER;
1087
1088         ace = (PACE_HEADER)(pAcl + 1);
1089         for (;dwAceIndex;dwAceIndex--)
1090                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1091
1092         *pAce = (LPVOID) ace;
1093
1094         return STATUS_SUCCESS;
1095 }
1096
1097 /*
1098  *      misc
1099  */
1100
1101 /******************************************************************************
1102  *  RtlAdjustPrivilege          [NTDLL.@]
1103  */
1104 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
1105 {
1106         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
1107         return 0;
1108 }
1109
1110 /******************************************************************************
1111  *  RtlImpersonateSelf          [NTDLL.@]
1112  */
1113 BOOL WINAPI
1114 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1115 {
1116         FIXME("(%08x), stub\n", ImpersonationLevel);
1117         return TRUE;
1118 }
1119
1120 /******************************************************************************
1121  *  NtAccessCheck               [NTDLL.@]
1122  *  ZwAccessCheck               [NTDLL.@]
1123  */
1124 NTSTATUS WINAPI
1125 NtAccessCheck(
1126         IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1127         IN HANDLE ClientToken,
1128         IN ACCESS_MASK DesiredAccess,
1129         IN PGENERIC_MAPPING GenericMapping,
1130         OUT PPRIVILEGE_SET PrivilegeSet,
1131         OUT PULONG ReturnLength,
1132         OUT PULONG GrantedAccess,
1133         OUT PBOOLEAN AccessStatus)
1134 {
1135         FIXME("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1136           SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1137           PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1138         *AccessStatus = TRUE;
1139         return STATUS_SUCCESS;
1140 }
1141
1142 /******************************************************************************
1143  *  NtSetSecurityObject         [NTDLL.@]
1144  */
1145 NTSTATUS WINAPI
1146 NtSetSecurityObject(
1147         IN HANDLE Handle,
1148         IN SECURITY_INFORMATION SecurityInformation,
1149         IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1150 {
1151         FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1152         return STATUS_SUCCESS;
1153 }
1154
1155 /******************************************************************************
1156  * RtlGetControlSecurityDescriptor (NTDLL.@)
1157  */
1158
1159 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1160         PSECURITY_DESCRIPTOR  pSecurityDescriptor,
1161         PSECURITY_DESCRIPTOR_CONTROL pControl,
1162         LPDWORD lpdwRevision)
1163 {
1164         FIXME("(%p,%p,%p),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
1165         return STATUS_SUCCESS;
1166 }
1167
1168 /******************************************************************************
1169  * RtlConvertSidToUnicodeString (NTDLL.@)
1170  *
1171  * The returned SID is used to access the USER registry hive usually
1172  *
1173  * the native function returns something like
1174  * "S-1-5-21-0000000000-000000000-0000000000-500";
1175  */
1176 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1177        PUNICODE_STRING String,
1178        PSID Sid,
1179        BOOLEAN AllocateString)
1180 {
1181         const char *p = wine_get_user_name();
1182         NTSTATUS status;
1183         ANSI_STRING AnsiStr;
1184
1185         FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1186
1187         RtlInitAnsiString(&AnsiStr, p);
1188         status = RtlAnsiStringToUnicodeString(String, &AnsiStr, AllocateString);
1189
1190         TRACE("%s (%u %u)\n",debugstr_w(String->Buffer),String->Length,String->MaximumLength);
1191         return status;
1192 }
1193
1194 /******************************************************************************
1195  * RtlQueryInformationAcl (NTDLL.@)
1196  */
1197 NTSTATUS WINAPI RtlQueryInformationAcl(
1198     PACL pAcl,
1199     LPVOID pAclInformation,
1200     DWORD nAclInformationLength,
1201     ACL_INFORMATION_CLASS dwAclInformationClass)
1202 {
1203     NTSTATUS status = STATUS_SUCCESS;
1204
1205     TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n", 
1206         pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1207
1208     switch (dwAclInformationClass)
1209     {
1210         case AclRevisionInformation:
1211         {
1212             PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1213
1214             if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1215                 status = STATUS_INVALID_PARAMETER;
1216             else
1217                 paclrev->AclRevision = pAcl->AclRevision;
1218
1219             break;
1220         }
1221
1222         case AclSizeInformation:
1223         {
1224             PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1225
1226             if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1227                 status = STATUS_INVALID_PARAMETER;
1228             else
1229             {
1230                 INT i;
1231                 PACE_HEADER ace;
1232
1233                 paclsize->AceCount = pAcl->AceCount;
1234
1235                 paclsize->AclBytesInUse = 0;
1236                 ace = (PACE_HEADER) (pAcl + 1);
1237
1238                 for (i = 0; i < pAcl->AceCount; i++)
1239                 {
1240                     paclsize->AclBytesInUse += ace->AceSize;
1241                     ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1242                 }
1243
1244                 if (pAcl->AclSize < paclsize->AclBytesInUse)
1245                 {
1246                     WARN("Acl has %ld bytes free\n", pAcl->AclSize - paclsize->AclBytesInUse);
1247                     paclsize->AclBytesFree = 0;
1248                     paclsize->AclBytesInUse = pAcl->AclSize;
1249                 }
1250                 else
1251                     paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1252             }
1253
1254             break;
1255         }
1256
1257         default:
1258             WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1259             status = STATUS_INVALID_PARAMETER;
1260     }
1261
1262     return status;
1263 }