00079 :
00080
00081 This service operates on a directory
file or OLE container specified by
the
00082 FileHandle parameter. The service returns information about files in
the
00083 directory or embeddings and streams in
the container specified by
the file
00084 handle. The ReturnSingleEntry parameter specifies that
only a single entry
00085 should be returned rather than filling
the buffer. The actual number of
00086 files whose information
is returned,
is the smallest of
the following:
00087
00088 o One entry,
if the ReturnSingleEntry parameter
is TRUE.
00089
00090 o The number of entries whose information fits into
the specified
00091 buffer.
00092
00093 o The number of entries that exist.
00094
00095 o One entry
if the optional
FileName parameter
is specified.
00096
00097 If
the optional
FileName parameter
is specified, then
the only information
00098 that
is returned
is for that single entries,
if it exists. Note that
the
00099
file name may not specify any wildcard characters according to
the naming
00100 conventions of
the target
file system. The ReturnSingleEntry parameter
is
00101 simply ignored.
00102
00103 The information that
is obtained about
the entries in
the directory or OLE
00104 container
is based on
the FileInformationClass parameter. Legal values are
00105 hard coded based on
the MinorFunction.
00106
00107 Arguments:
00108
00109 FileHandle - Supplies a handle to
the directory
file or OLE container
for
00110 which information should be returned.
00111
00112
Event - Supplies an optional event to be set to
the Signaled state when
00113
the query
is complete.
00114
00115 ApcRoutine - Supplies an optional APC routine to be executed when
the
00116 query
is complete.
00117
00118 ApcContext - Supplies a context parameter to be passed to
the ApcRoutine,
00119
if an ApcRoutine was specified.
00120
00121 IoStatusBlock - Address of
the caller's I/O status block.
00122
00123 FileInformation - Supplies a buffer to receive
the requested information
00124 returned about
the contents of
the directory.
00125
00126 Length - Supplies
the length, in bytes, of
the FileInformation buffer.
00127
00128 FileInformationClass - Specfies
the type of information that
is to be
00129 returned about
the files in
the specified directory or OLE container.
00130
00131 ReturnSingleEntry - Supplies a BOOLEAN value that,
if TRUE, indicates that
00132
only a single entry should be returned.
00133
00134
FileName - Optionally supplies a
file name within
the specified directory
00135 or OLE container.
00136
00137 RestartScan - Supplies a BOOLEAN value that,
if TRUE, indicates that
the
00138 scan should be restarted from
the beginning. This parameter must be
00139 set to
TRUE by
the caller
the first time
the service
is invoked.
00140
00141 MinorFunction -
IRP_MN_QUERY_DIRECTORY or IRP_MN_QUERY_OLE_DIRECTORY
00142
00143
SynchronousIo - pointer to returned BOOLEAN;
TRUE if synchronous I/O
00144
00145 DeviceObject - pointer to returned pointer to device object
00146
00147
Irp - pointer to returned pointer to device object
00148
00149 FileObject - pointer to returned pointer to
file object
00150
00151 RequestorMode - pointer to returned requestor mode
00152
00153 Return Value:
00154
00155 The status returned
is STATUS_SUCCESS
if a valid irp was created
for the
00156 query operation.
00157
00158 --*/
00159
00160 {
00161
PIRP irp;
00162
NTSTATUS status;
00163
PFILE_OBJECT fileObject;
00164
PDEVICE_OBJECT deviceObject;
00165
PKEVENT eventObject = (
PKEVENT)
NULL;
00166
KPROCESSOR_MODE requestorMode;
00167 PCHAR auxiliaryBuffer = (PCHAR)
NULL;
00168
PIO_STACK_LOCATION irpSp;
00169
PMDL mdl;
00170
00171
PAGED_CODE();
00172
00173
00174
00175
00176
00177 requestorMode = KeGetPreviousMode();
00178 *RequestorMode = requestorMode;
00179
00180
try {
00181
00182
if (requestorMode !=
KernelMode) {
00183
00184 ULONG operationlength = 0;
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
ProbeForWriteIoStatusEx( IoStatusBlock, ApcRoutine);
00199
00200
00201
00202
00203
00204
00205
if (FileInformationClass == FileDirectoryInformation) {
00206 operationlength =
sizeof(FILE_DIRECTORY_INFORMATION);
00207 }
else if (MinorFunction ==
IRP_MN_QUERY_DIRECTORY) {
00208
switch (FileInformationClass)
00209 {
00210
case FileFullDirectoryInformation:
00211 operationlength =
sizeof(FILE_FULL_DIR_INFORMATION);
00212
break;
00213
00214
case FileBothDirectoryInformation:
00215 operationlength =
sizeof(FILE_BOTH_DIR_INFORMATION);
00216
break;
00217
00218
case FileNamesInformation:
00219 operationlength =
sizeof(FILE_NAMES_INFORMATION);
00220
break;
00221
00222
case FileObjectIdInformation:
00223 operationlength =
sizeof(FILE_OBJECTID_INFORMATION);
00224
break;
00225
00226
case FileQuotaInformation:
00227 operationlength =
sizeof(FILE_QUOTA_INFORMATION);
00228
break;
00229
00230
case FileReparsePointInformation:
00231 operationlength =
sizeof(FILE_REPARSE_POINT_INFORMATION);
00232
break;
00233 }
00234 }
00235
00236
00237
00238
00239
00240
if (operationlength == 0) {
00241
return STATUS_INVALID_INFO_CLASS;
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
if (Length < operationlength) {
00251
return STATUS_INFO_LENGTH_MISMATCH;
00252 }
00253
00254
00255
00256
00257
00258
00259
#if defined(_X86_)
00260
ProbeForWrite( FileInformation, Length,
sizeof( ULONG ) );
00261
#elif defined(_WIN64)
00262
00263
00264
00265
00266
00267
if (
PsGetCurrentProcess()->Wow64Process) {
00268
ProbeForWrite( FileInformation, Length,
sizeof( ULONG ) );
00269 }
else {
00270
ProbeForWrite( FileInformation,
00271 Length,
00272 IopQuerySetAlignmentRequirement[FileInformationClass] );
00273 }
00274
00275
#else
00276
ProbeForWrite( FileInformation,
00277 Length,
00278 IopQuerySetAlignmentRequirement[FileInformationClass] );
00279
#endif
00280
}
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
if (ARGUMENT_PRESENT( FileName )) {
00291
00292 UNICODE_STRING fileName;
00293 PUNICODE_STRING nameBuffer;
00294
00295
00296
00297
00298
00299
00300
00301
if (requestorMode !=
KernelMode) {
00302 fileName =
ProbeAndReadUnicodeString( FileName );
00303 }
else {
00304 fileName = *
FileName;
00305 }
00306
00307
if (fileName.Length) {
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
if (requestorMode !=
KernelMode) {
00318
ProbeForRead( fileName.Buffer,
00319 fileName.Length,
00320
sizeof( UCHAR ) );
00321
00322
00323
00324
00325
if (fileName.Length > MAXIMUM_FILENAME_LENGTH<<1) {
00326
ExRaiseStatus( STATUS_INVALID_PARAMETER );
00327 }
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337 auxiliaryBuffer =
ExAllocatePoolWithQuota( NonPagedPool,
00338 fileName.Length +
sizeof( UNICODE_STRING ) );
00339 RtlCopyMemory( auxiliaryBuffer +
sizeof( UNICODE_STRING ),
00340 fileName.Buffer,
00341 fileName.Length );
00342
00343
00344
00345
00346
00347
00348 nameBuffer = (PUNICODE_STRING) auxiliaryBuffer;
00349 nameBuffer->Length = fileName.Length;
00350 nameBuffer->MaximumLength = fileName.Length;
00351 nameBuffer->Buffer = (PWSTR) (auxiliaryBuffer +
sizeof( UNICODE_STRING ) );
00352 }
00353 }
00354
00355 } except(EXCEPTION_EXECUTE_HANDLER) {
00356
00357
00358
00359
00360
00361
00362
00363
00364
if (auxiliaryBuffer) {
00365
ExFreePool( auxiliaryBuffer );
00366 }
00367
00368
#if DBG
00369
if (GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT) {
00370 DbgBreakPoint();
00371 }
00372
#endif // DBG
00373
00374
return GetExceptionCode();
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384 status =
ObReferenceObjectByHandle( FileHandle,
00385 FILE_LIST_DIRECTORY,
00386 IoFileObjectType,
00387 requestorMode,
00388 (PVOID *) &fileObject,
00389 (
POBJECT_HANDLE_INFORMATION) NULL );
00390
if (!
NT_SUCCESS( status )) {
00391
if (auxiliaryBuffer) {
00392
ExFreePool( auxiliaryBuffer );
00393 }
00394
return status;
00395 }
00396 *FileObject = fileObject;
00397
00398
00399
00400
00401
00402
00403
00404
if (fileObject->CompletionContext &&
IopApcRoutinePresent( ApcRoutine )) {
00405
ObDereferenceObject( fileObject );
00406
if (auxiliaryBuffer) {
00407
ExFreePool( auxiliaryBuffer );
00408 }
00409
return STATUS_INVALID_PARAMETER;
00410
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420
if (ARGUMENT_PRESENT( Event )) {
00421 status =
ObReferenceObjectByHandle( Event,
00422 EVENT_MODIFY_STATE,
00423 ExEventObjectType,
00424 requestorMode,
00425 (PVOID *) &eventObject,
00426 (
POBJECT_HANDLE_INFORMATION) NULL );
00427
if (!
NT_SUCCESS( status )) {
00428
if (auxiliaryBuffer) {
00429
ExFreePool( auxiliaryBuffer );
00430 }
00431
ObDereferenceObject( fileObject );
00432
return status;
00433 }
else {
00434
KeClearEvent( eventObject );
00435 }
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
if (fileObject->Flags &
FO_SYNCHRONOUS_IO) {
00445
00446 BOOLEAN interrupted;
00447
00448
if (!
IopAcquireFastLock( fileObject )) {
00449 status =
IopAcquireFileObjectLock( fileObject,
00450 requestorMode,
00451 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0),
00452 &interrupted );
00453
if (interrupted) {
00454
if (auxiliaryBuffer !=
NULL) {
00455
ExFreePool( auxiliaryBuffer );
00456 }
00457
if (eventObject !=
NULL) {
00458
ObDereferenceObject( eventObject );
00459 }
00460
ObDereferenceObject( fileObject );
00461
return status;
00462 }
00463 }
00464 *
SynchronousIo =
TRUE;
00465 }
else {
00466 *
SynchronousIo =
FALSE;
00467 }
00468
00469
00470
00471
00472
00473
KeClearEvent( &fileObject->Event );
00474
00475
00476
00477
00478
00479 deviceObject =
IoGetRelatedDeviceObject( fileObject );
00480 *DeviceObject = deviceObject;
00481
00482
00483
00484
00485
00486
00487 irp =
IoAllocateIrp( deviceObject->StackSize, TRUE );
00488
if (!irp) {
00489
00490
00491
00492
00493
00494
00495
IopAllocateIrpCleanup( fileObject, eventObject );
00496
if (auxiliaryBuffer) {
00497
ExFreePool( auxiliaryBuffer );
00498 }
00499
00500
return STATUS_INSUFFICIENT_RESOURCES;
00501 }
00502 *
Irp = irp;
00503
00504 irp->
Tail.Overlay.OriginalFileObject = fileObject;
00505 irp->Tail.Overlay.Thread =
PsGetCurrentThread();
00506 irp->RequestorMode = requestorMode;
00507
00508
00509
00510
00511
00512 irp->UserEvent = eventObject;
00513 irp->UserIosb = IoStatusBlock;
00514 irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
00515 irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
00516
00517
00518
00519
00520
00521
00522 irpSp =
IoGetNextIrpStackLocation( irp );
00523 irpSp->
MajorFunction =
IRP_MJ_DIRECTORY_CONTROL;
00524 irpSp->
MinorFunction = MinorFunction;
00525 irpSp->
FileObject = fileObject;
00526
00527
00528
00529
00530
00531 irp->Tail.Overlay.AuxiliaryBuffer = auxiliaryBuffer;
00532 irp->AssociatedIrp.SystemBuffer = (PVOID)
NULL;
00533 irp->MdlAddress = (
PMDL)
NULL;
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
if (deviceObject->Flags &
DO_BUFFERED_IO) {
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
try {
00555
00556
00557
00558
00559
00560
00561 irp->AssociatedIrp.SystemBuffer =
00562
ExAllocatePoolWithQuota( NonPagedPool, Length );
00563
00564 } except(EXCEPTION_EXECUTE_HANDLER) {
00565
00566
00567
00568
00569
00570
00571
00572
00573
IopExceptionCleanup( fileObject,
00574 irp,
00575 eventObject,
00576 (
PKEVENT) NULL );
00577
00578
if (auxiliaryBuffer !=
NULL) {
00579
ExFreePool( auxiliaryBuffer );
00580 }
00581
00582
return GetExceptionCode();
00583
00584 }
00585
00586
00587
00588
00589
00590
00591
00592 irp->UserBuffer = FileInformation;
00593 irp->Flags = (ULONG) (
IRP_BUFFERED_IO |
00594
IRP_DEALLOCATE_BUFFER |
00595
IRP_INPUT_OPERATION);
00596
00597 }
else if (deviceObject->Flags &
DO_DIRECT_IO) {
00598
00599
00600
00601
00602
00603
00604
00605
00606 mdl = (
PMDL)
NULL;
00607
00608
try {
00609
00610
00611
00612
00613
00614
00615
00616
00617 mdl =
IoAllocateMdl( FileInformation, Length, FALSE, TRUE, irp );
00618
if (mdl ==
NULL) {
00619
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
00620 }
00621
MmProbeAndLockPages( mdl, requestorMode, IoWriteAccess );
00622
00623 } except(EXCEPTION_EXECUTE_HANDLER) {
00624
00625
00626
00627
00628
00629
00630
00631
IopExceptionCleanup( fileObject,
00632 irp,
00633 eventObject,
00634 (
PKEVENT) NULL );
00635
00636
if (auxiliaryBuffer !=
NULL) {
00637
ExFreePool( auxiliaryBuffer );
00638 }
00639
00640
return GetExceptionCode();
00641
00642 }
00643
00644 }
else {
00645
00646
00647
00648
00649
00650
00651 irp->UserBuffer = FileInformation;
00652
00653 }
00654
00655
00656
00657
00658
00659
00660 irpSp->
Parameters.QueryDirectory.Length = Length;
00661 irpSp->
Parameters.QueryDirectory.FileInformationClass = FileInformationClass;
00662 irpSp->
Parameters.QueryDirectory.FileIndex = 0;
00663 irpSp->
Parameters.QueryDirectory.FileName = (PSTRING) auxiliaryBuffer;
00664 irpSp->
Flags = 0;
00665
if (RestartScan) {
00666 irpSp->
Flags =
SL_RESTART_SCAN;
00667 }
00668
if (ReturnSingleEntry) {
00669 irpSp->
Flags |=
SL_RETURN_SINGLE_ENTRY;
00670 }
00671
00672 irp->Flags |=
IRP_DEFER_IO_COMPLETION;
00673
00674
00675
00676
00677
00678
return STATUS_SUCCESS;
00679 }