Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendircntrl.c
Go to the documentation of this file.
00001 /************************************************************************* 00002 * 00003 * File: dircntrl.c 00004 * 00005 * Module: Ext2 File System Driver (Kernel mode execution only) 00006 * 00007 * Description: 00008 * Contains code to handle the "directory control" dispatch entry point. 00009 * 00010 * Author: Manoj Paul Joseph 00011 * 00012 * 00013 *************************************************************************/ 00014 00015 #include "ext2fsd.h" 00016 00017 // define the file specific bug-check id 00018 #define EXT2_BUG_CHECK_ID EXT2_FILE_DIR_CONTROL 00019 00020 #define DEBUG_LEVEL (DEBUG_TRACE_DIRCTRL) 00021 00022 00023 /************************************************************************* 00024 * 00025 * Function: Ext2DirControl() 00026 * 00027 * Description: 00028 * The I/O Manager will invoke this routine to handle a directory control 00029 * request 00030 * 00031 * Expected Interrupt Level (for execution) : 00032 * 00033 * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution 00034 * to be deferred to a worker thread context) 00035 * 00036 * Return Value: STATUS_SUCCESS/Error 00037 * 00038 *************************************************************************/ 00039 NTSTATUS NTAPI Ext2DirControl( 00040 PDEVICE_OBJECT DeviceObject, // the logical volume device object 00041 PIRP Irp) // I/O Request Packet 00042 { 00043 NTSTATUS RC = STATUS_SUCCESS; 00044 PtrExt2IrpContext PtrIrpContext = NULL; 00045 BOOLEAN AreWeTopLevel = FALSE; 00046 00047 DebugTrace(DEBUG_TRACE_IRP_ENTRY, "DIR Control IRP received...", 0); 00048 00049 00050 FsRtlEnterFileSystem(); 00051 00052 ASSERT(DeviceObject); 00053 ASSERT(Irp); 00054 00055 // set the top level context 00056 AreWeTopLevel = Ext2IsIrpTopLevel(Irp); 00057 00058 try 00059 { 00060 // get an IRP context structure and issue the request 00061 PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject); 00062 ASSERT(PtrIrpContext); 00063 00064 RC = Ext2CommonDirControl(PtrIrpContext, Irp); 00065 00066 } 00067 except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) 00068 { 00069 00070 RC = Ext2ExceptionHandler(PtrIrpContext, Irp); 00071 00072 Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC); 00073 } 00074 00075 if (AreWeTopLevel) { 00076 IoSetTopLevelIrp(NULL); 00077 } 00078 00079 FsRtlExitFileSystem(); 00080 00081 return(RC); 00082 } 00083 00084 00085 00086 /************************************************************************* 00087 * 00088 * Function: Ext2CommonDirControl() 00089 * 00090 * Description: 00091 * The actual work is performed here. This routine may be invoked in one' 00092 * of the two possible contexts: 00093 * (a) in the context of a system worker thread 00094 * (b) in the context of the original caller 00095 * 00096 * Expected Interrupt Level (for execution) : 00097 * 00098 * IRQL_PASSIVE_LEVEL 00099 * 00100 * Return Value: STATUS_SUCCESS/Error 00101 * 00102 *************************************************************************/ 00103 NTSTATUS NTAPI Ext2CommonDirControl( 00104 PtrExt2IrpContext PtrIrpContext, 00105 PIRP PtrIrp) 00106 { 00107 NTSTATUS RC = STATUS_SUCCESS; 00108 PIO_STACK_LOCATION PtrIoStackLocation = NULL; 00109 PFILE_OBJECT PtrFileObject = NULL; 00110 PtrExt2FCB PtrFCB = NULL; 00111 PtrExt2CCB PtrCCB = NULL; 00112 00113 // First, get a pointer to the current I/O stack location 00114 PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); 00115 ASSERT(PtrIoStackLocation); 00116 00117 PtrFileObject = PtrIoStackLocation->FileObject; 00118 ASSERT(PtrFileObject); 00119 00120 // Get the FCB and CCB pointers 00121 PtrCCB = (PtrExt2CCB)(PtrFileObject->FsContext2); 00122 ASSERT(PtrCCB); 00123 PtrFCB = PtrCCB->PtrFCB; 00124 00125 AssertFCB( PtrFCB ); 00126 00127 00128 // Get some of the parameters supplied to us 00129 switch (PtrIoStackLocation->MinorFunction) { 00130 case IRP_MN_QUERY_DIRECTORY: 00131 #ifdef _GNU_NTIFS_ 00132 RC = Ext2QueryDirectory(PtrIrpContext, PtrIrp, (PEXTENDED_IO_STACK_LOCATION)PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB); 00133 #else 00134 RC = Ext2QueryDirectory(PtrIrpContext, PtrIrp, PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB); 00135 #endif 00136 break; 00137 case IRP_MN_NOTIFY_CHANGE_DIRECTORY: 00138 { 00139 RC = STATUS_NOT_IMPLEMENTED; 00140 PtrIrp->IoStatus.Status = RC; 00141 PtrIrp->IoStatus.Information = 0; 00142 IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT); 00143 } 00144 // RC = Ext2NotifyChangeDirectory(PtrIrpContext, PtrIrp, PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB); 00145 break; 00146 default: 00147 // This should not happen. 00148 RC = STATUS_INVALID_DEVICE_REQUEST; 00149 PtrIrp->IoStatus.Status = RC; 00150 PtrIrp->IoStatus.Information = 0; 00151 00152 // Free up the Irp Context 00153 Ext2ReleaseIrpContext(PtrIrpContext); 00154 00155 // complete the IRP 00156 IoCompleteRequest(PtrIrp, IO_NO_INCREMENT); 00157 break; 00158 } 00159 00160 return(RC); 00161 } 00162 00163 00164 /************************************************************************* 00165 * 00166 * Function: Ext2QueryDirectory() 00167 * 00168 * Description: 00169 * Query directory request. 00170 * 00171 * Expected Interrupt Level (for execution) : 00172 * 00173 * IRQL_PASSIVE_LEVEL 00174 * 00175 * Return Value: STATUS_SUCCESS/Error 00176 * 00177 *************************************************************************/ 00178 NTSTATUS NTAPI Ext2QueryDirectory( 00179 PtrExt2IrpContext PtrIrpContext, 00180 PIRP PtrIrp, 00181 #ifdef _GNU_NTIFS_ 00182 PEXTENDED_IO_STACK_LOCATION PtrIoStackLocation, 00183 #else 00184 PIO_STACK_LOCATION PtrIoStackLocation, 00185 #endif 00186 PFILE_OBJECT PtrFileObject, 00187 PtrExt2FCB PtrFCB, 00188 PtrExt2CCB PtrCCB) 00189 { 00190 NTSTATUS RC = STATUS_SUCCESS; 00191 BOOLEAN PostRequest = FALSE; 00192 PtrExt2NTRequiredFCB PtrReqdFCB = NULL; 00193 BOOLEAN CanWait = FALSE; 00194 PtrExt2VCB PtrVCB = NULL; 00195 BOOLEAN AcquiredFCB = FALSE; 00196 unsigned long BufferLength = 0; 00197 unsigned long BufferIndex = 0; 00198 unsigned long FileIndex = 0; 00199 PUNICODE_STRING PtrSearchPattern = NULL; 00200 FILE_INFORMATION_CLASS FileInformationClass; 00201 BOOLEAN RestartScan = FALSE; 00202 BOOLEAN ReturnSingleEntry = FALSE; 00203 BOOLEAN IndexSpecified = FALSE; 00204 unsigned char *Buffer = NULL; 00205 BOOLEAN FirstTimeQuery = FALSE; 00206 unsigned long StartingIndexForSearch = 0; 00207 unsigned long BytesReturned = 0; 00208 BOOLEAN BufferUsedup = FALSE; 00209 00210 BOOLEAN SearchWithWildCards = FALSE; 00211 00212 PFILE_BOTH_DIR_INFORMATION BothDirInformation = NULL; 00213 PFILE_DIRECTORY_INFORMATION DirectoryInformation = NULL; 00214 00215 00216 PEXT2_DIR_ENTRY PtrDirEntry = NULL; 00217 PEXT2_INODE PtrInode = NULL; 00218 00219 unsigned long LogicalBlockSize; 00220 00221 unsigned long ThisBlock; 00222 00223 // The starting Physical Block No... 00224 //LARGE_INTEGER StartPhysicalBlock; 00225 LARGE_INTEGER StartBufferOffset ; 00226 ULONG PinBufferLength; 00227 00228 // Buffer Control Block 00229 PBCB PtrBCB = NULL; 00230 BYTE * PtrPinnedBlockBuffer = NULL; 00231 00232 unsigned int j; 00233 00234 DebugTrace(DEBUG_TRACE_MISC, " === Querying Directory %S", PtrFCB->FCBName->ObjectName.Buffer ); 00235 00236 try 00237 { 00238 // Validate the sent-in FCB 00239 if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || !(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY)) 00240 { 00241 // We will only allow notify requests on directories. 00242 RC = STATUS_INVALID_PARAMETER; 00243 } 00244 00245 PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 00246 CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE); 00247 PtrVCB = PtrFCB->PtrVCB; 00248 00249 // 00250 // Asynchronous IO requested 00251 // Posting request... 00252 // 00253 /* 00254 * This is incorrect because posted IRP_MJ_DIRECTORY_CONTROL 00255 * requests aren't handled in the worker thread yet. I tried 00256 * adding handling of them to the worked routine, but there 00257 * were problems with accessing the PtrIoStackLocation-> 00258 * Parameters.QueryDirectory.FileName variable. 00259 * -- Filip Navara, 18/08/2004 00260 */ 00261 #if 0 00262 if (!CanWait) 00263 { 00264 PostRequest = TRUE; 00265 try_return(RC = STATUS_PENDING); 00266 } 00267 #endif 00268 00269 // Obtain the callers parameters 00270 BufferLength = PtrIoStackLocation->Parameters.QueryDirectory.Length; 00271 PtrSearchPattern = ( PUNICODE_STRING ) PtrIoStackLocation->Parameters.QueryDirectory.FileName; 00272 FileInformationClass = PtrIoStackLocation->Parameters.QueryDirectory.FileInformationClass; 00273 FileIndex = PtrIoStackLocation->Parameters.QueryDirectory.FileIndex; 00274 00275 // Some additional arguments that affect the FSD behavior 00276 RestartScan = (PtrIoStackLocation->Flags & SL_RESTART_SCAN); 00277 ReturnSingleEntry = (PtrIoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY); 00278 IndexSpecified = (PtrIoStackLocation->Flags & SL_INDEX_SPECIFIED); 00279 00280 // 00281 // Acquiring exclusive access to the FCB. 00282 // This is not mandatory 00283 // 00284 DebugTrace(DEBUG_TRACE_MISC, "*** Going into a block to acquire FCB Exclusively[DirCtrl]", 0); 00285 00286 DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters ); 00287 ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE); 00288 00289 DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [DirCtrl]", 0); 00290 AcquiredFCB = TRUE; 00291 00292 // We must determine the buffer pointer to be used. Since this 00293 // routine could either be invoked directly in the context of the 00294 // calling thread, or in the context of a worker thread, here is 00295 // a general way of determining what we should use. 00296 Buffer = Ext2GetCallersBuffer ( PtrIrp ); 00297 00298 // The method of determining where to look from and what to look for is 00299 // unfortunately extremely confusing. However, here is a methodology you 00300 // you can broadly adopt: 00301 // (a) You have to maintain a search buffer per CCB structure. 00302 // (b) This search buffer is initialized the very first time 00303 // a query directory operation is performed using the file object. 00304 // (For the sample FSD, the search buffer is stored in the 00305 // DirectorySearchPattern field) 00306 // However, the caller still has the option of "overriding" this stored 00307 // search pattern by supplying a new one in a query directory operation. 00308 // 00309 00310 if( PtrCCB->DirectorySearchPattern.Length ) 00311 { 00312 if( PtrCCB->DirectorySearchPattern.Buffer[PtrCCB->DirectorySearchPattern.Length/2] != 0 ) 00313 { 00314 DebugTrace(DEBUG_TRACE_MISC, "&&&&&&&&& PtrCCB->DirectorySearchPattern not NULL terminated!", 0); 00315 } 00316 DebugTrace(DEBUG_TRACE_MISC, " === Old Search pattern %S", PtrCCB->DirectorySearchPattern.Buffer ); 00317 } 00318 00319 if (PtrSearchPattern != NULL) 00320 { 00321 // User has supplied a search pattern 00322 // Now validate that the search pattern is legitimate 00323 00324 if ( PtrCCB->DirectorySearchPattern.Length == 0 ) 00325 { 00326 // This must be the very first query request. 00327 FirstTimeQuery = TRUE; 00328 } 00329 else 00330 { 00331 // We should ignore the search pattern in the CCB and instead, 00332 // use the user-supplied pattern for this particular query 00333 // directory request. 00334 Ext2DeallocateUnicodeString( &PtrCCB->DirectorySearchPattern ); 00335 } 00336 00337 // Now, allocate enough memory to contain the caller 00338 // supplied search pattern and fill in the DirectorySearchPattern 00339 // field in the CCB 00340 Ext2CopyUnicodeString( &PtrCCB->DirectorySearchPattern, PtrSearchPattern ); 00341 /* 00342 PtrCCB->DirectorySearchPattern = Ext2AllocatePool(PagedPool, sizeof( PtrSearchPattern ) ); 00343 ASSERT(PtrCCB->DirectorySearchPattern); 00344 RtlCopyMemory( PtrCCB->DirectorySearchPattern, PtrSearchPattern, sizeof( PtrSearchPattern ) ); 00345 */ 00346 } 00347 else if ( PtrCCB->DirectorySearchPattern.Length == 0 ) 00348 { 00349 // This MUST be the first directory query operation (else the 00350 // DirectorySearchPattern field would never be empty. Also, the caller 00351 // has neglected to provide a pattern so we MUST invent one. 00352 // Use "*" (following NT conventions) as your search pattern 00353 // and store it in the PtrCCB->DirectorySearchPattern field. 00354 00355 /* 00356 PtrCCB->DirectorySearchPattern = Ext2AllocatePool(PagedPool, sizeof(L"*") ); 00357 ASSERT(PtrCCB->DirectorySearchPattern); 00358 RtlCopyMemory( PtrCCB->DirectorySearchPattern, L"*", 4 );*/ 00359 00360 Ext2CopyWideCharToUnicodeString( &PtrCCB->DirectorySearchPattern, L"*" ); 00361 00362 FirstTimeQuery = TRUE; 00363 } 00364 else 00365 { 00366 // The caller has not supplied any search pattern... 00367 // Using previously supplied pattern 00368 PtrSearchPattern = &PtrCCB->DirectorySearchPattern; 00369 } 00370 00371 if( PtrCCB->DirectorySearchPattern.Buffer[PtrCCB->DirectorySearchPattern.Length/2] != 0 ) 00372 { 00373 DebugTrace(DEBUG_TRACE_MISC, "&&&&&&&&& PtrCCB->DirectorySearchPattern not NULL terminated!", 0 ); 00374 } 00375 DebugTrace(DEBUG_TRACE_MISC, " === Search pattern %S", PtrCCB->DirectorySearchPattern.Buffer ); 00376 SearchWithWildCards = FsRtlDoesNameContainWildCards( PtrSearchPattern ); 00377 00378 // There is one other piece of information that your FSD must store 00379 // in the CCB structure for query directory support. This is the index 00380 // value (i.e. the offset in your on-disk directory structure) from 00381 // which you should start searching. 00382 // However, the flags supplied with the IRP can make us override this 00383 // as well. 00384 00385 if (FileIndex) 00386 { 00387 // Caller has told us wherefrom to begin. 00388 // You may need to round this to an appropriate directory entry 00389 // entry alignment value. 00390 StartingIndexForSearch = FileIndex; 00391 } 00392 else if (RestartScan) 00393 { 00394 StartingIndexForSearch = 0; 00395 } 00396 else 00397 { 00398 // Get the starting offset from the CCB. 00399 StartingIndexForSearch = PtrCCB->CurrentByteOffset.LowPart; 00400 } 00401 00402 // Read in the file inode if it hasn't already been read... 00403 Ext2InitializeFCBInodeInfo( PtrFCB ); 00404 00405 if (PtrFileObject->PrivateCacheMap == NULL) 00406 { 00407 CcInitializeCacheMap(PtrFileObject, (PCC_FILE_SIZES)(&(PtrReqdFCB->CommonFCBHeader.AllocationSize)), 00408 TRUE, // We will utilize pin access for directories 00409 &(Ext2GlobalData.CacheMgrCallBacks), // callbacks 00410 PtrCCB); // The context used in callbacks 00411 } 00412 00413 00414 // 00415 // Read in the next Data Block of this directory 00416 // 00417 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 00418 StartBufferOffset.QuadPart = ( StartingIndexForSearch / LogicalBlockSize ); 00419 StartBufferOffset.QuadPart *= LogicalBlockSize; // This should be the StartBufferOffset alaigned to LBlock boundary... 00420 00421 PinBufferLength = PtrReqdFCB->CommonFCBHeader.FileSize.LowPart - StartBufferOffset.LowPart; 00422 00423 if ( !CcMapData( PtrFileObject, 00424 &StartBufferOffset, 00425 PinBufferLength, 00426 TRUE, 00427 &PtrBCB, 00428 (PVOID*)&PtrPinnedBlockBuffer ) ) 00429 { 00430 // Read Failure 00431 DebugTrace(DEBUG_TRACE_MISC, "Cache read failiure while reading in volume meta data", 0); 00432 try_return(); 00433 } 00434 else 00435 { 00436 DebugTrace(DEBUG_TRACE_MISC, "Cache hit while reading in volume meta data", 0); 00437 } 00438 00439 PtrInode = Ext2AllocatePool( PagedPool, sizeof( EXT2_INODE ) ); 00440 00441 // 00442 // Walking through the directory entries... 00443 for( BufferUsedup = FALSE, BufferIndex = 0; !BufferUsedup && StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ; ) 00444 { 00445 PtrDirEntry = (PEXT2_DIR_ENTRY) &PtrPinnedBlockBuffer[ StartingIndexForSearch - StartBufferOffset.LowPart ]; 00446 00447 StartingIndexForSearch += PtrDirEntry->rec_len; 00448 PtrCCB->CurrentByteOffset.LowPart = StartingIndexForSearch; 00449 00450 if( PtrDirEntry->inode == 0 ) 00451 { 00452 continue; 00453 } 00454 if( PtrDirEntry->name_len == 0 || PtrDirEntry->rec_len == 0 ) 00455 { 00456 // 00457 // This should not happen 00458 // Hqw can this be so!!! 00459 // 00460 Ext2BreakPoint(); 00461 if( BothDirInformation ) 00462 { 00463 BothDirInformation->NextEntryOffset = 0; 00464 } 00465 if( !BytesReturned ) 00466 { 00467 if( FirstTimeQuery ) 00468 RC = STATUS_NO_SUCH_FILE; 00469 else 00470 RC = STATUS_NO_MORE_FILES; 00471 } 00472 break; 00473 } 00474 00475 // Does this entry match the search criterian? 00476 // Checking 00477 // 00478 { 00479 UNICODE_STRING FileName; 00480 LONG Matched = 0; 00481 // Constructing a counted Unicode string out of PtrDirEntry 00482 Ext2CopyCharToUnicodeString( &FileName, PtrDirEntry->name, PtrDirEntry->name_len ); 00483 00484 if ( SearchWithWildCards ) 00485 { 00486 Matched = FsRtlIsNameInExpression ( PtrSearchPattern, &FileName, FALSE, NULL ); 00487 } 00488 else 00489 { 00490 Matched = ! RtlCompareUnicodeString( PtrSearchPattern, &FileName, FALSE ); 00491 } 00492 00493 Ext2DeallocateUnicodeString( &FileName ); 00494 if( !Matched ) 00495 { 00496 continue; 00497 } 00498 } 00499 00500 switch( FileInformationClass ) 00501 { 00502 case FileBothDirectoryInformation: 00503 00504 DebugTrace(DEBUG_TRACE_DIRINFO, " === FileBothDirectoryInformation", 0 ); 00505 ThisBlock = sizeof( FILE_BOTH_DIR_INFORMATION ); 00506 ThisBlock += PtrDirEntry->name_len*2; 00507 ThisBlock = Ext2QuadAlign( ThisBlock ); 00508 00509 if( ( BufferIndex + ThisBlock ) > BufferLength ) 00510 { 00511 // 00512 // Next entry won't fit into the buffer... 00513 // will have to return... 00514 // :( 00515 // 00516 if( BothDirInformation ) 00517 BothDirInformation->NextEntryOffset = 0; 00518 if( !BytesReturned ) 00519 RC = STATUS_NO_MORE_FILES; 00520 BufferUsedup = TRUE; 00521 break; 00522 } 00523 00524 Ext2ReadInode( PtrVCB, PtrDirEntry->inode, PtrInode ); 00525 if( !PtrInode ) 00526 { 00527 try_return( RC = STATUS_UNSUCCESSFUL ); 00528 } 00529 00530 BothDirInformation = ( PFILE_BOTH_DIR_INFORMATION ) ( Buffer + ( BufferIndex ) ); 00531 BothDirInformation->EaSize = 0; 00532 BothDirInformation->AllocationSize.QuadPart = PtrInode->i_blocks * 512; 00533 BothDirInformation->EndOfFile.QuadPart = PtrInode->i_size; 00534 BothDirInformation->ChangeTime.QuadPart = 0; 00535 00536 BothDirInformation->CreationTime.QuadPart = ( __int64 ) PtrInode->i_ctime * 10000000; 00537 BothDirInformation->CreationTime.QuadPart += Ext2GlobalData.TimeDiff.QuadPart; 00538 00539 BothDirInformation->LastAccessTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 ) PtrInode->i_atime * 10000000 ); 00540 BothDirInformation->LastWriteTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 )PtrInode->i_mtime * 10000000 ); 00541 00542 // Getting the file type... 00543 BothDirInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL; 00544 if( ! Ext2IsModeRegularFile( PtrInode->i_mode ) ) 00545 { 00546 // Not a reqular file... 00547 if( Ext2IsModeDirectory( PtrInode->i_mode) ) 00548 { 00549 // Directory... 00550 BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; 00551 } 00552 else 00553 { 00554 // Special File... 00555 // Treated with respect... ;) 00556 // 00557 BothDirInformation->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY); 00558 // FILE_ATTRIBUTE_DEVICE 00559 } 00560 if ( Ext2IsModeHidden( PtrInode->i_mode ) ) 00561 { 00562 BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_HIDDEN; 00563 } 00564 00565 if ( Ext2IsModeReadOnly( PtrInode->i_mode ) ) 00566 { 00567 BothDirInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY; 00568 } 00569 } 00570 00571 BothDirInformation->FileIndex = StartingIndexForSearch; 00572 BothDirInformation->FileNameLength = PtrDirEntry->name_len*2 + 2; 00573 BothDirInformation->ShortNameLength = 0; 00574 BothDirInformation->ShortName[0] = 0; 00575 00576 // Copying out the name as WCHAR null terminated strings 00577 for( j = 0; j< PtrDirEntry->name_len ; j ++ ) 00578 { 00579 // BothDirInformation->ShortName[ j ] = PtrDirEntry->name[j]; 00580 BothDirInformation->FileName[ j ] = PtrDirEntry->name[j]; 00581 // if( j < 11 ) 00582 // BothDirInformation->ShortName[j] = PtrDirEntry->name[j]; 00583 } 00584 00585 /* 00586 if( j < 11 ) 00587 { 00588 BothDirInformation->ShortNameLength = j * 2 + 2; 00589 BothDirInformation->ShortName[ j ] = 0; 00590 } 00591 else 00592 { 00593 BothDirInformation->ShortNameLength = 24; 00594 BothDirInformation->ShortName[ 11 ] = 0; 00595 }*/ 00596 00597 BothDirInformation->FileName[ j ] = 0; 00598 BytesReturned += ThisBlock; 00599 BufferIndex += ThisBlock; 00600 00601 if( !ReturnSingleEntry && ( StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) )) 00602 BothDirInformation->NextEntryOffset = ThisBlock; 00603 else 00604 BothDirInformation->NextEntryOffset = 0; 00605 break; 00606 00607 case FileDirectoryInformation: 00608 // DirectoryInformation 00609 DebugTrace(DEBUG_TRACE_DIRINFO, " === FileDirectoryInformation", 0 ); 00610 ThisBlock = sizeof( FILE_DIRECTORY_INFORMATION ); 00611 ThisBlock += PtrDirEntry->name_len*2; 00612 ThisBlock = Ext2QuadAlign( ThisBlock ); 00613 00614 if( ( BufferIndex + ThisBlock ) > BufferLength ) 00615 { 00616 // 00617 // Next entry won't fit into the buffer... 00618 // will have to return... 00619 // :( 00620 // 00621 if( DirectoryInformation ) 00622 DirectoryInformation->NextEntryOffset = 0; 00623 if( !BytesReturned ) 00624 RC = STATUS_NO_MORE_FILES; 00625 BufferUsedup = TRUE; 00626 break; 00627 } 00628 00629 Ext2ReadInode( PtrVCB, PtrDirEntry->inode, PtrInode ); 00630 if( !PtrInode ) 00631 { 00632 try_return( RC = STATUS_UNSUCCESSFUL ); 00633 } 00634 00635 DirectoryInformation = ( PFILE_DIRECTORY_INFORMATION ) ( Buffer + ( BufferIndex ) ); 00636 DirectoryInformation->AllocationSize.QuadPart = PtrInode->i_blocks * 512; 00637 DirectoryInformation->EndOfFile.QuadPart = PtrInode->i_size; 00638 DirectoryInformation->ChangeTime.QuadPart = 0; 00639 00640 DirectoryInformation->CreationTime.QuadPart = ( __int64 ) PtrInode->i_ctime * 10000000; 00641 DirectoryInformation->CreationTime.QuadPart += Ext2GlobalData.TimeDiff.QuadPart; 00642 00643 DirectoryInformation->LastAccessTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 ) PtrInode->i_atime * 10000000 ); 00644 DirectoryInformation->LastWriteTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 )PtrInode->i_mtime * 10000000 ); 00645 00646 // Getting the file type... 00647 DirectoryInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL; 00648 if( ! Ext2IsModeRegularFile( PtrInode->i_mode ) ) 00649 { 00650 // Not a reqular file... 00651 if( Ext2IsModeDirectory( PtrInode->i_mode) ) 00652 { 00653 // Directory... 00654 DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; 00655 } 00656 else 00657 { 00658 // Special File... 00659 // Treated with respect... ;) 00660 // 00661 DirectoryInformation->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY); 00662 // FILE_ATTRIBUTE_DEVICE 00663 } 00664 if ( Ext2IsModeHidden( PtrInode->i_mode ) ) 00665 { 00666 DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_HIDDEN; 00667 } 00668 00669 if ( Ext2IsModeReadOnly( PtrInode->i_mode ) ) 00670 { 00671 DirectoryInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY; 00672 } 00673 } 00674 00675 DirectoryInformation->FileIndex = StartingIndexForSearch; 00676 DirectoryInformation->FileNameLength = PtrDirEntry->name_len*2 + 2; 00677 00678 // Copying out the name as WCHAR null terminated strings 00679 for( j = 0; j< PtrDirEntry->name_len ; j ++ ) 00680 { 00681 DirectoryInformation->FileName[ j ] = PtrDirEntry->name[j]; 00682 } 00683 00684 DirectoryInformation->FileName[ j ] = 0; 00685 BytesReturned += ThisBlock; 00686 BufferIndex += ThisBlock; 00687 00688 if( !ReturnSingleEntry && ( StartingIndexForSearch < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) )) 00689 DirectoryInformation->NextEntryOffset = ThisBlock; 00690 else 00691 DirectoryInformation->NextEntryOffset = 0; 00692 break; 00693 00694 case FileFullDirectoryInformation: 00695 // FullDirInformation-> 00696 DebugTrace(DEBUG_TRACE_DIRINFO, " === FileFullDirectoryInformation - Not handled", 0 ); 00697 try_return(); 00698 case FileNamesInformation: 00699 // NamesInformation-> 00700 DebugTrace(DEBUG_TRACE_DIRINFO, " === FileNamesInformation - Not handled", 0 ); 00701 try_return(); 00702 default: 00703 DebugTrace(DEBUG_TRACE_DIRINFO, " === Invalid Dir Info class - Not handled", 0 ); 00704 try_return( RC = STATUS_INVALID_INFO_CLASS ); 00705 } 00706 if( ReturnSingleEntry ) 00707 { 00708 break; 00709 } 00710 }// end of for... 00711 00712 00713 00714 if( !BytesReturned && StartingIndexForSearch >= ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart) ) 00715 { 00716 Ext2DeallocateUnicodeString( &PtrCCB->DirectorySearchPattern ); 00717 PtrCCB->CurrentByteOffset.QuadPart = 0; 00718 if( FirstTimeQuery ) 00719 RC = STATUS_NO_SUCH_FILE; 00720 else 00721 RC = STATUS_NO_MORE_FILES; 00722 try_return(); 00723 } 00724 else if( BytesReturned ) 00725 { 00726 BothDirInformation->NextEntryOffset = 0; 00727 } 00728 00729 try_exit: NOTHING; 00730 } 00731 finally 00732 { 00733 00734 if( PtrInode ) 00735 { 00736 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [DirCtrl]", PtrInode ); 00737 ExFreePool( PtrInode ); 00738 } 00739 00740 if( PtrBCB ) 00741 { 00742 CcUnpinData( PtrBCB ); 00743 PtrBCB = NULL; 00744 } 00745 00746 if (PostRequest) 00747 { 00748 if (AcquiredFCB) 00749 { 00750 Ext2ReleaseResource(&(PtrReqdFCB->MainResource)); 00751 DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released in [DirCtrl]", 0); 00752 DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]", 00753 PtrReqdFCB->MainResource.ActiveCount, 00754 PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, 00755 PtrReqdFCB->MainResource.NumberOfSharedWaiters ); 00756 } 00757 00758 // Map the users buffer and then post the request. 00759 RC = Ext2LockCallersBuffer(PtrIrp, TRUE, BufferLength); 00760 ASSERT(NT_SUCCESS(RC)); 00761 00762 RC = Ext2PostRequest(PtrIrpContext, PtrIrp); 00763 00764 } 00765 else if (!(PtrIrpContext->IrpContextFlags & 00766 EXT2_IRP_CONTEXT_EXCEPTION)) 00767 { 00768 if (AcquiredFCB) 00769 { 00770 Ext2ReleaseResource(&(PtrReqdFCB->MainResource)); 00771 DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released [DirCtrl]", 0); 00772 DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]", 00773 PtrReqdFCB->MainResource.ActiveCount, 00774 PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, 00775 PtrReqdFCB->MainResource.NumberOfSharedWaiters ); 00776 } 00777 00778 // Complete the request. 00779 PtrIrp->IoStatus.Status = RC; 00780 PtrIrp->IoStatus.Information = BytesReturned; 00781 00782 // Free up the Irp Context 00783 Ext2ReleaseIrpContext(PtrIrpContext); 00784 00785 // complete the IRP 00786 IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT); 00787 } 00788 00789 // Flush the saved BCBs... 00790 // Ext2FlushSavedBCBs ( PtrIrpContext ); 00791 00792 } 00793 00794 return(RC); 00795 } 00796 00797 00798 00799 /************************************************************************* 00800 * 00801 * Function: Ext2NotifyChangeDirectory() 00802 * 00803 * Description: 00804 * Handle the notify request. 00805 * 00806 * Expected Interrupt Level (for execution) : 00807 * 00808 * IRQL_PASSIVE_LEVEL 00809 * 00810 * Return Value: STATUS_SUCCESS/Error 00811 * 00812 *************************************************************************/ 00813 NTSTATUS NTAPI Ext2NotifyChangeDirectory( 00814 PtrExt2IrpContext PtrIrpContext, 00815 PIRP PtrIrp, 00816 #ifdef _GNU_NTIFS_ 00817 PEXTENDED_IO_STACK_LOCATION PtrIoStackLocation, 00818 #else 00819 PIO_STACK_LOCATION PtrIoStackLocation, 00820 #endif 00821 PFILE_OBJECT PtrFileObject, 00822 PtrExt2FCB PtrFCB, 00823 PtrExt2CCB PtrCCB) 00824 { 00825 NTSTATUS RC = STATUS_SUCCESS; 00826 BOOLEAN CompleteRequest = FALSE; 00827 BOOLEAN PostRequest = FALSE; 00828 PtrExt2NTRequiredFCB PtrReqdFCB = NULL; 00829 BOOLEAN CanWait = FALSE; 00830 ULONG CompletionFilter = 0; 00831 BOOLEAN WatchTree = FALSE; 00832 PtrExt2VCB PtrVCB = NULL; 00833 BOOLEAN AcquiredFCB = FALSE; 00834 00835 try { 00836 00837 // Validate the sent-in FCB 00838 if ((PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) || !(PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY)) { 00839 // We will only allow notify requests on directories. 00840 RC = STATUS_INVALID_PARAMETER; 00841 CompleteRequest = TRUE; 00842 } 00843 00844 PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 00845 CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE); 00846 PtrVCB = PtrFCB->PtrVCB; 00847 00848 // Acquire the FCB resource shared 00849 DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire FCB Shared[DirCtrl]", 0); 00850 DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters ); 00851 if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->MainResource), CanWait)) 00852 { 00853 DebugTrace(DEBUG_TRACE_MISC, "*** FCB Acquisition FAILED [DirCtrl]", 0); 00854 PostRequest = TRUE; 00855 try_return(RC = STATUS_PENDING); 00856 } 00857 AcquiredFCB = TRUE; 00858 DebugTrace(DEBUG_TRACE_MISC, "*** FCB acquired [DirCtrl]", 0); 00859 00860 // Obtain some parameters sent by the caller 00861 CompletionFilter = PtrIoStackLocation->Parameters.NotifyDirectory.CompletionFilter; 00862 WatchTree = (PtrIoStackLocation->Flags & SL_WATCH_TREE ? TRUE : FALSE); 00863 00864 // If you wish to capture the subject context, you can do so as 00865 // follows: 00866 // { 00867 // PSECURITY_SUBJECT_CONTEXT SubjectContext; 00868 // SubjectContext = Ext2AllocatePool(PagedPool, 00869 // sizeof(SECURITY_SUBJECT_CONTEXT) ); 00870 // SeCaptureSubjectContext(SubjectContext); 00871 // } 00872 00873 FsRtlNotifyFullChangeDirectory((PNOTIFY_SYNC)&(PtrVCB->NotifyIRPMutex), &(PtrVCB->NextNotifyIRP), (void *)PtrCCB, 00874 (PSTRING)(PtrFCB->FCBName->ObjectName.Buffer), WatchTree, FALSE, CompletionFilter, PtrIrp, 00875 NULL, // Ext2TraverseAccessCheck(...) ? 00876 NULL); // SubjectContext ? 00877 00878 RC = STATUS_PENDING; 00879 00880 try_exit: NOTHING; 00881 00882 } 00883 finally 00884 { 00885 00886 if (PostRequest) 00887 { 00888 // Perform appropriate post related processing here 00889 if (AcquiredFCB) 00890 { 00891 Ext2ReleaseResource(&(PtrReqdFCB->MainResource)); 00892 DebugTrace(DEBUG_TRACE_MISC, "*** FCB Released in DirCtrl", 0); 00893 DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]", 00894 PtrReqdFCB->MainResource.ActiveCount, 00895 PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, 00896 PtrReqdFCB->MainResource.NumberOfSharedWaiters ); 00897 00898 AcquiredFCB = FALSE; 00899 } 00900 RC = Ext2PostRequest(PtrIrpContext, PtrIrp); 00901 } 00902 else if (CompleteRequest) 00903 { 00904 PtrIrp->IoStatus.Status = RC; 00905 PtrIrp->IoStatus.Information = 0; 00906 00907 // Free up the Irp Context 00908 Ext2ReleaseIrpContext(PtrIrpContext); 00909 00910 // complete the IRP 00911 IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT); 00912 } else { 00913 // Simply free up the IrpContext since the IRP has been queued 00914 Ext2ReleaseIrpContext(PtrIrpContext); 00915 } 00916 00917 // Release the FCB resources if acquired. 00918 if (AcquiredFCB) 00919 { 00920 Ext2ReleaseResource(&(PtrReqdFCB->MainResource)); 00921 DebugTrace(DEBUG_TRACE_MISC, "*** FReleased in [DirCtrl]", 0); 00922 DebugTraceState( "FCBMain AC:0x%LX SW:0x%LX EX:0x%LX [DirCtrl]", 00923 PtrReqdFCB->MainResource.ActiveCount, 00924 PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, 00925 PtrReqdFCB->MainResource.NumberOfSharedWaiters ); 00926 00927 AcquiredFCB = FALSE; 00928 } 00929 00930 } 00931 00932 return(RC); 00933 } Generated on Sun May 27 2012 04:27:38 for ReactOS by
1.7.6.1
|