Branch setupapi
[reactos.git] / reactos / 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 INIT_FUNCTION
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 = (char*)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 */