'sizeof type' is best avoided as it won't always compile (e.g. 'int
[wine] / dlls / ntdll / sec.c
1 /*
2  *      Security functions
3  *
4  *      Copyright 1996-1998 Marcus Meissner
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <ctype.h>
28 #include <math.h>
29 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 #endif
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "wine/exception.h"
36 #include "file.h"
37 #include "winnls.h"
38 #include "wine/debug.h"
39 #include "winerror.h"
40 #include "stackframe.h"
41
42 #include "winternl.h"
43 #include "winreg.h"
44 #include "ntdll_misc.h"
45 #include "excpt.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 Size;
396         Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
397         if ( SecurityDescriptor == NULL )
398                 return 0;
399
400         if ( SecurityDescriptor->Owner != NULL )
401                 Size += SecurityDescriptor->Owner->SubAuthorityCount;
402         if ( SecurityDescriptor->Group != NULL )
403                 Size += SecurityDescriptor->Group->SubAuthorityCount;
404
405
406         if ( SecurityDescriptor->Sacl != NULL )
407                 Size += SecurityDescriptor->Sacl->AclSize;
408         if ( SecurityDescriptor->Dacl != NULL )
409                 Size += SecurityDescriptor->Dacl->AclSize;
410
411         return Size;
412 }
413
414 /******************************************************************************
415  *  RtlGetDaclSecurityDescriptor                [NTDLL.@]
416  *
417  */
418 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
419         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
420         OUT PBOOLEAN lpbDaclPresent,
421         OUT PACL *pDacl,
422         OUT PBOOLEAN lpbDaclDefaulted)
423 {
424         TRACE("(%p,%p,%p,%p)\n",
425         pSecurityDescriptor, lpbDaclPresent, *pDacl, lpbDaclDefaulted);
426
427         if (pSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
428           return STATUS_UNKNOWN_REVISION ;
429
430         if ( (*lpbDaclPresent = (SE_DACL_PRESENT & pSecurityDescriptor->Control) ? 1 : 0) )
431         {
432           if ( SE_SELF_RELATIVE & pSecurityDescriptor->Control)
433           { *pDacl = (PACL) ((LPBYTE)pSecurityDescriptor + (DWORD)pSecurityDescriptor->Dacl);
434           }
435           else
436           { *pDacl = pSecurityDescriptor->Dacl;
437           }
438         }
439
440         *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & pSecurityDescriptor->Control ) ? 1 : 0);
441
442         return STATUS_SUCCESS;
443 }
444
445 /**************************************************************************
446  *  RtlSetDaclSecurityDescriptor                [NTDLL.@]
447  */
448 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
449         PSECURITY_DESCRIPTOR lpsd,
450         BOOLEAN daclpresent,
451         PACL dacl,
452         BOOLEAN dacldefaulted )
453 {
454         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
455                 return STATUS_UNKNOWN_REVISION;
456         if (lpsd->Control & SE_SELF_RELATIVE)
457                 return STATUS_INVALID_SECURITY_DESCR;
458
459         if (!daclpresent)
460         {       lpsd->Control &= ~SE_DACL_PRESENT;
461                 return TRUE;
462         }
463
464         lpsd->Control |= SE_DACL_PRESENT;
465         lpsd->Dacl = dacl;
466
467         if (dacldefaulted)
468                 lpsd->Control |= SE_DACL_DEFAULTED;
469         else
470                 lpsd->Control &= ~SE_DACL_DEFAULTED;
471
472         return STATUS_SUCCESS;
473 }
474
475 /******************************************************************************
476  *  RtlGetSaclSecurityDescriptor                [NTDLL.@]
477  *
478  */
479 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
480         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
481         OUT PBOOLEAN lpbSaclPresent,
482         OUT PACL *pSacl,
483         OUT PBOOLEAN lpbSaclDefaulted)
484 {
485         TRACE("(%p,%p,%p,%p)\n",
486         pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
487
488         if (pSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
489           return STATUS_UNKNOWN_REVISION ;
490
491         if ( (*lpbSaclPresent = (SE_SACL_PRESENT & pSecurityDescriptor->Control) ? 1 : 0) )
492         {
493           if ( SE_SELF_RELATIVE & pSecurityDescriptor->Control)
494           { *pSacl = (PACL) ((LPBYTE)pSecurityDescriptor + (DWORD)pSecurityDescriptor->Sacl);
495           }
496           else
497           { *pSacl = pSecurityDescriptor->Sacl;
498           }
499         }
500
501         *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & pSecurityDescriptor->Control ) ? 1 : 0);
502
503         return STATUS_SUCCESS;
504 }
505
506 /**************************************************************************
507  * RtlSetSaclSecurityDescriptor                 [NTDLL.@]
508  */
509 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
510         PSECURITY_DESCRIPTOR lpsd,
511         BOOLEAN saclpresent,
512         PACL sacl,
513         BOOLEAN sacldefaulted)
514 {
515         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
516                 return STATUS_UNKNOWN_REVISION;
517         if (lpsd->Control & SE_SELF_RELATIVE)
518                 return STATUS_INVALID_SECURITY_DESCR;
519         if (!saclpresent) {
520                 lpsd->Control &= ~SE_SACL_PRESENT;
521                 return 0;
522         }
523         lpsd->Control |= SE_SACL_PRESENT;
524         lpsd->Sacl = sacl;
525         if (sacldefaulted)
526                 lpsd->Control |= SE_SACL_DEFAULTED;
527         else
528                 lpsd->Control &= ~SE_SACL_DEFAULTED;
529         return STATUS_SUCCESS;
530 }
531
532 /**************************************************************************
533  * RtlGetOwnerSecurityDescriptor                [NTDLL.@]
534  */
535 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
536         PSECURITY_DESCRIPTOR SecurityDescriptor,
537         PSID *Owner,
538         PBOOLEAN OwnerDefaulted)
539 {
540         if ( !SecurityDescriptor  || !Owner || !OwnerDefaulted )
541                 return STATUS_INVALID_PARAMETER;
542
543         *Owner = SecurityDescriptor->Owner;
544         if ( *Owner != NULL )  {
545                 if ( SecurityDescriptor->Control & SE_OWNER_DEFAULTED )
546                         *OwnerDefaulted = TRUE;
547                 else
548                         *OwnerDefaulted = FALSE;
549         }
550         return STATUS_SUCCESS;
551 }
552
553 /**************************************************************************
554  *                 RtlSetOwnerSecurityDescriptor                [NTDLL.@]
555  */
556 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
557         PSECURITY_DESCRIPTOR lpsd,
558         PSID owner,
559         BOOLEAN ownerdefaulted)
560 {
561         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
562                 return STATUS_UNKNOWN_REVISION;
563         if (lpsd->Control & SE_SELF_RELATIVE)
564                 return STATUS_INVALID_SECURITY_DESCR;
565
566         lpsd->Owner = owner;
567         if (ownerdefaulted)
568                 lpsd->Control |= SE_OWNER_DEFAULTED;
569         else
570                 lpsd->Control &= ~SE_OWNER_DEFAULTED;
571         return STATUS_SUCCESS;
572 }
573
574 /**************************************************************************
575  *                 RtlSetGroupSecurityDescriptor                [NTDLL.@]
576  */
577 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
578         PSECURITY_DESCRIPTOR lpsd,
579         PSID group,
580         BOOLEAN groupdefaulted)
581 {
582         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
583                 return STATUS_UNKNOWN_REVISION;
584         if (lpsd->Control & SE_SELF_RELATIVE)
585                 return STATUS_INVALID_SECURITY_DESCR;
586
587         lpsd->Group = group;
588         if (groupdefaulted)
589                 lpsd->Control |= SE_GROUP_DEFAULTED;
590         else
591                 lpsd->Control &= ~SE_GROUP_DEFAULTED;
592         return STATUS_SUCCESS;
593 }
594 /**************************************************************************
595  *                 RtlGetGroupSecurityDescriptor                [NTDLL.@]
596  */
597 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
598         PSECURITY_DESCRIPTOR SecurityDescriptor,
599         PSID *Group,
600         PBOOLEAN GroupDefaulted)
601 {
602         if ( !SecurityDescriptor || !Group || !GroupDefaulted )
603                 return STATUS_INVALID_PARAMETER;
604
605         *Group = SecurityDescriptor->Group;
606         if ( *Group != NULL )  {
607                 if ( SecurityDescriptor->Control & SE_GROUP_DEFAULTED )
608                         *GroupDefaulted = TRUE;
609                 else
610                         *GroupDefaulted = FALSE;
611         }
612         return STATUS_SUCCESS;
613 }
614
615 /**************************************************************************
616  *                 RtlMakeSelfRelativeSD                [NTDLL.@]
617  */
618 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
619         IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
620         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
621         IN OUT LPDWORD lpdwBufferLength)
622 {
623         FIXME("(%p,%p,%p(%lu))\n", pAbsoluteSecurityDescriptor,
624         pSelfRelativeSecurityDescriptor, lpdwBufferLength,*lpdwBufferLength);
625         return STATUS_SUCCESS;
626 }
627
628 /*
629  *      access control list's
630  */
631
632 /**************************************************************************
633  *                 RtlCreateAcl                         [NTDLL.@]
634  *
635  * NOTES
636  *    This should return NTSTATUS
637  */
638 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
639 {
640         TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
641
642         if (rev!=ACL_REVISION)
643                 return STATUS_INVALID_PARAMETER;
644         if (size<sizeof(ACL))
645                 return STATUS_BUFFER_TOO_SMALL;
646         if (size>0xFFFF)
647                 return STATUS_INVALID_PARAMETER;
648
649         memset(acl,'\0',sizeof(ACL));
650         acl->AclRevision        = rev;
651         acl->AclSize            = size;
652         acl->AceCount           = 0;
653         return STATUS_SUCCESS;
654 }
655
656 /**************************************************************************
657  *                 RtlFirstFreeAce                      [NTDLL.@]
658  * looks for the AceCount+1 ACE, and if it is still within the alloced
659  * ACL, return a pointer to it
660  */
661 BOOLEAN WINAPI RtlFirstFreeAce(
662         PACL acl,
663         PACE_HEADER *x)
664 {
665         PACE_HEADER     ace;
666         int             i;
667
668         *x = 0;
669         ace = (PACE_HEADER)(acl+1);
670         for (i=0;i<acl->AceCount;i++) {
671                 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
672                         return 0;
673                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
674         }
675         if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
676                 return 0;
677         *x = ace;
678         return 1;
679 }
680
681 /**************************************************************************
682  *                 RtlAddAce                            [NTDLL.@]
683  */
684 NTSTATUS WINAPI RtlAddAce(
685         PACL acl,
686         DWORD rev,
687         DWORD xnrofaces,
688         PACE_HEADER acestart,
689         DWORD acelen)
690 {
691         PACE_HEADER     ace,targetace;
692         int             nrofaces;
693
694         if (acl->AclRevision != ACL_REVISION)
695                 return STATUS_INVALID_PARAMETER;
696         if (!RtlFirstFreeAce(acl,&targetace))
697                 return STATUS_INVALID_PARAMETER;
698         nrofaces=0;ace=acestart;
699         while (((DWORD)ace-(DWORD)acestart)<acelen) {
700                 nrofaces++;
701                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
702         }
703         if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
704                 return STATUS_INVALID_PARAMETER;
705         memcpy((LPBYTE)targetace,acestart,acelen);
706         acl->AceCount+=nrofaces;
707         return STATUS_SUCCESS;
708 }
709
710 /******************************************************************************
711  *  RtlAddAccessAllowedAce              [NTDLL.@]
712  */
713 NTSTATUS WINAPI RtlAddAccessAllowedAce(
714         IN OUT PACL pAcl,
715         IN DWORD dwAceRevision,
716         IN DWORD AccessMask,
717         IN PSID pSid)
718 {
719         return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
720 }
721  
722 /******************************************************************************
723  *  RtlAddAccessAllowedAceEx            [NTDLL.@]
724  */
725 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
726         IN OUT PACL pAcl,
727         IN DWORD dwAceRevision,
728         IN DWORD AceFlags,
729         IN DWORD AccessMask,
730         IN PSID pSid)
731 {
732         DWORD dwLengthSid;
733         ACCESS_ALLOWED_ACE * pAaAce;
734         DWORD dwSpaceLeft;
735
736         TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
737                 pAcl, dwAceRevision, AccessMask, pSid);
738
739         if (!RtlValidSid(pSid))
740                 return STATUS_INVALID_SID;
741         if (!RtlValidAcl(pAcl))
742                 return STATUS_INVALID_ACL;
743
744         dwLengthSid = RtlLengthSid(pSid);
745         if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
746                 return STATUS_INVALID_ACL;
747
748         if (!pAaAce)
749                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
750
751         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
752         if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
753                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
754
755         pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
756         pAaAce->Header.AceFlags = AceFlags;
757         pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
758         pAaAce->Mask = AccessMask;
759         pAcl->AceCount++;
760         RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
761         return STATUS_SUCCESS;
762 }
763
764 /******************************************************************************
765  *  RtlAddAccessDeniedAce               [NTDLL.@]
766  */
767 NTSTATUS WINAPI RtlAddAccessDeniedAce(
768         IN OUT PACL pAcl,
769         IN DWORD dwAceRevision,
770         IN DWORD AccessMask,
771         IN PSID pSid)
772 {
773         return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
774 }
775
776 /******************************************************************************
777  *  RtlAddAccessDeniedAceEx             [NTDLL.@]
778  */
779 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
780         IN OUT PACL pAcl,
781         IN DWORD dwAceRevision,
782         IN DWORD AceFlags,
783         IN DWORD AccessMask,
784         IN PSID pSid)
785 {
786         DWORD dwLengthSid;
787         DWORD dwSpaceLeft;
788         ACCESS_DENIED_ACE * pAdAce;
789
790         TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
791                 pAcl, dwAceRevision, AccessMask, pSid);
792
793         if (!RtlValidSid(pSid))
794                 return STATUS_INVALID_SID;
795         if (!RtlValidAcl(pAcl))
796                 return STATUS_INVALID_ACL;
797
798         dwLengthSid = RtlLengthSid(pSid);
799         if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
800                 return STATUS_INVALID_ACL;
801
802         if (!pAdAce)
803                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
804
805         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
806         if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
807                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
808
809         pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
810         pAdAce->Header.AceFlags = AceFlags;
811         pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
812         pAdAce->Mask = AccessMask;
813         pAcl->AceCount++;
814         RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
815         return STATUS_SUCCESS;
816 }
817
818 /******************************************************************************
819  *  RtlValidAcl         [NTDLL.@]
820  */
821 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
822 {
823         BOOLEAN ret;
824         TRACE("(%p)\n", pAcl);
825
826         __TRY
827         {
828                 PACE_HEADER     ace;
829                 int             i;
830
831                 if (pAcl->AclRevision != ACL_REVISION)
832                     ret = FALSE;
833                 else
834                 {
835                     ace = (PACE_HEADER)(pAcl+1);
836                     ret = TRUE;
837                     for (i=0;i<=pAcl->AceCount;i++)
838                     {
839                         if ((char *)ace > (char *)pAcl + pAcl->AclSize)
840                         {
841                             ret = FALSE;
842                             break;
843                         }
844                         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
845                     }
846                 }
847         }
848         __EXCEPT(page_fault)
849         {
850                 WARN("(%p): invalid pointer!\n", pAcl);
851                 return 0;
852         }
853         __ENDTRY
854         return ret;
855 }
856
857 /******************************************************************************
858  *  RtlGetAce           [NTDLL.@]
859  */
860 DWORD WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
861 {
862         PACE_HEADER ace;
863
864         TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
865
866         if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
867                 return STATUS_INVALID_PARAMETER;
868
869         ace = (PACE_HEADER)(pAcl + 1);
870         for (;dwAceIndex;dwAceIndex--)
871                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
872
873         *pAce = (LPVOID) ace;
874
875         return STATUS_SUCCESS;
876 }
877
878 /*
879  *      misc
880  */
881
882 /******************************************************************************
883  *  RtlAdjustPrivilege          [NTDLL.@]
884  */
885 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
886 {
887         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
888         return 0;
889 }
890
891 /******************************************************************************
892  *  RtlImpersonateSelf          [NTDLL.@]
893  */
894 BOOL WINAPI
895 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
896 {
897         FIXME("(%08x), stub\n", ImpersonationLevel);
898         return TRUE;
899 }
900
901 /******************************************************************************
902  *  NtAccessCheck               [NTDLL.@]
903  *  ZwAccessCheck               [NTDLL.@]
904  */
905 NTSTATUS WINAPI
906 NtAccessCheck(
907         IN PSECURITY_DESCRIPTOR SecurityDescriptor,
908         IN HANDLE ClientToken,
909         IN ACCESS_MASK DesiredAccess,
910         IN PGENERIC_MAPPING GenericMapping,
911         OUT PPRIVILEGE_SET PrivilegeSet,
912         OUT PULONG ReturnLength,
913         OUT PULONG GrantedAccess,
914         OUT PBOOLEAN AccessStatus)
915 {
916         FIXME("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
917           SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
918           PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
919         *AccessStatus = TRUE;
920         return STATUS_SUCCESS;
921 }
922
923 /******************************************************************************
924  *  NtSetSecurityObject         [NTDLL.@]
925  */
926 NTSTATUS WINAPI
927 NtSetSecurityObject(
928         IN HANDLE Handle,
929         IN SECURITY_INFORMATION SecurityInformation,
930         IN PSECURITY_DESCRIPTOR SecurityDescriptor)
931 {
932         FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
933         return STATUS_SUCCESS;
934 }
935
936 /******************************************************************************
937  * RtlGetControlSecurityDescriptor (NTDLL.@)
938  */
939
940 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
941         PSECURITY_DESCRIPTOR  pSecurityDescriptor,
942         PSECURITY_DESCRIPTOR_CONTROL pControl,
943         LPDWORD lpdwRevision)
944 {
945         FIXME("(%p,%p,%p),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
946         return STATUS_SUCCESS;
947 }
948
949 /******************************************************************************
950  * RtlConvertSidToUnicodeString (NTDLL.@)
951  *
952  * The returned SID is used to access the USER registry hive usually
953  *
954  * the native function returns something like
955  * "S-1-5-21-0000000000-000000000-0000000000-500";
956  */
957 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
958        PUNICODE_STRING String,
959        PSID Sid,
960        BOOLEAN AllocateString)
961 {
962         const char *p = wine_get_user_name();
963         NTSTATUS status;
964         ANSI_STRING AnsiStr;
965
966         FIXME("(%p %p %u)\n", String, Sid, AllocateString);
967
968         RtlInitAnsiString(&AnsiStr, p);
969         status = RtlAnsiStringToUnicodeString(String, &AnsiStr, AllocateString);
970
971         TRACE("%s (%u %u)\n",debugstr_w(String->Buffer),String->Length,String->MaximumLength);
972         return status;
973 }