00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "cmp.h"
00023
00024
00025
00026
00027
NTSTATUS
00028
CmpOpenFileWithExtremePrejudice(
00029 OUT PHANDLE Primary,
00030 IN POBJECT_ATTRIBUTES Obja,
00031 IN ULONG IoFlags,
00032 IN ULONG AttributeFlags
00033 );
00034
00035
#ifdef ALLOC_PRAGMA
00036
#pragma alloc_text(PAGE,CmpOpenHiveFiles)
00037
#pragma alloc_text(PAGE,CmpInitializeHive)
00038
#pragma alloc_text(PAGE,CmpDestroyHive)
00039
#pragma alloc_text(PAGE,CmpOpenFileWithExtremePrejudice)
00040
#endif
00041
00042 extern PCMHIVE CmpMasterHive;
00043 extern LIST_ENTRY
CmpHiveListHead;
00044
00045
NTSTATUS
00046 CmpOpenHiveFiles(
00047 PUNICODE_STRING BaseName,
00048 PWSTR Extension OPTIONAL,
00049 PHANDLE Primary,
00050 PHANDLE Secondary,
00051 PULONG PrimaryDisposition,
00052 PULONG SecondaryDisposition,
00053 BOOLEAN CreateAllowed,
00054 BOOLEAN MarkAsSystemHive,
00055 OUT OPTIONAL PULONG ClusterSize
00056 )
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 {
00113 IO_STATUS_BLOCK IoStatus;
00114 IO_STATUS_BLOCK FsctlIoStatus;
00115 FILE_FS_SIZE_INFORMATION FsSizeInformation;
00116 ULONG Cluster;
00117 ULONG CreateDisposition;
00118 OBJECT_ATTRIBUTES
ObjectAttributes;
00119
NTSTATUS status;
00120 UNICODE_STRING ExtName;
00121 UNICODE_STRING
WorkName;
00122 PVOID WorkBuffer;
00123
USHORT NameSize;
00124 ULONG IoFlags;
00125 ULONG AttributeFlags;
00126
USHORT CompressionState;
00127 HANDLE hEvent;
00128
PKEVENT pEvent;
00129
00130
00131
00132
00133 status =
CmpCreateEvent(NotificationEvent, &hEvent, &pEvent);
00134
if (!
NT_SUCCESS(status)) {
00135
return(status);
00136 }
00137
00138
00139
00140
00141
WorkName.Length = 0;
00142
WorkName.MaximumLength = 0;
00143
WorkName.Buffer =
NULL;
00144 WorkBuffer =
NULL;
00145
00146 NameSize =
BaseName->Length;
00147
if (ARGUMENT_PRESENT(Extension)) {
00148 NameSize += (wcslen(Extension)+1) *
sizeof(WCHAR);
00149 WorkBuffer =
ExAllocatePool(
PagedPool, NameSize);
00150
WorkName.Buffer = WorkBuffer;
00151
if (WorkBuffer ==
NULL) {
00152
ObDereferenceObject(pEvent);
00153 ZwClose(hEvent);
00154
return STATUS_NO_MEMORY;
00155 }
00156
WorkName.MaximumLength = NameSize;
00157
RtlAppendStringToString((PSTRING)&
WorkName, (PSTRING)
BaseName);
00158 }
else {
00159
WorkName = *
BaseName;
00160 }
00161
00162
00163
00164
00165
00166 InitializeObjectAttributes(
00167 &
ObjectAttributes,
00168 &
WorkName,
00169 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
00170
NULL,
00171
NULL
00172 );
00173
00174
if (CreateAllowed) {
00175 CreateDisposition = FILE_OPEN_IF;
00176 }
else {
00177 CreateDisposition = FILE_OPEN;
00178 }
00179
00180
ASSERT_PASSIVE_LEVEL();
00181
00182 status =
ZwCreateFile(
00183 Primary,
00184 FILE_READ_DATA | FILE_WRITE_DATA,
00185 &
ObjectAttributes,
00186 &IoStatus,
00187
NULL,
00188 FILE_ATTRIBUTE_NORMAL,
00189 0,
00190 CreateDisposition,
00191 FILE_NO_INTERMEDIATE_BUFFERING |
00192 FILE_OPEN_FOR_BACKUP_INTENT |
00193 FILE_NO_COMPRESSION,
00194
NULL,
00195 0
00196 );
00197
if (status == STATUS_ACCESS_DENIED) {
00198
00199
00200
00201
00202
00203
00204
00205 status =
CmpOpenFileWithExtremePrejudice(Primary,
00206 &
ObjectAttributes,
00207 FILE_NO_INTERMEDIATE_BUFFERING |
00208 FILE_OPEN_FOR_BACKUP_INTENT |
00209 FILE_NO_COMPRESSION,
00210 FILE_ATTRIBUTE_NORMAL);
00211 }
00212
00213
if ((MarkAsSystemHive) &&
00214 (
NT_SUCCESS(status))) {
00215
00216
ASSERT_PASSIVE_LEVEL();
00217 status = ZwFsControlFile(*Primary,
00218 hEvent,
00219
NULL,
00220
NULL,
00221 &FsctlIoStatus,
00222 FSCTL_MARK_AS_SYSTEM_HIVE,
00223
NULL,
00224 0,
00225
NULL,
00226 0);
00227
if (status == STATUS_PENDING) {
00228
KeWaitForSingleObject(pEvent,
00229
Executive,
00230
KernelMode,
00231
FALSE,
00232
NULL);
00233 status = FsctlIoStatus.Status;
00234 }
00235
00236
00237
00238
00239
00240
if (status == STATUS_INVALID_DEVICE_REQUEST) {
00241 status = STATUS_SUCCESS;
00242
00243 }
else if (!
NT_SUCCESS(status)) {
00244 ZwClose(*Primary);
00245 }
00246 }
00247
00248
if (!
NT_SUCCESS(status)) {
00249
CMLOG(
CML_BUGCHECK,
CMS_INIT_ERROR) {
00250 KdPrint((
"CMINIT: CmpOpenHiveFile: "));
00251 KdPrint((
"\tPrimary Open/Create failed for:\n"));
00252 KdPrint((
"\t%wZ\n", &
WorkName));
00253 KdPrint((
"\tstatus = %08lx\n", status));
00254 }
00255
if (WorkBuffer !=
NULL) {
00256
ExFreePool(WorkBuffer);
00257 }
00258
ObDereferenceObject(pEvent);
00259 ZwClose(hEvent);
00260
return status;
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 CompressionState = 0;
00273
ASSERT_PASSIVE_LEVEL();
00274 status = ZwFsControlFile(*Primary,
00275 hEvent,
00276
NULL,
00277
NULL,
00278 &FsctlIoStatus,
00279 FSCTL_SET_COMPRESSION,
00280 &CompressionState,
00281
sizeof(CompressionState),
00282
NULL,
00283 0);
00284
if (status == STATUS_PENDING) {
00285
KeWaitForSingleObject(pEvent,
00286
Executive,
00287
KernelMode,
00288
FALSE,
00289
NULL);
00290 }
00291
00292 *PrimaryDisposition = (ULONG) IoStatus.Information;
00293
00294
if (ARGUMENT_PRESENT(ClusterSize)) {
00295
00296
ASSERT_PASSIVE_LEVEL();
00297 status = ZwQueryVolumeInformationFile(*Primary,
00298 &IoStatus,
00299 &FsSizeInformation,
00300
sizeof(FILE_FS_SIZE_INFORMATION),
00301 FileFsSizeInformation);
00302
if (!
NT_SUCCESS(status)) {
00303
ObDereferenceObject(pEvent);
00304 ZwClose(hEvent);
00305
return(status);
00306 }
00307
if (FsSizeInformation.BytesPerSector >
HBLOCK_SIZE) {
00308
CMLOG(
CML_BUGCHECK,
CMS_INIT_ERROR) {
00309 KdPrint((
"CmpOpenHiveFiles: sectorsize %lx > HBLOCK_SIZE\n"));
00310 }
00311
ObDereferenceObject(pEvent);
00312 ZwClose(hEvent);
00313
return(STATUS_CANNOT_LOAD_REGISTRY_FILE);
00314 }
00315
00316 Cluster = FsSizeInformation.BytesPerSector /
HSECTOR_SIZE;
00317 *ClusterSize = (Cluster < 1) ? 1 : Cluster;
00318
00319 }
00320
00321
if ( ! ARGUMENT_PRESENT(Extension)) {
00322
if (WorkBuffer !=
NULL) {
00323
ExFreePool(WorkBuffer);
00324 }
00325
ObDereferenceObject(pEvent);
00326 ZwClose(hEvent);
00327
return STATUS_SUCCESS;
00328 }
00329
00330
00331
00332
00333 CreateDisposition = FILE_OPEN_IF;
00334
if (*PrimaryDisposition == FILE_CREATED) {
00335 CreateDisposition = FILE_SUPERSEDE;
00336 }
00337
00338
RtlInitUnicodeString(&ExtName,Extension);
00339 status =
RtlAppendStringToString((PSTRING)&
WorkName, (PSTRING)&ExtName);
00340
00341 InitializeObjectAttributes(&
ObjectAttributes,
00342 &
WorkName,
00343 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
00344
NULL,
00345
NULL);
00346
00347 IoFlags = FILE_NO_COMPRESSION;
00348
if (_wcsnicmp(Extension,
L".log", 4) != 0) {
00349 IoFlags |= FILE_NO_INTERMEDIATE_BUFFERING;
00350 AttributeFlags = FILE_ATTRIBUTE_NORMAL;
00351 }
else {
00352 AttributeFlags = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_HIDDEN;
00353 }
00354
00355
ASSERT_PASSIVE_LEVEL();
00356 status =
ZwCreateFile(
00357 Secondary,
00358 FILE_READ_DATA | FILE_WRITE_DATA,
00359 &
ObjectAttributes,
00360 &IoStatus,
00361
NULL,
00362 AttributeFlags,
00363 0,
00364 CreateDisposition,
00365 IoFlags,
00366
NULL,
00367 0
00368 );
00369
00370
if (status == STATUS_ACCESS_DENIED) {
00371
00372
00373
00374
00375
00376
00377
00378 status =
CmpOpenFileWithExtremePrejudice(Secondary,
00379 &
ObjectAttributes,
00380 IoFlags,
00381 AttributeFlags);
00382 }
00383
00384
if ((MarkAsSystemHive) &&
00385 (
NT_SUCCESS(status))) {
00386
00387
ASSERT_PASSIVE_LEVEL();
00388 status = ZwFsControlFile(*Secondary,
00389 hEvent,
00390
NULL,
00391
NULL,
00392 &FsctlIoStatus,
00393 FSCTL_MARK_AS_SYSTEM_HIVE,
00394
NULL,
00395 0,
00396
NULL,
00397 0);
00398
if (status == STATUS_PENDING) {
00399
KeWaitForSingleObject(pEvent,
00400
Executive,
00401
KernelMode,
00402
FALSE,
00403
NULL);
00404 status = FsctlIoStatus.Status;
00405 }
00406
00407
00408
00409
00410
if (status == STATUS_INVALID_DEVICE_REQUEST) {
00411 status = STATUS_SUCCESS;
00412
00413 }
else if (!
NT_SUCCESS(status)) {
00414
00415 ZwClose(*Secondary);
00416 }
00417 }
00418
00419
if (!
NT_SUCCESS(status)) {
00420
CMLOG(
CML_BUGCHECK,
CMS_INIT_ERROR) {
00421 KdPrint((
"CMINIT: CmpOpenHiveFile: "));
00422 KdPrint((
"\tSecondary Open/Create failed for:\n"));
00423 KdPrint((
"\t%wZ\n", &
WorkName));
00424 KdPrint((
"\tstatus = %08lx\n", status));
00425 }
00426 *Secondary =
NULL;
00427 }
00428
00429 *SecondaryDisposition = (ULONG) IoStatus.Information;
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 CompressionState = 0;
00441
00442
ASSERT_PASSIVE_LEVEL();
00443 status = ZwFsControlFile(*Secondary,
00444 hEvent,
00445
NULL,
00446
NULL,
00447 &FsctlIoStatus,
00448 FSCTL_SET_COMPRESSION,
00449 &CompressionState,
00450
sizeof(CompressionState),
00451
NULL,
00452 0);
00453
if (status == STATUS_PENDING) {
00454
KeWaitForSingleObject(pEvent,
00455
Executive,
00456
KernelMode,
00457
FALSE,
00458
NULL);
00459 }
00460
00461
if (WorkBuffer !=
NULL) {
00462
ExFreePool(WorkBuffer);
00463 }
00464
ObDereferenceObject(pEvent);
00465 ZwClose(hEvent);
00466
return STATUS_SUCCESS;
00467 }
00468
00469
00470
NTSTATUS
00471 CmpInitializeHive(
00472
PCMHIVE *CmHive,
00473 ULONG OperationType,
00474 ULONG HiveFlags,
00475 ULONG FileType,
00476 PVOID HiveData OPTIONAL,
00477 HANDLE Primary,
00478 HANDLE Alternate,
00479 HANDLE Log,
00480 HANDLE External,
00481 PUNICODE_STRING FileName OPTIONAL
00482 )
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 {
00527 FILE_FS_SIZE_INFORMATION FsSizeInformation;
00528 IO_STATUS_BLOCK IoStatusBlock;
00529 ULONG Cluster;
00530
NTSTATUS Status;
00531
PCMHIVE cmhive2;
00532 ULONG rc;
00533
00534
CMLOG(
CML_MAJOR,
CMS_INIT) {
00535 KdPrint((
"CmpInitializeHive:\t\n"));
00536 }
00537
00538
00539
00540
00541
if ( (Alternate && Log) ||
00542 (External && (Primary || Alternate || Log)) ||
00543 (Alternate && !Primary) ||
00544 (Log && !Primary) ||
00545 ((HiveFlags &
HIVE_VOLATILE) && (Alternate || Primary || External || Log)) ||
00546 ((OperationType ==
HINIT_MEMORY) && (!ARGUMENT_PRESENT(HiveData))) ||
00547 (Log && (FileType !=
HFILE_TYPE_LOG)) ||
00548 (Alternate && (FileType !=
HFILE_TYPE_ALTERNATE))
00549 )
00550 {
00551
return (STATUS_INVALID_PARAMETER);
00552 }
00553
00554
00555
00556
00557
if (Primary) {
00558
00559
ASSERT_PASSIVE_LEVEL();
00560
Status = ZwQueryVolumeInformationFile(
00561 Primary,
00562 &IoStatusBlock,
00563 &FsSizeInformation,
00564
sizeof(FILE_FS_SIZE_INFORMATION),
00565 FileFsSizeInformation
00566 );
00567
if (!
NT_SUCCESS(
Status)) {
00568
return (
Status);
00569 }
00570
if (FsSizeInformation.BytesPerSector >
HBLOCK_SIZE) {
00571
return (STATUS_REGISTRY_IO_FAILED);
00572 }
00573 Cluster = FsSizeInformation.BytesPerSector /
HSECTOR_SIZE;
00574 Cluster = (Cluster < 1) ? 1 : Cluster;
00575 }
else {
00576 Cluster = 1;
00577 }
00578
00579 cmhive2 =
CmpAllocate(
sizeof(
CMHIVE),
FALSE);
00580
if (cmhive2 ==
NULL) {
00581
return (STATUS_INSUFFICIENT_RESOURCES);
00582 }
00583
00584
00585
00586
00587 cmhive2->
HiveLock = (
PFAST_MUTEX)
ExAllocatePoolWithTag(
NonPagedPool,
sizeof(
FAST_MUTEX), CM_POOL_TAG );
00588
if( cmhive2->
HiveLock ==
NULL ) {
00589
CmpFree(cmhive2,
sizeof(
CMHIVE));
00590
return (STATUS_INSUFFICIENT_RESOURCES);
00591 }
00592
00593
00594
00595
00596
00597
ASSERT((
HFILE_TYPE_EXTERNAL+1) ==
HFILE_TYPE_MAX);
00598 cmhive2->
FileHandles[
HFILE_TYPE_PRIMARY] = Primary;
00599 cmhive2->
FileHandles[
HFILE_TYPE_ALTERNATE] = Alternate;
00600 cmhive2->
FileHandles[
HFILE_TYPE_LOG] = Log;
00601 cmhive2->
FileHandles[
HFILE_TYPE_EXTERNAL] = External;
00602
00603 cmhive2->
NotifyList.Flink =
NULL;
00604 cmhive2->
NotifyList.Blink =
NULL;
00605
00606
ExInitializeFastMutex(cmhive2->
HiveLock);
00607
00608
00609
00610
00611
Status =
HvInitializeHive(
00612 &(cmhive2->
Hive),
00613 OperationType,
00614 HiveFlags,
00615 FileType,
00616 HiveData,
00617
CmpAllocate,
00618
CmpFree,
00619
CmpFileSetSize,
00620
CmpFileWrite,
00621
CmpFileRead,
00622
CmpFileFlush,
00623 Cluster,
00624
FileName
00625 );
00626
if (!
NT_SUCCESS(
Status)) {
00627
CMLOG(
CML_MAJOR,
CMS_INIT_ERROR) {
00628 KdPrint((
"CmpInitializeHive: "));
00629 KdPrint((
"HvInitializeHive failed, Status = %08lx\n",
Status));
00630 }
00631
ASSERT( cmhive2->
HiveLock );
00632
ExFreePool(cmhive2->
HiveLock);
00633
CmpFree(cmhive2,
sizeof(
CMHIVE));
00634
return (
Status);
00635 }
00636
if ( (OperationType ==
HINIT_FILE) ||
00637 (OperationType ==
HINIT_MEMORY) ||
00638 (OperationType ==
HINIT_MEMORY_INPLACE))
00639 {
00640 rc =
CmCheckRegistry(cmhive2,
TRUE);
00641
if (rc != 0) {
00642
CMLOG(
CML_MAJOR,
CMS_INIT_ERROR) {
00643 KdPrint((
"CmpInitializeHive: "));
00644 KdPrint((
"CmCheckRegistry failed, rc = %08lx\n",rc));
00645 }
00646
00647
00648
00649
00650
if (OperationType ==
HINIT_FILE) {
00651
HvFreeHive((
PHHIVE)cmhive2);
00652 }
00653
ASSERT( cmhive2->
HiveLock );
00654
ExFreePool(cmhive2->
HiveLock);
00655
CmpFree(cmhive2,
sizeof(
CMHIVE));
00656
return(STATUS_REGISTRY_CORRUPT);
00657 }
00658 }
00659
00660 InsertHeadList(&
CmpHiveListHead, &(cmhive2->
HiveList));
00661 *CmHive = cmhive2;
00662
return (STATUS_SUCCESS);
00663 }
00664
00665
00666 BOOLEAN
00667 CmpDestroyHive(
00668 IN
PHHIVE Hive,
00669 IN HCELL_INDEX Cell
00670 )
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691 {
00692
PCELL_DATA CellData;
00693
HCELL_INDEX LinkCell;
00694
NTSTATUS Status;
00695
00696
00697
00698
00699 CellData =
HvGetCell(
Hive,
Cell);
00700 LinkCell = CellData->
u.
KeyNode.
Parent;
00701
00702
00703
00704
00705
ASSERT(FIELD_OFFSET(
CMHIVE,
Hive) == 0);
00706
Status =
CmpFreeKeyByCell((
PHHIVE)
CmpMasterHive, LinkCell,
TRUE);
00707
00708
if (
NT_SUCCESS(
Status)) {
00709
00710
00711
00712 RemoveEntryList(&( ((
PCMHIVE)
Hive)->
HiveList));
00713
return(
TRUE);
00714 }
else {
00715
return(
FALSE);
00716 }
00717 }
00718
00719
00720
NTSTATUS
00721 CmpOpenFileWithExtremePrejudice(
00722 OUT PHANDLE Primary,
00723 IN POBJECT_ATTRIBUTES Obja,
00724 IN ULONG IoFlags,
00725 IN ULONG AttributeFlags
00726 )
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 {
00751
NTSTATUS Status;
00752 HANDLE
Handle;
00753 IO_STATUS_BLOCK IoStatusBlock;
00754 FILE_BASIC_INFORMATION FileInfo;
00755
00756
00757
00758
00759
ASSERT_PASSIVE_LEVEL();
00760
Status =
ZwQueryAttributesFile(Obja, &FileInfo);
00761
if (!
NT_SUCCESS(
Status)) {
00762
return(
Status);
00763 }
00764
00765
00766
00767
00768 FileInfo.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
00769
00770
00771
00772
00773
Status =
ZwOpenFile(&
Handle,
00774 FILE_WRITE_ATTRIBUTES,
00775 Obja,
00776 &IoStatusBlock,
00777 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
00778 FILE_OPEN_FOR_BACKUP_INTENT);
00779
if (!
NT_SUCCESS(
Status)) {
00780
return(
Status);
00781 }
00782
00783
00784
00785
00786
Status =
ZwSetInformationFile(
Handle,
00787 &IoStatusBlock,
00788 &FileInfo,
00789
sizeof(FileInfo),
00790 FileBasicInformation);
00791 ZwClose(
Handle);
00792
if (
NT_SUCCESS(
Status)) {
00793
00794
00795
00796
Status =
ZwCreateFile(Primary,
00797 FILE_READ_DATA | FILE_WRITE_DATA,
00798 Obja,
00799 &IoStatusBlock,
00800
NULL,
00801 AttributeFlags,
00802 0,
00803 FILE_OPEN,
00804 IoFlags,
00805
NULL,
00806 0);
00807 }
00808
00809
return(
Status);
00810
00811 }