00463 {
00464
NTSTATUS Status;
00465 MEMORY_BASIC_INFORMATION MemoryInformation;
00466 UNICODE_STRING CurrentName;
00467 UNICODE_STRING CurrentValue;
00468 PVOID pOld, pNew;
00469 ULONG
n,
Size;
00470 SIZE_T NewSize;
00471 LONG CompareResult;
00472 PWSTR p, pStart, pEnd;
00473
00474
00475
00476
00477
00478
n =
Name->Length /
sizeof( WCHAR );
00479
if (
n == 0) {
00480
return STATUS_INVALID_PARAMETER;
00481 }
00482
00483
try {
00484 p =
Name->Buffer;
00485
while (--
n) {
00486
if (*++p ==
L'=') {
00487
return STATUS_INVALID_PARAMETER;
00488 }
00489 }
00490 }
00491 except (EXCEPTION_EXECUTE_HANDLER) {
00492
return GetExceptionCode();
00493 }
00494
00495
RtlpEnvironCacheValid =
FALSE;
00496
Status = STATUS_VARIABLE_NOT_FOUND;
00497
if (ARGUMENT_PRESENT( Environment )) {
00498 pOld = *Environment;
00499 }
00500
else {
00501
00502
00503
00504
00505
00506
RtlAcquirePebLock();
00507
00508
00509
00510
00511
00512
00513 pOld = NtCurrentPeb()->ProcessParameters->Environment;
00514 }
00515 pNew =
NULL;
00516
00517
try {
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527 p = pOld;
00528 pEnd =
NULL;
00529
if (p !=
NULL)
while (*p) {
00530
00531
00532
00533
00534
00535 CurrentName.Buffer = p;
00536 CurrentName.Length = 0;
00537 CurrentName.MaximumLength = 0;
00538
while (*p) {
00539
00540
00541
00542
00543
00544
if (*p ==
L'=' && p != CurrentName.Buffer) {
00545 CurrentName.Length = (
USHORT)(p - CurrentName.Buffer) *
sizeof(WCHAR);
00546 CurrentName.MaximumLength = (
USHORT)(CurrentName.Length+
sizeof(WCHAR));
00547 CurrentValue.Buffer = ++p;
00548
00549
while(*p) {
00550 p++;
00551 }
00552 CurrentValue.Length = (
USHORT)(p - CurrentValue.Buffer) *
sizeof(WCHAR);
00553 CurrentValue.MaximumLength = (
USHORT)(CurrentValue.Length+
sizeof(WCHAR));
00554
00555
00556
00557
00558
00559
00560
break;
00561 }
00562
else {
00563 p++;
00564 }
00565 }
00566
00567
00568
00569
00570
00571
00572 p++;
00573
00574
00575
00576
00577
00578
00579
if (!(CompareResult =
RtlCompareUnicodeString( Name, &CurrentName, TRUE ))) {
00580
00581
00582
00583
00584
00585 pEnd = p;
00586
while (*pEnd) {
00587
while (*pEnd++) {
00588 }
00589 }
00590 pEnd++;
00591
00592
if (!ARGUMENT_PRESENT( Value )) {
00593
00594
00595
00596
00597
00598
00599 RtlMoveMemory( CurrentName.Buffer,
00600 p,
00601 (ULONG) ((pEnd - p)*
sizeof(WCHAR))
00602 );
00603
Status = STATUS_SUCCESS;
00604 }
00605
else
00606
if (Value->Length <= CurrentValue.Length) {
00607
00608
00609
00610
00611
00612
00613
00614 pStart = CurrentValue.Buffer;
00615 RtlMoveMemory( pStart, Value->Buffer, Value->Length );
00616 pStart += Value->Length/
sizeof(WCHAR);
00617 *pStart++ =
L'\0';
00618
00619 RtlMoveMemory( pStart, p,(ULONG)((pEnd - p)*
sizeof(WCHAR)) );
00620
Status = STATUS_SUCCESS;
00621 }
00622
else {
00623
00624
00625
00626
00627
00628
Status = ZwQueryVirtualMemory( NtCurrentProcess(),
00629 pOld,
00630 MemoryBasicInformation,
00631 &MemoryInformation,
00632
sizeof( MemoryInformation ),
00633 NULL
00634 );
00635
if (!
NT_SUCCESS( Status )) {
00636
return(
Status );
00637 }
00638
00639
00640
00641
00642
00643
00644
00645 NewSize = (pEnd - (PWSTR)pOld)*
sizeof(WCHAR) +
00646 Value->Length - CurrentValue.Length;
00647
if (NewSize >= MemoryInformation.RegionSize) {
00648
00649
00650
00651
00652
00653
00654
Status = ZwAllocateVirtualMemory( NtCurrentProcess(),
00655 &pNew,
00656 0,
00657 &NewSize,
00658 MEM_COMMIT,
00659 PAGE_READWRITE
00660 );
00661
if (!
NT_SUCCESS( Status )) {
00662
return(
Status );
00663 }
00664
00665
00666
00667
00668
00669
00670
Size = (ULONG) (CurrentValue.Buffer - (PWSTR)pOld);
00671 RtlMoveMemory( pNew, pOld, Size*
sizeof(WCHAR) );
00672 pStart = (PWSTR)pNew +
Size;
00673 RtlMoveMemory( pStart, Value->Buffer, Value->Length );
00674 pStart += Value->Length/
sizeof(WCHAR);
00675 *pStart++ =
L'\0';
00676 RtlMoveMemory( pStart, p,(ULONG)((pEnd - p)*
sizeof(WCHAR)));
00677
if (ARGUMENT_PRESENT( Environment ))
00678 *Environment = pNew;
00679
else {
00680 NtCurrentPeb()->ProcessParameters->Environment = pNew;
00681 NtCurrentPeb()->EnvironmentUpdateCount += 1;
00682 }
00683
00684 ZwFreeVirtualMemory( NtCurrentProcess(),
00685 &pOld,
00686 &MemoryInformation.RegionSize,
00687 MEM_RELEASE
00688 );
00689 pNew = pOld;
00690 }
00691
else {
00692 pStart = CurrentValue.Buffer + Value->Length/
sizeof(WCHAR) + 1;
00693 RtlMoveMemory( pStart, p,(ULONG)((pEnd - p)*
sizeof(WCHAR)));
00694 *--pStart =
L'\0';
00695
00696 RtlMoveMemory( pStart - Value->Length/
sizeof(WCHAR),
00697 Value->Buffer,
00698 Value->Length
00699 );
00700 }
00701 }
00702
00703
break;
00704 }
00705
else
00706
if (CompareResult < 0) {
00707
00708
00709
00710
00711
00712
00713
00714 p = CurrentName.Buffer;
00715
break;
00716 }
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
if (pEnd ==
NULL && ARGUMENT_PRESENT( Value )) {
00726
if (p !=
NULL) {
00727
00728
00729
00730
00731
00732 pEnd = p;
00733
while (*pEnd) {
00734
while (*pEnd++) {
00735 }
00736 }
00737 pEnd++;
00738
00739
00740
00741
00742
00743
00744
Status = ZwQueryVirtualMemory( NtCurrentProcess(),
00745 pOld,
00746 MemoryBasicInformation,
00747 &MemoryInformation,
00748
sizeof( MemoryInformation ),
00749 NULL
00750 );
00751
if (!
NT_SUCCESS( Status )) {
00752
return(
Status );
00753 }
00754
00755
00756
00757
00758
00759
00760
00761 NewSize = (pEnd - (PWSTR)pOld) *
sizeof(WCHAR) +
00762
Name->Length +
00763
sizeof(WCHAR) +
00764 Value->Length +
00765
sizeof(WCHAR);
00766 }
00767
else {
00768 NewSize =
Name->Length +
00769
sizeof(WCHAR) +
00770 Value->Length +
00771
sizeof(WCHAR);
00772 MemoryInformation.RegionSize = 0;
00773 }
00774
00775
if (NewSize >= MemoryInformation.RegionSize) {
00776
00777
00778
00779
00780
00781
00782
Status = ZwAllocateVirtualMemory( NtCurrentProcess(),
00783 &pNew,
00784 0,
00785 &NewSize,
00786 MEM_COMMIT,
00787 PAGE_READWRITE
00788 );
00789
if (!
NT_SUCCESS( Status )) {
00790
return(
Status );
00791 }
00792
00793
00794
00795
00796
00797
00798
if (p !=
NULL) {
00799
Size = (ULONG)(p - (PWSTR)pOld);
00800 RtlMoveMemory( pNew, pOld, Size*
sizeof(WCHAR) );
00801 }
00802
else {
00803
Size = 0;
00804 }
00805 pStart = (PWSTR)pNew +
Size;
00806 RtlMoveMemory( pStart,
Name->Buffer,
Name->Length );
00807 pStart +=
Name->Length/
sizeof(WCHAR);
00808 *pStart++ =
L'=';
00809 RtlMoveMemory( pStart, Value->Buffer, Value->Length );
00810 pStart += Value->Length/
sizeof(WCHAR);
00811 *pStart++ =
L'\0';
00812
if (p !=
NULL) {
00813 RtlMoveMemory( pStart, p,(ULONG)((pEnd - p)*
sizeof(WCHAR)) );
00814 }
00815
00816
if (ARGUMENT_PRESENT( Environment ))
00817 *Environment = pNew;
00818
else {
00819 NtCurrentPeb()->ProcessParameters->Environment = pNew;
00820 NtCurrentPeb()->EnvironmentUpdateCount += 1;
00821 }
00822 ZwFreeVirtualMemory( NtCurrentProcess(),
00823 &pOld,
00824 &MemoryInformation.RegionSize,
00825 MEM_RELEASE
00826 );
00827 }
00828
else {
00829 pStart = p +
Name->Length/
sizeof(WCHAR) + 1 + Value->Length/
sizeof(WCHAR) + 1;
00830 RtlMoveMemory( pStart, p,(ULONG)((pEnd - p)*
sizeof(WCHAR)) );
00831 RtlMoveMemory( p,
Name->Buffer,
Name->Length );
00832 p +=
Name->Length/
sizeof(WCHAR);
00833 *p++ =
L'=';
00834 RtlMoveMemory( p, Value->Buffer, Value->Length );
00835 p += Value->Length/
sizeof(WCHAR);
00836 *p++ =
L'\0';
00837 }
00838 }
00839 }
00840 finally {
00841
00842
00843
00844
00845
if (!ARGUMENT_PRESENT( Environment )) {
00846
RtlReleasePebLock();
00847 }
00848
00849
00850
00851
00852
00853
if (AbnormalTermination()) {
00854
return (STATUS_ACCESS_VIOLATION);
00855 }
00856 }
00857
00858
00859
00860
00861
00862
return(
Status );
00863 }