update for HEAD-2003091401
[reactos.git] / ntoskrnl / se / sd.c
1 /* $Id$
2  *
3  * COPYRIGHT:         See COPYING in the top level directory
4  * PROJECT:           ReactOS kernel
5  * PURPOSE:           Security manager
6  * FILE:              kernel/se/sd.c
7  * PROGRAMER:         David Welch <welch@cwcom.net>
8  * REVISION HISTORY:
9  *                 26/07/98: Added stubs for security functions
10  */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/se.h>
16
17 #include <internal/debug.h>
18
19 /* GLOBALS ******************************************************************/
20
21 PSECURITY_DESCRIPTOR SePublicDefaultSd = NULL;
22 PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd = NULL;
23 PSECURITY_DESCRIPTOR SePublicOpenSd = NULL;
24 PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd = NULL;
25 PSECURITY_DESCRIPTOR SeSystemDefaultSd = NULL;
26 PSECURITY_DESCRIPTOR SeUnrestrictedSd = NULL;
27
28 /* FUNCTIONS ***************************************************************/
29
30 BOOLEAN
31 SepInitSDs(VOID)
32 {
33   /* Create PublicDefaultSd */
34   SePublicDefaultSd = ExAllocatePool(NonPagedPool,
35                                      sizeof(SECURITY_DESCRIPTOR));
36   if (SePublicDefaultSd == NULL)
37     return(FALSE);
38
39   RtlCreateSecurityDescriptor(SePublicDefaultSd,
40                               SECURITY_DESCRIPTOR_REVISION);
41   RtlSetDaclSecurityDescriptor(SePublicDefaultSd,
42                                TRUE,
43                                SePublicDefaultDacl,
44                                FALSE);
45
46   /* Create PublicDefaultUnrestrictedSd */
47   SePublicDefaultUnrestrictedSd = ExAllocatePool(NonPagedPool,
48                                                  sizeof(SECURITY_DESCRIPTOR));
49   if (SePublicDefaultUnrestrictedSd == NULL)
50     return(FALSE);
51
52   RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd,
53                               SECURITY_DESCRIPTOR_REVISION);
54   RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd,
55                                TRUE,
56                                SePublicDefaultUnrestrictedDacl,
57                                FALSE);
58
59   /* Create PublicOpenSd */
60   SePublicOpenSd = ExAllocatePool(NonPagedPool,
61                                   sizeof(SECURITY_DESCRIPTOR));
62   if (SePublicOpenSd == NULL)
63     return(FALSE);
64
65   RtlCreateSecurityDescriptor(SePublicOpenSd,
66                               SECURITY_DESCRIPTOR_REVISION);
67   RtlSetDaclSecurityDescriptor(SePublicOpenSd,
68                                TRUE,
69                                SePublicOpenDacl,
70                                FALSE);
71
72   /* Create PublicOpenUnrestrictedSd */
73   SePublicOpenUnrestrictedSd = ExAllocatePool(NonPagedPool,
74                                               sizeof(SECURITY_DESCRIPTOR));
75   if (SePublicOpenUnrestrictedSd == NULL)
76     return(FALSE);
77
78   RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd,
79                               SECURITY_DESCRIPTOR_REVISION);
80   RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd,
81                                TRUE,
82                                SePublicOpenUnrestrictedDacl,
83                                FALSE);
84
85   /* Create SystemDefaultSd */
86   SeSystemDefaultSd = ExAllocatePool(NonPagedPool,
87                                      sizeof(SECURITY_DESCRIPTOR));
88   if (SeSystemDefaultSd == NULL)
89     return(FALSE);
90
91   RtlCreateSecurityDescriptor(SeSystemDefaultSd,
92                               SECURITY_DESCRIPTOR_REVISION);
93   RtlSetDaclSecurityDescriptor(SeSystemDefaultSd,
94                                TRUE,
95                                SeSystemDefaultDacl,
96                                FALSE);
97
98   /* Create UnrestrictedSd */
99   SeUnrestrictedSd = ExAllocatePool(NonPagedPool,
100                                     sizeof(SECURITY_DESCRIPTOR));
101   if (SeUnrestrictedSd == NULL)
102     return(FALSE);
103
104   RtlCreateSecurityDescriptor(SeUnrestrictedSd,
105                               SECURITY_DESCRIPTOR_REVISION);
106   RtlSetDaclSecurityDescriptor(SeUnrestrictedSd,
107                                TRUE,
108                                SeUnrestrictedDacl,
109                                FALSE);
110
111   return(TRUE);
112 }
113
114
115 /*
116  * @implemented
117  */
118 NTSTATUS STDCALL
119 RtlCreateSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
120                             ULONG Revision)
121 {
122   if (Revision != SECURITY_DESCRIPTOR_REVISION)
123     return(STATUS_UNSUCCESSFUL);
124
125   SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION;
126   SecurityDescriptor->Sbz1 = 0;
127   SecurityDescriptor->Control = 0;
128   SecurityDescriptor->Owner = NULL;
129   SecurityDescriptor->Group = NULL;
130   SecurityDescriptor->Sacl = NULL;
131   SecurityDescriptor->Dacl = NULL;
132
133   return(STATUS_SUCCESS);
134 }
135
136
137 /*
138  * @implemented
139  */
140 ULONG STDCALL
141 RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor)
142 {
143   PSID Owner;
144   PSID Group;
145   ULONG Length;
146   PACL Dacl;
147   PACL Sacl;
148
149   Length = sizeof(SECURITY_DESCRIPTOR);
150
151   if (SecurityDescriptor->Owner != NULL)
152     {
153       Owner = SecurityDescriptor->Owner;
154       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
155         {
156           Owner = (PSID)((ULONG)Owner +
157                          (ULONG)SecurityDescriptor);
158         }
159       Length = Length + ((sizeof(SID) + (Owner->SubAuthorityCount - 1) *
160                          sizeof(ULONG) + 3) & 0xfc);
161     }
162
163   if (SecurityDescriptor->Group != NULL)
164     {
165       Group = SecurityDescriptor->Group;
166       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
167         {
168           Group = (PSID)((ULONG)Group + (ULONG)SecurityDescriptor);
169         }
170       Length = Length + ((sizeof(SID) + (Group->SubAuthorityCount - 1) *
171                          sizeof(ULONG) + 3) & 0xfc);
172     }
173
174   if (SecurityDescriptor->Control & SE_DACL_PRESENT &&
175       SecurityDescriptor->Dacl != NULL)
176     {
177       Dacl = SecurityDescriptor->Dacl;
178       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
179         {
180           Dacl = (PACL)((ULONG)Dacl + (PVOID)SecurityDescriptor);
181         }
182       Length = Length + ((Dacl->AclSize + 3) & 0xfc);
183     }
184
185   if (SecurityDescriptor->Control & SE_SACL_PRESENT &&
186       SecurityDescriptor->Sacl != NULL)
187     {
188       Sacl = SecurityDescriptor->Sacl;
189       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
190         {
191           Sacl = (PACL)((ULONG)Sacl + (PVOID)SecurityDescriptor);
192         }
193       Length = Length + ((Sacl->AclSize + 3) & 0xfc);
194     }
195
196   return(Length);
197 }
198
199
200 /*
201  * @implemented
202  */
203 NTSTATUS STDCALL
204 RtlGetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
205                              PBOOLEAN DaclPresent,
206                              PACL* Dacl,
207                              PBOOLEAN DaclDefaulted)
208 {
209   if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
210     {
211       return(STATUS_UNSUCCESSFUL);
212     }
213
214   if (!(SecurityDescriptor->Control & SE_DACL_PRESENT))
215     {
216       *DaclPresent = FALSE;
217       return(STATUS_SUCCESS);
218     }
219   *DaclPresent = TRUE;
220
221   if (SecurityDescriptor->Dacl == NULL)
222     {
223       *Dacl = NULL;
224     }
225   else
226     {
227       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
228         {
229           *Dacl = (PACL)((ULONG)SecurityDescriptor->Dacl +
230                          (PVOID)SecurityDescriptor);
231         }
232       else
233         {
234           *Dacl = SecurityDescriptor->Dacl;
235         }
236     }
237
238   if (SecurityDescriptor->Control & SE_DACL_DEFAULTED)
239     {
240       *DaclDefaulted = TRUE;
241     }
242   else
243     {
244       *DaclDefaulted = FALSE;
245     }
246
247   return(STATUS_SUCCESS);
248 }
249
250
251 /*
252  * @implemented
253  */
254 NTSTATUS STDCALL
255 RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
256                              BOOLEAN DaclPresent,
257                              PACL Dacl,
258                              BOOLEAN DaclDefaulted)
259 {
260   if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
261     {
262       return(STATUS_UNSUCCESSFUL);
263     }
264
265   if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
266     {
267       return(STATUS_UNSUCCESSFUL);
268     }
269
270   if (!DaclPresent)
271     {
272       SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_DACL_PRESENT);
273       return(STATUS_SUCCESS);
274     }
275
276   SecurityDescriptor->Control = SecurityDescriptor->Control | SE_DACL_PRESENT;
277   SecurityDescriptor->Dacl = Dacl;
278   SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_DACL_DEFAULTED);
279
280   if (DaclDefaulted)
281     {
282       SecurityDescriptor->Control = SecurityDescriptor->Control | SE_DACL_DEFAULTED;
283     }
284
285   return(STATUS_SUCCESS);
286 }
287
288
289 /*
290  * @implemented
291  */
292 BOOLEAN STDCALL
293 RtlValidSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor)
294 {
295   PSID Owner;
296   PSID Group;
297   PACL Sacl;
298   PACL Dacl;
299
300   if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
301     {
302       return(FALSE);
303     }
304
305   Owner = SecurityDescriptor->Owner;
306   if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
307     {
308       Owner = (PSID)((ULONG)Owner + (ULONG)SecurityDescriptor);
309     }
310
311   if (!RtlValidSid(Owner))
312     {
313       return(FALSE);
314     }
315
316   Group = SecurityDescriptor->Group;
317   if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
318     {
319       Group = (PSID)((ULONG)Group + (ULONG)SecurityDescriptor);
320     }
321
322   if (!RtlValidSid(Group))
323     {
324       return(FALSE);
325     }
326
327   if (SecurityDescriptor->Control & SE_DACL_PRESENT &&
328       SecurityDescriptor->Dacl != NULL)
329     {
330       Dacl = SecurityDescriptor->Dacl;
331       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
332         {
333           Dacl = (PACL)((ULONG)Dacl + (ULONG)SecurityDescriptor);
334         }
335
336       if (!RtlValidAcl(Dacl))
337         {
338           return(FALSE);
339         }
340     }
341
342   if (SecurityDescriptor->Control & SE_SACL_PRESENT &&
343       SecurityDescriptor->Sacl != NULL)
344     {
345       Sacl = SecurityDescriptor->Sacl;
346       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
347         {
348           Sacl = (PACL)((ULONG)Sacl + (ULONG)SecurityDescriptor);
349         }
350
351       if (!RtlValidAcl(Sacl))
352         {
353           return(FALSE);
354         }
355     }
356
357   return(TRUE);
358 }
359
360
361 /*
362  * @implemented
363  */
364 NTSTATUS STDCALL
365 RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
366                               PSID Owner,
367                               BOOLEAN OwnerDefaulted)
368 {
369   if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
370     {
371       return(STATUS_UNSUCCESSFUL);
372     }
373
374   if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
375     {
376       return(STATUS_UNSUCCESSFUL);
377     }
378
379   SecurityDescriptor->Owner = Owner;
380   SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_OWNER_DEFAULTED);
381
382   if (OwnerDefaulted)
383     {
384       SecurityDescriptor->Control = SecurityDescriptor->Control | SE_OWNER_DEFAULTED;
385     }
386
387   return(STATUS_SUCCESS);
388 }
389
390
391 /*
392  * @implemented
393  */
394 NTSTATUS STDCALL
395 RtlGetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
396                               PSID* Owner,
397                               PBOOLEAN OwnerDefaulted)
398 {
399   if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
400     {
401       return(STATUS_UNSUCCESSFUL);
402     }
403
404   if (SecurityDescriptor->Owner != NULL)
405     {
406         if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
407           {
408              *Owner = (PSID)((ULONG)SecurityDescriptor->Owner +
409                              (PVOID)SecurityDescriptor);
410           }
411         else
412           {
413              *Owner = SecurityDescriptor->Owner;
414           }
415     }
416   else
417     {
418         *Owner = NULL;
419     }
420    if (SecurityDescriptor->Control & SE_OWNER_DEFAULTED)
421      {
422         *OwnerDefaulted = 1;
423      }
424    else
425      {
426         *OwnerDefaulted = 0;
427      }
428    return(STATUS_SUCCESS);
429 }
430
431
432 /*
433  * @implemented
434  */
435 NTSTATUS STDCALL
436 RtlSetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
437                               PSID Group,
438                               BOOLEAN GroupDefaulted)
439 {
440   if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
441     {
442       return(STATUS_UNSUCCESSFUL);
443     }
444
445   if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
446     {
447       return(STATUS_UNSUCCESSFUL);
448     }
449
450   SecurityDescriptor->Group = Group;
451   SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_GROUP_DEFAULTED);
452
453   if (GroupDefaulted)
454     {
455       SecurityDescriptor->Control = SecurityDescriptor->Control | SE_GROUP_DEFAULTED;
456     }
457
458   return(STATUS_SUCCESS);
459 }
460
461
462 /*
463  * @implemented
464  */
465 NTSTATUS STDCALL
466 RtlGetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
467                               PSID* Group,
468                               PBOOLEAN GroupDefaulted)
469 {
470   if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
471     {
472       return(STATUS_UNSUCCESSFUL);
473     }
474
475   if (SecurityDescriptor->Group != NULL)
476     {
477       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
478         {
479           *Group = (PSID)((ULONG)SecurityDescriptor->Group +
480                           (PVOID)SecurityDescriptor);
481         }
482       else
483         {
484           *Group = SecurityDescriptor->Group;
485         }
486     }
487   else
488     {
489       *Group = NULL;
490     }
491
492   if (SecurityDescriptor->Control & SE_GROUP_DEFAULTED)
493     {
494       *GroupDefaulted = TRUE;
495     }
496   else
497     {
498       *GroupDefaulted = FALSE;
499     }
500
501   return(STATUS_SUCCESS);
502 }
503
504
505 /*
506  * @implemented
507  */
508 NTSTATUS STDCALL
509 RtlGetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
510                              PBOOLEAN SaclPresent,
511                              PACL *Sacl,
512                              PBOOLEAN SaclDefaulted)
513 {
514   if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
515     {
516       return(STATUS_UNSUCCESSFUL);
517     }
518
519   if (!(SecurityDescriptor->Control & SE_SACL_PRESENT))
520     {
521       *SaclPresent = FALSE;
522       return(STATUS_SUCCESS);
523     }
524   *SaclPresent = TRUE;
525
526   if (SecurityDescriptor->Sacl == NULL)
527     {
528       *Sacl = NULL;
529     }
530   else
531     {
532       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
533         {
534           *Sacl = (PACL)((ULONG)SecurityDescriptor->Sacl +
535                          (PVOID)SecurityDescriptor);
536         }
537       else
538         {
539           *Sacl = SecurityDescriptor->Sacl;
540         }
541     }
542
543   if (SecurityDescriptor->Control & SE_SACL_DEFAULTED)
544     {
545       *SaclDefaulted = TRUE;
546     }
547   else
548     {
549       *SaclDefaulted = FALSE;
550     }
551
552   return(STATUS_SUCCESS);
553 }
554
555
556 /*
557  * @implemented
558  */
559 NTSTATUS STDCALL
560 RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
561                              BOOLEAN SaclPresent,
562                              PACL Sacl,
563                              BOOLEAN SaclDefaulted)
564 {
565   if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION)
566     {
567       return(STATUS_UNSUCCESSFUL);
568     }
569   if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
570     {
571       return(STATUS_UNSUCCESSFUL);
572     }
573
574   if (!SaclPresent)
575     {
576       SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_SACL_PRESENT);
577       return(STATUS_SUCCESS);
578     }
579
580   SecurityDescriptor->Control = SecurityDescriptor->Control | SE_SACL_PRESENT;
581   SecurityDescriptor->Sacl = Sacl;
582   SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_SACL_DEFAULTED);
583
584   if (SaclDefaulted)
585     {
586       SecurityDescriptor->Control = SecurityDescriptor->Control | SE_SACL_DEFAULTED;
587     }
588
589   return(STATUS_SUCCESS);
590 }
591
592
593 static VOID
594 RtlpQuerySecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor,
595                             PSID* Owner,
596                             PULONG OwnerLength,
597                             PSID* Group,
598                             PULONG GroupLength,
599                             PACL* Dacl,
600                             PULONG DaclLength,
601                             PACL* Sacl,
602                             PULONG SaclLength)
603 {
604   if (SecurityDescriptor->Owner == NULL)
605     {
606       *Owner = NULL;
607     }
608   else
609     {
610       *Owner = SecurityDescriptor->Owner;
611       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
612         {
613           *Owner = (PSID)((ULONG)*Owner + (ULONG)SecurityDescriptor);
614         }
615     }
616
617   if (*Owner != NULL)
618     {
619       *OwnerLength = (RtlLengthSid(*Owner) + 3) & ~3;
620     }
621   else
622     {
623       *OwnerLength = 0;
624     }
625
626   if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
627       SecurityDescriptor->Dacl != NULL)
628     {
629       *Dacl = SecurityDescriptor->Dacl;
630       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
631         {
632           *Dacl = (PACL)((ULONG)*Dacl + (ULONG)SecurityDescriptor);
633         }
634     }
635   else
636     {
637       *Dacl = NULL;
638     }
639
640   if (*Dacl != NULL)
641     {
642       *DaclLength = ((*Dacl)->AclSize + 3) & ~3;
643     }
644   else
645     {
646       *DaclLength = 0;
647     }
648
649   if (SecurityDescriptor->Group != NULL)
650     {
651       *Group = NULL;
652     }
653   else
654     {
655       *Group = SecurityDescriptor->Group;
656       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
657         {
658           *Group = (PSID)((ULONG)*Group + (ULONG)SecurityDescriptor);
659         }
660     }
661
662   if (*Group != NULL)
663     {
664       *GroupLength = (RtlLengthSid(*Group) + 3) & ~3;
665     }
666   else
667     {
668       *GroupLength = 0;
669     }
670
671   if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
672       SecurityDescriptor->Sacl != NULL)
673     {
674       *Sacl = SecurityDescriptor->Sacl;
675       if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
676         {
677           *Sacl = (PACL)((ULONG)*Sacl + (ULONG)SecurityDescriptor);
678         }
679     }
680   else
681     {
682       *Sacl = NULL;
683     }
684
685   if (*Sacl != NULL)
686     {
687       *SaclLength = ((*Sacl)->AclSize + 3) & ~3;
688     }
689 }
690
691
692 /*
693  * @implemented
694  */
695 NTSTATUS STDCALL
696 RtlAbsoluteToSelfRelativeSD(PSECURITY_DESCRIPTOR AbsSD,
697                             PSECURITY_DESCRIPTOR RelSD,
698                             PULONG BufferLength)
699 {
700   PSID Owner;
701   PSID Group;
702   PACL Sacl;
703   PACL Dacl;
704   ULONG OwnerLength;
705   ULONG GroupLength;
706   ULONG SaclLength;
707   ULONG DaclLength;
708   ULONG TotalLength;
709   ULONG Current;
710
711   if (AbsSD->Control & SE_SELF_RELATIVE)
712     {
713       return(STATUS_BAD_DESCRIPTOR_FORMAT);
714     }
715
716   RtlpQuerySecurityDescriptor(AbsSD,
717                               &Owner,
718                               &OwnerLength,
719                               &Group,
720                               &GroupLength,
721                               &Dacl,
722                               &DaclLength,
723                               &Sacl,
724                               &SaclLength);
725
726   TotalLength = OwnerLength + GroupLength + SaclLength +
727                 DaclLength + sizeof(SECURITY_DESCRIPTOR);
728   if (*BufferLength < TotalLength)
729     {
730       return(STATUS_BUFFER_TOO_SMALL);
731     }
732
733   RtlZeroMemory(RelSD,
734                 TotalLength);
735   memmove(RelSD,
736           AbsSD,
737           sizeof(SECURITY_DESCRIPTOR));
738   Current = (ULONG)RelSD + sizeof(SECURITY_DESCRIPTOR);
739
740   if (SaclLength != 0)
741     {
742       memmove((PVOID)Current,
743               Sacl,
744               SaclLength);
745       RelSD->Sacl = (PACL)((ULONG)Current - (ULONG)RelSD);
746       Current += SaclLength;
747     }
748
749   if (DaclLength != 0)
750     {
751       memmove((PVOID)Current,
752               Dacl,
753               DaclLength);
754       RelSD->Dacl = (PACL)((ULONG)Current - (ULONG)RelSD);
755       Current += DaclLength;
756     }
757
758   if (OwnerLength != 0)
759     {
760       memmove((PVOID)Current,
761               Owner,
762               OwnerLength);
763       RelSD->Owner = (PSID)((ULONG)Current - (ULONG)RelSD);
764       Current += OwnerLength;
765     }
766
767   if (GroupLength != 0)
768     {
769       memmove((PVOID)Current,
770               Group,
771               GroupLength);
772       RelSD->Group = (PSID)((ULONG)Current - (ULONG)RelSD);
773     }
774
775   RelSD->Control |= SE_SELF_RELATIVE;
776
777   return(STATUS_SUCCESS);
778 }
779
780 /* EOF */