c9a61005e2f9bb33481fdaee834661c280487fe2
[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 BOOLEAN STDCALL
472 RtlValidSid(PSID Sid)
473 {
474    if ((Sid->Revision & 0xf) != 1)
475      {
476         return(FALSE);
477      }
478    if (Sid->SubAuthorityCount > 15)
479      {
480         return(FALSE);
481      }
482    return(TRUE);
483 }
484
485
486 ULONG STDCALL
487 RtlLengthRequiredSid(UCHAR SubAuthorityCount)
488 {
489   return(sizeof(SID) + (SubAuthorityCount - 1) * sizeof(ULONG));
490 }
491
492
493 NTSTATUS STDCALL
494 RtlInitializeSid(PSID Sid,
495                  PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
496                  UCHAR SubAuthorityCount)
497 {
498   Sid->Revision = 1;
499   Sid->SubAuthorityCount = SubAuthorityCount;
500   RtlCopyMemory(&Sid->IdentifierAuthority,
501                 IdentifierAuthority,
502                 sizeof(SID_IDENTIFIER_AUTHORITY));
503   return(STATUS_SUCCESS);
504 }
505
506
507 PULONG STDCALL
508 RtlSubAuthoritySid(PSID Sid,
509                    ULONG SubAuthority)
510 {
511   return(&Sid->SubAuthority[SubAuthority]);
512 }
513
514
515 PUCHAR STDCALL
516 RtlSubAuthorityCountSid(PSID Sid)
517 {
518   return(&Sid->SubAuthorityCount);
519 }
520
521
522 BOOLEAN STDCALL
523 RtlEqualSid(PSID Sid1,
524             PSID Sid2)
525 {
526    if (Sid1->Revision != Sid2->Revision)
527      {
528         return(FALSE);
529      }
530    if ((*RtlSubAuthorityCountSid(Sid1)) !=
531        (*RtlSubAuthorityCountSid(Sid2)))
532      {
533         return(FALSE);
534      }
535    if (memcmp(Sid1, Sid2, RtlLengthSid(Sid1)) != 0)
536      {
537         return(FALSE);
538      }
539    return(TRUE);
540 }
541
542
543 ULONG STDCALL
544 RtlLengthSid(PSID Sid)
545 {
546   return(sizeof(SID) + (Sid->SubAuthorityCount-1)*4);
547 }
548
549
550 NTSTATUS STDCALL
551 RtlCopySid(ULONG BufferLength,
552            PSID Dest,
553            PSID Src)
554 {
555    if (BufferLength < RtlLengthSid(Src))
556      {
557         return(STATUS_UNSUCCESSFUL);
558      }
559    memmove(Dest, Src, RtlLengthSid(Src));
560    return(STATUS_SUCCESS);
561 }
562
563
564 NTSTATUS STDCALL
565 RtlCopySidAndAttributesArray(ULONG Count,
566                              PSID_AND_ATTRIBUTES Src,
567                              ULONG SidAreaSize,
568                              PSID_AND_ATTRIBUTES Dest,
569                              PVOID SidArea,
570                              PVOID* RemainingSidArea,
571                              PULONG RemainingSidAreaSize)
572 {
573   ULONG Length;
574   ULONG i;
575
576   Length = SidAreaSize;
577
578   for (i=0; i<Count; i++)
579     {
580         if (RtlLengthSid(Src[i].Sid) > Length)
581           {
582              return(STATUS_BUFFER_TOO_SMALL);
583           }
584         Length = Length - RtlLengthSid(Src[i].Sid);
585         Dest[i].Sid = SidArea;
586         Dest[i].Attributes = Src[i].Attributes;
587         RtlCopySid(RtlLengthSid(Src[i].Sid), SidArea, Src[i].Sid);
588         SidArea = SidArea + RtlLengthSid(Src[i].Sid);
589     }
590   *RemainingSidArea = SidArea;
591   *RemainingSidAreaSize = Length;
592   return(STATUS_SUCCESS);
593 }
594
595
596 NTSTATUS STDCALL
597 RtlConvertSidToUnicodeString(PUNICODE_STRING String,
598                              PSID Sid,
599                              BOOLEAN AllocateString)
600 {
601    WCHAR Buffer[256];
602    PWSTR Ptr;
603    ULONG Length;
604    ULONG i;
605
606    if (!RtlValidSid(Sid))
607      return STATUS_INVALID_SID;
608
609    Ptr = Buffer;
610    Ptr += swprintf (Ptr,
611                     L"S-%u-",
612                     Sid->Revision);
613
614    if(!Sid->IdentifierAuthority.Value[0] &&
615       !Sid->IdentifierAuthority.Value[1])
616       {
617         Ptr += swprintf(Ptr,
618                         L"%u",
619                         (ULONG)Sid->IdentifierAuthority.Value[2] << 24 |
620                         (ULONG)Sid->IdentifierAuthority.Value[3] << 16 |
621                         (ULONG)Sid->IdentifierAuthority.Value[4] << 8 |
622                         (ULONG)Sid->IdentifierAuthority.Value[5]);
623      }
624    else
625      {
626         Ptr += swprintf(Ptr,
627                         L"0x%02hx%02hx%02hx%02hx%02hx%02hx",
628                         Sid->IdentifierAuthority.Value[0],
629                         Sid->IdentifierAuthority.Value[1],
630                         Sid->IdentifierAuthority.Value[2],
631                         Sid->IdentifierAuthority.Value[3],
632                         Sid->IdentifierAuthority.Value[4],
633                         Sid->IdentifierAuthority.Value[5]);
634      }
635
636    for (i = 0; i < Sid->SubAuthorityCount; i++)
637      {
638         Ptr += swprintf(Ptr,
639                         L"-%u",
640                         Sid->SubAuthority[i]);
641      }
642
643    Length = (Ptr - Buffer) * sizeof(WCHAR);
644
645    if (AllocateString)
646      {
647         String->Buffer = ExAllocatePool(NonPagedPool,
648                                         Length + sizeof(WCHAR));
649         if (String->Buffer == NULL)
650           return STATUS_NO_MEMORY;
651
652         String->MaximumLength = Length + sizeof(WCHAR);
653      }
654    else
655      {
656         if (Length > String->MaximumLength)
657           return STATUS_BUFFER_TOO_SMALL;
658      }
659    String->Length = Length;
660    memmove(String->Buffer,
661            Buffer,
662            Length);
663    if (Length < String->MaximumLength)
664      String->Buffer[Length] = 0;
665
666    return STATUS_SUCCESS;
667 }
668
669 /* EOF */