00859 :
00860
00861 This service changes
the provided information about a specified
file. The
00862 information that
is changed
is determined by
the FileInformationClass that
00863
is specified. The
new information
is taken from
the FileInformation buffer.
00864
00865 Arguments:
00866
00867 FileHandle - Supplies a handle to
the file whose information should be
00868 changed.
00869
00870 IoStatusBlock - Address of
the caller's I/O status block.
00871
00872 FileInformation - Supplies a buffer containing
the information which should
00873 be changed on
the file.
00874
00875 Length - Supplies
the length, in bytes, of
the FileInformation buffer.
00876
00877 FileInformationClass - Specifies
the type of information which should be
00878 changed about
the file.
00879
00880 Return Value:
00881
00882 The status returned
is the final completion status of
the operation.
00883
00884 --*/
00885
00886 {
00887
PIRP irp;
00888
NTSTATUS status;
00889
PFILE_OBJECT fileObject;
00890
PDEVICE_OBJECT deviceObject;
00891
PKEVENT event = (
PKEVENT)
NULL;
00892
KPROCESSOR_MODE requestorMode;
00893
PIO_STACK_LOCATION irpSp;
00894 IO_STATUS_BLOCK localIoStatus;
00895 HANDLE targetHandle = (HANDLE)
NULL;
00896 BOOLEAN synchronousIo;
00897
00898
PAGED_CODE();
00899
00900
00901
00902
00903
00904 requestorMode = KeGetPreviousMode();
00905
00906
if (requestorMode !=
KernelMode) {
00907
00908
00909
00910
00911
00912
00913
if ((ULONG) FileInformationClass >= FileMaximumInformation ||
00914 !
IopSetOperationLength[FileInformationClass]) {
00915
return STATUS_INVALID_INFO_CLASS;
00916 }
00917
00918
00919
00920
00921
00922
00923
00924
if (Length < (ULONG)
IopSetOperationLength[FileInformationClass]) {
00925
return STATUS_INFO_LENGTH_MISMATCH;
00926 }
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
try {
00937
00938
00939
00940
00941
00942
ProbeForWriteIoStatus( IoStatusBlock );
00943
00944
00945
00946
00947
00948
#if defined(_X86_)
00949
ProbeForRead( FileInformation,
00950 Length,
00951 Length ==
sizeof( BOOLEAN ) ?
sizeof( BOOLEAN ) :
sizeof( ULONG ) );
00952
#elif defined(_WIN64)
00953
00954
if (
PsGetCurrentProcess()->Wow64Process) {
00955
ProbeForRead( FileInformation,
00956 Length,
00957 Length ==
sizeof( BOOLEAN ) ?
sizeof( BOOLEAN ) :
sizeof( ULONG ) );
00958 }
00959
else {
00960
ProbeForRead( FileInformation,
00961 Length,
00962 IopQuerySetAlignmentRequirement[FileInformationClass] );
00963 }
00964
#else
00965
ProbeForRead( FileInformation,
00966 Length,
00967 IopQuerySetAlignmentRequirement[FileInformationClass] );
00968
#endif
00969
00970 } except(EXCEPTION_EXECUTE_HANDLER) {
00971
00972
00973
00974
00975
00976
00977
#if DBG
00978
if (GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT) {
00979 DbgBreakPoint();
00980 }
00981
#endif // DBG
00982
00983
return GetExceptionCode();
00984
00985 }
00986
00987
#if DBG
00988
00989 }
else {
00990
00991
00992
00993
00994
00995
00996
if ((ULONG) FileInformationClass >= FileMaximumInformation ||
00997 !
IopSetOperationLength[FileInformationClass]) {
00998
return STATUS_INVALID_INFO_CLASS;
00999 }
01000
01001
if (Length < (ULONG)
IopSetOperationLength[FileInformationClass]) {
01002
return STATUS_INFO_LENGTH_MISMATCH;
01003 }
01004
01005
#endif // DBG
01006
01007 }
01008
01009
01010
01011
01012
01013
01014
01015
01016 status =
ObReferenceObjectByHandle( FileHandle,
01017 IopSetOperationAccess[FileInformationClass],
01018 IoFileObjectType,
01019 requestorMode,
01020 (PVOID *) &fileObject,
01021 NULL );
01022
if (!
NT_SUCCESS( status )) {
01023
return status;
01024 }
01025
01026
01027
01028
01029
01030
01031
01032
if (!(fileObject->
Flags &
FO_DIRECT_DEVICE_OPEN)) {
01033 deviceObject =
IoGetRelatedDeviceObject( fileObject );
01034 }
else {
01035 deviceObject =
IoGetAttachedDevice( fileObject->
DeviceObject );
01036 }
01037
01038
01039
01040
01041
01042
01043
01044
01045
if (fileObject->
Flags &
FO_SYNCHRONOUS_IO) {
01046
01047 BOOLEAN interrupted;
01048
01049
if (!
IopAcquireFastLock( fileObject )) {
01050 status =
IopAcquireFileObjectLock( fileObject,
01051 requestorMode,
01052 (BOOLEAN) ((fileObject->
Flags & FO_ALERTABLE_IO) != 0),
01053 &interrupted );
01054
if (interrupted) {
01055
ObDereferenceObject( fileObject );
01056
return status;
01057 }
01058 }
01059
01060
01061
01062
01063
01064
01065
01066
if (FileInformationClass == FilePositionInformation) {
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079 PFILE_POSITION_INFORMATION fileInformation = FileInformation;
01080 LARGE_INTEGER currentByteOffset;
01081
01082
try {
01083
01084
01085
01086
01087
01088 currentByteOffset.QuadPart = fileInformation->CurrentByteOffset.QuadPart;
01089
01090 } except( EXCEPTION_EXECUTE_HANDLER ) {
01091
01092
IopReleaseFileObjectLock( fileObject );
01093
ObDereferenceObject( fileObject );
01094
return GetExceptionCode();
01095 }
01096
01097
if ((fileObject->
Flags &
FO_NO_INTERMEDIATE_BUFFERING &&
01098 (deviceObject->
SectorSize &&
01099 (currentByteOffset.LowPart &
01100 (deviceObject->
SectorSize - 1)))) ||
01101 currentByteOffset.HighPart < 0) {
01102
01103 status = STATUS_INVALID_PARAMETER;
01104
01105 }
else {
01106
01107
01108
01109
01110
01111 fileObject->
CurrentByteOffset.QuadPart = currentByteOffset.QuadPart;
01112
01113
try {
01114
01115
01116
01117
01118
01119 IoStatusBlock->Status = STATUS_SUCCESS;
01120 IoStatusBlock->Information = 0;
01121
01122 } except( EXCEPTION_EXECUTE_HANDLER ) {
01123
01124
01125
01126
01127
01128
01129 NOTHING;
01130
01131 }
01132
01133 }
01134
01135
01136
01137
01138
01139
01140
IopUpdateOtherTransferCount( Length );
01141
01142
01143
01144
01145
01146
01147
01148
01149
IopReleaseFileObjectLock( fileObject );
01150
ObDereferenceObject( fileObject );
01151
return status;
01152 }
01153 synchronousIo =
TRUE;
01154 }
else {
01155
01156
01157
01158
01159
01160
01161
01162
01163 event =
ExAllocatePool( NonPagedPool,
sizeof(
KEVENT ) );
01164
if (event ==
NULL) {
01165
ObDereferenceObject( fileObject );
01166
return STATUS_INSUFFICIENT_RESOURCES;
01167 }
01168
KeInitializeEvent( event, SynchronizationEvent, FALSE );
01169 synchronousIo =
FALSE;
01170 }
01171
01172
01173
01174
01175
01176
KeClearEvent( &fileObject->
Event );
01177
01178
01179
01180
01181
01182
if (FileInformationClass == FileTrackingInformation) {
01183 status =
IopTrackLink( fileObject,
01184 &localIoStatus,
01185 FileInformation,
01186 Length,
01187 synchronousIo ? &fileObject->
Event : event,
01188 requestorMode );
01189
if (
NT_SUCCESS( status )) {
01190
try {
01191 IoStatusBlock->Information = 0;
01192 IoStatusBlock->Status = status;
01193 } except(EXCEPTION_EXECUTE_HANDLER) {
01194 NOTHING;
01195 }
01196 }
01197
01198
if (synchronousIo) {
01199
IopReleaseFileObjectLock( fileObject );
01200 }
else {
01201
ExFreePool( event );
01202 }
01203
ObDereferenceObject( fileObject );
01204
return status;
01205 }
01206
01207
01208
01209
01210
01211
01212 irp =
IoAllocateIrp( deviceObject->
StackSize, TRUE );
01213
if (!irp) {
01214
01215
01216
01217
01218
01219
01220
if (!(fileObject->
Flags &
FO_SYNCHRONOUS_IO)) {
01221
ExFreePool( event );
01222 }
01223
01224
IopAllocateIrpCleanup( fileObject, (
PKEVENT) NULL );
01225
01226
return STATUS_INSUFFICIENT_RESOURCES;
01227 }
01228 irp->
Tail.Overlay.OriginalFileObject = fileObject;
01229 irp->
Tail.Overlay.Thread =
PsGetCurrentThread();
01230 irp->
RequestorMode = requestorMode;
01231
01232
01233
01234
01235
01236
if (synchronousIo) {
01237 irp->
UserEvent = (
PKEVENT)
NULL;
01238 irp->
UserIosb = IoStatusBlock;
01239 }
else {
01240 irp->
UserEvent = event;
01241 irp->
UserIosb = &localIoStatus;
01242 irp->
Flags =
IRP_SYNCHRONOUS_API;
01243 }
01244 irp->
Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE)
NULL;
01245
01246
01247
01248
01249
01250
01251 irpSp =
IoGetNextIrpStackLocation( irp );
01252 irpSp->
MajorFunction =
IRP_MJ_SET_INFORMATION;
01253 irpSp->
FileObject = fileObject;
01254
01255
01256
01257
01258
01259
01260
01261
01262 irp->
AssociatedIrp.SystemBuffer = (PVOID)
NULL;
01263 irp->
MdlAddress = (
PMDL)
NULL;
01264
01265
try {
01266
01267 PVOID systemBuffer;
01268
01269 systemBuffer =
01270 irp->
AssociatedIrp.SystemBuffer =
ExAllocatePoolWithQuota( NonPagedPool,
01271 Length );
01272 RtlCopyMemory( irp->
AssociatedIrp.SystemBuffer,
01273 FileInformation,
01274 Length );
01275
01276
01277
01278
01279
01280
ASSERT((FIELD_OFFSET(FILE_END_OF_FILE_INFORMATION, EndOfFile) |
01281 FIELD_OFFSET(FILE_ALLOCATION_INFORMATION, AllocationSize) |
01282 FIELD_OFFSET(FILE_POSITION_INFORMATION, CurrentByteOffset)) == 0);
01283
01284
if (((FileInformationClass == FileEndOfFileInformation) ||
01285 (FileInformationClass == FileAllocationInformation) ||
01286 (FileInformationClass == FilePositionInformation)) &&
01287 (((PFILE_POSITION_INFORMATION)systemBuffer)->CurrentByteOffset.HighPart < 0)) {
01288
01289
ExRaiseStatus(STATUS_INVALID_PARAMETER);
01290 }
01291
01292
01293
01294 } except(EXCEPTION_EXECUTE_HANDLER) {
01295
01296
01297
01298
01299
01300
01301
01302
IopExceptionCleanup( fileObject,
01303 irp,
01304 (
PKEVENT) NULL,
01305 event );
01306
01307
return GetExceptionCode();
01308
01309 }
01310
01311 irp->
Flags |=
IRP_BUFFERED_IO |
IRP_DEALLOCATE_BUFFER |
IRP_DEFER_IO_COMPLETION;
01312
01313
01314
01315
01316
01317
01318 irpSp->
Parameters.SetFile.Length = Length;
01319 irpSp->
Parameters.SetFile.FileInformationClass = FileInformationClass;
01320
01321
01322
01323
01324
01325
IopQueueThreadIrp( irp );
01326
01327
01328
01329
01330
01331
01332
IopUpdateOtherOperationCount();
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
if (FileInformationClass == FileModeInformation) {
01345
01346 PFILE_MODE_INFORMATION modeBuffer = irp->
AssociatedIrp.SystemBuffer;
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
if ((modeBuffer->Mode & ~FILE_VALID_SET_FLAGS) ||
01368 ((modeBuffer->Mode & (
FSIO_A |
FSIO_NA)) && (!(fileObject->
Flags &
FO_SYNCHRONOUS_IO))) ||
01369 ((!(modeBuffer->Mode & (
FSIO_A |
FSIO_NA))) && (fileObject->
Flags &
FO_SYNCHRONOUS_IO)) ||
01370 (((modeBuffer->Mode &
FSIO_A) && (modeBuffer->Mode &
FSIO_NA) ))) {
01371 status = STATUS_INVALID_PARAMETER;
01372
01373 }
else {
01374
01375
01376
01377
01378
01379
if (!(fileObject->
Flags &
FO_NO_INTERMEDIATE_BUFFERING)) {
01380
if (modeBuffer->Mode & FILE_WRITE_THROUGH) {
01381 fileObject->
Flags |=
FO_WRITE_THROUGH;
01382 }
else {
01383 fileObject->
Flags &= ~
FO_WRITE_THROUGH;
01384 }
01385 }
01386
01387
if (modeBuffer->Mode & FILE_SEQUENTIAL_ONLY) {
01388 fileObject->
Flags |=
FO_SEQUENTIAL_ONLY;
01389 }
else {
01390 fileObject->
Flags &= ~
FO_SEQUENTIAL_ONLY;
01391 }
01392
01393
if (fileObject->
Flags &
FO_SYNCHRONOUS_IO) {
01394
if (modeBuffer->Mode &
FSIO_A) {
01395 fileObject->
Flags |=
FO_ALERTABLE_IO;
01396 }
else {
01397 fileObject->
Flags &= ~
FO_ALERTABLE_IO;
01398 }
01399 }
01400
01401 status = STATUS_SUCCESS;
01402 }
01403
01404
01405
01406
01407
01408 irp->
IoStatus.Status = status;
01409 irp->
IoStatus.Information = 0
L;
01410
01411 }
else if (FileInformationClass == FileRenameInformation ||
01412 FileInformationClass == FileLinkInformation ||
01413 FileInformationClass == FileMoveClusterInformation) {
01414
01415
01416
01417
01418
01419
01420
01421 PFILE_RENAME_INFORMATION renameBuffer = irp->
AssociatedIrp.SystemBuffer;
01422
01423
01424
01425
01426
01427
01428
01429
01430
if ((ULONG) (Length - FIELD_OFFSET( FILE_RENAME_INFORMATION, FileName[0] )) < renameBuffer->FileNameLength) {
01431 status = STATUS_INVALID_PARAMETER;
01432 irp->
IoStatus.Status = status;
01433
01434 }
else {
01435
01436
01437
01438
01439
01440
01441
01442
if (FileInformationClass == FileMoveClusterInformation) {
01443 irpSp->
Parameters.SetFile.ClusterCount =
01444 ((FILE_MOVE_CLUSTER_INFORMATION *) renameBuffer)->ClusterCount;
01445 }
else {
01446 irpSp->
Parameters.SetFile.ReplaceIfExists = renameBuffer->ReplaceIfExists;
01447 }
01448
01449
01450
01451
01452
01453
01454
if (renameBuffer->FileName[0] == (WCHAR) OBJ_NAME_PATH_SEPARATOR ||
01455 renameBuffer->RootDirectory) {
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465 status =
IopOpenLinkOrRenameTarget( &targetHandle,
01466 irp,
01467 renameBuffer,
01468 fileObject );
01469
if (!
NT_SUCCESS( status )) {
01470 irp->
IoStatus.Status = status;
01471
01472 }
else {
01473
01474
01475
01476
01477
01478
01479
01480 status =
IoCallDriver( deviceObject, irp );
01481
01482 }
01483
01484 }
else {
01485
01486
01487
01488
01489
01490
01491
01492 status =
IoCallDriver( deviceObject, irp );
01493
01494 }
01495 }
01496
01497 }
else if (FileInformationClass == FileDispositionInformation) {
01498
01499 PFILE_DISPOSITION_INFORMATION disposition = irp->
AssociatedIrp.SystemBuffer;
01500
01501
01502
01503
01504
01505
01506
01507
if (disposition->DeleteFile) {
01508 irpSp->
Parameters.SetFile.DeleteHandle = FileHandle;
01509 }
01510
01511
01512
01513
01514
01515 status =
IoCallDriver( deviceObject, irp );
01516
01517 }
else if (FileInformationClass == FileCompletionInformation) {
01518
01519 PFILE_COMPLETION_INFORMATION completion = irp->
AssociatedIrp.SystemBuffer;
01520
PIO_COMPLETION_CONTEXT context;
01521 PVOID portObject;
01522
01523
01524
01525
01526
01527
01528
if (fileObject->
CompletionContext || fileObject->
Flags &
FO_SYNCHRONOUS_IO) {
01529
01530 status = STATUS_INVALID_PARAMETER;
01531
01532 }
else {
01533
01534
01535
01536
01537
01538
01539 status =
ObReferenceObjectByHandle( completion->Port,
01540 IO_COMPLETION_MODIFY_STATE,
01541 IoCompletionObjectType,
01542 requestorMode,
01543 (PVOID *) &portObject,
01544 NULL );
01545
if (
NT_SUCCESS( status )) {
01546
01547
01548
01549
01550
01551 context =
ExAllocatePoolWithTag( PagedPool,
01552
sizeof(
IO_COMPLETION_CONTEXT ),
01553 'cCoI' );
01554
if (!context) {
01555
01556
ObDereferenceObject( portObject );
01557 status = STATUS_INSUFFICIENT_RESOURCES;
01558
01559 }
else {
01560
01561
01562
01563
01564
01565
01566 context->
Port = portObject;
01567 context->
Key = completion->Key;
01568
01569
if (!InterlockedCompareExchangePointer( &fileObject->
CompletionContext, context, NULL )) {
01570
01571 status = STATUS_SUCCESS;
01572
01573 }
else {
01574
01575
01576
01577
01578
01579
01580
01581
ExFreePool( context );
01582
ObDereferenceObject( portObject );
01583 status = STATUS_INVALID_PARAMETER;
01584 }
01585 }
01586 }
01587 }
01588
01589
01590
01591
01592
01593 irp->
IoStatus.Status = status;
01594 irp->
IoStatus.Information = 0;
01595
01596 }
else {
01597
01598
01599
01600
01601
01602
01603 status =
IoCallDriver( deviceObject, irp );
01604 }
01605
01606
01607
01608
01609
01610
01611
01612
01613
if (status == STATUS_PENDING) {
01614
01615
if (synchronousIo) {
01616
01617 status =
KeWaitForSingleObject( &fileObject->
Event,
01618 Executive,
01619 requestorMode,
01620 (BOOLEAN) ((fileObject->
Flags & FO_ALERTABLE_IO) != 0),
01621 (PLARGE_INTEGER) NULL );
01622
01623
if (status == STATUS_ALERTED || status == STATUS_USER_APC) {
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
IopCancelAlertedRequest( &fileObject->
Event, irp );
01635
01636 }
01637
01638 status = fileObject->
FinalStatus;
01639
01640
IopReleaseFileObjectLock( fileObject );
01641
01642 }
else {
01643
01644
01645
01646
01647
01648
01649
01650
01651 status =
KeWaitForSingleObject( event,
01652 Executive,
01653 requestorMode,
01654 FALSE,
01655 (PLARGE_INTEGER) NULL );
01656
01657
if (status == STATUS_ALERTED || status == STATUS_USER_APC) {
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
IopCancelAlertedRequest( event, irp );
01669
01670 }
01671
01672 status = localIoStatus.Status;
01673
01674
try {
01675
01676 *IoStatusBlock = localIoStatus;
01677
01678 } except(EXCEPTION_EXECUTE_HANDLER) {
01679
01680
01681
01682
01683
01684
01685
01686 status = GetExceptionCode();
01687 }
01688
01689
ExFreePool( event );
01690
01691 }
01692
01693 }
else {
01694
01695
01696
01697
01698
01699
01700
01701
PKNORMAL_ROUTINE normalRoutine;
01702 PVOID normalContext;
01703 KIRQL irql;
01704
01705
if (!synchronousIo) {
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 irp->
UserEvent = (
PKEVENT)
NULL;
01716
ExFreePool( event );
01717 }
01718
01719 irp->
UserIosb = IoStatusBlock;
01720
KeRaiseIrql( APC_LEVEL, &irql );
01721
IopCompleteRequest( &irp->
Tail.Apc,
01722 &normalRoutine,
01723 &normalContext,
01724 (PVOID *) &fileObject,
01725 &normalContext );
01726
KeLowerIrql( irql );
01727
01728
if (synchronousIo) {
01729
IopReleaseFileObjectLock( fileObject );
01730 }
01731
01732 }
01733
01734
01735
01736
01737
01738
01739
if (targetHandle) {
01740
NtClose( targetHandle );
01741 }
01742
01743
return status;
01744 }
}