00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "mi.h"
00024
00025 ULONG
MMCONTROL = 'aCmM';
00026 ULONG
MMTEMPORARY = 'xxmM';
00027 ULONG
MMSECT = 'tSmM';
00028
00029 #define MM_SIZE_OF_LARGEST_IMAGE ((ULONG)0x77000000)
00030
00031 #define MM_MAXIMUM_IMAGE_HEADER (2 * PAGE_SIZE)
00032
00033 #define MM_ALLOCATION_FRAGMENT (64 * 1024)
00034
00035
00036
00037
00038
00039
00040
00041 #define MM_MAXIMUM_IMAGE_SECTIONS \
00042
((MM_MAXIMUM_IMAGE_HEADER - (PAGE_SIZE + sizeof(IMAGE_NT_HEADERS))) / \
00043
sizeof(IMAGE_SECTION_HEADER))
00044
00045
#if DBG
00046
extern PEPROCESS MmWatchProcess;
00047
VOID MmFooBar(VOID);
00048
#endif // DBG
00049
00050 extern POBJECT_TYPE IoFileObjectType;
00051
00052 CCHAR
MmImageProtectionArray[16] = {
00053
MM_NOACCESS,
00054
MM_EXECUTE,
00055
MM_READONLY,
00056
MM_EXECUTE_READ,
00057
MM_WRITECOPY,
00058
MM_EXECUTE_WRITECOPY,
00059
MM_WRITECOPY,
00060
MM_EXECUTE_WRITECOPY,
00061
MM_NOACCESS,
00062
MM_EXECUTE,
00063
MM_READONLY,
00064
MM_EXECUTE_READ,
00065
MM_READWRITE,
00066
MM_EXECUTE_READWRITE,
00067
MM_READWRITE,
00068
MM_EXECUTE_READWRITE };
00069
00070
00071 CCHAR
00072
MiGetImageProtection (
00073 IN ULONG SectionCharacteristics
00074 );
00075
00076
NTSTATUS
00077
MiVerifyImageHeader (
00078 IN PIMAGE_NT_HEADERS NtHeader,
00079 IN PIMAGE_DOS_HEADER DosHeader,
00080 IN ULONG NtHeaderSize
00081 );
00082
00083 BOOLEAN
00084
MiCheckDosCalls (
00085 IN PIMAGE_OS2_HEADER Os2Header,
00086 IN ULONG HeaderSize
00087 );
00088
00089
PCONTROL_AREA
00090
MiFindImageSectionObject(
00091 IN
PFILE_OBJECT File,
00092 IN PBOOLEAN GlobalNeeded
00093 );
00094
00095
VOID
00096
MiInsertImageSectionObject(
00097 IN
PFILE_OBJECT File,
00098 IN
PCONTROL_AREA ControlArea
00099 );
00100
00101
VOID
00102
MiFlushDataSection(
00103 IN
PFILE_OBJECT File
00104 );
00105
00106
#ifdef ALLOC_PRAGMA
00107
#pragma alloc_text(PAGE,MiCreateImageFileMap)
00108
#pragma alloc_text(PAGE,NtCreateSection)
00109
#pragma alloc_text(PAGE,NtOpenSection)
00110
#pragma alloc_text(PAGE,MiGetImageProtection)
00111
#pragma alloc_text(PAGE,MiVerifyImageHeader)
00112
#pragma alloc_text(PAGE,MiCheckDosCalls)
00113
#pragma alloc_text(PAGE,MiCreatePagingFileMap)
00114
#pragma alloc_text(PAGE,MiCreateDataFileMap)
00115
00116
#pragma alloc_text(PAGEHYDRA,MiFindImageSectionObject)
00117
#pragma alloc_text(PAGEHYDRA,MiInsertImageSectionObject)
00118
#pragma alloc_text(PAGEHYDRA,MiRemoveImageSectionObject)
00119
#pragma alloc_text(PAGEHYDRA,MiGetWritablePagesInSection)
00120
#endif
00121
00122
#pragma pack (1)
00123 typedef struct _PHARLAP_CONFIG {
00124 UCHAR
uchCopyRight[0x32];
00125 USHORT usType;
00126 USHORT usRsv1;
00127 USHORT usRsv2;
00128 USHORT usSign;
00129 }
CONFIGPHARLAP, *
PCONFIGPHARLAP;
00130
#pragma pack ()
00131
00132
00133
NTSTATUS
00134 NtCreateSection (
00135 OUT PHANDLE SectionHandle,
00136 IN ACCESS_MASK DesiredAccess,
00137 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
00138 IN PLARGE_INTEGER MaximumSize OPTIONAL,
00139 IN ULONG SectionPageProtection,
00140 IN ULONG AllocationAttributes,
00141 IN HANDLE FileHandle OPTIONAL
00142 )
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 {
00227
NTSTATUS Status;
00228 PVOID Section;
00229 HANDLE
Handle;
00230 LARGE_INTEGER LargeSize;
00231 LARGE_INTEGER CapturedSize;
00232 ULONG RetryCount;
00233
00234
if ((AllocationAttributes & ~(SEC_COMMIT | SEC_RESERVE | SEC_BASED |
00235 SEC_IMAGE | SEC_NOCACHE | SEC_NO_CHANGE)) != 0) {
00236
return STATUS_INVALID_PARAMETER_6;
00237 }
00238
00239
if ((AllocationAttributes & (SEC_COMMIT | SEC_RESERVE | SEC_IMAGE)) == 0) {
00240
return STATUS_INVALID_PARAMETER_6;
00241 }
00242
00243
if ((AllocationAttributes & SEC_IMAGE) &&
00244 (AllocationAttributes & (SEC_COMMIT | SEC_RESERVE |
00245 SEC_NOCACHE | SEC_NO_CHANGE))) {
00246
00247
return STATUS_INVALID_PARAMETER_6;
00248 }
00249
00250
if ((AllocationAttributes & SEC_COMMIT) &&
00251 (AllocationAttributes & SEC_RESERVE)) {
00252
return STATUS_INVALID_PARAMETER_6;
00253 }
00254
00255
00256
00257
00258
00259
if ((SectionPageProtection & PAGE_NOCACHE) ||
00260 (SectionPageProtection & PAGE_GUARD) ||
00261 (SectionPageProtection & PAGE_NOACCESS)) {
00262
00263
00264
00265
00266
00267
00268
return STATUS_INVALID_PAGE_PROTECTION;
00269 }
00270
00271
00272
if (KeGetPreviousMode() !=
KernelMode) {
00273
try {
00274
ProbeForWriteHandle(SectionHandle);
00275
00276
if (ARGUMENT_PRESENT (MaximumSize)) {
00277
00278
00279
00280
00281
00282
00283
00284
ProbeForRead(MaximumSize,
sizeof(LARGE_INTEGER),
sizeof(UCHAR));
00285 LargeSize = *MaximumSize;
00286 }
else {
00287
ZERO_LARGE (LargeSize);
00288 }
00289
00290 } except (
EXCEPTION_EXECUTE_HANDLER) {
00291
return GetExceptionCode();
00292 }
00293 }
else {
00294
if (ARGUMENT_PRESENT (MaximumSize)) {
00295 LargeSize = *MaximumSize;
00296 }
else {
00297
ZERO_LARGE (LargeSize);
00298 }
00299 }
00300
00301 RetryCount = 0;
00302
00303 retry:
00304
00305 CapturedSize = LargeSize;
00306
00307
ASSERT (KeGetCurrentIrql() <
DISPATCH_LEVEL);
00308
Status =
MmCreateSection ( &Section,
00309 DesiredAccess,
00310
ObjectAttributes,
00311 &CapturedSize,
00312 SectionPageProtection,
00313 AllocationAttributes,
00314 FileHandle,
00315
NULL );
00316
00317
00318
ASSERT (KeGetCurrentIrql() <
DISPATCH_LEVEL);
00319
if (!
NT_SUCCESS(
Status)) {
00320
if ((
Status == STATUS_FILE_LOCK_CONFLICT) &&
00321 (RetryCount < 3)) {
00322
00323
00324
00325
00326
00327
00328 RetryCount += 1;
00329
00330
KeDelayExecutionThread (
KernelMode,
00331
FALSE,
00332 &
MmHalfSecond);
00333
00334
goto retry;
00335
00336 }
00337
return Status;
00338 }
00339
00340
#if DBG
00341
if (MmDebug &
MM_DBG_SECTIONS) {
00342
DbgPrint(
"inserting section %lx control %lx\n",Section,
00343 ((
PSECTION)Section)->Segment->ControlArea);
00344 }
00345
#endif
00346
00347 {
00348
PCONTROL_AREA ControlArea;
00349 ControlArea = ((
PSECTION)Section)->
Segment->
ControlArea;
00350
if ((ControlArea !=
NULL) && (ControlArea->
FilePointer !=
NULL)) {
00351
CcZeroEndOfLastPage (ControlArea->
FilePointer);
00352 }
00353 }
00354
00355
00356
00357
00358
00359
Status =
ObInsertObject (Section,
00360
NULL,
00361 DesiredAccess,
00362 0,
00363 (PVOID *)
NULL,
00364 &
Handle);
00365
00366
if (
NT_SUCCESS(
Status)) {
00367
try {
00368 *SectionHandle =
Handle;
00369 } except (
EXCEPTION_EXECUTE_HANDLER) {
00370
00371
00372
00373
00374
00375
00376 }
00377 }
00378
00379
#if DBG
00380
if (MmDebug &
MM_DBG_SHOW_NT_CALLS) {
00381
if ( !MmWatchProcess )
00382
DbgPrint(
"return creasect handle %lx status %lx\n",
Handle,
Status);
00383 }
00384
#endif
00385
00386
return Status;
00387 }
00388
00389
NTSTATUS
00390 MmCreateSection (
00391 OUT PVOID *SectionObject,
00392 IN ACCESS_MASK DesiredAccess,
00393 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
00394 IN PLARGE_INTEGER InputMaximumSize,
00395 IN ULONG SectionPageProtection,
00396 IN ULONG AllocationAttributes,
00397 IN HANDLE FileHandle OPTIONAL,
00398 IN
PFILE_OBJECT FileObject OPTIONAL
00399 )
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 {
00486
SECTION Section;
00487
PSECTION NewSection;
00488
PSEGMENT Segment;
00489
PSEGMENT NewSegment;
00490
KPROCESSOR_MODE PreviousMode;
00491 KIRQL OldIrql;
00492
NTSTATUS Status;
00493
PCONTROL_AREA ControlArea;
00494
PCONTROL_AREA NewControlArea;
00495
PCONTROL_AREA SegmentControlArea;
00496 ACCESS_MASK FileDesiredAccess;
00497
PFILE_OBJECT File;
00498
PEVENT_COUNTER Event;
00499 ULONG IgnoreFileSizing;
00500 ULONG ProtectionMask;
00501 ULONG ProtectMaskForAccess;
00502 ULONG FileAcquired;
00503
PEVENT_COUNTER SegmentEvent;
00504 BOOLEAN FileSizeChecked;
00505 LARGE_INTEGER TempSectionSize;
00506 UINT64 EndOfFile;
00507 ULONG IncrementedRefCount;
00508 ULONG ControlAreaSize;
00509 PUINT64 MaximumSize;
00510
PMMADDRESS_NODE *SectionBasedRoot;
00511 BOOLEAN GlobalNeeded;
00512
PFILE_OBJECT ChangeFileReference;
00513
#if DBG
00514
PVOID PreviousSectionPointer;
00515
#endif //DBG
00516
00517 DesiredAccess;
00518
00519 IgnoreFileSizing =
FALSE;
00520 FileAcquired =
FALSE;
00521 FileSizeChecked =
FALSE;
00522 IncrementedRefCount =
FALSE;
00523 ChangeFileReference =
NULL;
00524
00525 MaximumSize = (PUINT64) InputMaximumSize;
00526
00527
#if DBG
00528
if (MmDebug &
MM_DBG_SHOW_NT_CALLS) {
00529
if ( !MmWatchProcess ) {
00530
DbgPrint(
"crea sect access mask %lx maxsize %I64X page prot %lx\n",
00531 DesiredAccess, *MaximumSize, SectionPageProtection);
00532
DbgPrint(
" allocation attributes %lx file handle %lx\n",
00533 AllocationAttributes, FileHandle);
00534 }
00535 }
00536
#endif
00537
00538
00539
00540
00541
00542
File = (
PFILE_OBJECT)
NULL;
00543
00544
ASSERT ((AllocationAttributes & ~(SEC_COMMIT | SEC_RESERVE | SEC_BASED |
00545 SEC_IMAGE | SEC_NOCACHE | SEC_NO_CHANGE)) == 0);
00546
00547
ASSERT ((AllocationAttributes & (SEC_COMMIT | SEC_RESERVE | SEC_IMAGE)) != 0);
00548
00549
ASSERT (!((AllocationAttributes & SEC_IMAGE) &&
00550 (AllocationAttributes & (SEC_COMMIT | SEC_RESERVE |
00551 SEC_NOCACHE | SEC_NO_CHANGE))));
00552
00553
ASSERT (!((AllocationAttributes & SEC_COMMIT) &&
00554 (AllocationAttributes & SEC_RESERVE)));
00555
00556
ASSERT (!((SectionPageProtection & PAGE_NOCACHE) ||
00557 (SectionPageProtection & PAGE_GUARD) ||
00558 (SectionPageProtection & PAGE_NOACCESS)));
00559
00560
if (AllocationAttributes & SEC_NOCACHE) {
00561 SectionPageProtection |= PAGE_NOCACHE;
00562 }
00563
00564
00565
00566
00567
00568
try {
00569 ProtectionMask =
MiMakeProtectionMask (SectionPageProtection);
00570 } except (
EXCEPTION_EXECUTE_HANDLER) {
00571
return GetExceptionCode();
00572 }
00573
00574 ProtectMaskForAccess = ProtectionMask & 0x7;
00575
00576 FileDesiredAccess =
MmMakeFileAccess[ProtectMaskForAccess];
00577
00578
00579
00580
00581
00582 PreviousMode = KeGetPreviousMode();
00583
00584 Section.
InitialPageProtection = SectionPageProtection;
00585 Section.
Segment = (
PSEGMENT)
NULL;
00586
00587
if (ARGUMENT_PRESENT(FileHandle) || ARGUMENT_PRESENT(FileObject)) {
00588
00589
if (ARGUMENT_PRESENT(FileObject)) {
00590 IgnoreFileSizing =
TRUE;
00591
File = FileObject;
00592
00593
00594
00595
00596
00597
if (
File->SectionObjectPointer->DataSectionObject) {
00598
00599
LOCK_PFN (OldIrql);
00600 ControlArea =
00601 (
PCONTROL_AREA)(
File->SectionObjectPointer->DataSectionObject);
00602
00603
if ((ControlArea !=
NULL) &&
00604 (!ControlArea->
u.Flags.BeingDeleted) &&
00605 (!ControlArea->
u.Flags.BeingCreated)) {
00606
00607
00608
00609
00610
00611
00612 NewSegment = ControlArea->
Segment;
00613
if ((ControlArea->
NumberOfSectionReferences == 0) &&
00614 (ControlArea->
NumberOfMappedViews == 0) &&
00615 (ControlArea->
ModifiedWriteCount == 0)) {
00616
00617
00618
00619
00620
00621
00622 ChangeFileReference = ControlArea->
FilePointer;
00623 ControlArea->
FilePointer = FileObject;
00624
00625
00626
00627
00628
00629
00630
00631
00632
ObDereferenceObject (ChangeFileReference);
00633 }
00634 ControlArea->
u.Flags.Accessed = 1;
00635 ControlArea->
NumberOfSectionReferences += 1;
00636
if (ControlArea->
DereferenceList.Flink !=
NULL) {
00637
00638
00639
00640
00641
00642 RemoveEntryList (&ControlArea->
DereferenceList);
00643
00644
MI_UNUSED_SEGMENTS_REMOVE_CHARGE (ControlArea);
00645
00646 ControlArea->
DereferenceList.Flink =
NULL;
00647 ControlArea->
DereferenceList.Blink =
NULL;
00648 }
00649
UNLOCK_PFN (OldIrql);
00650 IncrementedRefCount =
TRUE;
00651 Section.
SizeOfSection.QuadPart = (LONGLONG)*MaximumSize;
00652
00653
goto ReferenceObject;
00654 }
00655
UNLOCK_PFN (OldIrql);
00656 }
00657
00658
ObReferenceObject (FileObject);
00659
00660 }
else {
00661
00662
00663
00664
00665
00666
00667
00668
00669
Status =
ObReferenceObjectByHandle ( FileHandle,
00670 FileDesiredAccess,
00671
IoFileObjectType,
00672 PreviousMode,
00673 (PVOID *)&
File,
00674
NULL );
00675
if (!
NT_SUCCESS(
Status)) {
00676
return Status;
00677 }
00678
00679
00680
00681
00682
00683
00684
if (
File->SectionObjectPointer ==
NULL) {
00685
ObDereferenceObject (
File);
00686
return STATUS_INVALID_FILE_FOR_SECTION;
00687 }
00688 }
00689
00690
00691
00692
00693
00694
00695
00696
00697
if (
MiHydra ==
TRUE && (AllocationAttributes & SEC_IMAGE)) {
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 ControlAreaSize = (ULONG)
sizeof(
LARGE_CONTROL_AREA) +
00711 (ULONG)
sizeof(
SUBSECTION);
00712 }
00713
else {
00714 ControlAreaSize = (ULONG)
sizeof(
CONTROL_AREA) +
00715 (ULONG)
sizeof(
SUBSECTION);
00716 }
00717
00718 NewControlArea =
ExAllocatePoolWithTag (
NonPagedPool,
00719 ControlAreaSize,
00720
MMCONTROL);
00721
00722
if (NewControlArea ==
NULL) {
00723
ObDereferenceObject (
File);
00724
return STATUS_INSUFFICIENT_RESOURCES;
00725 }
00726
00727 RtlZeroMemory (NewControlArea, ControlAreaSize);
00728
00729 NewControlArea->
NonPagedPoolUsage =
EX_REAL_POOL_USAGE(ControlAreaSize);
00730
00731 NewSegment = (
PSEGMENT)
NULL;
00732
00733
00734
00735
00736
00737
00738
if (ARGUMENT_PRESENT(FileHandle)) {
00739
00740
FsRtlAcquireFileExclusive (
File);
00741
IoSetTopLevelIrp((
PIRP)
FSRTL_FSP_TOP_LEVEL_IRP);
00742 FileAcquired =
TRUE;
00743 }
00744
00745
LOCK_PFN (OldIrql);
00746
00747
00748
00749
00750
00751
00752
00753 ReallocateandcheckSegment:
00754
00755 SegmentEvent =
MiGetEventCounter();
00756
00757
if (SegmentEvent ==
NULL) {
00758
UNLOCK_PFN (OldIrql);
00759
if (FileAcquired) {
00760
IoSetTopLevelIrp((
PIRP)
NULL);
00761
FsRtlReleaseFile (
File);
00762 }
00763
ExFreePool (NewControlArea);
00764
ObDereferenceObject (
File);
00765
return STATUS_INSUFFICIENT_RESOURCES;
00766 }
00767
00768 RecheckSegment:
00769
00770
if (AllocationAttributes & SEC_IMAGE) {
00771
00772
if (
MiHydra ==
TRUE) {
00773 ControlArea =
MiFindImageSectionObject (
File, &GlobalNeeded);
00774 }
00775
else {
00776 ControlArea =
00777 (
PCONTROL_AREA)(
File->SectionObjectPointer->ImageSectionObject);
00778 }
00779 }
else {
00780 ControlArea =
00781 (
PCONTROL_AREA)(
File->SectionObjectPointer->DataSectionObject);
00782 }
00783
00784
if (ControlArea !=
NULL) {
00785
00786
00787
00788
00789
00790
00791
00792
if ((ControlArea->
u.Flags.BeingDeleted) ||
00793 (ControlArea->
u.Flags.BeingCreated)) {
00794
00795
00796
00797
00798
00799
00800
00801
00802
if (ControlArea->
WaitingForDeletion ==
NULL) {
00803
00804
00805
00806
00807
00808 ControlArea->
WaitingForDeletion = SegmentEvent;
00809
Event = SegmentEvent;
00810 SegmentEvent =
NULL;
00811 }
else {
00812
Event = ControlArea->
WaitingForDeletion;
00813
Event->RefCount += 1;
00814 }
00815
00816
00817
00818
00819
00820
UNLOCK_PFN (OldIrql);
00821
if (FileAcquired) {
00822
IoSetTopLevelIrp((
PIRP)
NULL);
00823
FsRtlReleaseFile (
File);
00824 }
00825
00826
KeWaitForSingleObject(&
Event->Event,
00827
WrVirtualMemory,
00828
KernelMode,
00829
FALSE,
00830 (PLARGE_INTEGER)
NULL);
00831
00832
if (FileAcquired) {
00833
FsRtlAcquireFileExclusive (
File);
00834
IoSetTopLevelIrp((
PIRP)
FSRTL_FSP_TOP_LEVEL_IRP);
00835 }
00836
00837
LOCK_PFN (OldIrql);
00838
MiFreeEventCounter (
Event,
TRUE);
00839
00840
if (SegmentEvent ==
NULL) {
00841
00842
00843
00844
00845
00846
00847
goto ReallocateandcheckSegment;
00848 }
00849
goto RecheckSegment;
00850
00851 }
else {
00852
00853
00854
00855
00856
00857
00858
00859 NewSegment = ControlArea->
Segment;
00860 ControlArea->
u.Flags.Accessed = 1;
00861 ControlArea->
NumberOfSectionReferences += 1;
00862
if (ControlArea->
DereferenceList.Flink !=
NULL) {
00863
00864
00865
00866
00867
00868 RemoveEntryList (&ControlArea->
DereferenceList);
00869
00870
MI_UNUSED_SEGMENTS_REMOVE_CHARGE (ControlArea);
00871
00872 ControlArea->
DereferenceList.Flink =
NULL;
00873 ControlArea->
DereferenceList.Blink =
NULL;
00874 }
00875 IncrementedRefCount =
TRUE;
00876
00877
00878
00879
00880
00881
00882
if (IgnoreFileSizing ==
FALSE) {
00883 ControlArea->
NumberOfUserReferences += 1;
00884 }
00885 }
00886 }
else {
00887
00888
00889
00890
00891
00892
00893 ControlArea = NewControlArea;
00894 ControlArea->
u.Flags.BeingCreated = 1;
00895
00896
if (AllocationAttributes & SEC_IMAGE) {
00897
if (
MiHydra ==
TRUE) {
00898
if (GlobalNeeded ==
TRUE) {
00899 ControlArea->
u.Flags.GlobalOnlyPerSession = 1;
00900 }
00901
00902
MiInsertImageSectionObject (
File, ControlArea);
00903 }
00904
else {
00905 ((
PCONTROL_AREA)((
File->SectionObjectPointer->ImageSectionObject))) =
00906 ControlArea;
00907 }
00908 }
else {
00909
#if DBG
00910
PreviousSectionPointer =
File->SectionObjectPointer;
00911
#endif //DBG
00912
((
PCONTROL_AREA)((
File->SectionObjectPointer->DataSectionObject))) =
00913 ControlArea;
00914 }
00915 }
00916
00917
if (SegmentEvent !=
NULL) {
00918
MiFreeEventCounter (SegmentEvent,
TRUE);
00919 }
00920
00921
UNLOCK_PFN (OldIrql);
00922
00923
if (NewSegment != (
PSEGMENT)
NULL) {
00924
00925
00926
00927
00928
00929
00930
if (AllocationAttributes & SEC_IMAGE) {
00931
MiFlushDataSection (
File);
00932 }
00933
00934
00935
00936
00937
00938
00939
00940
ExFreePool (NewControlArea);
00941
00942
00943
00944
00945
00946
00947
if ((!IgnoreFileSizing) && (ControlArea->
u.Flags.Image == 0)) {
00948
00949
00950
00951
00952
00953
00954
00955
Status =
FsRtlGetFileSize (
File, (PLARGE_INTEGER)&EndOfFile );
00956
00957
if (!
NT_SUCCESS (
Status)) {
00958
00959
if (FileAcquired) {
00960
IoSetTopLevelIrp((
PIRP)
NULL);
00961
FsRtlReleaseFile (
File);
00962 FileAcquired =
FALSE;
00963 }
00964
00965
ObDereferenceObject (
File);
00966
goto UnrefAndReturn;
00967 }
00968
00969
if (EndOfFile == 0 && *MaximumSize == 0) {
00970
00971
00972
00973
00974
00975
00976
Status = STATUS_MAPPED_FILE_SIZE_ZERO;
00977
00978
if (FileAcquired) {
00979
IoSetTopLevelIrp((
PIRP)
NULL);
00980
FsRtlReleaseFile (
File);
00981 FileAcquired =
FALSE;
00982 }
00983
00984
ObDereferenceObject (
File);
00985
goto UnrefAndReturn;
00986 }
00987 }
else {
00988
00989
00990
00991
00992
00993 EndOfFile = (UINT64) NewSegment->
SizeOfSegment;
00994 }
00995
00996
if (FileAcquired) {
00997
IoSetTopLevelIrp((
PIRP)
NULL);
00998
FsRtlReleaseFile (
File);
00999 FileAcquired =
FALSE;
01000 }
01001
01002
ObDereferenceObject (
File);
01003
01004
if (*MaximumSize == 0) {
01005
01006 Section.
SizeOfSection.QuadPart = (LONGLONG)EndOfFile;
01007 FileSizeChecked =
TRUE;
01008
01009 }
else if (EndOfFile >= *MaximumSize) {
01010
01011
01012
01013
01014
01015
01016 Section.
SizeOfSection.QuadPart = (LONGLONG)*MaximumSize;
01017 FileSizeChecked =
TRUE;
01018
01019 }
else {
01020
01021
01022
01023
01024
01025
01026
if (((SectionPageProtection & PAGE_READWRITE) |
01027 (SectionPageProtection & PAGE_EXECUTE_READWRITE)) == 0) {
01028
01029
Status = STATUS_SECTION_TOO_BIG;
01030
goto UnrefAndReturn;
01031 }
01032 Section.
SizeOfSection.QuadPart = (LONGLONG)*MaximumSize;
01033 }
01034
01035 }
else {
01036
01037
01038
01039
01040
01041
01042
if (AllocationAttributes & SEC_IMAGE) {
01043
01044
Status =
MiCreateImageFileMap (
File, &Segment);
01045
01046 }
else {
01047
01048
Status =
MiCreateDataFileMap (
File,
01049 &Segment,
01050 MaximumSize,
01051 SectionPageProtection,
01052 AllocationAttributes,
01053 IgnoreFileSizing );
01054
ASSERT (PreviousSectionPointer ==
File->SectionObjectPointer);
01055 }
01056
01057
if (!
NT_SUCCESS(
Status)) {
01058
01059
01060
01061
01062
01063
01064
01065
LOCK_PFN (OldIrql);
01066
01067
Event = ControlArea->
WaitingForDeletion;
01068 ControlArea->
WaitingForDeletion =
NULL;
01069
ASSERT (ControlArea->
u.Flags.FilePointerNull == 0);
01070 ControlArea->
u.Flags.FilePointerNull = 1;
01071
01072
if (AllocationAttributes & SEC_IMAGE) {
01073
if (
MiHydra ==
TRUE) {
01074
MiRemoveImageSectionObject (
File, ControlArea);
01075 }
01076
else {
01077 (
PCONTROL_AREA)((
File->SectionObjectPointer->ImageSectionObject)) =
01078
NULL;
01079 }
01080 }
else {
01081 (
PCONTROL_AREA)((
File->SectionObjectPointer->DataSectionObject)) =
01082
NULL;
01083 }
01084 ControlArea->
u.Flags.BeingCreated = 0;
01085
01086
UNLOCK_PFN (OldIrql);
01087
01088
if (FileAcquired) {
01089
IoSetTopLevelIrp((
PIRP)
NULL);
01090
FsRtlReleaseFile (
File);
01091 }
01092
01093
ExFreePool (NewControlArea);
01094
01095
ObDereferenceObject (
File);
01096
01097
if (
Event !=
NULL) {
01098
01099
01100
01101
01102
01103
KeSetEvent (&
Event->Event, 0,
FALSE);
01104 }
01105
01106
return Status;
01107 }
01108
01109
01110
01111
01112
01113
01114
01115
01116
if (*MaximumSize == 0) {
01117 Section.
SizeOfSection.QuadPart = (LONGLONG)Segment->
SizeOfSegment;
01118 }
else {
01119 Section.
SizeOfSection.QuadPart = (LONGLONG)*MaximumSize;
01120 }
01121 }
01122
01123 }
else {
01124
01125
01126
01127
01128
01129
if (AllocationAttributes & SEC_IMAGE) {
01130
return STATUS_INVALID_FILE_FOR_SECTION;
01131 }
01132
01133
Status =
MiCreatePagingFileMap ( &NewSegment,
01134 MaximumSize,
01135 ProtectionMask,
01136 AllocationAttributes);
01137
01138
if (!
NT_SUCCESS(
Status)) {
01139
return Status;
01140 }
01141
01142
01143
01144
01145
01146
01147
01148 Section.
SizeOfSection.QuadPart = (LONGLONG)NewSegment->
SizeOfSegment;
01149 ControlArea = NewSegment->
ControlArea;
01150 }
01151
01152
#if DBG
01153
if (MmDebug &
MM_DBG_SECTIONS) {
01154
if (NewSegment == (
PSEGMENT)
NULL) {
01155
DbgPrint(
"inserting segment %lx control %lx\n",Segment,
01156 Segment->
ControlArea);
01157 }
else {
01158
DbgPrint(
"inserting segment %lx control %lx\n",NewSegment,
01159 NewSegment->
ControlArea);
01160 }
01161 }
01162
#endif
01163
01164
01165
if (NewSegment == (
PSEGMENT)
NULL) {
01166 NewSegment = Segment;
01167
01168
01169
01170
01171
01172
01173 SegmentControlArea = Segment->ControlArea;
01174
01175
ASSERT (
File !=
NULL);
01176
01177
LOCK_PFN (OldIrql);
01178
01179
Event = ControlArea->
WaitingForDeletion;
01180 ControlArea->
WaitingForDeletion =
NULL;
01181
01182
if (AllocationAttributes & SEC_IMAGE) {
01183
01184
01185
01186
01187
01188
if (
MiHydra ==
TRUE) {
01189
MiRemoveImageSectionObject (
File, NewControlArea);
01190
MiInsertImageSectionObject (
File, SegmentControlArea);
01191 }
01192
else {
01193 ((
PCONTROL_AREA)(
File->SectionObjectPointer->ImageSectionObject)) =
01194 SegmentControlArea;
01195 }
01196
01197 ControlArea = SegmentControlArea;
01198 }
01199
01200 ControlArea->
u.Flags.BeingCreated = 0;
01201
01202
UNLOCK_PFN (OldIrql);
01203
01204
if (AllocationAttributes & SEC_IMAGE) {
01205
01206
01207
01208
01209
01210
ExFreePool (NewControlArea);
01211 }
01212
01213
if (
Event !=
NULL) {
01214
01215
01216
01217
01218
01219
KeSetEvent (&
Event->Event, 0,
FALSE);
01220 }
01221
01222
PERFINFO_SECTION_CREATE(ControlArea);
01223 }
01224
01225
01226
01227
01228
01229
01230
if (FileAcquired) {
01231
IoSetTopLevelIrp((
PIRP)
NULL);
01232
FsRtlReleaseFile (
File);
01233 FileAcquired =
FALSE;
01234 }
01235
01236 ReferenceObject:
01237
01238
if (ChangeFileReference) {
01239
ObReferenceObject (FileObject);
01240 }
01241
01242
01243
01244
01245
01246
01247 Section.
Segment = NewSegment;
01248 Section.
u.LongFlags = ControlArea->
u.LongFlags;
01249
01250
01251
01252
01253
01254
01255
01256
Status =
ObCreateObject (PreviousMode,
01257
MmSectionObjectType,
01258
ObjectAttributes,
01259 PreviousMode,
01260
NULL,
01261
sizeof(
SECTION),
01262
sizeof(
SECTION) +
01263 NewSegment->
TotalNumberOfPtes *
sizeof(
MMPTE),
01264
sizeof(
CONTROL_AREA) +
01265 NewSegment->
ControlArea->
NumberOfSubsections *
01266
sizeof(
SUBSECTION),
01267 (PVOID *)&NewSection);
01268
01269
if (!
NT_SUCCESS(
Status)) {
01270
goto UnrefAndReturn;
01271 }
01272
01273 RtlMoveMemory (NewSection, &Section,
sizeof(
SECTION));
01274 NewSection->Address.StartingVpn = 0;
01275
01276
if (!IgnoreFileSizing) {
01277
01278
01279
01280
01281
01282
01283 NewSection->u.Flags.UserReference = 1;
01284
01285
if (AllocationAttributes & SEC_NO_CHANGE) {
01286
01287
01288
01289
01290
01291
01292 NewSection->u.Flags.NoChange = 1;
01293 }
01294
01295
if (((SectionPageProtection & PAGE_READWRITE) |
01296 (SectionPageProtection & PAGE_EXECUTE_READWRITE)) == 0) {
01297
01298
01299
01300
01301
01302
01303 NewSection->u.Flags.CopyOnWrite = 1;
01304 }
01305
01306
if (AllocationAttributes & SEC_BASED) {
01307
01308 NewSection->u.Flags.Based = 1;
01309
01310 SectionBasedRoot = &
MmSectionBasedRoot;
01311
01312
01313
01314
01315
01316 ExAcquireFastMutex (&
MmSectionBasedMutex);
01317
01318
01319
01320
01321
01322
try {
01323 NewSection->Address.StartingVpn = (ULONG_PTR)
MiFindEmptySectionBaseDown (
01324 NewSection->SizeOfSection.LowPart,
01325
MmHighSectionBase);
01326
01327 } except (
EXCEPTION_EXECUTE_HANDLER) {
01328 ExReleaseFastMutex (&
MmSectionBasedMutex);
01329
ObDereferenceObject (NewSection);
01330
return Status;
01331 }
01332
01333 NewSection->Address.EndingVpn = NewSection->Address.StartingVpn +
01334 NewSection->SizeOfSection.LowPart - 1;
01335
01336
MiInsertBasedSection (NewSection);
01337 ExReleaseFastMutex (&
MmSectionBasedMutex);
01338 }
01339 }
01340
01341
01342
01343
01344
01345
01346 ControlArea->
u.Flags.WasPurged |= IgnoreFileSizing;
01347
01348
01349
01350
01351
01352
01353
01354
if (((ControlArea->
u.Flags.WasPurged == 1) && (!IgnoreFileSizing)) &&
01355 (!FileSizeChecked)
01356 ||
01357 ((UINT64)NewSection->SizeOfSection.QuadPart >
01358 NewSection->Segment->SizeOfSegment)) {
01359
01360 TempSectionSize = NewSection->SizeOfSection;
01361
01362 NewSection->SizeOfSection.QuadPart = (LONGLONG)NewSection->Segment->SizeOfSegment;
01363
01364
01365
01366
01367
01368
01369
01370
01371
if (((NewSection->InitialPageProtection & PAGE_READWRITE) |
01372 (NewSection->InitialPageProtection & PAGE_EXECUTE_READWRITE)) == 0) {
01373
SECTION WritableSection;
01374
01375 *(
PSECTION)&WritableSection = *NewSection;
01376
01377
Status =
MmExtendSection (&WritableSection,
01378 &TempSectionSize,
01379 IgnoreFileSizing);
01380
01381 NewSection->SizeOfSection = WritableSection.
SizeOfSection;
01382 }
01383
else {
01384
Status =
MmExtendSection (NewSection,
01385 &TempSectionSize,
01386 IgnoreFileSizing);
01387 }
01388
01389
if (!
NT_SUCCESS(
Status)) {
01390
ObDereferenceObject (NewSection);
01391
return Status;
01392 }
01393 }
01394
01395 *SectionObject = (PVOID)NewSection;
01396
01397
return Status;
01398
01399 UnrefAndReturn:
01400
01401
01402
01403
01404
01405
01406
if (FileAcquired) {
01407
IoSetTopLevelIrp((
PIRP)
NULL);
01408
FsRtlReleaseFile (
File);
01409 }
01410
01411
if (IncrementedRefCount) {
01412
LOCK_PFN (OldIrql);
01413 ControlArea->
NumberOfSectionReferences -= 1;
01414
if (!IgnoreFileSizing) {
01415
ASSERT ((LONG)ControlArea->
NumberOfUserReferences > 0);
01416 ControlArea->
NumberOfUserReferences -= 1;
01417 }
01418
MiCheckControlArea (ControlArea,
NULL, OldIrql);
01419 }
01420
return Status;
01421 }
01422
01423
NTSTATUS
01424 MiCreateImageFileMap (
01425 IN
PFILE_OBJECT File,
01426 OUT
PSEGMENT *Segment
01427 )
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 {
01456
NTSTATUS Status;
01457 ULONG_PTR EndingAddress;
01458 ULONG NumberOfPtes;
01459 ULONG SizeOfSegment;
01460 ULONG SectionVirtualSize;
01461 ULONG i;
01462 ULONG j;
01463
PCONTROL_AREA ControlArea;
01464
PSUBSECTION Subsection;
01465
PMMPTE PointerPte;
01466
MMPTE TempPte;
01467
MMPTE TempPteDemandZero;
01468 PVOID Base;
01469 PIMAGE_DOS_HEADER DosHeader;
01470 PIMAGE_NT_HEADERS NtHeader;
01471 PIMAGE_FILE_HEADER FileHeader;
01472 ULONG SizeOfImage;
01473 ULONG SizeOfHeaders;
01474
#if defined(_WIN64)
01475
PIMAGE_NT_HEADERS32 NtHeader32;
01476
#endif
01477
PIMAGE_SECTION_HEADER SectionTableEntry;
01478
PSEGMENT NewSegment;
01479 ULONG
SectorOffset;
01480 ULONG NumberOfSubsections;
01481 PFN_NUMBER PageFrameNumber;
01482 LARGE_INTEGER StartingOffset;
01483 PCHAR ExtendedHeader;
01484 PPFN_NUMBER Page;
01485 ULONG_PTR PreferredImageBase;
01486 ULONG_PTR NextVa;
01487
PKEVENT InPageEvent;
01488
PMDL Mdl;
01489 ULONG ImageFileSize;
01490 ULONG OffsetToSectionTable;
01491 ULONG ImageAlignment;
01492 ULONG RoundingAlignment;
01493 ULONG FileAlignment;
01494 BOOLEAN ImageCommit;
01495 BOOLEAN SectionCommit;
01496 IO_STATUS_BLOCK IoStatus;
01497 LARGE_INTEGER EndOfFile;
01498 ULONG NtHeaderSize;
01499 ULONG SubsectionsAllocated;
01500
PLARGE_CONTROL_AREA LargeControlArea;
01501
PSUBSECTION NewSubsection;
01502 ULONG OriginalProtection;
01503 ULONG LoaderFlags;
01504
01505
#if defined (_ALPHA_) || defined(_IA64_)
01506
01507
01508 BOOLEAN InvalidAlignmentAllowed =
FALSE;
01509
01510 ULONG TempNumberOfSubsections;
01511 PIMAGE_SECTION_HEADER TempSectionTableEntry;
01512 ULONG AdditionalSubsections;
01513 ULONG AdditionalPtes;
01514 ULONG AdditionalBasePtes;
01515 ULONG NewSubsectionsAllocated;
01516
PSEGMENT OldSegment;
01517
PMMPTE NewPointerPte;
01518
PMMPTE OldPointerPte;
01519 ULONG OrigNumberOfPtes;
01520
PCONTROL_AREA NewControlArea;
01521
01522
#endif
01523
01524 ExtendedHeader =
NULL;
01525
01526
01527
01528
01529
01530
PAGED_CODE();
01531
01532
01533
Status =
FsRtlGetFileSize (
File, &EndOfFile);
01534
01535
if (
Status == STATUS_FILE_IS_A_DIRECTORY) {
01536
01537
01538
01539
01540
01541
return STATUS_INVALID_FILE_FOR_SECTION;
01542 }
01543
01544
if (!
NT_SUCCESS (
Status)) {
01545
return Status;
01546 }
01547
01548
if (EndOfFile.HighPart != 0) {
01549
01550
01551
01552
01553
01554
return STATUS_INVALID_FILE_FOR_SECTION;
01555 }
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567 InPageEvent =
ExAllocatePoolWithTag (
NonPagedPool,
01568
sizeof(
KEVENT) +
MmSizeOfMdl (
01569
NULL,
01570
MM_MAXIMUM_IMAGE_HEADER),
01571
MMTEMPORARY);
01572
if (InPageEvent ==
NULL) {
01573
return STATUS_INSUFFICIENT_RESOURCES;
01574 }
01575
01576 Mdl = (
PMDL)(InPageEvent + 1);
01577
01578
01579
01580
01581
01582
KeInitializeEvent (InPageEvent, NotificationEvent,
FALSE);
01583
01584
01585
01586
01587
01588
MmCreateMdl( Mdl,
NULL,
PAGE_SIZE);
01589 Mdl->
MdlFlags |=
MDL_PAGES_LOCKED;
01590
01591 PageFrameNumber =
MiGetPageForHeader();
01592
01593 Page = (PPFN_NUMBER)(Mdl + 1);
01594 *Page = PageFrameNumber;
01595
01596
ZERO_LARGE (StartingOffset);
01597
01598
CcZeroEndOfLastPage (
File);
01599
01600
01601
01602
01603
01604
MiFlushDataSection (
File);
01605
01606 Mdl->
MdlFlags |=
MDL_PAGES_LOCKED;
01607
Status =
IoPageRead (
File,
01608 Mdl,
01609 &StartingOffset,
01610 InPageEvent,
01611 &IoStatus
01612 );
01613
01614
if (
Status == STATUS_PENDING) {
01615
KeWaitForSingleObject( InPageEvent,
01616
WrPageIn,
01617
KernelMode,
01618
FALSE,
01619 (PLARGE_INTEGER)
NULL);
01620 }
01621
01622
if (Mdl->
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
01623
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
01624 }
01625
01626
if ((!
NT_SUCCESS(
Status)) || (!
NT_SUCCESS(IoStatus.Status))) {
01627
if (
Status != STATUS_FILE_LOCK_CONFLICT) {
01628
Status = STATUS_INVALID_FILE_FOR_SECTION;
01629 }
01630
goto BadSection;
01631 }
01632
01633 Base =
MiMapImageHeaderInHyperSpace (PageFrameNumber);
01634 DosHeader = (PIMAGE_DOS_HEADER)Base;
01635
01636
if (IoStatus.Information !=
PAGE_SIZE) {
01637
01638
01639
01640
01641
01642
01643 RtlZeroMemory ((PVOID)((PCHAR)Base + IoStatus.Information),
01644
PAGE_SIZE - IoStatus.Information);
01645 }
01646
01647
01648
01649
01650
01651
01652
01653
01654
if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
01655
01656
Status = STATUS_INVALID_IMAGE_NOT_MZ;
01657
goto NeImage;
01658 }
01659
01660
#ifndef i386
01661
if (((ULONG)DosHeader->e_lfanew & 3) != 0) {
01662
01663
01664
01665
01666
01667
01668
Status = STATUS_INVALID_IMAGE_PROTECT;
01669
goto NeImage;
01670 }
01671
#endif
01672
01673
if ((ULONG)DosHeader->e_lfanew > EndOfFile.LowPart) {
01674
Status = STATUS_INVALID_IMAGE_PROTECT;
01675
goto NeImage;
01676 }
01677
01678
if (((ULONG)DosHeader->e_lfanew +
01679
sizeof(IMAGE_NT_HEADERS) +
01680 (16 *
sizeof(IMAGE_SECTION_HEADER))) <= (ULONG)DosHeader->e_lfanew) {
01681
Status = STATUS_INVALID_IMAGE_PROTECT;
01682
goto NeImage;
01683 }
01684
01685
if (((ULONG)DosHeader->e_lfanew +
01686
sizeof(IMAGE_NT_HEADERS) +
01687 (16 *
sizeof(IMAGE_SECTION_HEADER))) >
PAGE_SIZE) {
01688
01689
01690
01691
01692
01693
01694
01695 ExtendedHeader =
ExAllocatePoolWithTag (
NonPagedPool,
01696
MM_MAXIMUM_IMAGE_HEADER,
01697
MMTEMPORARY);
01698
if (ExtendedHeader ==
NULL) {
01699
Status = STATUS_INSUFFICIENT_RESOURCES;
01700
goto NeImage;
01701 }
01702
01703
01704
01705
01706
01707
MmCreateMdl( Mdl, ExtendedHeader,
MM_MAXIMUM_IMAGE_HEADER);
01708
01709
MmBuildMdlForNonPagedPool (Mdl);
01710
01711 StartingOffset.LowPart = PtrToUlong(
PAGE_ALIGN ((ULONG)DosHeader->e_lfanew));
01712
01713
KeClearEvent (InPageEvent);
01714
Status =
IoPageRead (
File,
01715 Mdl,
01716 &StartingOffset,
01717 InPageEvent,
01718 &IoStatus
01719 );
01720
01721
if (
Status == STATUS_PENDING) {
01722
KeWaitForSingleObject( InPageEvent,
01723
WrPageIn,
01724
KernelMode,
01725
FALSE,
01726 (PLARGE_INTEGER)
NULL);
01727 }
01728
01729
if (Mdl->
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
01730
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
01731 }
01732
01733
if ((!
NT_SUCCESS(
Status)) || (!
NT_SUCCESS(IoStatus.Status))) {
01734
if (
Status != STATUS_FILE_LOCK_CONFLICT) {
01735
Status = STATUS_INVALID_FILE_FOR_SECTION;
01736 }
01737
goto NeImage;
01738 }
01739 NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)ExtendedHeader +
01740
BYTE_OFFSET((ULONG)DosHeader->e_lfanew));
01741 NtHeaderSize =
MM_MAXIMUM_IMAGE_HEADER -
01742 (ULONG)(
BYTE_OFFSET((ULONG)DosHeader->e_lfanew));
01743
01744 }
else {
01745 NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)DosHeader +
01746 (ULONG)DosHeader->e_lfanew);
01747 NtHeaderSize =
PAGE_SIZE - (ULONG)DosHeader->e_lfanew;
01748 }
01749 FileHeader = &NtHeader->FileHeader;
01750
01751
01752
01753
01754
01755
Status =
MiVerifyImageHeader (NtHeader, DosHeader, NtHeaderSize);
01756
if (
Status != STATUS_SUCCESS) {
01757
goto NeImage;
01758 }
01759
01760
#if defined(_WIN64)
01761
if (NtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
01762
01763
01764
01765
01766
01767 NtHeader32 = (PIMAGE_NT_HEADERS32)NtHeader;
01768 NtHeader =
NULL;
01769 }
else {
01770 NtHeader32 =
NULL;
01771 }
01772
01773
if (NtHeader) {
01774
#endif
01775
ImageAlignment = NtHeader->OptionalHeader.SectionAlignment;
01776 FileAlignment = NtHeader->OptionalHeader.FileAlignment - 1;
01777 SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
01778 LoaderFlags = NtHeader->OptionalHeader.LoaderFlags;
01779
#if defined (_WIN64)
01780
}
else {
01781 ImageAlignment = NtHeader32->OptionalHeader.SectionAlignment;
01782 FileAlignment = NtHeader32->OptionalHeader.FileAlignment - 1;
01783 SizeOfImage = NtHeader32->OptionalHeader.SizeOfImage;
01784 LoaderFlags = NtHeader32->OptionalHeader.LoaderFlags;
01785 }
01786
#endif
01787
01788 RoundingAlignment = ImageAlignment;
01789 NumberOfSubsections = FileHeader->NumberOfSections;
01790
01791
if (ImageAlignment <
PAGE_SIZE) {
01792
01793
01794
01795
01796
01797
01798 ControlArea =
ExAllocatePoolWithTag (
NonPagedPool,
01799 (ULONG)(
sizeof(
CONTROL_AREA) + (
sizeof(
SUBSECTION))),
01800
MMCONTROL);
01801 SubsectionsAllocated = 1;
01802 }
else {
01803
01804
01805
01806
01807
01808
01809 ControlArea =
ExAllocatePoolWithTag(
NonPagedPool,
01810 (ULONG)(
sizeof(
CONTROL_AREA) +
01811 (
sizeof(
SUBSECTION) *
01812 (NumberOfSubsections + 1))),
01813 'iCmM');
01814 SubsectionsAllocated = NumberOfSubsections + 1;
01815 }
01816
01817
if (ControlArea ==
NULL) {
01818
01819
01820
01821
01822
01823
Status = STATUS_INSUFFICIENT_RESOURCES;
01824
goto NeImage;
01825 }
01826
01827
01828
01829
01830
01831 RtlZeroMemory (ControlArea,
01832
sizeof(
CONTROL_AREA) +
sizeof(
SUBSECTION));
01833
01834 ControlArea->
NonPagedPoolUsage =
EX_REAL_POOL_USAGE(
sizeof(
CONTROL_AREA) +
01835
sizeof(
SUBSECTION) *
01836 SubsectionsAllocated);
01837
01838
ASSERT (ControlArea->
u.Flags.GlobalOnlyPerSession == 0);
01839
01840 Subsection = (
PSUBSECTION)(ControlArea + 1);
01841
01842 NumberOfPtes =
BYTES_TO_PAGES (SizeOfImage);
01843
01844
if (NumberOfPtes == 0) {
01845
ExFreePool (ControlArea);
01846
Status = STATUS_INVALID_IMAGE_FORMAT;
01847
goto NeImage;
01848 }
01849
01850
#if defined (_ALPHA_) || defined(_IA64_)
01851
if (ImageAlignment <
PAGE_SIZE && KeGetPreviousMode() !=
KernelMode &&
01852 (FileHeader->Machine < USER_SHARED_DATA->ImageNumberLow ||
01853 FileHeader->Machine > USER_SHARED_DATA->ImageNumberHigh)) {
01854
01855 InvalidAlignmentAllowed =
TRUE;
01856 }
01857 OrigNumberOfPtes = NumberOfPtes;
01858
#endif
01859
01860 SizeOfSegment =
sizeof(
SEGMENT) + (
sizeof(
MMPTE) * (NumberOfPtes - 1)) +
01861
sizeof(SECTION_IMAGE_INFORMATION);
01862
01863 NewSegment =
ExAllocatePoolWithTag (
PagedPool,
01864 SizeOfSegment,
01865
MMSECT);
01866
01867
if (NewSegment ==
NULL) {
01868
01869
01870
01871
01872
01873
ExFreePool (ControlArea);
01874
Status = STATUS_INSUFFICIENT_RESOURCES;
01875
goto NeImage;
01876 }
01877 *Segment = NewSegment;
01878 RtlZeroMemory (NewSegment,
sizeof(
SEGMENT));
01879
01880
01881
01882
01883
01884 PointerPte = &NewSegment->ThePtes[0];
01885 i = (ULONG) (((ULONG_PTR)PointerPte >>
PTE_SHIFT) &
01886 ((
MM_PROTO_PTE_ALIGNMENT /
PAGE_SIZE) - 1));
01887
01888
if (i != 0) {
01889 i = (
MM_PROTO_PTE_ALIGNMENT /
PAGE_SIZE) - i;
01890 }
01891
01892 NewSegment->PrototypePte = &NewSegment->ThePtes[i];
01893
01894 NewSegment->ControlArea = ControlArea;
01895 NewSegment->ImageInformation =
01896 (PSECTION_IMAGE_INFORMATION)((PCHAR)NewSegment +
sizeof(
SEGMENT) +
01897 (
sizeof(
MMPTE) * (NumberOfPtes - 1)));
01898 NewSegment->TotalNumberOfPtes = NumberOfPtes;
01899 NewSegment->NonExtendedPtes = NumberOfPtes;
01900 NewSegment->SizeOfSegment = (ULONG_PTR)NumberOfPtes *
PAGE_SIZE;
01901
01902 RtlZeroMemory (NewSegment->ImageInformation,
01903 sizeof (SECTION_IMAGE_INFORMATION));
01904
01905
01906
01907
01908
01909
01910
#define INIT_IMAGE_INFORMATION(OptHdr) { \
01911
NewSegment->ImageInformation->TransferAddress = \
01912
(PVOID)((ULONG_PTR)((OptHdr).ImageBase) + \
01913
(OptHdr).AddressOfEntryPoint); \
01914
NewSegment->ImageInformation->MaximumStackSize = \
01915
(OptHdr).SizeOfStackReserve; \
01916
NewSegment->ImageInformation->CommittedStackSize = \
01917
(OptHdr).SizeOfStackCommit; \
01918
NewSegment->ImageInformation->SubSystemType = \
01919
(OptHdr).Subsystem; \
01920
NewSegment->ImageInformation->SubSystemMajorVersion = (USHORT)((OptHdr).MajorSubsystemVersion); \
01921
NewSegment->ImageInformation->SubSystemMinorVersion = (USHORT)((OptHdr).MinorSubsystemVersion); \
01922
NewSegment->ImageInformation->DllCharacteristics = \
01923
(OptHdr).DllCharacteristics; \
01924
NewSegment->ImageInformation->ImageContainsCode = \
01925
(BOOLEAN)(((OptHdr).SizeOfCode != 0) || \
01926
((OptHdr).AddressOfEntryPoint != 0)); \
01927
}
01928
01929
#if defined (_WIN64)
01930
if (NtHeader) {
01931
#endif
01932
INIT_IMAGE_INFORMATION(NtHeader->OptionalHeader);
01933
#if defined (_WIN64)
01934
}
else {
01935
01936
INIT_IMAGE_INFORMATION(NtHeader32->OptionalHeader);
01937 }
01938
#endif
01939
#undef INIT_IMAGE_INFORMATION
01940
01941 NewSegment->ImageInformation->ImageCharacteristics =
01942 FileHeader->Characteristics;
01943 NewSegment->ImageInformation->Machine =
01944 FileHeader->Machine;
01945
01946 ControlArea->
Segment = NewSegment;
01947 ControlArea->
NumberOfSectionReferences = 1;
01948 ControlArea->
NumberOfUserReferences = 1;
01949 ControlArea->
u.Flags.BeingCreated = 1;
01950 ControlArea->
PagedPoolUsage =
EX_REAL_POOL_USAGE((
sizeof(
SEGMENT) + (NumberOfPtes *
sizeof(
MMPTE))));
01951
01952
if (ImageAlignment <
PAGE_SIZE) {
01953
01954
01955
01956
01957
01958
01959 ControlArea->
NumberOfSubsections = 1;
01960 }
else {
01961 ControlArea->
NumberOfSubsections = (
USHORT)NumberOfSubsections;
01962 }
01963
01964 ControlArea->
u.Flags.Image = 1;
01965 ControlArea->
u.Flags.File = 1;
01966
01967
if ((FILE_FLOPPY_DISKETTE &
File->DeviceObject->Characteristics) ||
01968 ((FileHeader->Characteristics &
01969 IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP) &&
01970 (FILE_REMOVABLE_MEDIA &
File->DeviceObject->Characteristics)) ||
01971 ((FileHeader->Characteristics &
01972 IMAGE_FILE_NET_RUN_FROM_SWAP) &&
01973 (FILE_REMOTE_DEVICE &
File->DeviceObject->Characteristics))) {
01974
01975
01976
01977
01978
01979
01980
01981 ControlArea->
u.Flags.FloppyMedia = 1;
01982 }
01983
01984
if (FILE_REMOTE_DEVICE &
File->DeviceObject->Characteristics) {
01985
01986
01987
01988
01989
01990 ControlArea->
u.Flags.Networked = 1;
01991 }
01992
01993 ControlArea->
FilePointer =
File;
01994
01995
01996
01997
01998
01999 Subsection->
ControlArea = ControlArea;
02000
#if defined(_WIN64)
02001
if (NtHeader) {
02002
#endif
02003
NextVa = NtHeader->OptionalHeader.ImageBase;
02004
#if defined(_WIN64)
02005
}
else {
02006 NextVa = NtHeader32->OptionalHeader.ImageBase;
02007 }
02008
#endif
02009
02010
02011
if ((NextVa & (
X64K - 1)) != 0) {
02012
02013
02014
02015
02016
02017
goto BadPeImageSegment;
02018 }
02019
02020 NewSegment->BasedAddress = (PVOID)NextVa;
02021
#if defined(_WIN64)
02022
if (NtHeader) {
02023
#endif
02024
SizeOfHeaders = NtHeader->OptionalHeader.SizeOfHeaders;
02025
#if defined(_WIN64)
02026
}
else {
02027 SizeOfHeaders = NtHeader32->OptionalHeader.SizeOfHeaders;
02028 }
02029
#endif
02030
02031
if (SizeOfHeaders >= SizeOfImage) {
02032
goto BadPeImageSegment;
02033 }
02034
02035 Subsection->
PtesInSubsection =
MI_ROUND_TO_SIZE (
02036 SizeOfHeaders,
02037 ImageAlignment
02038 ) >>
PAGE_SHIFT;
02039
02040 PointerPte = NewSegment->PrototypePte;
02041 Subsection->
SubsectionBase = PointerPte;
02042
02043 TempPte.
u.Long =
MiGetSubsectionAddressForPte (Subsection);
02044 TempPte.
u.Soft.Prototype = 1;
02045
02046 NewSegment->SegmentPteTemplate = TempPte;
02047
SectorOffset = 0;
02048
02049
if (ImageAlignment <
PAGE_SIZE) {
02050
02051
02052
02053
02054
02055
02056 PointerPte = NewSegment->PrototypePte;
02057
02058 Subsection->
PtesInSubsection = NumberOfPtes;
02059
02060 Subsection->
NumberOfFullSectors =
02061 (ULONG)(EndOfFile.QuadPart >>
MMSECTOR_SHIFT);
02062
02063
ASSERT ((ULONG)(EndOfFile.HighPart & 0xFFFFF000) == 0);
02064
02065 Subsection->
u.SubsectionFlags.SectorEndOffset =
02066 EndOfFile.LowPart &
MMSECTOR_MASK;
02067
02068 Subsection->
u.SubsectionFlags.Protection =
MM_EXECUTE_WRITECOPY;
02069
02070
02071
02072
02073
02074
02075
02076
02077 TempPte.
u.Soft.Protection =
MM_EXECUTE_WRITECOPY;
02078
02079 NewSegment->SegmentPteTemplate = TempPte;
02080
02081
02082
#if defined (_ALPHA_) || defined(_IA64_)
02083
02084
02085
02086
02087
02088
02089
02090
if (InvalidAlignmentAllowed) {
02091
02092 TempPteDemandZero.
u.Long = 0;
02093 TempPteDemandZero.
u.Soft.Protection =
MM_EXECUTE_WRITECOPY;
02094
SectorOffset = 0;
02095
02096
for (i = 0; i < NumberOfPtes; i += 1) {
02097
02098
02099
02100
02101
02102
if (
SectorOffset < EndOfFile.LowPart) {
02103
02104
02105
02106
02107
02108
MI_WRITE_INVALID_PTE (PointerPte, TempPte);
02109
02110 }
else {
02111
02112
02113
02114
02115
02116
MI_WRITE_INVALID_PTE (PointerPte, TempPteDemandZero);
02117 }
02118
02119
SectorOffset +=
PAGE_SIZE;
02120 PointerPte += 1;
02121 }
02122
02123 }
else
02124
#endif
02125
{
02126
02127
for (i = 0; i < NumberOfPtes; i += 1) {
02128
02129
02130
02131
02132
02133
MI_WRITE_INVALID_PTE (PointerPte, TempPte);
02134 PointerPte += 1;
02135 }
02136 }
02137
02138 NewSegment->ImageCommitment = NumberOfPtes;
02139
02140
02141
02142
02143
02144
02145 TempPte.
u.Long = 0;
02146
02147 }
else {
02148
02149
02150
02151
02152
02153
if (Subsection->
PtesInSubsection > NumberOfPtes) {
02154
02155
02156
02157
02158
02159
goto BadPeImageSegment;
02160 }
02161 NumberOfPtes -= Subsection->
PtesInSubsection;
02162
02163 Subsection->
NumberOfFullSectors =
02164 SizeOfHeaders >>
MMSECTOR_SHIFT;
02165
02166 Subsection->
u.SubsectionFlags.SectorEndOffset =
02167 SizeOfHeaders &
MMSECTOR_MASK;
02168
02169 Subsection->
u.SubsectionFlags.ReadOnly = 1;
02170 Subsection->
u.SubsectionFlags.CopyOnWrite = 1;
02171 Subsection->
u.SubsectionFlags.Protection =
MM_READONLY;
02172
02173 TempPte.
u.Soft.Protection =
MM_READONLY;
02174 NewSegment->SegmentPteTemplate = TempPte;
02175
02176
for (i = 0; i < Subsection->
PtesInSubsection; i += 1) {
02177
02178
02179
02180
02181
02182
if (
SectorOffset < SizeOfHeaders) {
02183
MI_WRITE_INVALID_PTE (PointerPte, TempPte);
02184 }
else {
02185
MI_WRITE_INVALID_PTE (PointerPte,
ZeroPte);
02186 }
02187
SectorOffset +=
PAGE_SIZE;
02188 PointerPte += 1;
02189 NextVa +=
PAGE_SIZE;
02190 }
02191 }
02192
02193
02194
02195
02196
02197
#if defined(_WIN64)
02198
if (NtHeader) {
02199
#endif
02200
PreferredImageBase = NtHeader->OptionalHeader.ImageBase;
02201
#if defined(_WIN64)
02202
}
else {
02203 PreferredImageBase = NtHeader32->OptionalHeader.ImageBase;
02204 }
02205
#endif
02206
02207
02208
02209
02210
02211
02212 SectionTableEntry =
NULL;
02213 OffsetToSectionTable =
sizeof(ULONG) +
02214
sizeof(IMAGE_FILE_HEADER) +
02215 FileHeader->SizeOfOptionalHeader;
02216
02217
if ((
BYTE_OFFSET(NtHeader) + OffsetToSectionTable +
02218
#if defined (_WIN64)
02219
BYTE_OFFSET(NtHeader32) +
02220
#endif
02221
((NumberOfSubsections + 1) *
02222
sizeof (IMAGE_SECTION_HEADER))) <=
PAGE_SIZE) {
02223
02224
02225
02226
02227
02228
#if defined(_WIN64)
02229
if (NtHeader32) {
02230 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader32 +
02231 OffsetToSectionTable);
02232 }
else
02233
#endif
02234
{
02235 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader +
02236 OffsetToSectionTable);
02237 }
02238
02239 }
else {
02240
02241
02242
02243
02244
02245
02246
if (ExtendedHeader !=
NULL) {
02247
02248
#if defined(_WIN64)
02249
if (NtHeader32) {
02250 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader32 +
02251 OffsetToSectionTable);
02252 }
else
02253
#endif
02254
{
02255 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader +
02256 OffsetToSectionTable);
02257 }
02258
02259
02260
02261
02262
02263
02264
if ((((PCHAR)SectionTableEntry +
02265 ((NumberOfSubsections + 1) *
02266
sizeof (IMAGE_SECTION_HEADER))) -
02267 (PCHAR)ExtendedHeader) >
02268
MM_MAXIMUM_IMAGE_HEADER) {
02269 SectionTableEntry =
NULL;
02270
02271 }
02272 }
02273 }
02274
02275
if (SectionTableEntry ==
NULL) {
02276
02277
02278
02279
02280
02281
02282
02283
if (ExtendedHeader ==
NULL) {
02284 ExtendedHeader =
ExAllocatePoolWithTag (
NonPagedPool,
02285
MM_MAXIMUM_IMAGE_HEADER,
02286
MMTEMPORARY);
02287
if (ExtendedHeader ==
NULL) {
02288
ExFreePool (NewSegment);
02289
ExFreePool (ControlArea);
02290
Status = STATUS_INSUFFICIENT_RESOURCES;
02291
goto NeImage;
02292 }
02293
02294
02295
02296
02297
02298
MmCreateMdl( Mdl, ExtendedHeader,
MM_MAXIMUM_IMAGE_HEADER);
02299
02300
MmBuildMdlForNonPagedPool (Mdl);
02301 }
02302
02303 StartingOffset.LowPart = PtrToUlong(
PAGE_ALIGN (
02304 (ULONG)DosHeader->e_lfanew +
02305 OffsetToSectionTable));
02306
02307 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)ExtendedHeader +
02308
BYTE_OFFSET((ULONG)DosHeader->e_lfanew +
02309 OffsetToSectionTable));
02310
02311
KeClearEvent (InPageEvent);
02312
Status =
IoPageRead (
File,
02313 Mdl,
02314 &StartingOffset,
02315 InPageEvent,
02316 &IoStatus
02317 );
02318
02319
if (
Status == STATUS_PENDING) {
02320
KeWaitForSingleObject( InPageEvent,
02321
WrPageIn,
02322
KernelMode,
02323
FALSE,
02324 (PLARGE_INTEGER)
NULL);
02325 }
02326
02327
if (Mdl->
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
02328
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
02329 }
02330
02331
if ((!
NT_SUCCESS(
Status)) || (!
NT_SUCCESS(IoStatus.Status))) {
02332
if (
Status != STATUS_FILE_LOCK_CONFLICT) {
02333
Status = STATUS_INVALID_FILE_FOR_SECTION;
02334 }
02335
ExFreePool (NewSegment);
02336
ExFreePool (ControlArea);
02337
goto NeImage;
02338 }
02339
02340
02341
02342
02343
02344
02345
02346 }
02347
02348
if (TempPte.
u.Long == 0
02349
#if defined (_ALPHA_) || defined(_IA64_)
02350
&& (!InvalidAlignmentAllowed)
02351
#endif
02352
) {
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
Status = STATUS_SUCCESS;
02364
02365
while (NumberOfSubsections > 0) {
02366
if (SectionTableEntry->Misc.VirtualSize == 0) {
02367 SectionVirtualSize = SectionTableEntry->SizeOfRawData;
02368 }
else {
02369 SectionVirtualSize = SectionTableEntry->Misc.VirtualSize;
02370 }
02371
02372
02373
02374
02375
02376
if (SectionTableEntry->PointerToRawData +
02377 SectionTableEntry->SizeOfRawData <
02378 SectionTableEntry->PointerToRawData) {
02379
02380 KdPrint((
"MMCREASECT: invalid section/file size %Z\n",
02381 &
File->FileName));
02382
02383
Status = STATUS_INVALID_IMAGE_FORMAT;
02384
break;
02385 }
02386
02387
02388
02389
02390
02391
02392
if (((SectionTableEntry->PointerToRawData !=
02393 SectionTableEntry->VirtualAddress))
02394 ||
02395 (SectionVirtualSize > SectionTableEntry->SizeOfRawData)) {
02396
02397 KdPrint((
"MMCREASECT: invalid BSS/Trailingzero %Z\n",
02398 &
File->FileName));
02399
02400
Status = STATUS_INVALID_IMAGE_FORMAT;
02401
break;
02402 }
02403
02404
02405 SectionTableEntry += 1;
02406 NumberOfSubsections -= 1;
02407 }
02408
02409
02410
if (!
NT_SUCCESS(
Status)) {
02411
ExFreePool (NewSegment);
02412
ExFreePool (ControlArea);
02413
goto NeImage;
02414 }
02415
02416
goto PeReturnSuccess;
02417
02418 }
02419
#if defined (_ALPHA_) || defined(_IA64_)
02420
02421
else if (TempPte.
u.Long == 0 && InvalidAlignmentAllowed) {
02422
02423 TempNumberOfSubsections = NumberOfSubsections;
02424 TempSectionTableEntry = SectionTableEntry;
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440 AdditionalSubsections = 0;
02441 AdditionalPtes = 0;
02442 AdditionalBasePtes = 0;
02443 RoundingAlignment =
PAGE_SIZE;
02444
02445
while (TempNumberOfSubsections > 0) {
02446 ULONG EndOfSection;
02447 ULONG ExtraPages;
02448
02449
if (TempSectionTableEntry->Misc.VirtualSize == 0) {
02450 SectionVirtualSize = TempSectionTableEntry->SizeOfRawData;
02451 }
else {
02452 SectionVirtualSize = TempSectionTableEntry->Misc.VirtualSize;
02453 }
02454
02455 EndOfSection = TempSectionTableEntry->PointerToRawData +
02456 TempSectionTableEntry->SizeOfRawData;
02457
02458
02459
02460
02461
02462
if (EndOfSection < TempSectionTableEntry->PointerToRawData) {
02463
02464 KdPrint((
"MMCREASECT: invalid section/file size %Z\n",
02465 &
File->FileName));
02466
02467
Status = STATUS_INVALID_IMAGE_FORMAT;
02468
02469
ExFreePool (NewSegment);
02470
ExFreePool (ControlArea);
02471
goto NeImage;
02472 }
02473
02474
02475
02476
02477
02478
02479
02480
02481
if ((EndOfSection <= EndOfFile.LowPart) &&
02482 (EndOfSection > SizeOfImage)) {
02483
02484
02485
02486
02487
02488
02489 ExtraPages =
MI_ROUND_TO_SIZE (EndOfSection - SizeOfImage, RoundingAlignment) >>
PAGE_SHIFT;
02490
if (ExtraPages > AdditionalBasePtes) {
02491 AdditionalBasePtes = ExtraPages;
02492 }
02493 }
02494
02495
02496
02497
if ((TempSectionTableEntry->Characteristics & IMAGE_SCN_MEM_SHARED) &&
02498 (!(TempSectionTableEntry->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
02499 (TempSectionTableEntry->Characteristics & IMAGE_SCN_MEM_WRITE))) {
02500 AdditionalPtes +=
02501
MI_ROUND_TO_SIZE (SectionVirtualSize, RoundingAlignment) >>
02502
PAGE_SHIFT;
02503 AdditionalSubsections += 1;
02504 }
02505
02506 TempSectionTableEntry += 1;
02507 TempNumberOfSubsections -= 1;
02508 }
02509
02510
if (AdditionalBasePtes == 0 && (AdditionalSubsections == 0 || AdditionalPtes == 0)) {
02511
02512
goto PeReturnSuccess;
02513 }
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524 NewSubsectionsAllocated = SubsectionsAllocated +
02525 AdditionalSubsections;
02526
02527 NewControlArea =
ExAllocatePoolWithTag(
NonPagedPool,
02528 (ULONG) (
sizeof(
CONTROL_AREA) +
02529 (
sizeof(
SUBSECTION) *
02530 NewSubsectionsAllocated)),
02531 'iCmM');
02532
if (NewControlArea ==
NULL) {
02533
ExFreePool (NewSegment);
02534
ExFreePool (ControlArea);
02535
Status = STATUS_INSUFFICIENT_RESOURCES;
02536
goto NeImage;
02537 }
02538
02539
02540
02541
02542
02543 RtlMoveMemory (NewControlArea, ControlArea,
02544
sizeof(
CONTROL_AREA) +
02545
sizeof(
SUBSECTION) * SubsectionsAllocated);
02546
02547 NewControlArea->
NonPagedPoolUsage =
02548
EX_REAL_POOL_USAGE(
sizeof(
CONTROL_AREA) +
02549 (
sizeof(
SUBSECTION) *
02550 NewSubsectionsAllocated));
02551
02552 NewControlArea->
NumberOfSubsections = (
USHORT) NewSubsectionsAllocated;
02553
02554
02555
02556
02557
02558
02559
02560 OldSegment = NewSegment;
02561
02562
02563 OrigNumberOfPtes += AdditionalBasePtes;
02564
02565 SizeOfSegment =
sizeof(
SEGMENT) +
02566 (
sizeof(
MMPTE) * (OrigNumberOfPtes + AdditionalPtes - 1)) +
02567
sizeof(SECTION_IMAGE_INFORMATION);
02568
02569 NewSegment =
ExAllocatePoolWithTag (
PagedPool,
02570 SizeOfSegment,
02571
MMSECT);
02572
02573
if (NewSegment ==
NULL) {
02574
02575
02576
02577
02578
02579
ExFreePool (ControlArea);
02580
ExFreePool (NewControlArea);
02581
ExFreePool (OldSegment);
02582
Status = STATUS_INSUFFICIENT_RESOURCES;
02583
goto NeImage;
02584 }
02585
02586 *Segment = NewSegment;
02587 RtlMoveMemory (NewSegment, OldSegment,
sizeof(
SEGMENT));
02588
02589
02590
02591
02592
02593 NewPointerPte = &NewSegment->ThePtes[0];
02594 i = (ULONG) (((ULONG_PTR)NewPointerPte >>
PTE_SHIFT) &
02595 ((
MM_PROTO_PTE_ALIGNMENT /
PAGE_SIZE) - 1));
02596
02597
if (i != 0) {
02598 i = (
MM_PROTO_PTE_ALIGNMENT /
PAGE_SIZE) - i;
02599 }
02600
02601 NewSegment->PrototypePte = &NewSegment->ThePtes[i];
02602
if (i != 0) {
02603 RtlZeroMemory (&NewSegment->ThePtes[0],
sizeof(
MMPTE) * i);
02604 }
02605 PointerPte = NewSegment->PrototypePte +
02606 (PointerPte - OldSegment->
PrototypePte);
02607
02608 NewSegment->ControlArea = NewControlArea;
02609 NewSegment->ImageInformation =
02610 (PSECTION_IMAGE_INFORMATION)((PCHAR)NewSegment +
sizeof(
SEGMENT) +
02611 (
sizeof(
MMPTE) * (OrigNumberOfPtes + AdditionalPtes - 1)));
02612 NewSegment->TotalNumberOfPtes = OrigNumberOfPtes + AdditionalPtes;
02613 NewSegment->NonExtendedPtes = OrigNumberOfPtes + AdditionalPtes;
02614 NewSegment->SizeOfSegment = (ULONG_PTR)(OrigNumberOfPtes + AdditionalPtes) *
PAGE_SIZE;
02615
02616 RtlMoveMemory (NewSegment->ImageInformation,
02617 OldSegment->
ImageInformation,
02618 sizeof (SECTION_IMAGE_INFORMATION));
02619
02620
02621
02622
02623
02624
02625
02626 NewControlArea->
Segment = NewSegment;
02627 NewControlArea->
PagedPoolUsage =
EX_REAL_POOL_USAGE((
sizeof(
SEGMENT) +
02628 ((OrigNumberOfPtes + AdditionalPtes) *
sizeof(
MMPTE))));
02629
02630 Subsection = (
PSUBSECTION)(ControlArea + 1);
02631 NewSubsection = (
PSUBSECTION)(NewControlArea + 1);
02632 NewSubsection->
PtesInSubsection += AdditionalBasePtes;
02633
02634
for (i = 0; i < SubsectionsAllocated; i += 1) {
02635
02636
02637
02638
02639
02640
02641 NewSubsection->
ControlArea = (
PCONTROL_AREA) NewControlArea;
02642
02643 NewSubsection->
SubsectionBase = NewSegment->PrototypePte +
02644 (Subsection->
SubsectionBase - OldSegment->
PrototypePte);
02645
02646 NewPointerPte = NewSegment->PrototypePte;
02647 OldPointerPte = OldSegment->
PrototypePte;
02648
02649 TempPte.
u.Long =
MiGetSubsectionAddressForPte (NewSubsection);
02650 TempPte.
u.Soft.Prototype = 1;
02651
02652
for (j = 0; j < OldSegment->
TotalNumberOfPtes+AdditionalBasePtes; j += 1) {
02653
02654
if ((OldPointerPte->
u.Soft.Prototype == 1) &&
02655 (
MiGetSubsectionAddress (OldPointerPte) == Subsection)) {
02656 OriginalProtection =
MI_GET_PROTECTION_FROM_SOFT_PTE (OldPointerPte);
02657 TempPte.
u.Soft.Protection = OriginalProtection;
02658
MI_WRITE_INVALID_PTE (NewPointerPte, TempPte);
02659 }
02660
else if (i == 0) {
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673 OriginalProtection =
MI_GET_PROTECTION_FROM_SOFT_PTE (OldPointerPte);
02674 TempPteDemandZero.
u.Long = 0;
02675 TempPteDemandZero.
u.Soft.Protection = OriginalProtection;
02676
MI_WRITE_INVALID_PTE (NewPointerPte, TempPteDemandZero);
02677 }
02678
02679 NewPointerPte += 1;
02680
02681
02682
if (j < OldSegment->
TotalNumberOfPtes-1) {
02683 OldPointerPte += 1;
02684 }
02685 }
02686
02687 Subsection += 1;
02688 NewSubsection += 1;
02689 }
02690
02691
02692 RtlZeroMemory (NewSubsection,
02693
sizeof(
SUBSECTION) * AdditionalSubsections);
02694
02695
ExFreePool (OldSegment);
02696
ExFreePool (ControlArea);
02697 ControlArea = (
PCONTROL_AREA) NewControlArea;
02698
02699
02700
02701
02702
02703
02704 SubsectionsAllocated = NewSubsectionsAllocated;
02705 Subsection = NewSubsection - 1;
02706 NumberOfPtes = AdditionalPtes;
02707
02708
02709
02710
02711
if (AdditionalSubsections == 0 || AdditionalPtes == 0) {
02712
02713
goto PeReturnSuccess;
02714 }
02715 }
02716
#endif
02717
02718
while (NumberOfSubsections > 0) {
02719
02720
#if defined (_ALPHA_) || defined(_IA64_)
02721
if (!InvalidAlignmentAllowed ||
02722 ((SectionTableEntry->Characteristics & IMAGE_SCN_MEM_SHARED) &&
02723 (!(SectionTableEntry->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
02724 (SectionTableEntry->Characteristics & IMAGE_SCN_MEM_WRITE)))) {
02725
#endif
02726
02727
02728
02729
02730
02731
if (SectionTableEntry->Misc.VirtualSize == 0) {
02732 SectionVirtualSize = SectionTableEntry->SizeOfRawData;
02733 }
else {
02734 SectionVirtualSize = SectionTableEntry->Misc.VirtualSize;
02735 }
02736
02737
02738
02739
02740
02741
02742
02743
if (SectionTableEntry->SizeOfRawData == 0) {
02744 SectionTableEntry->PointerToRawData = 0;
02745 }
02746
02747
02748
02749
02750
02751
if (SectionTableEntry->PointerToRawData +
02752 SectionTableEntry->SizeOfRawData <
02753 SectionTableEntry->PointerToRawData) {
02754
02755
goto BadPeImageSegment;
02756 }
02757
02758
02759 Subsection += 1;
02760 Subsection->
ControlArea = ControlArea;
02761 Subsection->
NextSubsection = (
PSUBSECTION)
NULL;
02762 Subsection->
UnusedPtes = 0;
02763
02764
if (((NextVa !=
02765 (PreferredImageBase + SectionTableEntry->VirtualAddress))
02766
02767
#if defined (_ALPHA_) || defined(_IA64_)
02768
&& !InvalidAlignmentAllowed
02769
#endif
02770
02771 ) ||
02772 (SectionVirtualSize == 0)) {
02773
02774
02775
02776
02777
02778
02779
goto BadPeImageSegment;
02780 }
02781
02782 Subsection->
PtesInSubsection =
02783
MI_ROUND_TO_SIZE (SectionVirtualSize, RoundingAlignment)
02784 >>
PAGE_SHIFT;
02785
02786
if (Subsection->
PtesInSubsection > NumberOfPtes) {
02787
02788
02789
02790
02791
02792
goto BadPeImageSegment;
02793 }
02794 NumberOfPtes -= Subsection->
PtesInSubsection;
02795
02796 Subsection->
u.LongFlags = 0;
02797 Subsection->
StartingSector =
02798 SectionTableEntry->PointerToRawData >>
MMSECTOR_SHIFT;
02799
02800
02801
02802
02803
02804 EndingAddress = (SectionTableEntry->PointerToRawData +
02805 SectionTableEntry->SizeOfRawData +
02806 FileAlignment) & ~FileAlignment;
02807
02808 Subsection->
NumberOfFullSectors = (ULONG)
02809 ((EndingAddress >>
MMSECTOR_SHIFT) -
02810 Subsection->
StartingSector);
02811
02812 Subsection->
u.SubsectionFlags.SectorEndOffset =
02813 (ULONG) EndingAddress &
MMSECTOR_MASK;
02814
02815 Subsection->
SubsectionBase = PointerPte;
02816
02817
02818
02819
02820
02821 TempPte.
u.Long = 0;
02822 TempPteDemandZero.
u.Long = 0;
02823
02824 TempPte.
u.Long =
MiGetSubsectionAddressForPte (Subsection);
02825 TempPte.
u.Soft.Prototype = 1;
02826 ImageFileSize = SectionTableEntry->PointerToRawData +
02827 SectionTableEntry->SizeOfRawData;
02828 TempPte.
u.Soft.Protection =
02829
MiGetImageProtection (SectionTableEntry->Characteristics);
02830 TempPteDemandZero.
u.Soft.Protection = TempPte.
u.Soft.Protection;
02831
02832
if (SectionTableEntry->PointerToRawData == 0) {
02833 TempPte = TempPteDemandZero;
02834 }
02835
02836 Subsection->
u.SubsectionFlags.ReadOnly = 1;
02837 Subsection->
u.SubsectionFlags.CopyOnWrite = 1;
02838 Subsection->
u.SubsectionFlags.Protection =
MI_GET_PROTECTION_FROM_SOFT_PTE (&TempPte);
02839
02840
if (TempPte.
u.Soft.Protection &
MM_PROTECTION_WRITE_MASK) {
02841
if ((TempPte.
u.Soft.Protection &
MM_COPY_ON_WRITE_MASK)
02842 ==
MM_COPY_ON_WRITE_MASK) {
02843
02844
02845
02846
02847
02848
02849 ImageCommit =
TRUE;
02850 }
else {
02851
02852
02853
02854
02855
02856
02857 SectionCommit =
TRUE;
02858 Subsection->
u.SubsectionFlags.GlobalMemory = 1;
02859 ControlArea->
u.Flags.GlobalMemory = 1;
02860 }
02861 }
else {
02862
02863
02864
02865
02866
02867 ImageCommit =
FALSE;
02868 SectionCommit =
FALSE;
02869 }
02870
02871 NewSegment->SegmentPteTemplate = TempPte;
02872
SectorOffset = 0;
02873
02874
for (i = 0; i < Subsection->
PtesInSubsection; i += 1) {
02875
02876
02877
02878
02879
02880
if (
SectorOffset < SectionVirtualSize) {
02881
02882
02883
02884
02885
02886
if (SectionCommit) {
02887 NewSegment->NumberOfCommittedPages += 1;
02888 }
02889
if (ImageCommit) {
02890 NewSegment->ImageCommitment += 1;
02891 }
02892
02893
if (
SectorOffset < SectionTableEntry->SizeOfRawData) {
02894
02895
02896
02897
02898
MI_WRITE_INVALID_PTE (PointerPte, TempPte);
02899 }
else {
02900
02901
02902
02903
02904
MI_WRITE_INVALID_PTE (PointerPte, TempPteDemandZero);
02905 }
02906 }
else {
02907
02908
02909
02910
02911
02912
MI_WRITE_INVALID_PTE (PointerPte,
ZeroPte);
02913 }
02914
SectorOffset +=
PAGE_SIZE;
02915 PointerPte += 1;
02916 NextVa +=
PAGE_SIZE;
02917 }
02918
02919
#if defined (_ALPHA_) || defined(_IA64_)
02920
}
02921
#endif
02922
02923 SectionTableEntry += 1;
02924 NumberOfSubsections -= 1;
02925 }
02926
02927
#if defined (_ALPHA_) || defined(_IA64_)
02928
if (!InvalidAlignmentAllowed) {
02929
#endif
02930
02931
02932
02933
02934
02935
ASSERT (ImageAlignment >=
PAGE_SIZE);
02936 ControlArea->
NumberOfSubsections += 1;
02937
02938
02939
02940
02941
02942
02943
if (ImageFileSize > EndOfFile.LowPart) {
02944
02945
02946
02947
02948
02949 KdPrint((
"MMCREASECT: invalid image size - file size %lx - image size %lx\n %Z\n",
02950 EndOfFile.LowPart, ImageFileSize, &
File->FileName));
02951
goto BadPeImageSegment;
02952 }
02953
02954
02955
02956
02957
02958
02959
if (NumberOfPtes >= (ImageAlignment >>
PAGE_SHIFT)) {
02960
02961
02962
02963
02964
02965 KdPrint((
"MMCREASECT: invalid image - PTE left %lx\n image name %Z\n",
02966 NumberOfPtes, &
File->FileName));
02967
02968
goto BadPeImageSegment;
02969 }
02970
02971
02972
02973
02974
02975
while (NumberOfPtes != 0) {
02976
MI_WRITE_INVALID_PTE (PointerPte,
ZeroPte);
02977 PointerPte += 1;
02978 NumberOfPtes -= 1;
02979 }
02980
02981
02982
02983
02984
02985
02986
if ((ExtendedHeader ==
NULL) && (SizeOfHeaders <
PAGE_SIZE)) {
02987
02988
02989
02990
02991
02992 RtlZeroMemory ((PVOID)((PCHAR)Base +
02993 SizeOfHeaders),
02994
PAGE_SIZE - SizeOfHeaders);
02995 }
02996
02997
02998
#if defined (_ALPHA_) || defined(_IA64_)
02999
}
03000
#endif
03001
03002
if (NewSegment->NumberOfCommittedPages != 0) {
03003
03004
03005
03006
03007
03008
if (
MiChargeCommitment (NewSegment->NumberOfCommittedPages,
NULL) ==
FALSE) {
03009
Status = STATUS_COMMITMENT_LIMIT;
03010
ExFreePool (NewSegment);
03011
ExFreePool (ControlArea);
03012
goto NeImage;
03013 }
03014
03015
MM_TRACK_COMMIT (
MM_DBG_COMMIT_IMAGE, NewSegment->NumberOfCommittedPages);
03016
Status = STATUS_SUCCESS;
03017
03018 ExAcquireFastMutex (&
MmSectionCommitMutex);
03019
MmSharedCommit += NewSegment->NumberOfCommittedPages;
03020 ExReleaseFastMutex (&
MmSectionCommitMutex);
03021 }
03022
03023 PeReturnSuccess:
03024
03025
03026
03027
03028
03029
03030
03031
if ((
MiHydra ==
TRUE) &&
03032 (ControlArea->
u.Flags.GlobalMemory) &&
03033 ((LoaderFlags & IMAGE_LOADER_FLAGS_SYSTEM_GLOBAL) == 0)) {
03034
03035 LargeControlArea =
ExAllocatePoolWithTag(
NonPagedPool,
03036 (ULONG)(
sizeof(
LARGE_CONTROL_AREA) +
03037 (
sizeof(
SUBSECTION) *
03038 SubsectionsAllocated)),
03039 'iCmM');
03040
if (LargeControlArea ==
NULL) {
03041
03042
03043
03044
03045
03046
if (NewSegment->NumberOfCommittedPages != 0) {
03047
MiReturnCommitment (NewSegment->NumberOfCommittedPages);
03048
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_IMAGE_NO_LARGE_CA, NewSegment->NumberOfCommittedPages);
03049 ExAcquireFastMutex (&
MmSectionCommitMutex);
03050
MmSharedCommit -= NewSegment->NumberOfCommittedPages;
03051 ExReleaseFastMutex (&
MmSectionCommitMutex);
03052 }
03053
03054
ExFreePool (NewSegment);
03055
ExFreePool (ControlArea);
03056
03057
03058
Status = STATUS_INSUFFICIENT_RESOURCES;
03059
03060
goto NeImage;
03061 }
03062
03063
03064
03065
03066
03067
03068 RtlMoveMemory (LargeControlArea, ControlArea,
sizeof(
CONTROL_AREA));
03069 LargeControlArea->
NonPagedPoolUsage =
EX_REAL_POOL_USAGE(
03070
sizeof(
LARGE_CONTROL_AREA) +
03071 (
sizeof(
SUBSECTION) *
03072 SubsectionsAllocated));
03073
03074
ASSERT (ControlArea->
u.Flags.GlobalOnlyPerSession == 0);
03075
03076 Subsection = (
PSUBSECTION)(ControlArea + 1);
03077 NewSubsection = (
PSUBSECTION)(LargeControlArea + 1);
03078
03079
for (i = 0; i < SubsectionsAllocated; i += 1) {
03080 RtlMoveMemory (NewSubsection, Subsection,
sizeof(
SUBSECTION));
03081 NewSubsection->
ControlArea = (
PCONTROL_AREA) LargeControlArea;
03082
03083 PointerPte = NewSegment->PrototypePte;
03084
03085 TempPte.
u.Long =
MiGetSubsectionAddressForPte (NewSubsection);
03086 TempPte.
u.Soft.Prototype = 1;
03087
03088
for (j = 0; j < NewSegment->TotalNumberOfPtes; j += 1) {
03089
03090
if ((PointerPte->
u.Soft.Prototype == 1) &&
03091 (
MiGetSubsectionAddress (PointerPte) == Subsection)) {
03092 OriginalProtection =
MI_GET_PROTECTION_FROM_SOFT_PTE (PointerPte);
03093 TempPte.
u.Soft.Protection = OriginalProtection;
03094
MI_WRITE_INVALID_PTE (PointerPte, TempPte);
03095 }
03096 PointerPte += 1;
03097 }
03098
03099 Subsection += 1;
03100 NewSubsection += 1;
03101 }
03102
03103 NewSegment->
ControlArea = (
PCONTROL_AREA) LargeControlArea;
03104
03105 LargeControlArea->
u.Flags.GlobalOnlyPerSession = 1;
03106
03107 LargeControlArea->
SessionId = 0;
03108 InitializeListHead (&LargeControlArea->
UserGlobalList);
03109
03110
ExFreePool (ControlArea);
03111
03112 ControlArea = (
PCONTROL_AREA) LargeControlArea;
03113 }
03114
03115
MiUnmapImageHeaderInHyperSpace ();
03116
03117
03118
03119
03120
03121
03122 PointerPte = NewSegment->PrototypePte;
03123
03124
MiUpdateImageHeaderPage (PointerPte, PageFrameNumber, ControlArea);
03125
if (ExtendedHeader !=
NULL) {
03126
ExFreePool (ExtendedHeader);
03127 }
03128
ExFreePool (InPageEvent);
03129
03130
return STATUS_SUCCESS;
03131
03132
03133
03134
03135
03136
03137 BadPeImageSegment:
03138
03139
ExFreePool (NewSegment);
03140
ExFreePool (ControlArea);
03141
03142
03143
Status = STATUS_INVALID_IMAGE_FORMAT;
03144
03145 NeImage:
03146
MiUnmapImageHeaderInHyperSpace ();
03147
03148 BadSection:
03149
MiRemoveImageHeaderPage(PageFrameNumber);
03150
if (ExtendedHeader !=
NULL) {
03151
ExFreePool (ExtendedHeader);
03152 }
03153
ExFreePool (InPageEvent);
03154
return Status;
03155 }
03156
03157
03158 BOOLEAN
03159 MiCheckDosCalls (
03160 IN PIMAGE_OS2_HEADER Os2Header,
03161 IN ULONG HeaderSize
03162 )
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177 {
03178 PUCHAR ImportTable;
03179 UCHAR EntrySize;
03180
USHORT ModuleCount;
03181
USHORT ModuleSize;
03182
USHORT i;
03183
PUSHORT ModuleTable;
03184
03185
PAGED_CODE();
03186
03187
03188
03189
03190
03191 ModuleCount = Os2Header->ne_cmod;
03192
03193
if (ModuleCount == 0) {
03194
return FALSE;
03195 }
03196
03197
03198
03199
03200
03201
03202
03203
try {
03204
03205
03206
03207
03208
03209
03210
03211 ModuleTable = (
PUSHORT)((PCHAR)Os2Header + (ULONG)Os2Header->ne_modtab);
03212
03213
03214
03215
03216
03217
03218
if (((ULONG)Os2Header->ne_modtab + (ModuleCount * 2)) > HeaderSize) {
03219
return FALSE;
03220 }
03221
03222
03223
03224
03225
03226
for (i = 0; i < ModuleCount; i += 1) {
03227
03228 ModuleSize = *((UNALIGNED
USHORT *)ModuleTable);
03229
03230
03231
03232
03233
03234
03235 ImportTable = (PUCHAR)((PCHAR)Os2Header +
03236 (ULONG)Os2Header->ne_imptab + (ULONG)ModuleSize);
03237
03238
03239
03240
03241
03242
if (((ULONG)Os2Header->ne_imptab + (ULONG)ModuleSize)
03243 >= HeaderSize) {
03244
return FALSE;
03245 }
03246
03247 EntrySize = *ImportTable++;
03248
03249
03250
03251
03252
03253
if (EntrySize == 0) {
03254
return FALSE;
03255 }
03256
03257
03258
03259
03260
03261
03262
03263
03264
if (((ULONG)Os2Header->ne_imptab + (ULONG)ModuleSize +
03265 (ULONG)EntrySize +
sizeof(UCHAR)) > HeaderSize) {
03266
return FALSE;
03267 }
03268
03269
03270
03271
03272
03273
if (EntrySize == 8) {
03274
if (RtlEqualMemory (ImportTable,
"DOSCALLS", 8) ) {
03275
return TRUE;
03276 }
03277 }
03278
03279
03280
03281
03282
03283 ModuleTable = (
PUSHORT)((PCHAR)ModuleTable + 2);
03284 }
03285 } except (
EXCEPTION_EXECUTE_HANDLER) {
03286
return FALSE;
03287 }
03288
03289
return FALSE;
03290 }
03291
03292
03293
03294
NTSTATUS
03295 MiVerifyImageHeader (
03296 IN PIMAGE_NT_HEADERS NtHeader,
03297 IN PIMAGE_DOS_HEADER DosHeader,
03298 IN ULONG NtHeaderSize
03299 )
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317
03318 {
03319
PCONFIGPHARLAP PharLapConfigured;
03320 PUCHAR pb;
03321 LONG pResTableAddress;
03322
03323
PAGED_CODE();
03324
03325
if (NtHeader->Signature != IMAGE_NT_SIGNATURE) {
03326
if ((
USHORT)NtHeader->Signature == (
USHORT)IMAGE_OS2_SIGNATURE) {
03327
03328
03329
03330
03331
03332
if ((!
MiCheckDosCalls ((PIMAGE_OS2_HEADER)NtHeader, NtHeaderSize)) &&
03333 ((((PIMAGE_OS2_HEADER)NtHeader)->ne_exetyp == 2)
03334 ||
03335 ((((PIMAGE_OS2_HEADER)NtHeader)->ne_exetyp == 0) &&
03336 (((((PIMAGE_OS2_HEADER)NtHeader)->ne_expver & 0xff00) ==
03337 0x200) ||
03338 ((((PIMAGE_OS2_HEADER)NtHeader)->ne_expver & 0xff00) ==
03339 0x300))))) {
03340
03341
03342
03343
03344
03345
return STATUS_INVALID_IMAGE_WIN_16;
03346 }
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
if (((PIMAGE_OS2_HEADER)NtHeader)->ne_exetyp == 5 ||
03365 ((PIMAGE_OS2_HEADER)NtHeader)->ne_enttab ==
03366 ((PIMAGE_OS2_HEADER)NtHeader)->ne_imptab )
03367 {
03368
return STATUS_INVALID_IMAGE_PROTECT;
03369 }
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380
03381
if (((PIMAGE_OS2_HEADER)NtHeader)->ne_exetyp == 1 &&
03382 RtlEqualMemory((PUCHAR)DosHeader + 0x200,
"16STUB", 6) )
03383 {
03384
return STATUS_INVALID_IMAGE_PROTECT;
03385 }
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395 PharLapConfigured =(
PCONFIGPHARLAP) ((PCHAR)DosHeader +
03396 ((ULONG)DosHeader->e_cparhdr << 4));
03397
03398
if ((PCHAR)PharLapConfigured <
03399 (PCHAR)DosHeader +
PAGE_SIZE -
sizeof(
CONFIGPHARLAP)) {
03400
if (RtlEqualMemory(&PharLapConfigured->
uchCopyRight[0x18],
03401
"Phar Lap Software, Inc.", 24) &&
03402 (PharLapConfigured->
usSign == 0x4b50 ||
03403 PharLapConfigured->
usSign == 0x4f50 ||
03404 PharLapConfigured->
usSign == 0x5650 ))
03405 {
03406
return STATUS_INVALID_IMAGE_PROTECT;
03407 }
03408 }
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420 pb = ((PUCHAR)DosHeader + ((ULONG)DosHeader->e_cparhdr << 4));
03421
03422
if ((ULONG_PTR)pb < (ULONG_PTR)DosHeader +
PAGE_SIZE - 0x30 -
sizeof(
USHORT)) {
03423 pb += *(
PUSHORT)(pb + 0x30);
03424
if ( (ULONG_PTR)pb < (ULONG_PTR)DosHeader +
PAGE_SIZE - 36 &&
03425 RtlEqualMemory(pb,
03426
"Copyright (C) Rational Systems, Inc.",
03427 36) )
03428 {
03429
return STATUS_INVALID_IMAGE_PROTECT;
03430 }
03431 }
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442 pResTableAddress = ((PIMAGE_OS2_HEADER)NtHeader)->ne_nrestab;
03443
if (pResTableAddress > DosHeader->e_lfanew &&
03444 ((ULONG)((pResTableAddress+16) - DosHeader->e_lfanew) <
03445 NtHeaderSize) &&
03446 RtlEqualMemory(
03447 ((PUCHAR)NtHeader + 1 +
03448 (ULONG)(pResTableAddress - DosHeader->e_lfanew)),
03449
"1-2-3 Preloader",
03450 15) ) {
03451
return STATUS_INVALID_IMAGE_PROTECT;
03452 }
03453
03454
return STATUS_INVALID_IMAGE_NE_FORMAT;
03455 }
03456
03457
if ((
USHORT)NtHeader->Signature == (
USHORT)IMAGE_OS2_SIGNATURE_LE) {
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
return STATUS_INVALID_IMAGE_PROTECT;
03468 }
03469
return STATUS_INVALID_IMAGE_PROTECT;
03470 }
03471
03472
if ((NtHeader->FileHeader.Machine == 0) &&
03473 (NtHeader->FileHeader.SizeOfOptionalHeader == 0)) {
03474
03475
03476
03477
03478
03479
03480
return STATUS_INVALID_IMAGE_PROTECT;
03481 }
03482
03483
if (!(NtHeader->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {
03484
return STATUS_INVALID_IMAGE_FORMAT;
03485 }
03486
03487
#ifdef i386
03488
03489
03490
03491
03492
03493
if (((ULONG_PTR)NtHeader & 3) != 0) {
03494
return STATUS_INVALID_IMAGE_FORMAT;
03495 }
03496
#endif
03497
03498
#define VALIDATE_NTHEADER(Hdr) { \
03499
\
03500 if (((((Hdr)->OptionalHeader).FileAlignment & 511) != 0) && \
03501 (((Hdr)->OptionalHeader).FileAlignment != \
03502 ((Hdr)->OptionalHeader).SectionAlignment)) { \
03503 return STATUS_INVALID_IMAGE_FORMAT; \
03504 } \
03505 \
03506 if (((Hdr)->OptionalHeader).FileAlignment == 0) { \
03507 return STATUS_INVALID_IMAGE_FORMAT; \
03508 } \
03509 \
03510 if (((((Hdr)->OptionalHeader).FileAlignment - 1) & \
03511 ((Hdr)->OptionalHeader).FileAlignment) != 0) { \
03512 return STATUS_INVALID_IMAGE_FORMAT; \
03513 } \
03514 \
03515 if (((Hdr)->OptionalHeader).SectionAlignment < ((Hdr)->OptionalHeader).FileAlignment) { \
03516 return STATUS_INVALID_IMAGE_FORMAT; \
03517 } \
03518 \
03519 if (((Hdr)->OptionalHeader).SizeOfImage > MM_SIZE_OF_LARGEST_IMAGE) { \
03520 return STATUS_INVALID_IMAGE_FORMAT; \
03521 } \
03522 \
03523 if ((Hdr)->FileHeader.NumberOfSections > MM_MAXIMUM_IMAGE_SECTIONS) { \
03524 return STATUS_INVALID_IMAGE_FORMAT; \
03525 } \
03526 }
03527
03528
if (NtHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) {
03529
03530
03531
03532
#if defined (_WIN64)
03533
if (NtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
03534
03535
03536
03537 PIMAGE_NT_HEADERS32 NtHeader32 = (PIMAGE_NT_HEADERS32)NtHeader;
03538
03539
VALIDATE_NTHEADER(NtHeader32);
03540
return STATUS_SUCCESS;
03541 }
03542
#endif
03543
return STATUS_INVALID_IMAGE_FORMAT;
03544 }
03545
03546
VALIDATE_NTHEADER(NtHeader);
03547
#undef VALIDATE_NTHEADER
03548
03549
return STATUS_SUCCESS;
03550 }
03551
03552
NTSTATUS
03553 MiCreateDataFileMap (
03554 IN
PFILE_OBJECT File,
03555 OUT
PSEGMENT *Segment,
03556 IN PUINT64 MaximumSize,
03557 IN ULONG SectionPageProtection,
03558 IN ULONG AllocationAttributes,
03559 IN ULONG IgnoreFileSizing
03560 )
03561
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596 {
03597
03598
NTSTATUS Status;
03599 ULONG NumberOfPtes;
03600 ULONG SizeOfSegment;
03601 ULONG j;
03602 ULONG
Size;
03603 ULONG PartialSize;
03604 ULONG First;
03605
PCONTROL_AREA ControlArea;
03606
PSEGMENT NewSegment;
03607
PSUBSECTION Subsection;
03608
PSUBSECTION ExtendedSubsection;
03609
PMMPTE PointerPte;
03610
MMPTE TempPte;
03611 ULONG NumberOfPtesWithAlignment;
03612 UINT64 EndOfFile;
03613 UINT64 LastFileChunk;
03614 UINT64 FileOffset;
03615 UINT64 NumberOfPtesForEntireFile;
03616 ULONG ExtendedSubsections;
03617
PSUBSECTION FirstSubsection;
03618
PSUBSECTION Last;
03619 ULONG NumberOfNewSubsections;
03620
03621
PAGED_CODE();
03622
03623 ExtendedSubsections = 0;
03624 FirstSubsection =
NULL;
03625 NumberOfNewSubsections = 0;
03626
03627
03628
03629
03630
03631
if (!IgnoreFileSizing) {
03632
03633
Status =
FsRtlGetFileSize (
File, (PLARGE_INTEGER)&EndOfFile);
03634
03635
if (
Status == STATUS_FILE_IS_A_DIRECTORY) {
03636
03637
03638
03639
03640
03641
return STATUS_INVALID_FILE_FOR_SECTION;
03642 }
03643
03644
if (!
NT_SUCCESS (
Status)) {
03645
return Status;
03646 }
03647
03648
if (EndOfFile == 0 && *MaximumSize == 0) {
03649
03650
03651
03652
03653
03654
03655
return STATUS_MAPPED_FILE_SIZE_ZERO;
03656 }
03657
03658
03659
03660
03661
03662
if (*MaximumSize > EndOfFile) {
03663
03664
03665
03666
03667
03668
03669
03670
if (((SectionPageProtection & PAGE_READWRITE) |
03671 (SectionPageProtection & PAGE_EXECUTE_READWRITE)) == 0) {
03672
03673
return STATUS_SECTION_TOO_BIG;
03674 }
03675
03676
03677
03678
03679
03680
03681 EndOfFile = *MaximumSize;
03682
03683
Status =
FsRtlSetFileSize (
File, (PLARGE_INTEGER)&EndOfFile);
03684
03685
if (!
NT_SUCCESS (
Status)) {
03686
return Status;
03687 }
03688 }
03689 }
else {
03690
03691
03692
03693
03694
03695 EndOfFile = *MaximumSize;
03696 }
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717 NumberOfPtesForEntireFile = (EndOfFile +
PAGE_SIZE - 1) >>
PAGE_SHIFT;
03718
03719 NumberOfPtes = (ULONG)NumberOfPtesForEntireFile;
03720
03721
if (EndOfFile >
MI_MAXIMUM_SECTION_SIZE) {
03722
return STATUS_SECTION_TOO_BIG;
03723 }
03724
03725
if (NumberOfPtesForEntireFile > (UINT64)((MAXULONG_PTR /
sizeof(
MMPTE)) -
sizeof (
SEGMENT))) {
03726
return STATUS_SECTION_TOO_BIG;
03727 }
03728
03729
if (NumberOfPtesForEntireFile > EndOfFile) {
03730
return STATUS_SECTION_TOO_BIG;
03731 }
03732
03733
03734
03735
03736
03737
03738
03739
03740 NumberOfPtesWithAlignment = (NumberOfPtes +
03741 ((
MM_PROTO_PTE_ALIGNMENT >>
PAGE_SHIFT) - 1)) &
03742 (~((
MM_PROTO_PTE_ALIGNMENT >>
PAGE_SHIFT) - 1));
03743
03744
if (NumberOfPtesWithAlignment < NumberOfPtes) {
03745
return STATUS_SECTION_TOO_BIG;
03746 }
03747
03748 SizeOfSegment =
sizeof(
SEGMENT) +
sizeof(
MMPTE) *
03749 (NumberOfPtesWithAlignment - 1);
03750
03751 NewSegment =
ExAllocatePoolWithTag (
PagedPool,
03752 SizeOfSegment,
03753
MMSECT);
03754
if (NewSegment ==
NULL) {
03755
03756
03757
03758
03759
03760
03761
if (SizeOfSegment <
MM_ALLOCATION_FRAGMENT) {
03762
return STATUS_INSUFFICIENT_RESOURCES;
03763 }
03764
03765
Size =
MM_ALLOCATION_FRAGMENT;
03766 PartialSize = SizeOfSegment;
03767
03768
do {
03769
03770
if (PartialSize <
MM_ALLOCATION_FRAGMENT) {
03771 PartialSize = (ULONG)
ROUND_TO_PAGES (PartialSize);
03772
Size = PartialSize;
03773 }
03774
03775 NewSegment =
ExAllocatePoolWithTag (
PagedPool,
03776
Size,
03777
MMSECT);
03778 ExtendedSubsection =
ExAllocatePoolWithTag (
NonPagedPool,
03779
sizeof(
SUBSECTION),
03780 'bSmM');
03781
03782
if ((NewSegment ==
NULL) || (ExtendedSubsection ==
NULL)) {
03783
if (NewSegment) {
03784
ExFreePool (NewSegment);
03785 }
03786
if (ExtendedSubsection) {
03787
ExFreePool (ExtendedSubsection);
03788 }
03789
03790
03791
03792
03793
03794
while (FirstSubsection !=
NULL) {
03795
ExFreePool (FirstSubsection->
SubsectionBase);
03796 Last = FirstSubsection->
NextSubsection;
03797
ExFreePool (FirstSubsection);
03798 FirstSubsection = Last;
03799 }
03800
return STATUS_INSUFFICIENT_RESOURCES;
03801 }
03802
03803 NumberOfNewSubsections += 1;
03804 RtlZeroMemory (ExtendedSubsection,
sizeof(
SUBSECTION));
03805
03806
if (FirstSubsection ==
NULL) {
03807 FirstSubsection = ExtendedSubsection;
03808 Last = ExtendedSubsection;
03809 NumberOfNewSubsections = 0;
03810 }
else {
03811 Last->
NextSubsection = ExtendedSubsection;
03812 }
03813
03814 ExtendedSubsection->
PtesInSubsection =
Size /
sizeof(
MMPTE);
03815 ExtendedSubsection->
SubsectionBase = (
PMMPTE)NewSegment;
03816 Last = ExtendedSubsection;
03817 PartialSize -=
Size;
03818 }
while (PartialSize != 0);
03819
03820
03821
03822
03823
03824
03825
03826 NewSegment = (
PSEGMENT)FirstSubsection->
SubsectionBase;
03827 }
03828
03829 *Segment = NewSegment;
03830 RtlZeroMemory (NewSegment,
sizeof(
SEGMENT));
03831
03832 ControlArea =
03833 (
PCONTROL_AREA)
File->SectionObjectPointer->DataSectionObject;
03834
03835
03836
03837
03838
03839 ControlArea->
Segment = NewSegment;
03840 ControlArea->
NumberOfSectionReferences = 1;
03841
03842
if (IgnoreFileSizing ==
FALSE) {
03843
03844
03845
03846
03847
03848 ControlArea->
NumberOfUserReferences = 1;
03849 }
03850
03851 ControlArea->
u.Flags.BeingCreated = 1;
03852 ControlArea->
u.Flags.File = 1;
03853
03854
if (FILE_REMOTE_DEVICE &
File->DeviceObject->Characteristics) {
03855
03856
03857
03858
03859
03860 ControlArea->
u.Flags.Networked = 1;
03861 }
03862
03863
if (AllocationAttributes & SEC_NOCACHE) {
03864 ControlArea->
u.Flags.NoCache = 1;
03865 }
03866
03867
if (IgnoreFileSizing) {
03868
03869
03870
03871
03872 ControlArea->
u.Flags.WasPurged = 1;
03873 }
03874
03875 ControlArea->
NumberOfSubsections = (
USHORT)(1 + NumberOfNewSubsections);
03876 ControlArea->
FilePointer =
File;
03877
03878
ASSERT (ControlArea->
u.Flags.GlobalOnlyPerSession == 0);
03879
03880 Subsection = (
PSUBSECTION)(ControlArea + 1);
03881
03882
if (FirstSubsection) {
03883
03884 Subsection->
NextSubsection = FirstSubsection->
NextSubsection;
03885 Subsection->
PtesInSubsection = FirstSubsection->
PtesInSubsection;
03886
ExFreePool (FirstSubsection);
03887
#if DBG
03888
FirstSubsection =
NULL;
03889
#endif //DBG
03890
}
else {
03891
ASSERT (Subsection->
NextSubsection ==
NULL);
03892 }
03893
03894 First =
TRUE;
03895
03896 FileOffset = 0;
03897
03898
do {
03899
03900
03901
03902
03903
03904
03905 TempPte.
u.Long =
MiGetSubsectionAddressForPte (Subsection);
03906 TempPte.
u.Soft.Prototype = 1;
03907
03908
03909
03910
03911
03912
03913
03914
03915 TempPte.
u.Soft.Protection =
MM_EXECUTE_READWRITE;
03916
03917
03918
03919
03920
03921
if (First) {
03922
03923 PointerPte = &NewSegment->ThePtes[0];
03924 j = (ULONG) (((ULONG_PTR)PointerPte >>
PTE_SHIFT) &
03925 ((
MM_PROTO_PTE_ALIGNMENT /
PAGE_SIZE) - 1));
03926
03927
if (j != 0) {
03928 j = (
MM_PROTO_PTE_ALIGNMENT /
PAGE_SIZE) - j;
03929 }
03930
03931 NewSegment->PrototypePte = &NewSegment->ThePtes[j];
03932 NewSegment->ControlArea = ControlArea;
03933 NewSegment->SizeOfSegment = EndOfFile;
03934 NewSegment->TotalNumberOfPtes = NumberOfPtes;
03935 NewSegment->SegmentPteTemplate = TempPte;
03936 PointerPte = NewSegment->PrototypePte;
03937 Subsection->
SubsectionBase = PointerPte;
03938 ControlArea->
PagedPoolUsage =
EX_REAL_POOL_USAGE((
sizeof(
SEGMENT) + (NumberOfPtes *
sizeof(
MMPTE))));
03939
03940
if (Subsection->
NextSubsection !=
NULL) {
03941
03942
03943
03944
03945
03946
03947
03948 NewSegment->NonExtendedPtes = (ULONG)
03949 ((((Subsection->
PtesInSubsection *
sizeof(
MMPTE)) -
03950 ((PCHAR)NewSegment->PrototypePte - (PCHAR)NewSegment))
03951 /
sizeof(
MMPTE)) & ~((
X64K >>
PAGE_SHIFT) - 1));
03952 }
else {
03953 NewSegment->NonExtendedPtes = NumberOfPtesWithAlignment;
03954 }
03955 Subsection->
PtesInSubsection = NewSegment->NonExtendedPtes;
03956
03957 First =
FALSE;
03958 }
else {
03959 PointerPte = (
PMMPTE)Subsection->
SubsectionBase;
03960 }
03961
03962 Subsection->
ControlArea = ControlArea;
03963
03964
Mi4KStartForSubsection(&FileOffset, Subsection);
03965
03966 Subsection->
u.SubsectionFlags.Protection =
MM_EXECUTE_READWRITE;
03967
03968
if (Subsection->
NextSubsection ==
NULL) {
03969
03970 LastFileChunk = (EndOfFile >>
MM4K_SHIFT) - FileOffset;
03971
03972
03973
03974
03975
03976
03977
03978 Subsection->
NumberOfFullSectors = (ULONG)LastFileChunk;
03979
03980 Subsection->
u.SubsectionFlags.SectorEndOffset =
03981 (ULONG) EndOfFile &
MM4K_MASK;
03982
03983 j = Subsection->
PtesInSubsection;
03984
03985 Subsection->
PtesInSubsection = (ULONG)(
03986 NumberOfPtesForEntireFile -
03987 (FileOffset >> (
PAGE_SHIFT -
MM4K_SHIFT)));
03988
03989
#if DBG
03990
MiSubsectionConsistent(Subsection);
03991
#endif
03992
03993 Subsection->
UnusedPtes = j - Subsection->
PtesInSubsection;
03994 }
else {
03995
03996 Subsection->
NumberOfFullSectors =
03997 Subsection->
PtesInSubsection << (
PAGE_SHIFT -
MM4K_SHIFT);
03998
#if DBG
03999
MiSubsectionConsistent(Subsection);
04000
#endif
04001
04002 }
04003
04004
MiFillMemoryPte (PointerPte,
04005 (Subsection->
PtesInSubsection +
04006 Subsection->
UnusedPtes) *
sizeof(
MMPTE),
04007 TempPte.
u.Long);
04008
04009 FileOffset += Subsection->
PtesInSubsection <<
04010 (
PAGE_SHIFT -
MM4K_SHIFT);
04011 Subsection = Subsection->
NextSubsection;
04012 }
while (Subsection !=
NULL);
04013
04014
return STATUS_SUCCESS;
04015 }
04016
04017
NTSTATUS
04018 MiCreatePagingFileMap (
04019 OUT
PSEGMENT *Segment,
04020 IN PUINT64 MaximumSize,
04021 IN ULONG ProtectionMask,
04022 IN ULONG AllocationAttributes
04023 )
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047
04048
04049
04050
04051
04052
04053 {
04054 PFN_NUMBER NumberOfPtes;
04055 ULONG SizeOfSegment;
04056 ULONG i;
04057
PCONTROL_AREA ControlArea;
04058
PSEGMENT NewSegment;
04059
PMMPTE PointerPte;
04060
PSUBSECTION Subsection;
04061
MMPTE TempPte;
04062 LARGE_INTEGER SpecifiedSize;
04063
04064
PAGED_CODE();
04065
04066
04067
04068
04069
04070
if (*MaximumSize == 0) {
04071
return STATUS_INVALID_PARAMETER_4;
04072 }
04073
04074
04075
04076
04077
04078
#if defined (_WIN64) || defined (_X86PAE_)
04079
SpecifiedSize.QuadPart = (
ROUND_TO_PAGES (*MaximumSize)) >>
PAGE_SHIFT;
04080
04081
if (SpecifiedSize.HighPart != 0)
04082
#else
04083
if (*MaximumSize > (((ULONGLONG) 4 * 1024 * 1024 * 1024)) - (1024 * 1024))
04084
#endif
04085
{
04086
return STATUS_SECTION_TOO_BIG;
04087 }
04088
04089
04090
04091
04092
04093
04094
04095
04096
04097 NumberOfPtes =
BYTES_TO_PAGES (*MaximumSize);
04098
04099
if (AllocationAttributes & SEC_COMMIT) {
04100
04101
04102
04103
04104
04105
if (
MiChargeCommitment (NumberOfPtes,
NULL) ==
FALSE) {
04106
return STATUS_COMMITMENT_LIMIT;
04107 }
04108
MM_TRACK_COMMIT (
MM_DBG_COMMIT_PAGEFILE_BACKED_SHMEM, NumberOfPtes);
04109 }
04110
04111 SizeOfSegment =
sizeof(
SEGMENT) +
sizeof(
MMPTE) * ((ULONG)NumberOfPtes - 1);
04112
04113 NewSegment =
ExAllocatePoolWithTag (
PagedPool, SizeOfSegment,
MMSECT);
04114
04115
if (NewSegment ==
NULL) {
04116
04117
04118
04119
04120
04121
if (AllocationAttributes & SEC_COMMIT) {
04122
MiReturnCommitment (NumberOfPtes);
04123
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_PAGEFILE_BACKED_SHMEM, NumberOfPtes);
04124 }
04125
return STATUS_INSUFFICIENT_RESOURCES;
04126 }
04127
04128 *Segment = NewSegment;
04129
04130 ControlArea =
ExAllocatePoolWithTag (
NonPagedPool,
04131 (ULONG)
sizeof(
CONTROL_AREA) +
04132 (ULONG)
sizeof(
SUBSECTION),
04133
MMCONTROL);
04134
04135
if (ControlArea ==
NULL) {
04136
04137
04138
04139
04140
04141
ExFreePool (NewSegment);
04142
04143
if (AllocationAttributes & SEC_COMMIT) {
04144
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_PAGEFILE_BACKED_SHMEM, NumberOfPtes);
04145
MiReturnCommitment (NumberOfPtes);
04146 }
04147
return STATUS_INSUFFICIENT_RESOURCES;
04148 }
04149
04150
04151
04152
04153
04154 RtlZeroMemory (ControlArea,
04155
sizeof(
CONTROL_AREA) +
sizeof(
SUBSECTION));
04156
04157 ControlArea->
NonPagedPoolUsage =
EX_REAL_POOL_USAGE(
sizeof(
CONTROL_AREA) +
sizeof(
SUBSECTION));
04158
04159 ControlArea->
Segment = NewSegment;
04160 ControlArea->
NumberOfSectionReferences = 1;
04161 ControlArea->
NumberOfUserReferences = 1;
04162 ControlArea->
NumberOfSubsections = 1;
04163
04164
if (AllocationAttributes & SEC_BASED) {
04165 ControlArea->
u.Flags.Based = 1;
04166 }
04167
04168
if (AllocationAttributes & SEC_RESERVE) {
04169 ControlArea->
u.Flags.Reserve = 1;
04170 }
04171
04172
if (AllocationAttributes & SEC_COMMIT) {
04173 ControlArea->
u.Flags.Commit = 1;
04174 }
04175
04176 Subsection = (
PSUBSECTION)(ControlArea + 1);
04177
04178 Subsection->
ControlArea = ControlArea;
04179 Subsection->
PtesInSubsection = (ULONG)NumberOfPtes;
04180 Subsection->
u.SubsectionFlags.Protection = ProtectionMask;
04181
04182
04183
04184
04185
04186 PointerPte = &NewSegment->ThePtes[0];
04187 i = (ULONG) (((ULONG_PTR)PointerPte >>
PTE_SHIFT) &
04188 ((
MM_PROTO_PTE_ALIGNMENT /
PAGE_SIZE) - 1));
04189
04190
if (i != 0) {
04191 i = (
MM_PROTO_PTE_ALIGNMENT /
PAGE_SIZE) - i;
04192 }
04193
04194
04195
04196
04197
04198 RtlZeroMemory (NewSegment,
sizeof(
SEGMENT));
04199
04200 NewSegment->PrototypePte = &NewSegment->ThePtes[i];
04201
04202 NewSegment->ControlArea = ControlArea;
04203
04204
04205
04206
04207
04208 NewSegment->SizeOfSegment = (ULONG_PTR)NumberOfPtes *
PAGE_SIZE;
04209 NewSegment->TotalNumberOfPtes = (ULONG)NumberOfPtes;
04210 NewSegment->NonExtendedPtes = (ULONG)NumberOfPtes;
04211
04212 ControlArea->
PagedPoolUsage =
EX_REAL_POOL_USAGE((
sizeof(
SEGMENT) + (NumberOfPtes *
sizeof(
MMPTE))));
04213
04214 PointerPte = NewSegment->PrototypePte;
04215 Subsection->
SubsectionBase = PointerPte;
04216 TempPte =
ZeroPte;
04217
04218
if (AllocationAttributes & SEC_COMMIT) {
04219 TempPte.
u.Soft.Protection = ProtectionMask;
04220
04221
04222
04223
04224
04225 NewSegment->NumberOfCommittedPages = NumberOfPtes;
04226
04227 ExAcquireFastMutex (&
MmSectionCommitMutex);
04228
MmSharedCommit += NewSegment->NumberOfCommittedPages;
04229 ExReleaseFastMutex (&
MmSectionCommitMutex);
04230 }
04231
04232 NewSegment->SegmentPteTemplate.u.Soft.Protection = ProtectionMask;
04233
04234
for (i = 0; i < NumberOfPtes; i += 1) {
04235
04236
04237
04238
04239
04240
04241
MI_WRITE_INVALID_PTE (PointerPte, TempPte);
04242 PointerPte += 1;
04243 }
04244
04245
return STATUS_SUCCESS;
04246 }
04247
04248
04249
NTSTATUS
04250 NtOpenSection (
04251 OUT PHANDLE SectionHandle,
04252 IN ACCESS_MASK DesiredAccess,
04253 IN POBJECT_ATTRIBUTES ObjectAttributes
04254 )
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291 {
04292 HANDLE
Handle;
04293
KPROCESSOR_MODE PreviousMode;
04294
NTSTATUS Status;
04295
04296
PAGED_CODE();
04297
04298
04299
04300
04301 PreviousMode = KeGetPreviousMode();
04302
if (PreviousMode !=
KernelMode) {
04303
try {
04304
ProbeForWriteHandle(SectionHandle);
04305 } except (
EXCEPTION_EXECUTE_HANDLER) {
04306
return GetExceptionCode();
04307 }
04308 }
04309
04310
04311
04312
04313
04314
04315
Status =
ObOpenObjectByName (
ObjectAttributes,
04316
MmSectionObjectType,
04317 PreviousMode,
04318
NULL,
04319 DesiredAccess,
04320
NULL,
04321 &
Handle
04322 );
04323
04324
try {
04325 *SectionHandle =
Handle;
04326 } except (
EXCEPTION_EXECUTE_HANDLER) {
04327
return Status;
04328 }
04329
04330
return Status;
04331 }
04332
04333 CCHAR
04334 MiGetImageProtection (
04335 IN ULONG SectionCharacteristics
04336 )
04337
04338
04339
04340
04341
04342
04343
04344
04345
04346
04347
04348
04349
04350
04351
04352
04353
04354
04355
04356 {
04357 ULONG
Index;
04358
PAGED_CODE();
04359
04360
Index = 0;
04361
if (SectionCharacteristics & IMAGE_SCN_MEM_EXECUTE) {
04362
Index |= 1;
04363 }
04364
if (SectionCharacteristics & IMAGE_SCN_MEM_READ) {
04365
Index |= 2;
04366 }
04367
if (SectionCharacteristics & IMAGE_SCN_MEM_WRITE) {
04368
Index |= 4;
04369 }
04370
if (SectionCharacteristics & IMAGE_SCN_MEM_SHARED) {
04371
Index |= 8;
04372 }
04373
04374
return MmImageProtectionArray[
Index];
04375 }
04376
04377 PFN_NUMBER
04378 MiGetPageForHeader (
04379 VOID
04380 )
04381
04382
04383
04384
04385
04386
04387
04388
04389
04390
04391
04392
04393
04394
04395
04396
04397
04398
04399
04400 {
04401 KIRQL OldIrql;
04402 PFN_NUMBER PageFrameNumber;
04403
PMMPFN Pfn1;
04404
PEPROCESS Process;
04405 ULONG PageColor;
04406
04407 Process =
PsGetCurrentProcess();
04408 PageColor =
MI_PAGE_COLOR_VA_PROCESS ((PVOID)
X64K,
04409 &Process->
NextPageColor);
04410
04411
04412
04413
04414
04415
LOCK_PFN (OldIrql);
04416
04417
MiEnsureAvailablePageOrWait (
NULL,
NULL);
04418
04419
04420
04421
04422
04423 PageFrameNumber =
MiRemoveAnyPage (PageColor);
04424
04425
04426
04427
04428
04429
04430 Pfn1 =
MI_PFN_ELEMENT (PageFrameNumber);
04431 Pfn1->
u3.e2.ReferenceCount += 1;
04432
04433
#ifndef PFN_CONSISTENCY
04434
04435
04436
04437
UNLOCK_PFN (OldIrql);
04438
#endif
04439
04440 Pfn1->
OriginalPte =
ZeroPte;
04441 Pfn1->
PteAddress = (PVOID) (ULONG_PTR)
X64K;
04442
MI_SET_PFN_DELETED (Pfn1);
04443
04444
CONSISTENCY_UNLOCK_PFN (OldIrql);
04445
04446
return PageFrameNumber;
04447 }
04448
04449
VOID
04450 MiUpdateImageHeaderPage (
04451 IN
PMMPTE PointerPte,
04452 IN PFN_NUMBER PageFrameNumber,
04453 IN
PCONTROL_AREA ControlArea
04454 )
04455
04456
04457
04458
04459
04460
04461
04462
04463
04464
04465
04466
04467
04468
04469
04470
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480 {
04481 KIRQL OldIrql;
04482
04483
LOCK_PFN (OldIrql);
04484
04485
MiMakeSystemAddressValidPfn (PointerPte);
04486
04487
MiInitializeTransitionPfn (PageFrameNumber, PointerPte, 0xFFFFFFFF);
04488 ControlArea->NumberOfPfnReferences += 1;
04489
04490
04491
04492
04493
04494
MiDecrementReferenceCount (PageFrameNumber);
04495
04496
UNLOCK_PFN (OldIrql);
04497
return;
04498 }
04499
04500
VOID
04501 MiRemoveImageHeaderPage (
04502 IN PFN_NUMBER PageFrameNumber
04503 )
04504
04505
04506
04507
04508
04509
04510
04511
04512
04513
04514
04515
04516
04517
04518
04519
04520
04521
04522 {
04523 KIRQL OldIrql;
04524
04525
LOCK_PFN (OldIrql);
04526
MiDecrementReferenceCount (PageFrameNumber);
04527
UNLOCK_PFN (OldIrql);
04528
return;
04529 }
04530
04531
PCONTROL_AREA
04532 MiFindImageSectionObject(
04533 IN
PFILE_OBJECT File,
04534 OUT PBOOLEAN GlobalNeeded
04535 )
04536
04537
04538
04539
04540
04541
04542
04543
04544
04545
04546
04547
04548
04549
04550
04551
04552
04553
04554
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564
04565
04566
04567
04568
04569 {
04570
PCONTROL_AREA ControlArea;
04571
PLARGE_CONTROL_AREA LargeControlArea;
04572 PLIST_ENTRY Head, Next;
04573 ULONG SessionId;
04574
04575
MM_PFN_LOCK_ASSERT();
04576
04577 *GlobalNeeded =
FALSE;
04578
04579
04580
04581
04582
04583 ControlArea = (
PCONTROL_AREA)(
File->SectionObjectPointer->ImageSectionObject);
04584
04585
04586
04587
04588
04589
04590
04591
if (ControlArea ==
NULL) {
04592
return NULL;
04593 }
04594
04595
if (ControlArea->
u.Flags.GlobalOnlyPerSession == 0) {
04596
return ControlArea;
04597 }
04598
04599 LargeControlArea = (
PLARGE_CONTROL_AREA) ControlArea;
04600
04601
04602
04603
04604
04605 SessionId =
PsGetCurrentProcess()->SessionId;
04606
04607
if (LargeControlArea->
SessionId == SessionId) {
04608
return (
PCONTROL_AREA) LargeControlArea;
04609 }
04610
04611
04612
04613
04614
04615 Head = &LargeControlArea->
UserGlobalList;
04616
04617
for (Next = Head->Flink; Next != Head; Next = Next->Flink) {
04618
04619 LargeControlArea = CONTAINING_RECORD (Next,
LARGE_CONTROL_AREA, UserGlobalList);
04620
04621
ASSERT (LargeControlArea->
u.Flags.GlobalOnlyPerSession == 1);
04622
04623
if (LargeControlArea->
SessionId == SessionId) {
04624
return (
PCONTROL_AREA) LargeControlArea;
04625 }
04626 }
04627
04628
04629
04630
04631
04632 *GlobalNeeded =
TRUE;
04633
04634
return NULL;
04635 }
04636
04637
VOID
04638 MiInsertImageSectionObject(
04639 IN
PFILE_OBJECT File,
04640 IN
PCONTROL_AREA InputControlArea
04641 )
04642
04643
04644
04645
04646
04647
04648
04649
04650
04651
04652
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664
04665
04666
04667
04668
04669
04670 {
04671 PLIST_ENTRY Head;
04672
PLARGE_CONTROL_AREA ControlArea;
04673
PLARGE_CONTROL_AREA FirstControlArea;
04674
#if DBG
04675
PLIST_ENTRY Next;
04676
PLARGE_CONTROL_AREA NextControlArea;
04677
#endif
04678
04679
MM_PFN_LOCK_ASSERT();
04680
04681 ControlArea = (
PLARGE_CONTROL_AREA) InputControlArea;
04682
04683
04684
04685
04686
04687
04688 FirstControlArea = (
PLARGE_CONTROL_AREA)(
File->SectionObjectPointer->ImageSectionObject);
04689
04690
if (FirstControlArea ==
NULL) {
04691
if (ControlArea->
u.Flags.GlobalOnlyPerSession == 0) {
04692 (
PCONTROL_AREA)(
File->SectionObjectPointer->ImageSectionObject) =
04693 (
PCONTROL_AREA) ControlArea;
04694
return;
04695 }
04696 }
04697
04698
04699
04700
04701
04702
ASSERT (ControlArea->
u.Flags.GlobalOnlyPerSession == 1);
04703
04704 ControlArea->
SessionId =
PsGetCurrentProcess()->SessionId;
04705
04706
04707
04708
04709
04710
if (
File->SectionObjectPointer->ImageSectionObject ==
NULL) {
04711 InitializeListHead (&ControlArea->
UserGlobalList);
04712 }
04713
else {
04714
04715
04716
04717
04718
04719
04720
04721
ASSERT (ControlArea->
u.Flags.BeingDeleted ||
04722 ControlArea->
u.Flags.BeingCreated ||
04723 ControlArea->
SessionId != (ULONG)-1);
04724
04725 FirstControlArea = (
PLARGE_CONTROL_AREA)(
File->SectionObjectPointer->ImageSectionObject);
04726
04727 Head = &FirstControlArea->
UserGlobalList;
04728
04729
#if DBG
04730
04731
04732
04733
04734
for (Next = Head->Flink; Next != Head; Next = Next->Flink) {
04735 NextControlArea = CONTAINING_RECORD (Next,
LARGE_CONTROL_AREA, UserGlobalList);
04736
ASSERT (NextControlArea->
SessionId != (ULONG)-1 &&
04737 NextControlArea->
SessionId != ControlArea->
SessionId);
04738 }
04739
#endif
04740
04741 InsertTailList (Head, &ControlArea->
UserGlobalList);
04742 }
04743
04744
04745
04746
04747
04748 (
PCONTROL_AREA)(
File->SectionObjectPointer->ImageSectionObject) =
04749 (
PCONTROL_AREA) ControlArea;
04750 }
04751
04752
VOID
04753 MiRemoveImageSectionObject(
04754 IN
PFILE_OBJECT File,
04755 IN
PCONTROL_AREA InputControlArea
04756 )
04757
04758
04759
04760
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770
04771
04772
04773
04774
04775
04776
04777
04778
04779
04780
04781
04782
04783
04784
04785
04786
04787 {
04788 PLIST_ENTRY Head, Next;
04789
PLARGE_CONTROL_AREA ControlArea;
04790
PLARGE_CONTROL_AREA FirstControlArea;
04791
PLARGE_CONTROL_AREA NextControlArea;
04792
04793
MM_PFN_LOCK_ASSERT();
04794
04795 ControlArea = (
PLARGE_CONTROL_AREA) InputControlArea;
04796
04797 FirstControlArea = (
PLARGE_CONTROL_AREA)(
File->SectionObjectPointer->ImageSectionObject);
04798
04799
04800
04801
04802
04803
04804
if (FirstControlArea->
u.Flags.GlobalOnlyPerSession == 0) {
04805
ASSERT (ControlArea->
u.Flags.GlobalOnlyPerSession == 0);
04806
04807 (
PCONTROL_AREA)(
File->SectionObjectPointer->ImageSectionObject) =
NULL;
04808
return;
04809 }
04810
04811
04812
04813
04814
04815
if (FirstControlArea == ControlArea) {
04816
04817
04818
04819
04820
04821
04822
04823
if (IsListEmpty (&FirstControlArea->
UserGlobalList)) {
04824 NextControlArea =
NULL;
04825 }
else {
04826 Next = FirstControlArea->
UserGlobalList.Flink;
04827 RemoveEntryList (&FirstControlArea->
UserGlobalList);
04828 NextControlArea = CONTAINING_RECORD (Next,
04829
LARGE_CONTROL_AREA,
04830 UserGlobalList);
04831
04832
ASSERT (NextControlArea->
u.Flags.GlobalOnlyPerSession == 1);
04833 }
04834
04835 (
PCONTROL_AREA)(
File->SectionObjectPointer->ImageSectionObject) =
04836 (
PCONTROL_AREA) NextControlArea;
04837
return;
04838 }
04839
04840
04841
04842
04843
04844
04845
#if DBG
04846
Head = &FirstControlArea->
UserGlobalList;
04847
04848
for (Next = Head->Flink; Next != Head; Next = Next->Flink) {
04849
04850 NextControlArea = CONTAINING_RECORD (Next,
04851
LARGE_CONTROL_AREA,
04852 UserGlobalList);
04853
04854
ASSERT (NextControlArea->
u.Flags.GlobalOnlyPerSession == 1);
04855
04856
if (NextControlArea == ControlArea) {
04857
break;
04858 }
04859 }
04860
ASSERT (Next != Head);
04861
#endif
04862
04863 RemoveEntryList (&ControlArea->
UserGlobalList);
04864 }
04865
04866
04867
NTSTATUS
04868 MiGetWritablePagesInSection(
04869 IN PSECTION Section,
04870 OUT PULONG WritablePages
04871 )
04872
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891
04892
04893
04894
04895
04896 {
04897
NTSTATUS Status;
04898 PVOID ViewBase;
04899 SIZE_T ViewSize;
04900 ULONG PagesInSubsection;
04901 ULONG Protection;
04902 ULONG NumberOfSubsections;
04903 ULONG OffsetToSectionTable;
04904 ULONG SectionVirtualSize;
04905
PEPROCESS Process;
04906 LARGE_INTEGER SectionOffset;
04907 PIMAGE_DOS_HEADER DosHeader;
04908 PIMAGE_NT_HEADERS NtHeader;
04909 PIMAGE_SECTION_HEADER SectionTableEntry;
04910
04911
PAGED_CODE();
04912
04913 ViewBase =
NULL;
04914 ViewSize = 0;
04915 SectionOffset.QuadPart = 0;
04916
04917 *WritablePages = 0;
04918
04919 Process =
PsGetCurrentProcess();
04920
04921
Status =
MmMapViewOfSection (Section,
04922 Process,
04923 &ViewBase,
04924 0,
04925 0,
04926 &SectionOffset,
04927 &ViewSize,
04928 ViewUnmap,
04929 0,
04930 PAGE_EXECUTE);
04931
04932
if (!
NT_SUCCESS(
Status)) {
04933
return Status;
04934 }
04935
04936
04937
04938
04939
04940
04941
04942 DosHeader = (PIMAGE_DOS_HEADER) ViewBase;
04943
04944
ASSERT (DosHeader->e_magic == IMAGE_DOS_SIGNATURE);
04945
04946
#ifndef i386
04947
ASSERT (((ULONG)DosHeader->e_lfanew & 3) == 0);
04948
#endif
04949
04950
ASSERT ((ULONG)DosHeader->e_lfanew <= ViewSize);
04951
04952 NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)DosHeader +
04953 (ULONG)DosHeader->e_lfanew);
04954
04955 OffsetToSectionTable =
sizeof(ULONG) +
04956
sizeof(IMAGE_FILE_HEADER) +
04957 NtHeader->FileHeader.SizeOfOptionalHeader;
04958
04959 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader +
04960 OffsetToSectionTable);
04961
04962 NumberOfSubsections = NtHeader->FileHeader.NumberOfSections;
04963
04964
while (NumberOfSubsections > 0) {
04965
04966 Protection =
MiGetImageProtection (SectionTableEntry->Characteristics);
04967
04968
if (Protection &
MM_PROTECTION_WRITE_MASK) {
04969
04970
04971
04972
04973
04974
if (SectionTableEntry->Misc.VirtualSize == 0) {
04975 SectionVirtualSize = SectionTableEntry->SizeOfRawData;
04976 }
else {
04977 SectionVirtualSize = SectionTableEntry->Misc.VirtualSize;
04978 }
04979
04980 PagesInSubsection =
04981
MI_ROUND_TO_SIZE (SectionVirtualSize,
PAGE_SIZE) >>
PAGE_SHIFT;
04982
04983 *WritablePages += PagesInSubsection;
04984 }
04985
04986 SectionTableEntry += 1;
04987 NumberOfSubsections -= 1;
04988 }
04989
04990
Status =
MmUnmapViewOfSection (Process, ViewBase);
04991
04992
ASSERT (
NT_SUCCESS(
Status));
04993
04994
return Status;
04995 }
04996
04997
04998
VOID
04999 MiFlushDataSection(
05000 IN
PFILE_OBJECT File
05001 )
05002
05003
05004
05005
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
05021
05022
05023 {
05024 KIRQL OldIrql;
05025 IO_STATUS_BLOCK IoStatus;
05026
PCONTROL_AREA ControlArea;
05027
05028
LOCK_PFN (OldIrql);
05029
05030 ControlArea = (
PCONTROL_AREA)
File->SectionObjectPointer->DataSectionObject;
05031
05032
if (ControlArea) {
05033
if (ControlArea->
NumberOfSystemCacheViews) {
05034
UNLOCK_PFN (OldIrql);
05035
CcFlushCache (
File->SectionObjectPointer,
05036
NULL,
05037 0,
05038 &IoStatus);
05039
05040 }
else {
05041
UNLOCK_PFN (OldIrql);
05042
MmFlushSection (
File->SectionObjectPointer,
05043
NULL,
05044 0,
05045 &IoStatus,
05046
TRUE);
05047 }
05048 }
05049
else {
05050
UNLOCK_PFN (OldIrql);
05051 }
05052 }