00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "ntrtlp.h"
00022
#include "zwapi.h"
00023
#include "nturtl.h"
00024
#include "string.h"
00025
00026
#if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
00027
#pragma alloc_text(INIT,RtlCreateEnvironment )
00028
#pragma alloc_text(INIT,RtlDestroyEnvironment )
00029
#pragma alloc_text(INIT,RtlSetCurrentEnvironment )
00030
#pragma alloc_text(INIT,RtlQueryEnvironmentVariable_U )
00031
#pragma alloc_text(INIT,RtlSetEnvironmentVariable )
00032
#endif
00033
00034
NTSTATUS
00035 RtlCreateEnvironment(
00036 IN BOOLEAN CloneCurrentEnvironment OPTIONAL,
00037 OUT PVOID *Environment
00038 )
00039 {
00040
NTSTATUS Status;
00041 MEMORY_BASIC_INFORMATION MemoryInformation;
00042 PVOID pNew, pOld;
00043
00044
00045
00046
00047
00048
00049
00050 pNew =
NULL;
00051
if (!CloneCurrentEnvironment) {
00052 createEmptyEnvironment:
00053 MemoryInformation.RegionSize = 1;
00054
Status = ZwAllocateVirtualMemory( NtCurrentProcess(),
00055 &pNew,
00056 0,
00057 &MemoryInformation.RegionSize,
00058 MEM_COMMIT,
00059 PAGE_READWRITE
00060 );
00061
if (
NT_SUCCESS(
Status )) {
00062 *Environment = pNew;
00063 }
00064
00065
return(
Status );
00066 }
00067
00068
00069
00070
00071
00072
00073
RtlAcquirePebLock();
00074
00075
00076
00077
00078
00079
00080 pOld = NtCurrentPeb()->ProcessParameters->Environment;
00081
if (pOld ==
NULL) {
00082
RtlReleasePebLock();
00083
goto createEmptyEnvironment;
00084 }
00085
00086
try {
00087
00088
00089
00090
00091
00092
Status = ZwQueryVirtualMemory( NtCurrentProcess(),
00093 pOld,
00094 MemoryBasicInformation,
00095 &MemoryInformation,
00096
sizeof( MemoryInformation ),
00097
NULL
00098 );
00099
if (!
NT_SUCCESS(
Status )) {
00100
return(
Status );
00101 }
00102
00103
00104
00105
00106
00107
00108
Status = ZwAllocateVirtualMemory( NtCurrentProcess(),
00109 &pNew,
00110 0,
00111 &MemoryInformation.RegionSize,
00112 MEM_COMMIT,
00113 PAGE_READWRITE
00114 );
00115
if (!
NT_SUCCESS(
Status )) {
00116
return(
Status );
00117 }
00118
00119
00120
00121
00122
00123
00124 RtlMoveMemory( pNew, pOld, MemoryInformation.RegionSize );
00125 *Environment = pNew;
00126 }
00127 finally {
00128
if (AbnormalTermination()) {
00129
Status = STATUS_ACCESS_VIOLATION;
00130
if (pNew !=
NULL) {
00131 ZwFreeVirtualMemory( NtCurrentProcess(),
00132 &pNew,
00133 &MemoryInformation.RegionSize,
00134 MEM_RELEASE
00135 );
00136 }
00137 }
00138
00139
RtlReleasePebLock();
00140 }
00141
00142
return(
Status );
00143 }
00144
00145
00146
NTSTATUS
00147 RtlDestroyEnvironment(
00148 IN PVOID Environment
00149 )
00150 {
00151
NTSTATUS Status;
00152 SIZE_T RegionSize;
00153
00154
00155
00156
00157
00158 RegionSize = 0;
00159
Status = ZwFreeVirtualMemory( NtCurrentProcess(),
00160 &Environment,
00161 &RegionSize,
00162 MEM_RELEASE
00163 );
00164
00165
00166
00167
00168
return(
Status );
00169 }
00170
00171
00172
NTSTATUS
00173 RtlSetCurrentEnvironment(
00174 IN PVOID Environment,
00175 OUT PVOID *PreviousEnvironment OPTIONAL
00176 )
00177 {
00178
NTSTATUS Status;
00179 PVOID pOld;
00180
00181
00182
00183
00184
00185
00186
RtlAcquirePebLock();
00187
00188
Status = STATUS_SUCCESS;
00189
try {
00190
00191
00192
00193
00194
00195 pOld = NtCurrentPeb()->ProcessParameters->Environment;
00196
00197
00198
00199
00200
00201
00202
00203 NtCurrentPeb()->ProcessParameters->Environment = Environment;
00204
00205
00206
00207
00208
00209
00210
00211
if (ARGUMENT_PRESENT( PreviousEnvironment )) {
00212 *PreviousEnvironment = pOld;
00213 pOld =
NULL;
00214 }
00215 }
00216 finally {
00217
if (AbnormalTermination()) {
00218
Status = STATUS_ACCESS_VIOLATION;
00219 pOld =
NULL;
00220 }
00221 }
00222
00223
00224
00225
00226
00227
RtlReleasePebLock();
00228
00229
00230
00231
00232
00233
00234
if (pOld !=
NULL) {
00235
RtlDestroyEnvironment( pOld );
00236 }
00237
00238
00239
00240
00241
00242
return(
Status );
00243 }
00244
00245 BOOLEAN
RtlpEnvironCacheValid;
00246 UNICODE_STRING
RtlpEnvironCacheName;
00247 UNICODE_STRING
RtlpEnvironCacheValue;
00248
00249
NTSTATUS
00250 RtlQueryEnvironmentVariable_U(
00251 IN PVOID Environment OPTIONAL,
00252 IN PUNICODE_STRING Name,
00253 IN OUT PUNICODE_STRING Value
00254 )
00255 {
00256
NTSTATUS Status;
00257 UNICODE_STRING CurrentName;
00258 UNICODE_STRING CurrentValue;
00259 PWSTR p;
00260 PPEB Peb;
00261
00262
Status = STATUS_VARIABLE_NOT_FOUND;
00263 Peb = NtCurrentPeb();
00264
00265
try {
00266
if (ARGUMENT_PRESENT( Environment )) {
00267 p = Environment;
00268
if (*p == UNICODE_NULL) {
00269 leave;
00270 }
00271 }
00272
else {
00273
00274
00275
00276
00277
00278
RtlAcquirePebLock();
00279
00280
00281
00282
00283
00284
00285 p = Peb->ProcessParameters->Environment;
00286
00287 }
00288
#if DBG
00289
if (*p == UNICODE_NULL)
00290
DbgPrint(
"RTL: QEV - Empty Environment being searched: %08x\n", p);
00291
else if ((UCHAR)((*p) >> 8) !=
'\0')
00292
DbgPrint(
"RTL: QEV - Possible ANSI Environment being searched: %08x\n", p);
00293
#endif
00294
00295
if (
RtlpEnvironCacheValid && p == Peb->ProcessParameters->Environment ) {
00296
if (
RtlEqualUnicodeString(
Name, &
RtlpEnvironCacheName,
TRUE )) {
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 Value->Length =
RtlpEnvironCacheValue.Length;
00309
if (Value->MaximumLength >=
RtlpEnvironCacheValue.Length) {
00310 RtlMoveMemory( Value->Buffer,
00311
RtlpEnvironCacheValue.Buffer,
00312
RtlpEnvironCacheValue.Length
00313 );
00314
00315
00316
00317
00318
if (Value->MaximumLength >
RtlpEnvironCacheValue.Length) {
00319 Value->Buffer[
RtlpEnvironCacheValue.Length/
sizeof(WCHAR) ] =
L'\0';
00320 }
00321
00322
Status = STATUS_SUCCESS;
00323 }
00324
else {
00325
Status = STATUS_BUFFER_TOO_SMALL;
00326 }
00327
goto environcachehit;
00328 }
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
if (p !=
NULL)
while (*p) {
00341
00342
00343
00344
00345
00346 CurrentName.Buffer = p;
00347 CurrentName.Length = 0;
00348 CurrentName.MaximumLength = 0;
00349
while (*p) {
00350
00351
00352
00353
00354
00355
if (*p ==
L'=' && p != CurrentName.Buffer) {
00356 CurrentName.Length = (
USHORT)(p - CurrentName.Buffer)*
sizeof(WCHAR);
00357 CurrentName.MaximumLength = (
USHORT)(CurrentName.Length+
sizeof(WCHAR));
00358 CurrentValue.Buffer = ++p;
00359
00360
while(*p) {
00361 p++;
00362 }
00363 CurrentValue.Length = (
USHORT)(p - CurrentValue.Buffer)*
sizeof(WCHAR);
00364 CurrentValue.MaximumLength = (
USHORT)(CurrentValue.Length+
sizeof(WCHAR));
00365
00366
00367
00368
00369
00370
00371
break;
00372 }
00373
else {
00374 p++;
00375 }
00376 }
00377
00378
00379
00380
00381
00382
00383 p++;
00384
00385
00386
00387
00388
00389
00390
if (
RtlEqualUnicodeString(
Name, &CurrentName,
TRUE )) {
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 Value->Length = CurrentValue.Length;
00402
if (Value->MaximumLength >= CurrentValue.Length) {
00403 RtlMoveMemory( Value->Buffer,
00404 CurrentValue.Buffer,
00405 CurrentValue.Length
00406 );
00407
00408
00409
00410
00411
if (Value->MaximumLength > CurrentValue.Length) {
00412 Value->Buffer[ CurrentValue.Length/
sizeof(WCHAR) ] =
L'\0';
00413 }
00414
00415
if ( !Environment || Environment == Peb->ProcessParameters->Environment) {
00416
RtlpEnvironCacheValid =
TRUE;
00417
RtlpEnvironCacheName = CurrentName;
00418
RtlpEnvironCacheValue = CurrentValue;
00419 }
00420
00421
Status = STATUS_SUCCESS;
00422 }
00423
else {
00424
Status = STATUS_BUFFER_TOO_SMALL;
00425 }
00426
break;
00427 }
00428 }
00429 environcachehit:;
00430 }
00431 finally {
00432
00433
00434
00435
00436
if (AbnormalTermination()) {
00437
Status = STATUS_ACCESS_VIOLATION;
00438 }
00439
00440
00441
00442
00443
00444
if (!ARGUMENT_PRESENT( Environment )) {
00445
RtlReleasePebLock();
00446 }
00447 }
00448
00449
00450
00451
00452
00453
return(
Status );
00454 }
00455
00456
00457
NTSTATUS
00458 RtlSetEnvironmentVariable(
00459 IN OUT PVOID *Environment OPTIONAL,
00460 IN PUNICODE_STRING Name,
00461 IN PUNICODE_STRING Value OPTIONAL
00462 )
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 }