~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/ntdll/sec.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 "ntstatus.h"
 36 #define WIN32_NO_STATUS
 37 #include "windef.h"
 38 #include "ntdll_misc.h"
 39 #include "wine/exception.h"
 40 #include "wine/library.h"
 41 #include "wine/unicode.h"
 42 #include "wine/debug.h"
 43 
 44 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 45 
 46 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
 47 
 48 /* helper function to retrieve active length of an ACL */
 49 static size_t acl_bytesInUse(PACL pAcl)
 50 {
 51     int i;
 52     size_t bytesInUse = sizeof(ACL);
 53     PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
 54     for (i = 0; i < pAcl->AceCount; i++)
 55     {
 56         bytesInUse += ace->AceSize;
 57         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
 58     }
 59     return bytesInUse;
 60 }
 61 
 62 /* helper function to copy an ACL */
 63 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
 64 {
 65     DWORD size;
 66 
 67     if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
 68         return FALSE;
 69 
 70     size = pSourceAcl->AclSize;
 71     if (nDestinationAclLength < size)
 72         return FALSE;
 73 
 74     memmove(pDestinationAcl, pSourceAcl, size);
 75     return TRUE;
 76 }
 77 
 78 /* generically adds an ACE to an ACL */
 79 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
 80                                DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
 81 {
 82     ACE_HEADER *pAceHeader;
 83     DWORD dwLengthSid;
 84     DWORD dwAceSize;
 85     DWORD *pAccessMask;
 86     DWORD *pSidStart;
 87 
 88     if (!RtlValidSid(pSid))
 89         return STATUS_INVALID_SID;
 90 
 91     if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
 92         return STATUS_REVISION_MISMATCH;
 93 
 94     if (!RtlValidAcl(pAcl))
 95         return STATUS_INVALID_ACL;
 96 
 97     if (!RtlFirstFreeAce(pAcl, &pAceHeader))
 98         return STATUS_INVALID_ACL;
 99 
100     if (!pAceHeader)
101         return STATUS_ALLOTTED_SPACE_EXCEEDED;
102 
103     /* calculate generic size of the ACE */
104     dwLengthSid = RtlLengthSid(pSid);
105     dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
106     if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
107         return STATUS_ALLOTTED_SPACE_EXCEEDED;
108 
109     /* fill the new ACE */
110     pAceHeader->AceType = dwAceType;
111     pAceHeader->AceFlags = dwAceFlags;
112     pAceHeader->AceSize = dwAceSize;
113 
114     /* skip past the ACE_HEADER of the ACE */
115     pAccessMask = (DWORD *)(pAceHeader + 1);
116     *pAccessMask = dwAccessMask;
117 
118     /* skip past ACE->Mask */
119     pSidStart = pAccessMask + 1;
120     RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
121 
122     pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
123     pAcl->AceCount++;
124 
125     return STATUS_SUCCESS;
126 }
127 
128 /*
129  *      SID FUNCTIONS
130  */
131 
132 /******************************************************************************
133  *  RtlAllocateAndInitializeSid         [NTDLL.@]
134  *
135  */
136 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
137         PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
138         BYTE nSubAuthorityCount,
139         DWORD nSubAuthority0, DWORD nSubAuthority1,
140         DWORD nSubAuthority2, DWORD nSubAuthority3,
141         DWORD nSubAuthority4, DWORD nSubAuthority5,
142         DWORD nSubAuthority6, DWORD nSubAuthority7,
143         PSID *pSid )
144 {
145     SID *tmp_sid;
146 
147     TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
148                 pIdentifierAuthority,nSubAuthorityCount,
149                 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
150                 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
151 
152     if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
153 
154     if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
155                                     RtlLengthRequiredSid(nSubAuthorityCount))))
156         return STATUS_NO_MEMORY;
157 
158     tmp_sid->Revision = SID_REVISION;
159 
160     if (pIdentifierAuthority)
161         tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
162     tmp_sid->SubAuthorityCount = nSubAuthorityCount;
163 
164     switch( nSubAuthorityCount )
165     {
166         case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
167         case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
168         case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
169         case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
170         case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
171         case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
172         case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
173         case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
174         break;
175     }
176     *pSid = tmp_sid;
177     return STATUS_SUCCESS;
178 }
179 
180 /******************************************************************************
181  *  RtlEqualSid         [NTDLL.@]
182  *
183  * Determine if two SIDs are equal.
184  *
185  * PARAMS
186  *  pSid1 [I] Source SID
187  *  pSid2 [I] SID to compare with
188  *
189  * RETURNS
190  *  TRUE, if pSid1 is equal to pSid2,
191  *  FALSE otherwise.
192  */
193 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
194 {
195     if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
196         return FALSE;
197 
198     if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
199         return FALSE;
200 
201     if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
202         return FALSE;
203 
204     return TRUE;
205 }
206 
207 /******************************************************************************
208  * RtlEqualPrefixSid    [NTDLL.@]
209  */
210 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
211 {
212     if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
213         return FALSE;
214 
215     if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
216         return FALSE;
217 
218     if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
219         return FALSE;
220 
221     return TRUE;
222 }
223 
224 
225 /******************************************************************************
226  *  RtlFreeSid          [NTDLL.@]
227  *
228  * Free the resources used by a SID.
229  *
230  * PARAMS
231  *  pSid [I] SID to Free.
232  *
233  * RETURNS
234  *  STATUS_SUCCESS.
235  */
236 DWORD WINAPI RtlFreeSid(PSID pSid)
237 {
238         TRACE("(%p)\n", pSid);
239         RtlFreeHeap( GetProcessHeap(), 0, pSid );
240         return STATUS_SUCCESS;
241 }
242 
243 /**************************************************************************
244  * RtlLengthRequiredSid [NTDLL.@]
245  *
246  * Determine the amount of memory a SID will use
247  *
248  * PARAMS
249  *   nrofsubauths [I] Number of Sub Authorities in the SID.
250  *
251  * RETURNS
252  *   The size, in bytes, of a SID with nrofsubauths Sub Authorities.
253  */
254 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
255 {
256         return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
257 }
258 
259 /**************************************************************************
260  *                 RtlLengthSid                         [NTDLL.@]
261  *
262  * Determine the amount of memory a SID is using
263  *
264  * PARAMS
265  *  pSid [I] SID to get the size of.
266  *
267  * RETURNS
268  *  The size, in bytes, of pSid.
269  */
270 DWORD WINAPI RtlLengthSid(PSID pSid)
271 {
272         TRACE("sid=%p\n",pSid);
273         if (!pSid) return 0;
274         return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
275 }
276 
277 /**************************************************************************
278  *                 RtlInitializeSid                     [NTDLL.@]
279  *
280  * Initialise a SID.
281  *
282  * PARAMS
283  *  pSid                 [I] SID to initialise
284  *  pIdentifierAuthority [I] Identifier Authority
285  *  nSubAuthorityCount   [I] Number of Sub Authorities
286  *
287  * RETURNS
288  *  Success: TRUE. pSid is initialised with the details given.
289  *  Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
290  */
291 BOOL WINAPI RtlInitializeSid(
292         PSID pSid,
293         PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
294         BYTE nSubAuthorityCount)
295 {
296         int i;
297         SID* pisid=pSid;
298 
299         if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
300           return FALSE;
301 
302         pisid->Revision = SID_REVISION;
303         pisid->SubAuthorityCount = nSubAuthorityCount;
304         if (pIdentifierAuthority)
305           pisid->IdentifierAuthority = *pIdentifierAuthority;
306 
307         for (i = 0; i < nSubAuthorityCount; i++)
308           *RtlSubAuthoritySid(pSid, i) = 0;
309 
310         return TRUE;
311 }
312 
313 /**************************************************************************
314  *                 RtlSubAuthoritySid                   [NTDLL.@]
315  *
316  * Return the Sub Authority of a SID
317  *
318  * PARAMS
319  *   pSid          [I] SID to get the Sub Authority from.
320  *   nSubAuthority [I] Sub Authority number.
321  *
322  * RETURNS
323  *   A pointer to The Sub Authority value of pSid.
324  */
325 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
326 {
327     return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
328 }
329 
330 /**************************************************************************
331  * RtlIdentifierAuthoritySid    [NTDLL.@]
332  *
333  * Return the Identifier Authority of a SID.
334  *
335  * PARAMS
336  *   pSid [I] SID to get the Identifier Authority from.
337  *
338  * RETURNS
339  *   A pointer to the Identifier Authority value of pSid.
340  */
341 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
342 {
343     return &(((SID*)pSid)->IdentifierAuthority);
344 }
345 
346 /**************************************************************************
347  *                 RtlSubAuthorityCountSid              [NTDLL.@]
348  *
349  * Get the number of Sub Authorities in a SID.
350  *
351  * PARAMS
352  *   pSid [I] SID to get the count from.
353  *
354  * RETURNS
355  *  A pointer to the Sub Authority count of pSid.
356  */
357 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
358 {
359     return &(((SID*)pSid)->SubAuthorityCount);
360 }
361 
362 /**************************************************************************
363  *                 RtlCopySid                           [NTDLL.@]
364  */
365 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
366 {
367         if (!pSourceSid || !RtlValidSid(pSourceSid) ||
368             (nDestinationSidLength < RtlLengthSid(pSourceSid)))
369           return FALSE;
370 
371         if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
372           return FALSE;
373 
374         memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
375         return TRUE;
376 }
377 /******************************************************************************
378  * RtlValidSid [NTDLL.@]
379  *
380  * Determine if a SID is valid.
381  *
382  * PARAMS
383  *   pSid [I] SID to check
384  *
385  * RETURNS
386  *   TRUE if pSid is valid,
387  *   FALSE otherwise.
388  */
389 BOOLEAN WINAPI RtlValidSid( PSID pSid )
390 {
391     BOOL ret;
392     __TRY
393     {
394         ret = TRUE;
395         if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
396             ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
397         {
398             ret = FALSE;
399         }
400     }
401     __EXCEPT_PAGE_FAULT
402     {
403         WARN("(%p): invalid pointer!\n", pSid);
404         return FALSE;
405     }
406     __ENDTRY
407     return ret;
408 }
409 
410 
411 /*
412  *      security descriptor functions
413  */
414 
415 /**************************************************************************
416  * RtlCreateSecurityDescriptor                  [NTDLL.@]
417  *
418  * Initialise a SECURITY_DESCRIPTOR.
419  *
420  * PARAMS
421  *  lpsd [O] Descriptor to initialise.
422  *  rev  [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
423  *
424  * RETURNS
425  *  Success: STATUS_SUCCESS.
426  *  Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
427  */
428 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
429         PSECURITY_DESCRIPTOR lpsd,
430         DWORD rev)
431 {
432         if (rev!=SECURITY_DESCRIPTOR_REVISION)
433                 return STATUS_UNKNOWN_REVISION;
434         memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
435         ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
436         return STATUS_SUCCESS;
437 }
438 
439 /**************************************************************************
440  * RtlCopySecurityDescriptor            [NTDLL.@]
441  *
442  * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
443  *
444  * PARAMS
445  *  pSourceSD      [O] SD to copy from.
446  *  pDestinationSD [I] Destination SD.
447  *
448  * RETURNS
449  *  Success: STATUS_SUCCESS.
450  *  Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
451  */
452 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
453 {
454     SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
455     SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
456     PSID Owner, Group;
457     PACL Dacl, Sacl;
458     BOOLEAN defaulted, present;
459     DWORD length;
460     BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
461     
462     if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
463         return STATUS_UNKNOWN_REVISION;
464 
465     /* copy initial data */
466     destSD->Revision = srcSD->Revision;
467     destSD->Sbz1 = srcSD->Sbz1;
468     destSD->Control = srcSD->Control;
469 
470     /* copy Owner */
471     RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
472     length = RtlLengthSid(Owner);
473 
474     if (isSelfRelative)
475     {
476         destSD->Owner = srcSD->Owner;
477         RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
478     }
479     else
480     {
481         destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
482         RtlCopySid(length, destSD->Owner, Owner);
483     }
484 
485     /* copy Group */
486     RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
487     length = RtlLengthSid(Group);
488 
489     if (isSelfRelative)
490     {
491         destSD->Group = srcSD->Group;
492         RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
493     }
494     else
495     {
496         destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
497         RtlCopySid(length, destSD->Group, Group);
498     }
499 
500     /* copy Dacl */
501     if (srcSD->Control & SE_DACL_PRESENT)
502     {
503         RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
504         length = Dacl->AclSize;
505 
506         if (isSelfRelative)
507         {
508             destSD->Dacl = srcSD->Dacl;
509             copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl);
510         }
511         else
512         {
513             destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
514             copy_acl(length, destSD->Dacl, Dacl);
515         }
516     }
517 
518     /* copy Sacl */
519     if (srcSD->Control & SE_SACL_PRESENT)
520     {
521         RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
522         length = Sacl->AclSize;
523 
524         if (isSelfRelative)
525         {
526             destSD->Sacl = srcSD->Sacl;
527             copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl);
528         }
529         else
530         {
531             destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
532             copy_acl(length, destSD->Sacl, Sacl);
533         }
534     }
535 
536     return STATUS_SUCCESS;
537 }
538 
539 /**************************************************************************
540  * RtlValidSecurityDescriptor                   [NTDLL.@]
541  *
542  * Determine if a SECURITY_DESCRIPTOR is valid.
543  *
544  * PARAMS
545  *  SecurityDescriptor [I] Descriptor to check.
546  *
547  * RETURNS
548  *   Success: STATUS_SUCCESS.
549  *   Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
550  */
551 NTSTATUS WINAPI RtlValidSecurityDescriptor(
552         PSECURITY_DESCRIPTOR SecurityDescriptor)
553 {
554         if ( ! SecurityDescriptor )
555                 return STATUS_INVALID_SECURITY_DESCR;
556         if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
557                 return STATUS_UNKNOWN_REVISION;
558 
559         return STATUS_SUCCESS;
560 }
561 
562 /**************************************************************************
563  *  RtlLengthSecurityDescriptor                 [NTDLL.@]
564  */
565 ULONG WINAPI RtlLengthSecurityDescriptor(
566         PSECURITY_DESCRIPTOR pSecurityDescriptor)
567 {
568         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
569         ULONG_PTR offset = 0;
570         ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
571 
572         if ( lpsd == NULL )
573                 return 0;
574 
575         if ( lpsd->Control & SE_SELF_RELATIVE)
576                 offset = (ULONG_PTR) lpsd;
577 
578         if ( lpsd->Owner != NULL )
579                 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
580 
581         if ( lpsd->Group != NULL )
582                 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
583 
584         if ( (lpsd->Control & SE_SACL_PRESENT) &&
585               lpsd->Sacl != NULL )
586                 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
587 
588         if ( (lpsd->Control & SE_DACL_PRESENT) &&
589               lpsd->Dacl != NULL )
590                 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
591 
592         return Size;
593 }
594 
595 /******************************************************************************
596  *  RtlGetDaclSecurityDescriptor                [NTDLL.@]
597  *
598  */
599 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
600         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
601         OUT PBOOLEAN lpbDaclPresent,
602         OUT PACL *pDacl,
603         OUT PBOOLEAN lpbDaclDefaulted)
604 {
605         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
606 
607         TRACE("(%p,%p,%p,%p)\n",
608         pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
609 
610         if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
611           return STATUS_UNKNOWN_REVISION ;
612 
613         if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
614         {
615           if ( SE_SELF_RELATIVE & lpsd->Control)
616             *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl);
617           else
618             *pDacl = lpsd->Dacl;
619 
620           *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
621         }
622 
623         return STATUS_SUCCESS;
624 }
625 
626 /**************************************************************************
627  *  RtlSetDaclSecurityDescriptor                [NTDLL.@]
628  */
629 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
630         PSECURITY_DESCRIPTOR pSecurityDescriptor,
631         BOOLEAN daclpresent,
632         PACL dacl,
633         BOOLEAN dacldefaulted )
634 {
635         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
636 
637         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
638                 return STATUS_UNKNOWN_REVISION;
639         if (lpsd->Control & SE_SELF_RELATIVE)
640                 return STATUS_INVALID_SECURITY_DESCR;
641 
642         if (!daclpresent)
643         {
644                 lpsd->Control &= ~SE_DACL_PRESENT;
645                 return STATUS_SUCCESS;
646         }
647 
648         lpsd->Control |= SE_DACL_PRESENT;
649         lpsd->Dacl = dacl;
650 
651         if (dacldefaulted)
652                 lpsd->Control |= SE_DACL_DEFAULTED;
653         else
654                 lpsd->Control &= ~SE_DACL_DEFAULTED;
655 
656         return STATUS_SUCCESS;
657 }
658 
659 /******************************************************************************
660  *  RtlGetSaclSecurityDescriptor                [NTDLL.@]
661  *
662  */
663 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
664         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
665         OUT PBOOLEAN lpbSaclPresent,
666         OUT PACL *pSacl,
667         OUT PBOOLEAN lpbSaclDefaulted)
668 {
669         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
670 
671         TRACE("(%p,%p,%p,%p)\n",
672         pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
673 
674         if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
675           return STATUS_UNKNOWN_REVISION;
676 
677         if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
678         {
679           if (SE_SELF_RELATIVE & lpsd->Control)
680             *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl);
681           else
682             *pSacl = lpsd->Sacl;
683 
684           *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
685         }
686 
687         return STATUS_SUCCESS;
688 }
689 
690 /**************************************************************************
691  * RtlSetSaclSecurityDescriptor                 [NTDLL.@]
692  */
693 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
694         PSECURITY_DESCRIPTOR pSecurityDescriptor,
695         BOOLEAN saclpresent,
696         PACL sacl,
697         BOOLEAN sacldefaulted)
698 {
699         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
700 
701         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
702                 return STATUS_UNKNOWN_REVISION;
703         if (lpsd->Control & SE_SELF_RELATIVE)
704                 return STATUS_INVALID_SECURITY_DESCR;
705         if (!saclpresent) {
706                 lpsd->Control &= ~SE_SACL_PRESENT;
707                 return 0;
708         }
709         lpsd->Control |= SE_SACL_PRESENT;
710         lpsd->Sacl = sacl;
711         if (sacldefaulted)
712                 lpsd->Control |= SE_SACL_DEFAULTED;
713         else
714                 lpsd->Control &= ~SE_SACL_DEFAULTED;
715         return STATUS_SUCCESS;
716 }
717 
718 /**************************************************************************
719  * RtlGetOwnerSecurityDescriptor                [NTDLL.@]
720  */
721 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
722         PSECURITY_DESCRIPTOR pSecurityDescriptor,
723         PSID *Owner,
724         PBOOLEAN OwnerDefaulted)
725 {
726         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
727 
728         if ( !lpsd  || !Owner || !OwnerDefaulted )
729                 return STATUS_INVALID_PARAMETER;
730 
731         if ( lpsd->Control & SE_OWNER_DEFAULTED )
732             *OwnerDefaulted = TRUE;
733         else
734             *OwnerDefaulted = FALSE;
735 
736         if (lpsd->Owner != NULL)
737         {
738             if (lpsd->Control & SE_SELF_RELATIVE)
739                 *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner);
740             else
741                 *Owner = lpsd->Owner;
742 
743         }
744         else
745             *Owner = NULL;
746 
747         return STATUS_SUCCESS;
748 }
749 
750 /**************************************************************************
751  *                 RtlSetOwnerSecurityDescriptor                [NTDLL.@]
752  */
753 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
754         PSECURITY_DESCRIPTOR pSecurityDescriptor,
755         PSID owner,
756         BOOLEAN ownerdefaulted)
757 {
758         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
759 
760         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
761                 return STATUS_UNKNOWN_REVISION;
762         if (lpsd->Control & SE_SELF_RELATIVE)
763                 return STATUS_INVALID_SECURITY_DESCR;
764 
765         lpsd->Owner = owner;
766         if (ownerdefaulted)
767                 lpsd->Control |= SE_OWNER_DEFAULTED;
768         else
769                 lpsd->Control &= ~SE_OWNER_DEFAULTED;
770         return STATUS_SUCCESS;
771 }
772 
773 /**************************************************************************
774  *                 RtlSetGroupSecurityDescriptor                [NTDLL.@]
775  */
776 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
777         PSECURITY_DESCRIPTOR pSecurityDescriptor,
778         PSID group,
779         BOOLEAN groupdefaulted)
780 {
781         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
782 
783         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
784                 return STATUS_UNKNOWN_REVISION;
785         if (lpsd->Control & SE_SELF_RELATIVE)
786                 return STATUS_INVALID_SECURITY_DESCR;
787 
788         lpsd->Group = group;
789         if (groupdefaulted)
790                 lpsd->Control |= SE_GROUP_DEFAULTED;
791         else
792                 lpsd->Control &= ~SE_GROUP_DEFAULTED;
793         return STATUS_SUCCESS;
794 }
795 
796 /**************************************************************************
797  *                 RtlGetGroupSecurityDescriptor                [NTDLL.@]
798  */
799 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
800         PSECURITY_DESCRIPTOR pSecurityDescriptor,
801         PSID *Group,
802         PBOOLEAN GroupDefaulted)
803 {
804         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
805 
806         if ( !lpsd || !Group || !GroupDefaulted )
807                 return STATUS_INVALID_PARAMETER;
808 
809         if ( lpsd->Control & SE_GROUP_DEFAULTED )
810             *GroupDefaulted = TRUE;
811         else
812             *GroupDefaulted = FALSE;
813 
814         if (lpsd->Group != NULL)
815         {
816             if (lpsd->Control & SE_SELF_RELATIVE)
817                 *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group);
818             else
819                 *Group = lpsd->Group;
820         }
821         else
822             *Group = NULL;
823 
824         return STATUS_SUCCESS;
825 }
826 
827 /**************************************************************************
828  *                 RtlMakeSelfRelativeSD                [NTDLL.@]
829  */
830 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
831         IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
832         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
833         IN OUT LPDWORD lpdwBufferLength)
834 {
835     ULONG_PTR offsetRel;
836     ULONG length;
837     SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
838     SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
839 
840     TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
841         lpdwBufferLength ? *lpdwBufferLength: -1);
842 
843     if (!lpdwBufferLength || !pAbs)
844         return STATUS_INVALID_PARAMETER;
845 
846     length = RtlLengthSecurityDescriptor(pAbs);
847     if (*lpdwBufferLength < length)
848     {
849         *lpdwBufferLength = length;
850         return STATUS_BUFFER_TOO_SMALL;
851     }
852 
853     if (!pRel)
854         return STATUS_INVALID_PARAMETER;
855 
856     if (pAbs->Control & SE_SELF_RELATIVE)
857     {
858         memcpy(pRel, pAbs, length);
859         return STATUS_SUCCESS;
860     }
861 
862     pRel->Revision = pAbs->Revision;
863     pRel->Sbz1 = pAbs->Sbz1;
864     pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
865 
866     offsetRel = sizeof(SECURITY_DESCRIPTOR);
867     if (pAbs->Owner)
868     {
869         pRel->Owner = (PSID) offsetRel;
870         length = RtlLengthSid(pAbs->Owner);
871         memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
872         offsetRel += length;
873     }
874     else
875     {
876         pRel->Owner = NULL;
877     }
878 
879     if (pAbs->Group)
880     {
881         pRel->Group = (PSID) offsetRel;
882         length = RtlLengthSid(pAbs->Group);
883         memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
884         offsetRel += length;
885     }
886     else
887     {
888         pRel->Group = NULL;
889     }
890 
891     if (pAbs->Sacl)
892     {
893         pRel->Sacl = (PACL) offsetRel;
894         length = pAbs->Sacl->AclSize;
895         memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
896         offsetRel += length;
897     }
898     else
899     {
900         pRel->Sacl = NULL;
901     }
902 
903     if (pAbs->Dacl)
904     {
905         pRel->Dacl = (PACL) offsetRel;
906         length = pAbs->Dacl->AclSize;
907         memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
908     }
909     else
910     {
911         pRel->Dacl = NULL;
912     }
913 
914     return STATUS_SUCCESS;
915 }
916 
917 
918 /**************************************************************************
919  *                 RtlSelfRelativeToAbsoluteSD [NTDLL.@]
920  */
921 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
922         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
923         OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
924         OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
925         OUT PACL pDacl,
926         OUT LPDWORD lpdwDaclSize,
927         OUT PACL pSacl,
928         OUT LPDWORD lpdwSaclSize,
929         OUT PSID pOwner,
930         OUT LPDWORD lpdwOwnerSize,
931         OUT PSID pPrimaryGroup,
932         OUT LPDWORD lpdwPrimaryGroupSize)
933 {
934     NTSTATUS status = STATUS_SUCCESS;
935     SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
936     SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
937 
938     if (!pRel ||
939         !lpdwAbsoluteSecurityDescriptorSize ||
940         !lpdwDaclSize ||
941         !lpdwSaclSize ||
942         !lpdwOwnerSize ||
943         !lpdwPrimaryGroupSize ||
944         ~pRel->Control & SE_SELF_RELATIVE)
945         return STATUS_INVALID_PARAMETER;
946 
947     /* Confirm buffers are sufficiently large */
948     if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
949     {
950         *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
951         status = STATUS_BUFFER_TOO_SMALL;
952     }
953 
954     if (pRel->Control & SE_DACL_PRESENT &&
955         *lpdwDaclSize  < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
956     {
957         *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
958         status = STATUS_BUFFER_TOO_SMALL;
959     }
960 
961     if (pRel->Control & SE_SACL_PRESENT &&
962         *lpdwSaclSize  < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
963     {
964         *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
965         status = STATUS_BUFFER_TOO_SMALL;
966     }
967 
968     if (pRel->Owner &&
969         *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
970     {
971         *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
972         status = STATUS_BUFFER_TOO_SMALL;
973     }
974 
975     if (pRel->Group &&
976         *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
977     {
978         *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
979         status = STATUS_BUFFER_TOO_SMALL;
980     }
981 
982     if (status != STATUS_SUCCESS)
983         return status;
984 
985     /* Copy structures, and clear the ones we don't set */
986     pAbs->Revision = pRel->Revision;
987     pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
988     pAbs->Sacl = NULL;
989     pAbs->Dacl = NULL;
990     pAbs->Owner = NULL;
991     pAbs->Group = NULL;
992 
993     if (pRel->Control & SE_SACL_PRESENT)
994     {
995         PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
996 
997         memcpy(pSacl, pAcl, pAcl->AclSize);
998         pAbs->Sacl = pSacl;
999     }
1000 
1001     if (pRel->Control & SE_DACL_PRESENT)
1002     {
1003         PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
1004         memcpy(pDacl, pAcl, pAcl->AclSize);
1005         pAbs->Dacl = pDacl;
1006     }
1007 
1008     if (pRel->Owner)
1009     {
1010         PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
1011         memcpy(pOwner, psid, RtlLengthSid(psid));
1012         pAbs->Owner = pOwner;
1013     }
1014 
1015     if (pRel->Group)
1016     {
1017         PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
1018         memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1019         pAbs->Group = pPrimaryGroup;
1020     }
1021 
1022     return status;
1023 }
1024 
1025 /******************************************************************************
1026  * RtlGetControlSecurityDescriptor (NTDLL.@)
1027  */
1028 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1029     PSECURITY_DESCRIPTOR pSecurityDescriptor,
1030     PSECURITY_DESCRIPTOR_CONTROL pControl,
1031     LPDWORD lpdwRevision)
1032 {
1033     SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1034 
1035     TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1036 
1037     *lpdwRevision = lpsd->Revision;
1038 
1039     if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1040         return STATUS_UNKNOWN_REVISION;
1041 
1042     *pControl = lpsd->Control;
1043 
1044     return STATUS_SUCCESS;
1045 }
1046 
1047 /******************************************************************************
1048  * RtlSetControlSecurityDescriptor (NTDLL.@)
1049  */
1050 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1051     PSECURITY_DESCRIPTOR SecurityDescriptor,
1052     SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1053     SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1054 {
1055     SECURITY_DESCRIPTOR_CONTROL const immutable
1056        = SE_OWNER_DEFAULTED  | SE_GROUP_DEFAULTED
1057        | SE_DACL_PRESENT     | SE_DACL_DEFAULTED
1058        | SE_SACL_PRESENT     | SE_SACL_DEFAULTED
1059        | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1060        ;
1061 
1062     SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1063 
1064     TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1065           ControlBitsOfInterest, ControlBitsToSet);
1066 
1067     if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1068         return STATUS_INVALID_PARAMETER;
1069 
1070     lpsd->Control |=  (ControlBitsOfInterest &  ControlBitsToSet);
1071     lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1072 
1073     return STATUS_SUCCESS;
1074 }
1075 
1076 
1077 /**************************************************************************
1078  *                 RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1079  */
1080 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1081     PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1082     PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1083     PULONG BufferLength)
1084 {
1085     SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1086 
1087     TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1088           SelfRelativeSecurityDescriptor, BufferLength);
1089 
1090     if (abs->Control & SE_SELF_RELATIVE)
1091         return STATUS_BAD_DESCRIPTOR_FORMAT;
1092 
1093     return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor, 
1094         SelfRelativeSecurityDescriptor, BufferLength);
1095 }
1096 
1097 
1098 /*
1099  *      access control list's
1100  */
1101 
1102 /**************************************************************************
1103  *                 RtlCreateAcl                         [NTDLL.@]
1104  *
1105  * NOTES
1106  *    This should return NTSTATUS
1107  */
1108 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1109 {
1110         TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1111 
1112         if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1113                 return STATUS_INVALID_PARAMETER;
1114         if (size<sizeof(ACL))
1115                 return STATUS_BUFFER_TOO_SMALL;
1116         if (size>0xFFFF)
1117                 return STATUS_INVALID_PARAMETER;
1118 
1119         memset(acl,'\0',sizeof(ACL));
1120         acl->AclRevision        = rev;
1121         acl->AclSize            = size;
1122         acl->AceCount           = 0;
1123         return STATUS_SUCCESS;
1124 }
1125 
1126 /**************************************************************************
1127  *                 RtlFirstFreeAce                      [NTDLL.@]
1128  * looks for the AceCount+1 ACE, and if it is still within the alloced
1129  * ACL, return a pointer to it
1130  */
1131 BOOLEAN WINAPI RtlFirstFreeAce(
1132         PACL acl,
1133         PACE_HEADER *x)
1134 {
1135         PACE_HEADER     ace;
1136         int             i;
1137 
1138         *x = 0;
1139         ace = (PACE_HEADER)(acl+1);
1140         for (i=0;i<acl->AceCount;i++) {
1141                 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1142                         return 0;
1143                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1144         }
1145         if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1146                 return 0;
1147         *x = ace;
1148         return 1;
1149 }
1150 
1151 /**************************************************************************
1152  *                 RtlAddAce                            [NTDLL.@]
1153  */
1154 NTSTATUS WINAPI RtlAddAce(
1155         PACL acl,
1156         DWORD rev,
1157         DWORD xnrofaces,
1158         PACE_HEADER acestart,
1159         DWORD acelen)
1160 {
1161         PACE_HEADER     ace,targetace;
1162         int             nrofaces;
1163 
1164         if (acl->AclRevision != ACL_REVISION)
1165                 return STATUS_INVALID_PARAMETER;
1166         if (!RtlFirstFreeAce(acl,&targetace))
1167                 return STATUS_INVALID_PARAMETER;
1168         nrofaces=0;ace=acestart;
1169         while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1170                 nrofaces++;
1171                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1172         }
1173         if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1174                 return STATUS_INVALID_PARAMETER;
1175         memcpy((LPBYTE)targetace,acestart,acelen);
1176         acl->AceCount+=nrofaces;
1177         return STATUS_SUCCESS;
1178 }
1179 
1180 /**************************************************************************
1181  *                 RtlDeleteAce                         [NTDLL.@]
1182  */
1183 NTSTATUS  WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1184 {
1185         NTSTATUS status;
1186         PACE_HEADER pAce;
1187 
1188         status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1189 
1190         if (STATUS_SUCCESS == status)
1191         {
1192                 PACE_HEADER pcAce;
1193                 DWORD len = 0;
1194 
1195                 /* skip over the ACE we are deleting */
1196                 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1197                 dwAceIndex++;
1198 
1199                 /* calculate the length of the rest */
1200                 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1201                 {
1202                         len += pcAce->AceSize;
1203                         pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1204                 }
1205 
1206                 /* slide them all backwards */
1207                 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1208                 pAcl->AceCount--;
1209         }
1210 
1211         TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1212 
1213         return status;
1214 }
1215 
1216 /******************************************************************************
1217  *  RtlAddAccessAllowedAce              [NTDLL.@]
1218  */
1219 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1220         IN OUT PACL pAcl,
1221         IN DWORD dwAceRevision,
1222         IN DWORD AccessMask,
1223         IN PSID pSid)
1224 {
1225         return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1226 }
1227  
1228 /******************************************************************************
1229  *  RtlAddAccessAllowedAceEx            [NTDLL.@]
1230  */
1231 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1232         IN OUT PACL pAcl,
1233         IN DWORD dwAceRevision,
1234         IN DWORD AceFlags,
1235         IN DWORD AccessMask,
1236         IN PSID pSid)
1237 {
1238    TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1239 
1240     return add_access_ace(pAcl, dwAceRevision, AceFlags,
1241                           AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1242 }
1243 
1244 /******************************************************************************
1245  *  RtlAddAccessDeniedAce               [NTDLL.@]
1246  */
1247 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1248         IN OUT PACL pAcl,
1249         IN DWORD dwAceRevision,
1250         IN DWORD AccessMask,
1251         IN PSID pSid)
1252 {
1253         return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1254 }
1255 
1256 /******************************************************************************
1257  *  RtlAddAccessDeniedAceEx             [NTDLL.@]
1258  */
1259 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1260         IN OUT PACL pAcl,
1261         IN DWORD dwAceRevision,
1262         IN DWORD AceFlags,
1263         IN DWORD AccessMask,
1264         IN PSID pSid)
1265 {
1266    TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1267 
1268     return add_access_ace(pAcl, dwAceRevision, AceFlags,
1269                           AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1270 }
1271 
1272 /************************************************************************** 
1273  *  RtlAddAuditAccessAce     [NTDLL.@] 
1274  */ 
1275 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1276     IN OUT PACL pAcl, 
1277     IN DWORD dwAceRevision, 
1278     IN DWORD dwAceFlags,
1279     IN DWORD dwAccessMask, 
1280     IN PSID pSid, 
1281     IN BOOL bAuditSuccess, 
1282     IN BOOL bAuditFailure) 
1283 { 
1284     TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1285           pSid,bAuditSuccess,bAuditFailure);
1286 
1287     if (bAuditSuccess)
1288         dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1289 
1290     if (bAuditFailure)
1291         dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1292 
1293     return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1294                           dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1295 } 
1296 
1297 /**************************************************************************
1298  *  RtlAddAuditAccessAce     [NTDLL.@]
1299  */
1300 NTSTATUS WINAPI RtlAddAuditAccessAce(
1301     IN OUT PACL pAcl,
1302     IN DWORD dwAceRevision,
1303     IN DWORD dwAccessMask,
1304     IN PSID pSid,
1305     IN BOOL bAuditSuccess,
1306     IN BOOL bAuditFailure)
1307 {
1308     return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1309 }
1310  
1311 /******************************************************************************
1312  *  RtlValidAcl         [NTDLL.@]
1313  */
1314 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1315 {
1316         BOOLEAN ret;
1317         TRACE("(%p)\n", pAcl);
1318 
1319         __TRY
1320         {
1321                 PACE_HEADER     ace;
1322                 int             i;
1323 
1324                 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1325                     pAcl->AclRevision > MAX_ACL_REVISION)
1326                     ret = FALSE;
1327                 else
1328                 {
1329                     ace = (PACE_HEADER)(pAcl+1);
1330                     ret = TRUE;
1331                     for (i=0;i<=pAcl->AceCount;i++)
1332                     {
1333                         if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1334                         {
1335                             ret = FALSE;
1336                             break;
1337                         }
1338                         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1339                     }
1340                 }
1341         }
1342         __EXCEPT_PAGE_FAULT
1343         {
1344                 WARN("(%p): invalid pointer!\n", pAcl);
1345                 return 0;
1346         }
1347         __ENDTRY
1348         return ret;
1349 }
1350 
1351 /******************************************************************************
1352  *  RtlGetAce           [NTDLL.@]
1353  */
1354 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1355 {
1356         PACE_HEADER ace;
1357 
1358         TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1359 
1360         if (dwAceIndex >= pAcl->AceCount)
1361                 return STATUS_INVALID_PARAMETER;
1362 
1363         ace = (PACE_HEADER)(pAcl + 1);
1364         for (;dwAceIndex;dwAceIndex--)
1365                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1366 
1367         *pAce = (LPVOID) ace;
1368 
1369         return STATUS_SUCCESS;
1370 }
1371 
1372 /*
1373  *      misc
1374  */
1375 
1376 /******************************************************************************
1377  *  RtlAdjustPrivilege          [NTDLL.@]
1378  *
1379  * Enables or disables a privilege from the calling thread or process.
1380  *
1381  * PARAMS
1382  *  Privilege     [I] Privilege index to change.
1383  *  Enable        [I] If TRUE, then enable the privilege otherwise disable.
1384  *  CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1385  *  Enabled       [O] Whether privilege was previously enabled or disabled.
1386  *
1387  * RETURNS
1388  *  Success: STATUS_SUCCESS.
1389  *  Failure: NTSTATUS code.
1390  *
1391  * SEE ALSO
1392  *  NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1393  *
1394  */
1395 NTSTATUS WINAPI
1396 RtlAdjustPrivilege(ULONG Privilege,
1397                    BOOLEAN Enable,
1398                    BOOLEAN CurrentThread,
1399                    PBOOLEAN Enabled)
1400 {
1401     TOKEN_PRIVILEGES NewState;
1402     TOKEN_PRIVILEGES OldState;
1403     ULONG ReturnLength;
1404     HANDLE TokenHandle;
1405     NTSTATUS Status;
1406 
1407     TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1408         CurrentThread ? "TRUE" : "FALSE", Enabled);
1409 
1410     if (CurrentThread)
1411     {
1412         Status = NtOpenThreadToken(GetCurrentThread(),
1413                                    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1414                                    FALSE,
1415                                    &TokenHandle);
1416     }
1417     else
1418     {
1419         Status = NtOpenProcessToken(GetCurrentProcess(),
1420                                     TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1421                                     &TokenHandle);
1422     }
1423 
1424     if (!NT_SUCCESS(Status))
1425     {
1426         WARN("Retrieving token handle failed (Status %x)\n", Status);
1427         return Status;
1428     }
1429 
1430     OldState.PrivilegeCount = 1;
1431 
1432     NewState.PrivilegeCount = 1;
1433     NewState.Privileges[0].Luid.LowPart = Privilege;
1434     NewState.Privileges[0].Luid.HighPart = 0;
1435     NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1436 
1437     Status = NtAdjustPrivilegesToken(TokenHandle,
1438                                      FALSE,
1439                                      &NewState,
1440                                      sizeof(TOKEN_PRIVILEGES),
1441                                      &OldState,
1442                                      &ReturnLength);
1443     NtClose (TokenHandle);
1444     if (Status == STATUS_NOT_ALL_ASSIGNED)
1445     {
1446         TRACE("Failed to assign all privileges\n");
1447         return STATUS_PRIVILEGE_NOT_HELD;
1448     }
1449     if (!NT_SUCCESS(Status))
1450     {
1451         WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1452         return Status;
1453     }
1454 
1455     if (OldState.PrivilegeCount == 0)
1456         *Enabled = Enable;
1457     else
1458         *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1459 
1460     return STATUS_SUCCESS;
1461 }
1462 
1463 /******************************************************************************
1464  *  RtlImpersonateSelf          [NTDLL.@]
1465  *
1466  * Makes an impersonation token that represents the process user and assigns
1467  * to the current thread.
1468  *
1469  * PARAMS
1470  *  ImpersonationLevel [I] Level at which to impersonate.
1471  *
1472  * RETURNS
1473  *  Success: STATUS_SUCCESS.
1474  *  Failure: NTSTATUS code.
1475  */
1476 NTSTATUS WINAPI
1477 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1478 {
1479     NTSTATUS Status;
1480     OBJECT_ATTRIBUTES ObjectAttributes;
1481     HANDLE ProcessToken;
1482     HANDLE ImpersonationToken;
1483 
1484     TRACE("(%08x)\n", ImpersonationLevel);
1485 
1486     Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1487                                  &ProcessToken);
1488     if (Status != STATUS_SUCCESS)
1489         return Status;
1490 
1491     InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1492 
1493     Status = NtDuplicateToken( ProcessToken,
1494                                TOKEN_IMPERSONATE,
1495                                &ObjectAttributes,
1496                                ImpersonationLevel,
1497                                TokenImpersonation,
1498                                &ImpersonationToken );
1499     if (Status != STATUS_SUCCESS)
1500     {
1501         NtClose( ProcessToken );
1502         return Status;
1503     }
1504 
1505     Status = NtSetInformationThread( GetCurrentThread(),
1506                                      ThreadImpersonationToken,
1507                                      &ImpersonationToken,
1508                                      sizeof(ImpersonationToken) );
1509 
1510     NtClose( ImpersonationToken );
1511     NtClose( ProcessToken );
1512 
1513     return Status;
1514 }
1515 
1516 /******************************************************************************
1517  *  NtAccessCheck               [NTDLL.@]
1518  *  ZwAccessCheck               [NTDLL.@]
1519  *
1520  * Checks that a user represented by a token is allowed to access an object
1521  * represented by a security descriptor.
1522  *
1523  * PARAMS
1524  *  SecurityDescriptor [I] The security descriptor of the object to check.
1525  *  ClientToken        [I] Token of the user accessing the object.
1526  *  DesiredAccess      [I] The desired access to the object.
1527  *  GenericMapping     [I] Mapping used to transform access rights in the SD to their specific forms.
1528  *  PrivilegeSet       [I/O] Privileges used during the access check.
1529  *  ReturnLength       [O] Number of bytes stored into PrivilegeSet.
1530  *  GrantedAccess      [O] The actual access rights granted.
1531  *  AccessStatus       [O] The status of the access check.
1532  *
1533  * RETURNS
1534  *  NTSTATUS code.
1535  *
1536  * NOTES
1537  *  DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1538  *  the maximum access rights allowed by the SD and returns them in
1539  *  GrantedAccess.
1540  *  The SecurityDescriptor must have a valid owner and groups present,
1541  *  otherwise the function will fail.
1542  */
1543 NTSTATUS WINAPI
1544 NtAccessCheck(
1545     PSECURITY_DESCRIPTOR SecurityDescriptor,
1546     HANDLE ClientToken,
1547     ACCESS_MASK DesiredAccess,
1548     PGENERIC_MAPPING GenericMapping,
1549     PPRIVILEGE_SET PrivilegeSet,
1550     PULONG ReturnLength,
1551     PULONG GrantedAccess,
1552     NTSTATUS *AccessStatus)
1553 {
1554     NTSTATUS status;
1555 
1556     TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1557         SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1558         PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1559 
1560     SERVER_START_REQ( access_check )
1561     {
1562         struct security_descriptor sd;
1563         PSID owner;
1564         PSID group;
1565         PACL sacl;
1566         PACL dacl;
1567         BOOLEAN defaulted, present;
1568         DWORD revision;
1569         SECURITY_DESCRIPTOR_CONTROL control;
1570 
1571         req->handle = wine_server_obj_handle( ClientToken );
1572         req->desired_access = DesiredAccess;
1573         req->mapping_read = GenericMapping->GenericRead;
1574         req->mapping_write = GenericMapping->GenericWrite;
1575         req->mapping_execute = GenericMapping->GenericExecute;
1576         req->mapping_all = GenericMapping->GenericAll;
1577 
1578         /* marshal security descriptor */
1579         RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1580         sd.control = control & ~SE_SELF_RELATIVE;
1581         RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1582         sd.owner_len = RtlLengthSid( owner );
1583         RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1584         sd.group_len = RtlLengthSid( group );
1585         RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1586         sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1587         RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1588         sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1589 
1590         wine_server_add_data( req, &sd, sizeof(sd) );
1591         wine_server_add_data( req, owner, sd.owner_len );
1592         wine_server_add_data( req, group, sd.group_len );
1593         wine_server_add_data( req, sacl, sd.sacl_len );
1594         wine_server_add_data( req, dacl, sd.dacl_len );
1595 
1596         wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1597 
1598         status = wine_server_call( req );
1599 
1600         *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1601         PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1602 
1603         if (status == STATUS_SUCCESS)
1604         {
1605             *AccessStatus = reply->access_status;
1606             *GrantedAccess = reply->access_granted;
1607         }
1608     }
1609     SERVER_END_REQ;
1610 
1611     return status;
1612 }
1613 
1614 /******************************************************************************
1615  *  NtSetSecurityObject         [NTDLL.@]
1616  *  ZwSetSecurityObject         [NTDLL.@]
1617  *
1618  * Sets specified parts of the object's security descriptor.
1619  *
1620  * PARAMS
1621  *  Handle              [I] Handle to the object to change security descriptor of.
1622  *  SecurityInformation [I] Specifies which parts of the security descriptor to set.
1623  *  SecurityDescriptor  [I] New parts of a security descriptor for the object.
1624  *
1625  * RETURNS
1626  *  NTSTATUS code.
1627  *
1628  */
1629 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1630         SECURITY_INFORMATION SecurityInformation,
1631         PSECURITY_DESCRIPTOR SecurityDescriptor)
1632 {
1633     NTSTATUS status;
1634     struct security_descriptor sd;
1635     PACL dacl = NULL, sacl = NULL;
1636     PSID owner = NULL, group = NULL;
1637     BOOLEAN defaulted, present;
1638     DWORD revision;
1639     SECURITY_DESCRIPTOR_CONTROL control;
1640 
1641     TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1642 
1643     if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1644 
1645     memset( &sd, 0, sizeof(sd) );
1646     status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1647     if (status != STATUS_SUCCESS) return status;
1648     sd.control = control & ~SE_SELF_RELATIVE;
1649 
1650     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1651     {
1652         status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1653         if (status != STATUS_SUCCESS) return status;
1654         if (!(sd.owner_len = RtlLengthSid( owner )))
1655             return STATUS_INVALID_SECURITY_DESCR;
1656     }
1657 
1658     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1659     {
1660         status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1661         if (status != STATUS_SUCCESS) return status;
1662         if (!(sd.group_len = RtlLengthSid( group )))
1663             return STATUS_INVALID_SECURITY_DESCR;
1664     }
1665 
1666     if (SecurityInformation & SACL_SECURITY_INFORMATION)
1667     {
1668         status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1669         if (status != STATUS_SUCCESS) return status;
1670         sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1671         sd.control |= SE_SACL_PRESENT;
1672     }
1673 
1674     if (SecurityInformation & DACL_SECURITY_INFORMATION)
1675     {
1676         status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1677         if (status != STATUS_SUCCESS) return status;
1678         sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1679         sd.control |= SE_DACL_PRESENT;
1680     }
1681 
1682     SERVER_START_REQ( set_security_object )
1683     {
1684         req->handle = wine_server_obj_handle( Handle );
1685         req->security_info = SecurityInformation;
1686 
1687         wine_server_add_data( req, &sd, sizeof(sd) );
1688         wine_server_add_data( req, owner, sd.owner_len );
1689         wine_server_add_data( req, group, sd.group_len );
1690         wine_server_add_data( req, sacl, sd.sacl_len );
1691         wine_server_add_data( req, dacl, sd.dacl_len );
1692         status = wine_server_call( req );
1693     }
1694     SERVER_END_REQ;
1695 
1696     return status;
1697 }
1698 
1699 /******************************************************************************
1700  * RtlConvertSidToUnicodeString (NTDLL.@)
1701  *
1702  * The returned SID is used to access the USER registry hive usually
1703  *
1704  * the native function returns something like
1705  * "S-1-5-21-0000000000-000000000-0000000000-500";
1706  */
1707 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1708        PUNICODE_STRING String,
1709        PSID pSid,
1710        BOOLEAN AllocateString)
1711 {
1712     static const WCHAR formatW[] = {'-','%','u',0};
1713     WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1714     WCHAR *p = buffer;
1715     const SID *sid = (const SID *)pSid;
1716     DWORD i, len;
1717 
1718     *p++ = 'S';
1719     p += sprintfW( p, formatW, sid->Revision );
1720     p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1721                                                    sid->IdentifierAuthority.Value[4] ),
1722                                          MAKEWORD( sid->IdentifierAuthority.Value[3],
1723                                                    sid->IdentifierAuthority.Value[2] )));
1724     for (i = 0; i < sid->SubAuthorityCount; i++)
1725         p += sprintfW( p, formatW, sid->SubAuthority[i] );
1726 
1727     len = (p + 1 - buffer) * sizeof(WCHAR);
1728 
1729     String->Length = len - sizeof(WCHAR);
1730     if (AllocateString)
1731     {
1732         String->MaximumLength = len;
1733         if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1734             return STATUS_NO_MEMORY;
1735     }
1736     else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1737 
1738     memcpy( String->Buffer, buffer, len );
1739     return STATUS_SUCCESS;
1740 }
1741 
1742 /******************************************************************************
1743  * RtlQueryInformationAcl (NTDLL.@)
1744  */
1745 NTSTATUS WINAPI RtlQueryInformationAcl(
1746     PACL pAcl,
1747     LPVOID pAclInformation,
1748     DWORD nAclInformationLength,
1749     ACL_INFORMATION_CLASS dwAclInformationClass)
1750 {
1751     NTSTATUS status = STATUS_SUCCESS;
1752 
1753     TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n", 
1754         pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1755 
1756     switch (dwAclInformationClass)
1757     {
1758         case AclRevisionInformation:
1759         {
1760             PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1761 
1762             if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1763                 status = STATUS_INVALID_PARAMETER;
1764             else
1765                 paclrev->AclRevision = pAcl->AclRevision;
1766 
1767             break;
1768         }
1769 
1770         case AclSizeInformation:
1771         {
1772             PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1773 
1774             if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1775                 status = STATUS_INVALID_PARAMETER;
1776             else
1777             {
1778                 paclsize->AceCount = pAcl->AceCount;
1779                 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1780                 if (pAcl->AclSize < paclsize->AclBytesInUse)
1781                 {
1782                     WARN("Acl uses %d bytes, but only has %d allocated!  Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1783                     paclsize->AclBytesFree = 0;
1784                     paclsize->AclBytesInUse = pAcl->AclSize;
1785                 }
1786                 else
1787                     paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1788             }
1789 
1790             break;
1791         }
1792 
1793         default:
1794             WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1795             status = STATUS_INVALID_PARAMETER;
1796     }
1797 
1798     return status;
1799 }
1800 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.