update for HEAD-2003091401
[reactos.git] / ntoskrnl / se / sid.c
1 /* $Id$
2  *
3  * COPYRIGHT:         See COPYING in the top level directory
4  * PROJECT:           ReactOS kernel
5  * PURPOSE:           Security manager
6  * FILE:              ntoskrnl/se/sid.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 #define TAG_SID    TAG('S', 'I', 'D', 'T')
20
21
22 /* GLOBALS ******************************************************************/
23
24 SID_IDENTIFIER_AUTHORITY SeNullSidAuthority = {SECURITY_NULL_SID_AUTHORITY};
25 SID_IDENTIFIER_AUTHORITY SeWorldSidAuthority = {SECURITY_WORLD_SID_AUTHORITY};
26 SID_IDENTIFIER_AUTHORITY SeLocalSidAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
27 SID_IDENTIFIER_AUTHORITY SeCreatorSidAuthority = {SECURITY_CREATOR_SID_AUTHORITY};
28 SID_IDENTIFIER_AUTHORITY SeNtSidAuthority = {SECURITY_NT_AUTHORITY};
29
30 PSID SeNullSid = NULL;
31 PSID SeWorldSid = NULL;
32 PSID SeLocalSid = NULL;
33 PSID SeCreatorOwnerSid = NULL;
34 PSID SeCreatorGroupSid = NULL;
35 PSID SeCreatorOwnerServerSid = NULL;
36 PSID SeCreatorGroupServerSid = NULL;
37 PSID SeNtAuthoritySid = NULL;
38 PSID SeDialupSid = NULL;
39 PSID SeNetworkSid = NULL;
40 PSID SeBatchSid = NULL;
41 PSID SeInteractiveSid = NULL;
42 PSID SeServiceSid = NULL;
43 PSID SeAnonymousLogonSid = NULL;
44 PSID SePrincipalSelfSid = NULL;
45 PSID SeLocalSystemSid = NULL;
46 PSID SeAuthenticatedUserSid = NULL;
47 PSID SeRestrictedCodeSid = NULL;
48 PSID SeAliasAdminsSid = NULL;
49 PSID SeAliasUsersSid = NULL;
50 PSID SeAliasGuestsSid = NULL;
51 PSID SeAliasPowerUsersSid = NULL;
52 PSID SeAliasAccountOpsSid = NULL;
53 PSID SeAliasSystemOpsSid = NULL;
54 PSID SeAliasPrintOpsSid = NULL;
55 PSID SeAliasBackupOpsSid = NULL;
56
57
58 /* FUNCTIONS ****************************************************************/
59
60
61 BOOLEAN
62 SepInitSecurityIDs(VOID)
63 {
64   ULONG SidLength0;
65   ULONG SidLength1;
66   ULONG SidLength2;
67   PULONG SubAuthority;
68
69   SidLength0 = RtlLengthRequiredSid(0);
70   SidLength1 = RtlLengthRequiredSid(1);
71   SidLength2 = RtlLengthRequiredSid(2);
72
73   /* create NullSid */
74   SeNullSid = ExAllocatePoolWithTag(NonPagedPool,
75                                     SidLength1,
76                                     TAG_SID);
77   if (SeNullSid == NULL)
78     return(FALSE);
79
80   RtlInitializeSid(SeNullSid,
81                    &SeNullSidAuthority,
82                    1);
83   SubAuthority = RtlSubAuthoritySid(SeNullSid,
84                                     0);
85   *SubAuthority = SECURITY_NULL_RID;
86
87   /* create WorldSid */
88   SeWorldSid = ExAllocatePoolWithTag(NonPagedPool,
89                                      SidLength1,
90                                      TAG_SID);
91   if (SeWorldSid == NULL)
92     return(FALSE);
93
94   RtlInitializeSid(SeWorldSid,
95                    &SeWorldSidAuthority,
96                    1);
97   SubAuthority = RtlSubAuthoritySid(SeWorldSid,
98                                     0);
99   *SubAuthority = SECURITY_WORLD_RID;
100
101   /* create LocalSid */
102   SeLocalSid = ExAllocatePoolWithTag(NonPagedPool,
103                                      SidLength1,
104                                      TAG_SID);
105   if (SeLocalSid == NULL)
106     return(FALSE);
107
108   RtlInitializeSid(SeLocalSid,
109                    &SeLocalSidAuthority,
110                    1);
111   SubAuthority = RtlSubAuthoritySid(SeLocalSid,
112                                     0);
113   *SubAuthority = SECURITY_LOCAL_RID;
114
115   /* create CreatorOwnerSid */
116   SeCreatorOwnerSid = ExAllocatePoolWithTag(NonPagedPool,
117                                             SidLength1,
118                                             TAG_SID);
119   if (SeCreatorOwnerSid == NULL)
120     return(FALSE);
121
122   RtlInitializeSid(SeCreatorOwnerSid,
123                    &SeCreatorSidAuthority,
124                    1);
125   SubAuthority = RtlSubAuthoritySid(SeCreatorOwnerSid,
126                                     0);
127   *SubAuthority = SECURITY_CREATOR_OWNER_RID;
128
129   /* create CreatorGroupSid */
130   SeCreatorGroupSid = ExAllocatePoolWithTag(NonPagedPool,
131                                             SidLength1,
132                                             TAG_SID);
133   if (SeCreatorGroupSid == NULL)
134     return(FALSE);
135
136   RtlInitializeSid(SeCreatorGroupSid,
137                    &SeCreatorSidAuthority,
138                    1);
139   SubAuthority = RtlSubAuthoritySid(SeCreatorGroupSid,
140                                     0);
141   *SubAuthority = SECURITY_CREATOR_GROUP_RID;
142
143   /* create CreatorOwnerServerSid */
144   SeCreatorOwnerServerSid = ExAllocatePoolWithTag(NonPagedPool,
145                                                   SidLength1,
146                                                   TAG_SID);
147   if (SeCreatorOwnerServerSid == NULL)
148     return(FALSE);
149
150   RtlInitializeSid(SeCreatorOwnerServerSid,
151                    &SeCreatorSidAuthority,
152                    1);
153   SubAuthority = RtlSubAuthoritySid(SeCreatorOwnerServerSid,
154                                     0);
155   *SubAuthority = SECURITY_CREATOR_OWNER_SERVER_RID;
156
157   /* create CreatorGroupServerSid */
158   SeCreatorGroupServerSid = ExAllocatePoolWithTag(NonPagedPool,
159                                                   SidLength1,
160                                                   TAG_SID);
161   if (SeCreatorGroupServerSid == NULL)
162     return(FALSE);
163
164   RtlInitializeSid(SeCreatorGroupServerSid,
165                    &SeCreatorSidAuthority,
166                    1);
167   SubAuthority = RtlSubAuthoritySid(SeCreatorGroupServerSid,
168                                     0);
169   *SubAuthority = SECURITY_CREATOR_GROUP_SERVER_RID;
170
171
172   /* create NtAuthoritySid */
173   SeNtAuthoritySid = ExAllocatePoolWithTag(NonPagedPool,
174                                            SidLength0,
175                                            TAG_SID);
176   if (SeNtAuthoritySid == NULL)
177     return(FALSE);
178
179   RtlInitializeSid(SeNtAuthoritySid,
180                    &SeNtSidAuthority,
181                    0);
182
183   /* create DialupSid */
184   SeDialupSid = ExAllocatePoolWithTag(NonPagedPool,
185                                       SidLength1,
186                                       TAG_SID);
187   if (SeDialupSid == NULL)
188     return(FALSE);
189
190   RtlInitializeSid(SeDialupSid,
191                    &SeNtSidAuthority,
192                    1);
193   SubAuthority = RtlSubAuthoritySid(SeDialupSid,
194                                     0);
195   *SubAuthority = SECURITY_DIALUP_RID;
196
197   /* create NetworkSid */
198   SeNetworkSid = ExAllocatePoolWithTag(NonPagedPool,
199                                        SidLength1,
200                                        TAG_SID);
201   if (SeNetworkSid == NULL)
202     return(FALSE);
203
204   RtlInitializeSid(SeNetworkSid,
205                    &SeNtSidAuthority,
206                    1);
207   SubAuthority = RtlSubAuthoritySid(SeNetworkSid,
208                                     0);
209   *SubAuthority = SECURITY_NETWORK_RID;
210
211   /* create BatchSid */
212   SeBatchSid = ExAllocatePoolWithTag(NonPagedPool,
213                                      SidLength1,
214                                      TAG_SID);
215   if (SeBatchSid == NULL)
216     return(FALSE);
217
218   RtlInitializeSid(SeBatchSid,
219                    &SeNtSidAuthority,
220                    1);
221   SubAuthority = RtlSubAuthoritySid(SeBatchSid,
222                                     0);
223   *SubAuthority = SECURITY_BATCH_RID;
224
225   /* create InteractiveSid */
226   SeInteractiveSid = ExAllocatePoolWithTag(NonPagedPool,
227                                            SidLength1,
228                                            TAG_SID);
229   if (SeInteractiveSid == NULL)
230     return(FALSE);
231
232   RtlInitializeSid(SeInteractiveSid,
233                    &SeNtSidAuthority,
234                    1);
235   SubAuthority = RtlSubAuthoritySid(SeInteractiveSid,
236                                     0);
237   *SubAuthority = SECURITY_INTERACTIVE_RID;
238
239   /* create ServiceSid */
240   SeServiceSid = ExAllocatePoolWithTag(NonPagedPool,
241                                        SidLength1,
242                                        TAG_SID);
243   if (SeServiceSid == NULL)
244     return(FALSE);
245
246   RtlInitializeSid(SeServiceSid,
247                    &SeNtSidAuthority,
248                    1);
249   SubAuthority = RtlSubAuthoritySid(SeServiceSid,
250                                     0);
251   *SubAuthority = SECURITY_SERVICE_RID;
252
253   /* create AnonymousLogonSid */
254   SeAnonymousLogonSid = ExAllocatePoolWithTag(NonPagedPool,
255                                               SidLength1,
256                                               TAG_SID);
257   if (SeAnonymousLogonSid == NULL)
258     return(FALSE);
259
260   RtlInitializeSid(SeAnonymousLogonSid,
261                    &SeNtSidAuthority,
262                    1);
263   SubAuthority = RtlSubAuthoritySid(SeAnonymousLogonSid,
264                                     0);
265   *SubAuthority = SECURITY_ANONYMOUS_LOGON_RID;
266
267   /* create PrincipalSelfSid */
268   SePrincipalSelfSid = ExAllocatePoolWithTag(NonPagedPool,
269                                              SidLength1,
270                                              TAG_SID);
271   if (SePrincipalSelfSid == NULL)
272     return(FALSE);
273
274   RtlInitializeSid(SePrincipalSelfSid,
275                    &SeNtSidAuthority,
276                    1);
277   SubAuthority = RtlSubAuthoritySid(SePrincipalSelfSid,
278                                     0);
279   *SubAuthority = SECURITY_PRINCIPAL_SELF_RID;
280
281   /* create LocalSystemSid */
282   SeLocalSystemSid = ExAllocatePoolWithTag(NonPagedPool,
283                                            SidLength1,
284                                            TAG_SID);
285   if (SeLocalSystemSid == NULL)
286     return(FALSE);
287
288   RtlInitializeSid(SeLocalSystemSid,
289                    &SeNtSidAuthority,
290                    1);
291   SubAuthority = RtlSubAuthoritySid(SeLocalSystemSid,
292                                     0);
293   *SubAuthority = SECURITY_LOCAL_SYSTEM_RID;
294
295   /* create AuthenticatedUserSid */
296   SeAuthenticatedUserSid = ExAllocatePoolWithTag(NonPagedPool,
297                                                  SidLength1,
298                                                  TAG_SID);
299   if (SeAuthenticatedUserSid == NULL)
300     return(FALSE);
301
302   RtlInitializeSid(SeAuthenticatedUserSid,
303                    &SeNtSidAuthority,
304                    1);
305   SubAuthority = RtlSubAuthoritySid(SeAuthenticatedUserSid,
306                                     0);
307   *SubAuthority = SECURITY_AUTHENTICATED_USER_RID;
308
309   /* create RestrictedCodeSid */
310   SeRestrictedCodeSid = ExAllocatePoolWithTag(NonPagedPool,
311                                               SidLength1,
312                                               TAG_SID);
313   if (SeRestrictedCodeSid == NULL)
314     return(FALSE);
315
316   RtlInitializeSid(SeRestrictedCodeSid,
317                    &SeNtSidAuthority,
318                    1);
319   SubAuthority = RtlSubAuthoritySid(SeRestrictedCodeSid,
320                                     0);
321   *SubAuthority = SECURITY_RESTRICTED_CODE_RID;
322
323   /* create AliasAdminsSid */
324   SeAliasAdminsSid = ExAllocatePoolWithTag(NonPagedPool,
325                                            SidLength2,
326                                            TAG_SID);
327   if (SeAliasAdminsSid == NULL)
328     return(FALSE);
329
330   RtlInitializeSid(SeAliasAdminsSid,
331                    &SeNtSidAuthority,
332                    2);
333   SubAuthority = RtlSubAuthoritySid(SeAliasAdminsSid,
334                                     0);
335   *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
336
337   SubAuthority = RtlSubAuthoritySid(SeAliasAdminsSid,
338                                     1);
339   *SubAuthority = DOMAIN_ALIAS_RID_ADMINS;
340
341   /* create AliasUsersSid */
342   SeAliasUsersSid = ExAllocatePoolWithTag(NonPagedPool,
343                                           SidLength2,
344                                           TAG_SID);
345   if (SeAliasUsersSid == NULL)
346     return(FALSE);
347
348   RtlInitializeSid(SeAliasUsersSid,
349                    &SeNtSidAuthority,
350                    2);
351   SubAuthority = RtlSubAuthoritySid(SeAliasUsersSid,
352                                     0);
353   *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
354
355   SubAuthority = RtlSubAuthoritySid(SeAliasUsersSid,
356                                     1);
357   *SubAuthority = DOMAIN_ALIAS_RID_USERS;
358
359   /* create AliasGuestsSid */
360   SeAliasGuestsSid = ExAllocatePoolWithTag(NonPagedPool,
361                                            SidLength2,
362                                            TAG_SID);
363   if (SeAliasGuestsSid == NULL)
364     return(FALSE);
365
366   RtlInitializeSid(SeAliasGuestsSid,
367                    &SeNtSidAuthority,
368                    2);
369   SubAuthority = RtlSubAuthoritySid(SeAliasGuestsSid,
370                                     0);
371   *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
372
373   SubAuthority = RtlSubAuthoritySid(SeAliasGuestsSid,
374                                     1);
375   *SubAuthority = DOMAIN_ALIAS_RID_GUESTS;
376
377   /* create AliasPowerUsersSid */
378   SeAliasPowerUsersSid = ExAllocatePoolWithTag(NonPagedPool,
379                                                SidLength2,
380                                                TAG_SID);
381   if (SeAliasPowerUsersSid == NULL)
382     return(FALSE);
383
384   RtlInitializeSid(SeAliasPowerUsersSid,
385                    &SeNtSidAuthority,
386                    2);
387   SubAuthority = RtlSubAuthoritySid(SeAliasPowerUsersSid,
388                                     0);
389   *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
390
391   SubAuthority = RtlSubAuthoritySid(SeAliasPowerUsersSid,
392                                     1);
393   *SubAuthority = DOMAIN_ALIAS_RID_POWER_USERS;
394
395   /* create AliasAccountOpsSid */
396   SeAliasAccountOpsSid = ExAllocatePoolWithTag(NonPagedPool,
397                                                SidLength2,
398                                                TAG_SID);
399   if (SeAliasAccountOpsSid == NULL)
400     return(FALSE);
401
402   RtlInitializeSid(SeAliasAccountOpsSid,
403                    &SeNtSidAuthority,
404                    2);
405   SubAuthority = RtlSubAuthoritySid(SeAliasAccountOpsSid,
406                                     0);
407   *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
408
409   SubAuthority = RtlSubAuthoritySid(SeAliasAccountOpsSid,
410                                     1);
411   *SubAuthority = DOMAIN_ALIAS_RID_ACCOUNT_OPS;
412
413   /* create AliasSystemOpsSid */
414   SeAliasSystemOpsSid = ExAllocatePoolWithTag(NonPagedPool,
415                                               SidLength2,
416                                               TAG_SID);
417   if (SeAliasSystemOpsSid == NULL)
418     return(FALSE);
419
420   RtlInitializeSid(SeAliasSystemOpsSid,
421                    &SeNtSidAuthority,
422                    2);
423   SubAuthority = RtlSubAuthoritySid(SeAliasSystemOpsSid,
424                                     0);
425   *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
426
427   SubAuthority = RtlSubAuthoritySid(SeAliasSystemOpsSid,
428                                     1);
429   *SubAuthority = DOMAIN_ALIAS_RID_SYSTEM_OPS;
430
431   /* create AliasPrintOpsSid */
432   SeAliasPrintOpsSid = ExAllocatePoolWithTag(NonPagedPool,
433                                              SidLength2,
434                                              TAG_SID);
435   if (SeAliasPrintOpsSid == NULL)
436     return(FALSE);
437
438   RtlInitializeSid(SeAliasPrintOpsSid,
439                    &SeNtSidAuthority,
440                    2);
441   SubAuthority = RtlSubAuthoritySid(SeAliasPrintOpsSid,
442                                     0);
443   *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
444
445   SubAuthority = RtlSubAuthoritySid(SeAliasPrintOpsSid,
446                                     1);
447   *SubAuthority = DOMAIN_ALIAS_RID_PRINT_OPS;
448
449   /* create AliasBackupOpsSid */
450   SeAliasBackupOpsSid = ExAllocatePoolWithTag(NonPagedPool,
451                                               SidLength2,
452                                               TAG_SID);
453   if (SeAliasBackupOpsSid == NULL)
454     return(FALSE);
455
456   RtlInitializeSid(SeAliasBackupOpsSid,
457                    &SeNtSidAuthority,
458                    2);
459   SubAuthority = RtlSubAuthoritySid(SeAliasBackupOpsSid,
460                                     0);
461   *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
462
463   SubAuthority = RtlSubAuthoritySid(SeAliasBackupOpsSid,
464                                     1);
465   *SubAuthority = DOMAIN_ALIAS_RID_BACKUP_OPS;
466
467   return(TRUE);
468 }
469
470
471 /*
472  * @implemented
473  */
474 BOOLEAN STDCALL
475 RtlValidSid(PSID Sid)
476 {
477    if ((Sid->Revision & 0xf) != 1)
478      {
479         return(FALSE);
480      }
481    if (Sid->SubAuthorityCount > 15)
482      {
483         return(FALSE);
484      }
485    return(TRUE);
486 }
487
488
489 /*
490  * @implemented
491  */
492 ULONG STDCALL
493 RtlLengthRequiredSid(UCHAR SubAuthorityCount)
494 {
495   return(sizeof(SID) + (SubAuthorityCount - 1) * sizeof(ULONG));
496 }
497
498
499 /*
500  * @implemented
501  */
502 NTSTATUS STDCALL
503 RtlInitializeSid(PSID Sid,
504                  PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
505                  UCHAR SubAuthorityCount)
506 {
507   Sid->Revision = 1;
508   Sid->SubAuthorityCount = SubAuthorityCount;
509   RtlCopyMemory(&Sid->IdentifierAuthority,
510                 IdentifierAuthority,
511                 sizeof(SID_IDENTIFIER_AUTHORITY));
512   return(STATUS_SUCCESS);
513 }
514
515
516 /*
517  * @implemented
518  */
519 PULONG STDCALL
520 RtlSubAuthoritySid(PSID Sid,
521                    ULONG SubAuthority)
522 {
523   return(&Sid->SubAuthority[SubAuthority]);
524 }
525
526
527 /*
528  * @implemented
529  */
530 PUCHAR STDCALL
531 RtlSubAuthorityCountSid(PSID Sid)
532 {
533   return(&Sid->SubAuthorityCount);
534 }
535
536
537 /*
538  * @implemented
539  */
540 BOOLEAN STDCALL
541 RtlEqualSid(PSID Sid1,
542             PSID Sid2)
543 {
544    if (Sid1->Revision != Sid2->Revision)
545      {
546         return(FALSE);
547      }
548    if ((*RtlSubAuthorityCountSid(Sid1)) !=
549        (*RtlSubAuthorityCountSid(Sid2)))
550      {
551         return(FALSE);
552      }
553    if (memcmp(Sid1, Sid2, RtlLengthSid(Sid1)) != 0)
554      {
555         return(FALSE);
556      }
557    return(TRUE);
558 }
559
560
561 /*
562  * @implemented
563  */
564 ULONG STDCALL
565 RtlLengthSid(PSID Sid)
566 {
567   return(sizeof(SID) + (Sid->SubAuthorityCount-1)*4);
568 }
569
570
571 /*
572  * @implemented
573  */
574 NTSTATUS STDCALL
575 RtlCopySid(ULONG BufferLength,
576            PSID Dest,
577            PSID Src)
578 {
579    if (BufferLength < RtlLengthSid(Src))
580      {
581         return(STATUS_UNSUCCESSFUL);
582      }
583    memmove(Dest, Src, RtlLengthSid(Src));
584    return(STATUS_SUCCESS);
585 }
586
587
588 NTSTATUS STDCALL
589 RtlCopySidAndAttributesArray(ULONG Count,
590                              PSID_AND_ATTRIBUTES Src,
591                              ULONG SidAreaSize,
592                              PSID_AND_ATTRIBUTES Dest,
593                              PVOID SidArea,
594                              PVOID* RemainingSidArea,
595                              PULONG RemainingSidAreaSize)
596 {
597   ULONG Length;
598   ULONG i;
599
600   Length = SidAreaSize;
601
602   for (i=0; i<Count; i++)
603     {
604         if (RtlLengthSid(Src[i].Sid) > Length)
605           {
606              return(STATUS_BUFFER_TOO_SMALL);
607           }
608         Length = Length - RtlLengthSid(Src[i].Sid);
609         Dest[i].Sid = SidArea;
610         Dest[i].Attributes = Src[i].Attributes;
611         RtlCopySid(RtlLengthSid(Src[i].Sid), SidArea, Src[i].Sid);
612         SidArea = SidArea + RtlLengthSid(Src[i].Sid);
613     }
614   *RemainingSidArea = SidArea;
615   *RemainingSidAreaSize = Length;
616   return(STATUS_SUCCESS);
617 }
618
619
620 /*
621  * @implemented
622  */
623 NTSTATUS STDCALL
624 RtlConvertSidToUnicodeString(PUNICODE_STRING String,
625                              PSID Sid,
626                              BOOLEAN AllocateString)
627 {
628    WCHAR Buffer[256];
629    PWSTR Ptr;
630    ULONG Length;
631    ULONG i;
632
633    if (!RtlValidSid(Sid))
634      return STATUS_INVALID_SID;
635
636    Ptr = Buffer;
637    Ptr += swprintf (Ptr,
638                     L"S-%u-",
639                     Sid->Revision);
640
641    if(!Sid->IdentifierAuthority.Value[0] &&
642       !Sid->IdentifierAuthority.Value[1])
643       {
644         Ptr += swprintf(Ptr,
645                         L"%u",
646                         (ULONG)Sid->IdentifierAuthority.Value[2] << 24 |
647                         (ULONG)Sid->IdentifierAuthority.Value[3] << 16 |
648                         (ULONG)Sid->IdentifierAuthority.Value[4] << 8 |
649                         (ULONG)Sid->IdentifierAuthority.Value[5]);
650      }
651    else
652      {
653         Ptr += swprintf(Ptr,
654                         L"0x%02hx%02hx%02hx%02hx%02hx%02hx",
655                         Sid->IdentifierAuthority.Value[0],
656                         Sid->IdentifierAuthority.Value[1],
657                         Sid->IdentifierAuthority.Value[2],
658                         Sid->IdentifierAuthority.Value[3],
659                         Sid->IdentifierAuthority.Value[4],
660                         Sid->IdentifierAuthority.Value[5]);
661      }
662
663    for (i = 0; i < Sid->SubAuthorityCount; i++)
664      {
665         Ptr += swprintf(Ptr,
666                         L"-%u",
667                         Sid->SubAuthority[i]);
668      }
669
670    Length = (Ptr - Buffer) * sizeof(WCHAR);
671
672    if (AllocateString)
673      {
674         String->Buffer = ExAllocatePool(NonPagedPool,
675                                         Length + sizeof(WCHAR));
676         if (String->Buffer == NULL)
677           return STATUS_NO_MEMORY;
678
679         String->MaximumLength = Length + sizeof(WCHAR);
680      }
681    else
682      {
683         if (Length > String->MaximumLength)
684           return STATUS_BUFFER_TOO_SMALL;
685      }
686    String->Length = Length;
687    memmove(String->Buffer,
688            Buffer,
689            Length);
690    if (Length < String->MaximumLength)
691      String->Buffer[Length/sizeof(WCHAR)] = 0;
692
693    return STATUS_SUCCESS;
694 }
695
696 /* EOF */