00049 :
00050
00051 This service returns
the Extended Attributes (EAs) associated with the
00052 file specified by the FileHandle parameter. The amount of information
00053 returned is based on the size of the EAs, and the size of the buffer.
00054 That is, either all of the EAs are written to the buffer, or the buffer
00055 is filled with complete EAs if the buffer is not large enough to contain
00056 all of the EAs. Only complete EAs are ever written to the buffer; no
00057 partial EAs will ever be returned.
00058
00059 Arguments:
00060
00061 FileHandle - Supplies a handle to the file for which the EAs are returned.
00062
00063 IoStatusBlock - Address of the caller's I/O status block.
00064
00065 Buffer - Supplies a buffer to receive the EAs for the file.
00066
00067 Length - Supplies the length, in bytes, of the buffer.
00068
00069 ReturnSingleEntry - Indicates that only a single entry should be returned
00070 rather than filling the buffer with as many EAs as possible.
00071
00072 EaList - Optionally supplies a list of EA names whose values are returned.
00073
00074 EaListLength - Supplies the length of the EA list, if an EA list was
00075 specified.
00076
00077 EaIndex - Supplies the optional index of an EA whose value is to be
00078 returned. If specified, then only that EA is returned.
00079
00080 RestartScan - Indicates whether the scan of the EAs should be restarted
00081 from the beginning.
00082
00083 Return Value:
00084
00085 The status returned is the final completion status of the operation.
00086
00087 --*/
00088
00089 #define GET_OFFSET_LENGTH( CurrentEa, EaBase ) ( \
00090 (ULONG) ((PCHAR) CurrentEa - (PCHAR) EaBase) )
00091
00092
00093 {
00094
PIRP irp;
00095
NTSTATUS status;
00096
PFILE_OBJECT fileObject;
00097
PDEVICE_OBJECT deviceObject;
00098
PKEVENT event = (
PKEVENT)
NULL;
00099 PCHAR auxiliaryBuffer = (PCHAR)
NULL;
00100 BOOLEAN eaListPresent =
FALSE;
00101 ULONG eaIndexValue = 0
L;
00102
KPROCESSOR_MODE requestorMode;
00103
PIO_STACK_LOCATION irpSp;
00104 IO_STATUS_BLOCK localIoStatus;
00105 BOOLEAN synchronousIo;
00106
00107
PAGED_CODE();
00108
00109
00110
00111
00112
00113 requestorMode = KeGetPreviousMode();
00114
00115
if (requestorMode !=
KernelMode) {
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
try {
00126
00127
00128
00129
00130
00131
ProbeForWriteIoStatus( IoStatusBlock );
00132
00133
00134
00135
00136
00137
ProbeForWrite( Buffer, Length,
sizeof( ULONG ) );
00138
00139
00140
00141
00142
00143
00144
if (ARGUMENT_PRESENT( EaIndex )) {
00145 eaIndexValue =
ProbeAndReadUlong( EaIndex );
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
if (ARGUMENT_PRESENT( EaList ) && EaListLength != 0) {
00155
00156 PFILE_GET_EA_INFORMATION eas;
00157 LONG tempLength;
00158 ULONG entrySize;
00159
00160 eaListPresent =
TRUE;
00161
00162
ProbeForRead( EaList, EaListLength,
sizeof( ULONG ) );
00163 auxiliaryBuffer =
ExAllocatePoolWithQuota( NonPagedPool,
00164 EaListLength );
00165 RtlCopyMemory( auxiliaryBuffer, EaList, EaListLength );
00166
00167 eas = (PFILE_GET_EA_INFORMATION) auxiliaryBuffer;
00168 tempLength = EaListLength;
00169
00170
00171
00172
00173
00174
00175
00176
for (;;) {
00177
00178
00179
00180
00181
00182
if (tempLength < FIELD_OFFSET( FILE_GET_EA_INFORMATION, EaName[0])) {
00183 tempLength = 0;
00184
ExFreePool( auxiliaryBuffer );
00185 auxiliaryBuffer = (PVOID)
NULL;
00186 IoStatusBlock->Status = STATUS_EA_LIST_INCONSISTENT;
00187 IoStatusBlock->Information = tempLength;
00188
return STATUS_EA_LIST_INCONSISTENT;
00189 }
00190
00191 entrySize = FIELD_OFFSET( FILE_GET_EA_INFORMATION, EaName[0] ) + eas->EaNameLength + 1;
00192
00193
if ((ULONG) tempLength < entrySize) {
00194 tempLength =
GET_OFFSET_LENGTH( eas, auxiliaryBuffer );
00195
ExFreePool( auxiliaryBuffer );
00196 auxiliaryBuffer = (PVOID)
NULL;
00197 IoStatusBlock->Status = STATUS_EA_LIST_INCONSISTENT;
00198 IoStatusBlock->Information = tempLength;
00199
return STATUS_EA_LIST_INCONSISTENT;
00200 }
00201
00202
if (eas->NextEntryOffset != 0) {
00203
00204
00205
00206
00207
00208
00209
00210
00211
if ((((entrySize + 3) & ~3) != eas->NextEntryOffset) ||
00212 ((LONG) eas->NextEntryOffset < 0)) {
00213 tempLength =
GET_OFFSET_LENGTH( eas, auxiliaryBuffer );
00214
ExFreePool( auxiliaryBuffer );
00215 auxiliaryBuffer = (PVOID)
NULL;
00216 IoStatusBlock->Status = STATUS_EA_LIST_INCONSISTENT;
00217 IoStatusBlock->Information = tempLength;
00218
return STATUS_EA_LIST_INCONSISTENT;
00219
00220 }
else {
00221
00222
00223
00224
00225
00226
00227
00228
00229 tempLength -= eas->NextEntryOffset;
00230
if (tempLength < 0) {
00231 tempLength =
GET_OFFSET_LENGTH( eas, auxiliaryBuffer );
00232
ExFreePool( auxiliaryBuffer );
00233 auxiliaryBuffer = (PVOID)
NULL;
00234 IoStatusBlock->Status = STATUS_EA_LIST_INCONSISTENT;
00235 IoStatusBlock->Information = tempLength;
00236
return STATUS_EA_LIST_INCONSISTENT;
00237 }
00238 eas = (PFILE_GET_EA_INFORMATION) ((PCHAR) eas + eas->NextEntryOffset);
00239 }
00240
00241 }
else {
00242
00243
00244
00245
00246
00247
00248
00249
00250 tempLength -= entrySize;
00251
break;
00252 }
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
if (tempLength < 0) {
00262 tempLength =
GET_OFFSET_LENGTH( eas, auxiliaryBuffer );
00263
ExFreePool( auxiliaryBuffer );
00264 auxiliaryBuffer = (PVOID)
NULL;
00265 IoStatusBlock->Status = STATUS_EA_LIST_INCONSISTENT;
00266 IoStatusBlock->Information = tempLength;
00267
return STATUS_EA_LIST_INCONSISTENT;
00268 }
00269
00270 }
00271
00272 } except(EXCEPTION_EXECUTE_HANDLER) {
00273
00274
00275
00276
00277
00278
00279
00280
00281
if (auxiliaryBuffer !=
NULL) {
00282
ExFreePool( auxiliaryBuffer );
00283 }
00284
00285
return GetExceptionCode();
00286
00287 }
00288
00289 }
else {
00290
00291
00292
00293
00294
00295
00296
00297
if (ARGUMENT_PRESENT( EaList ) && (EaListLength != 0)) {
00298 eaListPresent =
TRUE;
00299
try {
00300 auxiliaryBuffer =
ExAllocatePoolWithQuota( NonPagedPool,
00301 EaListLength );
00302 } except(EXCEPTION_EXECUTE_HANDLER) {
00303
return GetExceptionCode();
00304 }
00305 RtlCopyMemory( auxiliaryBuffer, EaList, EaListLength );
00306 }
00307
00308
if (ARGUMENT_PRESENT( EaIndex )) {
00309 eaIndexValue = *EaIndex;
00310 }
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320 status =
ObReferenceObjectByHandle( FileHandle,
00321 FILE_READ_EA,
00322 IoFileObjectType,
00323 requestorMode,
00324 (PVOID *) &fileObject,
00325 NULL );
00326
if (!
NT_SUCCESS( status )) {
00327
if (eaListPresent) {
00328
ExFreePool( auxiliaryBuffer );
00329 }
00330
return status;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
if (fileObject->
Flags &
FO_SYNCHRONOUS_IO) {
00341
00342 BOOLEAN interrupted;
00343
00344
if (!
IopAcquireFastLock( fileObject )) {
00345 status =
IopAcquireFileObjectLock( fileObject,
00346 requestorMode,
00347 (BOOLEAN) ((fileObject->
Flags & FO_ALERTABLE_IO) != 0),
00348 &interrupted );
00349
if (interrupted) {
00350
if (eaListPresent) {
00351
ExFreePool( auxiliaryBuffer );
00352 }
00353
ObDereferenceObject( fileObject );
00354
return status;
00355 }
00356 }
00357 synchronousIo =
TRUE;
00358 }
else {
00359
00360
00361
00362
00363
00364
00365
00366
00367 event =
ExAllocatePool( NonPagedPool,
sizeof(
KEVENT ) );
00368
if (event ==
NULL) {
00369
if (eaListPresent) {
00370
ExFreePool( auxiliaryBuffer );
00371 }
00372
ObDereferenceObject( fileObject );
00373
return STATUS_INSUFFICIENT_RESOURCES;
00374 }
00375
KeInitializeEvent( event, SynchronizationEvent, FALSE );
00376 synchronousIo =
FALSE;
00377 }
00378
00379
00380
00381
00382
00383
KeClearEvent( &fileObject->
Event );
00384
00385
00386
00387
00388
00389 deviceObject =
IoGetRelatedDeviceObject( fileObject );
00390
00391
00392
00393
00394
00395
00396 irp =
IoAllocateIrp( deviceObject->
StackSize, TRUE );
00397
if (!irp) {
00398
00399
00400
00401
00402
00403
00404
if (!(fileObject->
Flags &
FO_SYNCHRONOUS_IO)) {
00405
ExFreePool( event );
00406 }
00407
00408
IopAllocateIrpCleanup( fileObject, (
PKEVENT) NULL );
00409
00410
if (eaListPresent) {
00411
ExFreePool( auxiliaryBuffer );
00412 }
00413
00414
return STATUS_INSUFFICIENT_RESOURCES;
00415 }
00416 irp->
Tail.Overlay.OriginalFileObject = fileObject;
00417 irp->
Tail.Overlay.Thread =
PsGetCurrentThread();
00418 irp->
RequestorMode = requestorMode;
00419
00420
00421
00422
00423
00424
if (synchronousIo) {
00425 irp->
UserEvent = (
PKEVENT)
NULL;
00426 irp->
UserIosb = IoStatusBlock;
00427 }
else {
00428 irp->
UserEvent = event;
00429 irp->
UserIosb = &localIoStatus;
00430 irp->
Flags =
IRP_SYNCHRONOUS_API;
00431 }
00432 irp->
Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE)
NULL;
00433
00434
00435
00436
00437
00438
00439 irpSp =
IoGetNextIrpStackLocation( irp );
00440 irpSp->
MajorFunction =
IRP_MJ_QUERY_EA;
00441 irpSp->
FileObject = fileObject;
00442
00443
00444
00445
00446
00447
00448
00449
if (eaListPresent) {
00450 irp->
Tail.Overlay.AuxiliaryBuffer = auxiliaryBuffer;
00451 irpSp->
Parameters.QueryEa.EaList = auxiliaryBuffer;
00452 irpSp->
Parameters.QueryEa.EaListLength = EaListLength;
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
if (deviceObject->
Flags &
DO_BUFFERED_IO) {
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
if (Length) {
00480
try {
00481
00482
00483
00484
00485
00486
00487 irp->
AssociatedIrp.SystemBuffer =
00488
ExAllocatePoolWithQuota( NonPagedPool, Length );
00489
00490 } except(EXCEPTION_EXECUTE_HANDLER) {
00491
00492
00493
00494
00495
00496
00497
00498
00499
IopExceptionCleanup( fileObject,
00500 irp,
00501 (
PKEVENT) NULL,
00502 event );
00503
00504
if (auxiliaryBuffer !=
NULL) {
00505
ExFreePool( auxiliaryBuffer );
00506 }
00507
00508
return GetExceptionCode();
00509
00510 }
00511
00512
00513
00514
00515
00516
00517
00518
00519 irp->
UserBuffer =
Buffer;
00520 irp->
Flags |= (ULONG) (
IRP_BUFFERED_IO |
00521
IRP_DEALLOCATE_BUFFER |
00522
IRP_INPUT_OPERATION);
00523 }
else {
00524
00525
00526
00527
00528
00529
00530
00531 irp->
AssociatedIrp.SystemBuffer =
NULL;
00532 irp->
Flags |= (ULONG) (
IRP_BUFFERED_IO |
IRP_INPUT_OPERATION);
00533
00534 }
00535
00536 }
else if (deviceObject->
Flags &
DO_DIRECT_IO) {
00537
00538
PMDL mdl;
00539
00540
00541
00542
00543
00544
00545
00546
00547
if (Length) {
00548 mdl = (
PMDL)
NULL;
00549
00550
try {
00551
00552
00553
00554
00555
00556
00557
00558
00559 mdl =
IoAllocateMdl( Buffer, Length, FALSE, TRUE, irp );
00560
if (mdl ==
NULL) {
00561
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
00562 }
00563
MmProbeAndLockPages( mdl, requestorMode, IoWriteAccess );
00564
00565 } except(EXCEPTION_EXECUTE_HANDLER) {
00566
00567
00568
00569
00570
00571
00572
00573
00574
IopExceptionCleanup( fileObject,
00575 irp,
00576 (
PKEVENT) NULL,
00577 event );
00578
00579
if (auxiliaryBuffer !=
NULL) {
00580
ExFreePool( auxiliaryBuffer );
00581 }
00582
00583
return GetExceptionCode();
00584
00585 }
00586 }
00587
00588 }
else {
00589
00590
00591
00592
00593
00594
00595 irp->
UserBuffer =
Buffer;
00596
00597 }
00598
00599
00600
00601
00602
00603
00604 irpSp->
Parameters.QueryEa.Length = Length;
00605 irpSp->
Parameters.QueryEa.EaIndex = eaIndexValue;
00606 irpSp->
Flags = 0;
00607
if (RestartScan) {
00608 irpSp->
Flags =
SL_RESTART_SCAN;
00609 }
00610
if (ReturnSingleEntry) {
00611 irpSp->
Flags |=
SL_RETURN_SINGLE_ENTRY;
00612 }
00613
if (ARGUMENT_PRESENT( EaIndex )) {
00614 irpSp->
Flags |=
SL_INDEX_SPECIFIED;
00615 }
00616
00617
00618
00619
00620
00621
00622 status =
IopSynchronousServiceTail( deviceObject,
00623 irp,
00624 fileObject,
00625 FALSE,
00626 requestorMode,
00627 synchronousIo,
00628 OtherTransfer );
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
if (!synchronousIo) {
00639
00640 status =
IopSynchronousApiServiceTail( status,
00641 event,
00642 irp,
00643 requestorMode,
00644 &localIoStatus,
00645 IoStatusBlock );
00646 }
00647
00648
return status;
00649 }