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 <ctype.h>
00023
00024
NTSTATUS
00025
RtlpGetRegistryHandle(
00026 IN ULONG RelativeTo,
00027 IN PCWSTR KeyName,
00028 IN BOOLEAN WriteAccess,
00029 OUT PHANDLE Key
00030 );
00031
00032
NTSTATUS
00033
RtlpQueryRegistryDirect(
00034 IN ULONG ValueType,
00035 IN PVOID ValueData,
00036 IN ULONG ValueLength,
00037 IN OUT PVOID Destination
00038 );
00039
00040
NTSTATUS
00041
RtlpCallQueryRegistryRoutine(
00042 IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
00043 IN PKEY_VALUE_FULL_INFORMATION KeyValueInformation,
00044 IN OUT PULONG PKeyValueInfoLength,
00045 IN PVOID Context,
00046 IN PVOID Environment OPTIONAL
00047 );
00048
00049 PVOID
00050
RtlpAllocDeallocQueryBuffer(
00051 IN OUT SIZE_T *PAllocLength OPTIONAL,
00052 IN PVOID OldKeyValueInformation OPTIONAL,
00053 IN SIZE_T OldAllocLength OPTIONAL,
00054 OUT NTSTATUS *pStatus OPTIONAL
00055 );
00056
00057
NTSTATUS
00058
RtlpInitCurrentUserString(
00059 OUT PUNICODE_STRING UserString
00060 );
00061
00062
00063
NTSTATUS
00064
RtlpGetTimeZoneInfoHandle(
00065 IN BOOLEAN WriteAccess,
00066 OUT PHANDLE Key
00067 );
00068
00069
#if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
00070
#pragma alloc_text(PAGE,RtlpGetRegistryHandle)
00071
#pragma alloc_text(PAGE,RtlpQueryRegistryDirect)
00072
#pragma alloc_text(PAGE,RtlpCallQueryRegistryRoutine)
00073
#pragma alloc_text(PAGE,RtlpAllocDeallocQueryBuffer)
00074
#pragma alloc_text(PAGE,RtlQueryRegistryValues)
00075
#pragma alloc_text(PAGE,RtlWriteRegistryValue)
00076
#pragma alloc_text(PAGE,RtlCheckRegistryKey)
00077
#pragma alloc_text(PAGE,RtlCreateRegistryKey)
00078
#pragma alloc_text(PAGE,RtlDeleteRegistryValue)
00079
#pragma alloc_text(PAGE,RtlExpandEnvironmentStrings_U)
00080
#pragma alloc_text(PAGE,RtlGetNtGlobalFlags)
00081
#pragma alloc_text(PAGE,RtlpInitCurrentUserString)
00082
#pragma alloc_text(PAGE,RtlOpenCurrentUser)
00083
#pragma alloc_text(PAGE,RtlpGetTimeZoneInfoHandle)
00084
#pragma alloc_text(PAGE,RtlQueryTimeZoneInformation)
00085
#pragma alloc_text(PAGE,RtlSetTimeZoneInformation)
00086
#pragma alloc_text(PAGE,RtlSetActiveTimeBias)
00087
#endif
00088
00089 extern const PWSTR
RtlpRegistryPaths[ RTL_REGISTRY_MAXIMUM ];
00090
00091
NTSTATUS
00092 RtlpGetRegistryHandle(
00093 IN ULONG RelativeTo,
00094 IN PCWSTR KeyName,
00095 IN BOOLEAN WriteAccess,
00096 OUT PHANDLE Key
00097 )
00098 {
00099
NTSTATUS Status;
00100 OBJECT_ATTRIBUTES
ObjectAttributes;
00101 WCHAR
KeyPathBuffer[ MAXIMUM_FILENAME_LENGTH+6 ];
00102 UNICODE_STRING
KeyPath;
00103 UNICODE_STRING CurrentUserKeyPath;
00104 BOOLEAN OptionalPath;
00105
00106
if (RelativeTo & RTL_REGISTRY_HANDLE) {
00107 *
Key = (HANDLE)
KeyName;
00108
return STATUS_SUCCESS;
00109 }
00110
00111
if (RelativeTo & RTL_REGISTRY_OPTIONAL) {
00112 RelativeTo &= ~RTL_REGISTRY_OPTIONAL;
00113 OptionalPath =
TRUE;
00114 }
else {
00115 OptionalPath =
FALSE;
00116 }
00117
00118
if (RelativeTo >= RTL_REGISTRY_MAXIMUM) {
00119
return STATUS_INVALID_PARAMETER;
00120 }
00121
00122
KeyPath.Buffer =
KeyPathBuffer;
00123
KeyPath.Length = 0;
00124
KeyPath.MaximumLength =
sizeof(
KeyPathBuffer );
00125
if (RelativeTo != RTL_REGISTRY_ABSOLUTE) {
00126
if (RelativeTo == RTL_REGISTRY_USER &&
00127
NT_SUCCESS(
RtlFormatCurrentUserKeyPath( &CurrentUserKeyPath ) )
00128 ) {
00129
Status =
RtlAppendUnicodeStringToString( &
KeyPath, &CurrentUserKeyPath );
00130
RtlFreeUnicodeString( &CurrentUserKeyPath );
00131 }
else {
00132
Status =
RtlAppendUnicodeToString( &
KeyPath,
RtlpRegistryPaths[ RelativeTo ] );
00133 }
00134
00135
if (!
NT_SUCCESS(
Status )) {
00136
return Status;
00137 }
00138
00139
Status =
RtlAppendUnicodeToString( &
KeyPath,
L"\\" );
00140
if (!
NT_SUCCESS(
Status )) {
00141
return Status;
00142 }
00143 }
00144
00145
Status =
RtlAppendUnicodeToString( &
KeyPath,
KeyName );
00146
if (!
NT_SUCCESS(
Status )) {
00147
return Status;
00148 }
00149
00150
00151 InitializeObjectAttributes( &
ObjectAttributes,
00152 &
KeyPath,
00153 OBJ_CASE_INSENSITIVE,
00154
NULL,
00155
NULL
00156 );
00157
#ifdef NTOS_KERNEL_RUNTIME
00158
00159
00160
00161
00162
ObjectAttributes.Attributes |= OBJ_KERNEL_HANDLE;
00163
#endif
00164
if (WriteAccess) {
00165
Status = ZwCreateKey(
Key,
00166 GENERIC_WRITE,
00167 &
ObjectAttributes,
00168 0,
00169 (PUNICODE_STRING)
NULL,
00170 0,
00171
NULL
00172 );
00173 }
else {
00174
Status = ZwOpenKey(
Key,
00175 MAXIMUM_ALLOWED | GENERIC_READ,
00176 &
ObjectAttributes
00177 );
00178 }
00179
00180
return Status;
00181 }
00182
00183
00184
00185
00186 #define MAX_USTRING ( sizeof(WCHAR) * (MAXUSHORT/sizeof(WCHAR)) )
00187
00188
00189
00190
00191
00192 #define MAX_NONNULL_USTRING ( MAX_USTRING - sizeof(UNICODE_NULL) )
00193
00194
00195
00196
00197
00198
00199
NTSTATUS
00200 RtlpQueryRegistryDirect(
00201 IN ULONG ValueType,
00202 IN PVOID ValueData,
00203 IN ULONG ValueLength,
00204 IN OUT PVOID Destination
00205 )
00206 {
00207
00208
if (ValueType == REG_SZ ||
00209 ValueType == REG_EXPAND_SZ ||
00210 ValueType == REG_MULTI_SZ
00211 ) {
00212 PUNICODE_STRING DestinationString;
00213
USHORT TruncValueLength;
00214
00215
00216
00217
00218
if ( ValueLength <=
MAX_USTRING ) {
00219 TruncValueLength = (
USHORT)ValueLength;
00220 }
else {
00221 TruncValueLength =
MAX_USTRING;
00222
00223
00224
00225
00226
00227
DbgPrint(
"RtlpQueryRegistryDirect: truncating SZ Value length: %x -> %x\n",
00228 ValueLength, TruncValueLength);
00229
00230 }
00231
00232 DestinationString = (PUNICODE_STRING)Destination;
00233
if (DestinationString->Buffer ==
NULL) {
00234
00235 DestinationString->Buffer =
RtlAllocateStringRoutine( TruncValueLength );
00236
if (!DestinationString->Buffer) {
00237
return STATUS_NO_MEMORY;
00238 }
00239 DestinationString->MaximumLength = TruncValueLength;
00240 }
else if (TruncValueLength > DestinationString->MaximumLength) {
00241
return STATUS_BUFFER_TOO_SMALL;
00242 }
00243
00244 RtlCopyMemory( DestinationString->Buffer, ValueData, TruncValueLength );
00245 DestinationString->Length = (TruncValueLength -
sizeof(UNICODE_NULL));
00246
00247 }
else if (ValueLength <=
sizeof( ULONG )) {
00248 RtlCopyMemory( Destination, ValueData, ValueLength );
00249
00250 }
else {
00251 PULONG DestinationLength;
00252
00253 DestinationLength = (PULONG)Destination;
00254
if ((LONG)*DestinationLength < 0) {
00255 ULONG
n = -(LONG)*DestinationLength;
00256
00257
if (
n < ValueLength) {
00258
return STATUS_BUFFER_TOO_SMALL;
00259 }
00260 RtlCopyMemory( DestinationLength, ValueData, ValueLength );
00261
00262 }
else {
00263
if (*DestinationLength < (2 *
sizeof(*DestinationLength) + ValueLength)) {
00264
return STATUS_BUFFER_TOO_SMALL;
00265 }
00266
00267 *DestinationLength++ = ValueLength;
00268 *DestinationLength++ = ValueType;
00269 RtlCopyMemory( DestinationLength, ValueData, ValueLength );
00270 }
00271 }
00272
00273
return STATUS_SUCCESS;
00274 }
00275
00276 #define QuadAlignPtr(P) ( \
00277
(PVOID)((((ULONG_PTR)(P)) + 7) & (-8)) \
00278
)
00279
00280
NTSTATUS
00281 RtlpCallQueryRegistryRoutine(
00282 IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
00283 IN PKEY_VALUE_FULL_INFORMATION KeyValueInformation,
00284 IN OUT PULONG PKeyValueInfoLength,
00285 IN PVOID Context,
00286 IN PVOID Environment OPTIONAL
00287 )
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 {
00335
NTSTATUS Status;
00336 ULONG ValueType;
00337 PWSTR
ValueName;
00338 PVOID ValueData;
00339 ULONG ValueLength;
00340 PWSTR s;
00341 PCHAR FreeMem;
00342 PCHAR EndFreeMem;
00343 LONG FreeMemSize;
00344 ULONG KeyValueInfoLength;
00345
int retries;
00346
00347
00348
00349
00350
00351 KeyValueInfoLength = *PKeyValueInfoLength;
00352 *PKeyValueInfoLength = 0;
00353
00354
00355
00356
00357
00358 FreeMem = (PCHAR)KeyValueInformation;
00359 FreeMemSize = KeyValueInfoLength;
00360 EndFreeMem = FreeMem + FreeMemSize;
00361
00362
if (KeyValueInformation->Type == REG_NONE ||
00363 (KeyValueInformation->DataLength == 0 &&
00364 KeyValueInformation->Type == QueryTable->DefaultType)
00365 ) {
00366
00367
00368
00369
00370
00371
if (QueryTable->DefaultType == REG_NONE) {
00372
00373
00374
00375
00376
if ( QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED ) {
00377
return STATUS_OBJECT_NAME_NOT_FOUND;
00378 }
else {
00379
return STATUS_SUCCESS;
00380 }
00381 }
00382
00383
00384
00385
00386
00387
00388
ValueName = QueryTable->Name,
00389 ValueType = QueryTable->DefaultType;
00390 ValueData = QueryTable->DefaultData;
00391 ValueLength = QueryTable->DefaultLength;
00392
if (ValueLength == 0) {
00393
00394
00395
00396
00397
00398
00399 s = (PWSTR)ValueData;
00400
if (ValueType == REG_SZ || ValueType == REG_EXPAND_SZ) {
00401
while (*s++ != UNICODE_NULL) {
00402 }
00403 ValueLength = (ULONG)((PCHAR)s - (PCHAR)ValueData);
00404
00405 }
else if (ValueType == REG_MULTI_SZ) {
00406
while (*s != UNICODE_NULL) {
00407
while (*s++ != UNICODE_NULL) {
00408 }
00409 }
00410 ValueLength = (ULONG)((PCHAR)s - (PCHAR)ValueData) +
sizeof( UNICODE_NULL );
00411 }
00412 }
00413
00414 }
else {
00415
if (!(QueryTable->Flags & RTL_QUERY_REGISTRY_DIRECT)) {
00416 LONG ValueSpaceNeeded;
00417
00418
00419
00420
00421
00422
00423
if (KeyValueInformation->DataLength) {
00424 FreeMem += KeyValueInformation->DataOffset +
00425 KeyValueInformation->DataLength;
00426 }
else {
00427 FreeMem += FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION,
Name) +
00428 KeyValueInformation->NameLength;
00429 }
00430 FreeMem = (PCHAR)
QuadAlignPtr(FreeMem);
00431 FreeMemSize = (ULONG) (EndFreeMem - FreeMem);
00432
00433
00434
00435
00436
00437
00438 ValueSpaceNeeded = KeyValueInformation->NameLength +
sizeof(UNICODE_NULL);
00439
if ( FreeMemSize < ValueSpaceNeeded ) {
00440
00441 *PKeyValueInfoLength = (ULONG)(((PCHAR)FreeMem - (PCHAR)KeyValueInformation) + ValueSpaceNeeded);
00442
return STATUS_BUFFER_TOO_SMALL;
00443 }
00444
00445
00446
00447
00448
00449
ValueName = (PWSTR)FreeMem;
00450 RtlCopyMemory(
ValueName,
00451 KeyValueInformation->Name,
00452 KeyValueInformation->NameLength
00453 );
00454 *(PWSTR)((PCHAR)
ValueName + KeyValueInformation->NameLength) = UNICODE_NULL;
00455
00456
00457
00458
00459
00460 FreeMem += ValueSpaceNeeded;
00461 FreeMem = (PCHAR)
QuadAlignPtr(FreeMem);
00462 FreeMemSize = (LONG) (EndFreeMem - FreeMem);
00463
00464 }
else {
00465
ValueName = QueryTable->Name;
00466 }
00467
00468
00469
00470
00471
00472 ValueType = KeyValueInformation->Type;
00473 ValueData = (PCHAR)KeyValueInformation + KeyValueInformation->DataOffset;
00474 ValueLength = KeyValueInformation->DataLength;
00475 }
00476
00477
00478
00479
00480
00481
00482
if (!(QueryTable->Flags & RTL_QUERY_REGISTRY_NOEXPAND)) {
00483
if (ValueType == REG_MULTI_SZ) {
00484 PWSTR ValueEnd;
00485
00486
00487
00488
00489
00490
00491
00492
Status = STATUS_SUCCESS;
00493 ValueEnd = (PWSTR)((PCHAR)ValueData + ValueLength) -
sizeof(UNICODE_NULL);
00494 s = (PWSTR)ValueData;
00495
while (s < ValueEnd) {
00496
while (*s++ != UNICODE_NULL) {
00497 }
00498
00499 ValueLength = (ULONG)((PCHAR)s - (PCHAR)ValueData);
00500
if (QueryTable->Flags & RTL_QUERY_REGISTRY_DIRECT) {
00501
Status =
RtlpQueryRegistryDirect( REG_SZ,
00502 ValueData,
00503 ValueLength,
00504 QueryTable->EntryContext
00505 );
00506 (PUNICODE_STRING)(QueryTable->EntryContext) += 1;
00507
00508 }
else {
00509
Status = (QueryTable->QueryRoutine)(
ValueName,
00510 REG_SZ,
00511 ValueData,
00512 ValueLength,
00513 Context,
00514 QueryTable->EntryContext
00515 );
00516 }
00517
00518
00519
00520
00521
if (
Status == STATUS_BUFFER_TOO_SMALL) {
00522
Status = STATUS_SUCCESS;
00523 }
00524
00525
if (!
NT_SUCCESS(
Status )) {
00526
break;
00527 }
00528
00529 ValueData = (PVOID)s;
00530 }
00531
00532
return Status;
00533 }
00534
00535
00536
00537
00538
00539
if ((ValueType == REG_EXPAND_SZ) &&
00540 (ValueLength >=
sizeof(WCHAR)) &&
00541 (ValueLength <=
MAX_NONNULL_USTRING)) {
00542
00543
00544
00545
00546
00547 UNICODE_STRING Source;
00548 UNICODE_STRING Destination;
00549 PWCHAR Src;
00550 ULONG SrcLength;
00551 ULONG RequiredLength;
00552 BOOLEAN PercentFound;
00553
00554
00555
00556
00557
00558 PercentFound =
FALSE;
00559 SrcLength = ValueLength -
sizeof(WCHAR);
00560 Src = (PWSTR)ValueData;
00561
while (SrcLength) {
00562
if (*Src ==
L'%') {
00563 PercentFound =
TRUE;
00564
break;
00565 }
00566 Src++;
00567 SrcLength -=
sizeof(WCHAR);
00568 }
00569
00570
if ( PercentFound ) {
00571 Source.Buffer = (PWSTR)ValueData;
00572 Source.MaximumLength = (
USHORT)ValueLength;
00573 Source.Length = (
USHORT)(Source.MaximumLength -
sizeof(UNICODE_NULL));
00574 Destination.Buffer = (PWSTR)FreeMem;
00575 Destination.Length = 0;
00576
00577
if (FreeMemSize <= 0) {
00578 Destination.MaximumLength = 0;
00579 }
else if (FreeMemSize <=
MAX_USTRING) {
00580 Destination.MaximumLength = (
USHORT)FreeMemSize;
00581 Destination.Buffer[FreeMemSize/
sizeof(WCHAR) - 1] = UNICODE_NULL;
00582 }
else {
00583 Destination.MaximumLength =
MAX_USTRING;
00584 Destination.Buffer[
MAX_USTRING/
sizeof(WCHAR) - 1] = UNICODE_NULL;
00585 }
00586
00587
Status =
RtlExpandEnvironmentStrings_U( Environment,
00588 &Source,
00589 &Destination,
00590 &RequiredLength
00591 );
00592 ValueType = REG_SZ;
00593
00594
if (
NT_SUCCESS(
Status) ) {
00595 ValueData = Destination.Buffer;
00596 ValueLength = Destination.Length +
sizeof( UNICODE_NULL );
00597 }
else {
00598
if (
Status == STATUS_BUFFER_TOO_SMALL) {
00599 *PKeyValueInfoLength = (ULONG)((PCHAR)FreeMem - (PCHAR)KeyValueInformation) + RequiredLength;
00600 }
00601
00602
if (
Status == STATUS_BUFFER_TOO_SMALL) {
00603
DbgPrint(
"RTL: Expand variables for %wZ failed - Status == %lx Size %x > %x <%x>\n",
00604 &Source,
Status, *PKeyValueInfoLength, KeyValueInfoLength,
00605 Destination.MaximumLength );
00606 }
else {
00607
DbgPrint(
"RTL: Expand variables for %wZ failed - Status == %lx\n", &Source,
Status );
00608 }
00609
00610
if (
Status == STATUS_BUFFER_OVERFLOW ||
00611
Status == STATUS_BUFFER_TOO_SMALL &&
00612 ( Destination.MaximumLength ==
MAX_USTRING
00613 || RequiredLength >
MAX_NONNULL_USTRING ) ) {
00614
00615
00616
00617
00618
DbgPrint(
"RtlpCallQueryRegistryRoutine: skipping expansion. Status=%x RequiredLength=%x\n",
00619
Status, RequiredLength);
00620
00621 }
else {
00622
return Status;
00623 }
00624 }
00625 }
00626 }
00627
00628
else if (ValueType == REG_EXPAND_SZ && ValueLength >
MAX_NONNULL_USTRING) {
00629
DbgPrint(
"RtlpCallQueryRegistryRoutine: skipping environment expansion. ValueLength=%x\n",
00630 ValueLength);
00631 }
00632
00633 }
00634
00635
00636
00637
00638
00639
if (QueryTable->Flags & RTL_QUERY_REGISTRY_DIRECT) {
00640
Status =
RtlpQueryRegistryDirect( ValueType,
00641 ValueData,
00642 ValueLength,
00643 QueryTable->EntryContext
00644 );
00645 }
else {
00646
Status = (QueryTable->QueryRoutine)(
ValueName,
00647 ValueType,
00648 ValueData,
00649 ValueLength,
00650 Context,
00651 QueryTable->EntryContext
00652 );
00653
00654 }
00655
00656
00657
00658
00659
if (
Status == STATUS_BUFFER_TOO_SMALL) {
00660
Status = STATUS_SUCCESS;
00661 }
00662
return Status;
00663 }
00664
00665
00666
00667
00668
00669
#ifdef NTOS_KERNEL_RUNTIME
00670
SIZE_T
RtlpRegistryQueryInitialBuffersize = 0x80 +
sizeof(PVOID);
00671
#else
00672 SIZE_T
RtlpRegistryQueryInitialBuffersize =
PAGE_SIZE;
00673
#endif
00674
00675
00676
00677
00678 PVOID
00679 RtlpAllocDeallocQueryBuffer(
00680 IN OUT SIZE_T *PAllocLength OPTIONAL,
00681 IN PVOID OldKeyValueInformation OPTIONAL,
00682 IN SIZE_T OldAllocLength OPTIONAL,
00683 OUT NTSTATUS *pStatus OPTIONAL
00684 )
00685 {
00686 PVOID
Ptr =
NULL;
00687
NTSTATUS Status = STATUS_SUCCESS;
00688
00689
#ifdef NTOS_KERNEL_RUNTIME
00690
00691
00692
00693
00694
00695 UNREFERENCED_PARAMETER( OldAllocLength );
00696
00697
if ( ARGUMENT_PRESENT(OldKeyValueInformation) ) {
00698
ExFreePool( OldKeyValueInformation );
00699 }
00700
00701
if ( ARGUMENT_PRESENT(PAllocLength) ) {
00702
Ptr =
ExAllocatePoolWithTag(
PagedPool, *PAllocLength, 'vrqR' );
00703
if (
Ptr ==
NULL) {
00704
Status = STATUS_NO_MEMORY;
00705 }
00706 }
00707
00708
#else
00709
00710
00711
00712
00713
00714
if ( ARGUMENT_PRESENT(OldKeyValueInformation) ) {
00715
Status = ZwFreeVirtualMemory( NtCurrentProcess(),
00716 &OldKeyValueInformation,
00717 &OldAllocLength,
00718 MEM_RELEASE );
00719 }
00720
00721
if ( ARGUMENT_PRESENT(PAllocLength) ) {
00722
00723
Status = ZwAllocateVirtualMemory( NtCurrentProcess(),
00724 &
Ptr,
00725 0,
00726 PAllocLength,
00727 MEM_COMMIT,
00728 PAGE_READWRITE );
00729
if (!
NT_SUCCESS(
Status)) {
00730
Ptr =
NULL;
00731 }
00732 }
00733
00734
#endif
00735
00736
if ( ARGUMENT_PRESENT(pStatus) ) {
00737 *pStatus =
Status;
00738 }
00739
00740
return Ptr;
00741 }
00742
00743
NTSTATUS
00744 RtlQueryRegistryValues(
00745 IN ULONG RelativeTo,
00746 IN PCWSTR Path,
00747 IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
00748 IN PVOID Context,
00749 IN PVOID Environment OPTIONAL
00750 )
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893 {
00894
NTSTATUS Status;
00895 OBJECT_ATTRIBUTES
ObjectAttributes;
00896 UNICODE_STRING
KeyPath, KeyValueName;
00897 HANDLE
Key, Key1;
00898 PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
00899 SIZE_T KeyValueInfoLength;
00900 ULONG ValueIndex;
00901 SIZE_T AllocLength;
00902 ULONG KeyResultLength;
00903
int retries;
00904
00905
RTL_PAGED_CODE();
00906
00907 KeyValueInformation =
NULL;
00908
00909
Status =
RtlpGetRegistryHandle( RelativeTo, Path,
FALSE, &
Key );
00910
if (!
NT_SUCCESS(
Status )) {
00911
return Status;
00912 }
00913
00914
if ((RelativeTo & RTL_REGISTRY_HANDLE) == 0) {
00915
RtlInitUnicodeString(&
KeyPath, Path);
00916 }
else {
00917
RtlInitUnicodeString(&
KeyPath,
NULL);
00918 }
00919
00920 AllocLength =
RtlpRegistryQueryInitialBuffersize;
00921
00922 KeyValueInformation =
RtlpAllocDeallocQueryBuffer( &AllocLength,
NULL, 0, &
Status );
00923
if ( KeyValueInformation ==
NULL ) {
00924
if (!(RelativeTo & RTL_REGISTRY_HANDLE)) {
00925 ZwClose(
Key );
00926 }
00927
return Status;
00928 }
00929
00930 KeyValueInfoLength = AllocLength -
sizeof(UNICODE_NULL);
00931 Key1 =
Key;
00932
while (QueryTable->QueryRoutine !=
NULL ||
00933 (QueryTable->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_DIRECT))
00934 ) {
00935
00936
if ((QueryTable->Flags & RTL_QUERY_REGISTRY_DIRECT) &&
00937 (QueryTable->Name ==
NULL ||
00938 (QueryTable->Flags & RTL_QUERY_REGISTRY_SUBKEY) ||
00939 QueryTable->QueryRoutine !=
NULL)
00940 ) {
00941
00942
Status = STATUS_INVALID_PARAMETER;
00943
break;
00944 }
00945
00946
if (QueryTable->Flags & (RTL_QUERY_REGISTRY_TOPKEY | RTL_QUERY_REGISTRY_SUBKEY)) {
00947
if (Key1 !=
Key) {
00948
NtClose( Key1 );
00949 Key1 =
Key;
00950 }
00951 }
00952
00953
if (QueryTable->Flags & RTL_QUERY_REGISTRY_SUBKEY) {
00954
if (QueryTable->Name ==
NULL) {
00955
Status = STATUS_INVALID_PARAMETER;
00956 }
else {
00957
RtlInitUnicodeString( &
KeyPath, QueryTable->Name );
00958 InitializeObjectAttributes( &
ObjectAttributes,
00959 &
KeyPath,
00960 OBJ_CASE_INSENSITIVE,
00961
Key,
00962
NULL
00963 );
00964
#ifdef NTOS_KERNEL_RUNTIME
00965
00966
00967
00968
00969
ObjectAttributes.Attributes |= OBJ_KERNEL_HANDLE;
00970
#endif
00971
Status = ZwOpenKey( &Key1,
00972 MAXIMUM_ALLOWED,
00973 &
ObjectAttributes
00974 );
00975
if (
NT_SUCCESS(
Status )) {
00976
if (QueryTable->QueryRoutine !=
NULL) {
00977
goto enumvalues;
00978 }
00979 }
00980 }
00981
00982 }
else if (QueryTable->Name !=
NULL) {
00983
RtlInitUnicodeString( &KeyValueName, QueryTable->Name );
00984 retries = 0;
00985 retryqueryvalue:
00986
00987
00988
00989
00990
if (retries++ > 4) {
00991
00992
DbgPrint(
"RtlQueryRegistryValues: Miscomputed buffer size at line %d\n", __LINE__);
00993
00994
break;
00995 }
00996
00997
Status = ZwQueryValueKey( Key1,
00998 &KeyValueName,
00999 KeyValueFullInformation,
01000 KeyValueInformation,
01001 (ULONG) KeyValueInfoLength,
01002 &KeyResultLength
01003 );
01004
01005
01006
01007
01008
01009
if (
Status == STATUS_BUFFER_OVERFLOW) {
01010
Status = STATUS_BUFFER_TOO_SMALL;
01011 }
01012
01013
if (!
NT_SUCCESS(
Status )) {
01014
if (
Status == STATUS_OBJECT_NAME_NOT_FOUND) {
01015
01016 KeyValueInformation->Type = REG_NONE;
01017 KeyValueInformation->DataLength = 0;
01018 KeyResultLength = (ULONG)KeyValueInfoLength;
01019
Status =
RtlpCallQueryRegistryRoutine( QueryTable,
01020 KeyValueInformation,
01021 &KeyResultLength,
01022 Context,
01023 Environment
01024 );
01025 }
01026
01027
if (
Status == STATUS_BUFFER_TOO_SMALL) {
01028
01029
01030
01031
01032 AllocLength = KeyResultLength +
sizeof(PVOID) +
sizeof(UNICODE_NULL);
01033 KeyValueInformation =
RtlpAllocDeallocQueryBuffer( &AllocLength,
01034 KeyValueInformation,
01035 AllocLength,
01036 &
Status
01037 );
01038
if ( KeyValueInformation ==
NULL) {
01039
break;
01040 }
01041 KeyValueInfoLength = AllocLength -
sizeof(UNICODE_NULL);
01042
goto retryqueryvalue;
01043 }
01044
01045 }
else {
01046
01047
01048
01049
01050
if ( KeyValueInformation->Type == REG_MULTI_SZ ) {
01051 *(PWCHAR) ((PUCHAR)KeyValueInformation + KeyResultLength) = UNICODE_NULL;
01052 KeyValueInformation->DataLength +=
sizeof(UNICODE_NULL);
01053 }
01054
01055 KeyResultLength = (ULONG)KeyValueInfoLength;
01056
Status =
RtlpCallQueryRegistryRoutine( QueryTable,
01057 KeyValueInformation,
01058 &KeyResultLength,
01059 Context,
01060 Environment
01061 );
01062
01063
if (
Status == STATUS_BUFFER_TOO_SMALL ) {
01064
01065
01066
01067
01068 AllocLength = KeyResultLength +
sizeof(PVOID) +
sizeof(UNICODE_NULL);
01069 KeyValueInformation =
RtlpAllocDeallocQueryBuffer( &AllocLength,
01070 KeyValueInformation,
01071 AllocLength,
01072 &
Status
01073 );
01074
if ( KeyValueInformation ==
NULL) {
01075
break;
01076 }
01077 KeyValueInfoLength = AllocLength -
sizeof(UNICODE_NULL);
01078
goto retryqueryvalue;
01079 }
01080
01081
01082
01083
01084
01085
if (
NT_SUCCESS(
Status ) && QueryTable->Flags & RTL_QUERY_REGISTRY_DELETE) {
01086 ZwDeleteValueKey (Key1, &KeyValueName);
01087 }
01088 }
01089
01090 }
else if (QueryTable->Flags & RTL_QUERY_REGISTRY_NOVALUE) {
01091
Status = (QueryTable->QueryRoutine)(
NULL,
01092 REG_NONE,
01093
NULL,
01094 0,
01095 Context,
01096 QueryTable->EntryContext
01097 );
01098 }
else {
01099
01100 enumvalues:
01101 retries = 0;
01102
for (ValueIndex = 0;
TRUE; ValueIndex++) {
01103
Status = ZwEnumerateValueKey( Key1,
01104 ValueIndex,
01105 KeyValueFullInformation,
01106 KeyValueInformation,
01107 (ULONG) KeyValueInfoLength,
01108 &KeyResultLength
01109 );
01110
01111
01112
01113
01114
01115
if (
Status == STATUS_BUFFER_OVERFLOW) {
01116
Status = STATUS_BUFFER_TOO_SMALL;
01117 }
01118
01119
if (
Status == STATUS_NO_MORE_ENTRIES) {
01120
if (ValueIndex == 0 && (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED)) {
01121
Status = STATUS_OBJECT_NAME_NOT_FOUND;
01122 }
else {
01123
Status = STATUS_SUCCESS;
01124 }
01125
break;
01126 }
01127
01128
if (
NT_SUCCESS(
Status ) ) {
01129
01130 KeyResultLength = (ULONG)KeyValueInfoLength;
01131
Status =
RtlpCallQueryRegistryRoutine( QueryTable,
01132 KeyValueInformation,
01133 &KeyResultLength,
01134 Context,
01135 Environment
01136 );
01137 }
01138
01139
if (
Status == STATUS_BUFFER_TOO_SMALL) {
01140
01141
01142
01143 AllocLength = KeyResultLength +
sizeof(PVOID) +
sizeof(UNICODE_NULL);
01144 KeyValueInformation =
RtlpAllocDeallocQueryBuffer( &AllocLength,
01145 KeyValueInformation,
01146 AllocLength,
01147 &
Status
01148 );
01149
if (KeyValueInformation ==
NULL) {
01150
break;
01151 }
01152 KeyValueInfoLength = AllocLength -
sizeof(UNICODE_NULL);
01153 ValueIndex -= 1;
01154
01155
01156
01157
01158
01159
01160
if (retries++ <= 4) {
01161
continue;
01162 }
01163
01164
DbgPrint(
"RtlQueryRegistryValues: Miscomputed buffer size at line %d\n", __LINE__);
01165
01166
break;
01167 }
01168
01169
if (!
NT_SUCCESS(
Status )) {
01170
break;
01171 }
01172
01173 retries = 0;
01174
01175
01176
01177
01178
01179
01180
01181
01182
if (QueryTable->Flags & RTL_QUERY_REGISTRY_DELETE) {
01183 KeyValueName.Buffer = KeyValueInformation->Name;
01184 KeyValueName.Length = (
USHORT)KeyValueInformation->NameLength;
01185 KeyValueName.MaximumLength = (
USHORT)KeyValueInformation->NameLength;
01186
Status = ZwDeleteValueKey( Key1,
01187 &KeyValueName
01188 );
01189
if (
NT_SUCCESS(
Status )) {
01190 ValueIndex -= 1;
01191 }
01192 }
01193 }
01194 }
01195
01196
if (!
NT_SUCCESS(
Status )) {
01197
break;
01198 }
01199
01200 QueryTable++;
01201 }
01202
01203
if (
Key !=
NULL && !(RelativeTo & RTL_REGISTRY_HANDLE)) {
01204 ZwClose(
Key );
01205 }
01206
01207
if (Key1 !=
NULL && Key1 !=
Key) {
01208 ZwClose( Key1 );
01209 }
01210
01211
01212
01213
01214 (
void)
RtlpAllocDeallocQueryBuffer(
NULL, KeyValueInformation, AllocLength,
NULL );
01215
return Status;
01216 }
01217
01218
01219
NTSTATUS
01220 RtlWriteRegistryValue(
01221 IN ULONG RelativeTo,
01222 IN PCWSTR Path,
01223 IN PCWSTR ValueName,
01224 IN ULONG ValueType,
01225 IN PVOID ValueData,
01226 IN ULONG ValueLength
01227 )
01228 {
01229
NTSTATUS Status;
01230 UNICODE_STRING KeyValueName;
01231 HANDLE
Key;
01232
01233
RTL_PAGED_CODE();
01234
01235
Status =
RtlpGetRegistryHandle( RelativeTo, Path,
TRUE, &
Key );
01236
if (!
NT_SUCCESS(
Status )) {
01237
return Status;
01238 }
01239
01240
RtlInitUnicodeString( &KeyValueName,
ValueName );
01241
Status = ZwSetValueKey(
Key,
01242 &KeyValueName,
01243 0,
01244 ValueType,
01245 ValueData,
01246 ValueLength
01247 );
01248
if (!(RelativeTo & RTL_REGISTRY_HANDLE)) {
01249 ZwClose(
Key );
01250 }
01251
01252
return Status;
01253 }
01254
01255
01256
NTSTATUS
01257 RtlCheckRegistryKey(
01258 IN ULONG RelativeTo,
01259 IN PWSTR Path
01260 )
01261 {
01262
NTSTATUS Status;
01263 HANDLE
Key;
01264
01265
RTL_PAGED_CODE();
01266
01267
Status =
RtlpGetRegistryHandle( RelativeTo, Path,
FALSE, &
Key );
01268
if (!
NT_SUCCESS(
Status )) {
01269
return Status;
01270 }
01271
01272 ZwClose(
Key );
01273
return STATUS_SUCCESS;
01274 }
01275
01276
01277
NTSTATUS
01278 RtlCreateRegistryKey(
01279 IN ULONG RelativeTo,
01280 IN PWSTR Path
01281 )
01282 {
01283
NTSTATUS Status;
01284 HANDLE
Key;
01285
01286
RTL_PAGED_CODE();
01287
01288
Status =
RtlpGetRegistryHandle( RelativeTo, Path,
TRUE, &
Key );
01289
if (!
NT_SUCCESS(
Status )) {
01290
return Status;
01291 }
01292
01293 ZwClose(
Key );
01294
return STATUS_SUCCESS;
01295 }
01296
01297
01298
NTSTATUS
01299 RtlDeleteRegistryValue(
01300 IN ULONG RelativeTo,
01301 IN PCWSTR Path,
01302 IN PCWSTR ValueName
01303 )
01304 {
01305
NTSTATUS Status;
01306 UNICODE_STRING KeyValueName;
01307 HANDLE
Key;
01308
01309
RTL_PAGED_CODE();
01310
01311
Status =
RtlpGetRegistryHandle( RelativeTo, Path,
TRUE, &
Key );
01312
if (!
NT_SUCCESS(
Status )) {
01313
return Status;
01314 }
01315
01316
RtlInitUnicodeString( &KeyValueName,
ValueName );
01317
Status = ZwDeleteValueKey(
Key, &KeyValueName );
01318
01319 ZwClose(
Key );
01320
return Status;
01321 }
01322
01323
01324
NTSTATUS
01325 RtlExpandEnvironmentStrings_U(
01326 IN PVOID Environment OPTIONAL,
01327 IN PUNICODE_STRING Source,
01328 OUT PUNICODE_STRING Destination,
01329 OUT PULONG ReturnedLength OPTIONAL
01330 )
01331 {
01332
NTSTATUS Status, Status1;
01333 PWCHAR Src, Src1, Dst;
01334 UNICODE_STRING VariableName, VariableValue;
01335 ULONG SrcLength, DstLength, VarLength, RequiredLength;
01336
01337
RTL_PAGED_CODE();
01338
01339 Src = Source->Buffer;
01340 SrcLength = Source->Length;
01341 Dst = Destination->Buffer;
01342 DstLength = Destination->MaximumLength;
01343
Status = STATUS_SUCCESS;
01344 RequiredLength = 0;
01345
while (SrcLength >=
sizeof(WCHAR)) {
01346
if (*Src ==
L'%') {
01347 Src1 = Src + 1;
01348 VarLength = 0;
01349 VariableName.Length = 0;
01350 VariableName.Buffer = Src1;
01351
01352
while (VarLength < (SrcLength -
sizeof(WCHAR))) {
01353
if (*Src1 ==
L'%') {
01354
if (VarLength) {
01355 VariableName.Length = (
USHORT)VarLength;
01356 VariableName.MaximumLength = (
USHORT)VarLength;
01357 }
01358
break;
01359
01360 }
01361
01362 Src1++;
01363 VarLength +=
sizeof(WCHAR);
01364 }
01365
01366
if (VariableName.Length) {
01367 VariableValue.Buffer = Dst;
01368 VariableValue.Length = 0;
01369 VariableValue.MaximumLength = (
USHORT)DstLength;
01370 Status1 =
RtlQueryEnvironmentVariable_U( Environment,
01371 &VariableName,
01372 &VariableValue
01373 );
01374
if (
NT_SUCCESS( Status1 ) || Status1 == STATUS_BUFFER_TOO_SMALL) {
01375 RequiredLength += VariableValue.Length;
01376 Src = Src1 + 1;
01377 SrcLength -= (VarLength + 2*
sizeof(WCHAR));
01378
01379
if (
NT_SUCCESS( Status1 )) {
01380 DstLength -= VariableValue.Length;
01381 Dst += VariableValue.Length /
sizeof(WCHAR);
01382
01383 }
else {
01384
Status = Status1;
01385 }
01386
01387
continue;
01388 }
01389 }
01390 }
01391
01392
if (
NT_SUCCESS(
Status )) {
01393
if (DstLength >
sizeof(WCHAR)) {
01394 DstLength -=
sizeof(WCHAR);
01395 *Dst++ = *Src;
01396
01397 }
else {
01398
Status = STATUS_BUFFER_TOO_SMALL;
01399 }
01400 }
01401
01402 RequiredLength +=
sizeof(WCHAR);
01403 SrcLength -=
sizeof(WCHAR);
01404 Src++;
01405 }
01406
01407
if (
NT_SUCCESS(
Status )) {
01408
if (DstLength) {
01409 DstLength -=
sizeof(WCHAR);
01410 *Dst = UNICODE_NULL;
01411
01412 }
else {
01413
Status = STATUS_BUFFER_TOO_SMALL;
01414 }
01415 }
01416
01417 RequiredLength +=
sizeof(WCHAR);
01418
01419
if (ARGUMENT_PRESENT( ReturnedLength )) {
01420 *ReturnedLength = RequiredLength;
01421 }
01422
01423
if (
NT_SUCCESS(
Status )) {
01424 Destination->Length = (
USHORT)(RequiredLength -
sizeof(WCHAR));
01425 }
01426
01427
return Status;
01428 }
01429
01430
01431 ULONG
01432 RtlGetNtGlobalFlags( VOID )
01433 {
01434
#ifdef NTOS_KERNEL_RUNTIME
01435
return NtGlobalFlag;
01436
#else
01437
return NtCurrentPeb()->NtGlobalFlag;
01438
#endif
01439
}
01440
01441
01442
01443
01444
01445
01446 #define SIZE_OF_TOKEN_INFORMATION \
01447
sizeof( TOKEN_USER ) \
01448
+ sizeof( SID ) \
01449
+ sizeof( ULONG ) * SID_MAX_SUB_AUTHORITIES
01450
01451
01452
NTSTATUS
01453 RtlFormatCurrentUserKeyPath(
01454 OUT PUNICODE_STRING CurrentUserKeyPath
01455 )
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 {
01478 HANDLE TokenHandle;
01479 UCHAR TokenInformation[
SIZE_OF_TOKEN_INFORMATION ];
01480 ULONG ReturnLength;
01481 ULONG SidStringLength ;
01482 UNICODE_STRING SidString ;
01483
NTSTATUS Status;
01484
01485
Status = ZwOpenThreadToken( NtCurrentThread(),
01486 TOKEN_READ,
01487
TRUE,
01488 &TokenHandle
01489 );
01490
01491
if ( !
NT_SUCCESS(
Status ) && (
Status != STATUS_NO_TOKEN ) ) {
01492
return Status;
01493 }
01494
01495
if ( !
NT_SUCCESS(
Status ) ) {
01496
01497
Status = ZwOpenProcessToken( NtCurrentProcess(),
01498 TOKEN_READ,
01499 &TokenHandle
01500 );
01501
if ( !
NT_SUCCESS(
Status )) {
01502
return Status;
01503 }
01504 }
01505
01506
Status = ZwQueryInformationToken( TokenHandle,
01507 TokenUser,
01508 TokenInformation,
01509
sizeof( TokenInformation ),
01510 &ReturnLength
01511 );
01512
01513 ZwClose( TokenHandle );
01514
01515
if ( !
NT_SUCCESS(
Status )) {
01516
return Status;
01517 }
01518
01519
Status =
RtlLengthSidAsUnicodeString(
01520 ((PTOKEN_USER)TokenInformation)->User.Sid,
01521 &SidStringLength
01522 );
01523
01524
if ( !
NT_SUCCESS(
Status ) ) {
01525
return Status ;
01526 }
01527
01528 CurrentUserKeyPath->Length = 0;
01529 CurrentUserKeyPath->MaximumLength = (
USHORT)(SidStringLength +
01530
sizeof(
L"\\REGISTRY\\USER\\" ) +
01531
sizeof( UNICODE_NULL ));
01532 CurrentUserKeyPath->Buffer = (
RtlAllocateStringRoutine)( CurrentUserKeyPath->MaximumLength );
01533
if (CurrentUserKeyPath->Buffer ==
NULL) {
01534
return STATUS_NO_MEMORY;
01535 }
01536
01537
01538
01539
01540
01541
RtlAppendUnicodeToString( CurrentUserKeyPath,
L"\\REGISTRY\\USER\\" );
01542
01543 SidString.MaximumLength = (
USHORT)SidStringLength ;
01544 SidString.Length = 0 ;
01545 SidString.Buffer = CurrentUserKeyPath->Buffer +
01546 (CurrentUserKeyPath->Length /
sizeof(WCHAR) );
01547
01548
Status =
RtlConvertSidToUnicodeString( &SidString,
01549 ((PTOKEN_USER)TokenInformation)->User.Sid,
01550
FALSE
01551 );
01552
if ( !
NT_SUCCESS(
Status )) {
01553
RtlFreeUnicodeString( CurrentUserKeyPath );
01554
01555 }
else {
01556 CurrentUserKeyPath->Length += SidString.Length ;
01557 }
01558
01559
return Status;
01560 }
01561
01562
01563
NTSTATUS
01564 RtlOpenCurrentUser(
01565 IN ULONG DesiredAccess,
01566 OUT PHANDLE CurrentUserKey
01567 )
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587 {
01588 UNICODE_STRING CurrentUserKeyPath;
01589 OBJECT_ATTRIBUTES Obja;
01590
NTSTATUS Status;
01591
01592
RTL_PAGED_CODE();
01593
01594
01595
01596
01597
01598
Status =
RtlFormatCurrentUserKeyPath( &CurrentUserKeyPath );
01599
if (
NT_SUCCESS(
Status) ) {
01600
01601 InitializeObjectAttributes( &Obja,
01602 &CurrentUserKeyPath,
01603 OBJ_CASE_INSENSITIVE,
01604
NULL,
01605
NULL
01606 );
01607
Status = ZwOpenKey( CurrentUserKey,
01608 DesiredAccess,
01609 &Obja
01610 );
01611
RtlFreeUnicodeString( &CurrentUserKeyPath );
01612 }
01613
01614
if ( !
NT_SUCCESS(
Status) ) {
01615
01616
01617
01618
RtlInitUnicodeString( &CurrentUserKeyPath,
RtlpRegistryPaths[ RTL_REGISTRY_USER ] );
01619 InitializeObjectAttributes( &Obja,
01620 &CurrentUserKeyPath,
01621 OBJ_CASE_INSENSITIVE,
01622
NULL,
01623
NULL
01624 );
01625
01626
Status = ZwOpenKey( CurrentUserKey,
01627 DesiredAccess,
01628 &Obja
01629 );
01630 }
01631
01632
return Status;
01633 }
01634
01635
01636
NTSTATUS
01637 RtlpGetTimeZoneInfoHandle(
01638 IN BOOLEAN WriteAccess,
01639 OUT PHANDLE Key
01640 )
01641 {
01642
return RtlpGetRegistryHandle( RTL_REGISTRY_CONTROL,
L"TimeZoneInformation", WriteAccess,
Key );
01643 }
01644
01645
01646
01647 extern const WCHAR
szBias[];
01648 extern const WCHAR
szStandardName[];
01649 extern const WCHAR
szStandardBias[];
01650 extern const WCHAR
szStandardStart[];
01651 extern const WCHAR
szDaylightName[];
01652 extern const WCHAR
szDaylightBias[];
01653 extern const WCHAR
szDaylightStart[];
01654
01655
NTSTATUS
01656 RtlQueryTimeZoneInformation(
01657 OUT PRTL_TIME_ZONE_INFORMATION TimeZoneInformation
01658 )
01659 {
01660
NTSTATUS Status;
01661 HANDLE
Key;
01662 UNICODE_STRING StandardName, DaylightName;
01663 RTL_QUERY_REGISTRY_TABLE RegistryConfigurationTable[ 8 ];
01664
01665
RTL_PAGED_CODE();
01666
01667
Status =
RtlpGetTimeZoneInfoHandle(
FALSE, &
Key );
01668
if (!
NT_SUCCESS(
Status )) {
01669
return Status;
01670 }
01671
01672 RtlZeroMemory( TimeZoneInformation,
sizeof( *TimeZoneInformation ) );
01673 RtlZeroMemory( RegistryConfigurationTable,
sizeof( RegistryConfigurationTable ) );
01674
01675 RegistryConfigurationTable[ 0 ].Flags = RTL_QUERY_REGISTRY_DIRECT;
01676 RegistryConfigurationTable[ 0 ].Name = (PWSTR)
szBias;
01677 RegistryConfigurationTable[ 0 ].EntryContext = &TimeZoneInformation->Bias;
01678
01679
01680 StandardName.Buffer = TimeZoneInformation->StandardName;
01681 StandardName.Length = 0;
01682 StandardName.MaximumLength =
sizeof( TimeZoneInformation->StandardName );
01683 RegistryConfigurationTable[ 1 ].Flags = RTL_QUERY_REGISTRY_DIRECT;
01684 RegistryConfigurationTable[ 1 ].Name = (PWSTR)
szStandardName;
01685 RegistryConfigurationTable[ 1 ].EntryContext = &StandardName;
01686
01687 RegistryConfigurationTable[ 2 ].Flags = RTL_QUERY_REGISTRY_DIRECT;
01688 RegistryConfigurationTable[ 2 ].Name = (PWSTR)
szStandardBias;
01689 RegistryConfigurationTable[ 2 ].EntryContext = &TimeZoneInformation->StandardBias;
01690
01691 RegistryConfigurationTable[ 3 ].Flags = RTL_QUERY_REGISTRY_DIRECT;
01692 RegistryConfigurationTable[ 3 ].Name = (PWSTR)
szStandardStart;
01693 RegistryConfigurationTable[ 3 ].EntryContext = &TimeZoneInformation->StandardStart;
01694 *(PLONG)(RegistryConfigurationTable[ 3 ].EntryContext) = -(LONG)
sizeof( TIME_FIELDS );
01695
01696 DaylightName.Buffer = TimeZoneInformation->DaylightName;
01697 DaylightName.Length = 0;
01698 DaylightName.MaximumLength =
sizeof( TimeZoneInformation->DaylightName );
01699 RegistryConfigurationTable[ 4 ].Flags = RTL_QUERY_REGISTRY_DIRECT;
01700 RegistryConfigurationTable[ 4 ].Name = (PWSTR)
szDaylightName;
01701 RegistryConfigurationTable[ 4 ].EntryContext = &DaylightName;
01702
01703 RegistryConfigurationTable[ 5 ].Flags = RTL_QUERY_REGISTRY_DIRECT;
01704 RegistryConfigurationTable[ 5 ].Name = (PWSTR)
szDaylightBias;
01705 RegistryConfigurationTable[ 5 ].EntryContext = &TimeZoneInformation->DaylightBias;
01706
01707 RegistryConfigurationTable[ 6 ].Flags = RTL_QUERY_REGISTRY_DIRECT;
01708 RegistryConfigurationTable[ 6 ].Name = (PWSTR)
szDaylightStart;
01709 RegistryConfigurationTable[ 6 ].EntryContext = &TimeZoneInformation->DaylightStart;
01710 *(PLONG)(RegistryConfigurationTable[ 6 ].EntryContext) = -(LONG)
sizeof( TIME_FIELDS );
01711
01712
Status =
RtlQueryRegistryValues( RTL_REGISTRY_HANDLE,
01713 (PWSTR)
Key,
01714 RegistryConfigurationTable,
01715
NULL,
01716
NULL
01717 );
01718 ZwClose(
Key );
01719
return Status;
01720 }
01721
01722
01723
NTSTATUS
01724 RtlSetTimeZoneInformation(
01725 IN PRTL_TIME_ZONE_INFORMATION TimeZoneInformation
01726 )
01727 {
01728
NTSTATUS Status;
01729 HANDLE
Key;
01730
01731
RTL_PAGED_CODE();
01732
01733
Status =
RtlpGetTimeZoneInfoHandle(
TRUE, &
Key );
01734
if (!
NT_SUCCESS(
Status )) {
01735
return Status;
01736 }
01737
01738
Status =
RtlWriteRegistryValue( RTL_REGISTRY_HANDLE,
01739 (PWSTR)
Key,
01740
szBias,
01741 REG_DWORD,
01742 &TimeZoneInformation->Bias,
01743
sizeof( TimeZoneInformation->Bias )
01744 );
01745
if (
NT_SUCCESS(
Status )) {
01746
Status =
RtlWriteRegistryValue( RTL_REGISTRY_HANDLE,
01747 (PWSTR)
Key,
01748
szStandardName,
01749 REG_SZ,
01750 TimeZoneInformation->StandardName,
01751 (wcslen( TimeZoneInformation->StandardName ) + 1) *
sizeof( WCHAR )
01752 );
01753 }
01754
01755
if (
NT_SUCCESS(
Status )) {
01756
Status =
RtlWriteRegistryValue( RTL_REGISTRY_HANDLE,
01757 (PWSTR)
Key,
01758
szStandardBias,
01759 REG_DWORD,
01760 &TimeZoneInformation->StandardBias,
01761
sizeof( TimeZoneInformation->StandardBias )
01762 );
01763 }
01764
01765
if (
NT_SUCCESS(
Status )) {
01766
Status =
RtlWriteRegistryValue( RTL_REGISTRY_HANDLE,
01767 (PWSTR)
Key,
01768
szStandardStart,
01769 REG_BINARY,
01770 &TimeZoneInformation->StandardStart,
01771
sizeof( TimeZoneInformation->StandardStart )
01772 );
01773 }
01774
01775
if (
NT_SUCCESS(
Status )) {
01776
Status =
RtlWriteRegistryValue( RTL_REGISTRY_HANDLE,
01777 (PWSTR)
Key,
01778
szDaylightName,
01779 REG_SZ,
01780 TimeZoneInformation->DaylightName,
01781 (wcslen( TimeZoneInformation->DaylightName ) + 1) *
sizeof( WCHAR )
01782 );
01783 }
01784
01785
if (
NT_SUCCESS(
Status )) {
01786
Status =
RtlWriteRegistryValue( RTL_REGISTRY_HANDLE,
01787 (PWSTR)
Key,
01788
szDaylightBias,
01789 REG_DWORD,
01790 &TimeZoneInformation->DaylightBias,
01791
sizeof( TimeZoneInformation->DaylightBias )
01792 );
01793 }
01794
01795
if (
NT_SUCCESS(
Status )) {
01796
Status =
RtlWriteRegistryValue( RTL_REGISTRY_HANDLE,
01797 (PWSTR)
Key,
01798
szDaylightStart,
01799 REG_BINARY,
01800 &TimeZoneInformation->DaylightStart,
01801
sizeof( TimeZoneInformation->DaylightStart )
01802 );
01803 }
01804
01805 ZwClose(
Key );
01806
return Status;
01807 }
01808
01809
01810
NTSTATUS
01811 RtlSetActiveTimeBias(
01812 IN LONG ActiveBias
01813 )
01814 {
01815
NTSTATUS Status;
01816 HANDLE
Key;
01817 RTL_QUERY_REGISTRY_TABLE RegistryConfigurationTable[ 2 ];
01818 LONG CurrentActiveBias;
01819
01820
RTL_PAGED_CODE();
01821
01822
Status =
RtlpGetTimeZoneInfoHandle(
TRUE, &
Key );
01823
if (!
NT_SUCCESS(
Status )) {
01824
return Status;
01825 }
01826
01827 RtlZeroMemory( RegistryConfigurationTable,
sizeof( RegistryConfigurationTable ) );
01828 RegistryConfigurationTable[ 0 ].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
01829 RegistryConfigurationTable[ 0 ].Name =
L"ActiveTimeBias";
01830 RegistryConfigurationTable[ 0 ].EntryContext = &CurrentActiveBias;
01831
01832
Status =
RtlQueryRegistryValues( RTL_REGISTRY_HANDLE,
01833 (PWSTR)
Key,
01834 RegistryConfigurationTable,
01835
NULL,
01836
NULL
01837 );
01838
01839
if ( !
NT_SUCCESS(
Status) || CurrentActiveBias != ActiveBias ) {
01840
01841
Status =
RtlWriteRegistryValue( RTL_REGISTRY_HANDLE,
01842 (PWSTR)
Key,
01843
L"ActiveTimeBias",
01844 REG_DWORD,
01845 &ActiveBias,
01846
sizeof( ActiveBias )
01847 );
01848 }
01849
01850 ZwClose(
Key );
01851
return Status;
01852 }
01853