ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dircntrl.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.